20#include "pism/icemodel/IceModel.hh"
22#include "pism/util/pism_utilities.hh"
23#include "pism/util/Profiling.hh"
31 (not
m_config->get_flag(
"time_stepping.hit_extra_times"))) {
35 double eps =
m_config->get_number(
"time_stepping.resolution");
38 "reporting (-extra_times)");
42 const std::set<std::string> &input) {
43 std::set<std::string> result = input;
46 if (result.find(
"amount_fluxes") != result.end()) {
47 result.erase(
"amount_fluxes");
48 result.insert(
"tendency_of_ice_amount");
49 result.insert(
"tendency_of_ice_amount_due_to_basal_mass_flux");
50 result.insert(
"tendency_of_ice_amount_due_to_conservation_error");
51 result.insert(
"tendency_of_ice_amount_due_to_discharge");
52 result.insert(
"tendency_of_ice_amount_due_to_flow");
53 result.insert(
"tendency_of_ice_amount_due_to_surface_mass_flux");
56 if (result.find(
"mass_fluxes") != result.end()) {
57 result.erase(
"mass_fluxes");
58 result.insert(
"tendency_of_ice_mass");
59 result.insert(
"tendency_of_ice_mass_due_to_basal_mass_flux");
60 result.insert(
"tendency_of_ice_mass_due_to_conservation_error");
61 result.insert(
"tendency_of_ice_mass_due_to_discharge");
62 result.insert(
"tendency_of_ice_mass_due_to_flow");
63 result.insert(
"tendency_of_ice_mass_due_to_surface_mass_flux");
66 if (result.find(
"pdd_fluxes") != result.end()) {
67 result.erase(
"pdd_fluxes");
68 result.insert(
"surface_accumulation_flux");
69 result.insert(
"surface_runoff_flux");
70 result.insert(
"surface_melt_flux");
73 if (result.find(
"pdd_rates") != result.end()) {
74 result.erase(
"pdd_rates");
75 result.insert(
"surface_accumulation_rate");
76 result.insert(
"surface_runoff_rate");
77 result.insert(
"surface_melt_rate");
80 if (result.find(
"hydrology_fluxes") != result.end()) {
81 result.erase(
"hydrology_fluxes");
82 result.insert(
"tendency_of_subglacial_water_mass");
83 result.insert(
"tendency_of_subglacial_water_mass_due_to_input");
84 result.insert(
"tendency_of_subglacial_water_mass_due_to_flow");
85 result.insert(
"tendency_of_subglacial_water_mass_due_to_conservation_error");
86 result.insert(
"tendency_of_subglacial_water_mass_at_grounded_margins");
87 result.insert(
"tendency_of_subglacial_water_mass_at_grounding_line");
88 result.insert(
"tendency_of_subglacial_water_mass_at_domain_boundary");
91 if (result.find(
"ismip6") != result.end()) {
93 const char *flag_name =
"output.ISMIP6";
95 if (not config.
get_flag(flag_name)) {
97 "(-extra_vars ismip6).", flag_name);
100 result.erase(
"ismip6");
116 std::string times =
m_config->get_string(
"output.extra.times");
117 std::string vars =
m_config->get_string(
"output.extra.vars");
119 bool append =
m_config->get_flag(
"output.extra.append");
122 bool times_set = not times.empty();
124 if (extra_file_set ^ times_set) {
126 "you need to set both output.extra.file and output.extra.times"
127 " to save spatial time-series.");
130 if (not extra_file_set and not times_set) {
138 e.
add_context(
"parsing the output.extra.times argument %s", times.c_str());
146 if (append and
split) {
148 "both output.extra.split and output.extra.append are set.");
154 std::string time_name =
m_config->get_string(
"time.dimension_name");
165 "skipping times before the last record in %s (at %s)\n",
171 for (
unsigned int k = 0;
k < tmp.size(); ++
k) {
182 m_log->message(2,
"saving spatial time-series to '%s+year.nc'; ",
188 "PISM WARNING: spatial time-series file name '%s' does not have the '.nc' suffix!\n",
191 m_log->message(2,
"saving spatial time-series to '%s'; ",
195 m_log->message(2,
"times requested: %s\n", times.c_str());
199 "PISM WARNING: more than 500 times requested. This might fill your hard-drive!\n");
204 m_config->get_string(
"output.format") ==
"netcdf4_parallel") {
207 "more than 5000 times requested."
208 "Please use -extra_split to avoid a crash caused by a bug in NetCDF versions older than 4.7.3.\n"
210 "- split this simulation into several runs and then concatenate results\n"
211 "- select a different output.format value\n"
212 "- upgrade NetCDF to 4.7.3");
216 if (not vars.empty()) {
218 m_log->message(2,
"variables requested: %s\n", vars.c_str());
221 "PISM WARNING: output.extra.vars was not set. Writing the model state...\n");
227 double saving_after = -1.0e30;
232 unsigned int current_extra;
238 const double time_resolution =
m_config->get_number(
"time_stepping.resolution");
239 double current_time =
m_time->current();
262 if (current_extra == 0) {
271 if (not
m_config->get_flag(
"output.ISMIP6")) {
276 if (saving_after < m_time->start()) {
291 profiling.
begin(
"io.extra_file");
293 std::string time_name =
m_config->get_string(
"time.dimension_name");
316 m_extra_file->write_attribute(time_name,
"bounds",
"time_bounds");
323 m_log->message(3,
"saving spatial time-series to %s at %s\n",
m_extra_file->name().c_str(),
336 unsigned int time_length =
m_extra_file->dimension_length(time_name);
337 size_t time_start = time_length > 0 ?
static_cast<size_t>(time_length - 1) : 0;
344 profiling.
end(
"io.extra_file");
std::string get_string(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
bool get_flag(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
A class for storing and accessing PISM configuration flags and parameters.
bool variable_exists(const std::string &short_name) const
Checks if a variable exists.
High-level PISM I/O class.
MaxTimestep extras_max_timestep(double my_t)
Computes the maximum time-step we can take and still hit all -extra_times.
VariableMetadata run_stats() const
unsigned int m_next_extra
std::unique_ptr< File > m_extra_file
void write_extras()
Write spatially-variable diagnostic quantities.
const Time::Ptr m_time
Time manager.
virtual void reset_diagnostics()
std::shared_ptr< Context > m_ctx
Execution context.
void init_extras()
Initialize the code saving spatially-variable diagnostic quantities.
const Logger::Ptr m_log
Logger.
void flush_timeseries()
Flush scalar time-series.
Config::Ptr m_config
Configuration flags and parameters.
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
const units::System::Ptr m_sys
Unit system.
std::set< std::string > m_extra_vars
virtual void write_metadata(const File &file, MappingTreatment mapping_flag, HistoryTreatment history_flag) const
Write time-independent metadata to a file.
std::string m_extra_filename
std::vector< double > m_extra_times
const std::shared_ptr< Grid > m_grid
Computational grid.
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
void begin(const char *name) const
void end(const char *name) const
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
@ PISM_READWRITE_MOVE
create a file for writing, move foo.nc to foo.nc~ if present
@ PISM_READONLY
open an existing file for reading only
@ PISM_READWRITE
open an existing file for reading and writing
std::vector< double > read_1d_variable(const File &file, const std::string &variable_name, const std::string &units, std::shared_ptr< units::System > unit_system)
void define_time_bounds(const VariableMetadata &var, const std::string &dimension_name, const std::string &bounds_name, const File &file, io::Type nctype)
void write_time_bounds(const File &file, const VariableMetadata &metadata, size_t t_start, const std::vector< double > &data)
void define_time(const File &file, const Context &ctx)
Prepare a file for output.
MaxTimestep reporting_max_timestep(const std::vector< double > ×, double t, double eps, const std::string &description)
io::Backend string_to_backend(const std::string &backend)
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,...)
int netcdf_version()
return NetCDF version as an integer
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_extra_shortcuts(const Config &config, const std::set< std::string > &input)
std::string replace_character(const std::string &input, char from, char to)
void write_run_stats(const File &file, const pism::VariableMetadata &stats)
double vector_max(const std::vector< double > &input)
std::vector< std::string > split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a vector of strings.