pism

[fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
git clone git://src.adamsgaard.dk/pism # fast
git clone https://src.adamsgaard.dk/pism.git # slow
Log | Files | Refs | README | LICENSE Back to index

Config.cc (7441B)


      1 /* Copyright (C) 2014, 2015, 2016, 2017, 2019 PISM Authors
      2  *
      3  * This file is part of PISM.
      4  *
      5  * PISM is free software; you can redistribute it and/or modify it under the
      6  * terms of the GNU General Public License as published by the Free Software
      7  * Foundation; either version 3 of the License, or (at your option) any later
      8  * version.
      9  *
     10  * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
     11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
     13  * details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with PISM; if not, write to the Free Software
     17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18  */
     19 
     20 #include "Config.hh"
     21 #include "pism/util/io/File.hh"
     22 #include "pism_options.hh"
     23 #include "error_handling.hh"
     24 #include "io/io_helpers.hh"
     25 #include "pism/util/Logger.hh"
     26 #include "pism/util/pism_utilities.hh"
     27 #include "pism/pism_config.hh"  // pism::config_file
     28 
     29 namespace pism {
     30 
     31 NetCDFConfig::NetCDFConfig(MPI_Comm com, const std::string &name, units::System::Ptr system)
     32   : Config(system),
     33     m_com(com),
     34     m_data(name, system) {
     35 }
     36 
     37 NetCDFConfig::~NetCDFConfig() {
     38 }
     39 
     40 bool NetCDFConfig::is_set_impl(const std::string &name) const {
     41   return m_data.has_attribute(name);
     42 }
     43 
     44 // doubles
     45 
     46 double NetCDFConfig::get_number_impl(const std::string &name) const {
     47   const VariableMetadata::DoubleAttrs& doubles = m_data.get_all_doubles();
     48   if (doubles.find(name) != doubles.end()) {
     49     return m_data.get_number(name);
     50   } else {
     51     throw RuntimeError::formatted(PISM_ERROR_LOCATION,
     52                                   "parameter '%s' is unset. (Parameters read from '%s'.)",
     53                                   name.c_str(), m_config_filename.c_str());
     54   }
     55 
     56   return 0;                     // can't happen
     57 }
     58 
     59 std::vector<double> NetCDFConfig::get_numbers_impl(const std::string &name) const {
     60   const VariableMetadata::DoubleAttrs& doubles = m_data.get_all_doubles();
     61   if (doubles.find(name) != doubles.end()) {
     62     return m_data.get_numbers(name);
     63   } else {
     64     throw RuntimeError::formatted(PISM_ERROR_LOCATION,
     65                                   "parameter '%s' is unset. (Parameters read from '%s'.)",
     66                                   name.c_str(), m_config_filename.c_str());
     67   }
     68 
     69   return {};                    // can't happen
     70 }
     71 
     72 Config::Doubles NetCDFConfig::all_doubles_impl() const {
     73   Doubles result;
     74 
     75   for (auto d : m_data.get_all_doubles()) {
     76     result[d.first] = d.second;
     77   }
     78   return result;
     79 }
     80 
     81 
     82 void NetCDFConfig::set_number_impl(const std::string &name, double value) {
     83   m_data.set_number(name, value);
     84 }
     85 
     86 void NetCDFConfig::set_numbers_impl(const std::string &name,
     87                                     const std::vector<double> &values) {
     88   m_data.set_numbers(name, values);
     89 }
     90 
     91 // strings
     92 
     93 std::string NetCDFConfig::get_string_impl(const std::string &name) const {
     94   const VariableMetadata::StringAttrs& strings = m_data.get_all_strings();
     95   if (strings.find(name) != strings.end()) {
     96     return m_data.get_string(name);
     97   } else {
     98     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Parameter '%s' was not set. (Read from '%s'.)\n",
     99                                   name.c_str(), m_config_filename.c_str());
    100   }
    101 
    102   return std::string();         // will never happen
    103 }
    104 
    105 Config::Strings NetCDFConfig::all_strings_impl() const {
    106   VariableMetadata::StringAttrs strings = m_data.get_all_strings();
    107   Strings result;
    108 
    109   for (auto s : strings) {
    110     std::string name = s.first;
    111     std::string value = s.second;
    112 
    113     auto k = strings.find(name + "_type");
    114     if (k != strings.end() and k->second == "flag") {
    115       // Flags are stored as strings. Skip them.
    116       continue;
    117     }
    118 
    119     result[name] = value;
    120   }
    121   return result;
    122 }
    123 
    124 void NetCDFConfig::set_string_impl(const std::string &name, const std::string &value) {
    125   m_data.set_string(name, value);
    126 }
    127 
    128 // flags
    129 
    130 static bool string_is_false(const std::string &value) {
    131   return value == "false" or value == "off" or value == "no";
    132 }
    133 
    134 static bool string_is_true(const std::string &value) {
    135   return value == "true" or value == "on" or value == "yes";
    136 }
    137 
    138 bool NetCDFConfig::get_flag_impl(const std::string &name) const {
    139   const VariableMetadata::StringAttrs& strings = m_data.get_all_strings();
    140   auto j = strings.find(name);
    141   if (j != strings.end()) {
    142 
    143     const std::string &value = j->second;
    144 
    145     if (string_is_false(value)) {
    146       return false;
    147     }
    148 
    149     if (string_is_true(value)) {
    150       return true;
    151     }
    152 
    153     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Parameter '%s' (%s) cannot be interpreted as a flag.\n"
    154                                   "Please make sure that it is set to one of 'true', 'yes', 'on', 'false', 'no', 'off'.",
    155                                   name.c_str(), value.c_str());
    156   }
    157 
    158   throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Parameter '%s' was not set. (Read from '%s'.)",
    159                                 name.c_str(), m_config_filename.c_str());
    160 
    161   return true;                  // will never happen
    162 }
    163 
    164 Config::Flags NetCDFConfig::all_flags_impl() const {
    165   Flags result;
    166 
    167   for (auto b : m_data.get_all_strings()) {
    168     std::string name = b.first;
    169     std::string value = b.second;
    170 
    171     if (string_is_true(value)) {
    172       result[name] = true;
    173     } else if (string_is_false(value)) {
    174       result[name] = false;
    175     }
    176   }
    177   return result;
    178 }
    179 
    180 //! Set a value of a flag flag.
    181 void NetCDFConfig::set_flag_impl(const std::string &name, bool value) {
    182   if (value) {
    183     m_data.set_string(name, "true");
    184   } else {
    185     m_data.set_string(name, "false");
    186   }
    187 }
    188 
    189 // file I/O
    190 
    191 //! Read flag flags and double parameters from a NetCDF file.
    192 /*!
    193   Erases all the present parameters before reading.
    194 */
    195 void NetCDFConfig::read_impl(const File &nc) {
    196 
    197   io::read_attributes(nc, m_data.get_name(), m_data);
    198 
    199   m_config_filename = nc.filename();
    200 }
    201 
    202 //! Write a config variable to a file (with all its attributes).
    203 void NetCDFConfig::write_impl(const File &nc) const {
    204 
    205   bool variable_exists = nc.find_variable(m_data.get_name());
    206 
    207   if (not variable_exists) {
    208     nc.define_variable(m_data.get_name(),
    209                PISM_BYTE, std::vector<std::string>());
    210 
    211     io::write_attributes(nc, m_data, PISM_DOUBLE);
    212   } else {
    213     io::write_attributes(nc, m_data, PISM_DOUBLE);
    214   }
    215 }
    216 
    217 
    218 //! Config that respects command-line options and stores data in a NetCDF variable.
    219 DefaultConfig::DefaultConfig(MPI_Comm com,
    220                              const std::string &variable_name,
    221                              const std::string &option,
    222                              units::System::Ptr system)
    223   : NetCDFConfig(com, variable_name, system),
    224     m_option(option) {
    225   // empty
    226 }
    227 
    228 DefaultConfig::~DefaultConfig() {
    229   // empty
    230 }
    231 
    232 void DefaultConfig::init(const Logger &log, bool use_default_path) {
    233   options::String file(m_option,
    234                        "Name of the file to read " + m_data.get_name() + " from",
    235                        pism::config_file);
    236   if (use_default_path or file.is_set()) {
    237     this->read(m_com, file);
    238     log.message(2, "Reading configuration parameters (%s) from file '%s'.\n",
    239                 m_data.get_name().c_str(), file->c_str());
    240   }
    241 }
    242 
    243 void DefaultConfig::init_with_default(const Logger &log) {
    244   this->init(log, true);
    245 }
    246 
    247 void DefaultConfig::init(const Logger &log) {
    248   this->init(log, false);
    249 }
    250 
    251 } // end of namespace pism