21#include "pism/icemodel/IceModel.hh"
23#include "pism/util/pism_utilities.hh"
24#include "pism/util/Profiling.hh"
25#include "pism/util/io/io_helpers.hh"
33 (not
m_config->get_flag(
"time_stepping.hit_spatial_times"))) {
37 double eps =
m_config->get_number(
"time_stepping.resolution");
40 "reporting (-spatial_times)");
44 const std::set<std::string> &input) {
45 std::set<std::string> result = input;
48 if (result.find(
"amount_fluxes") != result.end()) {
49 result.erase(
"amount_fluxes");
50 result.insert({
"tendency_of_ice_amount",
"tendency_of_ice_amount_due_to_basal_mass_flux",
51 "tendency_of_ice_amount_due_to_conservation_error",
52 "tendency_of_ice_amount_due_to_discharge",
"tendency_of_ice_amount_due_to_flow",
53 "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",
"tendency_of_ice_mass_due_to_basal_mass_flux",
59 "tendency_of_ice_mass_due_to_conservation_error",
60 "tendency_of_ice_mass_due_to_discharge",
"tendency_of_ice_mass_due_to_flow",
61 "tendency_of_ice_mass_due_to_surface_mass_flux" });
64 if (result.find(
"pdd_fluxes") != result.end()) {
65 result.erase(
"pdd_fluxes");
66 result.insert({
"surface_accumulation_flux",
"surface_runoff_flux",
"surface_melt_flux" });
69 if (result.find(
"pdd_rates") != result.end()) {
70 result.erase(
"pdd_rates");
71 result.insert({
"surface_accumulation_rate",
"surface_runoff_rate",
"surface_melt_rate" });
74 if (result.find(
"hydrology_fluxes") != result.end()) {
75 result.erase(
"hydrology_fluxes");
76 result.insert({
"tendency_of_subglacial_water_mass",
77 "tendency_of_subglacial_water_mass_due_to_input",
78 "tendency_of_subglacial_water_mass_due_to_flow",
79 "tendency_of_subglacial_water_mass_due_to_conservation_error",
80 "tendency_of_subglacial_water_mass_at_grounded_margins",
81 "tendency_of_subglacial_water_mass_at_grounding_line",
82 "tendency_of_subglacial_water_mass_at_domain_boundary" });
85 if (result.find(
"ismip6") != result.end()) {
87 const char *flag_name =
"output.ISMIP6";
89 if (not config.
get_flag(flag_name)) {
91 "(-spatial_vars ismip6).", flag_name);
94 result.erase(
"ismip6");
95 for (
const auto& v :
set_split(config.
get_string(
"output.ISMIP6_spatial_variables"),
',')) {
110 std::string times =
m_config->get_string(
"output.spatial.times");
112 bool append =
m_config->get_flag(
"output.spatial.append");
115 bool times_set = not times.empty();
117 if (file_set ^ times_set) {
119 "you need to set both output.spatial.file and output.spatial.times"
120 " to save spatial time-series.");
123 if (not file_set and not times_set) {
131 e.
add_context(
"parsing the output.spatial.times argument %s", times.c_str());
139 if (append and
split) {
141 "both output.spatial.split and output.spatial.append are set.");
150 2,
"PISM WARNING: spatial time-series file name '%s' does not have the '.nc' suffix!\n",
157 m_log->message(2,
" times requested: %s\n", times.c_str());
161 2,
"PISM WARNING: more than 500 times requested. This might fill your hard-drive!\n");
167 auto vars =
m_config->get_string(
"output.spatial.vars");
168 if (not vars.empty()) {
173 m_log->message(2,
" variables requested: %s\n",
174 vars.empty() ?
"model state variables" : vars.c_str());
202 m_log->message(2,
"skipping times before the last record in %s (at %s)\n",
208 for (
unsigned int k = 0;
k < tmp.size(); ++
k) {
217 bool with_time_bounds =
true;
225 m_config->get_string(
"output.format") ==
"netcdf4_parallel") {
228 "more than 5000 times requested."
229 "Please use -spatial_split to avoid a crash caused by a bug in NetCDF versions older than 4.7.3.\n"
231 "- split this simulation into several runs and then concatenate results\n"
232 "- select a different output.format value\n"
233 "- upgrade NetCDF to 4.7.3");
241 double saving_after = -1.0e30;
246 unsigned int current_index;
252 const double time_resolution =
m_config->get_number(
"time_stepping.resolution");
253 double current_time =
m_time->current();
276 if (current_index == 0) {
285 if (not
m_config->get_flag(
"output.ISMIP6")) {
290 if (saving_after < m_time->start()) {
307 profiling.
begin(
"io.spatial_file");
320 if (
m_config->get_flag(
"output.spatial.append")) {
324 bool with_time_bounds =
true;
330 m_log->message(3,
"saving spatial time-series to %s at %s\n",
m_spatial_file->name().c_str(),
350 auto time_start = time_length > 0 ? (time_length - 1) : 0;
352 auto bounds_name =
m_time->variable_name() +
"_bounds";
354 m_spatial_file->write_array(bounds_name, { time_start, 0 }, { 1, 2 },
370 profiling.
end(
"io.spatial_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.
void define_variables(const OutputFile &file, const std::set< VariableMetadata > &variables) const
std::set< std::string > m_spatial_vars
std::shared_ptr< Config > m_config
Configuration flags and parameters.
MaxTimestep spatial_diagnostics_max_timestep(double t)
Computes the maximum time-step we can take and still hit all -spatial_times.
void define_time(const OutputFile &file, bool with_bounds=false) const
void write_run_stats(const OutputFile &file) const
std::shared_ptr< Context > m_ctx
Execution context.
std::shared_ptr< Logger > m_log
Logger.
std::set< VariableMetadata > m_spatial_file_contents
set of variables that will be written to extra files
virtual std::set< VariableMetadata > diagnostic_variables(const std::set< std::string > &variable_names) const
unsigned int m_next_spatial_index
virtual std::set< VariableMetadata > state_variables() const
std::shared_ptr< OutputWriter > m_spatial_writer
std::shared_ptr< Time > m_time
Time manager.
void write_spatial_diagnostics()
Write spatially-variable diagnostic quantities.
std::vector< double > m_spatial_times
std::map< std::string, Diagnostic::Ptr > m_available_spatial_diagnostics
Available spatially-variable diagnostics.
std::set< VariableMetadata > common_metadata() const
std::shared_ptr< OutputFile > m_spatial_file
void write_diagnostics(const OutputFile &file, const std::set< std::string > &variable_names) const
Writes variables listed in variable_names to file.
std::string m_spatial_filename
void init_spatial_diagnostics()
Initialize the code saving spatially-variable diagnostic quantities.
void scalar_diagnostics_flush_buffers()
Flush scalar time-series.
virtual void write_state(const OutputFile &file) const
double m_last_spatial_time
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
void write_config(const Config &config, const std::string &variable_name, const OutputFile &file)
MaxTimestep reporting_max_timestep(const std::vector< double > ×, double t, double eps, const std::string &description)
static std::set< std::string > process_variable_list_shortcuts(const Config &config, const std::set< std::string > &input)
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.
T combine(const T &a, const T &b)
std::string replace_character(const std::string &input, char from, char to)
std::vector< std::string > split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a vector of strings.