/*----< test_attr_types() >---------------------------------------------------*/ static int test_attr_types(char *filename, int format) { int i, err, rank, ncid, cmode, nerrs=0, attr=0; MPI_Info info=MPI_INFO_NULL; MPI_Comm comm=MPI_COMM_WORLD; nc_type xtype[5]={NC_UBYTE, NC_USHORT, NC_UINT, NC_INT64, NC_UINT64}; MPI_Comm_rank(comm, &rank); cmode = NC_CLOBBER|format; /* create a file in CDF-1 or CDF-2 format */ err = ncmpi_create(comm, filename, cmode, info, &ncid); ERR for (i=0; i<5; i++) { char name[32]; sprintf(name, "gattr_%d", i); err = ncmpi_put_att_int(ncid, NC_GLOBAL, name, xtype[i], 1, &attr); if (err != NC_ESTRICTCDF2) { printf("Error (line=%d): expecting NC_ESTRICTCDF2 but got %s\n", __LINE__,nc_err_code_name(err)); nerrs++; } } err = ncmpi_close(ncid); ERR return nerrs; }
int main(int argc, char **argv) { int i, j; int status; int ncid1, ncid2; int ndims, nvars, ngatts, unlimdimid; char name[NC_MAX_NAME]; nc_type type, vartypes[NC_MAX_VARS]; MPI_Offset attlen; MPI_Offset dimlen, shape[NC_MAX_VAR_DIMS], varsize, start[NC_MAX_VAR_DIMS]; void *valuep; int dimids[NC_MAX_DIMS], varids[NC_MAX_VARS]; int vardims[NC_MAX_VARS][NC_MAX_VAR_DIMS/16]; /* divided by 16 due to my memory limitation */ int varndims[NC_MAX_VARS], varnatts[NC_MAX_VARS]; params opts; int rank; int nprocs; MPI_Comm comm = MPI_COMM_WORLD; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank == 0) fprintf(stderr, "Testing independent read ... "); parse_read_args(argc, argv, rank, &opts); /********** START OF NETCDF ACCESS **************/ /* Read a netCDF file and write it out to another file */ /** * Open the input dataset - ncid1: * File name: "../data/test_int.nc" * Dataset API: Collective * And create the output dataset - ncid2: * File name: "testread.nc" * Dataset API: Collective */ status = ncmpi_open(comm, opts.infname, 0, MPI_INFO_NULL, &ncid1); if (status != NC_NOERR) handle_error(status); status = ncmpi_create(comm, opts.outfname, NC_CLOBBER, MPI_INFO_NULL, &ncid2); if (status != NC_NOERR) handle_error(status); /** * Inquire the dataset definitions of input dataset AND * Add dataset definitions for output dataset. */ status = ncmpi_inq(ncid1, &ndims, &nvars, &ngatts, &unlimdimid); if (status != NC_NOERR) handle_error(status); /* Inquire global attributes, assume CHAR attributes. */ for (i = 0; i < ngatts; i++) { status = ncmpi_inq_attname(ncid1, NC_GLOBAL, i, name); if (status != NC_NOERR) handle_error(status); status = ncmpi_inq_att (ncid1, NC_GLOBAL, name, &type, &attlen); if (status != NC_NOERR) handle_error(status); switch (type) { case NC_CHAR: valuep = (void *)malloc(attlen * sizeof(char)); status = ncmpi_get_att_text(ncid1, NC_GLOBAL, name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_text (ncid2, NC_GLOBAL, name, attlen, (char *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_SHORT: valuep = (void *)malloc(attlen * sizeof(short)); status = ncmpi_get_att_short(ncid1, NC_GLOBAL, name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_short (ncid2, NC_GLOBAL, name, type, attlen, (short *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_INT: valuep = (void *)malloc(attlen * sizeof(int)); status = ncmpi_get_att_int(ncid1, NC_GLOBAL, name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_int (ncid2, NC_GLOBAL, name, type, attlen, (int *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_FLOAT: valuep = (void *)malloc(attlen * sizeof(float)); status = ncmpi_get_att_float(ncid1, NC_GLOBAL, name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_float (ncid2, NC_GLOBAL, name, type, attlen, (float *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_DOUBLE: valuep = (void *)malloc(attlen * sizeof(double)); status = ncmpi_get_att_double(ncid1, NC_GLOBAL, name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_double (ncid2, NC_GLOBAL, name, type, attlen, (double *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; default: ; /* handle unexpected types */ } } /* Inquire dimension */ for (i = 0; i < ndims; i++) { status = ncmpi_inq_dim(ncid1, i, name, &dimlen); if (status != NC_NOERR) handle_error(status); if (i == unlimdimid) dimlen = NC_UNLIMITED; status = ncmpi_def_dim(ncid2, name, dimlen, dimids+i); if (status != NC_NOERR) handle_error(status); } /* Inquire variables */ for (i = 0; i < nvars; i++) { status = ncmpi_inq_var (ncid1, i, name, vartypes+i, varndims+i, vardims[i], varnatts+i); if (status != NC_NOERR) handle_error(status); status = ncmpi_def_var(ncid2, name, vartypes[i], varndims[i], vardims[i], varids+i); if (status != NC_NOERR) handle_error(status); /* var attributes, assume CHAR attributes */ for (j = 0; j < varnatts[i]; j++) { status = ncmpi_inq_attname(ncid1, varids[i], j, name); if (status != NC_NOERR) handle_error(status); status = ncmpi_inq_att (ncid1, varids[i], name, &type, &attlen); if (status != NC_NOERR) handle_error(status); switch (type) { case NC_CHAR: valuep = (void *)malloc(attlen * sizeof(char)); status = ncmpi_get_att_text(ncid1, varids[i], name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_text (ncid2, varids[i], name, attlen, (char *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_SHORT: valuep = (void *)malloc(attlen * sizeof(short)); status = ncmpi_get_att_short(ncid1, varids[i], name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_short (ncid2, varids[i], name, type, attlen, (short *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_INT: valuep = (void *)malloc(attlen * sizeof(int)); status = ncmpi_get_att_int(ncid1, varids[i], name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_int (ncid2, varids[i], name, type, attlen, (int *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_FLOAT: valuep = (void *)malloc(attlen * sizeof(float)); status = ncmpi_get_att_float(ncid1, varids[i], name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_float (ncid2, varids[i], name, type, attlen, (float *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_DOUBLE: valuep = (void *)malloc(attlen * sizeof(double)); status = ncmpi_get_att_double(ncid1, varids[i], name, valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_att_double (ncid2, varids[i], name, type, attlen, (double *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; default: ; /* handle unexpected types */ } } } /** * End Define Mode (switch to data mode) for output dataset * Dataset API: Collective */ status = ncmpi_enddef(ncid2); if (status != NC_NOERR) handle_error(status); /** * Read data of variables from input dataset (assume INT variables) * Write the data out to the corresponding variables in the output dataset * * Data Partition (Assume 4 processors): * square: 2-D, (Block, *), 25*100 from 100*100 * cube: 3-D, (Block, *, *), 25*100*100 from 100*100*100 * xytime: 3-D, (Block, *, *), 25*100*100 from 100*100*100 * time: 1-D, Block-wise, 25 from 100 * * Data Mode API: non-collective */ status = ncmpi_begin_indep_data(ncid1); if (status != NC_NOERR) handle_error(status); status =ncmpi_begin_indep_data(ncid2); if (status != NC_NOERR) handle_error(status); for (i = 0; i < NC_MAX_VAR_DIMS; i++) start[i] = 0; for (i = 0; i < nvars; i++) { varsize = 1; for (j = 0; j < varndims[i]; j++) { status = ncmpi_inq_dim(ncid1, vardims[i][j], name, shape + j); if (status != NC_NOERR) handle_error(status); if (j == 0) { shape[j] /= nprocs; start[j] = shape[j] * rank; } varsize *= shape[j]; } switch (vartypes[i]) { case NC_CHAR: break; case NC_SHORT: valuep = (void *)malloc(varsize * sizeof(short)); status = ncmpi_get_vara_short(ncid1, i, start, shape, (short *)valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_vara_short(ncid2, varids[i], start, shape, (short *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_INT: valuep = (void *)malloc(varsize * sizeof(int)); status = ncmpi_get_vara_int(ncid1, i, start, shape, (int *)valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_vara_int(ncid2, varids[i], start, shape, (int *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_FLOAT: valuep = (void *)malloc(varsize * sizeof(float)); status = ncmpi_get_vara_float(ncid1, i, start, shape, (float *)valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_vara_float(ncid2, varids[i], start, shape, (float *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; case NC_DOUBLE: valuep = (void *)malloc(varsize * sizeof(double)); status = ncmpi_get_vara_double(ncid1, i, start, shape, (double *)valuep); if (status != NC_NOERR) handle_error(status); status = ncmpi_put_vara_double(ncid2, varids[i], start, shape, (double *)valuep); if (status != NC_NOERR) handle_error(status); free(valuep); break; default: ; /* handle unexpected types */ } } status = ncmpi_end_indep_data(ncid1); if (status != NC_NOERR) handle_error(status); status = ncmpi_end_indep_data(ncid2); if (status != NC_NOERR) handle_error(status); status = ncmpi_sync(ncid1); if (status != NC_NOERR) handle_error(status); status = ncmpi_sync(ncid2); if (status != NC_NOERR) handle_error(status); /** * Close the datasets * Dataset API: collective */ status = ncmpi_close(ncid1); if (status != NC_NOERR) handle_error(status); status = ncmpi_close(ncid2); if (status != NC_NOERR) handle_error(status); /******************* END OF NETCDF ACCESS ****************/ if (rank == 0) fprintf(stderr, "OK\nInput file %s copied to: %s!\n", opts.infname, opts.outfname); MPI_Finalize(); return 0; }
/** * Write a parallel-nedcdf file. * * We assume here that localData is a scalar. * * Pnetcdf uses row-major format (same as FFTW). * * \param[in] filename : PnetCDF filename * \param[in] starts : offset to where to start reading data * \param[in] counts : number of elements read (3D sub-domain inside global) * \param[in] gsizes : global sizes * \param[in] localData : actual data buffer (size : nx*ny*nz*sizeof(float)) * */ void write_pnetcdf(const std::string &filename, MPI_Offset starts[3], MPI_Offset counts[3], int gsizes[3], float *localData) { int myRank; MPI_Comm_rank(MPI_COMM_WORLD, &myRank); // netcdf file id int ncFileId; int err; // file creation mode int ncCreationMode = NC_CLOBBER; // CDF-5 is almost mandatory for very large files (>= 2x10^9 cells) // not useful here bool useCDF5 = false; if (useCDF5) ncCreationMode = NC_CLOBBER|NC_64BIT_DATA; else // use CDF-2 file format ncCreationMode = NC_CLOBBER|NC_64BIT_OFFSET; // verbose log ? //bool pnetcdf_verbose = false; int nbVar=1; int dimIds[3], varIds[nbVar]; //MPI_Offset write_size, sum_write_size; MPI_Info mpi_info_used; //char str[512]; // time measurement variables //float write_timing, max_write_timing, write_bw; /* * Create NetCDF file */ err = ncmpi_create(MPI_COMM_WORLD, filename.c_str(), ncCreationMode, MPI_INFO_NULL, &ncFileId); if (err != NC_NOERR) { printf("Error: ncmpi_create() file %s (%s)\n",filename.c_str(),ncmpi_strerror(err)); MPI_Abort(MPI_COMM_WORLD, -1); exit(1); } /* * Define global dimensions */ err = ncmpi_def_dim(ncFileId, "x", gsizes[0], &dimIds[0]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_dim(ncFileId, "y", gsizes[1], &dimIds[1]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_dim(ncFileId, "z", gsizes[2], &dimIds[2]); PNETCDF_HANDLE_ERROR; /* * Define variables to write (give a name) */ nc_type ncDataType = NC_FLOAT; MPI_Datatype mpiDataType = MPI_FLOAT; err = ncmpi_def_var(ncFileId, "data", ncDataType, 3, dimIds, &varIds[0]); PNETCDF_HANDLE_ERROR; /* * global attributes */ // did we use CDF-2 or CDF-5 { int useCDF5_int = useCDF5 ? 1 : 0; err = ncmpi_put_att_int(ncFileId, NC_GLOBAL, "CDF-5 mode", NC_INT, 1, &useCDF5_int); PNETCDF_HANDLE_ERROR; } /* * exit the define mode */ err = ncmpi_enddef(ncFileId); PNETCDF_HANDLE_ERROR; /* * Get all the MPI_IO hints used */ err = ncmpi_get_file_info(ncFileId, &mpi_info_used); PNETCDF_HANDLE_ERROR; // copy data to write in intermediate buffer int nItems = counts[IX]*counts[IY]*counts[IZ]; { // debug // printf("Pnetcdf [rank=%d] starts=%lld %lld %lld, counts =%lld %lld %lld, gsizes=%d %d %d\n", // myRank, // starts[0],starts[1],starts[2], // counts[0],counts[1],counts[2], // gsizes[0],gsizes[1],gsizes[2]); /* * make sure PNetCDF doesn't complain when starts is outside of global domain * bound. When nItems is null, off course we don't write anything, but starts * offset have to be inside global domain. * So there is no harm, setting starts to origin. */ if (nItems == 0) { starts[0]=0; starts[1]=0; starts[2]=0; } err = ncmpi_put_vara_all(ncFileId, varIds[0], starts, counts, localData, nItems, mpiDataType); PNETCDF_HANDLE_ERROR; } /* * close the file */ err = ncmpi_close(ncFileId); PNETCDF_HANDLE_ERROR; } // write_pnetcdf
int main(int argc, char **argv) { /* create foo.nc */ int stat; /* return status */ int ncid; /* netCDF id */ /* dimension ids */ int lat_dim; int lon_dim; int time_dim; /* dimension lengths */ size_t lat_len = 10; size_t lon_len = 5; size_t time_len = NC_UNLIMITED; /* variable ids */ int lat_id; int lon_id; int time_id; int z_id; int t_id; int p_id; int rh_id; /* rank (number of dimensions) for each variable */ # define RANK_lat 1 # define RANK_lon 1 # define RANK_time 1 # define RANK_z 3 # define RANK_t 3 # define RANK_p 3 # define RANK_rh 3 /* variable shapes */ int lat_dims[RANK_lat]; int lon_dims[RANK_lon]; int time_dims[RANK_time]; int z_dims[RANK_z]; int t_dims[RANK_t]; int p_dims[RANK_p]; int rh_dims[RANK_rh]; /* attribute vectors */ double z_valid_range[2]; double p__FillValue[1]; int rh__FillValue[1]; int stat=0; MPI_Init(&argc, &argv); /* enter define mode */ stat = ncmpi_create(MPI_COMM_WORLD, "foo.nc", NC_CLOBBER, MPI_INFO_NULL, &ncid); check_err(stat,__LINE__,__FILE__); /* define dimensions */ stat = ncmpi_def_dim(ncid, "lat", lat_len, &lat_dim); check_err(stat,__LINE__,__FILE__); stat = ncmpi_def_dim(ncid, "lon", lon_len, &lon_dim); check_err(stat,__LINE__,__FILE__); stat = ncmpi_def_dim(ncid, "time", time_len, &time_dim); check_err(stat,__LINE__,__FILE__); /* define variables */ lat_dims[0] = lat_dim; stat = ncmpi_def_var(ncid, "lat", NC_INT, RANK_lat, lat_dims, &lat_id); check_err(stat,__LINE__,__FILE__); lon_dims[0] = lon_dim; stat = ncmpi_def_var(ncid, "lon", NC_INT, RANK_lon, lon_dims, &lon_id); check_err(stat,__LINE__,__FILE__); time_dims[0] = time_dim; stat = ncmpi_def_var(ncid, "time", NC_INT, RANK_time, time_dims, &time_id); check_err(stat,__LINE__,__FILE__); z_dims[0] = time_dim; z_dims[1] = lat_dim; z_dims[2] = lon_dim; stat = ncmpi_def_var(ncid, "z", NC_FLOAT, RANK_z, z_dims, &z_id); check_err(stat,__LINE__,__FILE__); t_dims[0] = time_dim; t_dims[1] = lat_dim; t_dims[2] = lon_dim; stat = ncmpi_def_var(ncid, "t", NC_FLOAT, RANK_t, t_dims, &t_id); check_err(stat,__LINE__,__FILE__); p_dims[0] = time_dim; p_dims[1] = lat_dim; p_dims[2] = lon_dim; stat = ncmpi_def_var(ncid, "p", NC_DOUBLE, RANK_p, p_dims, &p_id); check_err(stat,__LINE__,__FILE__); rh_dims[0] = time_dim; rh_dims[1] = lat_dim; rh_dims[2] = lon_dim; stat = ncmpi_def_var(ncid, "rh", NC_INT, RANK_rh, rh_dims, &rh_id); check_err(stat,__LINE__,__FILE__); /* assign attributes */ stat = ncmpi_put_att_text(ncid, lat_id, "units", 13, "degrees_north"); check_err(stat,__LINE__,__FILE__); stat = ncmpi_put_att_text(ncid, lon_id, "units", 12, "degrees_east"); check_err(stat,__LINE__,__FILE__); stat = ncmpi_put_att_text(ncid, time_id, "units", 7, "seconds"); check_err(stat,__LINE__,__FILE__); stat = ncmpi_put_att_text(ncid, z_id, "units", 6, "meters"); check_err(stat,__LINE__,__FILE__); z_valid_range[0] = 0; z_valid_range[1] = 5000; stat = ncmpi_put_att_double(ncid, z_id, "valid_range", NC_DOUBLE, 2, z_valid_range); check_err(stat,__LINE__,__FILE__); p__FillValue[0] = -9999; stat = ncmpi_put_att_double(ncid, p_id, "_FillValue", NC_DOUBLE, 1, p__FillValue); check_err(stat,__LINE__,__FILE__); rh__FillValue[0] = -1; stat = ncmpi_put_att_int(ncid, rh_id, "_FillValue", NC_INT, 1, rh__FillValue); check_err(stat,__LINE__,__FILE__); /* leave define mode */ stat = ncmpi_enddef (ncid); check_err(stat,__LINE__,__FILE__); { /* store lat */ static int lat[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90}; ncmpi_begin_indep_data(ncid); stat = ncmpi_put_var_int(ncid, lat_id, lat); ncmpi_end_indep_data(ncid); check_err(stat,__LINE__,__FILE__); } { /* store lon */ static int lon[] = {-140, -118, -96, -84, -52}; ncmpi_begin_indep_data(ncid); stat = ncmpi_put_var_int(ncid, lon_id, lon); ncmpi_end_indep_data(ncid); check_err(stat,__LINE__,__FILE__); } stat = ncmpi_close(ncid); check_err(stat,__LINE__,__FILE__); MPI_Finalize(); return 0; }
/* * adapted from HydroRunBaseMpi::outputPnetcdf * * assumes here that localData have size nx,ny,nz (no ghostWidth) * * see : test_pnetcdf_write.cpp * * Note that if ghostIncluded is false local_data must be sized upon nx,ny,nz * if not size must be nx+2*ghostWidth,ny+2*ghostWidth,nz+2*ghostWidth * */ void write_pnetcdf(const std::string &filename, HostArray<double> &localData, ConfigMap &configMap) { int myRank; MPI_Comm_rank(MPI_COMM_WORLD, &myRank); // read local domain sizes int nx=configMap.getInteger("mesh","nx",32); int ny=configMap.getInteger("mesh","ny",32); int nz=configMap.getInteger("mesh","nz",32); // read mpi geometry int mx=configMap.getInteger("mpi","mx",1); int my=configMap.getInteger("mpi","my",1); int mz=configMap.getInteger("mpi","mz",1); // MPI cartesian coordinates // myRank = mpiCoord[0] + mx*mpiCoord[1] + mx*my*mpiCoord[2] int mpiCoord[3]; { mpiCoord[2] = myRank/(mx*my); mpiCoord[1] = (myRank - mx*my*mpiCoord[2])/mx; mpiCoord[0] = myRank - mx*my*mpiCoord[2] -mx*mpiCoord[1]; } bool ghostIncluded = configMap.getBool("output", "ghostIncluded",false); int ghostWidth = configMap.getInteger("mesh","ghostWidth",3); // global size int NX=nx*mx, NY=ny*my, NZ=nz*mz; int gsizes[3]; gsizes[IZ] = NX; gsizes[IY] = NY; gsizes[IX] = NZ; if ( ghostIncluded ) { gsizes[IZ] += 2*ghostWidth; gsizes[IY] += 2*ghostWidth; gsizes[IX] += 2*ghostWidth; } // netcdf file id int ncFileId; int err; // file creation mode int ncCreationMode = NC_CLOBBER; bool useCDF5 = configMap.getBool("output","pnetcdf_cdf5",false); if (useCDF5) ncCreationMode = NC_CLOBBER|NC_64BIT_DATA; else // use CDF-2 file format ncCreationMode = NC_CLOBBER|NC_64BIT_OFFSET; // verbose log ? bool pnetcdf_verbose = configMap.getBool("output","pnetcdf_verbose",false); int nbVar=8; int dimIds[3], varIds[nbVar]; MPI_Offset write_size, sum_write_size; MPI_Info mpi_info_used; char str[512]; // time measurement variables double write_timing, max_write_timing, write_bw; /* * writing parameter (offset and size) */ MPI_Offset starts[3] = {0}; MPI_Offset counts[3] = {nz, ny, nx}; // take care that row-major / column major format starts[IZ] = mpiCoord[IX]*nx; starts[IY] = mpiCoord[IY]*ny; starts[IX] = mpiCoord[IZ]*nz; if ( ghostIncluded ) { if ( mpiCoord[IX] == 0 ) counts[IZ] += ghostWidth; if ( mpiCoord[IY] == 0 ) counts[IY] += ghostWidth; if ( mpiCoord[IZ] == 0 ) counts[IX] += ghostWidth; if ( mpiCoord[IX] == mx-1 ) counts[IZ] += ghostWidth; if ( mpiCoord[IY] == my-1 ) counts[IY] += ghostWidth; if ( mpiCoord[IZ] == mz-1 ) counts[IX] += ghostWidth; starts[IZ] += ghostWidth; starts[IY] += ghostWidth; starts[IX] += ghostWidth; if ( mpiCoord[IX] == 0 ) starts[IZ] -= ghostWidth; if ( mpiCoord[IY] == 0 ) starts[IY] -= ghostWidth; if ( mpiCoord[IZ] == 0 ) starts[IX] -= ghostWidth; } /* * Create NetCDF file */ err = ncmpi_create(MPI_COMM_WORLD, filename.c_str(), ncCreationMode, MPI_INFO_NULL, &ncFileId); if (err != NC_NOERR) { printf("Error: ncmpi_create() file %s (%s)\n",filename.c_str(),ncmpi_strerror(err)); MPI_Abort(MPI_COMM_WORLD, -1); exit(1); } /* * Define dimensions */ err = ncmpi_def_dim(ncFileId, "x", gsizes[0], &dimIds[0]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_dim(ncFileId, "y", gsizes[1], &dimIds[1]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_dim(ncFileId, "z", gsizes[2], &dimIds[2]); PNETCDF_HANDLE_ERROR; /* * Define variables */ nc_type ncDataType = NC_DOUBLE; MPI_Datatype mpiDataType = MPI_DOUBLE; err = ncmpi_def_var(ncFileId, "rho", ncDataType, 3, dimIds, &varIds[ID]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_var(ncFileId, "E", ncDataType, 3, dimIds, &varIds[IP]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_var(ncFileId, "rho_vx", ncDataType, 3, dimIds, &varIds[IU]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_var(ncFileId, "rho_vy", ncDataType, 3, dimIds, &varIds[IV]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_var(ncFileId, "rho_vz", ncDataType, 3, dimIds, &varIds[IW]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_var(ncFileId, "Bx", ncDataType, 3, dimIds, &varIds[IA]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_var(ncFileId, "By", ncDataType, 3, dimIds, &varIds[IB]); PNETCDF_HANDLE_ERROR; err = ncmpi_def_var(ncFileId, "Bz", ncDataType, 3, dimIds, &varIds[IC]); PNETCDF_HANDLE_ERROR; /* * global attributes */ // did we use CDF-2 or CDF-5 { int useCDF5_int = useCDF5 ? 1 : 0; err = ncmpi_put_att_int(ncFileId, NC_GLOBAL, "CDF-5 mode", NC_INT, 1, &useCDF5_int); PNETCDF_HANDLE_ERROR; } /* * exit the define mode */ err = ncmpi_enddef(ncFileId); PNETCDF_HANDLE_ERROR; /* * Get all the MPI_IO hints used */ err = ncmpi_get_file_info(ncFileId, &mpi_info_used); PNETCDF_HANDLE_ERROR; int nItems = counts[IX]*counts[IY]*counts[IZ]; for (int iVar=0; iVar<nbVar; iVar++) { double *data = &(localData(0,0,0,iVar)); err = ncmpi_put_vara_all(ncFileId, varIds[iVar], starts, counts, data, nItems, mpiDataType); PNETCDF_HANDLE_ERROR; } /* * close the file */ err = ncmpi_close(ncFileId); PNETCDF_HANDLE_ERROR; } // write_pnetcdf
static int tst_norm(char *filename, int cmode) { int ncid, dimid, varid; int dimids[NDIMS]; /* unnormalized UTF-8 encoding for Unicode 8-character "Hello" in Greek: */ unsigned char uname_utf8[] = { 0x41, /* LATIN CAPITAL LETTER A */ 0xCC, 0x80, /* COMBINING GRAVE ACCENT */ 0x41, /* LATIN CAPITAL LETTER A */ 0xCC, 0x81, /* COMBINING ACUTE ACCENT */ 0x41, /* LATIN CAPITAL LETTER A */ 0xCC, 0x82, /* COMBINING CIRCUMFLEX ACCENT */ 0x41, /* LATIN CAPITAL LETTER A */ 0xCC, 0x83, /* COMBINING TILDE */ 0x41, /* LATIN CAPITAL LETTER A */ 0xCC, 0x88, /* COMBINING DIAERESIS */ 0x41, /* LATIN CAPITAL LETTER A */ 0xCC, 0x8A, /* COMBINING RING ABOVE */ 0x43, /* LATIN CAPITAL LETTER C */ 0xCC, 0xA7, /* COMBINING CEDILLA */ 0x45, /* LATIN CAPITAL LETTER E */ 0xCC, 0x80, /* COMBINING GRAVE ACCENT */ 0x45, /* LATIN CAPITAL LETTER E */ 0xCC, 0x81, /* COMBINING ACUTE ACCENT */ 0x45, /* LATIN CAPITAL LETTER E */ 0xCC, 0x82, /* COMBINING CIRCUMFLEX ACCENT */ 0x45, /* LATIN CAPITAL LETTER E */ 0xCC, 0x88, /* COMBINING DIAERESIS */ 0x49, /* LATIN CAPITAL LETTER I */ 0xCC, 0x80, /* COMBINING GRAVE ACCENT */ 0x49, /* LATIN CAPITAL LETTER I */ 0xCC, 0x81, /* COMBINING ACUTE ACCENT */ 0x49, /* LATIN CAPITAL LETTER I */ 0xCC, 0x82, /* COMBINING CIRCUMFLEX ACCENT */ 0x49, /* LATIN CAPITAL LETTER I */ 0xCC, 0x88, /* COMBINING DIAERESIS */ 0x4E, /* LATIN CAPITAL LETTER N */ 0xCC, 0x83, /* COMBINING TILDE */ 0x00 }; /* NFC normalized UTF-8 encoding for same Unicode string: */ unsigned char nname_utf8[] = { 0xC3, 0x80, /* LATIN CAPITAL LETTER A WITH GRAVE */ 0xC3, 0x81, /* LATIN CAPITAL LETTER A WITH ACUTE */ 0xC3, 0x82, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ 0xC3, 0x83, /* LATIN CAPITAL LETTER A WITH TILDE */ 0xC3, 0x84, /* LATIN CAPITAL LETTER A WITH DIAERESIS */ 0xC3, 0x85, /* LATIN CAPITAL LETTER A WITH RING ABOVE */ 0xC3, 0x87, /* LATIN CAPITAL LETTER C WITH CEDILLA */ 0xC3, 0x88, /* LATIN CAPITAL LETTER E WITH GRAVE */ 0xC3, 0x89, /* LATIN CAPITAL LETTER E WITH ACUTE */ 0xC3, 0x8A, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ 0xC3, 0x8B, /* LATIN CAPITAL LETTER E WITH DIAERESIS */ 0xC3, 0x8C, /* LATIN CAPITAL LETTER I WITH GRAVE */ 0xC3, 0x8D, /* LATIN CAPITAL LETTER I WITH ACUTE */ 0xC3, 0x8E, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ 0xC3, 0x8F, /* LATIN CAPITAL LETTER I WITH DIAERESIS */ 0xC3, 0x91, /* LATIN CAPITAL LETTER N WITH TILDE */ 0x00 }; /* Unnormalized name used for dimension, variable, and attribute value */ #define UNAME ((char *) uname_utf8) #define UNAMELEN (sizeof uname_utf8) /* Normalized name */ #define NNAME ((char *) nname_utf8) #define NNAMELEN (sizeof nname_utf8) char name_in[UNAMELEN + 1], strings_in[UNAMELEN + 1]; nc_type att_type; MPI_Offset att_len; int err, dimid_in, varid_in, attnum_in; int attvals[] = {42}; #define ATTNUM ((sizeof attvals)/(sizeof attvals[0])) err = ncmpi_create(MPI_COMM_WORLD, filename, cmode, MPI_INFO_NULL,&ncid); ERR /* Define dimension with unnormalized Unicode UTF-8 encoded name */ err = ncmpi_def_dim(ncid, UNAME, NX, &dimid); ERR dimids[0] = dimid; /* Define variable with same name */ err = ncmpi_def_var(ncid, UNAME, NC_CHAR, NDIMS, dimids, &varid); ERR /* Create string attribute with same value */ err = ncmpi_put_att_text(ncid, varid, UNITS, UNAMELEN, UNAME); ERR /* Create int attribute with same name */ err = ncmpi_put_att_int(ncid, varid, UNAME, NC_INT, ATTNUM, attvals); ERR /* Try to create dimension and variable with NFC-normalized * version of same name. These should fail, as unnormalized name * should have been normalized in library, so these are attempts to * create duplicate netCDF objects. */ if ((err = ncmpi_def_dim(ncid, NNAME, NX, &dimid)) != NC_ENAMEINUSE) { printf("Error at line %d: expecting error code %d but got %d\n",__LINE__,NC_ENAMEINUSE,err); return 1; } if ((err=ncmpi_def_var(ncid, NNAME, NC_CHAR, NDIMS, dimids, &varid)) != NC_ENAMEINUSE) { printf("Error at line %d: expecting error code %d but got %d\n",__LINE__,NC_ENAMEINUSE,err); return 1; } err = ncmpi_enddef(ncid); ERR /* Write string data, UTF-8 encoded, to the file */ err = ncmpi_put_var_text_all(ncid, varid, UNAME); ERR err = ncmpi_close(ncid); ERR /* Check it out. */ err = ncmpi_open(MPI_COMM_WORLD, filename, NC_NOWRITE, MPI_INFO_NULL, &ncid); ERR err = ncmpi_inq_varid(ncid, UNAME, &varid); ERR err = ncmpi_inq_varname(ncid, varid, name_in); ERR err = strncmp(NNAME, name_in, NNAMELEN); ERR err = ncmpi_inq_varid(ncid, NNAME, &varid_in); ERR if ((err = ncmpi_inq_dimid(ncid, UNAME, &dimid_in)) || dimid != dimid_in) {printf("Error at line %d\n",__LINE__);return 1;} if ((err = ncmpi_inq_dimid(ncid, NNAME, &dimid_in)) || dimid != dimid_in) {printf("Error at line %d\n",__LINE__);return 1;} err = ncmpi_inq_att(ncid, varid, UNITS, &att_type, &att_len); ERR if ( att_type != NC_CHAR || att_len != UNAMELEN) {printf("Error at line %d\n",__LINE__);return 1;} err = ncmpi_get_att_text(ncid, varid, UNITS, strings_in); ERR strings_in[UNAMELEN] = '\0'; err = strncmp(UNAME, strings_in, UNAMELEN); ERR if ((err = ncmpi_inq_attid(ncid, varid, UNAME, &attnum_in)) || ATTNUM != attnum_in) {printf("Error at line %d\n",__LINE__);return 1;} if ((err = ncmpi_inq_attid(ncid, varid, NNAME, &attnum_in)) || ATTNUM != attnum_in) {printf("Error at line %d\n",__LINE__);return 1;} err = ncmpi_close(ncid); ERR return 0; }
/* Write an attribute with type conversion. */ static int nc4_put_att_tc(int ncid, int varid, const char *name, nc_type file_type, nc_type mem_type, int mem_type_is_long, size_t len, const void *op) { NC *nc; NC_HDF5_FILE_INFO_T *h5; if (!name || strlen(name) > NC_MAX_NAME) return NC_EBADNAME; LOG((3, "nc4_put_att_tc: ncid 0x%x varid %d name %s file_type %d " "mem_type %d len %d", ncid, varid, name, file_type, mem_type, len)); /* The length needs to be positive (cast needed for braindead systems with signed size_t). */ if((unsigned long) len > X_INT_MAX) return NC_EINVAL; /* Find metadata. */ if (!(nc = nc4_find_nc_file(ncid,NULL))) return NC_EBADID; /* get netcdf-4 metadata */ h5 = NC4_DATA(nc); assert(h5); #if 0 /*def USE_PNETCDF*/ /* Take care of files created/opened with parallel-netcdf library. */ if (h5->pnetcdf_file) { if (mem_type == NC_UBYTE) mem_type = NC_BYTE; switch(mem_type) { case NC_BYTE: return ncmpi_put_att_schar(nc->int_ncid, varid, name, file_type, len, op); case NC_CHAR: return ncmpi_put_att_text(nc->int_ncid, varid, name, len, op); case NC_SHORT: return ncmpi_put_att_short(nc->int_ncid, varid, name, file_type, len, op); case NC_INT: if (mem_type_is_long) return ncmpi_put_att_long(nc->int_ncid, varid, name, file_type, len, op); else return ncmpi_put_att_int(nc->int_ncid, varid, name, file_type, len, op); case NC_FLOAT: return ncmpi_put_att_float(nc->int_ncid, varid, name, file_type, len, op); case NC_DOUBLE: return ncmpi_put_att_double(nc->int_ncid, varid, name, file_type, len, op); case NC_NAT: default: return NC_EBADTYPE; } } #endif /* USE_PNETCDF */ /* Otherwise, handle things the netcdf-4 way. */ return nc4_put_att(ncid, nc, varid, name, file_type, mem_type, len, mem_type_is_long, op); }