tVars.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
       ---
       tVars.cc (11540B)
       ---
            1 // Copyright (C) 2009--2011, 2013, 2014, 2015, 2016, 2017 Constantine Khroulev
            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 #include <memory>
           20 using std::dynamic_pointer_cast;
           21 
           22 #include "Vars.hh"
           23 #include "VariableMetadata.hh"
           24 #include "iceModelVec.hh"
           25 #include "IceModelVec2CellType.hh"
           26 #include "error_handling.hh"
           27 
           28 namespace pism {
           29 
           30 Vars::Vars() {
           31 }
           32 
           33 bool Vars::is_available(const std::string &name) const {
           34   // check if "name" is a standard name
           35   if (m_standard_names.find(name) != m_standard_names.end()) {
           36     return true;
           37   }
           38   // check if "name" is a short name of a read-only variable
           39   if (m_variables.find(name) != m_variables.end()) {
           40     return true;
           41   }
           42   // check if "name" is a short name of a "shared" variable
           43   if (m_variables_shared.find(name) != m_variables_shared.end()) {
           44     return true;
           45   }
           46   return false;
           47 }
           48 
           49 //! \brief Add an IceModelVec v using the name `name`.
           50 void Vars::add(const IceModelVec &v, const std::string &name) {
           51 
           52   if (m_variables.find(name) != m_variables.end()) {
           53     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Vars::add(): an IceModelVec with the name '%s'"
           54                                   " was added already.",
           55                                   name.c_str());
           56   }
           57   m_variables[name] = &v;
           58 }
           59 
           60 //!Add an IceModelVec to the dictionary.
           61 /*!
           62   Adds standard_name if present, otherwise uses short_name.
           63 
           64   This code will only work for IceModelVecs with dof == 1.
           65 */
           66 void Vars::add(const IceModelVec &v) {
           67 
           68   const SpatialVariableMetadata &m = v.metadata();
           69   std::string name = v.get_name();
           70 
           71   if (m.has_attribute("standard_name")) {
           72 
           73     std::string standard_name = m.get_string("standard_name");
           74     if (m_standard_names[standard_name].empty()) {
           75       m_standard_names[standard_name] = name;
           76     } else {
           77       throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Vars::add(): an IceModelVec with the standard_name '%s'"
           78                                     " was added already.",
           79                                     standard_name.c_str());
           80     }
           81   }
           82 
           83   if (m_variables[name] == NULL) {
           84     m_variables[name] = &v;
           85   } else {
           86     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Vars::add(): an IceModelVec with the name '%s'"
           87                                   " was added already.",
           88                                   name.c_str());
           89   }
           90 }
           91 
           92 //! Removes a variable with the key `name` from the dictionary.
           93 void Vars::remove(const std::string &name) {
           94 
           95   const IceModelVec *v = m_variables[name];
           96   const SpatialVariableMetadata &m = v->metadata();
           97 
           98   if (v != NULL) {              // the argument is a "short" name
           99     m_variables.erase(name);
          100     if (m.has_attribute("standard_name")) {
          101       std::string std_name = m.get_string("standard_name");
          102 
          103       m_standard_names.erase(std_name);
          104     }
          105   } else {
          106     std::string &short_name = m_standard_names[name];
          107     v = m_variables[short_name];
          108 
          109     if (v != NULL) {            // the argument is a standard_name
          110       m_variables.erase(short_name);
          111       m_standard_names.erase(name);
          112     }
          113   }
          114 }
          115 
          116 //! \brief Returns a pointer to an IceModelVec containing variable `name` or
          117 //! NULL if that variable was not found.
          118 /*!
          119  * Checks standard_name first, then short name
          120  */
          121 const IceModelVec* Vars::get(const std::string &name) const {
          122   const IceModelVec *tmp = get_internal(name);
          123   if (tmp == NULL) {
          124     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "variable '%s' is not available", name.c_str());
          125   }
          126   return tmp;
          127 }
          128 
          129 const IceModelVec* Vars::get_internal(const std::string &name) const {
          130 
          131   auto j = m_standard_names.find(name);
          132   if (j != m_standard_names.end()) {
          133     std::string short_name = j->second;
          134 
          135     auto k = m_variables.find(short_name);
          136     if (k != m_variables.end()) {
          137       return k->second;
          138     }
          139   }
          140 
          141   auto k = m_variables.find(name);
          142   if (k != m_variables.end()) {
          143     return (k->second);
          144   }
          145 
          146   IceModelVec::Ptr shared = get_internal_shared(name);
          147   if ((bool)shared) {
          148     return shared.get();
          149   }
          150 
          151   return NULL;
          152 }
          153 
          154 const IceModelVec2S* Vars::get_2d_scalar(const std::string &name) const {
          155   const IceModelVec2S *tmp = dynamic_cast<const IceModelVec2S*>(this->get_internal(name));
          156   if (tmp == NULL) {
          157     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "2D scalar variable '%s' is not available", name.c_str());
          158   }
          159   return tmp;
          160 }
          161 
          162 const IceModelVec2V* Vars::get_2d_vector(const std::string &name) const {
          163   const IceModelVec2V *tmp = dynamic_cast<const IceModelVec2V*>(this->get_internal(name));
          164   if (tmp == NULL) {
          165     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "2D vector variable '%s' is not available", name.c_str());
          166   }
          167   return tmp;
          168 }
          169 
          170 const IceModelVec2Int* Vars::get_2d_mask(const std::string &name) const {
          171   const IceModelVec2Int *tmp = dynamic_cast<const IceModelVec2Int*>(this->get_internal(name));
          172   if (tmp == NULL) {
          173     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "2D mask variable '%s' is not available", name.c_str());
          174   }
          175   return tmp;
          176 }
          177 
          178 const IceModelVec2CellType* Vars::get_2d_cell_type(const std::string &name) const {
          179   const IceModelVec2CellType *tmp = dynamic_cast<const IceModelVec2CellType*>(this->get_internal(name));
          180   if (tmp == NULL) {
          181     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "2D cell type variable '%s' is not available", name.c_str());
          182   }
          183   return tmp;
          184 }
          185 
          186 const IceModelVec3* Vars::get_3d_scalar(const std::string &name) const {
          187   const IceModelVec3* tmp = dynamic_cast<const IceModelVec3*>(this->get_internal(name));
          188   if (tmp == NULL) {
          189     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "3D scalar variable '%s' is not available", name.c_str());
          190   }
          191   return tmp;
          192 }
          193 
          194 //! \brief Returns the set of keys (variable names) in the dictionary.
          195 /*!
          196  * Provides one (short) name per variable.
          197  *
          198  * This means that one can safely iterate over these keys, reading, writing,
          199  * displaying or de-allocating variables (without worrying that a variable will
          200  * get written or de-allocated twice).
          201  */
          202 std::set<std::string> Vars::keys() const {
          203 
          204   std::set<std::string> result;
          205 
          206   for (auto v : m_variables) {
          207     result.insert(v.first);
          208   }
          209 
          210   for (auto v : m_variables_shared) {
          211     result.insert(v.first);
          212   }
          213 
          214   return result;
          215 }
          216 
          217 void Vars::add_shared(VecPtr variable) {
          218 
          219   const SpatialVariableMetadata &m = variable->metadata();
          220   std::string name = variable->get_name();
          221 
          222   if (m.has_attribute("standard_name")) {
          223 
          224     std::string standard_name = m.get_string("standard_name");
          225     if (m_standard_names[standard_name].empty()) {
          226       m_standard_names[standard_name] = name;
          227     } else {
          228       throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Vars::add_shared(): an IceModelVec with the standard_name '%s'"
          229                                     " was added already.",
          230                                     standard_name.c_str());
          231     }
          232   }
          233 
          234   if (m_variables_shared.find(name) == m_variables_shared.end()) {
          235     m_variables_shared[name] = variable;
          236   } else {
          237     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Vars::add_shared(): an IceModelVec with the name '%s'"
          238                                   " was added already.",
          239                                   name.c_str());
          240   }
          241 }
          242 
          243 
          244 void Vars::add_shared(VecPtr variable, const std::string &name) {
          245 
          246   if (m_variables_shared.find(name) != m_variables_shared.end()) {
          247     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Vars::add_shared(): an IceModelVec with the name '%s'"
          248                                   " was added already.",
          249                                   name.c_str());
          250   }
          251   m_variables_shared[name] = variable;
          252 }
          253 
          254 
          255 bool Vars::is_available_shared(const std::string &name) const {
          256 
          257   // check the standard name
          258   if (m_standard_names.find(name) != m_standard_names.end()) {
          259     std::string short_name = m_standard_names[name];
          260     // return true if the corresponding short name is one of a
          261     // "shared" variable
          262     if (m_variables_shared.find(short_name) != m_variables_shared.end()) {
          263       return true;
          264     }
          265     return false;
          266   }
          267 
          268   // check if "name" is a short name of a "shared" variable
          269   if (m_variables_shared.find(name) != m_variables_shared.end()) {
          270     return true;
          271   }
          272   return false;
          273 }
          274 
          275 
          276 IceModelVec::Ptr Vars::get_shared(const std::string &name) const {
          277   IceModelVec::Ptr tmp = get_internal_shared(name);
          278   if (not (bool)tmp) {
          279     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "shared variable '%s' is not available", name.c_str());
          280   }
          281   return tmp;
          282 }
          283 
          284 
          285 IceModelVec2S::Ptr Vars::get_2d_scalar_shared(const std::string &name) const {
          286   IceModelVec2S::Ptr tmp = dynamic_pointer_cast<IceModelVec2S,IceModelVec>(this->get_internal_shared(name));
          287   if (not (bool)tmp) {
          288     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "shared 2D scalar variable '%s' is not available", name.c_str());
          289   }
          290   return tmp;
          291 }
          292 
          293 
          294 IceModelVec2V::Ptr Vars::get_2d_vector_shared(const std::string &name) const {
          295   IceModelVec2V::Ptr tmp = dynamic_pointer_cast<IceModelVec2V,IceModelVec>(this->get_internal_shared(name));
          296   if (not (bool)tmp) {
          297     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "shared 2D vector variable '%s' is not available", name.c_str());
          298   }
          299   return tmp;
          300 }
          301 
          302 
          303 IceModelVec2Int::Ptr Vars::get_2d_mask_shared(const std::string &name) const {
          304   IceModelVec2Int::Ptr tmp = dynamic_pointer_cast<IceModelVec2Int,IceModelVec>(this->get_internal_shared(name));
          305   if (not (bool)tmp) {
          306     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "shared 2D mask variable '%s' is not available", name.c_str());
          307   }
          308   return tmp;
          309 }
          310 
          311 IceModelVec2CellType::Ptr Vars::get_2d_cell_type_shared(const std::string &name) const {
          312   IceModelVec2CellType::Ptr tmp = dynamic_pointer_cast<IceModelVec2CellType,IceModelVec>(this->get_internal_shared(name));
          313   if (not (bool)tmp) {
          314     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "shared 2D mask variable '%s' is not available", name.c_str());
          315   }
          316   return tmp;
          317 }
          318 
          319 
          320 IceModelVec3::Ptr Vars::get_3d_scalar_shared(const std::string &name) const {
          321   IceModelVec3::Ptr tmp = dynamic_pointer_cast<IceModelVec3,IceModelVec>(this->get_internal_shared(name));
          322   if (not (bool)tmp) {
          323     throw RuntimeError::formatted(PISM_ERROR_LOCATION, "shared 3D scalar variable '%s' is not available", name.c_str());
          324   }
          325   return tmp;
          326 }
          327 
          328 
          329 std::set<std::string> Vars::keys_shared() const {
          330 
          331   std::set<std::string> result;
          332   for (auto v : m_variables_shared) {
          333     result.insert(v.first);
          334   }
          335 
          336   return result;
          337 }
          338 
          339 IceModelVec::Ptr Vars::get_internal_shared(const std::string &name) const {
          340 
          341   auto j = m_standard_names.find(name);
          342   if (j != m_standard_names.end()) {
          343     std::string short_name = j->second;
          344 
          345     auto k = m_variables_shared.find(short_name);
          346     if (k != m_variables_shared.end()) {
          347       return k->second;
          348     } else {
          349       return IceModelVec::Ptr();
          350     }
          351   }
          352 
          353   auto k = m_variables_shared.find(name);
          354   if (k != m_variables_shared.end()) {
          355     return (k->second);
          356   }
          357 
          358   return IceModelVec::Ptr();
          359 }
          360 
          361 } // end of namespace pism