REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_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 REMORA_NC_INTERFACE_H
10#define REMORA_NC_INTERFACE_H
11
12#ifdef REMORA_USE_NETCDF
13#include <string>
14#include <unordered_map>
15#include <vector>
16
17#include <pnetcdf.h>
18
19namespace ncutils {
20
21//! Wrapper around NetCDF data types
22struct NCDType
23{
24 static constexpr nc_type Int = NC_INT;
25#ifdef AMREX_USE_FLOAT
26 static constexpr nc_type Real = NC_FLOAT;
27 using RType = float;
28#else
29 static constexpr nc_type Real = NC_DOUBLE;
30 using RType = double;
31#endif
32};
33
34//! Representation of NetCDF dimension
35struct NCDim
36{
37 //! File/Group Identifier
38 const int ncid;
39
40 //! Dimension ID used with NetCDF API
41 const int dimid;
42
43 //! Name of this dimension
44 std::string name() const;
45
46 //! Length of this dimension
47 MPI_Offset len() const;
48};
49
50//! Representation of a NetCDF variable
51struct NCVar
52{
53 //! File/Group identifier
54 const int ncid;
55
56 //! Variable ID used with NetCDF API
57 const int varid;
58
59 //! Name of this variable
60 std::string name() const;
61
62 //! Number of array dimensions for this variable
63 int ndim() const;
64
65 //! Shape of the array (size in each array dimension)
66 std::vector<MPI_Offset> shape() const;
67
68 //! Write out the entire double variable
69 void put(const double* ptr) const;
70 //! Write out the entire float variable
71 void put(const float* ptr) const;
72 //! Write out the entire int variable
73 void put(const int* ptr) const;
74
75 //! Write out a slice of data
76 void
77 put(const double* dptr,
78 const std::vector<MPI_Offset>& start,
79 const std::vector<MPI_Offset>& count) const;
80
81 //! Write out a slice of data, collective
82 void
83 put_all(const double* dptr,
84 const std::vector<MPI_Offset>& start,
85 const std::vector<MPI_Offset>& count) const;
86
87 //! Write out `num` subarrays in a single collective call. Every rank that
88 //! opened the file must call this, in the same order, but `num` may differ
89 //! between ranks and may be zero. `starts[i]`/`counts[i]` describe subarray
90 //! i, and `dptr` holds all subarrays' data concatenated in that order.
91 void
92 put_varn_all(int num,
93 MPI_Offset* const* starts,
94 MPI_Offset* const* counts,
95 const double* dptr) const;
96
97 //! Write out `num` subarrays in a single collective call (float overload)
98 void
99 put_varn_all(int num,
100 MPI_Offset* const* starts,
101 MPI_Offset* const* counts,
102 const float* dptr) const;
103 //! Write out a slice of data with with strides (see hyperslab definition in NetCDF)
104 void iput(
105 const double* dptr,
106 const std::vector<MPI_Offset>& start,
107 const std::vector<MPI_Offset>& count,
108 int * request) const ;
109
110 //! Write out a slice of data with with strides
111 void
112 put(const double* dptr,
113 const std::vector<MPI_Offset>& start,
114 const std::vector<MPI_Offset>& count,
115 const std::vector<MPI_Offset>& stride) const;
116 //! Write out a slice of data with with strides , collective
117 void
118 put_all(const double* dptr,
119 const std::vector<MPI_Offset>& start,
120 const std::vector<MPI_Offset>& count,
121 const std::vector<MPI_Offset>& stride) const;
122 //! Write out a slice of data
123 void
124 put(const float* dptr,
125 const std::vector<MPI_Offset>& start,
126 const std::vector<MPI_Offset>& count) const;
127 //! Write out a slice of data, collective
128 void
129 put_all(const float* dptr,
130 const std::vector<MPI_Offset>& start,
131 const std::vector<MPI_Offset>& count) const;
132 //! Write out a slice of data with with strides (see hyperslab definition in NetCDF)
133 void
134 put(const float* dptr,
135 const std::vector<MPI_Offset>& start,
136 const std::vector<MPI_Offset>& count,
137 const std::vector<MPI_Offset>& stride) const;
138 //! Write out a slice of data with with strides, collective
139 void
140 put_all(const float* dptr,
141 const std::vector<MPI_Offset>& start,
142 const std::vector<MPI_Offset>& count,
143 const std::vector<MPI_Offset>& stride) const;
144
145
146 //! Write out a slice of data
147 void put(const int* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
148 //! Write out a slice of data, collective
149 void put_all(const int* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
150
151 //! Write out a slice of data with with strides (see hyperslab definition in NetCDF)
152 void
153 put(const int* dptr,
154 const std::vector<MPI_Offset>& start,
155 const std::vector<MPI_Offset>& count,
156 const std::vector<MPI_Offset>& stride) const;
157 //! Write out a slice of data with with strides, collective
158 void
159 put_all(const int* dptr,
160 const std::vector<MPI_Offset>& start,
161 const std::vector<MPI_Offset>& count,
162 const std::vector<MPI_Offset>& stride) const;
163
164
165 //! Write out a slice of string data
166 void put(const char** dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
167 //! Write out a slice of string data with stride
168 void
169 put(
170 const char** dptr,
171 const std::vector<MPI_Offset>& start,
172 const std::vector<MPI_Offset>& count,
173 const std::vector<MPI_Offset>& stride) const;
174
175 //! Read the entire variable from file
176 void get(double* ptr) const;
177 //! Read the entire variable from file
178 void get(float* ptr) const;
179 //! Read the entire variable from file
180 void get(int* ptr) const;
181
182 //! Read a chunk of data from the file
183 void
184 get(double* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
185
186 //! Read a chunk of data from the file, collective
187 void
188 get_all(double* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
189
190 //! Read a chunk of data with strides
191 void
192 get(double* dptr,
193 const std::vector<MPI_Offset>& start,
194 const std::vector<MPI_Offset>& count,
195 const std::vector<MPI_Offset>& stride) const;
196
197 //! Read a chunk of data with strides, collective
198 void
199 get_all(double* dptr,
200 const std::vector<MPI_Offset>& start,
201 const std::vector<MPI_Offset>& count,
202 const std::vector<MPI_Offset>& stride) const;
203
204 //! Read a chunk of data from the file
205 void
206 get(float* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
207 //! Read a chunk of data from file, collective
208 void get_all(float* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
209
210 //! Read a chunk of data with strides
211 void
212 get(float* dptr,
213 const std::vector<MPI_Offset>& start,
214 const std::vector<MPI_Offset>& count,
215 const std::vector<MPI_Offset>& stride) const;
216
217 //! Read a chunk of data with strides, collective
218 void
219 get_all(float* dptr,
220 const std::vector<MPI_Offset>& start,
221 const std::vector<MPI_Offset>& count,
222 const std::vector<MPI_Offset>& stride) const;
223
224 //! Read a chunk of data from the file
225 void
226 get(int* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
227 //! Read a chunk of data from the file, collective
228 void
229 get_all(int* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
230
231 //! Read a chunk of data with strides
232 void
233 get(int* dptr,
234 const std::vector<MPI_Offset>& start,
235 const std::vector<MPI_Offset>& count,
236 const std::vector<MPI_Offset>& stride) const;
237 //! Read a chunk of data with strides, collective
238 void
239 get_all(int* dptr,
240 const std::vector<MPI_Offset>& start,
241 const std::vector<MPI_Offset>& count,
242 const std::vector<MPI_Offset>& stride) const;
243
244
245 //! Read a chunk of data from the file
246 void
247 get(char* dptr, const std::vector<MPI_Offset>& start, const std::vector<MPI_Offset>& count) const;
248
249 //! Read a chunk of data with strides
250 void
251 get(char* dptr,
252 const std::vector<MPI_Offset>& start,
253 const std::vector<MPI_Offset>& count,
254 const std::vector<MPI_Offset>& stride) const;
255
256 //! Whether a variable has an attribute with name
257 bool has_attr(const std::string& name) const;
258 //! Set attribute "name" to "value"
259 void put_attr(const std::string& name, const std::string& value) const;
260 //! Set attribute "name" to "value"
261 void
262 put_attr(const std::string& name, const std::vector<double>& value) const;
263 //! Set attribute "name" to "value"
264 void
265 put_attr(const std::string& name, const std::vector<float>& value) const;
266 //! Set attribute "name" to "value"
267 void put_attr(const std::string& name, const std::vector<int>& value) const;
268
269 //! Read attribute from file
270 std::string get_attr(const std::string& name) const;
271 //! Read attribute from file
272 void get_attr(const std::string& name, std::vector<double>& value) const;
273 //! Read attribute from file
274 void get_attr(const std::string& name, std::vector<float>& value) const;
275 //! Read attribute from file
276 void get_attr(const std::string& name, std::vector<int>& value) const;
277};
278
279
280/** Representation of a NetCDF file
281 *
282 * Provide wrappers to create and open file
283 */
285{
286public:
287
288 //! Create a file. Defaults to CDF-5; classic CDF-1 has a 2GB limit.
289 static NCFile create(
290 const std::string& name,
291 const int cmode = NC_CLOBBER | NC_64BIT_DATA,
292 MPI_Comm comm = MPI_COMM_WORLD,
294
295 //! Open an existing file
296 static NCFile open(
297 const std::string& name,
298 const int cmode = NC_NOWRITE,
299 MPI_Comm comm = MPI_COMM_WORLD,
301
302 ~NCFile();
303
304 //! Close file object
305 void close();
306
307 //! Number of dimensions
308 int num_dimensions() const;
309
310 //! Number of variables
311 int num_variables() const;
312
313 //! Number of attributes
314 int num_attributes() const;
315
316 //! Check if a dimension exists by name
317 bool has_dim(const std::string&) const;
318
319 //! Check if a variable exists by name
320 bool has_var(const std::string&) const;
321
322 //! Check if an attribute exists
323 bool has_attr(const std::string&) const;
324
325 //! Get the dimension instance by name
326 NCDim dim(const std::string&) const;
327
328 //! Get the variable instance by name
329 NCVar var(const std::string&) const;
330
331 //! Define new dimension
332 NCDim def_dim(const std::string&, const size_t len) const;
333
334 //! Define a scalar variable, i.e., 0-dimensional array
335 NCVar def_scalar(const std::string& name, const nc_type dtype) const;
336
337 //! Define an array
339 const std::string& name,
340 const nc_type dtype,
341 const std::vector<std::string>&) const;
342
343 //! Define an array with a fill value
345 const std::string& name,
346 const nc_type dtype,
347 const std::vector<std::string>& dnames,
348 const void* fill_val) const;
349
350 //! Define a variable (wrapper for def_array)
352 const std::string& name,
353 const nc_type dtype,
354 const std::vector<std::string>& dnames) const
355 {
356 return def_array(name, dtype, dnames);
357 }
358
359 //! Define a variable (wrapper for def_array)
361 const std::string& name,
362 const nc_type dtype,
363 const std::vector<std::string>& dnames,
364 const void* fill_val) const
365 {
366 return def_array_fill(name, dtype, dnames, fill_val);
367 }
368
369 //! Set file attribute to value
370 void put_attr(const std::string& name, const std::string& value) const;
371 //! Set file attribute to value
372 void put_attr(const std::string& name, const std::vector<double>& value) const;
373 //! Set file attribute to value
374 void put_attr(const std::string& name, const std::vector<float>& value) const;
375 //! Set file attribute to value
376 void put_attr(const std::string& name, const std::vector<int>& value) const;
377
378 //! Read file attribute from file
379 std::string get_attr(const std::string& name) const;
380 //! Read file attribute from file
381 void get_attr(const std::string& name, std::vector<double>& value) const;
382 //! Read file attribute from file
383 void get_attr(const std::string& name, std::vector<float>& value) const;
384 //! Read file attribute from file
385 void get_attr(const std::string& name, std::vector<int>& value) const;
386
387 //! wait for non-blocking calls to finish
388 void wait_all( int num_requests, int * requests);
389
390 //! Return a list of all dimensions defined in this group
391 std::vector<NCDim> all_dims() const;
392
393 //! Return a list of all variables defined in this group
394 std::vector<NCVar> all_vars() const;
395
396 //! Enter definition mode (not needed for NetCDF4 format)
397 void enter_def_mode() const;
398
399 //! Exit definition mode
400 void exit_def_mode() const;
401
402 NCFile(const int id) : ncid(id), is_open{true} {}
403
404 const int ncid{-1};
405 bool is_open{false};
406};
407
408} // namespace ncutils
409
410#else
411// why do we need this if netcdf is not defined ?
412
413namespace ncutils {
414
415struct NCDim {
416 const int ncid { -1 };
417 const int dimid { -1 };
418};
419
420struct NCVar {
421 const int ncid { -1 };
422 const int varid { -1 };
423};
424
425class NCFile {
426public:
427 const int ncid { -1 };
428};
429
430} // namespace ncutils
431
432#endif
433
434#endif /* NC_INTERFACE_H */
mf_h setVal(geomdata.ProbHi(2))
void put_attr(const std::string &name, const std::string &value) const
Set file attribute to value.
std::vector< NCDim > all_dims() const
Return a list of all dimensions defined in this group.
NCVar def_scalar(const std::string &name, const nc_type dtype) const
Define a scalar variable, i.e., 0-dimensional array.
NCVar def_array(const std::string &name, const nc_type dtype, const std::vector< std::string > &) const
Define an array.
std::vector< NCVar > all_vars() const
Return a list of all variables defined in this group.
NCDim dim(const std::string &) const
Get the dimension instance by name.
void enter_def_mode() const
Enter definition mode (not needed for NetCDF4 format)
bool has_var(const std::string &) const
Check if a variable exists by name.
bool has_attr(const std::string &) const
Check if an attribute exists.
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)
NCDim def_dim(const std::string &, const size_t len) const
Define new dimension.
void exit_def_mode() const
Exit definition mode.
std::string get_attr(const std::string &name) const
Read file attribute from file.
int num_dimensions() const
Number of dimensions.
void wait_all(int num_requests, int *requests)
wait for non-blocking calls to finish
bool has_dim(const std::string &) const
Check if a dimension exists by name.
int num_attributes() const
Number of attributes.
static NCFile create(const std::string &name, const int cmode=NC_CLOBBER|NC_64BIT_DATA, MPI_Comm comm=MPI_COMM_WORLD, MPI_Info info=MPI_INFO_NULL)
Create a file. Defaults to CDF-5; classic CDF-1 has a 2GB limit.
int num_variables() const
Number of variables.
static NCFile open(const std::string &name, const int cmode=NC_NOWRITE, MPI_Comm comm=MPI_COMM_WORLD, MPI_Info info=MPI_INFO_NULL)
Open an existing file.
void close()
Close file object.
NCVar var(const std::string &) const
Get the variable instance by name.
NCVar def_var_fill(const std::string &name, const nc_type dtype, const std::vector< std::string > &dnames, const void *fill_val) const
Define a variable (wrapper for def_array)
NCVar def_array_fill(const std::string &name, const nc_type dtype, const std::vector< std::string > &dnames, const void *fill_val) const
Define an array with a fill value.
Wrapper around NetCDF data types.
static constexpr nc_type Real
static constexpr nc_type Int
Representation of NetCDF dimension.
const int dimid
Dimension ID used with NetCDF API.
const int ncid
File/Group Identifier.
MPI_Offset len() const
Length of this dimension.
std::string name() const
Name of this dimension.
Representation of a NetCDF variable.
bool has_attr(const std::string &name) const
Whether a variable has an attribute with name.
const int ncid
File/Group identifier.
const int varid
Variable ID used with NetCDF API.
void iput(const double *dptr, const std::vector< MPI_Offset > &start, const std::vector< MPI_Offset > &count, int *request) const
Write out a slice of data with with strides (see hyperslab definition in NetCDF)
std::string name() const
Name of this variable.
void put_varn_all(int num, MPI_Offset *const *starts, MPI_Offset *const *counts, const double *dptr) const
void put(const double *ptr) const
Write out the entire double variable.
void get(double *ptr) const
Read the entire variable from file.
std::string get_attr(const std::string &name) const
Read attribute from file.
void put_all(const double *dptr, const std::vector< MPI_Offset > &start, const std::vector< MPI_Offset > &count) const
Write out a slice of data, collective.
void put_attr(const std::string &name, const std::string &value) const
Set attribute "name" to "value".
std::vector< MPI_Offset > shape() const
Shape of the array (size in each array dimension)
void get_all(double *dptr, const std::vector< MPI_Offset > &start, const std::vector< MPI_Offset > &count) const
Read a chunk of data from the file, collective.
int ndim() const
Number of array dimensions for this variable.