ERF
Energy Research and Forecasting: An Atmospheric Modeling Code
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  //! 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 
103  void
104  put (const int*,
105  const std::vector<size_t>&,
106  const std::vector<size_t>&,
107  const std::vector<ptrdiff_t>&) const;
108 
109  void put (const char**, const std::vector<size_t>&, const std::vector<size_t>&) const;
110 
111  void
112  put (const char** dptr,
113  const std::vector<size_t>& start,
114  const std::vector<size_t>& count,
115  const std::vector<ptrdiff_t>& stride) const;
116 
117  //! Read the entire variable from file
118  void get (double*) const;
119  void get (float*) const;
120  void get (int*) const;
121 
122  //! Read a chunk of data from the file
123  void
124  get (double*, const std::vector<size_t>&, const std::vector<size_t>&) const;
125 
126  //! Read a chunk of data with strides
127  void
128  get (double*,
129  const std::vector<size_t>&,
130  const std::vector<size_t>&,
131  const std::vector<ptrdiff_t>&) const;
132 
133  //! Read a chunk of data from the file
134  void
135  get (float*, const std::vector<size_t>&, const std::vector<size_t>&) const;
136 
137  //! Read a chunk of data with strides
138  void
139  get (float*,
140  const std::vector<size_t>&,
141  const std::vector<size_t>&,
142  const std::vector<ptrdiff_t>&) const;
143 
144  void
145  get (int*, const std::vector<size_t>&, const std::vector<size_t>&) const;
146 
147  void
148  get (int*,
149  const std::vector<size_t>&,
150  const std::vector<size_t>&,
151  const std::vector<ptrdiff_t>&) const;
152 
153  //! Read a chunk of data from the file
154  void
155  get (char*, const std::vector<size_t>&, const std::vector<size_t>&) const;
156 
157  //! Read a chunk of data with strides
158  void
159  get (char*,
160  const std::vector<size_t>&,
161  const std::vector<size_t>&,
162  const std::vector<ptrdiff_t>&) const;
163 
164  [[nodiscard]] bool has_attr (const std::string& name) const;
165 
166  void put_attr (const std::string& name, const std::string& value) const;
167 
168  void
169  put_attr (const std::string& name, const std::vector<double>& value) const;
170 
171  void
172  put_attr (const std::string& name, const std::vector<float>& value) const;
173 
174  void put_attr (const std::string& name, const std::vector<int>& value) const;
175 
176  [[nodiscard]] std::string get_attr (const std::string& name) const;
177 
178  void get_attr (const std::string& name, std::vector<double>& value) const;
179  void get_attr (const std::string& name, std::vector<float>& value) const;
180  void get_attr (const std::string& name, std::vector<int>& value) const;
181 
182  void par_access (int cmode) const; //Uncomment for parallel NetCDF
183 };
184 
185 //! Representation of a NetCDF group
186 class NCGroup
187 {
188 public:
189  //! Identifier used with NetCDF API calls
190  const int ncid;
191 
192  //! Name of this group
193  [[nodiscard]] std::string name () const;
194 
195  //! Full name for this group
196  [[nodiscard]] std::string full_name () const;
197 
198  //! Number of sub-groups within this group
199  [[nodiscard]] int num_groups () const;
200 
201  //! Number of dimensions in this group
202  [[nodiscard]] int num_dimensions () const;
203 
204  //! Number of variables within this group
205  [[nodiscard]] int num_variables () const;
206 
207  //! Number of attributes within this group
208  [[nodiscard]] int num_attributes () const;
209 
210  //! Check if a group exists
211  [[nodiscard]] bool has_group (const std::string&) const;
212 
213  //! Check if a dimension exists by name
214  [[nodiscard]] bool has_dim (const std::string&) const;
215 
216  //! Check if a variable exists by name
217  [[nodiscard]] bool has_var (const std::string&) const;
218 
219  //! Check if an attribute exists
220  [[nodiscard]] bool has_attr (const std::string&) const;
221 
222  /** Get the group by name
223  *
224  * Throws error if the group doesn't exist, use `has_group` to check
225  */
226  [[nodiscard]] NCGroup group (const std::string&) const;
227 
228  //! Get the dimension instance by name
229  [[nodiscard]] NCDim dim (const std::string&) const;
230 
231  //! Get the variable instance by name
232  [[nodiscard]] NCVar var (const std::string&) const;
233 
234  //! Define new dimension
235  void def_dim (const std::string&, size_t len) const;
236 
237  //! Define an array
238  void def_array (const std::string& name,
239  nc_type dtype,
240  const std::vector<std::string>&) const;
241 
242  //! Define a variable (wrapper for def_array)
243  void def_var (const std::string& name,
244  const nc_type dtype,
245  const std::vector<std::string>& dnames) const
246  {
247  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  [[nodiscard]] 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  [[nodiscard]] std::vector<NCGroup> all_groups () const;
262 
263  //! Return a list of all dimensions defined in this group
264  [[nodiscard]] std::vector<NCDim> all_dims () const;
265 
266  //! Return a list of all variables defined in this group
267  [[nodiscard]] 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 (const std::string& name,
293  const int cmode = NC_CLOBBER | NC_NETCDF4 | NC_MPIIO,
294  MPI_Comm comm = MPI_COMM_WORLD,
295  MPI_Info info = MPI_INFO_NULL);
296 
297  static NCFile open_par (const std::string& name,
298  const int cmode = NC_NOWRITE,
299  MPI_Comm comm = MPI_COMM_WORLD,
300  MPI_Info info = MPI_INFO_NULL);
301 
302  ~NCFile ();
303 
304  void close ();
305 
306 protected:
307  NCFile (const int id) : NCGroup(id), is_open{true} {}
308 
309  bool is_open{false};
310 };
311 
312 } // namespace ncutils
313 
314 #else
315 
316 namespace ncutils {
317 
318 struct NCDim
319 {
320  const int ncid{-1};
321  const int dimid{-1};
322 };
323 
324 struct NCVar
325 {
326  const int ncid{-1};
327  const int varid{-1};
328 };
329 
330 class NCGroup
331 {
332 public:
333  const int ncid{-1};
334 };
335 
336 class NCFile : public NCGroup
337 {};
338 
339 } // namespace ncutils
340 
341 #endif
342 
343 #endif /* NC_INTERFACE_H */
Definition: ERF_NCInterface.H:285
static NCFile open(const std::string &name, const int cmode=NC_NOWRITE)
Definition: ERF_NCInterface.cpp:674
static NCFile create(const std::string &name, const int cmode=NC_CLOBBER|NC_NETCDF4)
Definition: ERF_NCInterface.cpp:667
~NCFile()
Definition: ERF_NCInterface.cpp:696
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:689
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:681
bool is_open
Definition: ERF_NCInterface.H:309
NCFile(const int id)
Definition: ERF_NCInterface.H:307
void close()
Definition: ERF_NCInterface.cpp:701
Representation of a NetCDF group.
Definition: ERF_NCInterface.H:187
bool has_group(const std::string &) const
Check if a group exists.
Definition: ERF_NCInterface.cpp:531
bool has_attr(const std::string &) const
Check if an attribute exists.
Definition: ERF_NCInterface.cpp:549
std::string get_attr(const std::string &name) const
Definition: ERF_NCInterface.cpp:581
void exit_def_mode() const
Exit definition mode.
Definition: ERF_NCInterface.cpp:665
std::string name() const
Name of this group.
Definition: ERF_NCInterface.cpp:442
int num_dimensions() const
Number of dimensions in this group.
Definition: ERF_NCInterface.cpp:510
int num_variables() const
Number of variables within this group.
Definition: ERF_NCInterface.cpp:524
int num_groups() const
Number of sub-groups within this group.
Definition: ERF_NCInterface.cpp:503
std::string full_name() const
Full name for this group.
Definition: ERF_NCInterface.cpp:452
NCGroup(const int id, const NCGroup *)
Definition: ERF_NCInterface.H:277
NCGroup group(const std::string &) const
Definition: ERF_NCInterface.cpp:462
NCVar var(const std::string &) const
Get the variable instance by name.
Definition: ERF_NCInterface.cpp:496
std::vector< NCGroup > all_groups() const
Return a list of all groups defined in this group.
Definition: ERF_NCInterface.cpp:617
const int ncid
Identifier used with NetCDF API calls.
Definition: ERF_NCInterface.H:190
void def_dim(const std::string &, size_t len) const
Define new dimension.
Definition: ERF_NCInterface.cpp:476
std::vector< NCDim > all_dims() const
Return a list of all dimensions defined in this group.
Definition: ERF_NCInterface.cpp:632
NCGroup(const int id)
Definition: ERF_NCInterface.H:276
bool has_var(const std::string &) const
Check if a variable exists by name.
Definition: ERF_NCInterface.cpp:543
bool has_dim(const std::string &) const
Check if a dimension exists by name.
Definition: ERF_NCInterface.cpp:537
void put_attr(const std::string &name, const std::string &value) const
Definition: ERF_NCInterface.cpp:557
void def_array(const std::string &name, nc_type dtype, const std::vector< std::string > &) const
Define an array.
Definition: ERF_NCInterface.cpp:483
NCDim dim(const std::string &) const
Get the dimension instance by name.
Definition: ERF_NCInterface.cpp:469
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:243
void enter_def_mode() const
Enter definition mode (not needed for NetCDF4 format)
Definition: ERF_NCInterface.cpp:654
int num_attributes() const
Number of attributes within this group.
Definition: ERF_NCInterface.cpp:517
std::vector< NCVar > all_vars() const
Return a list of all variables defined in this group.
Definition: ERF_NCInterface.cpp:643
Definition: ERF_NCInterface.cpp:8
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:31
size_t len() const
Length of this dimension.
Definition: ERF_NCInterface.cpp:40
Representation of a NetCDF variable.
Definition: ERF_NCInterface.H:53
bool has_attr(const std::string &name) const
Definition: ERF_NCInterface.cpp:370
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:50
void par_access(int cmode) const
Definition: ERF_NCInterface.cpp:437
std::string get_attr(const std::string &name) const
Definition: ERF_NCInterface.cpp:402
void put(const double *) const
Write out the entire variable.
Definition: ERF_NCInterface.cpp:89
void put_attr(const std::string &name, const std::string &value) const
Definition: ERF_NCInterface.cpp:378
void get(double *) const
Read the entire variable from file.
Definition: ERF_NCInterface.cpp:247
std::vector< size_t > shape() const
Shape of the array (size in each array dimension)
Definition: ERF_NCInterface.cpp:69
int ndim() const
Number of array dimensions for this variable.
Definition: ERF_NCInterface.cpp:59