PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
output_ts.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_options.hh"
23 #include "pism/util/pism_utilities.hh"
24 
25 namespace pism {
26 
27 /*!
28  * Process -ts_vars shortcuts.
29  */
30 static std::set<std::string> process_ts_shortcuts(const Config &config,
31  const std::set<std::string> &input) {
32  std::set<std::string> result = input;
33 
34  if (result.find("ismip6") != result.end()) {
35  result.erase("ismip6");
36  for (auto v : set_split(config.get_string("output.ISMIP6_ts_variables"), ',')) {
37  result.insert(v);
38  }
39  }
40 
41  return result;
42 }
43 
44 //! Initializes the code writing scalar time-series.
46 
47  m_ts_filename = m_config->get_string("output.timeseries.filename");
48 
49  auto times = m_config->get_string("output.timeseries.times");
50  bool times_set = not times.empty();
51 
52  if (times_set xor not m_ts_filename.empty()) {
54  "you need to specity both -ts_file and -ts_times"
55  " to save scalar diagnostic time-series.");
56  }
57 
58  if (m_ts_filename.empty()) {
59  return;
60  }
61 
62  try {
63  *m_ts_times = m_time->parse_times(times);
64  } catch (RuntimeError &e) {
65  e.add_context("parsing the -ts_times argument %s", times.c_str());
66  throw;
67  }
68 
69  m_log->message(2, " saving scalar time-series to '%s'\n", m_ts_filename.c_str());
70  m_log->message(2, " times requested: %s\n", times.c_str());
71 
72  m_ts_vars = set_split(m_config->get_string("output.timeseries.variables"), ',');
73  if (not m_ts_vars.empty()) {
75  m_log->message(2, "variables requested: %s\n", set_join(m_ts_vars, ",").c_str());
76  }
77 
78  // prepare the output file
79  {
80  // default behavior is to move the file aside if it exists already; option allows appending
81  bool append = m_config->get_flag("output.timeseries.append");
82  auto mode = append ? io::PISM_READWRITE : io::PISM_READWRITE_MOVE;
83  File file(m_grid->com, m_ts_filename, io::PISM_NETCDF3, mode); // Use NetCDF-3 to write time-series.
84  // add the last saved time to the list of requested times so that the first time is interpreted
85  // as the end of a reporting time step
86  if (append and file.dimension_length("time") > 0) {
87  double
88  epsilon = m_config->get_number("time_stepping.resolution"), // usually one second
89  t = vector_max(file.read_dimension("time"));
90 
91  // add this time only if it is strictly before the first requested one
92  if (t + epsilon < m_ts_times->front()) {
93  m_ts_times->insert(m_ts_times->begin(), t);
94  }
95  }
96 
98  write_run_stats(file, run_stats());
99 
100  // initialize scalar diagnostics
101  for (auto d : m_ts_diagnostics) {
102  d.second->init(file, m_ts_times);
103  }
104  }
105 }
106 
107 //! Computes the maximum time-step we can take and still hit all `-ts_times`.
109 
110  if ((not m_config->get_flag("time_stepping.hit_ts_times")) or
111  m_ts_diagnostics.empty()) {
112  return MaxTimestep("reporting (-ts_times)");
113  }
114 
115  double eps = m_config->get_number("time_stepping.resolution");
116 
117  return reporting_max_timestep(*m_ts_times, my_t, eps,
118  "reporting (-ts_times)");
119 }
120 
121 //! Flush scalar time-series.
123  // flush all the time-series buffers:
124  for (auto d : m_ts_diagnostics) {
125  d.second->flush();
126  }
127 
128  // update run_stats in the time series output file
129  if (not m_ts_diagnostics.empty()) {
131  write_run_stats(file, run_stats());
132  }
133 }
134 
135 } // end of namespace pism
std::string get_string(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
A class for storing and accessing PISM configuration flags and parameters.
unsigned int dimension_length(const std::string &name) const
Get the length of a dimension.
Definition: File.cc:454
std::vector< double > read_dimension(const std::string &name) const
Get dimension data (a coordinate variable).
Definition: File.cc:603
High-level PISM I/O class.
Definition: File.hh:56
VariableMetadata run_stats() const
Definition: utilities.cc:92
std::map< std::string, TSDiagnostic::Ptr > m_ts_diagnostics
Requested scalar diagnostics.
Definition: IceModel.hh:421
const Config::Ptr m_config
Configuration flags and parameters.
Definition: IceModel.hh:243
const Time::Ptr m_time
Time manager.
Definition: IceModel.hh:251
std::shared_ptr< std::vector< double > > m_ts_times
requested times for scalar time-series
Definition: IceModel.hh:439
const Logger::Ptr m_log
Logger.
Definition: IceModel.hh:249
MaxTimestep ts_max_timestep(double my_t)
Computes the maximum time-step we can take and still hit all -ts_times.
Definition: output_ts.cc:108
void flush_timeseries()
Flush scalar time-series.
Definition: output_ts.cc:122
std::string m_ts_filename
file to write scalar time-series to
Definition: IceModel.hh:437
std::set< std::string > m_ts_vars
Definition: IceModel.hh:440
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
void init_timeseries()
Initializes the code writing scalar time-series.
Definition: output_ts.cc:45
const std::shared_ptr< Grid > m_grid
Computational grid.
Definition: IceModel.hh:241
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
Definition: MaxTimestep.hh:31
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_NETCDF3
Definition: IO_Flags.hh:57
@ 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
std::string set_join(const std::set< std::string > &input, const std::string &separator)
std::set< std::string > set_split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a set of strings.
static std::set< std::string > process_ts_shortcuts(const Config &config, const std::set< std::string > &input)
Definition: output_ts.cc:30
void write_run_stats(const File &file, const pism::VariableMetadata &stats)
Definition: output.cc:162
double vector_max(const std::vector< double > &input)