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