PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
output_snapshots.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#include <memory>
20
21#include "pism/icemodel/IceModel.hh"
22
23#include "pism/util/pism_utilities.hh"
24#include "pism/util/Profiling.hh"
25#include "pism/util/io/io_helpers.hh"
26
27namespace pism {
28
29//! Computes the maximum time-step we can take and still hit all `-save_times`.
31
32 if (m_snapshots_filename.empty() or (not m_config->get_flag("time_stepping.hit_save_times"))) {
33 return MaxTimestep("reporting (-save_times)");
34 }
35
36 double eps = m_config->get_number("time_stepping.resolution");
37
39 "reporting (-save_times)");
40}
41
42//! Initializes the snapshot-saving mechanism.
45
46 m_snapshots_filename = m_config->get_string("output.snapshot.file");
47 auto save_times = m_config->get_string("output.snapshot.times");
48 m_snapshot_vars = output_variables(m_config->get_string("output.snapshot.size"));
49 m_split_snapshots = m_config->get_flag("output.snapshot.split");
50
51 {
52 bool filename_set = not m_snapshots_filename.empty();
53 bool times_set = not save_times.empty();
54
55 if (filename_set ^ times_set) {
57 "you need to set both output.snapshot.file and output.snapshot.times"
58 " to save snapshots.");
59 }
60
61 if (not (filename_set and times_set)) {
62 return;
63 }
64 }
65
73
74 try {
75 // parse
76 std::vector<double> times = m_time->parse_times(save_times);
77
78 // discard times before the beginning and after the end of the run
79 m_snapshot_times.clear();
80 for (const auto &t : times) {
81 if (t >= m_time->start() and t <= m_time->end()) {
82 m_snapshot_times.push_back(t);
83 }
84 }
85 } catch (RuntimeError &e) {
86 e.add_context("processing output.snapshot.times");
87 throw;
88 }
89
90 if (m_snapshot_times.empty()) {
92 "output.snapshot.times was set, but all requested times"
93 " are outside of the modeled time interval");
94 }
95
96 if (not m_split_snapshots and not ends_with(m_snapshots_filename, ".nc")) {
97 m_log->message(2, "PISM WARNING: snapshots file name does not have the '.nc' suffix!\n");
98 }
99
100 m_log->message(2, "saving model state snapshots to '%s%s'%s\n",
101 m_snapshots_filename.c_str(),
102 m_split_snapshots ? "+date.nc" : "",
103 m_snapshot_writer->is_async() ? " using asynchronous output" : "");
104
105 m_log->message(2, " times requested: %s\n", save_times.c_str());
106}
107
108//! Writes a snapshot of the model state (if necessary)
110 // initialize to avoid compiler warning; this value is never used, because saving_after
111 // is only used if save_now == true, and in this case saving_after is guaranteed to be
112 // initialized. See the code below.
113 double saving_after = -1.0e30;
114
115 // determine if the user set the -save_times and -save_file options
116 if (m_snapshots_filename.empty()) {
117 return;
118 }
119
120 // do we need to save *now*?
121 if ((m_time->current() >= m_snapshot_times[m_current_snapshot]) and
123 saving_after = m_snapshot_times[m_current_snapshot];
124
125 while ((m_current_snapshot < m_snapshot_times.size()) and
126 (m_snapshot_times[m_current_snapshot] <= m_time->current())) {
128 }
129 } else {
130 // we don't need to save now, so just return
131 return;
132 }
133
134 // flush time-series buffers
136
137 const Profiling &profiling = m_ctx->profiling();
138
139 profiling.begin("io.snapshots");
140 std::string filename;
141 if (m_snapshot_file == nullptr) {
142 if (m_split_snapshots) {
143 auto date_without_spaces = replace_character(m_time->date(saving_after), ' ', '_');
144 filename =
145 pism::printf("%s_%s.nc", m_snapshots_filename.c_str(), date_without_spaces.c_str());
146 } else {
147 filename = m_snapshots_filename;
148 }
149
150 m_snapshot_file = std::make_shared<OutputFile>(m_snapshot_writer, filename);
151
152 {
155 }
156 }
157
158 {
159 m_log->message(2, "saving snapshot to %s at %s, for time-step goal %s\n", filename.c_str(),
160 m_time->date(m_time->current()).c_str(), m_time->date(saving_after).c_str());
161
162 {
163 io::write_config(*m_config, "pism_config", *m_snapshot_file);
164 m_snapshot_file->append_time(m_time->current());
169 }
170 }
171
172 if (m_split_snapshots) {
173 m_snapshot_file.reset();
174 }
175
176 profiling.end("io.snapshots");
177}
178
179} // end of namespace pism
unsigned int m_current_snapshot
Definition IceModel.hh:470
std::set< std::string > m_snapshot_vars
Definition IceModel.hh:473
std::string m_snapshots_filename
Definition IceModel.hh:466
void define_variables(const OutputFile &file, const std::set< VariableMetadata > &variables) const
Definition output.cc:206
bool m_split_snapshots
Definition IceModel.hh:468
void write_snapshot()
Writes a snapshot of the model state (if necessary)
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::vector< double > m_snapshot_times
Definition IceModel.hh:469
MaxTimestep snapshots_max_timestep(double my_t)
Computes the maximum time-step we can take and still hit all -save_times.
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::shared_ptr< OutputFile > m_snapshot_file
Definition IceModel.hh:467
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::shared_ptr< OutputWriter > m_snapshot_writer
Definition IceModel.hh:289
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< VariableMetadata > m_snapshot_file_contents
set of variables that will be written to snapshot files
Definition IceModel.hh:475
virtual std::set< std::string > output_variables(const std::string &keyword)
Assembles a list of diagnostics corresponding to an output file size.
void init_snapshots()
Initializes the snapshot-saving mechanism.
void scalar_diagnostics_flush_buffers()
Flush scalar time-series.
virtual void write_state(const OutputFile &file) const
Definition output.cc:240
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
void begin(const char *name) const
Definition Profiling.cc:75
void end(const char *name) const
Definition Profiling.cc:91
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...
#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
bool ends_with(const std::string &str, const std::string &suffix)
Returns true if str ends with suffix and false otherwise.
std::string printf(const char *format,...)
T combine(const T &a, const T &b)
std::string replace_character(const std::string &input, char from, char to)