26 #include "pism/util/io/File.hh"
27 #include "pism/util/ConfigInterface.hh"
28 #include "pism/util/Units.hh"
29 #include "pism/util/pism_utilities.hh"
30 #include "pism/util/pism_options.hh"
31 #include "pism/util/error_handling.hh"
32 #include "pism/util/io/IO_Flags.hh"
36 #include "pism/util/Config.hh"
37 #include "pism/util/Logger.hh"
60 : m_impl(new
Impl(system)) {
84 void Config::write(MPI_Comm com,
const std::string &filename,
bool append)
const {
99 auto parameters = this->
keys();
102 if (
member(p.first, parameters)) {
106 "unrecognized parameter %s in %s",
107 p.first.c_str(), other.
filename().c_str());
112 if (
member(p.first, parameters)) {
116 "unrecognized parameter %s in %s",
117 p.first.c_str(), other.
filename().c_str());
121 for (
const auto &p : other.
all_flags()) {
122 if (
member(p.first, parameters)) {
126 "unrecognized parameter %s in %s",
127 p.first.c_str(), other.
filename().c_str());
134 auto parameter = s.first;
135 auto value = s.second;
141 auto last_token =
pism::split(parameter,
'.').back();
143 if (last_token ==
"file") {
144 char resolved_path[PATH_MAX];
146 if (realpath(value.c_str(), resolved_path) != NULL) {
178 const std::string &units,
181 std::string input_units = this->
units(name);
186 e.
add_context(
"converting \"%s\" from \"%s\" to \"%s\"",
187 name.c_str(), input_units.c_str(),
units.c_str());
200 const std::string &units,
203 auto input_units = this->
units(name);
207 for (
unsigned int k = 0;
k < value.size(); ++
k) {
208 value[
k] = converter(value[
k]);
212 e.
add_context(
"converting \"%s\" from \"%s\" to \"%s\"",
213 name.c_str(), input_units.c_str(),
units.c_str());
223 set_by_user.insert(name);
228 set_by_user.find(name) != set_by_user.end()) {
236 const std::vector<double> &values,
241 set_by_user.insert(name);
246 set_by_user.find(name) != set_by_user.end()) {
265 const std::string &value,
270 set_by_user.insert(name);
275 set_by_user.find(name) != set_by_user.end()) {
298 set_by_user.insert(name);
303 set_by_user.find(name) != set_by_user.end()) {
311 for (
const auto &suffix : {
"_doc",
"_units",
"_type",
"_option",
"_choices"}) {
319 return (name ==
"long_name");
323 const int v = verbosity_threshhold;
332 size_t max_name_size = 0;
333 for (
const auto &s : strings) {
337 max_name_size =
std::max(max_name_size, s.first.size());
341 for (
const auto &s : strings) {
342 std::string name = s.first;
343 std::string value = s.second;
349 std::string padding(max_name_size - name.size(),
' ');
351 if (config.
type(name) ==
"keyword") {
352 log.
message(v,
" %s%s = \"%s\" (allowed choices: %s)\n",
353 name.c_str(), padding.c_str(), value.c_str(),
356 log.
message(v,
" %s%s = \"%s\"\n", name.c_str(), padding.c_str(), value.c_str());
367 max_name_size =
std::max(max_name_size, d.first.size());
371 std::string name = d.first;
372 double value = d.second[0];
374 std::string units = config.
units(name);
375 std::string padding(max_name_size - name.size(),
' ');
377 const double large = 1.0e7;
378 const double small = 1.0e-4;
379 if (fabs(value) >= large or fabs(value) <= small) {
381 log.
message(v,
" %s%s = %13.3e (%s)\n", name.c_str(), padding.c_str(), value, units.c_str());
383 log.
message(v,
" %s%s = %13.5f (%s)\n", name.c_str(), padding.c_str(), value, units.c_str());
393 for (
const auto &b : config.
all_flags()) {
394 max_name_size =
std::max(max_name_size, b.first.size());
398 for (
const auto &b : config.
all_flags()) {
399 std::string name = b.first;
400 std::string value = b.second ?
"true" :
"false";
401 std::string padding(max_name_size - name.size(),
' ');
403 log.
message(v,
" %s%s = %s\n", name.c_str(), padding.c_str(), value.c_str());
407 "### List of configuration parameters ends here.\n"
416 if (
options::Bool(
"-options_left",
"report unused options")) {
420 for (
const auto &p : parameters_set) {
426 if (parameters_used.find(p) == parameters_used.end()) {
427 log.
message(verbosity_threshhold,
428 "PISM WARNING: flag or parameter \"%s\" was set but was not used!\n",
460 const std::string ¶meter_name) {
464 std::string doc = config.
doc(parameter_name);
470 if (
member(opt.
value(), {
"",
"on",
"yes",
"true",
"True" })) {
474 }
else if (
member(opt.
value(), {
"off",
"no",
"false",
"False" })) {
480 opt.
value().c_str());
491 "Inconsistent command-line options:"
492 " both -%s and -no_%s are set.\n",
493 option.c_str(), option.c_str());
514 const std::string ¶meter) {
530 const std::string ¶meter) {
535 if (default_value.size() < 2 and list->size() != default_value.size()) {
537 "Option -%s requires a list of %d numbers (got %d instead).",
538 option.c_str(), (
int)default_value.size(), (
int)list->size());
553 const std::string ¶meter) {
554 std::vector<int> default_value;
557 default_value.push_back(v);
562 std::vector<double> value;
563 for (
auto v : list.
value()) {
568 if (default_value.size() < 2 and value.size() != default_value.size()) {
570 "Option -%s requires a list of %d integers (got %d instead).",
571 option.c_str(), (
int)default_value.size(), (
int)value.size());
579 const std::string ¶meter) {
603 const std::string &choices) {
614 const std::string &name) {
623 std::string option = name;
625 if (not config.
option(name).empty()) {
626 std::string short_option = config.
option(name);
627 std::string description = config.
doc(name);
633 "both -%s and -%s are set (please use one or the other)",
634 option.c_str(), short_option.c_str());
638 option = short_option;
642 std::string type = config.
type(name);
644 if (type ==
"string") {
646 }
else if (type ==
"flag") {
648 }
else if (type ==
"number") {
650 }
else if (type ==
"integer") {
652 }
else if (type ==
"keyword") {
669 for (
const auto &b : config.
all_flags()) {
676 "choose the energy model (one of 'none', 'cold', 'enthalpy')",
677 "none,cold,enthalpy",
"enthalpy");
680 if (energy ==
"none") {
684 }
else if (energy ==
"cold") {
687 }
else if (energy ==
"enthalpy") {
692 "this can't happen: options::Keyword validates input");
699 std::vector<double> defaults = {
700 config.
get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.phi_min"),
701 config.
get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.phi_max"),
702 config.
get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.topg_min"),
703 config.
get_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.topg_max")
706 options::RealList topg_to_phi(
"-topg_to_phi",
"phi_min, phi_max, topg_min, topg_max", defaults);
707 if (topg_to_phi.
is_set()) {
708 if (topg_to_phi->size() != 4) {
710 "option -topg_to_phi expected 4 numbers; got %d",
711 (
int)topg_to_phi->size());
713 config.
set_flag(
"basal_yield_stress.mohr_coulomb.topg_to_phi.enabled",
true);
714 config.
set_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.phi_min", topg_to_phi[0]);
715 config.
set_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.phi_max", topg_to_phi[1]);
716 config.
set_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.topg_min", topg_to_phi[2]);
717 config.
set_number(
"basal_yield_stress.mohr_coulomb.topg_to_phi.topg_max", topg_to_phi[3]);
722 bool nu_bedrock =
options::Bool(
"-nu_bedrock",
"constant viscosity near margins");
731 bool pik =
options::Bool(
"-pik",
"enable suite of PISM-PIK mechanisms");
739 if (config.
get_string(
"calving.methods").find(
"eigen_calving") != std::string::npos) {
742 config.
set_number(
"grid.max_stencil_width", 3);
746 if (not config.
get_string(
"calving.methods").empty()) {
751 if (config.
get_flag(
"geometry.remove_icebergs")) {
755 bool test_climate_models =
756 options::Bool(
"-test_climate_models",
"Disable ice dynamics to test climate models");
757 if (test_climate_models) {
765 if (config.
get_string(
"hydrology.model") ==
"routing") {
766 if (config.
get_flag(
"frontal_melt.include_floating_ice")) {
767 config.
set_flag(
"hydrology.routing.include_floating_ice",
true);
771 if (config.
get_flag(
"output.ISMIP6")) {
773 config.
set_flag(
"output.use_MKS",
true);
781 overrides(
new DefaultConfig(com,
"pism_overrides",
"-config_override", unit_system));
782 overrides->init(log);
783 config->init_with_default(log);
784 config->import_from(*overrides);
786 config->resolve_filenames();
792 : m_prefix(prefix), m_config(c) {
817 std::set<std::string> result;
820 result.insert(p.first);
824 result.insert(p.first);
828 result.insert(p.first);
847 if (this->
is_set(parameter +
"_option")) {
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::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
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)
virtual void set_string_impl(const std::string &name, const std::string &value)=0
std::string units(const std::string ¶meter) const
virtual std::vector< double > get_numbers_impl(const std::string &name) const =0
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.
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.
std::shared_ptr< DefaultConfig > Ptr
Default PISM configuration database: uses NetCDF files; can be initialized from a file specified usin...
std::string filename() const
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
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
@ 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_list_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.
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 &name, const std::string ¶meter)
Sets a configuration parameter from a command-line option.
void set_string_from_option(Config &config, const std::string &name, 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_integer_from_option(Config &config, const std::string &name, const std::string ¶meter)
void set_flag_from_option(Config &config, const std::string &option, const std::string ¶meter_name)
Get a flag from a command-line option.
void set_number_list_from_option(Config &config, const std::string &option, const std::string ¶meter)
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_parameter_from_options(units::System::Ptr unit_system, Config &config, const std::string &name)
Set one parameter using command-line options.
void set_keyword_from_option(Config &config, const std::string &name, const std::string ¶meter, const std::string &choices)
Set a keyword parameter from a command-line option.
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.