int ReadCDFFile(char *name, InputSection section) { int cdfid, i, j, *dimdim, dimfound, ndim, nvar, natt, recdim, *dim, nvarfound, bigdim = 0, coordfound = 0, mem, pointvalues; static int ncoord = 0; FILE *f; BOOL timedvar, noclose = FALSE; VarDesc *v, vh, *vo; Coordinate *coord = NULL; size_t start[1], count[1]; ptrdiff_t stride[1], imap[1]; const struct { char name[5]; Dimension dim; int *size; } dimtab[] = {"X", X_DIM, &nxm, "Y", Y_DIM, &nym, "Z", Z_DIM, &nz, "Time", TIME_DIM, NULL, "CNT", COUNT_DIM, &ncoord}; char txt[MAX_NC_NAME]; BorderTimeDesc *bt; size_t *coords, len, *dimptr[5], lcoord[5], ntimes; long *timetable = NULL; double *doubtable; nc_type datatype; if (section == GRID || section == TIME || section == DEPOSITION) { InputError(ERROR, "CDFIMPORT is not allowed in this section."); return (1); } if (!(f = fopen(name, "r"))) { InputError(ERROR, "Unable to open CDF-File \"%s\".", name); return (1); } fclose(f); if (nc_open(name, NC_NOWRITE, &cdfid)) { InputError(ERROR, "Unable to open CDF-File %s.", name); return (1); } nc_inq(cdfid, &ndim, &nvar, &natt, &recdim); dim = (int *)calloc(ndim, sizeof(int)); dimdim = (int *)calloc(ndim, sizeof(int)); nvarfound = dimfound = 0; for (i = ndim; i--; ) { nc_inq_dim(cdfid, i, txt, &len); for (j = 5; --j >= 0 && strcmp(txt, dimtab[j].name); ); dimdim[i] = j; if (j >= 0 && dimtab[j].size) { if (j < 2) { if (len != *dimtab[j].size && len != *dimtab[j].size+2) { InputError(WARNING, "\"%s\": Dimension %s has wrong size. Is %i should be %i or %i.", name, txt, len, *dimtab[j].size, *dimtab[j].size+2); dimdim[i] = -1; } else { dimfound |= 1 << j; if (len == *dimtab[j].size+2) bigdim |= 1 << j; } } else if (j < 4) { if (len != *dimtab[j].size) { InputError(WARNING, "\"%s\": Dimension %s has wrong size. Is %i should be %i.", name, txt, len, *dimtab[j].size); dimdim[i] = -1; } else dimfound |= 1 << j; } else { *dimtab[j].size = len; dimfound |= 1 << j; } } if (j == 3) ntimes = len; } if (bigdim && bigdim != ((X_DIM | Y_DIM) & dimfound)) { InputError(ERROR, "Mismatch of X/Y-Dimension-sizes."); goto error_end; } bigdim = !!bigdim; for (i = nvar; i--; ) { nc_inq_var(cdfid, i, txt, &datatype, &ndim, dim, &natt); for (v = variable; v && strcmp(txt, v->name); v = v->next); if (v) { vo = v; if (v->storetype == GRID_VAL && actualsection->id >= NORTH_BORDER && actualsection->id <= EAST_BORDER) v = BorderVariable(v, &vh); if (v->storetype == GRID_VAL && actualsection->id == EMISSIONS) { pointvalues = (ndim < 3 && (dimdim[*dim] == 4 || dimdim[dim[1]] == 4) ? *dimtab[4].size : 0); if (pointvalues && !coord) coord = AllocateCoordVar(pointvalues); v = EmissionVariable(v, pointvalues, 0, coord); } if (v->section == section) { if (v->inputtype != NORMAL_NUM) { InputError(WARNING, "The Variable %s cannot be set via a CDF-File.\n", inplineno, txt); continue; } if (datatype != NC_DOUBLE && datatype != NC_FLOAT && datatype != NC_LONG) { InputError(ERROR, "\"%s\": The type of variable %s is not of appropriate type.", name, txt); goto error_end; } if (v->init == WAS_SET_BY_USER) { InputError(WARNING, "The variable \"%s\" found in file \"%s\" is already initialized.", txt, name); if (section == EMISSIONS) InputError(WARNING, " ....so summing up emissions.\n"); else continue; } if (v->init == CALCULATED_VALUES) { InputError(WARNING, "The variable \"%s\" found in file \"%s\" cannot be initialized.\n" " It's calculated by meteochem.", txt, name); continue; } if ((v->option & STARTING_WITH_ZERO) && !bigdim) { InputError(ERROR, "Variable \"%s\" requires Dimensions X and Y to be two fields bigger", v->name); goto error_end; } memset(dimptr, 0, 5 * sizeof(*dimptr)); for (j = ndim; --j >= 0 && dimdim[dim[j]] != 3; ); if (timedvar = j >= 0) { if (actualsection->id < ENVIRONMENT || actualsection->id == INITIAL_DATA) { InputError(ERROR, "Time-dependent variables are not allowed in this section."); goto error_end; } noclose = TRUE; bt = (BorderTimeDesc *)malloc(sizeof(BorderTimeDesc)); if (v->dims == (X_DIM | Z_DIM)) bt->vartype = XWALL_VAR; else if (v->dims == (Y_DIM | Z_DIM)) bt->vartype = WALL_VAR; else if (v->dims == (X_DIM | Y_DIM)) bt->vartype = (v->storetype == GROUND_PARAM ? GROUND_VAR : LAYER_VAR); else if (v->dims == Z_DIM) bt->vartype = PROFILE_VAR; else if (v->dims == ALL_DIM) bt->vartype = MESH_VAR; else if (v->dims == COUNT_DIM) bt->vartype = COORD_VAR; else { InputError(ERROR, "The variable \"%s\" must not be time-dependent.", v->name); goto error_end; } bt->section = InputSection(actualsection->id); bt->bigdim = bigdim; bt->ntime = ntimes; bt->itime = -1; bt->actime = 0; bt->cdfid = cdfid; bt->vid = i; bt->actualvar = *v; bt->nextvar = *v; bt->timetable = timetable; coords = bt->coords; bt->actualdata.d = v->v.d; switch (bt->vartype) { case XWALL_VAR : mem = xrow*nz; break; case WALL_VAR : mem = row*nz; break; case GROUND_VAR : bt->nextvar.storetype = DOUBLE_PTR; case LAYER_VAR : mem = layer; break; case PROFILE_VAR : mem = nz; break; case MESH_VAR : mem = mesh; break; case COORD_VAR : mem = v->ncoord; break; } bt->nextdata = (double *)calloc(mem, sizeof(double)); if (!(bt->nextvar.v.d = bt->nextdata)) { InputError(ERROR, "Unable to allocate memory in Function \"ReadCDFFile\""); goto error_end; } bt->next = bordertime; bordertime = bt; } else coords = lcoord; for (j = ndim; j--; ) { if (dimdim[dim[j]] < 0) { nc_inq_dim(cdfid, dim[j], txt, &len); InputError(ERROR, "\"%s\": Variable %s includes \"%s\", an unkown or unusable dimension.", name, v->name, txt); goto error_end; } dimptr[dimdim[dim[j]]] = coords + j; } for (j = 5; j--; ) if (!dimptr[j]) dimptr[j] = coords + ndim++; printf("Reading Variable %s from CDF-File \"%s\"\n", txt, name); *dimptr[3] = 0; nvarfound++; vo->init = WAS_SET_BY_USER; if (ReadVarFromCDF(cdfid, i, v, dimptr, coords, !!bigdim)) goto error_end; if (timedvar) memcpy(bt->dimptr, dimptr, 5 * sizeof(long *)); } else if (!strcmp(txt, "Time")) { timetable = (long *)calloc(ntimes, sizeof(long)); *lcoord = 0; if (nc_get_vara_long(cdfid, i, lcoord, &ntimes, timetable)) { InputError(ERROR, "A variable called \"Time\" was found, but I couldn't read it."); } else { if (*timetable > tstart) InputError(WARNING, "The first time-slice for value for %s is later (%ld sec) than tstart(%ld sec).", v->name, *timetable, tstart); for (bt = bordertime; bt; bt = bt->next) if (!bt->timetable) bt->timetable = timetable; } } } else if (!strcmp(txt, "XCoord") || !strcmp(txt, "YCoord") || !strcmp(txt, "ZCoord")) { if (ndim == 1 && dimdim[*dim] == 4) { if (!coord) coord = AllocateCoordVar(*dimtab[4].size); *start = 0; *count = *dimtab[4].size; *stride = 1; *imap = &coord[1].x - &coord[0].x; nc_get_varm_float(cdfid, i, start, count, stride, imap, &coord[0].x + (*txt - 'X')); coordfound |= 1 << (*txt - 'X'); } } } if (coord) if (coordfound != 7) { InputError(ERROR, "Not all necessary coordinates found in file \"%s\".", name); goto error_end; } else ConvertEmissionCoords(*dimtab[4].size, coord, 0); if (!noclose) nc_close(cdfid); free(dim); if (!nvarfound) InputError(WARNING, "No usable Variable found in File \"%s\".", name); return (0); error_end : nc_close(cdfid); free(dim); free(dimdim); return (1); }
/* * Read a generalized hypercube of numeric values from a netCDF variable of an * open netCDF file. */ static void c_ncvgtg ( int ncid, /* netCDF ID */ int varid, /* variable ID */ const size_t* start, /* multidimensional index of hypercube corner */ const size_t* count, /* multidimensional hypercube edge lengths */ const ptrdiff_t* strides,/* netCDF variable access strides */ const ptrdiff_t* imap, /* memory values access basis vector */ void* value, /* block of data values to be read */ int* rcode /* returned error code */ ) { int status; int rank; nc_type datatype; if ((status = nc_inq_vartype(ncid, varid, &datatype)) == 0 && (status = nc_inq_varndims(ncid, varid, &rank)) == 0) { switch (datatype) { case NC_CHAR: status = NC_ECHAR; break; case NC_BYTE: # if NF_INT1_IS_C_SIGNED_CHAR status = nc_get_varm_schar(ncid, varid, start, count, strides, imap, (signed char*)value); # elif NF_INT1_IS_C_SHORT status = nc_get_varm_short(ncid, varid, start, count, strides, imap, (short*)value); # elif NF_INT1_IS_C_INT status = nc_get_varm_int(ncid, varid, start, count, strides, imap, (int*)value); # elif NF_INT1_IS_C_LONG status = nc_get_varm_long(ncid, varid, start, count, strides, imap, (long*)value); # endif break; case NC_SHORT: # if NF_INT2_IS_C_SHORT status = nc_get_varm_short(ncid, varid, start, count, strides, imap, (short*)value); # elif NF_INT2_IS_C_INT status = nc_get_varm_int(ncid, varid, start, count, strides, imap, (int*)value); # elif NF_INT2_IS_C_LONG status = nc_get_varm_long(ncid, varid, start, count, strides, imap, (long*)value); # endif break; case NC_INT: # if NF_INT_IS_C_INT status = nc_get_varm_int(ncid, varid, start, count, strides, imap, (int*)value); # elif NF_INT_IS_C_LONG status = nc_get_varm_long(ncid, varid, start, count, strides, imap, (long*)value); # endif break; case NC_FLOAT: # if NF_REAL_IS_C_FLOAT status = nc_get_varm_float(ncid, varid, start, count, strides, imap, (float*)value); # elif NF_REAL_IS_C_DOUBLE status = nc_get_varm_double(ncid, varid, start, count, strides, imap, (double*)value); # endif break; case NC_DOUBLE: # if NF_DOUBLEPRECISION_IS_C_FLOAT status = nc_get_varm_float(ncid, varid, start, count, strides, imap, (float*)value); # elif NF_DOUBLEPRECISION_IS_C_DOUBLE status = nc_get_varm_double(ncid, varid, start, count, strides, imap, (double*)value); # endif break; } } if (status == 0) *rcode = 0; else { nc_advise("NCVGTG", status, ""); *rcode = ncerr; } }
int main() { int ncid; int varid; int i,fail; int err; size_t start[5], count[5]; ptrdiff_t stride[5], imap[5]; int idim, ndim; float dat[20]; #ifdef DEBUG oc_loginit(); oc_setlogging(1); oc_logopen(NULL); #endif printf("*** Test: varm on URL: %s\n",URL); check(err = nc_open(URL, NC_NOWRITE, &ncid),__FILE__,__LINE__); check(err = nc_inq_varid(ncid, VAR, &varid),__FILE__,__LINE__); for (idim=0; idim<4; idim++) { start[idim] = 0; count[idim] = 1; stride[idim] = 1; imap[idim] = 1; } ndim=3; printf("*** Testing: stride case 1\n"); start[1] = 44; start[2] = 66; count[0] = 12; #ifdef STANDALONE printf("start = "); for(i=0;i<ndim;i++) printf(" %d",(int)start[i]); printf("\n"); printf("count = "); for(i=0;i<ndim;i++) printf(" %d",(int)count[i]); printf("\n"); printf("stride = "); for(i=0;i<ndim;i++) printf(" %d",(int)stride[i]); printf("\n"); printf("map = "); for(i=0;i<ndim;i++) printf(" %d",(int)imap[i]); printf("\n"); err = nc_get_vars_float (ncid, varid, start, count, stride, (float*) dat); printf("vars: %s =",VAR); for(i=0;i<12;i++) printf(" %f",dat[i]); printf("\n"); #endif check(err = nc_get_varm_float (ncid, varid, start, count, stride, imap, (float*) dat),__FILE__,__LINE__); #ifdef STANDALONE printf("varm: %s =",VAR); for(i=0;i<12;i++) printf(" %f",dat[i]); printf("\n"); #endif fail=0; for(i=0;i<12;i++) { float delta = (dat[i] - expected_stride1[i]); if(delta > 0.0005 || delta < -0.0005) { fprintf(stderr,"*** Failure: unexpected value: delta=%g dat[%d]=%g expected[%d]=%g\n", delta, i, dat[i], i, expected_stride1[i]); fail = 1; } } printf("*** %s: stride case 1\n",(fail?"Fail":"Pass")); printf("*** Testing: stride case 2\n"); /* case with strides #1 where len % stride == 0 */ start[1] = 44; start[2] = 66; count[0] = 6; stride[0] = 2; #ifdef STANDALONE printf("start = "); for(i=0;i<ndim;i++) printf(" %d",(int)start[i]); printf("\n"); printf("count = "); for(i=0;i<ndim;i++) printf(" %d",(int)count[i]); printf("\n"); printf("stride = "); for(i=0;i<ndim;i++) printf(" %d",(int)stride[i]); printf("\n"); printf("map = "); for(i=0;i<ndim;i++) printf(" %d",(int)imap[i]); printf("\n"); check(err = nc_get_vars_float(ncid, varid, start, count, stride, (float*) dat),__FILE__,__LINE__); printf("strided.vars: %s =",VAR); for(i=0;i<6;i++) printf(" %f",dat[i]); printf("\n"); #endif check(err = nc_get_varm_float(ncid, varid, start, count, stride, imap, (float*) dat),__FILE__,__LINE__); #ifdef STANDALONE printf("strided.varm: %s =",VAR); for(i=0;i<6;i++) printf(" %f",dat[i]); printf("\n"); #endif fail=0; for(i=0;i<6;i++) { float delta = (dat[i] - expected_stride2[i]); if(delta > 0.0005 || delta < -0.0005) { fprintf(stderr,"*** Failure: unexpected value: delta=%g dat[%d]=%g expected[%d]=%g\n", delta, i, dat[i], i, expected_stride2[i]); fail=1; } } printf("*** %s: stride case 2\n",(fail?"Fail":"Pass")); /* case with strides #2: len % stride != 0 */ printf("*** Testing: stride case 3\n"); start[1] = 44; start[2] = 66; count[0] = 3; stride[0] = 5; #ifdef STANDALONE printf("start = "); for(i=0;i<ndim;i++) printf(" %d",(int)start[i]); printf("\n"); printf("count = "); for(i=0;i<ndim;i++) printf(" %d",(int)count[i]); printf("\n"); printf("stride = "); for(i=0;i<ndim;i++) printf(" %d",(int)stride[i]); printf("\n"); printf("map = "); for(i=0;i<ndim;i++) printf(" %d",(int)imap[i]); printf("\n"); check(err = nc_get_vars_float(ncid, varid, start, count, stride, (float*) dat),__FILE__,__LINE__); printf("strided.vars: %s =",VAR); for(i=0;i<3;i++) printf(" %f",dat[i]); printf("\n"); #endif check(err = nc_get_varm_float(ncid, varid, start, count, stride, imap, (float*) dat),__FILE__,__LINE__); #ifdef STANDALONE printf("strided.varm: %s =",VAR); for(i=0;i<3;i++) printf(" %f",dat[i]); printf("\n"); #endif fail=0; for(i=0;i<3;i++) { float delta = (dat[i] - expected_stride3[i]); if(delta > 0.0005 || delta < -0.0005) { fprintf(stderr,"*** Failure: stride case 2: unexpected value: delta=%g dat[%d]=%g expected[%d]=%g\n", delta, i, dat[i], i, expected_stride3[i]); fail=1; } } printf("*** %s: stride case 3\n",(fail?"Fail":"Pass")); return fail; ncfail: printf("*** nc function failure: %d %s\n",err,nc_strerror(err)); return 1; }