PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
output_save.cc
Go to the documentation of this file.
1 /* Copyright (C) 2017, 2018, 2019, 2021, 2023 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/pism_utilities.hh"
23 #include "pism/util/Profiling.hh"
24 
25 namespace pism {
26 
27 //! Computes the maximum time-step we can take and still hit all `-save_times`.
29 
30  if ((not m_save_snapshots) or
31  (not m_config->get_flag("time_stepping.hit_save_times"))) {
32  return MaxTimestep("reporting (-save_times)");
33  }
34 
35  double eps = m_config->get_number("time_stepping.resolution");
36 
37  return reporting_max_timestep(m_snapshot_times, my_t, eps,
38  "reporting (-save_times)");
39 }
40 
41 //! Initializes the snapshot-saving mechanism.
44 
45  m_snapshots_filename = m_config->get_string("output.snapshot.file");
46  bool filename_set = not m_snapshots_filename.empty();
47 
48  auto save_times = m_config->get_string("output.snapshot.times");
49  bool times_set = not save_times.empty();
50 
51  bool split = m_config->get_flag("output.snapshot.split");
52 
53  m_snapshot_vars = output_variables(m_config->get_string("output.snapshot.size"));
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 not times_set) {
62  m_save_snapshots = false;
63  return;
64  }
65 
66  try {
67  // parse
68  std::vector<double> times = m_time->parse_times(save_times);
69 
70  // discard times before the beginning and after the end of the run
71  m_snapshot_times.clear();
72  for (const auto &t : times) {
73  if (t >= m_time->start() and t <= m_time->end()) {
74  m_snapshot_times.push_back(t);
75  }
76  }
77  } catch (RuntimeError &e) {
78  e.add_context("processing output.snapshot.times");
79  throw;
80  }
81 
82  if (m_snapshot_times.size() == 0) {
84  "output.snapshot.times was set, but all requested times"
85  " are outside of the modeled time interval");
86  }
87 
88  m_save_snapshots = true;
90  m_split_snapshots = false;
91 
92  if (split) {
93  m_split_snapshots = true;
94  } else if (not ends_with(m_snapshots_filename, ".nc")) {
95  m_log->message(2,
96  "PISM WARNING: snapshots file name does not have the '.nc' suffix!\n");
97  }
98 
99  if (split) {
100  m_log->message(2, "saving snapshots to '%s+year.nc'; ",
101  m_snapshots_filename.c_str());
102  } else {
103  m_log->message(2, "saving snapshots to '%s'; ",
104  m_snapshots_filename.c_str());
105  }
106 
107  m_log->message(2, "times requested: %s\n", save_times.c_str());
108 }
109 
110  //! Writes a snapshot of the model state (if necessary)
112  double saving_after = -1.0e30; // initialize to avoid compiler warning; this
113  // value is never used, because saving_after
114  // is only used if save_now == true, and in
115  // this case saving_after is guaranteed to be
116  // initialized. See the code below.
117  std::string filename;
118 
119  // determine if the user set the -save_times and -save_file options
120  if (not m_save_snapshots) {
121  return;
122  }
123 
124  // do we need to save *now*?
125  if ((m_time->current() >= m_snapshot_times[m_current_snapshot]) and
127  saving_after = m_snapshot_times[m_current_snapshot];
128 
129  while ((m_current_snapshot < m_snapshot_times.size()) and
130  (m_snapshot_times[m_current_snapshot] <= m_time->current())) {
132  }
133  } else {
134  // we don't need to save now, so just return
135  return;
136  }
137 
138  // flush time-series buffers
140 
141  if (m_split_snapshots) {
142  m_snapshots_file_is_ready = false; // each snapshot is written to a separate file
143  auto date_without_spaces = replace_character(m_time->date(saving_after), ' ', '_');
144  filename = pism::printf("%s_%s.nc",
145  m_snapshots_filename.c_str(),
146  date_without_spaces.c_str());
147  } else {
148  filename = m_snapshots_filename.c_str();
149  }
150 
151  m_log->message(2,
152  "saving snapshot to %s at %s, for time-step goal %s\n",
153  filename.c_str(), m_time->date(m_time->current()).c_str(),
154  m_time->date(saving_after).c_str());
155 
156  const Profiling &profiling = m_ctx->profiling();
157 
158  profiling.begin("io.snapshots");
160  {
161  File file(m_grid->com,
162  filename,
163  string_to_backend(m_config->get_string("output.format")),
164  mode,
165  m_ctx->pio_iosys_id());
166 
167  if (not m_snapshots_file_is_ready) {
169 
171  }
172 
173  write_run_stats(file, run_stats());
174 
176  }
177  profiling.end("io.snapshots");
178 }
179 
180 } // end of namespace pism
High-level PISM I/O class.
Definition: File.hh:56
unsigned int m_current_snapshot
Definition: IceModel.hh:431
std::set< std::string > m_snapshot_vars
Definition: IceModel.hh:430
std::string m_snapshots_filename
Definition: IceModel.hh:427
VariableMetadata run_stats() const
Definition: utilities.cc:92
const Config::Ptr m_config
Configuration flags and parameters.
Definition: IceModel.hh:243
bool m_split_snapshots
Definition: IceModel.hh:428
void write_snapshot()
Writes a snapshot of the model state (if necessary)
Definition: output_save.cc:111
const Time::Ptr m_time
Time manager.
Definition: IceModel.hh:251
std::vector< double > m_snapshot_times
Definition: IceModel.hh:429
const std::shared_ptr< Context > m_ctx
Execution context.
Definition: IceModel.hh:245
const Logger::Ptr m_log
Logger.
Definition: IceModel.hh:249
void flush_timeseries()
Flush scalar time-series.
Definition: output_ts.cc:122
virtual void save_variables(const File &file, OutputKind kind, const std::set< std::string > &variables, double time, io::Type default_diagnostics_type=io::PISM_FLOAT) const
Definition: output.cc:169
virtual std::set< std::string > output_variables(const std::string &keyword)
Assembles a list of diagnostics corresponding to an output file size.
MaxTimestep save_max_timestep(double my_t)
Computes the maximum time-step we can take and still hit all -save_times.
Definition: output_save.cc:28
void init_snapshots()
Initializes the snapshot-saving mechanism.
Definition: output_save.cc:42
virtual void write_metadata(const File &file, MappingTreatment mapping_flag, HistoryTreatment history_flag) const
Write time-independent metadata to a file.
Definition: output.cc:72
bool m_snapshots_file_is_ready
Definition: IceModel.hh:428
const std::shared_ptr< Grid > m_grid
Computational grid.
Definition: IceModel.hh:241
bool m_save_snapshots
Definition: IceModel.hh:428
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
Definition: MaxTimestep.hh:31
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
@ PISM_READWRITE_MOVE
create a file for writing, move foo.nc to foo.nc~ if present
Definition: IO_Flags.hh:78
@ PISM_READWRITE
open an existing file for reading and writing
Definition: IO_Flags.hh:74
MaxTimestep reporting_max_timestep(const std::vector< double > &times, double t, double eps, const std::string &description)
Definition: output.cc:41
io::Backend string_to_backend(const std::string &backend)
Definition: File.cc:57
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,...)
std::string replace_character(const std::string &input, char from, char to)
void write_run_stats(const File &file, const pism::VariableMetadata &stats)
Definition: output.cc:162
std::vector< std::string > split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a vector of strings.