Пример #1
0
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);
}
Пример #2
0
/*
 * 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;
}