12#include "../dg/blas.h"
13#include "../dg/backend/memory.h"
144 open( filename, mode);
173 std::cerr << e.
what() << std::endl;
191 void open(
const std::filesystem::path& filename,
203 err = nc_open( filename.string().c_str(), NC_NETCDF4 |
204 NC_NOWRITE, &m_ncid);
207 err = nc_open( filename.string().c_str(), NC_NETCDF4 |
211 err = nc_create( filename.string().c_str(), NC_NETCDF4 |
212 NC_NOCLOBBER, &m_ncid);
215 err = nc_create( filename.string().c_str(), NC_NETCDF4 |
216 NC_CLOBBER, &m_ncid);
245 err = nc_close(m_ncid);
257 err = nc_sync( m_ncid);
281 err = nc_def_grp( m_grp, name.c_str(), &new_grp_id);
298 if( not path.has_root_path())
301 path = (current / path);
303 int groupid = m_ncid;
304 auto rel_path = path.relative_path();
306 for(
auto it = rel_path.begin(); it != rel_path.end(); it++)
310 std::wstring string_to_convert = *it;
312 using convert_type = std::codecvt_utf8<wchar_t>;
313 std::wstring_convert<convert_type, wchar_t> converter;
316 std::string grp = converter.to_bytes(string_to_convert);
319 std::string grp = *it;
322 int retval = nc_inq_ncid( groupid, grp.c_str(), &new_grpid);
323 if( retval != NC_NOERR)
324 err = nc_def_grp( groupid, grp.c_str(), &groupid);
336 std::string name = path.generic_string();
337 if( not path.has_root_path())
340 name = (current / path ).generic_string();
343 int retval = nc_inq_grp_full_ncid( m_ncid, name.c_str(), &grpid);
344 return retval == NC_NOERR;
355 void set_grp( std::filesystem::path path =
"")
359 std::string name = path.generic_string();
362 if ( name ==
"" or name ==
"/")
366 else if ( name ==
"..")
370 err = nc_inq_grp_parent( m_grp, &m_grp);
374 if( not path.has_root_path())
377 name = (current / path ).generic_string();
379 err = nc_inq_grp_full_ncid( m_ncid, name.c_str(), &m_grp);
389 err = nc_inq_grp_ncid( m_grp, old_name.c_str(), &old_grp);
390 err = nc_rename_grp( old_grp, new_name.c_str());
400 return get_grp_path( m_grp);
408 auto grps = get_grps_abs(m_grp);
409 std::list<std::filesystem::path> grps_v;
410 for(
auto grp : grps)
411 grps_v.push_back( grp.second);
427 auto grps = get_grps_abs_r(m_grp);
428 std::list<std::filesystem::path> grps_v;
429 for(
auto grp : grps)
430 grps_v.push_back( grp.second);
453 err = nc_def_dim( m_grp, name.c_str(), size, &dim_id);
461 err = nc_inq_dimid( m_grp, old_name.c_str(), &dimid);
462 err = nc_rename_dim( m_grp, dimid, new_name.c_str());
476 err = nc_inq_dimid( m_grp, name.c_str(), &dimid);
478 err = nc_inq_dimlen( m_grp, dimid, &len);
486 std::vector<size_t> shape( dims.size());
487 for(
unsigned u=0; u<dims.size(); u++)
501 std::vector<std::string>
get_dims(
bool include_parents =
true)
const
508 err = nc_inq_dimids( m_grp, &ndims, NULL, include_parents);
511 std::vector<int> dimids(ndims);
512 err = nc_inq_dimids( m_grp, &ndims, &dimids[0], include_parents);
515 std::vector<std::string> dims;
516 for (
int i = 0; i < ndims; i++)
518 char dimname [ NC_MAX_NAME+1];
519 err = nc_inq_dimname( m_grp, dimids[i], dimname);
520 if( std::find(dims.begin(), dims.end(), std::string(dimname) ) ==
522 dims.push_back(dimname);
538 err = nc_inq_unlimdims( m_grp, &ndims, NULL);
541 std::vector<int> dimids(ndims);
544 err = nc_inq_unlimdims( m_grp, &ndims, &dimids[0]);
545 std::vector<std::string> dims;
546 for(
int i=0; i<ndims; i++)
548 char dimname [ NC_MAX_NAME+1];
549 err = nc_inq_dimname( m_grp, dimids[i], dimname);
550 if( std::find(dims.begin(), dims.end(), std::string(dimname) ) ==
552 dims.push_back(dimname);
562 int retval = nc_inq_dimid( m_grp, name.c_str(), &dimid);
563 return retval == NC_NOERR;
573 void put_att(
const std::pair<std::string, nc_att_t>& att, std::string
id =
"")
575 int varid = name2varid(
id);
576 dg::file::detail::put_att( m_grp, varid, att);
588 template<
class S,
class T>
589 void put_att(
const std::tuple<S,nc_type, T>& att, std::string
id =
"")
591 int varid = name2varid(
id);
592 dg::file::detail::put_att( m_grp, varid, att);
608 template<
class Attributes = std::map<std::
string, nc_att_t> >
609 void put_atts(
const Attributes& atts, std::string
id =
"")
611 int varid = name2varid(
id);
612 dg::file::detail::put_atts( m_grp, varid, atts);
629 T
get_att_as(std::string att_name, std::string
id =
"")
const
631 int varid = name2varid(
id);
632 return dg::file::detail::get_att_as<T>( m_grp, varid, att_name);
657 int varid = name2varid(
id);
658 return dg::file::detail::get_atts_as<T>( m_grp, varid);
663 std::map<std::string, nc_att_t>
get_atts( std::string
id =
"")
const
678 void del_att(std::string att_name, std::string
id =
"")
680 int varid = name2varid(
id);
681 auto name = att_name.c_str();
683 err = nc_del_att( m_grp, varid, name);
689 int varid = name2varid(
id);
691 int retval = nc_inq_attid( m_grp, varid, att_name.c_str(), &attid);
692 return retval == NC_NOERR;
697 new_att_name, std::string
id =
"")
699 int varid = name2varid(
id);
700 auto old_name = old_att_name.c_str();
701 auto new_name = new_att_name.c_str();
703 err = nc_rename_att( m_grp, varid, old_name, new_name);
719 template<
class T,
class Attributes = std::map<std::
string, nc_att_t>>
721 const std::vector<std::string>& dim_names,
722 const Attributes& atts = {})
724 def_var( name, detail::getNCDataType<T>(), dim_names, atts);
738 template<
class Attributes = std::map<std::
string, nc_att_t>>
739 void def_var( std::string name, nc_type xtype,
740 const std::vector<std::string>& dim_names,
741 const Attributes& atts = {})
744 std::vector<int> dimids( dim_names.size());
745 for(
unsigned u=0; u<dim_names.size(); u++)
746 err = nc_inq_dimid( m_grp, dim_names[u].c_str(), &dimids[u]);
748 err = nc_def_var( m_grp, name.c_str(), xtype, dim_names.size(),
764 template<
class ContainerType, std::enable_if_t< dg::is_vector_v<
765 ContainerType, SharedVectorTag>,
bool > =
true>
767 const ContainerType& data)
769 int varid = name2varid( name);
772 err = nc_inq_varndims( m_grp, varid, &ndims);
773 assert( (
unsigned)ndims == slab.
ndim());
774 if constexpr ( dg::has_policy_v<ContainerType, dg::CudaTag>)
776 using value_type = dg::get_value_type<ContainerType>;
777 m_buffer.template set<value_type>( data.size());
778 auto& buffer = m_buffer.template get<value_type>( );
779 dg::assign ( data, buffer);
780 err = detail::put_vara_T( m_grp, varid, slab.
startp(), slab.
countp(),
784 err = detail::put_vara_T( m_grp, varid, slab.
startp(), slab.
countp(),
785 thrust::raw_pointer_cast(data.data()));
799 template<
class ContainerType,
class Attributes = std::map<std::
string, nc_att_t>,
800 std::enable_if_t< dg::is_vector_v<ContainerType, SharedVectorTag>,
bool > = true>
801 void defput_var( std::string name,
const std::vector<std::string>& dim_names,
803 const ContainerType& data)
820 template<
class T, std::enable_if_t< dg::is_scalar_v<T>,
bool> = true>
821 void put_var( std::string name,
const std::vector<size_t>& start, T data)
823 int varid = name2varid( name);
825 std::vector<size_t> count( start.size(), 1);
826 err = detail::put_vara_T( m_grp, varid, &start[0], &count[0], &data);
847 template<
class T,
class Attributes = std::map<std::
string, nc_att_t>>
870 template<
class ContainerType,
class Attributes = std::map<std::
string, nc_att_t>>
872 const Attributes& atts,
873 const ContainerType& abscissas)
876 abscissas.size(), atts);
877 put_var( name, {abscissas}, abscissas);
889 template<
class ContainerType, std::enable_if_t< dg::is_vector_v<
890 ContainerType, SharedVectorTag>,
bool > =
true>
892 ContainerType& data)
const
894 int varid = name2varid( name);
897 err = nc_inq_varndims( m_grp, varid, &ndims);
898 assert( (
unsigned)ndims == slab.
ndim());
900 for(
unsigned u=0; u<slab.
ndim(); u++)
901 size *= slab.
count()[u];
902 if constexpr ( dg::has_policy_v<ContainerType, dg::CudaTag>)
904 using value_type = dg::get_value_type<ContainerType>;
905 m_buffer.template set<value_type>( size);
906 auto& buffer = m_buffer.template get<value_type>( );
907 err = detail::get_vara_T( m_grp, varid, slab.
startp(), slab.
countp(),
909 dg::assign ( buffer, data);
914 err = detail::get_vara_T( m_grp, varid, slab.
startp(), slab.
countp(),
915 thrust::raw_pointer_cast(data.data()));
927 template<
class T, std::enable_if_t< dg::is_scalar_v<T>,
bool> = true>
928 void get_var( std::string name,
const std::vector<size_t>& start, T& data)
const
930 int varid = name2varid( name);
933 err = nc_inq_varndims( m_grp, varid, &ndims);
934 assert( (
unsigned)ndims == start.size());
936 err = detail::get_vara_T( m_grp, varid, NULL, NULL, &data);
939 std::vector<size_t> count( start.size(), 1);
940 err = detail::get_vara_T( m_grp, varid, &start[0], &count[0], &data);
950 int retval = nc_inq_varid( m_grp, name.c_str(), &varid);
951 return retval == NC_NOERR;
958 int varid = name2varid( name);
961 err = nc_inq_vartype( m_grp, varid, &xtype);
973 int varid = name2varid( name);
977 err = nc_inq_varndims( m_grp, varid, &ndims);
980 std::vector<int> dimids(ndims);
981 err = nc_inq_vardimid( m_grp, varid, &dimids[0]);
983 std::vector<std::string> dims(ndims);
984 for(
int i=0; i<ndims; i++)
986 char dimname [ NC_MAX_NAME+1];
987 err = nc_inq_dimname( m_grp, dimids[i], dimname);
1005 return get_var_names_private( m_grp);
1009 int name2varid( std::string
id)
const
1021 err = nc_inq_varid( m_grp,
id.c_str(), &varid);
1027 std::filesystem::path get_grp_path(
int ncid )
const
1030 NC_Error_Handle err;
1031 err = nc_inq_grpname_full( ncid, &len, NULL);
1032 std::string current( len,
'x');
1033 err = nc_inq_grpname_full( ncid, &len, ¤t[0]);
1037 std::map<int, std::filesystem::path> get_grps_abs(
int ncid )
const
1039 NC_Error_Handle err;
1041 err = nc_inq_grps( ncid, &num_grps, NULL);
1044 std::vector<int> group_ids( num_grps);
1045 err = nc_inq_grps( ncid, &num_grps, &group_ids[0]);
1046 std::map<int, std::filesystem::path> groups;
1047 for(
int i=0; i<num_grps; i++)
1050 err = nc_inq_grpname_full( group_ids[i], &len, NULL);
1051 std::string name( len,
'z');
1052 err = nc_inq_grpname_full( group_ids[i], &len, &name[0]);
1053 groups[group_ids[i]] = name;
1057 std::map<int, std::filesystem::path> get_grps_abs_r(
int ncid)
const
1059 auto grps = get_grps_abs(ncid);
1060 for(
auto grp : grps)
1062 auto subgrps = get_grps_abs_r( grp.first);
1063 grps.merge( subgrps);
1068 std::list<std::string> get_var_names_private(
int grpid)
const
1070 std::list<std::string> vars;
1071 int num_vars = 0, num_dims;
1072 file::NC_Error_Handle err;
1073 err = nc_inq(grpid, &num_dims, &num_vars, NULL, NULL);
1075 for(
int i=0; i<num_vars; i++)
1077 char name[NC_MAX_NAME+1];
1078 err = nc_inq_varname( grpid, i, name);
1079 vars.push_back( name);
1085 void check_open()
const
1088 throw NC_Error( 1000);
1091 bool m_open =
false;
1099 mutable dg::detail::AnyVector<thrust::host_vector> m_buffer;
1112using NcFile = SerialNcFile;
MPINcFile NcFile
Definition nc_mpi_file.h:693
NcFileMode
NetCDF file format.
Definition nc_file.h:95
@ nc_clobber
NC_CLOBBER Create a new file for read and write access, overwrite if file exists.
Definition nc_file.h:98
@ nc_nowrite
NC_NOWRITE Open an existing file for read-only access, fail if it does not exist.
Definition nc_file.h:96
@ nc_write
NC_WRITE Open an existing file for read and write access, fail if it does not exist.
Definition nc_file.h:97
@ nc_noclobber
NC_NOCLOBBER Create new file for read and write access, fail if already exists.
Definition nc_file.h:99
Definition easy_atts.h:15
DEPRECATED Empty utitlity class that handles return values of netcdf functions and throws NC_Error(st...
Definition nc_error.h:70
Class thrown by the NC_Error_Handle.
Definition nc_error.h:20
char const * what() const noexcept
What string.
Definition nc_error.h:35
A NetCDF Hyperslab for SerialNcFile.
Definition nc_hyperslab.h:27
const size_t * countp() const
Definition nc_hyperslab.h:134
const std::vector< size_t > & count() const
Definition nc_hyperslab.h:126
const size_t * startp() const
Definition nc_hyperslab.h:132
unsigned ndim() const
Definition nc_hyperslab.h:121
Serial NetCDF-4 file.
Definition nc_file.h:123
T get_att_as(std::string att_name, std::string id="") const
Get an attribute named att_name of the group or variable id.
Definition nc_file.h:629
void sync()
Call nc_sync.
Definition nc_file.h:253
void get_var(std::string name, const std::vector< size_t > &start, T &data) const
Read scalar from position start from variable named name.
Definition nc_file.h:928
std::vector< std::string > get_var_dims(std::string name) const
Get the dimension names associated to variable name.
Definition nc_file.h:971
void def_grp(std::string name)
Definition nc_file.h:276
void defput_var(std::string name, const std::vector< std::string > &dim_names, const Attributes &atts, const NcHyperslab &slab, const ContainerType &data)
Define and put a variable in one go.
Definition nc_file.h:801
void put_att(const std::tuple< S, nc_type, T > &att, std::string id="")
Put an individual attribute of preset type to variable id.
Definition nc_file.h:589
void put_att(const std::pair< std::string, nc_att_t > &att, std::string id="")
Put an individual attribute.
Definition nc_file.h:573
void del_att(std::string att_name, std::string id="")
Remove an attribute named att_name from variable id.
Definition nc_file.h:678
SerialNcFile(SerialNcFile &&rhs)=default
Swap resources between two file handles.
std::vector< size_t > get_dims_shape(const std::vector< std::string > &dims) const
Get the size of each dimension in dims.
Definition nc_file.h:484
void rename_dim(std::string old_name, std::string new_name)
Rename a dimension from old_name to new_name.
Definition nc_file.h:456
void rename_att(std::string old_att_name, std::string new_att_name, std::string id="")
Definition nc_file.h:696
std::list< std::filesystem::path > get_grps_r() const
Get all subgroups recursively in the current group as absolute paths.
Definition nc_file.h:425
SerialNcFile(const SerialNcFile &rhs)=delete
There can only be exactly one file handle per physical file.
bool var_is_defined(std::string name) const
Definition nc_file.h:946
std::list< std::string > get_var_names() const
Get a list of variable names in the current group.
Definition nc_file.h:1002
void put_atts(const Attributes &atts, std::string id="")
Write a collection of attributes to a NetCDF variable or file.
Definition nc_file.h:609
nc_type get_var_type(std::string name) const
Definition nc_file.h:956
std::map< std::string, nc_att_t > get_atts(std::string id="") const
Definition nc_file.h:663
bool is_open() const noexcept
Definition nc_file.h:224
void def_var(std::string name, nc_type xtype, const std::vector< std::string > &dim_names, const Attributes &atts={})
Define a variable with given type, dimensions and (optionally) attributes.
Definition nc_file.h:739
void def_grp_p(std::filesystem::path path)
Definition nc_file.h:295
void defput_dim(std::string name, const Attributes &atts, const ContainerType &abscissas)
Define a dimension and define and write to a dimension variable in one go.
Definition nc_file.h:871
void set_grp(std::filesystem::path path="")
Change group to path.
Definition nc_file.h:355
std::filesystem::path get_current_path() const
Get the absolute path of the current group.
Definition nc_file.h:397
bool dim_is_defined(std::string name) const
Definition nc_file.h:559
void def_dim(std::string name, size_t size)
Define a dimension named name of size size.
Definition nc_file.h:448
void get_var(std::string name, const NcHyperslab &slab, ContainerType &data) const
Read hyperslab slab from variable named name into container data.
Definition nc_file.h:891
~SerialNcFile()
Close open nc file and release all resources.
Definition nc_file.h:165
std::vector< T > get_att_vec_as(std::string att_name, std::string id="") const
Short for get_att_as<std::vector<T>>( id, att_name);
Definition nc_file.h:637
int get_grpid() const noexcept
Get the NetCDF-C ID of the current group.
Definition nc_file.h:394
SerialNcFile(const std::filesystem::path &filename, enum NcFileMode mode=nc_nowrite)
Open/Create a netCDF file.
Definition nc_file.h:141
void put_var(std::string name, const std::vector< size_t > &start, T data)
Write a single data point.
Definition nc_file.h:821
void close()
Explicitly close a file.
Definition nc_file.h:239
SerialNcFile & operator=(const SerialNcFile &rhs)=delete
There can only be exactly one file handle per physical file.
bool grp_is_defined(std::filesystem::path path) const
Check for existence of the group given by path.
Definition nc_file.h:333
bool att_is_defined(std::string att_name, std::string id="") const
Definition nc_file.h:687
std::vector< std::string > get_unlim_dims() const
Definition nc_file.h:533
void put_var(std::string name, const NcHyperslab &slab, const ContainerType &data)
Write data to a variable.
Definition nc_file.h:766
std::vector< std::string > get_dims(bool include_parents=true) const
Definition nc_file.h:501
void def_dimvar_as(std::string name, size_t size, const Attributes &atts)
Define a dimension and dimension variable in one go.
Definition nc_file.h:848
int get_ncid() const noexcept
Get the ncid of the underlying NetCDF C-API.
Definition nc_file.h:265
size_t get_dim_size(std::string name) const
Get the size of the dimension named name.
Definition nc_file.h:471
void def_var_as(std::string name, const std::vector< std::string > &dim_names, const Attributes &atts={})
Define a variable with given type, dimensions and (optionally) attributes.
Definition nc_file.h:720
std::map< std::string, T > get_atts_as(std::string id="") const
Read all NetCDF attributes of a certain type.
Definition nc_file.h:655
std::list< std::filesystem::path > get_grps() const
Definition nc_file.h:405
void rename_grp(std::string old_name, std::string new_name)
Definition nc_file.h:384
void open(const std::filesystem::path &filename, enum NcFileMode mode=nc_nowrite)
Definition nc_file.h:191