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