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