/* Initialize iteration for a variable. Just a wrapper for * nc_blkio_init() that makes the netCDF calls needed to initialize * lower-level iterator. */ int nc_get_iter(int ncid, int varid, size_t bufsize, /* size in bytes of memory buffer */ nciter_t **iterpp /* returned opaque iteration state */) { int stat = NC_NOERR; nciter_t *iterp; nc_type vartype; size_t value_size = 0; /* size in bytes of each variable element */ int ndims; /* number of dimensions for variable */ int *dimids; long long nvalues = 1; int dim; int chunked = 0; /* Caller should free this by calling nc_free_iter(iterp) */ iterp = (nciter_t *) emalloc(sizeof(nciter_t)); memset((void*)iterp,0,sizeof(nciter_t)); /* make sure it is initialized */ NC_CHECK(nc_inq_varndims(ncid, varid, &ndims)); dimids = (int *) emalloc((ndims + 1) * sizeof(int)); iterp->dimsizes = (size_t *) emalloc((ndims + 1) * sizeof(size_t)); iterp->chunksizes = (size_t *) emalloc((ndims + 1) * sizeof(size_t)); NC_CHECK(nc_inq_vardimid (ncid, varid, dimids)); for(dim = 0; dim < ndims; dim++) { size_t len; NC_CHECK(nc_inq_dimlen(ncid, dimids[dim], &len)); nvalues *= len; iterp->dimsizes[dim] = len; } NC_CHECK(nc_inq_vartype(ncid, varid, &vartype)); NC_CHECK(inq_value_size(ncid, vartype, &value_size)); #ifdef USE_NETCDF4 { int contig = 1; if(ndims > 0) { NC_CHECK(nc_inq_var_chunking(ncid, varid, &contig, NULL)); } if(contig == 0) { /* chunked */ NC_CHECK(nc_inq_var_chunking(ncid, varid, &contig, iterp->chunksizes)); chunked = 1; } } #endif /* USE_NETCDF4 */ NC_CHECK(nc_blkio_init(bufsize, value_size, ndims, chunked, iterp)); iterp->to_get = 0; free(dimids); *iterpp = iterp; return stat; }
/* Determine whether a variable named varname exists in any group in an open netCDF file with id ncid. If so, return the count of how many matching variables were found, else return a count of 0. The variable name can be absolute such as "/foo" or "/GRP1/GRP1A/foo", in which case there is only one group to look in, given by the path from the root group. Alternatively, the variable name can be relative, such as "foo" or "GRPA/GRPB/foo", in which case every group is examined for a variable with that relative name. */ size_t nc_inq_varname_count(int ncid, char *varname) { /* count = 0; status = nc_inq_gvarid(ncid, varname, varid); if (status == NC_NOERR) count++; for each subgroup gid { count += nc_inq_varname_count(gid, varname); } return count; */ size_t count = 0; int varid; /* look in this group */ int status = nc_inq_gvarid(ncid, varname, &varid); #ifdef USE_NETCDF4 int numgrps; int *ncids; int g; #endif if (status == NC_NOERR) count++; #ifdef USE_NETCDF4 /* if this group has subgroups, call recursively on each of them */ NC_CHECK( nc_inq_grps(ncid, &numgrps, NULL) ); /* Allocate memory to hold the list of group ids. */ ncids = emalloc((numgrps + 1) * sizeof(int)); /* Get the list of group ids. */ NC_CHECK( nc_inq_grps(ncid, NULL, ncids) ); /* Call this function for each group. */ for (g = 0; g < numgrps; g++) { count += nc_inq_varname_count(ncids[g], varname); } free(ncids); #endif /* USE_NETCDF4 */ return count; }
/* Get parent id needed to define a new group from its full name in an * open file identified by ncid. Assumes all intermediate groups are * already defined. */ static int nc_inq_parid(int ncid, const char *fullname, int *locidp) { int stat = NC_NOERR; char *parent = strdup(fullname); char *slash = "/"; /* groupname separator */ char *last_slash; if(parent == NULL) { NC_CHECK(NC_ENOMEM); } last_slash = strrchr(parent, '/'); if(last_slash == parent) { /* parent is root */ free(parent); parent = strdup(slash); } else { *last_slash = '\0'; /* truncate to get parent name */ } NC_CHECK(nc_inq_grp_full_ncid(ncid, parent, locidp)); free(parent); return stat; }
/* * copy a user-defined enum type in the group igrp to the group ogrp */ static int copy_enum_type(int igrp, nc_type itype, int ogrp) { int stat = NC_NOERR; nc_type otype; nc_type basetype; size_t basesize; size_t nmembers; char name[NC_MAX_NAME]; int i; NC_CHECK(nc_inq_enum(igrp, itype, name, &basetype, &basesize, &nmembers)); NC_CHECK(nc_def_enum(ogrp, basetype, name, &otype)); for(i = 0; i < nmembers; i++) { /* insert enum members */ char ename[NC_MAX_NAME]; long long val; /* large enough to hold any integer type */ NC_CHECK(nc_inq_enum_member(igrp, itype, i, ename, &val)); NC_CHECK(nc_insert_enum(ogrp, otype, ename, &val)); } return stat; }
/* * Get total number of groups (including the top-level group and all * descendant groups, recursively) and all descendant subgroup ids * (including the input rootid of the start group) for a group and * all its descendants, in preorder. * * If grpids or numgrps is NULL, it will be ignored. So typical use * is to call with grpids NULL to get numgrps, allocate enough space * for the group ids, then call again to get them. */ int nc_inq_grps_full(int rootid, int *numgrps, int *grpids) { int stat = NC_NOERR; ncgiter_t *giter; /* pointer to group iterator */ int grpid; size_t count; NC_CHECK(nc_get_giter(rootid, &giter)); count = 0; NC_CHECK(nc_next_giter(giter, &grpid)); while(grpid != 0) { if(grpids) grpids[count] = grpid; count++; NC_CHECK(nc_next_giter(giter, &grpid)); } if(numgrps) *numgrps = count; nc_free_giter(giter); return stat; }
/* * Get group id of next group. On first call gets start group id, * subsequently returns other subgroup ids in preorder. Returns zero * when no more groups left. */ int nc_next_giter(ncgiter_t *iterp, int *grpidp) { int stat = NC_NOERR; int numgrps; int *grpids; int i; if(gs_empty(iterp)) { *grpidp = 0; /* not a group, signals iterator is done */ } else { *grpidp = gs_pop(iterp); NC_CHECK(nc_inq_grps2(*grpidp, &numgrps, NULL)); if(numgrps > 0) { grpids = (int *)emalloc(sizeof(int) * numgrps); NC_CHECK(nc_inq_grps2(*grpidp, &numgrps, grpids)); for(i = numgrps - 1; i >= 0; i--) { /* push ids on stack in reverse order */ gs_push(iterp, grpids[i]); } free(grpids); } } return stat; }
static void pr_att( int ncid, int varid, const char *varname, int ia ) { struct ncatt att; /* attribute */ NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) ); Printf ("\t\t%s:%s = ", varname, att.name); NC_CHECK( nc_inq_att(ncid, varid, att.name, &att.type, &att.len) ); if (att.len == 0) { /* show 0-length attributes as empty strings */ att.type = NC_CHAR; att.len = 1; } switch (att.type) { case NC_CHAR: att.string = (char *) malloc(att.len); if (!att.string) { error("Out of memory!"); NC_CHECK( nc_close(ncid) ); return; } NC_CHECK( nc_get_att_text(ncid, varid, att.name, att.string ) ); pr_att_string(att.len, att.string); free(att.string); break; default: att.vals = (double *) malloc(att.len * sizeof(double)); if (!att.vals) { error("Out of memory!"); NC_CHECK( nc_close(ncid) ); return; } NC_CHECK( nc_get_att_double(ncid, varid, att.name, att.vals ) ); pr_att_vals(att.type, att.len, att.vals); free(att.vals); break; } Printf (" ;\n"); }
/* * copy a user-defined compound type in the group igrp to the group ogrp */ static int copy_compound_type(int igrp, nc_type itype, int ogrp) { int stat = NC_NOERR; char name[NC_MAX_NAME]; size_t size; size_t nfields; nc_type otype; int fid; NC_CHECK(nc_inq_compound(igrp, itype, name, &size, &nfields)); NC_CHECK(nc_def_compound(ogrp, size, name, &otype)); for (fid = 0; fid < nfields; fid++) { char fname[NC_MAX_NAME]; char ftypename[NC_MAX_NAME]; size_t foff; nc_type iftype, oftype; int fndims; NC_CHECK(nc_inq_compound_field(igrp, itype, fid, fname, &foff, &iftype, &fndims, NULL)); /* type ids in source don't necessarily correspond to same * typeids in destination, so look up destination typeid by using * field type name */ NC_CHECK(nc_inq_type(igrp, iftype, ftypename, NULL)); NC_CHECK(nc_inq_typeid(ogrp, ftypename, &oftype)); if(fndims == 0) { NC_CHECK(nc_insert_compound(ogrp, otype, fname, foff, oftype)); } else { /* field is array type */ int *fdimsizes; fdimsizes = (int *) emalloc((fndims + 1) * sizeof(int)); stat = nc_inq_compound_field(igrp, itype, fid, NULL, NULL, NULL, NULL, fdimsizes); NC_CHECK(nc_insert_array_compound(ogrp, otype, fname, foff, oftype, fndims, fdimsizes)); free(fdimsizes); } } return stat; }
/* * return 1 if varid identifies a record variable * else return 0 */ int isrecvar(int ncid, int varid) { int ndims; int is_recvar = 0; int *dimids; NC_CHECK( nc_inq_varndims(ncid, varid, &ndims) ); #ifdef USE_NETCDF4 if (ndims > 0) { int nunlimdims; int *recdimids; int dim, recdim; dimids = (int *) emalloc((ndims + 1) * sizeof(int)); NC_CHECK( nc_inq_vardimid(ncid, varid, dimids) ); NC_CHECK( nc_inq_unlimdims(ncid, &nunlimdims, NULL) ); recdimids = (int *) emalloc((nunlimdims + 1) * sizeof(int)); NC_CHECK( nc_inq_unlimdims(ncid, NULL, recdimids) ); for (dim = 0; dim < ndims && is_recvar == 0; dim++) { for(recdim = 0; recdim < nunlimdims; recdim++) { if(dimids[dim] == recdimids[recdim]) { is_recvar = 1; break; } } } free(dimids); free(recdimids); } #else if (ndims > 0) { int recdimid; dimids = (int *) emalloc((ndims + 1) * sizeof(int)); NC_CHECK( nc_inq_vardimid(ncid, varid, dimids) ); NC_CHECK( nc_inq_unlimdim(ncid, &recdimid) ); if(dimids[0] == recdimid) is_recvar = 1; free(dimids); } #endif /* USE_NETCDF4 */ return is_recvar; }
static void do_ncdump(const char *path, struct fspec* specp) { int ndims; /* number of dimensions */ int nvars; /* number of variables */ int ngatts; /* number of global attributes */ int xdimid; /* id of unlimited dimension */ int dimid; /* dimension id */ int varid; /* variable id */ struct ncdim dims[NC_MAX_DIMS]; /* dimensions */ size_t vdims[NC_MAX_DIMS]; /* dimension sizes for a single variable */ struct ncvar var; /* variable */ struct ncatt att; /* attribute */ int id; /* dimension number per variable */ int ia; /* attribute number */ int iv; /* variable number */ int is_coord; /* true if variable is a coordinate variable */ int ncid; /* netCDF id */ vnode* vlist = 0; /* list for vars specified with -v option */ int nc_status; /* return from netcdf calls */ nc_status = nc_open(path, NC_NOWRITE, &ncid); if (nc_status != NC_NOERR) { error("%s: %s", path, nc_strerror(nc_status)); } /* * If any vars were specified with -v option, get list of associated * variable ids */ if (specp->nlvars > 0) { vlist = newvlist(); /* list for vars specified with -v option */ for (iv=0; iv < specp->nlvars; iv++) { NC_CHECK( nc_inq_varid(ncid, specp->lvars[iv], &varid) ); varadd(vlist, varid); } } /* if name not specified, derive it from path */ if (specp->name == (char *)0) { specp->name = name_path (path); } Printf ("netcdf %s {\n", specp->name); /* * get number of dimensions, number of variables, number of global * atts, and dimension id of unlimited dimension, if any */ NC_CHECK( nc_inq(ncid, &ndims, &nvars, &ngatts, &xdimid) ); /* get dimension info */ if (ndims > 0) Printf ("dimensions:\n"); for (dimid = 0; dimid < ndims; dimid++) { NC_CHECK( nc_inq_dim(ncid, dimid, dims[dimid].name, &dims[dimid].size) ); if (dimid == xdimid) Printf ("\t%s = %s ; // (%ld currently)\n",dims[dimid].name, "UNLIMITED", (long)dims[dimid].size); else Printf ("\t%s = %ld ;\n", dims[dimid].name, (long)dims[dimid].size); } if (nvars > 0) Printf ("variables:\n"); /* get variable info, with variable attributes */ for (varid = 0; varid < nvars; varid++) { NC_CHECK( nc_inq_var(ncid, varid, var.name, &var.type, &var.ndims, var.dims, &var.natts) ); Printf ("\t%s %s", type_name(var.type), var.name); if (var.ndims > 0) Printf ("("); for (id = 0; id < var.ndims; id++) { Printf ("%s%s", dims[var.dims[id]].name, id < var.ndims-1 ? ", " : ")"); } Printf (" ;\n"); /* get variable attributes */ for (ia = 0; ia < var.natts; ia++) pr_att(ncid, varid, var.name, ia); /* print ia-th attribute */ } /* get global attributes */ if (ngatts > 0) Printf ("\n// global attributes:\n"); for (ia = 0; ia < ngatts; ia++) pr_att(ncid, NC_GLOBAL, "", ia); /* print ia-th global attribute */ if (! specp->header_only) { if (nvars > 0) { Printf ("data:\n"); } /* output variable data */ for (varid = 0; varid < nvars; varid++) { /* if var list specified, test for membership */ if (specp->nlvars > 0 && ! varmember(vlist, varid)) continue; NC_CHECK( nc_inq_var(ncid, varid, var.name, &var.type, &var.ndims, var.dims, &var.natts) ); if (specp->coord_vals) { /* Find out if this is a coordinate variable */ is_coord = 0; for (dimid = 0; dimid < ndims; dimid++) { if (strcmp(dims[dimid].name, var.name) == 0 && var.ndims == 1) { is_coord = 1; break; } } if (! is_coord) /* don't get data for non-coordinate vars */ continue; } /* * Only get data for variable if it is not a record variable, * or if it is a record variable and at least one record has * been written. */ if (var.ndims == 0 || var.dims[0] != xdimid || dims[xdimid].size != 0) { /* Collect variable's dim sizes */ for (id = 0; id < var.ndims; id++) vdims[id] = dims[var.dims[id]].size; var.has_fillval = 1; /* by default, but turn off for bytes */ /* get _FillValue attribute */ nc_status = nc_inq_att(ncid,varid,_FillValue,&att.type,&att.len); if(nc_status == NC_NOERR && att.type == var.type && att.len == 1) { if(var.type == NC_CHAR) { char fillc; NC_CHECK( nc_get_att_text(ncid, varid, _FillValue, &fillc ) ); var.fillval = fillc; } else { NC_CHECK( nc_get_att_double(ncid, varid, _FillValue, &var.fillval) ); } } else { switch (var.type) { case NC_BYTE: /* don't do default fill-values for bytes, too risky */ var.has_fillval = 0; break; case NC_CHAR: var.fillval = NC_FILL_CHAR; break; case NC_SHORT: var.fillval = NC_FILL_SHORT; break; case NC_INT: var.fillval = NC_FILL_INT; break; case NC_FLOAT: var.fillval = NC_FILL_FLOAT; break; case NC_DOUBLE: var.fillval = NC_FILL_DOUBLE; break; default: break; } } if (vardata(&var, vdims, ncid, varid, specp) == -1) { error("can't output data for variable %s", var.name); NC_CHECK( nc_close(ncid) ); if (vlist) free(vlist); return; } } } } Printf ("}\n"); NC_CHECK( nc_close(ncid) ); if (vlist) free(vlist); }
/* Output the data for a single variable, in CDL syntax. */ int vardata( const struct ncvar *vp, /* variable */ long vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid, /* variable id */ const struct fspec* fsp /* formatting specs */ ) { long cor[NC_MAX_DIMS]; /* corner coordinates */ long edg[NC_MAX_DIMS]; /* edges of hypercube */ long add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ #define VALBUFSIZ 1000 double vals[VALBUFSIZ] ; /* aligned buffer */ int gulp = VALBUFSIZ; int id; int ir; long nels; long ncols; long nrows; int vrank = vp->ndims; static int initeps = 0; /* printf format used to print each value */ char *fmt = get_fmt(ncid, varid, vp->type); if (!initeps) { /* make sure epsilons get initialized */ init_epsilons(); initeps = 1; } nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } if (vrank <= 1) { Printf("\n %s = ", vp->name); set_indent ((int)strlen(vp->name) + 4); } else { Printf("\n %s =\n ", vp->name); set_indent (2); } if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ for (ir = 0; ir < nrows; ir++) { /* * rather than just printing a whole row at once (which might exceed * the capacity of MSDOS platforms, for example), we break each row * into smaller chunks, if necessary. */ long corsav; int left = (int)ncols; boolean lastrow; if (vrank > 0) { corsav = cor[vrank-1]; if (fsp->brief_data_cmnts != false && vrank > 1 && left > 0) { /* print brief comment with indices range */ Printf("// %s(",vp->name); switch (fsp->data_lang) { case LANG_C: /* print brief comment with C variable indices */ for (id = 0; id < vrank-1; id++) Printf("%lu,", (unsigned long)cor[id]); if (vdims[vrank-1] == 1) Printf("0"); else Printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1); break; case LANG_F: /* print brief comment with Fortran variable indices */ if (vdims[vrank-1] == 1) Printf("1"); else Printf("1-%lu ", (unsigned long)vdims[vrank-1]); for (id = vrank-2; id >=0 ; id--) { Printf(",%lu", (unsigned long)(1 + cor[id])); } break; } Printf(")\n "); set_indent(4); } } lastrow = (boolean)(ir == nrows-1); while (left > 0) { long toget = left < gulp ? left : gulp; if (vrank > 0) edg[vrank-1] = toget; switch(vp->type) { case NC_CHAR: NC_CHECK( ncvarget(ncid, varid, cor, edg, (char *)vals) ); pr_tvals(vp, toget, fmt, left > toget, lastrow, (char *) vals, fsp, cor); break; case NC_BYTE: NC_CHECK( ncvarget(ncid, varid, cor, edg, (signed char *)vals) ); pr_bvals(vp, toget, fmt, left > toget, lastrow, (signed char *) vals, fsp, cor); break; case NC_SHORT: NC_CHECK( ncvarget(ncid, varid, cor, edg, (short *)vals) ); pr_svals(vp, toget, fmt, left > toget, lastrow, (short *) vals, fsp, cor); break; case NC_INT: NC_CHECK( ncvarget(ncid, varid, cor, edg, (int *)vals) ); pr_ivals(vp, toget, fmt, left > toget, lastrow, (int *) vals, fsp, cor); break; case NC_FLOAT: NC_CHECK( ncvarget(ncid, varid, cor, edg, (float *)vals) ); pr_fvals(vp, toget, fmt, left > toget, lastrow, (float *) vals, fsp, cor); break; case NC_DOUBLE: NC_CHECK( ncvarget(ncid, varid, cor, edg, (double *)vals) ); pr_dvals(vp, toget, fmt, left > toget, lastrow, (double *) vals, fsp, cor); break; default: error("vardata: bad type"); } left -= toget; if (vrank > 0) cor[vrank-1] += toget; } if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } return 0; }
int main(int argc, char ** argv) { int ncid, dimid, varid; MPI_Init(&argc, &argv); MPI_Datatype vtype, rtype, usertype; MPI_Aint lb, extent; int userbufsz, *userbuf, *cmpbuf, i, errs=0; int count = 25; double pi = 3.14159; MPI_Offset start, acount; ncmpi_create(MPI_COMM_WORLD, "vectors.nc", NC_CLOBBER, MPI_INFO_NULL, &ncid); ncmpi_def_dim(ncid, "50k", 1024*50, &dimid); ncmpi_def_var(ncid, "vector", NC_DOUBLE, 1, &dimid, &varid); ncmpi_enddef(ncid); MPI_Type_vector(VECCOUNT, BLOCKLEN, STRIDE, MPI_INT, &vtype); MPI_Type_create_resized(vtype, 0, STRIDE*VECCOUNT*sizeof(int), &rtype); MPI_Type_contiguous(count, rtype, &usertype); MPI_Type_commit(&usertype); MPI_Type_free(&vtype); MPI_Type_free(&rtype); MPI_Type_get_extent(usertype, &lb, &extent); userbufsz = extent; userbuf = malloc(userbufsz); cmpbuf = calloc(userbufsz, 1); for (i=0; i< userbufsz/sizeof(int); i++) { userbuf[i] = pi*i; } start = 10; acount = count*12; ncmpi_begin_indep_data(ncid); ncmpi_put_vara(ncid, varid, &start, &acount, userbuf, 1, usertype); ncmpi_close(ncid); NC_CHECK(ncmpi_open(MPI_COMM_WORLD, "vectors.nc", NC_NOWRITE, MPI_INFO_NULL, &ncid)); ncmpi_begin_indep_data(ncid); NC_CHECK(ncmpi_inq_varid(ncid, "vector", &varid)); NC_CHECK(ncmpi_get_vara(ncid, varid, &start, &acount, cmpbuf, 1, usertype)); ncmpi_close(ncid); for (i=0; errs < 10 && i < acount; i++) { /* vector of 4,3,5, so skip 4th and 5th items of every block */ if (i%STRIDE >= BLOCKLEN) continue; if (userbuf[i] != cmpbuf[i]) { errs++; fprintf(stderr, "%d: expected 0x%x got 0x%x\n", i, userbuf[i], cmpbuf[i]); } } free(userbuf); free(cmpbuf); MPI_Type_free(&usertype); MPI_Finalize(); return 0; }
/* Output the data for a single variable, in NcML syntax. * TODO: currently not called, need option for NcML with values ... */ int vardatax( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid /* variable id */ ) { size_t *cor; /* corner coordinates */ size_t *edg; /* edges of hypercube */ size_t *add; /* "odometer" increment to next "row" */ void *vals; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; cor = (size_t *) emalloc((vrank + 1) * sizeof(size_t)); edg = (size_t *) emalloc((vrank + 1) * sizeof(size_t)); add = (size_t *) emalloc((vrank + 1) * sizeof(size_t)); nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } printf(" <values>\n "); set_indent (7); if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ vals = emalloc(ncols * vp->tinfo->size); for (ir = 0; ir < nrows; ir++) { size_t corsav; bool_t lastrow; if (vrank > 0) { corsav = cor[vrank-1]; } lastrow = (bool_t)(ir == nrows-1); if (vrank > 0) edg[vrank-1] = ncols; NC_CHECK(nc_get_vara(ncid, varid, cor, edg, vals) ); /* Test if we should treat array of chars as a string */ if(vp->type == NC_CHAR && (vp->fmt == 0 || STREQ(vp->fmt,"%s") || STREQ(vp->fmt,""))) { pr_tvalsx(vp, ncols, 0, lastrow, (char *) vals); } else { pr_any_valsx(vp, ncols, 0, lastrow, vals); } if (vrank > 0) cor[vrank-1] += ncols; if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } printf(" </values>\n"); free(vals); free(cor); free(edg); free(add); return 0; }
/* Output the data for a single variable, in CDL syntax. */ int vardata( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid /* variable id */ ) { size_t *cor; /* corner coordinates */ size_t *edg; /* edges of hypercube */ size_t *add; /* "odometer" increment to next "row" */ void *vals; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; cor = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); edg = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); add = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); nels = 1; if(vrank == 0) { /*scalar*/ cor[0] = 0; edg[0] = 1; } else { for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } } printf("\n"); indent_out(); printf(" "); print_name(vp->name); if (vrank <= 1) { printf(" = "); set_indent ((int)strlen(vp->name) + 4 + indent_get()); } else { printf(" =\n "); set_indent (2 + indent_get()); } if (vrank == 0) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = ncols; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ vals = emalloc(ncols * vp->tinfo->size); /* Test if we should treat array of chars as a string */ if(vp->type == NC_CHAR && (vp->fmt == 0 || STREQ(vp->fmt,"%s") || STREQ(vp->fmt,""))) { for (ir = 0; ir < nrows; ir++) { if (vrank > 0) { if (formatting_specs.brief_data_cmnts != false && vrank > 1 && ncols > 0) { annotate_brief(vp, cor, vdims); } } NC_CHECK(nc_get_vara(ncid, varid, cor, edg, vals)); pr_tvals(vp, ncols, (ir == nrows-1), (char *) vals, cor); if (ir < nrows-1) if (!upcorner(vdims, vp->ndims, cor, add)) error("vardata: odometer overflowed!"); set_indent(2); } } else { int level = 0; int rank = vp->ndims; int marks_pending = 0; NC_CHECK(print_rows(level, ncid, varid, vp, ncols, rank, vdims, cor, edg, vals, marks_pending)); } free(vals); free(cor); free(edg); free(add); return 0; }
/* Print data values for variable varid. * * Recursive to handle possibility of variables with multiple * unlimited dimensions, for which the CDL syntax requires use of "{" * and "}" in data section to disambiguate the size of nested records * in a simple linear list of values. */ static int print_rows( int level, /* 0 at top-level, incremented for each recursive level */ int ncid, /* netcdf id */ int varid, /* variable id */ const ncvar_t *vp, /* variable */ size_t ncols, /* number of values in a row */ int rank, /* number of elements in following 3 arrays */ size_t vdims[], /* variable dimension sizes */ size_t cor[], /* corner coordinates */ size_t edg[], /* edges of hypercube */ void *vals, /* allocated buffer for ncols values in a row */ int marks_pending /* number of pending closing "}" record markers */ ) { int d0 = 0; size_t inc = 1; int i; bool_t mark_record = (level > 0 && is_unlim_dim(ncid, vp->dims[level])); safebuf_t *sb = sbuf_new(); if (rank > 0) d0 = vdims[level]; for(i = level + 1; i < rank; i++) { inc *= vdims[i]; } if(mark_record) { /* the whole point of this recursion is printing these "{}" */ lput("{"); marks_pending++; /* matching "}"s to emit after last "row" */ } if(rank - level > 1) { /* this level is just d0 next levels */ size_t *local_cor = emalloc((rank + 1) * sizeof(size_t)); size_t *local_edg = emalloc((rank + 1) * sizeof(size_t)); for(i = 0; i < rank; i++) { local_cor[i] = cor[i]; local_edg[i] = edg[i]; } local_cor[level] = 0; local_edg[level] = 1; for(i = 0; i < d0 - 1; i++) { print_rows(level + 1, ncid, varid, vp, ncols, rank, vdims, local_cor, local_edg, vals, 0); local_cor[level] += 1; } print_rows(level + 1, ncid, varid, vp, ncols, rank, vdims, local_cor, local_edg, vals, marks_pending); free(local_edg); free(local_cor); } else { /* bottom out of recursion */ char *valp = vals; bool_t lastrow; int j; if(formatting_specs.brief_data_cmnts && rank > 1) { annotate_brief(vp, cor, vdims); } NC_CHECK(nc_get_vara(ncid, varid, cor, edg, (void *)valp)); for(i=0; i < d0 - 1; i++) { print_any_val(sb, vp, (void *)valp); valp += vp->tinfo->size; /* next value according to type */ if (formatting_specs.full_data_cmnts) { printf("%s, ", sb->buf); annotate (vp, cor, i); } else { sbuf_cat(sb, ", "); lput(sbuf_str(sb)); } } print_any_val(sb, vp, (void *)valp); /* determine if this is the last row */ lastrow = true; for(j = 0; j < rank - 1; j++) { if (cor[j] != vdims[j] - 1) { lastrow = false; break; } } if (formatting_specs.full_data_cmnts) { for (j = 0; j < marks_pending; j++) { sbuf_cat(sb, "}"); } printf("%s", sbuf_str(sb)); lastdelim (0, lastrow); annotate (vp, cor, i); } else { for (j = 0; j < marks_pending; j++) { sbuf_cat(sb, "}"); } lput(sbuf_str(sb)); lastdelim2 (0, lastrow); } } sbuf_free(sb); return NC_NOERR; }
/* Output the data for a single variable, in NcML syntax. * TODO: currently not called, need option for NcML with values ... */ int vardatax( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid, /* variable id */ const fspec_t *fsp /* formatting specs */ ) { size_t cor[NC_MAX_DIMS]; /* corner coordinates */ size_t edg[NC_MAX_DIMS]; /* edges of hypercube */ size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ size_t gulp; void *vals; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } printf(" <values>\n "); set_indent (7); if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ gulp = ncols < VALBUFSIZ ? VALBUFSIZ : ncols; vals = emalloc(gulp * vp->tinfo->size); for (ir = 0; ir < nrows; ir++) { /* * rather than just printing a whole row at once (which might * exceed the capacity of some platforms), we break each row * into smaller chunks, if necessary. */ size_t corsav; int left = (int)ncols; boolean lastrow; if (vrank > 0) { corsav = cor[vrank-1]; } lastrow = (boolean)(ir == nrows-1); while (left > 0) { size_t toget = left < gulp ? left : gulp; if (vrank > 0) edg[vrank-1] = toget; NC_CHECK(nc_get_vara(ncid, varid, cor, edg, vals) ); /* Test if we should treat array of chars as a string */ if(vp->type == NC_CHAR && (vp->fmt == 0 || STREQ(vp->fmt,"%s") || STREQ(vp->fmt,""))) { pr_tvalsx(vp, toget, left > toget, lastrow, (char *) vals); } else { pr_any_valsx(vp, toget, left > toget, lastrow, vals); } left -= toget; if (vrank > 0) cor[vrank-1] += toget; } if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } printf(" </values>\n"); free(vals); return 0; }
/* Output the data for a single variable, in CDL syntax. */ int vardata( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid, /* variable id */ const fspec_t *fsp /* formatting specs */ ) { size_t cor[NC_MAX_DIMS]; /* corner coordinates */ size_t edg[NC_MAX_DIMS]; /* edges of hypercube */ size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ size_t gulp; void *vals; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } printf("\n"); indent_out(); /* printf(" %s = ", vp->name); */ /* or */ /* printf(" %s =\n ", vp->name); */ printf(" "); print_name(vp->name); if (vrank <= 1) { printf(" = "); set_indent ((int)strlen(vp->name) + 4 + indent_get()); } else { printf(" =\n "); set_indent (2 + indent_get()); } if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ gulp = ncols < VALBUFSIZ ? ncols : VALBUFSIZ; vals = emalloc(gulp * vp->tinfo->size); for (ir = 0; ir < nrows; ir++) { /* * rather than just printing a whole row at once (which might * exceed the capacity of some platforms), we break each row * into smaller chunks, if necessary. */ size_t corsav = 0; int left = (int)ncols; boolean lastrow; if (vrank > 0) { corsav = cor[vrank-1]; if (fsp->brief_data_cmnts != false && vrank > 1 && left > 0) { /* print brief comment with indices range */ /* printf("// %s(",vp->name); */ printf("// "); printf(vp->name); printf("("); switch (fsp->data_lang) { case LANG_C: /* print brief comment with C variable indices */ for (id = 0; id < vrank-1; id++) printf("%lu,", (unsigned long)cor[id]); if (vdims[vrank-1] == 1) printf("0"); else printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1); break; case LANG_F: /* print brief comment with Fortran variable indices */ if (vdims[vrank-1] == 1) printf("1"); else printf("1-%lu ", (unsigned long)vdims[vrank-1]); for (id = vrank-2; id >=0 ; id--) { printf(",%lu", (unsigned long)(1 + cor[id])); } break; } printf(")\n"); indent_out(); printf(" "); set_indent(4 + indent_get()); } } lastrow = (boolean)(ir == nrows-1); while (left > 0) { size_t toget = left < gulp ? left : gulp; if (vrank > 0) edg[vrank-1] = toget; NC_CHECK(nc_get_vara(ncid, varid, cor, edg, vals) ); /* Test if we should treat array of chars as a string */ if(vp->type == NC_CHAR && (vp->fmt == 0 || STREQ(vp->fmt,"%s") || STREQ(vp->fmt,""))) { pr_tvals(vp, toget, left > toget, lastrow, (char *) vals, fsp, cor); } else { pr_any_vals(vp, toget, left > toget, lastrow, vals, fsp, cor); } left -= toget; if (vrank > 0) cor[vrank-1] += toget; } if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } free(vals); return 0; }
/* Output the data for a single variable, in CDL syntax. */ int vardata( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid /* variable id */ ) { size_t *cor; /* corner coordinates */ size_t *edg; /* edges of hypercube */ size_t *add; /* "odometer" increment to next "row" */ void *vals; int id; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; int level = 0; int marks_pending = 0; cor = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); edg = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); add = (size_t *) emalloc((1 + vrank) * sizeof(size_t)); nels = 1; if(vrank == 0) { /*scalar*/ cor[0] = 0; edg[0] = 1; } else { for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } } printf("\n"); indent_out(); printf(" "); print_name(vp->name); if (vrank <= 1) { printf(" = "); set_indent ((int)strlen(vp->name) + 4 + indent_get()); } else { printf(" =\n "); set_indent (2 + indent_get()); } if (vrank == 0) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = ncols; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ vals = emalloc(ncols * vp->tinfo->size); NC_CHECK(print_rows(level, ncid, varid, vp, vdims, cor, edg, vals, marks_pending)); free(vals); free(cor); free(edg); free(add); return 0; }