PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
output_scalar.cc
Go to the documentation of this file.
1/* Copyright (C) 2017, 2018, 2019, 2021, 2023, 2024, 2025, 2026 PISM Authors
2 *
3 * This file is part of PISM.
4 *
5 * PISM is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with PISM; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "pism/icemodel/IceModel.hh"
21
22#include "pism/util/io/io_helpers.hh"
23#include "pism/util/pism_utilities.hh"
24#include <memory>
25
26namespace pism {
27
28/*!
29 * Process -scalar_vars shortcuts.
30 */
31static std::set<std::string> process_ts_shortcuts(const Config &config,
32 const std::set<std::string> &input) {
33 std::set<std::string> result = input;
34
35 if (result.find("ismip6") != result.end()) {
36 result.erase("ismip6");
37 for (auto v : set_split(config.get_string("output.ISMIP6_ts_variables"), ',')) {
38 result.insert(v);
39 }
40 }
41
42 return result;
43}
44
45//! Initializes the code writing scalar time-series.
47
48 auto filename = m_config->get_string("output.scalar.file");
49
50 auto times = m_config->get_string("output.scalar.times");
51 bool times_set = not times.empty();
52
53 if (times_set xor not filename.empty()) {
55 "you need to specity both -scalar_file and -scalar_times"
56 " to save scalar diagnostic time-series.");
57 }
58
59 if (filename.empty()) {
61 return;
62 }
63
64 // initialize m_ts_times and m_ts_vars
65 {
66 try {
67 *m_scalar_times = m_time->parse_times(times);
68 } catch (RuntimeError &e) {
69 e.add_context("parsing the -scalar_times argument %s", times.c_str());
70 throw;
71 }
72
73 m_log->message(2, " saving scalar time-series to '%s'\n", filename.c_str());
74 m_log->message(2, " times requested: %s\n", times.c_str());
75
76 m_scalar_vars = set_split(m_config->get_string("output.scalar.variables"), ',');
77 if (not m_scalar_vars.empty()) {
79 m_log->message(2, "variables requested: %s\n", set_join(m_scalar_vars, ",").c_str());
80 }
81 }
82
83 // de-allocate unused scalar diagnostics
84 {
85 if (m_scalar_vars.empty()) {
86 // use all diagnostics
87 } else {
88 std::vector<std::string> missing;
89 TSDiagnosticList diagnostics;
90 for (const auto &v : m_scalar_vars) {
92 diagnostics[v] = m_available_scalar_diagnostics[v];
93 } else {
94 missing.push_back(v);
95 }
96 }
97 // replace m_available_scalar_diagnostics with requested diagnostics, de-allocating
98 // the rest
100
101 // stop with an error message if some requested diagnostics are not available:
102 if (not missing.empty()) {
104 "requested scalar diagnostics %s are not available",
105 join(missing, ",").c_str());
106 }
107 }
108 }
109
110 // prepare the output file
111 {
112 m_scalar_file = std::make_shared<OutputFile>(m_output_writer, filename);
113 bool append = m_config->get_flag("output.scalar.append");
114 // default behavior is to move the file aside if it exists already; option allows appending
115 if (append) {
116 m_scalar_file->append();
117 if (m_scalar_file->time_dimension_length() > 0) {
118 // add the last saved time to the list of requested times so that the first time is interpreted
119 // as the end of a reporting time step
120 double epsilon = m_config->get_number("time_stepping.resolution"), // usually one second
121 t = m_scalar_file->last_time_value();
122
123 // add this time only if it is strictly before the first requested one
124 if (t + epsilon < m_scalar_times->front()) {
125 m_scalar_times->insert(m_scalar_times->begin(), t);
126 }
127 }
128 } else {
129 std::set<VariableMetadata> variables = { config_metadata(*m_config),
131 for (const auto &d : m_available_scalar_diagnostics) {
132 variables.insert(d.second->metadata());
133 }
134
135 bool with_time_bounds = true;
136 define_time(*m_scalar_file, with_time_bounds);
137 define_variables(*m_scalar_file, variables);
138 }
139 }
140
141 // initialize scalar diagnostics using m_ts_file allocated above:
142 for (const auto &d : m_available_scalar_diagnostics) {
143 d.second->init(m_scalar_file, m_scalar_times);
144 }
145
146}
147
148//! Computes the maximum time-step we can take and still hit all `-scalar_times`.
150
151 if ((not m_config->get_flag("time_stepping.hit_scalar_times")) or
153 return MaxTimestep("reporting (-scalar_times)");
154 }
155
156 double eps = m_config->get_number("time_stepping.resolution");
157
158 return reporting_max_timestep(*m_scalar_times, my_t, eps,
159 "reporting (-scalar_times)");
160}
161
162//! Flush scalar time-series.
164
165 if (m_scalar_file == nullptr) {
166 return;
167 }
168
169 io::write_config(*m_config, "pism_config", *m_scalar_file);
170
171 // flush all the time-series buffers:
172 for (const auto &d : m_available_scalar_diagnostics) {
173 d.second->flush();
174 }
175
176 // FIXME: update run stats
177}
178
179} // end of namespace pism
std::string get_string(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
Definition Config.cc:322
A class for storing and accessing PISM configuration flags and parameters.
Definition Config.hh:56
MaxTimestep scalar_diagnostics_max_timestep(double t)
Computes the maximum time-step we can take and still hit all -scalar_times.
void define_variables(const OutputFile &file, const std::set< VariableMetadata > &variables) const
Definition output.cc:206
std::shared_ptr< Config > m_config
Configuration flags and parameters.
Definition IceModel.hh:278
void define_time(const OutputFile &file, bool with_bounds=false) const
Definition output.cc:73
std::shared_ptr< Logger > m_log
Logger.
Definition IceModel.hh:284
std::set< std::string > m_scalar_vars
Definition IceModel.hh:484
std::shared_ptr< std::vector< double > > m_scalar_times
requested times for scalar time-series
Definition IceModel.hh:483
VariableMetadata m_output_global_attributes
stores global attributes saved in a PISM output file
Definition IceModel.hh:293
std::shared_ptr< Time > m_time
Time manager.
Definition IceModel.hh:286
void init_scalar_diagnostics()
Initializes the code writing scalar time-series.
std::map< std::string, TSDiagnostic::Ptr > m_available_scalar_diagnostics
Available scalar diagnostics.
Definition IceModel.hh:463
std::shared_ptr< OutputWriter > m_output_writer
Definition IceModel.hh:288
void scalar_diagnostics_flush_buffers()
Flush scalar time-series.
std::shared_ptr< OutputFile > m_scalar_file
file to write scalar time-series to
Definition IceModel.hh:481
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
void add_context(const std::string &message)
Add a message providing some context. This way we can (sort of) get a stack trace even though C++ exc...
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
#define PISM_ERROR_LOCATION
void write_config(const Config &config, const std::string &variable_name, const OutputFile &file)
MaxTimestep reporting_max_timestep(const std::vector< double > &times, double t, double eps, const std::string &description)
Definition output.cc:43
static std::set< std::string > process_ts_shortcuts(const Config &config, const std::set< std::string > &input)
std::string set_join(const std::set< std::string > &input, const std::string &separator)
std::map< std::string, TSDiagnostic::Ptr > TSDiagnosticList
std::set< std::string > set_split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a set of strings.
std::string join(const std::vector< std::string > &strings, const std::string &separator)
Concatenate strings, inserting separator between elements.
VariableMetadata config_metadata(const Config &config)
Definition Config.cc:939