PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
output.cc
Go to the documentation of this file.
1// Copyright (C) 2004-2026 Jed Brown, Ed Bueler and Constantine Khroulev
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#include <gsl/gsl_interp.h> // gsl_interp_bsearch()
20
21#include <algorithm>
22#include <memory>
23#include <set>
24#include <string>
25#include <vector>
26
27#include "pism/icemodel/IceModel.hh"
28
29#include "pism/util/Grid.hh"
30#include "pism/util/Config.hh"
31#include "pism/util/Diagnostic.hh"
32#include "pism/util/Time.hh"
33#include "pism/util/io/File.hh"
34#include "pism/util/Profiling.hh"
35#include "pism/util/pism_utilities.hh"
36#include "pism/util/Component.hh"
37#include "pism/util/io/IO_Flags.hh"
38#include "pism/util/io/io_helpers.hh"
39#include "pism/util/io/SynchronousOutputWriter.hh"
40
41namespace pism {
42
43MaxTimestep reporting_max_timestep(const std::vector<double> &times, double t,
44 double resolution,
45 const std::string &description) {
46
47 const size_t N = times.size();
48 if (t >= times.back()) {
49 return MaxTimestep();
50 }
51
52 size_t j = 0;
53 double dt = 0.0;
54 if (t < times[0]) {
55 j = -1;
56 } else {
57 j = gsl_interp_bsearch(times.data(), t, 0, N - 1);
58 }
59
60 dt = times[j + 1] - t;
61
62 // now make sure that we don't end up taking a time-step of less than "resolution"
63 // second long
64 if (dt < resolution) {
65 if (j + 2 < N) {
66 return MaxTimestep(times[j + 2] - t, description);
67 }
68 return MaxTimestep(description);
69 }
70 return MaxTimestep(dt, description);
71}
72
73void IceModel::define_time(const OutputFile &file, bool with_bounds) const {
74 file.define_variable(m_time->metadata(with_bounds));
75
76 if (with_bounds) {
77 file.define_variable(m_time->bounds_metadata());
78 }
79}
80
81std::set<VariableMetadata> IceModel::common_metadata() const {
82 VariableMetadata wall_clock("wall_clock_time", m_sys);
83 wall_clock.long_name("wall-clock time since the beginning of the run")
84 .units("hours")
87
88 VariableMetadata myph("model_years_per_processor_hour", m_sys);
89 myph.long_name("average number of model years per processor hour, since the beginning of the run")
90 .units("years / hour")
93
94 VariableMetadata step_counter("step_counter", m_sys);
95 step_counter.long_name("number of time steps since the beginning of the run")
96 .units("")
99
100 std::set<VariableMetadata> result = { wall_clock, myph, step_counter, m_output_global_attributes,
102
103 {
104 auto mapping = m_grid->get_mapping_info();
105
106 if (mapping.has_attributes()) {
107 result.insert(mapping);
108 }
109 }
110
111 return result;
112}
113
115 m_output_filename = m_config->get_string("output.file");
116
117 if (m_output_filename.empty()) {
118 m_output_filename = "unnamed.nc";
119 m_log->message(2, "WARNING: output.file is empty. Using '%s' instead.\n",
120 m_output_filename.c_str());
121 }
122
123 if (not ends_with(m_output_filename, ".nc")) {
124 m_log->message(2, "PISM WARNING: output file name does not have the '.nc' suffix!\n");
125 }
126
127 m_output_vars = output_variables(m_config->get_string("output.size"));
128
129#if (Pism_USE_PROJ == 1)
130 {
131 std::string proj_string = m_grid->get_mapping_info()["proj_params"];
132 if (not proj_string.empty()) {
133 for (std::string v : {"lon", "lat"}) {
134 if (set_member(v, m_output_vars)) {
135 m_output_vars.insert(v + "_bnds");
136 }
137 }
138 }
139 }
140#endif
141
149}
150
151//! Save model state in NetCDF format.
152/*!
153Calls write_variables() to do the actual work.
154 */
156 append_history("PISM done");
157
158 const Profiling &profiling = m_ctx->profiling();
159
160 profiling.begin("io.model_state");
161 if (m_config->get_string("output.size") != "none") {
162 m_log->message(2, "Writing model state to file `%s'...\n", m_output_filename.c_str());
164
165 {
166 define_time(file);
168 }
169
170 {
171 io::write_config(*m_config, "pism_config", file);
172 file.append_time(m_time->current());
173 write_state(file);
176 write_run_stats(file);
177 }
178 }
179 profiling.end("io.model_state");
180}
181
182void IceModel::write_run_stats(const OutputFile &file) const {
183
184 auto t_length = file.time_dimension_length();
185 auto t_start = t_length > 0 ? t_length - 1 : 0;
186
188 proc_hours = m_grid->size() * wall_clock_hours,
189 model_years = m_time->convert_time_interval(m_time->current() - m_time->start(), "years");
190
191 std::vector<unsigned int> start{};
192 std::vector<unsigned int> count{};
193 if (m_config->get_string("output.experiment_id").empty()) {
194 start = { t_start };
195 count = { 1 };
196 } else {
197 start = { 0, t_start };
198 count = { 1, 1 };
199 }
200
201 file.write_array("wall_clock_time", start, count, { wall_clock_hours });
202 file.write_array("model_years_per_processor_hour", start, count, { model_years / proc_hours });
203 file.write_array("step_counter", start, count, { (double)m_step_counter });
204}
205
207 const std::set<VariableMetadata> &variables) const {
208 io::define_variables(file, variables,
209 m_grid->get_mapping_info(),
210 m_config->get_flag("output.use_MKS"));
211}
212
213/*!
214 * Return the set of state variables from IceModel and all its sub-models. Does not
215 * include state variables from requested diagnostics.
216 */
217std::set<VariableMetadata> IceModel::state_variables() const {
218 std::set<VariableMetadata> result{};
219 {
220 // IceModel's state variables:
221 for (auto *v : m_model_state) {
222 for (unsigned int k = 0; k < v->ndof(); ++k) {
223 result.insert(v->metadata(k));
224 }
225 }
226
227 // state variables from sub-models:
228 for (const auto &m : m_submodels) {
229 result = pism::combine(result, m.second->state());
230 }
231 }
232
233 return result;
234}
235
236/*!
237 * Write state variables of IceModel and all its sub-models. Does not include state
238 * variables corresponding to requested diagnostic variables.
239 */
240void IceModel::write_state(const OutputFile &file) const {
241 for (auto *v : m_model_state) {
242 v->write(file);
243 }
244
245 for (const auto& m : m_submodels) {
246 m.second->write_state(file);
247 }
248}
249
250std::string IceModel::save_state_on_error(const std::string &suffix,
251 const std::set<std::string> &additional_variables) {
252
253 auto filename = filename_add_suffix(m_output_filename, suffix, "");
254
255 std::shared_ptr<OutputWriter> writer =
256 std::make_shared<SynchronousOutputWriter>(m_grid->com, *m_config);
257
258 auto variables = pism::combine(m_output_file_contents, diagnostic_variables(additional_variables));
259
260 std::set<std::string> variable_names;
261 for (const auto &v : variables) {
262 variable_names.insert(v.get_name());
263 }
264
265 writer->initialize(variables);
266
267 OutputFile file(writer, filename);
268
269 {
270 define_time(file);
271 define_variables(file, variables);
272 }
273
274 {
275 io::write_config(*m_config, "pism_config", file);
276 file.append_time(m_time->current());
277 write_state(file);
278 write_state_diagnostics(file, variable_names);
279 write_diagnostics(file, variable_names);
280 write_run_stats(file);
281 }
282
283 file.close();
284
285 return filename;
286}
287
288} // end of namespace pism
std::map< std::string, const Component * > m_submodels
the list of sub-models, for writing model states and obtaining diagnostics
Definition IceModel.hh:297
double m_start_time
Definition IceModel.hh:524
void define_variables(const OutputFile &file, const std::set< VariableMetadata > &variables) const
Definition output.cc:206
unsigned int m_step_counter
Definition IceModel.hh:368
std::set< std::string > m_spatial_vars
Definition IceModel.hh:494
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
void write_run_stats(const OutputFile &file) const
Definition output.cc:182
std::shared_ptr< Context > m_ctx
Execution context.
Definition IceModel.hh:280
std::shared_ptr< Logger > m_log
Logger.
Definition IceModel.hh:284
virtual std::set< VariableMetadata > diagnostic_variables(const std::set< std::string > &variable_names) const
std::set< VariableMetadata > m_output_file_contents
Set of variables that will be written to the output file.
Definition IceModel.hh:239
std::set< VariableMetadata > state_variables_diagnostics(const std::set< std::string > &variable_names) const
virtual std::set< VariableMetadata > state_variables() const
Definition output.cc:217
std::string save_state_on_error(const std::string &suffix, const std::set< std::string > &additional_variables)
Definition output.cc:250
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
std::set< VariableMetadata > common_metadata() const
Definition output.cc:81
void write_state_diagnostics(const OutputFile &file, const std::set< std::string > &variable_names) const
void write_diagnostics(const OutputFile &file, const std::set< std::string > &variable_names) const
Writes variables listed in variable_names to file.
std::set< array::Array * > m_model_state
Definition IceModel.hh:459
virtual std::set< std::string > output_variables(const std::string &keyword)
Assembles a list of diagnostics corresponding to an output file size.
const units::System::Ptr m_sys
Unit system.
Definition IceModel.hh:282
void write_final_output()
Save model state in NetCDF format.
Definition output.cc:155
std::shared_ptr< OutputWriter > m_output_writer
Definition IceModel.hh:288
void init_final_output()
Definition output.cc:114
std::string m_output_filename
Name of the output file.
Definition IceModel.hh:233
virtual void write_state(const OutputFile &file) const
Definition output.cc:240
virtual void append_history(const std::string &string)
Get time and user/host name and add it to the given string.
Definition utilities.cc:106
std::set< std::string > m_output_vars
Definition IceModel.hh:236
const std::shared_ptr< Grid > m_grid
Computational grid.
Definition IceModel.hh:276
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
void append_time(double time_seconds) const
Definition OutputFile.cc:41
unsigned int time_dimension_length() const
Definition OutputFile.cc:86
void define_variable(const VariableMetadata &variable) const
Definition OutputFile.cc:31
void write_array(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::vector< double > &input) const
Definition OutputFile.cc:49
void begin(const char *name) const
Definition Profiling.cc:75
void end(const char *name) const
Definition Profiling.cc:91
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
std::string get_string(const std::string &name) const
Get a string attribute.
VariableMetadata & set_output_type(io::Type type)
VariableMetadata & set_time_dependent(bool flag)
@ PISM_FLOAT
Definition IO_Flags.hh:52
void write_config(const Config &config, const std::string &variable_name, const OutputFile &file)
void define_variables(const OutputFile &file, const std::set< VariableMetadata > &variables, const VariableMetadata &mapping, bool use_internal_units)
MaxTimestep reporting_max_timestep(const std::vector< double > &times, double t, double eps, const std::string &description)
Definition output.cc:43
double wall_clock_hours(MPI_Comm com, double start_time)
Return time since the beginning of the run, in hours.
bool ends_with(const std::string &str, const std::string &suffix)
Returns true if str ends with suffix and false otherwise.
static const double k
Definition exactTestP.cc:42
std::string filename_add_suffix(const std::string &filename, const std::string &separator, const std::string &suffix)
Adds a suffix to a filename.
T combine(const T &a, const T &b)
VariableMetadata config_metadata(const Config &config)
Definition Config.cc:939
bool set_member(const std::string &string, const std::set< std::string > &set)
int count
Definition test_cube.c:16