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));
54 NcDim(std::string name,
size_t len,
int id,
bool is_unlim) {
58 this->is_unlim = is_unlim;
64 this->is_unlim = in.is_unlim;
66 NcDim(NcDim
const &in) {
70 this->is_unlim = in.is_unlim;
72 NcDim &operator=(NcDim &&in) {
76 this->is_unlim = in.is_unlim;
79 NcDim &operator=(NcDim
const &in) {
83 this->is_unlim = in.is_unlim;
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; }
101 std::vector<NcDim> dims;
107 dims = std::vector<NcDim>(0);
112 NcVar(
int ncid , std::string name, std::vector<NcDim> dims,
int id,
int type) {
120 this->ncid = in.ncid;
121 this->name = in.name;
122 this->dims = in.dims;
124 this->type = in.type;
126 NcVar(NcVar
const &in) {
127 this->ncid = in.ncid;
128 this->name = in.name;
129 this->dims = in.dims;
131 this->type = in.type;
133 NcVar &operator=(NcVar &&in) {
134 this->ncid = in.ncid;
135 this->name = in.name;
136 this->dims = in.dims;
138 this->type = in.type;
141 NcVar &operator=(NcVar
const &in) {
142 this->ncid = in.ncid;
143 this->name = in.name;
144 this->dims = in.dims;
146 this->type = in.type;
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) {
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"); }
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"); }
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."); }
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";
224 NcFile() { ncid = -999; }
226 NcFile(
int ncid) { this->ncid = ncid; }
227 NcFile(NcFile &&in) {
228 this->ncid = in.ncid;
230 NcFile(NcFile
const &in) {
231 this->ncid = in.ncid;
233 NcFile &operator=(NcFile &&in) {
234 this->ncid = in.ncid;
237 NcFile &operator=(NcFile
const &in) {
238 this->ncid = in.ncid;
242 bool isNull() {
return ncid == -999; }
244 void open( std::string fname ,
int mode ) {
247 yakl_throw(
"ERROR: open mode can be NETCDF_MODE_READ or NETCDF_MODE_WRITE");
249 ncwrap( nc_open( fname.c_str() , mode , &ncid ) , __LINE__ );
252 void create( std::string fname ,
int mode ) {
255 yakl_throw(
"ERROR: open mode can be NETCDF_MODE_NEW or NETCDF_MODE_REPLACE");
257 ncwrap( nc_create( fname.c_str() , mode | NC_NETCDF4 , &ncid ) , __LINE__ );
261 if (ncid != -999) ncwrap( nc_close( ncid ) , __LINE__ );
265 NcVar getVar( std::string varName )
const {
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];
272 int dimids[NC_MAX_VAR_DIMS];
275 ncwrap( nc_inq_var(ncid , varid , vname , &type , &ndims , dimids , &natts ) , __LINE__ );
277 std::vector<NcDim> dims(ndims);
278 for (
int i=0; i < ndims; i++) {
279 dims[i] = getDim( dimids[i] );
281 return NcVar( ncid , varName , dims , varid , type );
284 NcDim getDim( std::string dimName )
const {
286 int ierr = nc_inq_dimid( ncid , dimName.c_str() , &dimid);
287 if (ierr != NC_NOERR)
return NcDim();
288 return getDim( dimid );
291 NcDim getDim(
int dimid )
const {
292 char dname[NC_MAX_NAME+1];
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 );
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(); }
304 ncwrap( nc_def_var(ncid , varName.c_str() , type , dims.size() , dimids.data() , &varid) , __LINE__ );
305 return NcVar( ncid , varName , dims , varid , type );
308 NcVar addVar( std::string varName ,
int type ) {
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 );
315 NcDim addDim( std::string dimName ,
size_t len ) {
317 ncwrap( nc_def_dim(ncid , dimName.c_str() , len , &dimid ) , __LINE__ );
318 return NcDim( dimName , len , dimid ,
false );
321 NcDim addDim( std::string dimName ) {
323 ncwrap( nc_def_dim(ncid , dimName.c_str() , NC_UNLIMITED , &dimid ) , __LINE__ );
324 return NcDim( dimName , 0 , dimid ,
true );
348 void create(std::string fname ,
int mode = NC_CLOBBER) { file.create(fname,mode); }
356 bool varExists( std::string varName )
const {
return ! file.getVar(varName).isNull(); }
360 bool dimExists( std::string dimName )
const {
return ! file.getDim(dimName).isNull(); }
364 size_t getDimSize( std::string dimName )
const {
return file.getDim(dimName).getSize(); }
368 void createDim( std::string dimName ,
size_t len ) { file.addDim( dimName , len ); }
371 void createDim( std::string dimName ) { file.addDim( dimName ); }
375 template <
class T,
int rank,
int myMem,
int myStyle>
377 if (rank != dimNames.size()) {
yakl_throw(
"dimNames.size() != Array's rank"); }
378 std::vector<NcDim> dims(rank);
380 for (
int i=0; i<rank; i++) {
381 auto dimLoc = file.getDim( dimNames[i] );
384 if ( dimLoc.isNull() ) {
385 tmp = file.addDim( dimNames[i] , arr.extent(i) );
387 if (dimLoc.getSize() != arr.extent(i)) {
388 yakl_throw(
"dimension size differs from the file");
395 dims[rank-1-i] = tmp;
399 auto var = file.getVar(varName);
400 if ( var.isNull() ) {
401 var = file.addVar( varName , getType<T>() , dims );
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++) {
408 if (varDims[i].getSize() != arr.extent(i)) {
409 yakl_throw(
"Existing variable's dimension sizes are not the same as the array's");
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");
420 var.putVar(arr.createHostCopy().data());
422 var.putVar(arr.data());
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" ) {
431 auto ulDim = file.getDim( ulDimName );
432 if ( ulDim.isNull() ) {
433 ulDim = file.addDim( ulDimName );
436 auto var = file.getVar(varName);
437 if ( var.isNull() ) {
438 std::vector<NcDim> dims(1);
440 var = file.addVar( varName , getType<T>() , dims );
442 std::vector<size_t> start(1);
443 std::vector<size_t>
count(1);
446 var.putVar(start,
count,&val);
451 template <
class T,
int rank,
int myMem,
int myStyle>
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);
457 dims[0] = file.getDim( ulDimName );
458 if ( dims[0].isNull() ) {
459 dims[0] = file.addDim( ulDimName );
462 for (
int i=0; i<rank; i++) {
463 auto dimLoc = file.getDim( dimNames[i] );
466 if ( dimLoc.isNull() ) {
467 tmp = file.addDim( dimNames[i] , arr.extent(i) );
469 if (dimLoc.getSize() != arr.extent(i)) {
470 yakl_throw(
"dimension size differs from the file");
477 dims[1+rank-1-i] = tmp;
481 auto var = file.getVar(varName);
482 if ( var.isNull() ) {
483 var = file.addVar( varName , getType<T>() , dims );
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");
490 for (
int i=1; i < varDims.size(); i++) {
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");
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");
503 std::vector<size_t> start(rank+1);
504 std::vector<size_t>
count(rank+1);
507 for (
int i=1; i < rank+1; i++) {
509 count[i] = dims[i].getSize();
512 var.putVar(start,
count,arr.createHostCopy().data());
514 var.putVar(start,
count,arr.data());
520 template <
class T,
int rank,
int myMem,
int myStyle>
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"); }
529 for (
int i=0; i < varDims.size(); i++) { dimSizes[i] = varDims[i].getSize(); }
531 for (
int i=0; i < varDims.size(); i++) { dimSizes[i] = varDims[varDims.size()-1-i].getSize(); }
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)) {
538 std::cout <<
"WARNING: Array dims wrong size; deallocating previous array and allocating a new one\n";
545 }
else {
yakl_throw(
"Variable does not exist"); }
548 auto arrHost = arr.createHostCopy();
549 if (std::is_same<T,bool>::value) {
551 var.getVar(tmp.data());
552 for (
int i=0; i < arr.totElems(); i++) { arrHost.data()[i] = tmp.data()[i] == 1; }
554 var.getVar(arrHost.data());
556 arrHost.deep_copy_to(arr);
559 if (std::is_same<T,bool>::value) {
561 var.getVar(tmp.data());
562 for (
int i=0; i < arr.totElems(); i++) { arr.data()[i] = tmp.data()[i] == 1; }
564 var.getVar(arr.data());
572 void read(T &arr , std::string varName) {
573 auto var = file.getVar(varName);
574 if ( var.isNull() ) {
yakl_throw(
"Variable does not exist"); }
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>() );
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; }