ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ERF_NCInterface.H
Go to the documentation of this file.
1 /** \file nc_interface.H
2  *
3  * Interface to NetCDF library
4  *
5  * Defines convenience wrappers to interact with a NetCDF file in a more
6  * OOP-like manner.
7  */
8 
9 #ifndef ERF_NC_INTERFACE_H
10 #define ERF_NC_INTERFACE_H
11 
12 #ifndef USE_NETCDF
13 #include <string>
14 #include <unordered_map>
15 #include <vector>
16 
17 #include <netcdf.h>
18 #include <netcdf_par.h>
19 
20 namespace ncutils {
21 
22 //! Wrapper around NetCDF data types
23 struct NCDType
24 {
25  static constexpr nc_type Int = NC_INT;
26 #ifdef AMREX_USE_FLOAT
27  static constexpr nc_type Real = NC_FLOAT;
28  using RType = float;
29 #else
30  static constexpr nc_type Real = NC_DOUBLE;
31  using RType = double;
32 #endif
33 };
34 
35 //! Representation of NetCDF dimension
36 struct NCDim
37 {
38  //! File/Group Identifier
39  const int ncid;
40 
41  //! Dimension ID used with NetCDF API
42  const int dimid;
43 
44  //! Name of this dimension
45  [[nodiscard]] std::string name() const;
46 
47  //! Length of this dimension
48  [[nodiscard]] size_t len() const;
49 };
50 
51 //! Representation of a NetCDF variable
52 struct NCVar
53 {
54  //! File/Group identifier
55  const int ncid;
56 
57  //! Variable ID used with NetCDF API
58  const int varid;
59 
60  //! Name of this variable
61  [[nodiscard]] std::string name () const;
62 
63  //! Number of array dimensions for this variable
64  [[nodiscard]] int ndim () const;
65 
66  //! Shape of the array (size in each array dimension)
67  [[nodiscard]] std::vector<size_t> shape () const;
68 
69  //! Dimension names of the array (str in each array dimension)
70  [[nodiscard]] std::vector<std::string> dimnames () const;
71 
72  //! Write out the entire variable
73  void put (const double*) const;
74  void put (const float*) const;
75  void put (const int*) const;
76 
77  //! Write out a slice of data
78  void
79  put (const double*,
80  const std::vector<size_t>&,
81  const std::vector<size_t>&) const;
82 
83  //! Write out a slice of data with with strides (see hyperslab definition in
84  //! NetCDF)
85  void
86  put (const double*,
87  const std::vector<size_t>&,
88  const std::vector<size_t>&,
89  const std::vector<ptrdiff_t>&) const;
90  //! Write out a slice of data
91  void
92  put (const float*,
93  const std::vector<size_t>&,
94  const std::vector<size_t>&) const;
95 
96  //! Write out a slice of data with with strides (see hyperslab definition in
97  //! NetCDF)
98  void
99  put (const float*,
100  const std::vector<size_t>&,
101  const std::vector<size_t>&,
102  const std::vector<ptrdiff_t>&) const;
103 
104  void put (const int*, const std::vector<size_t>&, const std::vector<size_t>&) const;
105 
106  void
107  put (const int*,
108  const std::vector<size_t>&,
109  const std::vector<size_t>&,
110  const std::vector<ptrdiff_t>&) const;
111 
112  void put (const char**, const std::vector<size_t>&, const std::vector<size_t>&) const;
113 
114  void
115  put (const char** dptr,
116  const std::vector<size_t>& start,
117  const std::vector<size_t>& count,
118  const std::vector<ptrdiff_t>& stride) const;
119 
120  //! Read the entire variable from file
121  void get (double*) const;
122  void get (float*) const;
123  void get (int*) const;
124 
125  //! Read a chunk of data from the file
126  void
127  get (double*, const std::vector<size_t>&, const std::vector<size_t>&) const;
128 
129  //! Read a chunk of data with strides
130  void
131  get (double*,
132  const std::vector<size_t>&,
133  const std::vector<size_t>&,
134  const std::vector<ptrdiff_t>&) const;
135 
136  //! Read a chunk of data from the file
137  void
138  get (float*, const std::vector<size_t>&, const std::vector<size_t>&) const;
139 
140  //! Read a chunk of data with strides
141  void
142  get (float*,
143  const std::vector<size_t>&,
144  const std::vector<size_t>&,
145  const std::vector<ptrdiff_t>&) const;
146 
147  void
148  get (int*, const std::vector<size_t>&, const std::vector<size_t>&) const;
149 
150  void
151  get (int*,
152  const std::vector<size_t>&,
153  const std::vector<size_t>&,
154  const std::vector<ptrdiff_t>&) const;
155 
156  //! Read a chunk of data from the file
157  void
158  get (char*, const std::vector<size_t>&, const std::vector<size_t>&) const;
159 
160  //! Read a chunk of data with strides
161  void
162  get (char*,
163  const std::vector<size_t>&,
164  const std::vector<size_t>&,
165  const std::vector<ptrdiff_t>&) const;
166 
167  [[nodiscard]] bool has_attr (const std::string& name) const;
168 
169  void put_attr (const std::string& name, const std::string& value) const;
170 
171  void
172  put_attr (const std::string& name, const std::vector<double>& value) const;
173 
174  void
175  put_attr (const std::string& name, const std::vector<float>& value) const;
176 
177  void put_attr (const std::string& name, const std::vector<int>& value) const;
178 
179  [[nodiscard]] std::string get_attr (const std::string& name) const;
180 
181  void get_attr (const std::string& name, std::vector<double>& value) const;
182  void get_attr (const std::string& name, std::vector<float>& value) const;
183  void get_attr (const std::string& name, std::vector<int>& value) const;
184 
185  void par_access (int cmode) const; //Uncomment for parallel NetCDF
186 };
187 
188 //! Representation of a NetCDF group
189 class NCGroup
190 {
191 public:
192  //! Identifier used with NetCDF API calls
193  const int ncid;
194 
195  //! Name of this group
196  [[nodiscard]] std::string name () const;
197 
198  //! Full name for this group
199  [[nodiscard]] std::string full_name () const;
200 
201  //! Number of sub-groups within this group
202  [[nodiscard]] int num_groups () const;
203 
204  //! Number of dimensions in this group
205  [[nodiscard]] int num_dimensions () const;
206 
207  //! Number of variables within this group
208  [[nodiscard]] int num_variables () const;
209 
210  //! Number of attributes within this group
211  [[nodiscard]] int num_attributes () const;
212 
213  //! Check if a group exists
214  [[nodiscard]] bool has_group (const std::string&) const;
215 
216  //! Check if a dimension exists by name
217  [[nodiscard]] bool has_dim (const std::string&) const;
218 
219  /** Return id of variable by name
220  *
221  * Throws error if variable does not exist, use 'has_var' to check
222  */
223  [[nodiscard]] int get_id (const std::string&) const;
224 
225  //! Check if a variable exists by name
226  [[nodiscard]] bool has_var (const std::string&) const;
227 
228  //! Check if an attribute exists
229  [[nodiscard]] bool has_attr (const std::string&) const;
230 
231  /** Get the group by name
232  *
233  * Throws error if the group doesn't exist, use `has_group` to check
234  */
235  [[nodiscard]] NCGroup group (const std::string&) const;
236 
237  //! Get the dimension instance by name
238  [[nodiscard]] NCDim dim (const std::string&) const;
239 
240  //! Get the variable instance by name
241  [[nodiscard]] NCVar var (const std::string&) const;
242 
243  //! Define new dimension
244  void def_dim (const std::string&, size_t len) const;
245 
246  //! Define an array
247  void def_array (const std::string& name,
248  nc_type dtype,
249  const std::vector<std::string>&) const;
250 
251  //! Define a variable (wrapper for def_array)
252  void def_var (const std::string& name,
253  const nc_type dtype,
254  const std::vector<std::string>& dnames) const
255  {
256  def_array(name, dtype, dnames);
257  }
258 
259  void put_attr (const std::string& name, const std::string& value) const;
260  void put_attr (const std::string& name, const std::vector<double>& value) const;
261  void put_attr (const std::string& name, const std::vector<float>& value) const;
262  void put_attr (const std::string& name, const std::vector<int>& value) const;
263 
264  [[nodiscard]] std::string get_attr (const std::string& name) const;
265  void get_attr (const std::string& name, std::vector<double>& value) const;
266  void get_attr (const std::string& name, std::vector<float>& value) const;
267  void get_attr (const std::string& name, std::vector<int>& value) const;
268 
269  //! Return a list of all groups defined in this group
270  [[nodiscard]] std::vector<NCGroup> all_groups () const;
271 
272  //! Return a list of all dimensions defined in this group
273  [[nodiscard]] std::vector<NCDim> all_dims () const;
274 
275  //! Return a list of all variables defined in this group
276  [[nodiscard]] std::vector<NCVar> all_vars () const;
277 
278  //! Enter definition mode (not needed for NetCDF4 format)
279  void enter_def_mode () const;
280 
281  //! Exit definition mode
282  void exit_def_mode () const;
283 
284 protected:
285  NCGroup (const int id) : ncid(id) {}
286  NCGroup (const int id, const NCGroup* /*par*/) : ncid(id) {}
287 };
288 
289 /** Representation of a NetCDF file
290  *
291  * Provide wrappes to create and open file
292  */
293 class NCFile : public NCGroup
294 {
295 public:
296  static NCFile
297  create (const std::string& name, const int cmode = NC_CLOBBER | NC_NETCDF4);
298 
299  static NCFile open (const std::string& name, const int cmode = NC_NOWRITE);
300 
301  static NCFile create_par (const std::string& name,
302  const int cmode = NC_CLOBBER | NC_NETCDF4 | NC_MPIIO,
303  MPI_Comm comm = MPI_COMM_WORLD,
304  MPI_Info info = MPI_INFO_NULL);
305 
306  static NCFile open_par (const std::string& name,
307  const int cmode = NC_NOWRITE,
308  MPI_Comm comm = MPI_COMM_WORLD,
309  MPI_Info info = MPI_INFO_NULL);
310 
311  ~NCFile ();
312 
313  void close ();
314 
315 protected:
316  NCFile (const int id) : NCGroup(id), is_open{true} {}
317 
318  bool is_open{false};
319 };
320 
321 } // namespace ncutils
322 
323 #else
324 
325 namespace ncutils {
326 
327 struct NCDim
328 {
329  const int ncid{-1};
330  const int dimid{-1};
331 };
332 
333 struct NCVar
334 {
335  const int ncid{-1};
336  const int varid{-1};
337 };
338 
339 class NCGroup
340 {
341 public:
342  const int ncid{-1};
343 };
344 
345 class NCFile : public NCGroup
346 {};
347 
348 } // namespace ncutils
349 
350 #endif
351 
352 #endif /* NC_INTERFACE_H */
Definition: ERF_NCInterface.H:294
static NCFile open(const std::string &name, const int cmode=NC_NOWRITE)
Definition: ERF_NCInterface.cpp:707
static NCFile create(const std::string &name, const int cmode=NC_CLOBBER|NC_NETCDF4)
Definition: ERF_NCInterface.cpp:700
~NCFile()
Definition: ERF_NCInterface.cpp:729
static NCFile open_par(const std::string &name, const int cmode=NC_NOWRITE, MPI_Comm comm=MPI_COMM_WORLD, MPI_Info info=MPI_INFO_NULL)
Definition: ERF_NCInterface.cpp:722
static NCFile create_par(const std::string &name, const int cmode=NC_CLOBBER|NC_NETCDF4|NC_MPIIO, MPI_Comm comm=MPI_COMM_WORLD, MPI_Info info=MPI_INFO_NULL)
Definition: ERF_NCInterface.cpp:714
bool is_open
Definition: ERF_NCInterface.H:318
NCFile(const int id)
Definition: ERF_NCInterface.H:316
void close()
Definition: ERF_NCInterface.cpp:734
Representation of a NetCDF group.
Definition: ERF_NCInterface.H:190
bool has_group(const std::string &) const
Check if a group exists.
Definition: ERF_NCInterface.cpp:553
bool has_attr(const std::string &) const
Check if an attribute exists.
Definition: ERF_NCInterface.cpp:582
std::string get_attr(const std::string &name) const
Definition: ERF_NCInterface.cpp:614
void exit_def_mode() const
Exit definition mode.
Definition: ERF_NCInterface.cpp:698
std::string name() const
Name of this group.
Definition: ERF_NCInterface.cpp:464
int num_dimensions() const
Number of dimensions in this group.
Definition: ERF_NCInterface.cpp:532
int num_variables() const
Number of variables within this group.
Definition: ERF_NCInterface.cpp:546
int num_groups() const
Number of sub-groups within this group.
Definition: ERF_NCInterface.cpp:525
std::string full_name() const
Full name for this group.
Definition: ERF_NCInterface.cpp:474
NCGroup(const int id, const NCGroup *)
Definition: ERF_NCInterface.H:286
NCGroup group(const std::string &) const
Definition: ERF_NCInterface.cpp:484
NCVar var(const std::string &) const
Get the variable instance by name.
Definition: ERF_NCInterface.cpp:518
std::vector< NCGroup > all_groups() const
Return a list of all groups defined in this group.
Definition: ERF_NCInterface.cpp:650
const int ncid
Identifier used with NetCDF API calls.
Definition: ERF_NCInterface.H:193
void def_dim(const std::string &, size_t len) const
Define new dimension.
Definition: ERF_NCInterface.cpp:498
std::vector< NCDim > all_dims() const
Return a list of all dimensions defined in this group.
Definition: ERF_NCInterface.cpp:665
NCGroup(const int id)
Definition: ERF_NCInterface.H:285
bool has_var(const std::string &) const
Check if a variable exists by name.
Definition: ERF_NCInterface.cpp:575
bool has_dim(const std::string &) const
Check if a dimension exists by name.
Definition: ERF_NCInterface.cpp:559
int get_id(const std::string &) const
Definition: ERF_NCInterface.cpp:565
void put_attr(const std::string &name, const std::string &value) const
Definition: ERF_NCInterface.cpp:590
void def_array(const std::string &name, nc_type dtype, const std::vector< std::string > &) const
Define an array.
Definition: ERF_NCInterface.cpp:505
NCDim dim(const std::string &) const
Get the dimension instance by name.
Definition: ERF_NCInterface.cpp:491
void def_var(const std::string &name, const nc_type dtype, const std::vector< std::string > &dnames) const
Define a variable (wrapper for def_array)
Definition: ERF_NCInterface.H:252
void enter_def_mode() const
Enter definition mode (not needed for NetCDF4 format)
Definition: ERF_NCInterface.cpp:687
int num_attributes() const
Number of attributes within this group.
Definition: ERF_NCInterface.cpp:539
std::vector< NCVar > all_vars() const
Return a list of all variables defined in this group.
Definition: ERF_NCInterface.cpp:676
Definition: ERF_NCInterface.cpp:9
Wrapper around NetCDF data types.
Definition: ERF_NCInterface.H:24
double RType
Definition: ERF_NCInterface.H:31
static constexpr nc_type Real
Definition: ERF_NCInterface.H:30
static constexpr nc_type Int
Definition: ERF_NCInterface.H:25
Representation of NetCDF dimension.
Definition: ERF_NCInterface.H:37
const int dimid
Dimension ID used with NetCDF API.
Definition: ERF_NCInterface.H:42
const int ncid
File/Group Identifier.
Definition: ERF_NCInterface.H:39
std::string name() const
Name of this dimension.
Definition: ERF_NCInterface.cpp:32
size_t len() const
Length of this dimension.
Definition: ERF_NCInterface.cpp:41
Representation of a NetCDF variable.
Definition: ERF_NCInterface.H:53
bool has_attr(const std::string &name) const
Definition: ERF_NCInterface.cpp:392
const int ncid
File/Group identifier.
Definition: ERF_NCInterface.H:55
const int varid
Variable ID used with NetCDF API.
Definition: ERF_NCInterface.H:58
std::string name() const
Name of this variable.
Definition: ERF_NCInterface.cpp:51
void par_access(int cmode) const
Definition: ERF_NCInterface.cpp:459
std::string get_attr(const std::string &name) const
Definition: ERF_NCInterface.cpp:424
void put(const double *) const
Write out the entire variable.
Definition: ERF_NCInterface.cpp:111
void put_attr(const std::string &name, const std::string &value) const
Definition: ERF_NCInterface.cpp:400
std::vector< std::string > dimnames() const
Dimension names of the array (str in each array dimension)
Definition: ERF_NCInterface.cpp:70
void get(double *) const
Read the entire variable from file.
Definition: ERF_NCInterface.cpp:269
std::vector< size_t > shape() const
Shape of the array (size in each array dimension)
Definition: ERF_NCInterface.cpp:91
int ndim() const
Number of array dimensions for this variable.
Definition: ERF_NCInterface.cpp:60