28#include "pism/util/io/IO_Flags.hh"
29#include "pism/util/Config.hh"
30#include "pism/util/GridInfo.hh"
31#include "pism/util/VariableMetadata.hh"
32#include "pism/util/io/OutputWriter.hh"
33#include "pism/util/error_handling.hh"
34#include "pism/util/pism_utilities.hh"
44 auto variable = metadata;
46 auto get = [&variable](
const std::string &name) {
47 auto j = variable.strings.find(name);
48 if (j != variable.strings.end()) {
55 std::string units = get(
"units");
56 std::string output_units = get(
"output_units");
59 variable.strings[
"output_units"] =
"";
61 bool use_output_units =
62 (not units.empty() and not output_units.empty() and units != output_units);
64 if (use_output_units) {
66 if (variable.is_set(
"units")) {
67 variable.strings[
"units"] = output_units;
74 if (variable.is_set(
"valid_range")) {
75 auto bounds = variable.numbers[
"valid_range"];
77 variable.numbers[
"valid_range"] = { c(bounds[0]), c(bounds[1]) };
79 if (variable.is_set(
"valid_min")) {
80 auto min = variable.numbers[
"valid_min"][0];
81 variable.numbers[
"valid_min"] = { c(min) };
83 if (variable.is_set(
"valid_max")) {
84 auto max = variable.numbers[
"valid_max"][0];
85 variable.numbers[
"valid_max"] = { c(max) };
89 if (variable.is_set(
"_FillValue")) {
90 auto fill = variable.numbers[
"_FillValue"][0];
91 variable.numbers[
"_FillValue"] = { c(fill) };
111 "the length of '%s' (%d) exceeds '%s' - 1. Please increase '%s'.",
113 "output.experiment_id_max_length",
114 "output.experiment_id_max_length");
118 auto format = config.
get_string(
"output.format");
119 if (format ==
"netcdf3" or format ==
"pnetcdf") {
122 "cannot save experiment ID \"%s\" to NetCDF-3 output files ('output.format' == \"%s\")",
147 const std::string &variable_name,
148 bool time_dependent) {
149 if (time_dependent) {
157 : m_impl(new
Impl(comm, config)) {
168 for (
const auto &variable : array_variables) {
169 if (variable.grid_info() !=
nullptr) {
203 "variable '%s' was not added using add_variable()",
204 variable_name.c_str());
208 unsigned int length) {
213 const std::vector<std::string> &dims,
io::Type type,
222 for (
const auto &dimension : variable.
dimensions()) {
224 if (dimension.coordinate_variable()) {
225 define_variable(file_name, dimension.get_name(), dimension.dimension_names(),
226 dimension.get_output_type(), dimension.attributes());
241 id.long_name(
"experiment ID");
253 dimensions.insert(dimensions.begin(),
time_name());
257 bool time_or_bounds =
282 const auto &name = metadata.get_name();
290 const std::string &file_name,
const std::map<std::string, std::string> &strings,
291 const std::map<std::string, std::vector<double> > &numbers) {
306 const std::vector<unsigned int> &start,
307 const std::vector<unsigned int> &
count,
308 const std::vector<double> &input) {
313 const std::vector<unsigned int> &start,
314 const std::vector<unsigned int> &
count,
const std::string &input) {
321 for (
const auto &dim : variable.
dimensions()) {
324 const std::vector<double> *coordinates =
nullptr;
328 if (grid !=
nullptr) {
329 coordinates = &grid->x;
335 if (grid !=
nullptr) {
336 coordinates = &grid->y;
341 coordinates = &variable.
levels();
344 if (coordinates ==
nullptr or coordinates->empty()) {
349 auto dimension_name = dim.get_name();
351 write_array(file_name, dimension_name, { 0 }, { (
unsigned int)coordinates->size() },
364 const std::string &variable_name,
const double *input) {
368 if (variable.grid_info() ==
nullptr) {
371 "write_distributed_array() called for a variable (%s) that has no grid info",
372 variable_name.c_str());
375 bool time_dependent = variable.get_time_dependent();
390 e.
add_context(
"writing gridded variable '%s' to '%s'", variable_name.c_str(),
398 const std::string &variable_name,
399 const std::vector<unsigned int> &start,
400 const std::vector<unsigned int> &
count,
401 const std::vector<double> &input) {
407 S.insert(
S.cbegin(), 0);
408 C.insert(C.cbegin(), 1);
441 write_text(file_name, variable_name, { 0, 0 }, { 1, (unsigned)exp_id.size() + 1 }, exp_id);
double get_number(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
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.
OutputWriter(MPI_Comm comm, const Config &config)
void write_text(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::string &input)
unsigned int time_dimension_length(const std::string &file_name)
void close(const std::string &file_name)
void append(const std::string &file_name)
void add_variable(const VariableMetadata &metadata)
void set_is_async(bool flag)
virtual void write_array_impl(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const double *data)=0
virtual double last_time_value_impl(const std::string &file_name)=0
const std::string & time_name() const
virtual void set_global_attributes_impl(const std::string &file_name, const std::map< std::string, std::string > &strings, const std::map< std::string, std::vector< double > > &numbers)=0
void write_dimensions(const std::string &file_name, const VariableMetadata &variable)
bool & already_written(const std::string &file_name, const std::string &variable_name, bool time_dependent)
void define_variable(const std::string &file_name, const VariableMetadata &variable)
virtual void define_variable_impl(const std::string &file_name, const std::string &variable_name, const std::vector< std::string > &dims, io::Type type, const VariableAttributes &attributes)=0
virtual void define_dimension_impl(const std::string &file_name, const std::string &name, unsigned int length)=0
void set_global_attributes(const std::string &file_name, const std::map< std::string, std::string > &strings, const std::map< std::string, std::vector< double > > &numbers)
double last_time_value(const std::string &file_name)
void define_dimension(const std::string &file_name, const std::string &dimension_name, unsigned int length)
virtual void initialize_impl(const std::set< VariableMetadata > &array_variables)=0
void write_timeseries(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::vector< double > &input)
void append_time(const std::string &file_name, double time_seconds)
virtual void write_distributed_array_impl(const std::string &file_name, const std::string &variable_name, const double *data)=0
virtual void append_time_impl(const std::string &file_name, double time_seconds)=0
virtual void write_text_impl(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::string &input)=0
void initialize(const std::set< VariableMetadata > &array_variables, bool relaxed_mode=false)
virtual unsigned int time_dimension_length_impl(const std::string &file_name)=0
const std::string & experiment_id() const
void sync(const std::string &file_name)
std::vector< std::string > define_dimensions(const std::string &file_name, const VariableMetadata &variable)
virtual void close_impl(const std::string &file_name)=0
void write_experiment_id(const std::string &file_name)
void write_distributed_array(const std::string &file_name, const std::string &variable_name, const double *input)
virtual void sync_impl(const std::string &file_name)=0
const VariableMetadata & variable_info(const std::string &variable_name) const
bool variable_info_is_available(const std::string &variable_name) const
void append_history(const std::string &file_name, const std::string &text)
virtual void append_history_impl(const std::string &file_name, const std::string &text)=0
void write_array(const std::string &file_name, const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::vector< double > &input)
virtual void append_impl(const std::string &file_name)=0
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
static VariableAttributes format_attributes(const VariableAttributes &metadata)
AxisType axis_type_from_string(const std::string &input)
bool set_member(const std::string &string, const std::set< std::string > &set)
int experiment_id_max_length
Impl(MPI_Comm comm_, const Config &config)
std::string experiment_id_name
std::map< std::tuple< std::string, std::string >, bool > written_time_dependent
std::map< std::tuple< std::string, std::string >, bool > written_time_independent
std::map< std::string, VariableMetadata > variables
std::string experiment_id
static double S(unsigned n)