PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
VariableMetadata.hh
Go to the documentation of this file.
1 // Copyright (C) 2009--2018, 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 #ifndef __VariableMetadata_hh
20 #define __VariableMetadata_hh
21 
22 #include <set>
23 #include <map>
24 #include <vector>
25 #include <string>
26 
27 #include "pism/util/Units.hh"
28 
29 namespace pism {
30 namespace io {
31 enum Type : int;
32 }
33 
34 class Logger;
35 
36 //! @brief A class for handling variable metadata, reading, writing and converting
37 //! from input units and to output units.
38 /*! A NetCDF variable can have any number of attributes, but some of them get
39  special treatment:
40 
41  - units: specifies internal units. When read, a variable is
42  converted to these units. When written, it is converted from these
43  to output_units.
44 
45  - output_units: is never written to a file; replaces 'units'
46  in the output file.
47 
48  - valid_min, valid_max: specify the valid range of a variable. Are
49  read from an input file *only* if not specified previously. If
50  both are set, then valid_range is used in the output instead.
51 
52  Also:
53 
54  - empty string attributes are ignored (they are not written to the
55  output file and has_attribute("foo") returns false if "foo" is
56  absent or equal to an empty string).
57 
58  Typical attributes stored here:
59 
60  - long_name
61  - standard_name
62  - pism_intent
63  - units
64  - output_units (saved to files as "units")
65 
66  Use the `name` of "PISM_GLOBAL" to read and write global attributes.
67  (See also File.)
68 
69 */
70 
71 class VariableMetadata;
72 
74 public:
75  friend class VariableMetadata;
76  ConstAttribute(const ConstAttribute&) = delete;
78 
79  operator std::string() const;
80  operator double() const;
81  operator std::vector<double> () const;
82 protected:
83  ConstAttribute(const VariableMetadata *var, const std::string &name);
84  ConstAttribute(ConstAttribute&& a) noexcept;
85 
86  std::string m_name;
88 };
89 
90 class Attribute : public ConstAttribute {
91 public:
92  friend class VariableMetadata;
93  void operator=(const std::string &value);
94  void operator=(const std::initializer_list<double> &value);
95  void operator=(const std::vector<double> &value);
96 private:
98 };
99 
101 public:
102  VariableMetadata(const std::string &name, units::System::Ptr system, unsigned int ndims = 0);
103  virtual ~VariableMetadata() = default;
104 
105  Attribute operator[](const std::string &name) {
106  return Attribute(this, name);
107  }
108 
109  ConstAttribute operator[](const std::string &name) const {
110  return ConstAttribute(this, name);
111  }
112 
113  // setters for common attributes
114 
115  VariableMetadata &long_name(const std::string &input) {
116  return set_string("long_name", input);
117  }
118 
119  VariableMetadata &standard_name(const std::string &input) {
120  return set_string("standard_name", input);
121  }
122 
123  VariableMetadata &units(const std::string &input) {
124  return set_string("units", input);
125  }
126 
127  VariableMetadata &output_units(const std::string &input) {
128  return set_string("output_units", input);
129  }
130 
131  // getters and setters
132  double get_number(const std::string &name) const;
133  VariableMetadata &set_number(const std::string &name, double value);
134 
135  std::vector<double> get_numbers(const std::string &name) const;
136  VariableMetadata &set_numbers(const std::string &name, const std::vector<double> &values);
137 
138  std::string get_name() const;
139  VariableMetadata &set_name(const std::string &name);
140 
141  std::string get_string(const std::string &name) const;
142  VariableMetadata &set_string(const std::string &name, const std::string &value);
143  VariableMetadata &set_units_without_validation(const std::string &value);
144 
145  bool get_time_independent() const;
147 
148  io::Type get_output_type() const;
150 
151  //! Clear all attributes
153 
154  // more getters
156 
157  unsigned int n_spatial_dimensions() const;
158 
159  bool has_attribute(const std::string &name) const;
160  bool has_attributes() const;
161 
162  const std::map<std::string, std::string> &all_strings() const;
163  const std::map<std::string, std::vector<double> > &all_doubles() const;
164 
165  void report_to_stdout(const Logger &log, int verbosity_threshold) const;
166  void check_range(const std::string &filename, double min, double max) const;
167  void report_range(const Logger &log, double min, double max, bool found_by_standard_name);
168 
169 protected:
170  unsigned int m_n_spatial_dims;
171 
172 private:
173  //! @brief The unit system to use.
175 
176  //! string and boolean attributes
177  std::map<std::string, std::string> m_strings;
178 
179  //! scalar and array attributes
180  std::map<std::string, std::vector<double> > m_doubles;
181  std::string m_short_name;
183 
185 };
186 
187 //! Spatial NetCDF variable (corresponding to a 2D or 3D scalar field).
189 public:
190  SpatialVariableMetadata(units::System::Ptr system, const std::string &name,
191  const std::vector<double> &zlevels = {0.0});
192  virtual ~SpatialVariableMetadata() = default;
193 
194  const std::vector<double>& levels() const;
195 
196  VariableMetadata& x();
197  VariableMetadata& y();
198  VariableMetadata& z();
199 
200  const VariableMetadata& x() const;
201  const VariableMetadata& y() const;
202  const VariableMetadata& z() const;
203 
204 private:
206  std::vector<double> m_zlevels;
207 };
208 
209 } // end of namespace pism
210 
211 #endif // __VariableMetadata_hh
void operator=(const std::string &value)
ConstAttribute & operator=(const ConstAttribute &)=delete
ConstAttribute(const ConstAttribute &)=delete
VariableMetadata * m_var
A basic logging class.
Definition: Logger.hh:40
std::vector< double > m_zlevels
const std::vector< double > & levels() const
SpatialVariableMetadata(units::System::Ptr system, const std::string &name, const std::vector< double > &zlevels={0.0})
virtual ~SpatialVariableMetadata()=default
Spatial NetCDF variable (corresponding to a 2D or 3D scalar field).
VariableMetadata & clear()
Clear all attributes.
Attribute operator[](const std::string &name)
VariableMetadata & standard_name(const std::string &input)
void report_to_stdout(const Logger &log, int verbosity_threshold) const
ConstAttribute operator[](const std::string &name) const
VariableMetadata & set_name(const std::string &name)
unsigned int n_spatial_dimensions() const
VariableMetadata & set_number(const std::string &name, double value)
Set a scalar attribute to a single (scalar) value.
VariableMetadata & long_name(const std::string &input)
VariableMetadata(const std::string &name, units::System::Ptr system, unsigned int ndims=0)
VariableMetadata & output_units(const std::string &input)
units::System::Ptr m_unit_system
The unit system to use.
double get_number(const std::string &name) const
Get a single-valued scalar attribute.
std::string get_string(const std::string &name) const
Get a string attribute.
virtual ~VariableMetadata()=default
const std::map< std::string, std::string > & all_strings() const
std::map< std::string, std::string > m_strings
string and boolean attributes
void report_range(const Logger &log, double min, double max, bool found_by_standard_name)
Report the range of a global Vec v.
units::System::Ptr unit_system() const
io::Type get_output_type() const
std::map< std::string, std::vector< double > > m_doubles
scalar and array attributes
bool get_time_independent() const
VariableMetadata & set_units_without_validation(const std::string &value)
std::vector< double > get_numbers(const std::string &name) const
Get an array-of-doubles attribute.
VariableMetadata & set_output_type(io::Type type)
bool has_attribute(const std::string &name) const
VariableMetadata & units(const std::string &input)
VariableMetadata & set_numbers(const std::string &name, const std::vector< double > &values)
Set a scalar attribute to a single (scalar) value.
std::string get_name() const
VariableMetadata & set_string(const std::string &name, const std::string &value)
Set a string attribute.
void check_range(const std::string &filename, double min, double max) const
Check if the range [min, max] is a subset of [valid_min, valid_max].
const std::map< std::string, std::vector< double > > & all_doubles() const
VariableMetadata & set_time_independent(bool flag)
std::shared_ptr< System > Ptr
Definition: Units.hh:47
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:165
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:193