tConfig.cc - pism - [fork] customized build of PISM, the parallel ice sheet model (tillflux branch)
 (HTM) git clone git://src.adamsgaard.dk/pism
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
       tConfig.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