REMORA
Energy Research and Forecasting: An Atmospheric Modeling Code
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 NC_INTREMORAACE_H
10 #define NC_INTREMORAACE_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  std::string name() const;
46 
47  //! Length of this dimension
48  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  std::string name() const;
62 
63  //! Number of array dimensions for this variable
64  int ndim() const;
65 
66  //! Shape of the array (size in each array dimension)
67  std::vector<size_t> shape() const;
68 
69  //! Write out the entire variable
70  void put(const double*) const;
71  void put(const float*) const;
72  void put(const int*) const;
73 
74  //! Write out a slice of data
75  void
76  put(const double*,
77  const std::vector<size_t>&,
78  const std::vector<size_t>&) const;
79 
80  //! Write out a slice of data with with strides (see hyperslab definition in
81  //! NetCDF)
82  void
83  put(const double*,
84  const std::vector<size_t>&,
85  const std::vector<size_t>&,
86  const std::vector<ptrdiff_t>&) const;
87  //! Write out a slice of data
88  void
89  put(const float*,
90  const std::vector<size_t>&,
91  const std::vector<size_t>&) const;
92 
93  //! Write out a slice of data with with strides (see hyperslab definition in
94  //! NetCDF)
95  void
96  put(const float*,
97  const std::vector<size_t>&,
98  const std::vector<size_t>&,
99  const std::vector<ptrdiff_t>&) const;
100 
101  void put(const int*, const std::vector<size_t>&, const std::vector<size_t>&) const;
102  void
103  put(const int*,
104  const std::vector<size_t>&,
105  const std::vector<size_t>&,
106  const std::vector<ptrdiff_t>&) const;
107 
108  void put(const char**, const std::vector<size_t>&, const std::vector<size_t>&) const;
109  void
110  put(
111  const char** dptr,
112  const std::vector<size_t>& start,
113  const std::vector<size_t>& count,
114  const std::vector<ptrdiff_t>& stride) const;
115 
116  //! Read the entire variable from file
117  void get(double*) const;
118  void get(float*) const;
119  void get(int*) const;
120 
121  //! Read a chunk of data from the file
122  void
123  get(double*, const std::vector<size_t>&, const std::vector<size_t>&) const;
124 
125  //! Read a chunk of data with strides
126  void
127  get(double*,
128  const std::vector<size_t>&,
129  const std::vector<size_t>&,
130  const std::vector<ptrdiff_t>&) const;
131 
132  //! Read a chunk of data from the file
133  void
134  get(float*, const std::vector<size_t>&, const std::vector<size_t>&) const;
135 
136  //! Read a chunk of data with strides
137  void
138  get(float*,
139  const std::vector<size_t>&,
140  const std::vector<size_t>&,
141  const std::vector<ptrdiff_t>&) const;
142 
143  void
144  get(int*, const std::vector<size_t>&, const std::vector<size_t>&) const;
145  void
146  get(int*,
147  const std::vector<size_t>&,
148  const std::vector<size_t>&,
149  const std::vector<ptrdiff_t>&) const;
150 
151  //! Read a chunk of data from the file
152  void
153  get(char*, const std::vector<size_t>&, const std::vector<size_t>&) const;
154 
155  //! Read a chunk of data with strides
156  void
157  get(char*,
158  const std::vector<size_t>&,
159  const std::vector<size_t>&,
160  const std::vector<ptrdiff_t>&) const;
161 
162  bool has_attr(const std::string& name) const;
163  void put_attr(const std::string& name, const std::string& value) const;
164  void
165  put_attr(const std::string& name, const std::vector<double>& value) const;
166  void
167  put_attr(const std::string& name, const std::vector<float>& value) const;
168  void put_attr(const std::string& name, const std::vector<int>& value) const;
169 
170  std::string get_attr(const std::string& name) const;
171  void get_attr(const std::string& name, std::vector<double>& value) const;
172  void get_attr(const std::string& name, std::vector<float>& value) const;
173  void get_attr(const std::string& name, std::vector<int>& value) const;
174  void par_access(const int cmode) const; //Uncomment for parallel NetCDF
175 };
176 
177 //! Representation of a NetCDF group
178 class NCGroup
179 {
180 public:
181  //! Identifier used with NetCDF API calls
182  const int ncid;
183 
184  //! Name of this group
185  std::string name() const;
186 
187  //! Full name for this group
188  std::string full_name() const;
189 
190  //! Number of sub-groups within this group
191  int num_groups() const;
192 
193  //! Number of dimensions in this group
194  int num_dimensions() const;
195 
196  //! Number of variables within this group
197  int num_variables() const;
198 
199  //! Number of attributes within this group
200  int num_attributes() const;
201 
202  //! Check if a group exists
203  bool has_group(const std::string&) const;
204 
205  //! Check if a dimension exists by name
206  bool has_dim(const std::string&) const;
207 
208  //! Check if a variable exists by name
209  bool has_var(const std::string&) const;
210 
211  //! Check if an attribute exists
212  bool has_attr(const std::string&) const;
213 
214  /** Get the group by name
215  *
216  * Throws error if the group doesn't exist, use `has_group` to check
217  */
218  NCGroup group(const std::string&) const;
219 
220  //! Get the dimension instance by name
221  NCDim dim(const std::string&) const;
222 
223  //! Get the variable instance by name
224  NCVar var(const std::string&) const;
225 
226  //! Define new group
227  NCGroup def_group(const std::string&) const;
228 
229  //! Define new dimension
230  NCDim def_dim(const std::string&, const size_t len) const;
231 
232  //! Define a scalar variable, i.e., 0-dimensional array
233  NCVar def_scalar(const std::string& name, const nc_type dtype) const;
234 
235  //! Define an array
237  const std::string& name,
238  const nc_type dtype,
239  const std::vector<std::string>&) const;
240 
241  //! Define a variable (wrapper for def_array)
243  const std::string& name,
244  const nc_type dtype,
245  const std::vector<std::string>& dnames) const
246  {
247  return def_array(name, dtype, dnames);
248  }
249 
250  void put_attr(const std::string& name, const std::string& value) const;
251  void put_attr(const std::string& name, const std::vector<double>& value) const;
252  void put_attr(const std::string& name, const std::vector<float>& value) const;
253  void put_attr(const std::string& name, const std::vector<int>& value) const;
254 
255  std::string get_attr(const std::string& name) const;
256  void get_attr(const std::string& name, std::vector<double>& value) const;
257  void get_attr(const std::string& name, std::vector<float>& value) const;
258  void get_attr(const std::string& name, std::vector<int>& value) const;
259 
260  //! Return a list of all groups defined in this group
261  std::vector<NCGroup> all_groups() const;
262 
263  //! Return a list of all dimensions defined in this group
264  std::vector<NCDim> all_dims() const;
265 
266  //! Return a list of all variables defined in this group
267  std::vector<NCVar> all_vars() const;
268 
269  //! Enter definition mode (not needed for NetCDF4 format)
270  void enter_def_mode() const;
271 
272  //! Exit definition mode
273  void exit_def_mode() const;
274 
275 protected:
276  NCGroup(const int id) : ncid(id) {}
277  NCGroup(const int id, const NCGroup* /*par*/) : ncid(id) {}
278 };
279 
280 /** Representation of a NetCDF file
281  *
282  * Provide wrappes to create and open file
283  */
284 class NCFile : public NCGroup
285 {
286 public:
287  static NCFile
288  create(const std::string& name, const int cmode = NC_CLOBBER | NC_NETCDF4);
289 
290  static NCFile open(const std::string& name, const int cmode = NC_NOWRITE);
291 
292  static NCFile create_par(
293  const std::string& name,
294  const int cmode = NC_CLOBBER | NC_NETCDF4 | NC_MPIIO,
295  MPI_Comm comm = MPI_COMM_WORLD,
296  MPI_Info info = MPI_INFO_NULL);
297 
298  static NCFile open_par(
299  const std::string& name,
300  const int cmode = NC_NOWRITE,
301  MPI_Comm comm = MPI_COMM_WORLD,
302  MPI_Info info = MPI_INFO_NULL);
303 
304  ~NCFile();
305 
306  void close();
307 
308 protected:
309  NCFile(const int id) : NCGroup(id), is_open{true} {}
310 
311  bool is_open{false};
312 };
313 
314 } // namespace ncutils
315 
316 #else
317 
318 namespace ncutils {
319 
320 struct NCDim
321 {
322  const int ncid{-1};
323  const int dimid{-1};
324 };
325 
326 struct NCVar
327 {
328  const int ncid{-1};
329  const int varid{-1};
330 };
331 
332 class NCGroup
333 {
334 public:
335  const int ncid{-1};
336 };
337 
338 class NCFile : public NCGroup
339 {};
340 
341 } // namespace ncutils
342 
343 #endif
344 
345 #endif /* NC_INTREMORAACE_H */
Definition: NCInterface.H:285
static NCFile open(const std::string &name, const int cmode=NC_NOWRITE)
Definition: NCInterface.cpp:577
static NCFile create(const std::string &name, const int cmode=NC_CLOBBER|NC_NETCDF4)
Definition: NCInterface.cpp:570
~NCFile()
Definition: NCInterface.cpp:601
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: NCInterface.cpp:593
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: NCInterface.cpp:584
bool is_open
Definition: NCInterface.H:311
NCFile(const int id)
Definition: NCInterface.H:309
void close()
Definition: NCInterface.cpp:606
Representation of a NetCDF group.
Definition: NCInterface.H:179
bool has_group(const std::string &) const
Check if a group exists.
Definition: NCInterface.cpp:429
bool has_attr(const std::string &) const
Check if an attribute exists.
Definition: NCInterface.cpp:447
std::string get_attr(const std::string &name) const
Definition: NCInterface.cpp:482
void exit_def_mode() const
Exit definition mode.
Definition: NCInterface.cpp:568
std::string name() const
Name of this group.
Definition: NCInterface.cpp:322
NCVar def_scalar(const std::string &name, const nc_type dtype) const
Define a scalar variable, i.e., 0-dimensional array.
Definition: NCInterface.cpp:370
int num_dimensions() const
Number of dimensions in this group.
Definition: NCInterface.cpp:408
int num_variables() const
Number of variables within this group.
Definition: NCInterface.cpp:422
int num_groups() const
Number of sub-groups within this group.
Definition: NCInterface.cpp:401
std::string full_name() const
Full name for this group.
Definition: NCInterface.cpp:332
NCGroup(const int id, const NCGroup *)
Definition: NCInterface.H:277
NCGroup group(const std::string &) const
Definition: NCInterface.cpp:349
NCVar var(const std::string &) const
Get the variable instance by name.
Definition: NCInterface.cpp:394
std::vector< NCGroup > all_groups() const
Return a list of all groups defined in this group.
Definition: NCInterface.cpp:520
const int ncid
Identifier used with NetCDF API calls.
Definition: NCInterface.H:182
std::vector< NCDim > all_dims() const
Return a list of all dimensions defined in this group.
Definition: NCInterface.cpp:535
NCGroup(const int id)
Definition: NCInterface.H:276
NCVar 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: NCInterface.H:242
bool has_var(const std::string &) const
Check if a variable exists by name.
Definition: NCInterface.cpp:441
bool has_dim(const std::string &) const
Check if a dimension exists by name.
Definition: NCInterface.cpp:435
NCGroup def_group(const std::string &) const
Define new group.
Definition: NCInterface.cpp:342
NCVar def_array(const std::string &name, const nc_type dtype, const std::vector< std::string > &) const
Define an array.
Definition: NCInterface.cpp:377
void put_attr(const std::string &name, const std::string &value) const
Definition: NCInterface.cpp:455
NCDim dim(const std::string &) const
Get the dimension instance by name.
Definition: NCInterface.cpp:356
NCDim def_dim(const std::string &, const size_t len) const
Define new dimension.
Definition: NCInterface.cpp:363
void enter_def_mode() const
Enter definition mode (not needed for NetCDF4 format)
Definition: NCInterface.cpp:557
int num_attributes() const
Number of attributes within this group.
Definition: NCInterface.cpp:415
std::vector< NCVar > all_vars() const
Return a list of all variables defined in this group.
Definition: NCInterface.cpp:546
Definition: NCInterface.cpp:9
Wrapper around NetCDF data types.
Definition: NCInterface.H:24
double RType
Definition: NCInterface.H:31
static constexpr nc_type Real
Definition: NCInterface.H:30
static constexpr nc_type Int
Definition: NCInterface.H:25
Representation of NetCDF dimension.
Definition: NCInterface.H:37
const int dimid
Dimension ID used with NetCDF API.
Definition: NCInterface.H:42
const int ncid
File/Group Identifier.
Definition: NCInterface.H:39
std::string name() const
Name of this dimension.
Definition: NCInterface.cpp:24
size_t len() const
Length of this dimension.
Definition: NCInterface.cpp:30
Representation of a NetCDF variable.
Definition: NCInterface.H:53
bool has_attr(const std::string &name) const
Definition: NCInterface.cpp:247
const int ncid
File/Group identifier.
Definition: NCInterface.H:55
const int varid
Variable ID used with NetCDF API.
Definition: NCInterface.H:58
std::string name() const
Name of this variable.
Definition: NCInterface.cpp:37
std::string get_attr(const std::string &name) const
Definition: NCInterface.cpp:282
void put(const double *) const
Write out the entire variable.
Definition: NCInterface.cpp:65
void par_access(const int cmode) const
Definition: NCInterface.cpp:317
void put_attr(const std::string &name, const std::string &value) const
Definition: NCInterface.cpp:255
void get(double *) const
Read the entire variable from file.
Definition: NCInterface.cpp:156
std::vector< size_t > shape() const
Shape of the array (size in each array dimension)
Definition: NCInterface.cpp:50
int ndim() const
Number of array dimensions for this variable.
Definition: NCInterface.cpp:43