YAKL
YAKL_netcdf.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include <netcdf.h>
5 #include <vector>
6 #include "YAKL.h"
7 
8 
9 
11 namespace yakl {
12  //Error reporting routine for the PNetCDF I/O
14  inline void ncwrap( int ierr , int line ) {
15  if (ierr != NC_NOERR) {
16  printf("NetCDF Error at line: %d\n", line);
17  printf("%s\n",nc_strerror(ierr));
18  yakl_throw(nc_strerror(ierr));
19  }
20  }
21 
23  int constexpr NETCDF_MODE_READ = NC_NOWRITE;
25  int constexpr NETCDF_MODE_WRITE = NC_WRITE;
27  int constexpr NETCDF_MODE_REPLACE = NC_CLOBBER;
29  int constexpr NETCDF_MODE_NEW = NC_NOCLOBBER;
30 
31  // Evidently there were ton of issues when using the C++ interface for NetCDF
32  // People can't seem to install it correctly.
33  // Therefore, I'm replicating the basic functionality so that I can use the code
34  // I previously wrote for handling netCDF files for YAKL Array objects
36  class SimpleNetCDF {
37  public:
38 
39 
41  class NcDim {
42  public:
43  std::string name;
44  size_t len;
45  int id;
46  bool is_unlim;
47  NcDim() {
48  name = "";
49  id = -999;
50  len = 0;
51  is_unlim = false;
52  }
53  ~NcDim() {}
54  NcDim(std::string name, size_t len, int id, bool is_unlim) {
55  this->name = name;
56  this->len = len;
57  this->id = id;
58  this->is_unlim = is_unlim;
59  }
60  NcDim(NcDim &&in) {
61  this->name = in.name;
62  this->len = in.len;
63  this->id = in.id;
64  this->is_unlim = in.is_unlim;
65  }
66  NcDim(NcDim const &in) {
67  this->name = in.name;
68  this->len = in.len;
69  this->id = in.id;
70  this->is_unlim = in.is_unlim;
71  }
72  NcDim &operator=(NcDim &&in) {
73  this->name = in.name;
74  this->len = in.len;
75  this->id = in.id;
76  this->is_unlim = in.is_unlim;
77  return *this;
78  }
79  NcDim &operator=(NcDim const &in) {
80  this->name = in.name;
81  this->len = in.len;
82  this->id = in.id;
83  this->is_unlim = in.is_unlim;
84  return *this;
85  }
86  std::string getName() const { return name; }
87  size_t getSize() const { return len; }
88  int getId() const { return id; }
89  bool isNull() const { return id == -999; }
90  bool operator==(NcDim const &rhs) const { return this->name == rhs.name && !isNull(); }
91  bool operator!=(NcDim const &rhs) const { return this->name != rhs.name || isNull(); }
92  bool isUnlimited() const { return is_unlim; }
93  };
94 
95 
97  class NcVar {
98  public:
99  int ncid;
100  std::string name;
101  std::vector<NcDim> dims;
102  int id;
103  int type;
104  NcVar() {
105  ncid = -999;
106  name = "";
107  dims = std::vector<NcDim>(0);
108  id = -999;
109  type = -999;
110  }
111  ~NcVar() {}
112  NcVar(int ncid , std::string name, std::vector<NcDim> dims, int id, int type) {
113  this->ncid = ncid;
114  this->name = name;
115  this->dims = dims;
116  this->id = id;
117  this->type = type;
118  }
119  NcVar(NcVar &&in) {
120  this->ncid = in.ncid;
121  this->name = in.name;
122  this->dims = in.dims;
123  this->id = in.id;
124  this->type = in.type;
125  }
126  NcVar(NcVar const &in) {
127  this->ncid = in.ncid;
128  this->name = in.name;
129  this->dims = in.dims;
130  this->id = in.id;
131  this->type = in.type;
132  }
133  NcVar &operator=(NcVar &&in) {
134  this->ncid = in.ncid;
135  this->name = in.name;
136  this->dims = in.dims;
137  this->id = in.id;
138  this->type = in.type;
139  return *this;
140  }
141  NcVar &operator=(NcVar const &in) {
142  this->ncid = in.ncid;
143  this->name = in.name;
144  this->dims = in.dims;
145  this->id = in.id;
146  this->type = in.type;
147  return *this;
148  }
149  std::string getName() const { return name; }
150  std::vector<NcDim> getDims() const { return dims; }
151  int getDimCount() const { return dims.size(); }
152  int getId() const { return id; }
153  int getType() const { return type; }
154  bool isNull () const { return id == -999; }
155  bool operator==(NcDim const &rhs) const { return this->name == rhs.name && !isNull(); }
156  bool operator!=(NcDim const &rhs) const { return this->name != rhs.name || isNull(); }
157  NcDim getDim(int i) const {
158  if (isNull() || dims.size() <= i) {
159  return NcDim();
160  } else {
161  return dims[i];
162  }
163  }
164 
165  void putVar(double const *data) { ncwrap( nc_put_var_double ( ncid , id , data ) , __LINE__ ); }
166  void putVar(float const *data) { ncwrap( nc_put_var_float ( ncid , id , data ) , __LINE__ ); }
167  void putVar(int const *data) { ncwrap( nc_put_var_int ( ncid , id , data ) , __LINE__ ); }
168  void putVar(long const *data) { ncwrap( nc_put_var_long ( ncid , id , data ) , __LINE__ ); }
169  void putVar(long long const *data) { ncwrap( nc_put_var_longlong ( ncid , id , data ) , __LINE__ ); }
170  void putVar(signed char const *data) { ncwrap( nc_put_var_schar ( ncid , id , data ) , __LINE__ ); }
171  void putVar(short const *data) { ncwrap( nc_put_var_short ( ncid , id , data ) , __LINE__ ); }
172  void putVar(unsigned char const *data) { ncwrap( nc_put_var_uchar ( ncid , id , data ) , __LINE__ ); }
173  void putVar(unsigned int const *data) { ncwrap( nc_put_var_uint ( ncid , id , data ) , __LINE__ ); }
174  void putVar(unsigned long const *data) { ncwrap( nc_put_var_uint ( ncid , id , (unsigned int const *) data ) , __LINE__ ); }
175  void putVar(unsigned long long const *data) { ncwrap( nc_put_var_ulonglong( ncid , id , data ) , __LINE__ ); }
176  void putVar(unsigned short const *data) { ncwrap( nc_put_var_ushort ( ncid , id , data ) , __LINE__ ); }
177  void putVar(char const *data) { ncwrap( nc_put_var_text ( ncid , id , data ) , __LINE__ ); }
178  void putVar(bool const *data) { yakl_throw("ERROR: Cannot write bools to netCDF file"); }
179 
180  void putVar(std::vector<size_t> start , std::vector<size_t> count, double const *data) { ncwrap( nc_put_vara_double ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
181  void putVar(std::vector<size_t> start , std::vector<size_t> count, float const *data) { ncwrap( nc_put_vara_float ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
182  void putVar(std::vector<size_t> start , std::vector<size_t> count, int const *data) { ncwrap( nc_put_vara_int ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
183  void putVar(std::vector<size_t> start , std::vector<size_t> count, long const *data) { ncwrap( nc_put_vara_long ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
184  void putVar(std::vector<size_t> start , std::vector<size_t> count, long long const *data) { ncwrap( nc_put_vara_longlong ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
185  void putVar(std::vector<size_t> start , std::vector<size_t> count, signed char const *data) { ncwrap( nc_put_vara_schar ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
186  void putVar(std::vector<size_t> start , std::vector<size_t> count, short const *data) { ncwrap( nc_put_vara_short ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
187  void putVar(std::vector<size_t> start , std::vector<size_t> count, unsigned char const *data) { ncwrap( nc_put_vara_uchar ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
188  void putVar(std::vector<size_t> start , std::vector<size_t> count, unsigned int const *data) { ncwrap( nc_put_vara_uint ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
189  void putVar(std::vector<size_t> start , std::vector<size_t> count, unsigned long const *data) { ncwrap( nc_put_vara_uint ( ncid , id , start.data() , count.data(), (unsigned int const *) data ) , __LINE__ ); }
190  void putVar(std::vector<size_t> start , std::vector<size_t> count, unsigned long long const *data) { ncwrap( nc_put_vara_ulonglong( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
191  void putVar(std::vector<size_t> start , std::vector<size_t> count, unsigned short const *data) { ncwrap( nc_put_vara_ushort ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
192  void putVar(std::vector<size_t> start , std::vector<size_t> count, char const *data) { ncwrap( nc_put_vara_text ( ncid , id , start.data() , count.data(), data ) , __LINE__ ); }
193  void putVar(std::vector<size_t> start , std::vector<size_t> count, bool const *data) { yakl_throw("ERROR: Cannot write bools to netCDF file"); }
194 
195  void getVar(double *data) const { ncwrap( nc_get_var_double ( ncid , id , data ) , __LINE__ ); }
196  void getVar(float *data) const { ncwrap( nc_get_var_float ( ncid , id , data ) , __LINE__ ); }
197  void getVar(int *data) const { ncwrap( nc_get_var_int ( ncid , id , data ) , __LINE__ ); }
198  void getVar(long *data) const { ncwrap( nc_get_var_long ( ncid , id , data ) , __LINE__ ); }
199  void getVar(long long *data) const { ncwrap( nc_get_var_longlong ( ncid , id , data ) , __LINE__ ); }
200  void getVar(signed char *data) const { ncwrap( nc_get_var_schar ( ncid , id , data ) , __LINE__ ); }
201  void getVar(short *data) const { ncwrap( nc_get_var_short ( ncid , id , data ) , __LINE__ ); }
202  void getVar(unsigned char *data) const { ncwrap( nc_get_var_uchar ( ncid , id , data ) , __LINE__ ); }
203  void getVar(unsigned int *data) const { ncwrap( nc_get_var_uint ( ncid , id , data ) , __LINE__ ); }
204  void getVar(unsigned long *data) const { ncwrap( nc_get_var_uint ( ncid , id , (unsigned int *) data ) , __LINE__ ); }
205  void getVar(unsigned long long *data) const { ncwrap( nc_get_var_ulonglong( ncid , id , data ) , __LINE__ ); }
206  void getVar(unsigned short *data) const { ncwrap( nc_get_var_ushort ( ncid , id , data ) , __LINE__ ); }
207  void getVar(char *data) const { ncwrap( nc_get_var_text ( ncid , id , data ) , __LINE__ ); }
208  void getVar(bool *data) const { yakl_throw("ERROR: Cannot read bools directly from netCDF file. This should've been intercepted and changed to int."); }
209 
210  void print() {
211  std::cout << "Variable Name: " << name << "\n";
212  std::cout << "Dims: \n";
213  for (int i=0; i < dims.size(); i++) {
214  std::cout << " " << dims[i].getName() << "; Size: " << dims[i].getSize() << "\n\n";
215  }
216  }
217  };
218 
219 
221  class NcFile {
222  public:
223  int ncid;
224  NcFile() { ncid = -999; }
225  ~NcFile() {}
226  NcFile(int ncid) { this->ncid = ncid; }
227  NcFile(NcFile &&in) {
228  this->ncid = in.ncid;
229  }
230  NcFile(NcFile const &in) {
231  this->ncid = in.ncid;
232  }
233  NcFile &operator=(NcFile &&in) {
234  this->ncid = in.ncid;
235  return *this;
236  }
237  NcFile &operator=(NcFile const &in) {
238  this->ncid = in.ncid;
239  return *this;
240  }
241 
242  bool isNull() { return ncid == -999; }
243 
244  void open( std::string fname , int mode ) {
245  close();
246  if (! (mode == NETCDF_MODE_READ || mode == NETCDF_MODE_WRITE) ) {
247  yakl_throw("ERROR: open mode can be NETCDF_MODE_READ or NETCDF_MODE_WRITE");
248  }
249  ncwrap( nc_open( fname.c_str() , mode , &ncid ) , __LINE__ );
250  }
251 
252  void create( std::string fname , int mode ) {
253  close();
254  if (! (mode == NETCDF_MODE_NEW || mode == NETCDF_MODE_REPLACE) ) {
255  yakl_throw("ERROR: open mode can be NETCDF_MODE_NEW or NETCDF_MODE_REPLACE");
256  }
257  ncwrap( nc_create( fname.c_str() , mode | NC_NETCDF4 , &ncid ) , __LINE__ );
258  }
259 
260  void close() {
261  if (ncid != -999) ncwrap( nc_close( ncid ) , __LINE__ );
262  ncid = -999;
263  }
264 
265  NcVar getVar( std::string varName ) const {
266  int varid;
267  int ierr = nc_inq_varid( ncid , varName.c_str() , &varid);
268  if (ierr != NC_NOERR) return NcVar();
269  char vname[NC_MAX_NAME+1];
270  int type;
271  int ndims;
272  int dimids[NC_MAX_VAR_DIMS];
273  int natts;
274  // Get variable information
275  ncwrap( nc_inq_var(ncid , varid , vname , &type , &ndims , dimids , &natts ) , __LINE__ );
276  // Accumulate the dimensions
277  std::vector<NcDim> dims(ndims);
278  for (int i=0; i < ndims; i++) {
279  dims[i] = getDim( dimids[i] );
280  }
281  return NcVar( ncid , varName , dims , varid , type );
282  }
283 
284  NcDim getDim( std::string dimName ) const {
285  int dimid;
286  int ierr = nc_inq_dimid( ncid , dimName.c_str() , &dimid);
287  if (ierr != NC_NOERR) return NcDim();
288  return getDim( dimid );
289  }
290 
291  NcDim getDim( int dimid ) const {
292  char dname[NC_MAX_NAME+1];
293  size_t len;
294  int unlim_dimid;
295  ncwrap( nc_inq_dim( ncid , dimid , dname , &len ) , __LINE__ );
296  ncwrap( nc_inq_unlimdim( ncid , &unlim_dimid ) , __LINE__ );
297  return NcDim( std::string(dname) , len , dimid , dimid == unlim_dimid );
298  }
299 
300  NcVar addVar( std::string varName , int type , std::vector<NcDim> &dims ) {
301  std::vector<int> dimids(dims.size());
302  for (int i=0; i < dims.size(); i++) { dimids[i] = dims[i].getId(); }
303  int varid;
304  ncwrap( nc_def_var(ncid , varName.c_str() , type , dims.size() , dimids.data() , &varid) , __LINE__ );
305  return NcVar( ncid , varName , dims , varid , type );
306  }
307 
308  NcVar addVar( std::string varName , int type ) {
309  int varid;
310  int *dummy = nullptr;
311  ncwrap( nc_def_var(ncid , varName.c_str() , type , 0 , dummy , &varid) , __LINE__ );
312  return NcVar( ncid , varName , std::vector<NcDim>(0) , varid , type );
313  }
314 
315  NcDim addDim( std::string dimName , size_t len ) {
316  int dimid;
317  ncwrap( nc_def_dim(ncid , dimName.c_str() , len , &dimid ) , __LINE__ );
318  return NcDim( dimName , len , dimid , false );
319  }
320 
321  NcDim addDim( std::string dimName ) {
322  int dimid;
323  ncwrap( nc_def_dim(ncid , dimName.c_str() , NC_UNLIMITED , &dimid ) , __LINE__ );
324  return NcDim( dimName , 0 , dimid , true );
325  }
326 
327  };
328 
329 
331  NcFile file;
332 
333 
335 
336 
339 
340 
343  void open(std::string fname , int mode = NETCDF_MODE_READ) { file.open(fname,mode); }
344 
345 
348  void create(std::string fname , int mode = NC_CLOBBER) { file.create(fname,mode); }
349 
350 
352  void close() { file.close(); }
353 
354 
356  bool varExists( std::string varName ) const { return ! file.getVar(varName).isNull(); }
357 
358 
360  bool dimExists( std::string dimName ) const { return ! file.getDim(dimName).isNull(); }
361 
362 
364  size_t getDimSize( std::string dimName ) const { return file.getDim(dimName).getSize(); }
365 
366 
368  void createDim( std::string dimName , size_t len ) { file.addDim( dimName , len ); }
369 
371  void createDim( std::string dimName ) { file.addDim( dimName ); }
372 
373 
375  template <class T, int rank, int myMem, int myStyle>
376  void write(Array<T,rank,myMem,myStyle> const &arr , std::string varName , std::vector<std::string> dimNames) {
377  if (rank != dimNames.size()) { yakl_throw("dimNames.size() != Array's rank"); }
378  std::vector<NcDim> dims(rank); // List of dimensions for this variable
379  // Make sure the dimensions are in there and are the right sizes
380  for (int i=0; i<rank; i++) {
381  auto dimLoc = file.getDim( dimNames[i] );
382  // If dimension doesn't exist, create it; otherwise, make sure it's the right size
383  NcDim tmp;
384  if ( dimLoc.isNull() ) {
385  tmp = file.addDim( dimNames[i] , arr.extent(i) );
386  } else {
387  if (dimLoc.getSize() != arr.extent(i)) {
388  yakl_throw("dimension size differs from the file");
389  }
390  tmp = dimLoc;
391  }
392  if (myStyle == styleC) {
393  dims[i] = tmp;
394  } else {
395  dims[rank-1-i] = tmp;
396  }
397  }
398  // Make sure the variable is there and is the right dimension
399  auto var = file.getVar(varName);
400  if ( var.isNull() ) {
401  var = file.addVar( varName , getType<T>() , dims );
402  } else {
403  if ( var.getType() != getType<T>() ) { yakl_throw("Existing variable's type != array's type"); }
404  auto varDims = var.getDims();
405  if (varDims.size() != rank) { yakl_throw("Existing variable's rank != array's rank"); }
406  for (int i=0; i < varDims.size(); i++) {
407  if (myStyle == styleC) {
408  if (varDims[i].getSize() != arr.extent(i)) {
409  yakl_throw("Existing variable's dimension sizes are not the same as the array's");
410  }
411  } else {
412  if (varDims[rank-1-i].getSize() != arr.extent(i)) {
413  yakl_throw("Existing variable's dimension sizes are not the same as the array's");
414  }
415  }
416  }
417  }
418 
419  if (myMem == memDevice) {
420  var.putVar(arr.createHostCopy().data());
421  } else {
422  var.putVar(arr.data());
423  }
424  }
425 
426 
428  template <class T, typename std::enable_if<std::is_arithmetic<T>::value,int>::type = 0 >
429  void write1(T val , std::string varName , int ind , std::string ulDimName="unlim" ) {
430  // Get the unlimited dimension or create it if it doesn't exist
431  auto ulDim = file.getDim( ulDimName );
432  if ( ulDim.isNull() ) {
433  ulDim = file.addDim( ulDimName );
434  }
435  // Make sure the variable is there and is the right dimension
436  auto var = file.getVar(varName);
437  if ( var.isNull() ) {
438  std::vector<NcDim> dims(1);
439  dims[0] = ulDim;
440  var = file.addVar( varName , getType<T>() , dims );
441  }
442  std::vector<size_t> start(1);
443  std::vector<size_t> count(1);
444  start[0] = ind;
445  count[0] = 1;
446  var.putVar(start,count,&val);
447  }
448 
449 
451  template <class T, int rank, int myMem, int myStyle>
452  void write1(Array<T,rank,myMem,myStyle> const &arr , std::string varName , std::vector<std::string> dimNames ,
453  int ind , std::string ulDimName="unlim" ) {
454  if (rank != dimNames.size()) { yakl_throw("dimNames.size() != Array's rank"); }
455  std::vector<NcDim> dims(rank+1); // List of dimensions for this variable
456  // Get the unlimited dimension or create it if it doesn't exist
457  dims[0] = file.getDim( ulDimName );
458  if ( dims[0].isNull() ) {
459  dims[0] = file.addDim( ulDimName );
460  }
461  // Make sure the dimensions are in there and are the right sizes
462  for (int i=0; i<rank; i++) {
463  auto dimLoc = file.getDim( dimNames[i] );
464  // If dimension doesn't exist, create it; otherwise, make sure it's the right size
465  NcDim tmp;
466  if ( dimLoc.isNull() ) {
467  tmp = file.addDim( dimNames[i] , arr.extent(i) );
468  } else {
469  if (dimLoc.getSize() != arr.extent(i)) {
470  yakl_throw("dimension size differs from the file");
471  }
472  tmp = dimLoc;
473  }
474  if (myStyle == styleC) {
475  dims[1+i] = tmp;
476  } else {
477  dims[1+rank-1-i] = tmp;
478  }
479  }
480  // Make sure the variable is there and is the right dimension
481  auto var = file.getVar(varName);
482  if ( var.isNull() ) {
483  var = file.addVar( varName , getType<T>() , dims );
484  } else {
485  if ( var.getType() != getType<T>() ) { yakl_throw("Existing variable's type != array's type"); }
486  auto varDims = var.getDims();
487  if (varDims.size() != rank+1) {
488  yakl_throw("Existing variable's rank != array's rank");
489  }
490  for (int i=1; i < varDims.size(); i++) {
491  if (myStyle == styleC) {
492  if (varDims[i].getSize() != arr.extent(i-1)) {
493  yakl_throw("Existing variable's dimension sizes are not the same as the array's");
494  }
495  } else {
496  if (varDims[1+rank-i].getSize() != arr.extent(i-1)) {
497  yakl_throw("Existing variable's dimension sizes are not the same as the array's");
498  }
499  }
500  }
501  }
502 
503  std::vector<size_t> start(rank+1);
504  std::vector<size_t> count(rank+1);
505  start[0] = ind;
506  count[0] = 1;
507  for (int i=1; i < rank+1; i++) {
508  start[i] = 0;
509  count[i] = dims[i].getSize();
510  }
511  if (myMem == memDevice) {
512  var.putVar(start,count,arr.createHostCopy().data());
513  } else {
514  var.putVar(start,count,arr.data());
515  }
516  }
517 
518 
520  template <class T, int rank, int myMem, int myStyle>
521  void read(Array<T,rank,myMem,myStyle> &arr , std::string varName) {
522  // Make sure the variable is there and is the right dimension
523  auto var = file.getVar(varName);
524  std::vector<int> dimSizes(rank);
525  if ( ! var.isNull() ) {
526  auto varDims = var.getDims();
527  if (varDims.size() != rank) { yakl_throw("Existing variable's rank != array's rank"); }
528  if (myStyle == styleC) {
529  for (int i=0; i < varDims.size(); i++) { dimSizes[i] = varDims[i].getSize(); }
530  } else if (myStyle == styleFortran) {
531  for (int i=0; i < varDims.size(); i++) { dimSizes[i] = varDims[varDims.size()-1-i].getSize(); }
532  }
533  bool createArr = ! arr.initialized();
534  if (arr.initialized()) {
535  for (int i=0; i < dimSizes.size(); i++) {
536  if (dimSizes[i] != arr.extent(i)) {
537  #ifdef YAKL_DEBUG
538  std::cout << "WARNING: Array dims wrong size; deallocating previous array and allocating a new one\n";
539  #endif
540  createArr = true;
541  }
542  }
543  }
544  if (createArr) { arr = Array<T,rank,myMem,myStyle>(varName.c_str(),dimSizes); }
545  } else { yakl_throw("Variable does not exist"); }
546 
547  if (myMem == memDevice) {
548  auto arrHost = arr.createHostCopy();
549  if (std::is_same<T,bool>::value) {
550  Array<int,rank,memHost,myStyle> tmp("tmp",dimSizes);
551  var.getVar(tmp.data());
552  for (int i=0; i < arr.totElems(); i++) { arrHost.data()[i] = tmp.data()[i] == 1; }
553  } else {
554  var.getVar(arrHost.data());
555  }
556  arrHost.deep_copy_to(arr);
557  fence();
558  } else {
559  if (std::is_same<T,bool>::value) {
560  Array<int,rank,memHost,myStyle> tmp("tmp",dimSizes);
561  var.getVar(tmp.data());
562  for (int i=0; i < arr.totElems(); i++) { arr.data()[i] = tmp.data()[i] == 1; }
563  } else {
564  var.getVar(arr.data());
565  }
566  }
567  }
568 
569 
571  template <class T>
572  void read(T &arr , std::string varName) {
573  auto var = file.getVar(varName);
574  if ( var.isNull() ) { yakl_throw("Variable does not exist"); }
575  var.getVar(&arr);
576  }
577 
578 
580  template <class T>
581  void write(T arr , std::string varName) {
582  auto var = file.getVar(varName);
583  if ( var.isNull() ) {
584  var = file.addVar( varName , getType<T>() );
585  }
586  var.putVar(&arr);
587  }
588 
589 
591  template <class T> int getType() const {
592  if ( std::is_same<typename std::remove_cv<T>::type,signed char>::value ) { return NC_BYTE; }
593  else if ( std::is_same<typename std::remove_cv<T>::type,unsigned char>::value ) { return NC_UBYTE; }
594  else if ( std::is_same<typename std::remove_cv<T>::type, short>::value ) { return NC_SHORT; }
595  else if ( std::is_same<typename std::remove_cv<T>::type,unsigned short>::value ) { return NC_USHORT; }
596  else if ( std::is_same<typename std::remove_cv<T>::type, int>::value ) { return NC_INT; }
597  else if ( std::is_same<typename std::remove_cv<T>::type,unsigned int>::value ) { return NC_UINT; }
598  else if ( std::is_same<typename std::remove_cv<T>::type, long>::value ) { return NC_INT; }
599  else if ( std::is_same<typename std::remove_cv<T>::type,unsigned long>::value ) { return NC_UINT; }
600  else if ( std::is_same<typename std::remove_cv<T>::type, long long>::value ) { return NC_INT64; }
601  else if ( std::is_same<typename std::remove_cv<T>::type,unsigned long long>::value ) { return NC_UINT64; }
602  else if ( std::is_same<typename std::remove_cv<T>::type, float>::value ) { return NC_FLOAT; }
603  else if ( std::is_same<typename std::remove_cv<T>::type, double>::value ) { return NC_DOUBLE; }
604  if ( std::is_same<typename std::remove_cv<T>::type, char>::value ) { return NC_CHAR; }
605  else { yakl_throw("Invalid type"); }
606  return -1;
607  }
608 
609  };
610 
611 
612 
613 }
615 
616 
yakl::memDevice
constexpr int memDevice
Specifies a device memory address space for a yakl::Array object.
Definition: YAKL_memory_spaces.h:13
yakl::NETCDF_MODE_REPLACE
constexpr int NETCDF_MODE_REPLACE
Tells NetCDF the created file should overwite a file of the same name.
Definition: YAKL_netcdf.h:27
yakl::SimpleNetCDF::write1
void write1(T val, std::string varName, int ind, std::string ulDimName="unlim")
Write one entry of a scalar into the unlimited index.
Definition: YAKL_netcdf.h:429
yakl::SimpleNetCDF::createDim
void createDim(std::string dimName, size_t len)
Create a dimension of the given length.
Definition: YAKL_netcdf.h:368
yakl::SimpleNetCDF::varExists
bool varExists(std::string varName) const
Determine if a variable name exists.
Definition: YAKL_netcdf.h:356
YAKL.h
yakl::intrinsics::count
int count(Array< bool, rank, memHost, myStyle > const &mask)
Definition: YAKL_intrinsics_count.h:10
yakl::NETCDF_MODE_WRITE
constexpr int NETCDF_MODE_WRITE
Tells NetCDF the opened file should be opened for reading and writing.
Definition: YAKL_netcdf.h:25
yakl::SimpleNetCDF::close
void close()
Close the netcdf file.
Definition: YAKL_netcdf.h:352
yakl::SimpleNetCDF::create
void create(std::string fname, int mode=NC_CLOBBER)
Create a netcdf file.
Definition: YAKL_netcdf.h:348
__YAKL_NAMESPACE_WRAPPER_END__
#define __YAKL_NAMESPACE_WRAPPER_END__
Definition: YAKL.h:20
yakl::SimpleNetCDF::write
void write(T arr, std::string varName)
Write a single scalar value.
Definition: YAKL_netcdf.h:581
__YAKL_NAMESPACE_WRAPPER_BEGIN__
#define __YAKL_NAMESPACE_WRAPPER_BEGIN__
Definition: YAKL.h:19
yakl::SimpleNetCDF::open
void open(std::string fname, int mode=NETCDF_MODE_READ)
Open a netcdf file.
Definition: YAKL_netcdf.h:343
yakl::SimpleNetCDF::write1
void write1(Array< T, rank, myMem, myStyle > const &arr, std::string varName, std::vector< std::string > dimNames, int ind, std::string ulDimName="unlim")
Write one entry of an Array into the unlimited index.
Definition: YAKL_netcdf.h:452
yakl::SimpleNetCDF::dimExists
bool dimExists(std::string dimName) const
Determine if a dimension name exists.
Definition: YAKL_netcdf.h:360
yakl::SimpleNetCDF::createDim
void createDim(std::string dimName)
Create an unlimited dimension.
Definition: YAKL_netcdf.h:371
yakl::fence
void fence()
Block the host code until all device code has completed.
Definition: YAKL_fence.h:16
yakl::SimpleNetCDF::getDimSize
size_t getDimSize(std::string dimName) const
Determine the size of a dimension name.
Definition: YAKL_netcdf.h:364
yakl::SimpleNetCDF::~SimpleNetCDF
~SimpleNetCDF()
Files are automatically closed when SimpleNetCDF objects are destroyed.
Definition: YAKL_netcdf.h:338
yakl::SimpleNetCDF::SimpleNetCDF
SimpleNetCDF()
Definition: YAKL_netcdf.h:334
yakl::NETCDF_MODE_READ
constexpr int NETCDF_MODE_READ
Tells NetCDF the opened file should be opened for reading only.
Definition: YAKL_netcdf.h:23
yakl::componentwise::operator!=
Array< decltype(T1()!=T2()), N, memHost, STYLE > operator!=(Array< T1, N, memHost, STYLE > const &left, T2 const &right)
Definition: YAKL_componentwise.h:393
yakl::yakl_throw
YAKL_INLINE void yakl_throw(const char *msg)
Throw an error message. Works from the host or device.
Definition: YAKL_error.h:17
yakl::styleC
constexpr int styleC
Template parameter for yakl::Array that specifies it should follow C-style behavior.
Definition: YAKL_Array.h:20
yakl::SimpleNetCDF::read
void read(Array< T, rank, myMem, myStyle > &arr, std::string varName)
Read an entire Array.
Definition: YAKL_netcdf.h:521
yakl::Array
This declares the yakl::Array class. Please see the yakl::styleC and yakl::styleFortran template spec...
Definition: YAKL_Array.h:40
yakl::SimpleNetCDF::write
void write(Array< T, rank, myMem, myStyle > const &arr, std::string varName, std::vector< std::string > dimNames)
Write an entire Array at once.
Definition: YAKL_netcdf.h:376
yakl::styleFortran
constexpr int styleFortran
Template parameter for yakl::Array that specifies it should follow Fortran-style behavior.
Definition: YAKL_Array.h:22
yakl
yakl::SimpleNetCDF
Simple way to write yakl::Array objects to NetCDF files.
Definition: YAKL_netcdf.h:36
yakl::NETCDF_MODE_NEW
constexpr int NETCDF_MODE_NEW
Tells NetCDF the created file should not overwite a file of the same name.
Definition: YAKL_netcdf.h:29
yakl::componentwise::operator==
Array< decltype(T1()==T2()), N, memHost, STYLE > operator==(Array< T1, N, memHost, STYLE > const &left, T2 const &right)
Definition: YAKL_componentwise.h:352
yakl::SimpleNetCDF::read
void read(T &arr, std::string varName)
Read a single scalar value.
Definition: YAKL_netcdf.h:572