27 #include "pism/util/io/ParallelIO.hh"
29 #include "pism/util/error_handling.hh"
30 #include "pism/util/io/pism_type_conversion.hh"
31 #include "pism/util/Grid.hh"
32 #include "pism/util/io/File.hh"
38 char message[PIO_MAX_NAME + 1];
39 if (return_code != PIO_NOERR) {
40 PIOc_strerror(return_code, message);
46 if (PIOc_iotype_available(PIO_IOTYPE_PNETCDF) and netcdf3) {
49 if (PIOc_iotype_available(PIO_IOTYPE_NETCDF4P)) {
52 if (PIOc_iotype_available(PIO_IOTYPE_NETCDF4C)) {
61 :
NCFile(com), m_iosysid(iosysid) {
62 assert(iosysid != -1);
96 int mode = NC_CLOBBER;
97 if (
m_iotype == PIO_IOTYPE_PNETCDF) {
98 mode |= NC_64BIT_DATA;
130 int stat = PIOc_def_dim(
m_file_id, name.c_str(), length, &dim_id);
137 int stat = PIOc_inq_dimid(
m_file_id, dimension_name.c_str(), &tmp);
139 if (stat == PIO_NOERR) {
147 int stat, dimid = -1;
150 stat = PIOc_inq_dimid(
m_file_id, dimension_name.c_str(), &dimid);
153 stat = PIOc_inq_dimlen(
m_file_id, dimid, &len);
156 result =
static_cast<unsigned int>(len);
160 int stat = PIO_NOERR, dimid = -1;
161 char dimname[PIO_MAX_NAME + 1];
163 stat = PIOc_inq_unlimdim(
m_file_id, &dimid);
169 stat = PIOc_inq_dimname(
m_file_id, dimid, dimname);
178 const std::vector<std::string> &dims)
const {
179 std::vector<int> dimids;
182 for (
auto d : dims) {
184 stat = PIOc_inq_dimid(
m_file_id, d.c_str(), &dimid);
186 dimids.push_back(dimid);
190 static_cast<int>(dims.size()), dimids.data(), &varid);
195 std::vector<size_t> &dimensions)
const {
202 const std::vector<unsigned int> &start,
203 const std::vector<unsigned int> &
count,
double *input)
const {
204 int stat, varid, ndims =
static_cast<int>(start.size());
206 std::vector<PIO_Offset> nc_start(ndims), nc_count(ndims);
208 stat = PIOc_inq_varid(
m_file_id, variable_name.c_str(), &varid);
211 for (
int j = 0; j < ndims; ++j) {
212 nc_start[j] = start[j];
213 nc_count[j] =
count[j];
216 stat = PIOc_get_vara_double(
m_file_id, varid, nc_start.data(), nc_count.data(), input);
221 const std::vector<unsigned int> &start,
222 const std::vector<unsigned int> &
count,
223 const double *output)
const {
224 int stat, varid, ndims =
static_cast<int>(start.size());
226 std::vector<PIO_Offset> nc_start(ndims), nc_count(ndims);
228 stat = PIOc_inq_varid(
m_file_id, variable_name.c_str(), &varid);
231 for (
int j = 0; j < ndims; ++j) {
232 nc_start[j] = start[j];
233 nc_count[j] =
count[j];
236 stat = PIOc_put_vara_double(
m_file_id, varid, nc_start.data(), nc_count.data(), output);
240 template <
typename T>
242 std::vector<T> buffer(length);
243 for (
size_t k = 0;
k < length; ++
k) {
244 buffer[
k] =
static_cast<T
>(input[
k]);
250 unsigned int z_count,
bool time_dependent,
unsigned int record,
251 const double *input) {
252 (void)time_dependent;
256 stat = PIOc_inq_varid(
m_file_id, variable_name.c_str(), &varid);
260 stat = PIOc_inq_vartype(
m_file_id, varid, &type);
264 size_t length = grid.
xm() * grid.
ym() * z_count;
269 stat = PIOc_put_vard_double(
m_file_id, varid, decompid, (PIO_Offset)record, input);
273 auto buffer = convert_data<float>(input, length);
274 stat = PIOc_put_vard_float(
m_file_id, varid, decompid, (PIO_Offset)record, buffer.data());
279 auto buffer = convert_data<int>(input, length);
280 stat = PIOc_put_vard_int(
m_file_id, varid, decompid, (PIO_Offset)record, buffer.data());
286 "ParallelIO: type conversion is not supported");
292 const std::vector<unsigned int> &start,
293 const std::vector<unsigned int> &
count,
294 const std::vector<unsigned int> &imap,
double *input)
const {
301 "ParallelIO does not support transposed access");
305 int stat = PIOc_inq_nvars(
m_file_id, &result);
310 std::vector<std::string> &result)
const {
311 int stat, ndims, varid = -1;
312 std::vector<int> dimids;
314 stat = PIOc_inq_varid(
m_file_id, variable_name.c_str(), &varid);
317 stat = PIOc_inq_varndims(
m_file_id, varid, &ndims);
325 result.resize(ndims);
326 dimids.resize(ndims);
328 stat = PIOc_inq_vardimid(
m_file_id, varid, dimids.data());
331 for (
int k = 0;
k < ndims; ++
k) {
332 char name[PIO_MAX_NAME];
333 memset(name, 0, PIO_MAX_NAME);
335 stat = PIOc_inq_dimname(
m_file_id, dimids[
k], name);
345 int stat = PIO_NOERR;
346 if (varid == PIO_GLOBAL) {
347 stat = PIOc_inq_natts(
m_file_id, &result);
349 stat = PIOc_inq_varnatts(
m_file_id, varid, &result);
357 stat = PIOc_inq_varid(
m_file_id, variable_name.c_str(), &flag);
359 exists = (stat == PIO_NOERR);
364 char varname[PIO_MAX_NAME];
365 memset(varname, 0, PIO_MAX_NAME);
367 stat = PIOc_inq_varname(
m_file_id, j, varname);
375 std::vector<double> &result)
const {
379 PIO_Offset attlen = 0;
380 int stat = PIOc_inq_attlen(
m_file_id, varid, att_name.c_str(), &attlen);
383 if (stat == NC_NOERR) {
384 len =
static_cast<int>(attlen);
385 }
else if (stat == NC_ENOTATT) {
398 stat = PIOc_get_att_double(
m_file_id, varid, att_name.c_str(), result.data());
403 std::string &result)
const {
408 int stat = PIOc_inq_attlen(
m_file_id, varid, att_name.c_str(), &attlen);
411 if (stat == NC_NOERR) {
412 len =
static_cast<int>(attlen);
424 std::vector<char> str(len + 1, 0);
425 stat = PIOc_get_att_text(
m_file_id, varid, att_name.c_str(), str.data());
432 io::Type xtype,
const std::vector<double> &data)
const {
439 const std::string &value)
const {
440 int stat = PIOc_put_att_text(
m_file_id,
get_varid(variable_name), att_name.c_str(), value.size(),
446 std::string &result)
const {
447 std::vector<char> name(PIO_MAX_NAME + 1, 0);
452 result = name.data();
458 int stat = PIOc_inq_atttype(
m_file_id,
get_varid(variable_name), att_name.c_str(), &tmp);
459 if (stat == PIO_ENOTATT) {
471 int stat = PIOc_set_fill(
m_file_id, fillmode, &old_modep);
481 if (variable_name ==
"PISM_GLOBAL") {
486 int stat = PIOc_inq_varid(
m_file_id, variable_name.c_str(), &varid);
int pio_io_decomposition(int dof, int output_datatype) const
int xm() const
Width of this processor's sub-domain.
int ym() const
Width of this processor's sub-domain.
Describes the PISM grid and the distribution of data across processors.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
std::string filename() const
The PISM wrapper for a subset of the NetCDF C API.
void inq_varid_impl(const std::string &variable_name, bool &exists) const
ParallelIO(MPI_Comm com, int iosysid, io::Backend iotype)
void inq_dimlen_impl(const std::string &dimension_name, unsigned int &result) const
void get_vara_double_impl(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, double *ip) const
void del_att_impl(const std::string &variable_name, const std::string &att_name) const
void inq_varnatts_impl(const std::string &variable_name, int &result) const
void set_fill_impl(int fillmode, int &old_modep) const
void put_att_text_impl(const std::string &variable_name, const std::string &att_name, const std::string &value) const
void def_var_impl(const std::string &name, io::Type nctype, const std::vector< std::string > &dims) const
void inq_nvars_impl(int &result) const
void open_impl(const std::string &filename, io::Mode mode)
static io::Backend best_iotype(bool netcdf3)
void put_att_double_impl(const std::string &variable_name, const std::string &att_name, io::Type xtype, const std::vector< double > &data) const
void create_impl(const std::string &filename)
void get_att_double_impl(const std::string &variable_name, const std::string &att_name, std::vector< double > &result) const
void inq_dimid_impl(const std::string &dimension_name, bool &exists) const
void set_compression_level_impl(int level) const
void def_dim_impl(const std::string &name, size_t length) const
void get_att_text_impl(const std::string &variable_name, const std::string &att_name, std::string &result) const
int get_varid(const std::string &variable_name) const
void def_var_chunking_impl(const std::string &name, std::vector< size_t > &dimensions) const
void write_darray_impl(const std::string &variable_name, const Grid &grid, unsigned int z_count, bool time_dependent, unsigned int record, const double *input)
void put_vara_double_impl(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const double *op) const
void inq_attname_impl(const std::string &variable_name, unsigned int n, std::string &result) const
void get_varm_double_impl(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::vector< unsigned int > &imap, double *ip) const
void inq_atttype_impl(const std::string &variable_name, const std::string &att_name, io::Type &result) const
void inq_vardimid_impl(const std::string &variable_name, std::vector< std::string > &result) const
void inq_varname_impl(unsigned int j, std::string &result) const
void inq_unlimdim_impl(std::string &result) const
#define PISM_ERROR_LOCATION
@ PISM_READONLY
open an existing file for reading only
static void check(const ErrorLocation &where, int return_code)
Prints an error message; for debugging.
std::vector< T > convert_data(const double *input, size_t length)
static pism::io::Type nc_type_to_pism_type(int input)
static nc_type pism_type_to_nc_type(pism::io::Type input)