22 #include <netcdf_meta.h>
25 #include "pism/icemodel/IceModel.hh"
27 #include "pism/util/pism_utilities.hh"
28 #include "pism/util/Profiling.hh"
36 (not
m_config->get_flag(
"time_stepping.hit_extra_times"))) {
40 double eps =
m_config->get_number(
"time_stepping.resolution");
43 "reporting (-extra_times)");
47 const std::set<std::string> &input) {
48 std::set<std::string> result = input;
51 if (result.find(
"amount_fluxes") != result.end()) {
52 result.erase(
"amount_fluxes");
53 result.insert(
"tendency_of_ice_amount");
54 result.insert(
"tendency_of_ice_amount_due_to_basal_mass_flux");
55 result.insert(
"tendency_of_ice_amount_due_to_conservation_error");
56 result.insert(
"tendency_of_ice_amount_due_to_discharge");
57 result.insert(
"tendency_of_ice_amount_due_to_flow");
58 result.insert(
"tendency_of_ice_amount_due_to_surface_mass_flux");
61 if (result.find(
"mass_fluxes") != result.end()) {
62 result.erase(
"mass_fluxes");
63 result.insert(
"tendency_of_ice_mass");
64 result.insert(
"tendency_of_ice_mass_due_to_basal_mass_flux");
65 result.insert(
"tendency_of_ice_mass_due_to_conservation_error");
66 result.insert(
"tendency_of_ice_mass_due_to_discharge");
67 result.insert(
"tendency_of_ice_mass_due_to_flow");
68 result.insert(
"tendency_of_ice_mass_due_to_surface_mass_flux");
71 if (result.find(
"pdd_fluxes") != result.end()) {
72 result.erase(
"pdd_fluxes");
73 result.insert(
"surface_accumulation_flux");
74 result.insert(
"surface_runoff_flux");
75 result.insert(
"surface_melt_flux");
78 if (result.find(
"pdd_rates") != result.end()) {
79 result.erase(
"pdd_rates");
80 result.insert(
"surface_accumulation_rate");
81 result.insert(
"surface_runoff_rate");
82 result.insert(
"surface_melt_rate");
85 if (result.find(
"hydrology_fluxes") != result.end()) {
86 result.erase(
"hydrology_fluxes");
87 result.insert(
"tendency_of_subglacial_water_mass");
88 result.insert(
"tendency_of_subglacial_water_mass_due_to_input");
89 result.insert(
"tendency_of_subglacial_water_mass_due_to_flow");
90 result.insert(
"tendency_of_subglacial_water_mass_due_to_conservation_error");
91 result.insert(
"tendency_of_subglacial_water_mass_at_grounded_margins");
92 result.insert(
"tendency_of_subglacial_water_mass_at_grounding_line");
93 result.insert(
"tendency_of_subglacial_water_mass_at_domain_boundary");
96 if (result.find(
"ismip6") != result.end()) {
98 const char *flag_name =
"output.ISMIP6";
100 if (not config.
get_flag(flag_name)) {
102 "(-extra_vars ismip6).", flag_name);
105 result.erase(
"ismip6");
121 std::string times =
m_config->get_string(
"output.extra.times");
122 std::string vars =
m_config->get_string(
"output.extra.vars");
124 bool append =
m_config->get_flag(
"output.extra.append");
127 bool times_set = not times.empty();
129 if (extra_file_set ^ times_set) {
131 "you need to set both output.extra.file and output.extra.times"
132 " to save spatial time-series.");
135 if (not extra_file_set and not times_set) {
143 e.
add_context(
"parsing the output.extra.times argument %s", times.c_str());
151 if (append and
split) {
153 "both output.extra.split and output.extra.append are set.");
159 std::string time_name =
m_config->get_string(
"time.dimension_name");
169 "skipping times before the last record in %s (at %s)\n",
175 for (
unsigned int k = 0;
k < tmp.size(); ++
k) {
190 m_log->message(2,
"saving spatial time-series to '%s+year.nc'; ",
195 "PISM WARNING: spatial time-series file name '%s' does not have the '.nc' suffix!\n",
198 m_log->message(2,
"saving spatial time-series to '%s'; ",
202 m_log->message(2,
"times requested: %s\n", times.c_str());
206 "PISM WARNING: more than 500 times requested. This might fill your hard-drive!\n");
209 #ifdef NC_HAVE_META_H
211 if (100 * NC_VERSION_MAJOR + 10 * NC_VERSION_MINOR + NC_VERSION_PATCH < 473) {
214 "more than 5000 times requested."
215 "Please use -extra_split to avoid a crash caused by a bug in NetCDF versions older than 4.7.3.\n"
217 "- split this simulation into several runs and then concatenate results\n"
218 "- select a different output.format value\n"
219 "- upgrade NetCDF to 4.7.3");
225 if (not vars.empty()) {
227 m_log->message(2,
"variables requested: %s\n", vars.c_str());
230 "PISM WARNING: output.extra.vars was not set. Writing the model state...\n");
236 double saving_after = -1.0e30;
241 std::string filename;
242 unsigned int current_extra;
248 const double time_resolution =
m_config->get_number(
"time_stepping.resolution");
249 double current_time =
m_time->current();
272 if (current_extra == 0) {
281 if (not
m_config->get_flag(
"output.ISMIP6")) {
286 if (saving_after < m_time->start()) {
305 date_without_spaces.c_str());
311 "saving spatial time-series to %s at %s\n",
312 filename.c_str(),
m_time->date(
m_time->current()).c_str());
315 bool append =
m_config->get_flag(
"output.extra.append");
319 profiling.
begin(
"io.extra_file");
326 m_ctx->pio_iosys_id()));
329 std::string time_name =
m_config->get_string(
"time.dimension_name");
334 m_extra_file->write_attribute(time_name,
"bounds",
"time_bounds");
354 unsigned int time_length =
m_extra_file->dimension_length(time_name);
355 size_t time_start = time_length > 0 ?
static_cast<size_t>(time_length - 1) : 0;
362 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.
VariableLookupData find_variable(const std::string &short_name, const std::string &std_name) const
Find a variable using its standard name and/or short name.
std::vector< double > read_dimension(const std::string &name) const
Get dimension data (a coordinate variable).
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
const Config::Ptr m_config
Configuration flags and parameters.
void write_extras()
Write spatially-variable diagnostic quantities.
const Time::Ptr m_time
Time manager.
virtual void reset_diagnostics()
void init_extras()
Initialize the code saving spatially-variable diagnostic quantities.
const std::shared_ptr< Context > m_ctx
Execution context.
const Logger::Ptr m_log
Logger.
void flush_timeseries()
Flush scalar time-series.
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
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
bool m_extra_file_is_ready
std::vector< double > m_extra_times
const std::shared_ptr< Grid > m_grid
Computational grid.
VariableMetadata m_extra_bounds
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
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,...)
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.