25#include "pism/util/io/File.hh"
26#include "pism/util/ConfigInterface.hh"
27#include "pism/util/Units.hh"
28#include "pism/util/pism_utilities.hh"
29#include "pism/util/pism_options.hh"
30#include "pism/util/error_handling.hh"
31#include "pism/util/io/IO_Flags.hh"
35#include "pism/util/Config.hh"
36#include "pism/util/Logger.hh"
59 : m_impl(new
Impl(system)) {
83void Config::write(MPI_Comm com,
const std::string &filename,
bool append)
const {
83void Config::write(MPI_Comm com,
const std::string &filename,
bool append)
const {
…}
98 auto parameters = this->
keys();
101 if (
member(p.first, parameters)) {
105 "unrecognized parameter %s in %s",
106 p.first.c_str(), other.
filename().c_str());
111 if (
member(p.first, parameters)) {
115 "unrecognized parameter %s in %s",
116 p.first.c_str(), other.
filename().c_str());
120 for (
const auto &p : other.
all_flags()) {
121 if (
member(p.first, parameters)) {
125 "unrecognized parameter %s in %s",
126 p.first.c_str(), other.
filename().c_str());
133 auto parameter = s.first;
134 auto value = s.second;
140 auto last_token =
pism::split(parameter,
'.').back();
142 if (last_token ==
"file") {
143 char *resolved_path = realpath(value.c_str(), NULL);
145 if (resolved_path != NULL) {
174 if (std::get<0>(min)) {
183 if (std::get<0>(max)) {
205 if (
type(name) ==
"integer" and std::round(value) != value) {
208 "integer parameter '%s' was set to a number with a non-zero fractional part (%f)",
209 name.c_str(), value);
213 if (std::get<0>(min)) {
217 if (
type(name) ==
"integer") {
219 "Please set '%s' to a number greater than or equal to %d",
223 "Please set '%s' to a number greater than or equal to %f",
229 if (std::get<0>(max)) {
233 if (
type(name) ==
"integer") {
235 "Please set '%s' to a number less than or equal to %d",
239 "Please set '%s' to a number less than or equal to %f",
249 const std::string &units,
252 std::string input_units = this->units(name);
257 e.
add_context(
"converting \"%s\" from \"%s\" to \"%s\"",
258 name.c_str(), input_units.c_str(), units.c_str());
271 const std::string &units,
274 auto input_units = this->units(name);
278 for (
unsigned int k = 0;
k < value.size(); ++
k) {
279 value[
k] = converter(value[
k]);
283 e.
add_context(
"converting \"%s\" from \"%s\" to \"%s\"",
284 name.c_str(), input_units.c_str(), units.c_str());
294 set_by_user.insert(name);
299 set_by_user.find(name) != set_by_user.end()) {
307 const std::vector<double> &values,
312 set_by_user.insert(name);
317 set_by_user.find(name) != set_by_user.end()) {
336 const std::string &value,
341 set_by_user.insert(name);
346 set_by_user.find(name) != set_by_user.end()) {
369 set_by_user.insert(name);
374 set_by_user.find(name) != set_by_user.end()) {
382 for (
const auto &suffix : {
"_doc",
"_units",
"_type",
"_option",
"_choices",
"_valid_min",
"_valid_max"}) {
390 return (name ==
"long_name");
394 const int v = verbosity_threshhold;
403 size_t max_name_size = 0;
404 for (
const auto &s : strings) {
408 max_name_size = std::max(max_name_size, s.first.size());
412 for (
const auto &s : strings) {
413 std::string name = s.first;
414 std::string value = s.second;
420 std::string padding(max_name_size - name.size(),
' ');
422 if (config.
type(name) ==
"keyword") {
423 log.
message(v,
" %s%s = \"%s\" (allowed choices: %s)\n",
424 name.c_str(), padding.c_str(), value.c_str(),
427 log.
message(v,
" %s%s = \"%s\"\n", name.c_str(), padding.c_str(), value.c_str());
438 max_name_size = std::max(max_name_size, d.first.size());
442 std::string name = d.first;
443 double value = d.second[0];
449 std::string units = config.
units(name);
450 std::string padding(max_name_size - name.size(),
' ');
452 const double large = 1.0e7;
453 const double small = 1.0e-4;
454 if (fabs(value) >= large or fabs(value) <= small) {
456 log.
message(v,
" %s%s = %13.3e (%s)\n", name.c_str(), padding.c_str(), value, units.c_str());
458 log.
message(v,
" %s%s = %13.5f (%s)\n", name.c_str(), padding.c_str(), value, units.c_str());
468 for (
const auto &b : config.
all_flags()) {
469 max_name_size = std::max(max_name_size, b.first.size());
473 for (
const auto &b : config.
all_flags()) {
474 std::string name = b.first;
475 std::string value = b.second ?
"true" :
"false";
476 std::string padding(max_name_size - name.size(),
' ');
478 log.
message(v,
" %s%s = %s\n", name.c_str(), padding.c_str(), value.c_str());
482 "### List of configuration parameters ends here.\n"
491 if (
options::Bool(
"-options_left",
"report unused options")) {
495 for (
const auto &p : parameters_set) {
501 if (parameters_used.find(p) == parameters_used.end()) {
502 log.
message(verbosity_threshhold,
503 "PISM WARNING: flag or parameter \"%s\" was set but was not used!\n",
535 const std::string ¶meter_name) {
539 std::string doc = config.
doc(parameter_name);
545 if (
member(opt.
value(), {
"",
"on",
"yes",
"true",
"True" })) {
549 }
else if (
member(opt.
value(), {
"off",
"no",
"false",
"False" })) {
555 opt.
value().c_str());
566 "Inconsistent command-line options:"
567 " both -%s and -no_%s are set.\n",
568 option.c_str(), option.c_str());
589 const std::string ¶meter) {
598 const std::string ¶meter) {
622 const std::string &choices) {
633 const std::string &name) {
642 std::string option = name;
644 if (not config.
option(name).empty()) {
645 std::string short_option = config.
option(name);
646 std::string description = config.
doc(name);
652 "both -%s and -%s are set (please use one or the other)",
653 option.c_str(), short_option.c_str());
657 option = short_option;
661 std::string type = config.
type(name);
663 if (type ==
"string") {
665 }
else if (type ==
"flag") {
667 }
else if (type ==
"number") {
669 }
else if (type ==
"integer") {
671 }
else if (type ==
"keyword") {
688 for (
const auto &b : config.
all_flags()) {
696 bool pik =
options::Bool(
"-pik",
"enable suite of PISM-PIK mechanisms");
704 if (config.
get_string(
"calving.methods").find(
"eigen_calving") != std::string::npos) {
707 config.
set_number(
"grid.max_stencil_width", 3);
711 if (not config.
get_string(
"calving.methods").empty()) {
716 if (config.
get_flag(
"geometry.remove_icebergs")) {
721 if (config.
get_string(
"hydrology.model") ==
"routing") {
722 if (config.
get_flag(
"frontal_melt.include_floating_ice")) {
723 config.
set_flag(
"hydrology.routing.include_floating_ice",
true);
727 if (config.
get_flag(
"output.ISMIP6")) {
729 config.
set_flag(
"output.use_MKS",
true);
734 options::String T(
"-ice_surface_temp",
"ice surface temperature parameterization");
739 if (IST.size() != 4) {
741 " (comma-separated list of 4 numbers)");
744 config.
set_number(
"surface.elevation_dependent.T_min", IST[0]);
745 config.
set_number(
"surface.elevation_dependent.T_max", IST[1]);
746 config.
set_number(
"surface.elevation_dependent.z_T_min", IST[2]);
747 config.
set_number(
"surface.elevation_dependent.z_T_max", IST[3]);
750 options::String M(
"-climatic_mass_balance",
"climatic mass balance parameterization");
755 if (CMB.size() != 5) {
757 " (comma-separated list of 5 numbers)");
760 config.
set_number(
"surface.elevation_dependent.M_min", CMB[0]);
761 config.
set_number(
"surface.elevation_dependent.M_max", CMB[1]);
762 config.
set_number(
"surface.elevation_dependent.z_M_min", CMB[2]);
763 config.
set_number(
"surface.elevation_dependent.z_ELA", CMB[3]);
764 config.
set_number(
"surface.elevation_dependent.z_M_max", CMB[4]);
768 "lower and upper limits of the climatic mass balance");
776 " (a comma-separated list of 2 numbers)");
781 config.
set_number(
"surface.elevation_dependent.M_limit_min", meter_per_second(
L[0]));
782 config.
set_number(
"surface.elevation_dependent.M_limit_max", meter_per_second(
L[1]));
791 auto config = std::make_shared<T>(com,
"pism_config",
"-config", unit_system);
792 auto overrides = std::make_shared<T>(com,
"pism_overrides",
"-config_override", unit_system);
794 overrides->init(log);
796 config->init_with_default(log);
798 config->import_from(*overrides);
802 config->resolve_filenames();
808 : m_prefix(prefix), m_config(c) {
833 std::set<std::string> result;
836 result.insert(p.first);
840 result.insert(p.first);
844 result.insert(p.first);
863 if (this->
is_set(parameter +
"_option")) {
875 if (
is_set(parameter +
"_valid_min")) {
878 return {
false, {} };
882 if (
is_set(parameter +
"_valid_max")) {
885 return {
false, {} };
void reset_prefix(const std::string &prefix)
bool get_flag(const std::string &name) const
std::string get_string(const std::string &name) const
double get_number(const std::string &name) const
Config::ConstPtr m_config
ConfigWithPrefix(Config::ConstPtr c, const std::string &prefix)
virtual bool is_set_impl(const std::string &name) const =0
std::map< std::string, std::string > Strings
const std::set< std::string > & parameters_used() const
std::shared_ptr< Config > Ptr
bool is_set(const std::string &name) const
std::string choices(const std::string ¶meter) const
virtual Strings all_strings_impl() const =0
std::set< std::string > keys() const
std::pair< bool, double > valid_max(const std::string ¶meter) const
std::map< std::string, std::vector< double > > Doubles
void set_string(const std::string &name, const std::string &value, ConfigSettingFlag flag=CONFIG_FORCE)
double get_number(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
virtual void set_numbers_impl(const std::string &name, const std::vector< double > &values)=0
std::vector< double > get_numbers(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
virtual void read_impl(const File &nc)=0
std::shared_ptr< const Config > ConstPtr
virtual Flags all_flags_impl() const =0
virtual std::vector< double > get_numbers_impl(const std::string &name) const =0
const std::set< std::string > & parameters_set_by_user() const
virtual void set_flag_impl(const std::string &name, bool value)=0
void read(MPI_Comm com, const std::string &filename)
bool is_valid_number(const std::string &name) const
virtual void set_string_impl(const std::string &name, const std::string &value)=0
std::string units(const std::string ¶meter) const
void import_from(const Config &other)
Config(units::System::Ptr unit_system)
void set_flag(const std::string &name, bool value, ConfigSettingFlag flag=CONFIG_FORCE)
virtual std::string get_string_impl(const std::string &name) const =0
std::map< std::string, bool > Flags
std::string get_string(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
std::string type(const std::string ¶meter) const
virtual Doubles all_doubles_impl() const =0
virtual void set_number_impl(const std::string &name, double value)=0
void write(MPI_Comm com, const std::string &filename, bool append=true) const
bool get_flag(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
void set_number(const std::string &name, double value, ConfigSettingFlag flag=CONFIG_FORCE)
std::string option(const std::string ¶meter) const
std::string filename() const
Returns the name of the file used to initialize the database.
Strings all_strings() const
virtual void write_impl(const File &nc) const =0
void set_numbers(const std::string &name, const std::vector< double > &values, ConfigSettingFlag flag=CONFIG_FORCE)
Doubles all_doubles() const
std::string doc(const std::string ¶meter) const
UseFlag
Flag used by get_...() methods.
std::pair< bool, double > valid_min(const std::string ¶meter) const
virtual double get_number_impl(const std::string &name) const =0
virtual bool get_flag_impl(const std::string &name) const =0
A class for storing and accessing PISM configuration flags and parameters.
Default PISM configuration database: uses NetCDF files; can be initialized from a file specified usin...
High-level PISM I/O class.
void message(int threshold, const char format[],...) const __attribute__((format(printf
Print a message to the log.
int get_threshold() const
Get verbosity threshold.
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
std::shared_ptr< System > Ptr
#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
bool Bool(const std::string &option, const std::string &description)
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
void set_integer_from_option(Config &config, const std::string &option, const std::string ¶meter)
bool ends_with(const std::string &str, const std::string &suffix)
Returns true if str ends with suffix and false otherwise.
std::vector< double > parse_number_list(const std::string &input)
Config::Ptr config_from_options(MPI_Comm com, const Logger &log, units::System::Ptr unit_system)
Create a configuration database using command-line options.
void set_number_from_option(units::System::Ptr unit_system, Config &config, const std::string &option, const std::string ¶meter)
Sets a configuration parameter from a command-line option.
void set_string_from_option(Config &config, const std::string &option, const std::string ¶meter)
Set one free-form string parameter using command-line options.
bool member(const std::string &string, const std::set< std::string > &set)
void set_config_from_options(units::System::Ptr unit_system, Config &config)
Set configuration parameters using command-line options.
static bool special_parameter(const std::string &name)
void set_flag_from_option(Config &config, const std::string &option, const std::string ¶meter_name)
Get a flag from a command-line option.
ConfigSettingFlag
Flag used by set_...() methods.
void print_unused_parameters(const Logger &log, int verbosity_threshhold, const Config &config)
Report unused configuration parameters to stdout.
void set_keyword_from_option(Config &config, const std::string &option, const std::string ¶meter, const std::string &choices)
Set a keyword parameter from a command-line option.
void set_parameter_from_options(units::System::Ptr unit_system, Config &config, const std::string &name)
Set one parameter using command-line options.
void print_config(const Logger &log, int verbosity_threshhold, const Config &config)
Report configuration parameters to stdout.
std::vector< std::string > split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a vector of strings.
units::System::Ptr unit_system
std::set< std::string > parameters_used
Set of parameters used in a run. Used to warn about parameters that were set but were not used.
Impl(units::System::Ptr sys)
std::set< std::string > parameters_set_by_user
Set of parameters set by the user. Used to warn about parameters that were set but were not used.