Ejemplo n.º 1
0
Archivo: mpp_io.c Proyecto: djibi2/AM3
/*********************************************************************
void mpp_get_var_dimname(int fid, int vid, int i, char *name)
For each dimension we are assuming there is a 1-d field have the same name as the dimension.
*********************************************************************/
void mpp_get_var_dimname(int fid, int vid, int ind, char *name)
{
  int status, ncid, fldid, ndims, dims[4];
  char errmsg[512];
  
  if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_var_dimname): invalid fid number, fid should be "
				    "a nonnegative integer that less than nfiles");
  if(vid<0 || vid >=files[fid].nvar) mpp_error("mpp_io(mpp_get_var_dimname): invalid vid number, vid should be "
				    "a nonnegative integer that less than nvar");
  ncid = files[fid].ncid;
  fldid = files[fid].var[vid].fldid;
  
  status = nc_inq_varndims(ncid, fldid, &ndims);
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_get_var2D_dimname): Error in getting ndims of var %s from file %s",
	    files[fid].var[vid].name, files[fid].name );
    netcdf_error(errmsg, status);
  }

  if(ind < 0 || ind >= ndims) mpp_error("mpp_io(mpp_get_var_dimname): invalid ind value, ind should be between 0 and ndim-1");
  
  status = nc_inq_vardimid(ncid,fldid,dims);
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_get_var2D_dimname): Error in getting dimid of var %s from file %s",
	    files[fid].var[vid].name, files[fid].name );
    netcdf_error(errmsg, status);
  }
  status = nc_inq_dimname(ncid, dims[ind], name);
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_get_var2D_dimname): Error in getting %d dimension name of var %s from file %s",
	    ind, files[fid].var[vid].name, files[fid].name );
    netcdf_error(errmsg, status);
  }

}; /* mpp_get_var_dimname */
Ejemplo n.º 2
0
   std::vector<std::string> CONetCDF4::getDimensionsIdList (const std::string * _varname)
   {
      char full_name_in[NC_MAX_NAME +1];
      int nbdim = 0, *dimid = NULL;
      int grpid = this->getCurrentGroup();
      int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
      std::vector<std::string> retvalue;

      if (_varname != NULL)
      {
         CheckError(nc_inq_varndims(grpid, varid, &nbdim));
         dimid = new int[nbdim]();
         CheckError(nc_inq_vardimid(grpid, varid, dimid));
      }
      else
      {
         CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
         dimid = new int[nbdim]();
         CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
      }

      for (int i = 0; i < nbdim; i++)
      {
         CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
         std::string dimname(full_name_in);
         retvalue.push_back(dimname);
      }
      delete [] dimid;

      return (retvalue);
   }
Ejemplo n.º 3
0
/* Given an ncid, check the file to make sure it has all the objects I
 * expect. */
int
check_classic_file(int ncid)
{
   int varid, dimid, attnum;
   size_t att_len;
   nc_type att_type;
   char name_in[sizeof(name_utf8) + 1], strings_in[sizeof(name_utf8) + 1];

   /* Check the variable. */
   if (nc_inq_varid(ncid, name_utf8, &varid)) ERR;
   if (nc_inq_varname(ncid, varid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;
   if (nc_inq_varid(ncid, norm_utf8, &varid)) ERR;
   name_in[0] = 0;
   if (nc_inq_varname(ncid, varid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;
   if (nc_get_var_text(ncid, varid, strings_in)) ERR;
   if (strncmp(name_utf8, strings_in, sizeof(name_utf8))) ERR;
   strings_in[0] = '\0'; /* Reset my string buffer. */

   /* Check the dimension. */
   if (nc_inq_dimid(ncid, name_utf8, &dimid)) ERR;
   if (nc_inq_dimname(ncid, dimid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;
   if (nc_inq_dimid(ncid, norm_utf8, &dimid)) ERR;
   if (nc_inq_dimname(ncid, dimid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;

   /* Check the attribute.  We don't normalize data or attribute
    * values, so get exactly what was put for the value, but
    * normalized values for names. */
   if (nc_inq_attid(ncid, varid, norm_utf8, &attnum)) ERR;
   if (attnum) ERR;
   attnum = 99; /* Reset. */
   if (nc_inq_attid(ncid, varid, name_utf8, &attnum)) ERR;
   if (attnum) ERR;
   if (nc_inq_att(ncid, varid, norm_utf8, &att_type, &att_len)) ERR;
   if (att_type != NC_CHAR || att_len != sizeof(name_utf8)) ERR;
   if (nc_get_att_text(ncid, varid, norm_utf8, strings_in)) ERR;
   if (strncmp(name_utf8, strings_in, sizeof(name_utf8))) ERR;
   return NC_NOERR;
}
Ejemplo n.º 4
0
int read_axes(char var_name[], double **array, size_t *nz, size_t *nx, size_t *ny) {
  size_t count[MAX_VAR_DIMS];
  int ncid, i, varid, ndims, dimids[MAX_VAR_DIMS], status;
  char dimname[NC_MAX_NAME];
  
  ncid = ncInid[0];
  if (ncid < 0) {
    printf("ERROR: Required file (%d) for reading axes of %s is not open.\n",0,var_name);
    exit(-1);
  }

  // printf("Inquire unlimdim of %s - id %d.\n",in_file,ncid);
  // status = nc_inq_unlimdim(ncid,&recdim);
  //if (status != NC_NOERR) handle_error(status,var_name,status);
  // printf("Done opening %s.\n",in_file);

  status = nc_inq_varid(ncid,var_name,&varid);
  if (status != NC_NOERR) handle_error(status,var_name,status);
  status = nc_inq_varndims(ncid,varid,&ndims);
  if (status != NC_NOERR) handle_error(status,var_name,status);
  if (ndims < 3) {
    printf("ERROR: Unable to determine array sizes from %d-D field %s in file 0.\n",
        ndims, var_name); return -1;
  }
  status = nc_inq_vardimid(ncid,varid,dimids);
  if (status != NC_NOERR) handle_error(status,var_name,status);
  // printf("Get %d dim lengths %s.\n",ndims,in_file);
  for (i=0;i<ndims;i++) {
    status = nc_inq_dimlen(ncid,dimids[i],&count[i]);
    if (status != NC_NOERR) handle_error(status,var_name,i);
  }
  *nz = count[ndims-3];
  *ny = count[ndims-2];
  *nx = count[ndims-1];

  // printf("Done getting info about %s.\n",var_name);

  if (*array == NULL) {
    *array = (double *) calloc(*nz, sizeof(double));
    if (*array == NULL) printf("Unable to allocate array of size %ld for %s.\n",(long) *nz,var_name);
  }
  
  status = nc_inq_dimname(ncid,dimids[ndims-3],dimname);
  if (status != NC_NOERR) handle_error(status,var_name,dimids[ndims-3]);
  status = nc_inq_varid(ncid, dimname, &varid);
  if (status != NC_NOERR) handle_error(status,dimname,status);
  status = nc_get_var_double(ncid,varid,*array);
  if (status != NC_NOERR) handle_error(status,dimname,status);
  
  if (status != NC_NOERR) return -1;

  return 0;
}
Ejemplo n.º 5
0
   std::string CONetCDF4::getUnlimitedDimensionName(void)
   {
      char full_name_in[NC_MAX_NAME +1];
      int grpid = this->getGroup(path);
      int dimid = this->getUnlimitedDimension();
      
      if (dimid == -1) return (std::string());
      CheckError(nc_inq_dimname(grpid, dimid, full_name_in));

      std::string dimname(full_name_in);
      return (dimname);
   }
Ejemplo n.º 6
0
NcDim::NcDim(NcFile* nc, int id)
	: the_file(nc), the_id(id)
{
    char nam[NC_MAX_NAME];
    if (the_file && NcError::set_err(
				     nc_inq_dimname(the_file->id(), the_id, nam)
				     ) == NC_NOERR) {
	the_name = new char[strlen(nam) + 1]; 
	strcpy(the_name, nam);
    } else {
	the_name = 0;
    }
}
Ejemplo n.º 7
0
NcBool NcDim::sync(void) 
{    
    char nam[NC_MAX_NAME];
    if (the_name) {
	delete [] the_name;
    }
    if (the_file && NcError::set_err(
				     nc_inq_dimname(the_file->id(), the_id, nam)
				     ) == NC_NOERR) {
	the_name = new char[strlen(nam) + 1]; 
	strcpy(the_name, nam);
	return TRUE;
    }
    the_name = 0;
    return FALSE;
}
Ejemplo n.º 8
0
/*!
This function makes a request to netcdf, returns name of a dimension, given its id
\param [in] ncid Groupd id (or File Id)
\param [in] dimId Id of desired dimension
\param [out] dimName Name of desired dimension
\return Status code
*/
int CNetCdfInterface::inqDimName(int ncid, int dimId, StdString& dimName)
{
  char fullNameIn[NC_MAX_NAME + 1];
  int status = nc_inq_dimname(ncid, dimId, fullNameIn);
  if (NC_NOERR != status)
  {
    StdString errormsg(nc_strerror(status));
    StdStringStream sstr;

    sstr << "Error when calling function nc_inq_dimname(ncid, dimId, fullNameIn)" << std::endl
         << errormsg << std::endl
         << "Unable to get dimension name: " << dimName << " given its id: " << dimId << std::endl;
    StdString e = sstr.str();
    throw CNetCdfException(e);
  }
  dimName = StdString(fullNameIn);
  return status;
}
Ejemplo n.º 9
0
int main(int argc, char* argv[]) 
{
   int c;
   int ncid; // id of netcdf file
   int dimid; // dimension id
   int varid; // variable id
   int attid; // attribute id
   int ndims; // number of dimensions
   int verbose=0; // level of verbosity
   char name[NC_MAX_NAME+1];
   
   if(argc<2) {
      usage(argv[0]);
      return 1;
   }
   
   // parse command-line arguments
   while ((c = getopt(argc, argv, "dh")) != -1)
      switch (c) {
      case 'd':
	 verbose++;
	 break;
      case 'h':
      default:
	 usage(argv[0]);
	 return 1;
      }
   
   __NC_ASRT__(nc_open(argv[optind],NC_NOWRITE,&ncid));
   __NC_ASRT__(nc_inq_ndims(ncid,&ndims));
   if (verbose) printf("Found %d dimensions\n",ndims);
   for (dimid=0; dimid<ndims; dimid++) {
      __NC_ASRT__(nc_inq_dimname(ncid,dimid,name));
      if (verbose) printf("Examining \"%s\"\n",name);
      if (nc_inq_varid(ncid,name,&varid)==NC_NOERR &&
          nc_inq_attid(ncid,varid,"compress",&attid)==NC_NOERR) {
          return 0;
      }
   }
   __NC_ASRT__(nc_close(ncid));

   return -1;
}
Ejemplo n.º 10
0
Archivo: ncdf3.c Proyecto: cran/ncdf
/*******************************************************************************
 * Internal utility function that returns '1' if the passed var name is
 * the name of a dimvar, '0' if it is NOT the name of a dimvar, and '-1' on error.
 */
int R_ncu_isdimvar( int ncid, char *name ) 
{
	int 	i, ndims, ierr;
	char 	dimname[MAX_NC_NAME];

	ierr = nc_inq_ndims( ncid, &ndims );
	if( ierr != NC_NOERR ) {
		error( "Internal error in ncdf package, routine R_ncu_isdimvar: error while reading file to get ndims!\n" );
		return( -1 );
		}

	for( i=0; i<ndims; i++ ) {
		ierr = nc_inq_dimname( ncid, i, dimname );
		if( ierr != NC_NOERR ) {
			error( "Internal error in ncdf package, routine R_ncu_isdimvar: error while reading file to get dim name!\n" );
			return( -1 );
			}
		if( strcmp( name, dimname ) == 0 )
			return(1);
		}

	return(0);
}
Ejemplo n.º 11
0
int
main(int argc, char **argv) 
{/* create file that caused seg fault in ncdump */

    int  ncid;  /* netCDF id */

    /* dimension ids */
    int Time_dim;
    int X_dim;
    int Y_dim;

    /* dimension lengths */
    size_t Time_len = NC_UNLIMITED;
    size_t X_len = 4;
    size_t Y_len = 3;

    /* variable ids */
    int Time_id;
    int P_id;

    /* rank (number of dimensions) for each variable */
#   define RANK_Time 1
#   define RANK_P 3

    /* variable shapes */
    int Time_dims[RANK_Time];
    int P_dims[RANK_P];

   printf("\n*** Testing preparation of fillbug test.\n");
   printf("*** creating fillbug test file %s...", FILENAME);

    /* enter define mode */
    if (nc_create(FILENAME, NC_CLOBBER|NC_NETCDF4, &ncid)) ERR;

    /* define dimensions */
    if (nc_def_dim(ncid, "Time", Time_len, &Time_dim)) ERR;
    if (nc_def_dim(ncid, "X", X_len, &X_dim)) ERR;
    if (nc_def_dim(ncid, "Y", Y_len, &Y_dim)) ERR;

    /* define variables */

    Time_dims[0] = Time_dim;
    if (nc_def_var(ncid, "Time", NC_DOUBLE, RANK_Time, Time_dims, &Time_id)) ERR;

    P_dims[0] = Time_dim;
    P_dims[1] = Y_dim;
    P_dims[2] = X_dim;
    if (nc_def_var(ncid, "P", NC_FLOAT, RANK_P, P_dims, &P_id)) ERR;

    /* leave define mode */
    if (nc_enddef (ncid)) ERR;

    {/* assign variable data */
    static double Time_data[1]={3.14159};
    static size_t Time_startset[1] = {0};
    static size_t Time_countset[1] = {1};
    if (nc_put_vara(ncid, Time_id, Time_startset, Time_countset, Time_data)) ERR;
    }

    if (nc_close(ncid)) ERR;

    /* Try to duplicate segfault ncdump gets by making the same calls
     * to the netCDF-4 library, in the same order.  This doesn't
     * result in the same segfault, so either we have missed a call
     * made by ncdump, or an earlier ncdump bug masks the real problem
     * until a call is made into the netCDF-4 library ...  */
    if (nc_open(FILENAME, NC_NOWRITE, &ncid)) ERR;
    
    {   		
	/* We declare local arrays with small constant sizes to avoid
	 * all the mallocs and frees used in ncdump.  For the example
	 * above, the fixed-size arrays are ample. */
	int format, ndims, nvars, ngatts, xdimid, ndims_grp, dimids_grp[3],
	    unlimids[1], d_grp, nunlim, nvars_grp, varids_grp[3], v_grp,
	    varid, varndims, vardims[3], varnatts, vartype, dimids[3], is_recvar,
	    vdims[3], id, ntypes, numgrps, atttype, nc_status;
	size_t dimsize, len, attlen;
	char dimname[20], varname[20];
	if ( nc_inq_format(ncid, &format)) ERR;
	ntypes = count_udtypes(ncid);
	if ( nc_inq_typeids(ncid, &ntypes, NULL) ) ERR;
	if ( nc_inq_format(ncid, &format)) ERR;
	if ( nc_inq_grps(ncid, &numgrps, NULL) ) ERR;
	if ( nc_inq_typeids(ncid, &ntypes, NULL) ) ERR;
	if ( nc_inq(ncid, &ndims, &nvars, &ngatts, &xdimid) ) ERR;
	if ( nc_inq_ndims(ncid, &ndims_grp) ) ERR;
	if ( nc_inq_dimids(ncid, 0, dimids_grp, 0) ) ERR;
	if ( nc_inq_unlimdims(ncid, &nunlim, NULL) ) ERR;
	if ( nc_inq_unlimdims(ncid, &nunlim, unlimids) ) ERR;
	for (d_grp = 0; d_grp < ndims_grp; d_grp++) {
	    int dimid = dimids_grp[d_grp];
	    if ( nc_inq_dim(ncid, dimid, dimname, &dimsize) ) ERR;
	}
	if ( nc_inq_format(ncid, &format) ) ERR;
	if ( nc_inq_varids(ncid, &nvars_grp, varids_grp) ) ERR;
	for (v_grp = 0; v_grp < nvars_grp; v_grp++) {
	    varid = varids_grp[v_grp];
	    if ( nc_inq_varndims(ncid, varid, &varndims) ) ERR;
	    if ( nc_inq_var(ncid, varid, varname, &vartype, 0, vardims, 
			    &varnatts) ) ERR;
	    for (id = 0; id < varndims; id++) {
		if ( nc_inq_dimname(ncid, vardims[id], dimname) ) ERR;
	    }
	}
	for (v_grp = 0; v_grp < nvars_grp; v_grp++) {
	    varid = varids_grp[v_grp];
	    if( nc_inq_varndims(ncid, varid, &varndims) ) ERR;
	    if( nc_inq_var(ncid, varid, varname, &vartype, 0, vardims, 
			   &varnatts) ) ERR;
	    {
		is_recvar = 0;
		if ( nc_inq_varndims(ncid, varid, &ndims) ) ERR;
		if (ndims > 0) {
		    int nunlimdims;
		    int recdimids[3];
		    int dim, recdim;
		    if ( nc_inq_vardimid(ncid, varid, dimids) ) ERR;
		    if ( nc_inq_unlimdims(ncid, &nunlimdims, NULL) ) ERR;
		    if ( nc_inq_unlimdims(ncid, NULL, recdimids) ) ERR;
		    for (dim = 0; dim < ndims && is_recvar == 0; dim++) {
			for(recdim = 0; recdim < nunlimdims; recdim++) {
			    if(dimids[dim] == recdimids[recdim]) {
				is_recvar = 1;
				break;
			    }		
			}
		    }
		}
	    }
	    for (id = 0; id < varndims; id++) {
		if( nc_inq_dimlen(ncid, vardims[id], &len) ) ERR;
		vdims[id] = len;
	    }
	    nc_status = nc_inq_att(ncid,varid,_FillValue,&atttype,&attlen);
	    nc_status = nc_inq_att(ncid, varid, "units", &atttype, &attlen);
	    nc_status = nc_inq_att(ncid, varid, "C_format", &atttype, &attlen);
	    if (varid == 0) {
		/* read Time variable */
		static double Time_data;
		static size_t cor[RANK_Time] = {0};
		static size_t edg[RANK_Time] = {1};
		if (nc_get_vara(ncid, varid, cor, edg, &Time_data)) ERR;
	    } else {
		/* read data slices from P variable, should get fill values */
		static float P_data[4];
		static size_t cor[RANK_P] = {0, 0, 0};
		static size_t edg[RANK_P] = {1, 1, 4};

		/* first slice retrieved OK */
		if (nc_get_vara(ncid, varid, cor, edg, P_data)) ERR;
		
		/* In ncdump, reading second slice gets seg fault in
		 * nc4_open_var_grp(), but this attempt to do all the
		 * same netCDF calls as ncdump can't duplicate the
		 * error, which would seem to implicate ncdump rather
		 * than HDF5 or netCDF-4 library ... */
		cor[1] = 1;
		if (nc_get_vara(ncid, varid, cor, edg, P_data)) ERR;
	    }
	}
    }
    if (nc_close(ncid)) ERR;
      
   SUMMARIZE_ERR;
   FINAL_RESULTS;
}
Ejemplo n.º 12
0
int
check_4D_example(char *file_name, int expected_format)
{
   int ncid;
   int format, ndims_in, nvars_in, natts_in;
   int dimid[NDIMS_EX];
   int varid[NVARS_EX];
   char dim_name_in[NDIMS_EX][NC_MAX_NAME];
   char var_name_in[NVARS_EX][NC_MAX_NAME];
   char name_in[NC_MAX_NAME + 1];
   char units_in[NC_MAX_NAME + 1];
   nc_type xtype_in;
   size_t len_in;
   int i;

   if (nc_open(file_name, 0, &ncid)) ERR;

   /* Count stuff. */
   if (nc_inq_format(ncid, &format)) ERR;
   if (nc_inq_ndims(ncid, &ndims_in)) ERR;
   if (ndims_in != NDIMS_EX) ERR;
   if (nc_inq_nvars(ncid, &nvars_in)) ERR;
   if (nvars_in != NVARS_EX) ERR;
   if (nc_inq_natts(ncid, &natts_in)) ERR;
   if (natts_in != 0) ERR;
   if (format != expected_format) ERR;

   /* Check dimensions. */
   ndims_in = 0;
   if (nc_inq_dimids(ncid, &ndims_in, dimid, 0)) ERR;
   if (ndims_in != NDIMS_EX) ERR;
   for (i = 0; i < NDIMS_EX; i++)
   {
      if (dimid[i] != i) ERR;
      if (nc_inq_dimname(ncid, i, dim_name_in[i])) ERR;
   }
   if (strcmp(dim_name_in[0], LVL_NAME) || strcmp(dim_name_in[1], LAT_NAME) ||
       strcmp(dim_name_in[2], LON_NAME) || strcmp(dim_name_in[3], REC_NAME)) ERR;

   /* Check variables. */
   nvars_in = 0;
   if (nc_inq_varids(ncid, &nvars_in, varid)) ERR;
   if (nvars_in != NVARS_EX) ERR;
   for (i = 0; i < NVARS_EX; i++)
   {
      if (varid[i] != i) ERR;
      if (nc_inq_varname(ncid, i, var_name_in[i])) ERR;
   }
   if (strcmp(var_name_in[0], LAT_NAME) || strcmp(var_name_in[1], LON_NAME) ||
       strcmp(var_name_in[2], PRES_NAME) || strcmp(var_name_in[3], TEMP_NAME)) ERR;

   if (nc_inq_var(ncid, 0, name_in, &xtype_in, &ndims_in, dimid, &natts_in)) ERR;
   if (strcmp(name_in, LAT_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 || 
       dimid[0] != 1 || natts_in != 1) ERR;
   if (nc_inq_var(ncid, 1, name_in, &xtype_in, &ndims_in, dimid, &natts_in)) ERR;
   if (strcmp(name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 || 
       dimid[0] != 2 || natts_in != 1) ERR;
   if (nc_inq_var(ncid, 2, name_in, &xtype_in, &ndims_in, dimid, &natts_in)) ERR;
   if (strcmp(name_in, PRES_NAME) || xtype_in != NC_FLOAT || ndims_in != 4 || 
       dimid[0] != 3 || dimid[1] != 0 || dimid[2] != 1 || dimid[3] != 2 || 
       natts_in != 1) ERR;
   if (nc_inq_var(ncid, 3, name_in, &xtype_in, &ndims_in, dimid, &natts_in)) ERR;
   if (strcmp(name_in, TEMP_NAME) || xtype_in != NC_FLOAT || ndims_in != 4 || 
       dimid[0] != 3 || dimid[1] != 0 || dimid[2] != 1 || dimid[3] != 2 || 
       natts_in != 1) ERR;

   /* Check variable atts. */
   if (nc_inq_att(ncid, 0, UNITS, &xtype_in, &len_in)) ERR;
   if (xtype_in != NC_CHAR || len_in != strlen(DEGREES_NORTH)) ERR;
   if (nc_get_att_text(ncid, 0, UNITS, units_in)) ERR;
   if (strncmp(units_in, DEGREES_NORTH, strlen(DEGREES_NORTH))) ERR;

   if (nc_inq_att(ncid, 1, UNITS, &xtype_in, &len_in)) ERR;
   if (xtype_in != NC_CHAR || len_in != strlen(DEGREES_EAST)) ERR;
   if (nc_get_att_text(ncid, 1, UNITS, units_in)) ERR;
   if (strncmp(units_in, DEGREES_EAST, strlen(DEGREES_EAST))) ERR;

   if (nc_inq_att(ncid, 2, UNITS, &xtype_in, &len_in)) ERR;
   if (xtype_in != NC_CHAR || len_in != strlen(PRES_UNITS)) ERR;
   if (nc_get_att_text(ncid, 2, UNITS, units_in)) ERR;
   if (strncmp(units_in, PRES_UNITS, strlen(PRES_UNITS))) ERR;

   if (nc_inq_att(ncid, 3, UNITS, &xtype_in, &len_in)) ERR;
   if (xtype_in != NC_CHAR || len_in != strlen(TEMP_UNITS)) ERR;
   if (nc_get_att_text(ncid, 3, UNITS, units_in)) ERR;
   if (strncmp(units_in, TEMP_UNITS, strlen(TEMP_UNITS))) ERR;

   if (nc_close(ncid)) ERR;
   return err;
}
Ejemplo n.º 13
0
int
main(int argc, char **argv)
{
   printf("\n*** Testing netcdf-4 coordinate variables and dimensions.\n");

   printf("**** testing Jeff Whitakers reported 4.1 bug...");
   {
#define NDIMS 2
#define NLAT 10
#define NLON 20
#define LAT_NAME "lat"
#define LON_NAME "lon"
#define NVARS 2
#define START_LAT 25.0
#define START_LON -125.0
      {
	 int ncid, lon_dimid, lat_dimid;
	 int lat_varid, lon_varid;
	 float lats[NLAT], lons[NLON];
	 int lat, lon;
	 int nvars, ndims, ngatts, unlimdimid, nvars_in, varids_in[NVARS];
	 int ndims_in, natts_in, dimids_in[NDIMS];
	 char var_name_in[NC_MAX_NAME + 1];
	 nc_type xtype_in;

	 /* Initialize coord data. */
	 for (lat = 0; lat < NLAT; lat++)
	    lats[lat] = START_LAT + 5. * lat;
	 for (lon = 0; lon < NLON; lon++)
	    lons[lon] = START_LON + 5. * lon;

	 /* Create file with two dimensions. */
	 if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
	 if (nc_def_dim(ncid, LAT_NAME, NLAT, &lat_dimid)) ERR;
	 if (nc_def_dim(ncid, LON_NAME, NLON, &lon_dimid)) ERR;

	 if (nc_def_var(ncid, LON_NAME, NC_FLOAT, 1, &lon_dimid, &lon_varid)) ERR;

	 /* Define and write longitude coord variable. */
	 if (nc_put_var_float(ncid, lon_varid, &lons[0])) ERR;

	 /* Define and write latitude coord variable. */
	 if (nc_def_var(ncid, LAT_NAME, NC_FLOAT, 1, &lat_dimid, &lat_varid)) ERR;
	 if (nc_put_var_float(ncid, lat_varid, &lats[0])) ERR;

	 if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
	 if (nvars != 2 || ndims != 2 || ngatts != 0 || unlimdimid != -1) ERR;
	 if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
	 if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
	 if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
	 if (strcmp(var_name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	     dimids_in[0] != 1 || natts_in != 0) ERR;

	 /* Close the file. */
	 if (nc_close(ncid)) ERR;

	 /* Re-open and check the file. */
	 if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

	 if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
	 if (nvars != 2 || ndims != 2 || ngatts != 0 || unlimdimid != -1) ERR;
	 if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
	 if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
	 if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
	 if (strcmp(var_name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	 dimids_in[0] != 1 || natts_in != 0) ERR;

	 if (nc_close(ncid)) ERR;
      }

   }
   SUMMARIZE_ERR;
   printf("**** testing setting cache values for coordinate variables...");
   {
#define RANK_1 1
#define DIM0_NAME "d0"
#define CACHE_SIZE 1000000
#define CACHE_NELEMS 1009
#define CACHE_PREEMPTION .90

      int ncid, dimid, varid;
      char name_in[NC_MAX_NAME + 1];

      /* Create a test file with one dim and coord variable. */
      if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM0_NAME, NC_UNLIMITED, &dimid)) ERR;
      if (nc_def_var(ncid, DIM0_NAME, NC_DOUBLE, 1, &dimid, &varid)) ERR;
      if (nc_set_var_chunk_cache(ncid, varid, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR;
      if (nc_close(ncid)) ERR;

      /* Reopen the file and check. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_varname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, DIM0_NAME)) ERR;
      if (nc_set_var_chunk_cache(ncid, 0, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR;
      if (nc_inq_dimname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, DIM0_NAME)) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing multi-line strings in attributes...");
   {
      int ncid_classic, ncid_nc4;
      /*int attid;*/
      char att_in_classic[NC_MAX_NAME + 1], att_in_nc4[NC_MAX_NAME + 1];

#define FILE_CLASSIC "tst_coords_classic_att.nc"
#define FILE_NC4 "tst_coords_nc4_att.nc"
      /* Create a classic and a netcdf-4 file. */
      if (nc_create(FILE_CLASSIC, 0, &ncid_classic)) ERR;
      if (nc_create(FILE_NC4, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid_nc4)) ERR;

      /* Write an att to both. */
      if (nc_put_att_text(ncid_classic, NC_GLOBAL, INST_NAME, strlen(INSTITUTION) + 1, INSTITUTION)) ERR;
      if (nc_put_att_text(ncid_nc4, NC_GLOBAL, INST_NAME, strlen(INSTITUTION) + 1, INSTITUTION)) ERR;

      /* Close them. */
      if (nc_close(ncid_classic)) ERR;
      if (nc_close(ncid_nc4)) ERR;

      /* Reopen the files. */
      if (nc_open(FILE_CLASSIC, 0, &ncid_classic)) ERR;
      if (nc_open(FILE_NC4, 0, &ncid_nc4)) ERR;

      /* I'll show you mine, if you show me yours... */
      if (nc_get_att_text(ncid_classic, NC_GLOBAL, INST_NAME, att_in_classic)) ERR;
      if (nc_get_att_text(ncid_nc4, NC_GLOBAL, INST_NAME, att_in_nc4)) ERR;
      if (strcmp(att_in_classic, INSTITUTION) || strcmp(att_in_nc4, INSTITUTION) ||
	  strcmp(att_in_classic, att_in_nc4)) ERR;
      if (memcmp(att_in_classic, att_in_nc4, strlen(INSTITUTION) + 1)) ERR;

      /* Close them. */
      if (nc_close(ncid_classic)) ERR;
      if (nc_close(ncid_nc4)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing ar-4 example metadata with ncgen-generated code...");
   {
      int  stat;  /* return status */
      int  ncid;  /* netCDF id */

      /* group ids */
      int root_grp;

      /* dimension ids */
      int lon_dim;
      int lat_dim;
      int bnds_dim;
      int time_dim;

      /* dimension lengths */
      size_t lon_len = 256;
      size_t lat_len = 128;
      size_t bnds_len = 2;
      size_t time_len = NC_UNLIMITED;

      /* variable ids */
      int lon_bnds_id;
      int lat_bnds_id;
      int time_bnds_id;
      int time_id;
      int lat_id;
      int lon_id;
      int pr_id;

      /* rank (number of dimensions) for each variable */
#   define RANK_lon_bnds 2
#   define RANK_lat_bnds 2
#   define RANK_time_bnds 2
#   define RANK_time 1
#   define RANK_lat 1
#   define RANK_lon 1
#   define RANK_pr 3

      /* variable shapes */
      int lon_bnds_dims[RANK_lon_bnds];
      int lat_bnds_dims[RANK_lat_bnds];
      int time_bnds_dims[RANK_time_bnds];
      int time_dims[RANK_time];
      int lat_dims[RANK_lat];
      int lon_dims[RANK_lon];
      int pr_dims[RANK_pr];

      /* enter define mode */
      stat = nc_create(FILE_NAME, NC_NETCDF4 | NC_CLASSIC_MODEL, &ncid);
      check_err(stat,__LINE__,__FILE__);
      root_grp = ncid;

      /* define dimensions */
      stat = nc_def_dim(root_grp, "lon", lon_len, &lon_dim);
      check_err(stat,__LINE__,__FILE__);
      stat = nc_def_dim(root_grp, "lat", lat_len, &lat_dim);
      check_err(stat,__LINE__,__FILE__);
      stat = nc_def_dim(root_grp, "bnds", bnds_len, &bnds_dim);
      check_err(stat,__LINE__,__FILE__);
      stat = nc_def_dim(root_grp, "time", time_len, &time_dim);
      check_err(stat,__LINE__,__FILE__);

      /* define variables */

      lon_bnds_dims[0] = lon_dim;
      lon_bnds_dims[1] = bnds_dim;
      stat = nc_def_var(root_grp, "lon_bnds", NC_DOUBLE, RANK_lon_bnds, lon_bnds_dims, &lon_bnds_id);
      check_err(stat,__LINE__,__FILE__);

      lat_bnds_dims[0] = lat_dim;
      lat_bnds_dims[1] = bnds_dim;
      stat = nc_def_var(root_grp, "lat_bnds", NC_DOUBLE, RANK_lat_bnds, lat_bnds_dims, &lat_bnds_id);
      check_err(stat,__LINE__,__FILE__);

      time_bnds_dims[0] = time_dim;
      time_bnds_dims[1] = bnds_dim;
      stat = nc_def_var(root_grp, "time_bnds", NC_DOUBLE, RANK_time_bnds, time_bnds_dims, &time_bnds_id);
      check_err(stat,__LINE__,__FILE__);

      time_dims[0] = time_dim;
      stat = nc_def_var(root_grp, "time", NC_DOUBLE, RANK_time, time_dims, &time_id);
      check_err(stat,__LINE__,__FILE__);

      lat_dims[0] = lat_dim;
      stat = nc_def_var(root_grp, "lat", NC_DOUBLE, RANK_lat, lat_dims, &lat_id);
      check_err(stat,__LINE__,__FILE__);

      lon_dims[0] = lon_dim;
      stat = nc_def_var(root_grp, "lon", NC_DOUBLE, RANK_lon, lon_dims, &lon_id);
      check_err(stat,__LINE__,__FILE__);

      pr_dims[0] = time_dim;
      pr_dims[1] = lat_dim;
      pr_dims[2] = lon_dim;
      stat = nc_def_var(root_grp, "pr", NC_FLOAT, RANK_pr, pr_dims, &pr_id);
      check_err(stat,__LINE__,__FILE__);

      /* assign global attributes */
      { /* table_id */
	 static const char table_id_att[8] = {"Table A1"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "table_id", 8, table_id_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* title */
	 static const char title_att[34] = {"model output prepared for IPCC AR4"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "title", 34, title_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* institution */
	 static const char institution_att[66] = {INSTITUTION} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, INST_NAME, 66, institution_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* source */
	 static const char source_att[153] = {"CCSM3.0, version vector05 (2004): \natmosphere: CAM3.0, T85L26;\nocean     : POP1.4.3 (modified), gx1v3\nsea ice   : CSIM5.0, gx1v3;\nland      : CLM3.0, T85"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "source", 153, source_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* contact */
	 static const char contact_att[13] = {"*****@*****.**"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "contact", 13, contact_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* project_id */
	 static const char project_id_att[22] = {"IPCC Fourth Assessment"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "project_id", 22, project_id_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* Conventions */
	 static const char Conventions_att[6] = {"CF-1.0"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "Conventions", 6, Conventions_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* references */
	 static const char references_att[137] = {"Collins, W.D., et al., 2005:\n The Community Climate System Model, Version 3\n Journal of Climate\n \n Main website: http://www.ccsm.ucar.edu"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "references", 137, references_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* acknowledgment */
	 static const char acknowledgment_att[847] = {" Any use of CCSM data should acknowledge the contribution\n of the CCSM project and CCSM sponsor agencies with the \n following citation:\n 'This research uses data provided by the Community Climate\n System Model project (www.ccsm.ucar.edu), supported by the\n Directorate for Geosciences of the National Science Foundation\n and the Office of Biological and Environmental Research of\n the U.S. Department of Energy.'\nIn addition, the words 'Community Climate System Model' and\n 'CCSM' should be included as metadata for webpages referencing\n work using CCSM data or as keywords provided to journal or book\npublishers of your manuscripts.\nUsers of CCSM data accept the responsibility of emailing\n citations of publications of research using CCSM data to\n [email protected].\nAny redistribution of CCSM data must include this data\n acknowledgement statement."} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "acknowledgment", 847, acknowledgment_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* realization */
	 static const int realization_att[1] = {8} ;
	 stat = nc_put_att_int(root_grp, NC_GLOBAL, "realization", NC_INT, 1, realization_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* experiment_id */
	 static const char experiment_id_att[46] = {"climate of the 20th Century experiment (20C3M)"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "experiment_id", 46, experiment_id_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* history */
	 static const char history_att[139] = {"Created from CCSM3 case b30.030g.ES01\n by [email protected]\n on Wed Sep 10 12:22:06 MDT 2008\n \n For all data, added IPCC requested metadata"} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "history", 139, history_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* comment */
	 static const char comment_att[1105] = {"This simulation was initiated from year 460 of \n CCSM3 model run b30.020.ES01 and executed on \n hardware Earth Simulator Center, JAMSTEC. The input external forcings are\nozone forcing    : mozart.o3.128x64_L18_1870-2000_c040515.nc\naerosol optics   : AerosolOptics_c040105.nc\naerosol MMR      : AerosolMass_V_128x256_clim_c031022.nc\ncarbon scaling   : carbonscaling_1870-2000_c040225.nc\nsolar forcing    : scon_lean_1870-2100_c040123.nc\nGHGs             : ghg_1870_2100_c040122.nc\nGHG loss rates   : noaamisc.r8.nc\nvolcanic forcing : VolcanicMass_1870-1999_64x1_L18_c040123.nc\nDMS emissions    : DMS_emissions_128x256_clim_c040122.nc\noxidants         : oxid_128x256_L26_clim_c040112.nc\nSOx emissions    : SOx_emissions_128x256_L2_1850-2000_c040321.nc\n Physical constants used for derived data:\n Lv (latent heat of evaporation): 2.501e6 J kg-1\n Lf (latent heat of fusion     ): 3.337e5 J kg-1\n r[h2o] (density of water      ): 1000 kg m-3\n g2kg   (grams to kilograms    ): 1000 g kg-1\n \n Integrations were performed by NCAR and CRIEPI with support\n and facilities provided by NSF, DOE, MEXT and ESC/JAMSTEC."} ;
	 stat = nc_put_att_text(root_grp, NC_GLOBAL, "comment", 1105, comment_att);
	 check_err(stat,__LINE__,__FILE__);
      }


      /* assign per-variable attributes */
      { /* calendar */
	 static const char time_calendar_att[6] = {"noleap"} ;
	 stat = nc_put_att_text(root_grp, time_id, "calendar", 6, time_calendar_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* standard_name */
	 static const char time_standard_name_att[4] = {"time"} ;
	 stat = nc_put_att_text(root_grp, time_id, "standard_name", 4, time_standard_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* axis */
	 static const char time_axis_att[1] = {"T"} ;
	 stat = nc_put_att_text(root_grp, time_id, "axis", 1, time_axis_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* units */
	 static const char time_units_att[19] = {"days since 0000-1-1"} ;
	 stat = nc_put_att_text(root_grp, time_id, "units", 19, time_units_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* bounds */
	 static const char time_bounds_att[9] = {"time_bnds"} ;
	 stat = nc_put_att_text(root_grp, time_id, "bounds", 9, time_bounds_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* long_name */
	 static const char time_long_name_att[4] = {"time"} ;
	 stat = nc_put_att_text(root_grp, time_id, "long_name", 4, time_long_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* axis */
	 static const char lat_axis_att[1] = {"Y"} ;
	 stat = nc_put_att_text(root_grp, lat_id, "axis", 1, lat_axis_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* standard_name */
	 static const char lat_standard_name_att[8] = {"latitude"} ;
	 stat = nc_put_att_text(root_grp, lat_id, "standard_name", 8, lat_standard_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* bounds */
	 static const char lat_bounds_att[8] = {"lat_bnds"} ;
	 stat = nc_put_att_text(root_grp, lat_id, "bounds", 8, lat_bounds_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* long_name */
	 static const char lat_long_name_att[8] = {"latitude"} ;
	 stat = nc_put_att_text(root_grp, lat_id, "long_name", 8, lat_long_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* units */
	 static const char lat_units_att[13] = {"degrees_north"} ;
	 stat = nc_put_att_text(root_grp, lat_id, "units", 13, lat_units_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* axis */
	 static const char lon_axis_att[1] = {"X"} ;
	 stat = nc_put_att_text(root_grp, lon_id, "axis", 1, lon_axis_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* standard_name */
	 static const char lon_standard_name_att[9] = {"longitude"} ;
	 stat = nc_put_att_text(root_grp, lon_id, "standard_name", 9, lon_standard_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* bounds */
	 static const char lon_bounds_att[8] = {"lon_bnds"} ;
	 stat = nc_put_att_text(root_grp, lon_id, "bounds", 8, lon_bounds_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* long_name */
	 static const char lon_long_name_att[9] = {"longitude"} ;
	 stat = nc_put_att_text(root_grp, lon_id, "long_name", 9, lon_long_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* units */
	 static const char lon_units_att[12] = {"degrees_east"} ;
	 stat = nc_put_att_text(root_grp, lon_id, "units", 12, lon_units_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* comment */
	 static const char pr_comment_att[60] = {"Created using NCL code CCSM_atmm_2cf.ncl on\n machine mineral"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "comment", 60, pr_comment_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* missing_value */
	 static const float pr_missing_value_att[1] = {1e+20} ;
	 stat = nc_put_att_float(root_grp, pr_id, "missing_value", NC_FLOAT, 1, pr_missing_value_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* _FillValue */
	 static const float pr_FillValue_att[1] = {1e+20} ;
	 stat = nc_put_att_float(root_grp, pr_id, "_FillValue", NC_FLOAT, 1, pr_FillValue_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* cell_methods */
	 static const char pr_cell_methods_att[30] = {"time: mean (interval: 1 month)"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "cell_methods", 30, pr_cell_methods_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* history */
	 static const char pr_history_att[20] = {"(PRECC+PRECL)*r[h2o]"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "history", 20, pr_history_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* original_units */
	 static const char pr_original_units_att[7] = {"m-1 s-1"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "original_units", 7, pr_original_units_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* original_name */
	 static const char pr_original_name_att[12] = {"PRECC, PRECL"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "original_name", 12, pr_original_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* standard_name */
	 static const char pr_standard_name_att[18] = {"precipitation_flux"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "standard_name", 18, pr_standard_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* units */
	 static const char pr_units_att[10] = {"kg m-2 s-1"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "units", 10, pr_units_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* long_name */
	 static const char pr_long_name_att[18] = {"precipitation_flux"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "long_name", 18, pr_long_name_att);
	 check_err(stat,__LINE__,__FILE__);
      }
      { /* cell_method */
	 static const char pr_cell_method_att[10] = {"time: mean"} ;
	 stat = nc_put_att_text(root_grp, pr_id, "cell_method", 10, pr_cell_method_att);
	 check_err(stat,__LINE__,__FILE__);
      }

      /* don't initialize variables with fill values */
      stat = nc_set_fill(root_grp, NC_NOFILL, 0);
      check_err(stat,__LINE__,__FILE__);

      /* leave define mode */
      stat = nc_enddef (root_grp);
      check_err(stat,__LINE__,__FILE__);

      stat = nc_close(root_grp);
      check_err(stat,__LINE__,__FILE__);

      {
#define NDIMS4 4
	 int ndims, dimids_in[NDIMS4];
	 char name_in[NC_MAX_NAME + 1];
	 char institution_att_in[NC_MAX_NAME + 1];

	 /* Now open this file and check order of dimensions. */
	 if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

	 /* Check dimids. */
	 if (nc_inq_dimname(ncid, 0, name_in)) ERR;
	 if (strcmp(name_in, "lon")) ERR;
	 if (nc_inq_dimname(ncid, 1, name_in)) ERR;
	 if (strcmp(name_in, "lat")) ERR;
	 if (nc_inq_dimname(ncid, 2, name_in)) ERR;
	 if (strcmp(name_in, "bnds")) ERR;
	 if (nc_inq_dimname(ncid, 3, name_in)) ERR;
	 if (strcmp(name_in, "time")) ERR;

	 /* Check inq_dimids function. */
	 if (nc_inq_dimids(ncid, &ndims, dimids_in, 0)) ERR;
	 if (ndims != NDIMS4 || dimids_in[0] != 0 || dimids_in[1] != 1 ||
	     dimids_in[2] != 2 || dimids_in[3] != 3) ERR;

	 /* Check attribute with line breaks. */
	 if (nc_get_att_text(ncid, NC_GLOBAL, INST_NAME,
			     institution_att_in)) ERR;
	 if (strncmp(institution_att_in, INSTITUTION, strlen(INSTITUTION))) ERR;

	 if (nc_close(ncid)) ERR;
      }

   }
   SUMMARIZE_ERR;
   printf("**** testing dim order when coord vars are defined in the wrong order...");
   {
#define RANK_2 2
#define DIM0 "d0"
#define DIM1 "d1"
      int ncid, dimids[RANK_2], varid[RANK_2];
      char name_in[NC_MAX_NAME + 1];

      /* Create a test file. */
      if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;

      /* Define dimensions in order. */
      if (nc_def_dim(ncid, DIM0, NC_UNLIMITED, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM1, 4, &dimids[1])) ERR;

      /* Define coordinate variables in a different order. */
      if (nc_def_var(ncid, DIM1, NC_DOUBLE, 1, &dimids[1], &varid[1])) ERR;
      if (nc_def_var(ncid, DIM0, NC_DOUBLE, 1, &dimids[0], &varid[0])) ERR;

      /* That's it! */
      if (nc_close(ncid)) ERR;

      /* Reopen the file and check dimension order. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

      if (nc_inq_dimname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, DIM0)) ERR;
      if (nc_inq_dimname(ncid, 1, name_in)) ERR;
      if (strcmp(name_in, DIM1)) ERR;

      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing order of coordinate dims...");
   {
#define RANK_3 3
#define DIM1_NAME "d1"
#define DIM2_NAME "d2"
#define DIM3_NAME "d3"
      int ncid, dimids[RANK_3], varid[RANK_3];
      char name_in[NC_MAX_NAME + 1];

      /* Create a 3D test file. */
      if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR;

      /* Define dimensions in order. */
      if (nc_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM2_NAME, 4, &dimids[1])) ERR;
      if (nc_def_dim(ncid, DIM3_NAME, 3, &dimids[2])) ERR;

      /* Define coordinate variables in a different order. */
      if (nc_def_var(ncid, DIM1_NAME, NC_DOUBLE, 1, &dimids[0], &varid[0])) ERR;
      if (nc_def_var(ncid, DIM2_NAME, NC_DOUBLE, 1, &dimids[1], &varid[1])) ERR;
      if (nc_def_var(ncid, DIM3_NAME, NC_DOUBLE, 1, &dimids[2], &varid[2])) ERR;

      /* That's it! */
      if (nc_close(ncid)) ERR;

      /* Reopen the file and check dimension order. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

      if (nc_inq_dimname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, DIM1_NAME)) ERR;
      if (nc_inq_dimname(ncid, 1, name_in)) ERR;
      if (strcmp(name_in, DIM2_NAME)) ERR;
      if (nc_inq_dimname(ncid, 2, name_in)) ERR;
      if (strcmp(name_in, DIM3_NAME)) ERR;

      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing coordinate vars...");
   {
#   define RANK_Coordinates_lat 1
      int ncid;
      int Coordinates_grp;
      int lat_dim;
      size_t lat_len = 3;
      int Coordinates_lat_id;

      if(nc_create(FILE_NAME, NC_CLOBBER|NC_NETCDF4, &ncid)) ERR;
      if (nc_def_grp(ncid, "Coordinates", &Coordinates_grp)) ERR;

      /* Define dimensions in root group. */
      if (nc_def_dim(ncid, "lat", lat_len, &lat_dim)) ERR;

      /* Define coordinate variable in Coordinates group. */
      if (nc_def_var(Coordinates_grp, "lat", NC_FLOAT,
		     1, &lat_dim, &Coordinates_lat_id)) ERR;

      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing 2D non-coordinate variable...");
   {
#define VAR_NAME "Britany"
#define NDIMS 2
#define TEXT_LEN 15
#define D0_NAME "time"
#define D1_NAME "tl"
      int ncid, nvars_in, varids_in[1];
      int time_dimids[NDIMS], time_id;
      size_t time_count[NDIMS], time_index[NDIMS] = {0, 0};
      const char ttext[TEXT_LEN]="20051224.150000";
      int nvars, ndims, ngatts, unlimdimid;
      int ndims_in, natts_in, dimids_in[NDIMS];
      char var_name_in[NC_MAX_NAME + 1];
      nc_type xtype_in;

      /* Create a netcdf-4 file with 2D coordinate var. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;

      if (nc_def_dim(ncid, D0_NAME, NC_UNLIMITED, &time_dimids[0])) ERR;
      if (nc_def_dim(ncid, D1_NAME, TEXT_LEN, &time_dimids[1])) ERR;
      if (nc_def_var(ncid, VAR_NAME, NC_USHORT, NDIMS, time_dimids,
		     &time_id) != NC_ESTRICTNC3) ERR;
      if (nc_def_var(ncid, VAR_NAME, NC_CHAR, NDIMS, time_dimids, &time_id)) ERR;
      if (nc_enddef(ncid)) ERR;

      /* Write one time to the coordinate variable. */
      time_count[0] = 1;
      time_count[1] = TEXT_LEN;
      if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR;
      if (nc_close(ncid)) ERR;

      /* Open the file and check. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
      if (nvars != 1 || ndims != 2 || ngatts != 0 || unlimdimid != 0) ERR;
      if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
      if (nvars_in != 1 || varids_in[0] != 0) ERR;
      if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(var_name_in, VAR_NAME) || xtype_in != NC_CHAR || ndims_in != 2 ||
          dimids_in[0] != 0 || dimids_in[1] != 1 || natts_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing 2D coordinate variable...");
   {
#define NDIMS 2
#define TEXT_LEN 15
#define D0_NAME "time"
#define D1_NAME "tl"
      int ncid, nvars_in, varids_in[1];
      int time_dimids[NDIMS], time_id;
      size_t time_count[NDIMS], time_index[NDIMS] = {0, 0};
      const char ttext[TEXT_LEN + 1]="20051224.150000";
      int nvars, ndims, ngatts, unlimdimid;
      int ndims_in, natts_in, dimids_in[NDIMS];
      char var_name_in[NC_MAX_NAME + 1];
      nc_type xtype_in;

      /* Create a netcdf-4 file with 2D coordinate var. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, D0_NAME, NC_UNLIMITED, &time_dimids[0])) ERR;
      if (nc_def_dim(ncid, D1_NAME, TEXT_LEN, &time_dimids[1])) ERR;
      if (nc_def_var(ncid, D0_NAME, NC_CHAR, NDIMS, time_dimids, &time_id)) ERR;

      /* Write one time to the coordinate variable. */
      time_count[0] = 1;
      time_count[1] = TEXT_LEN;
      if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR;
      if (nc_close(ncid)) ERR;

      /* Open the file and check. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
      if (nvars != 1 || ndims != 2 || ngatts != 0 || unlimdimid != 0) ERR;
      if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
      if (nvars_in != 1 || varids_in[0] != 0) ERR;
      if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(var_name_in, D0_NAME) || xtype_in != NC_CHAR || ndims_in != 2 ||
	dimids_in[0] != 0 || dimids_in[1] != 1 || natts_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing new order of doing things with coordinate variable...");
   {
      /* In this test:
           define a dimension
           define a variable that uses that dimension
           put values in the variable
           define coordinate values for the dimension
      */
#define VAR_NAME_BB "The_Birth_of_Britain"
#define NDIMS_1 1
#define TEXT_LEN 15
#define WINSTON_CHURCHILL "Winston_S_Churchill"
#define D0_LEN 2
#define NUM_VARS_2 2
      int ncid, nvars_in, varids_in[NUM_VARS_2];
      int dimid, varid, varid2;
      int nvars, ndims, ngatts, unlimdimid;
      int ndims_in, natts_in, dimids_in[NDIMS];
      char var_name_in[NC_MAX_NAME + 1];
      nc_type xtype_in;
      int data[D0_LEN] = {42, -42};

      /* Create a netcdf-4 file with 2D coordinate var. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, WINSTON_CHURCHILL, NC_UNLIMITED, &dimid)) ERR;
      if (nc_def_var(ncid, VAR_NAME, NC_INT, NDIMS_1, &dimid, &varid)) ERR;
      if (nc_put_var_int(ncid, varid, data)) ERR;
      if (nc_def_var(ncid, WINSTON_CHURCHILL, NC_INT, NDIMS_1, &dimid, &varid2)) ERR;
      if (nc_put_var_int(ncid, varid2, data)) ERR;

      /* Check things. */
      if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
      if (nvars != 2 || ndims != 1 || ngatts != 0 || unlimdimid != 0) ERR;
      if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
      if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
      if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(var_name_in, VAR_NAME) || xtype_in != NC_INT || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;

      if (nc_close(ncid)) ERR;

      /* Open the file and check. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
      if (nvars != 2 || ndims != 1 || ngatts != 0 || unlimdimid != 0) ERR;
      if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
      if (nvars_in != 2 || varids_in[0] != 0 || varids_in[1] != 1) ERR;
      if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(var_name_in, VAR_NAME) || xtype_in != NC_INT || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing 2D coordinate variable with dimensions defined in different order...");
   {
#define NDIMS 2
#define TEXT_LEN 15
#define D0_NAME "time"
#define D1_NAME "tl"
#define NUM_VARS 2
      int ncid, nvars_in, varids_in[NUM_VARS];
      int time_dimids[NDIMS], time_id, tl_id;
      size_t time_count[NDIMS], time_index[NDIMS] = {0, 0};
      const char ttext[TEXT_LEN + 1]="20051224.150000";
      char ttext_in[TEXT_LEN + 1];
      int nvars, ndims, ngatts, unlimdimid;
      int ndims_in, natts_in, dimids_in[NDIMS];
      char var_name_in[NC_MAX_NAME + 1], dim_name_in[NC_MAX_NAME + 1];
      size_t len_in;
      nc_type xtype_in;

      /* Create a netcdf-4 file with 2D coordinate var. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, D1_NAME, TEXT_LEN, &time_dimids[1])) ERR;
      if (nc_def_dim(ncid, D0_NAME, NC_UNLIMITED, &time_dimids[0])) ERR;
      if (nc_def_var(ncid, D0_NAME, NC_CHAR, NDIMS, time_dimids, &time_id)) ERR;
      if (nc_def_var(ncid, D1_NAME, NC_CHAR, 1, &time_dimids[0], &tl_id)) ERR;

      /* Write one time to the coordinate variable. */
      time_count[0] = 1;
      time_count[1] = TEXT_LEN;
      if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR;

      /* Check the data. */
      if (nc_get_vara_text(ncid, time_id, time_index, time_count, ttext_in)) ERR;
      if (strncmp(ttext, ttext_in, TEXT_LEN)) ERR;

      /* Close up. */
      if (nc_close(ncid)) ERR;

      /* Open the file and check. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
      if (nvars != NUM_VARS || ndims != NDIMS || ngatts != 0 || unlimdimid != 1) ERR;
      if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
      if (nvars_in != NUM_VARS || varids_in[0] != 0 || varids_in[1] != 1) ERR;
      if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(var_name_in, D0_NAME) || xtype_in != NC_CHAR || ndims_in != NDIMS ||
	dimids_in[0] != 1 || dimids_in[1] != 0 || natts_in != 0) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != NDIMS || dimids_in[0] != 0 || dimids_in[1] != 1) ERR;
      if (nc_inq_dim(ncid, 0, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, D1_NAME) || len_in != TEXT_LEN) ERR;
      if (nc_inq_dim(ncid, 1, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, D0_NAME) || len_in != 1) ERR;

      /* Check the data. */
      if (nc_get_vara_text(ncid, time_id, time_index, time_count, ttext_in)) ERR;
      if (strncmp(ttext, ttext_in, TEXT_LEN)) ERR;

      /* Close up. */
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   FINAL_RESULTS;
}
Ejemplo n.º 14
0
int
main(int argc, char **argv)
{
   printf("\n*** Testing netcdf-4 dimensions.\n");
   printf("*** Testing that netcdf-4 dimids inq works on netcdf-3 file...");
   {
      int ncid, dimid;
      int ndims_in, dimids_in[MAX_DIMS];

      /* Create a netcdf-3 file with one dim. */
      if (nc_create(FILE_NAME, 0, &ncid)) ERR;
      if (nc_def_dim(ncid, LAT_NAME, LAT_LEN, &dimid)) ERR;
      if (nc_close(ncid)) ERR;

      /* Open the file and make sure nc_inq_dimids yeilds correct
       * result. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_unlimdims(ncid, &ndims_in, dimids_in)) ERR;
      if (ndims_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing that netcdf-4 dimids inq works on more complex netcdf-3 file...");
   {
      int ncid, dimid;
      int lon_dimid;
      int ndims_in, dimids_in[MAX_DIMS];

      /* Create a netcdf-3 file with three dim. */
      if (nc_create(FILE_NAME, 0, &ncid)) ERR;
      if (nc_def_dim(ncid, LEVEL_NAME, NC_UNLIMITED, &dimid)) ERR;
      if (nc_def_dim(ncid, LAT_NAME, LAT_LEN, &dimid)) ERR;
      if (nc_def_dim(ncid, LON_NAME, LON_LEN, &lon_dimid)) ERR;
      if (nc_close(ncid)) ERR;

      /* Open the file and make sure nc_inq_dimids yeilds correct
       * result. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 3 || dimids_in[0] != 0 || dimids_in[1] != 1 ||
	 dimids_in[2] != 2) ERR;
      if (nc_inq_unlimdims(ncid, &ndims_in, dimids_in)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** Testing file with just one dimension...");
   {
      int ncid, dimid;
      int ndims_in, dimids_in[MAX_DIMS];
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int dimid_in;

      /* Create a file with one dim and nothing else. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, LAT_NAME, LAT_LEN, &dimid)) ERR;

      /* Check out what we've got. */
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != LAT_LEN || strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1) ERR;
      if (nc_inq_dimid(ncid, LAT_NAME, &dimid_in)) ERR;
      if (dimid_in != 0) ERR;
      if (nc_inq_dimname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
      if (len_in != LAT_LEN) ERR;
      if (nc_inq_unlimdims(ncid, &ndims_in, dimids_in)) ERR;
      if (ndims_in != 0) ERR;
      if (nc_close(ncid)) ERR;

      /* Reopen and check it out again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != LAT_LEN || strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1) ERR;
      if (nc_inq_dimid(ncid, LAT_NAME, &dimid_in)) ERR;
      if (dimid_in != 0) ERR;
      if (nc_inq_dimname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
      if (len_in != LAT_LEN) ERR;
      if (nc_inq_unlimdims(ncid, &ndims_in, dimids_in)) ERR;
      if (ndims_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** Testing renaming of one dimension...");
   {
      int ncid, dimid, dimid_in;
      char name_in[NC_MAX_NAME + 1];
      size_t len_in;
      int ndims_in, dimids_in[MAX_DIMS];

      /* Reopen the file with one dim, and change the name of the dim. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_rename_dim(ncid, 0, BUBBA)) ERR;

      /* Check out what we've got. */
      dimid = 0;
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != LAT_LEN || strcmp(name_in, BUBBA)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1) ERR;
      if (dimids_in[0] != 0) ERR;
      if (nc_inq_dimid(ncid, BUBBA, &dimid_in)) ERR;
      if (dimid_in != 0) ERR;
      if (nc_inq_dimname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, BUBBA)) ERR;
      if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
      if (len_in != LAT_LEN) ERR;
      if (nc_close(ncid)) ERR;

      /* Reopen and check out what we've got again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != LAT_LEN || strcmp(name_in, BUBBA)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_dimid(ncid, BUBBA, &dimid_in)) ERR;
      if (dimid_in != 0) ERR;
      if (nc_inq_dimname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, BUBBA)) ERR;
      if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
      if (len_in != LAT_LEN) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing renaming dimensions and vars...");
   {
#define FILE_NAME1 "foo1.nc"
#define FILE_NAME2 "foo2.nc"
#define FILE_NAME3 "foo3.nc"
#define FILE_NAME4 "foo4.nc"
#define DIM_NAME "lat_T42"
#define VAR_NAME DIM_NAME
#define DIM_NAME2 "lat"
#define VAR_NAME2 DIM_NAME2
#define RANK_lat_T42 1
      int  ncid, varid, dimid;
      int lat_T42_dim;
      size_t lat_T42_len = 3;
      int lat_T42_id;
      int lat_T42_dims[RANK_lat_T42];
      char name[NC_MAX_NAME + 1];

    /* =========== */
    /* Sub-test #1 */
    /* =========== */
      /* create file with dimension and associated coordinate variable */
      if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR;
      lat_T42_dims[0] = lat_T42_dim;
      if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, rename coordinate dimension and then associated variable */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR;
      if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR;
      if (nc_rename_dim(ncid, dimid, DIM_NAME2)) ERR;
      if (nc_rename_var(ncid, varid, VAR_NAME2)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, check coordinate dimension and associated variable names */
      /* Should be just like they created the file with DIM_NAME2 & VAR_NAME2 to
       *  begin with.
       */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_dimid(ncid, DIM_NAME2, &dimid)) ERR;
      if (nc_inq_varid(ncid, VAR_NAME2, &varid)) ERR;
      if (nc_inq_dimname(ncid, dimid, name)) ERR;
      if (strcmp(name, DIM_NAME2)) ERR;
      if (nc_inq_varname(ncid, varid, name)) ERR;
      if (strcmp(name, VAR_NAME2)) ERR;
      if (nc_close(ncid)) ERR;


    /* =========== */
    /* Sub-test #2 */
    /* =========== */
      /* create file with dimension and associated coordinate variable */
      if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR;
      lat_T42_dims[0] = lat_T42_dim;
      if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, just rename coordinate dimension */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR;
      if (nc_rename_dim(ncid, dimid, DIM_NAME2)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, check coordinate dimension and associated variable names */
      /* Should be just like the file was created with DIM_NAME2 to begin with */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_dimid(ncid, DIM_NAME2, &dimid)) ERR;
      if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR;
      if (nc_inq_dimname(ncid, dimid, name)) ERR;
      if (strcmp(name, DIM_NAME2)) ERR;
      if (nc_inq_varname(ncid, varid, name)) ERR;
      if (strcmp(name, VAR_NAME)) ERR;
      if (nc_close(ncid)) ERR;


    /* =========== */
    /* Sub-test #3 */
    /* =========== */
      /* create file with dimension and associated coordinate variable */
      if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR;
      lat_T42_dims[0] = lat_T42_dim;
      if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, just rename variable */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR;
      if (nc_rename_var(ncid, varid, VAR_NAME2)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, check coordinate dimension and associated variable names */
      /* Should be just like the file was created with VAR_NAME2 to begin with */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR;
      if (nc_inq_varid(ncid, VAR_NAME2, &varid)) ERR;
      if (nc_inq_dimname(ncid, dimid, name)) ERR;
      if (strcmp(name, DIM_NAME)) ERR;
      if (nc_inq_varname(ncid, varid, name)) ERR;
      if (strcmp(name, VAR_NAME2)) ERR;
      if (nc_close(ncid)) ERR;


    /* =========== */
    /* Sub-test #4 */
    /* =========== */
      /* create file with dimension and associated coordinate variable */
      if (nc_create(FILE_NAME1, NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM_NAME, lat_T42_len, &lat_T42_dim)) ERR;
      lat_T42_dims[0] = lat_T42_dim;
      if (nc_def_var(ncid, VAR_NAME, NC_INT, RANK_lat_T42, lat_T42_dims, &lat_T42_id)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, rename associated variable and then coordinate dimension */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_dimid(ncid, DIM_NAME, &dimid)) ERR;
      if (nc_inq_varid(ncid, VAR_NAME, &varid)) ERR;
      if (nc_rename_var(ncid, varid, VAR_NAME2)) ERR;
      if (nc_rename_dim(ncid, dimid, DIM_NAME2)) ERR;
      if (nc_close(ncid)) ERR;


      /* reopen file, check coordinate dimension and associated variable names */
      /* Should be just like they created the file with DIM_NAME2 & VAR_NAME2 to
       *  begin with.
       */
      if (nc_open(FILE_NAME1, NC_WRITE, &ncid)) ERR;
      if (nc_inq_dimid(ncid, DIM_NAME2, &dimid)) ERR;
      if (nc_inq_varid(ncid, VAR_NAME2, &varid)) ERR;
      if (nc_inq_dimname(ncid, dimid, name)) ERR;
      if (strcmp(name, DIM_NAME2)) ERR;
      if (nc_inq_varname(ncid, varid, name)) ERR;
      if (strcmp(name, VAR_NAME2)) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing file with just one unlimited dimension...");
   {
      int ncid, dimid;
      int ndims_in, dimids_in[MAX_DIMS];
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int unlimdimid_in;
      int nunlimdims_in;

      /* Create a file with one unlimied dim and nothing else. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, LEVEL_NAME, NC_UNLIMITED, &dimid)) ERR;

      /* Check it out before the enddef. */
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != NC_UNLIMITED || strcmp(name_in, LEVEL_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_unlimdim(ncid, &unlimdimid_in)) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_inq_unlimdims(ncid, &nunlimdims_in, &unlimdimid_in)) ERR;
      if (nunlimdims_in != 1 || unlimdimid_in != 0) ERR;

      /* Automatically enddef and close. */
      if (nc_close(ncid)) ERR;

      /* Reopen and check it out. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != NC_UNLIMITED || strcmp(name_in, LEVEL_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_unlimdim(ncid, &unlimdimid_in)) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_inq_unlimdims(ncid, &nunlimdims_in, &unlimdimid_in)) ERR;
      if (nunlimdims_in != 1 || unlimdimid_in != 0) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
#define ROMULUS "Romulus"
#define REMUS "Remus"
#define DIMS2 2
   printf("*** Testing file with two unlimited dimensions...");
   {
      int ncid, dimid[DIMS2];
      int ndims_in, dimids_in[DIMS2];
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int unlimdimid_in[DIMS2];
      int nunlimdims_in;

      /* Create a file with two unlimited dims and nothing else. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, REMUS, NC_UNLIMITED, &dimid[0])) ERR;
      if (nc_def_dim(ncid, ROMULUS, NC_UNLIMITED, &dimid[1])) ERR;

      /* Check it out before the enddef. */
      if (nc_inq_dim(ncid, dimid[0], name_in, &len_in)) ERR;
      if (len_in != NC_UNLIMITED || strcmp(name_in, REMUS)) ERR;
      if (nc_inq_dim(ncid, dimid[1], name_in, &len_in)) ERR;
      if (len_in != NC_UNLIMITED || strcmp(name_in, ROMULUS)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 2 || dimids_in[0] != 0 || dimids_in[1] != 1) ERR;
      if (nc_inq_unlimdim(ncid, &unlimdimid_in[0])) ERR;
      if (unlimdimid_in[0] != 0) ERR;
      if (nc_inq_unlimdims(ncid, &nunlimdims_in, unlimdimid_in)) ERR;
      if (nunlimdims_in != 2 || unlimdimid_in[0] != 0 || unlimdimid_in[1] != 1) ERR;

      /* Automatically enddef and close. */
      if (nc_close(ncid)) ERR;

      /* Reopen and check it out. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing ordering of dimensions...");
   {
#define A_NAME "a"
#define B_NAME "b"
#define A_LEN 50
#define B_LEN 92
#define A_DIMID 1
#define B_DIMID 0

      int ncid;
      int ndims_in, dimids_in[MAX_DIMS];
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int dimid_a, dimid_b;

      /* Create a file with two dims and nothing else. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, B_NAME, B_LEN, &dimid_b)) ERR;
      if (nc_def_dim(ncid, A_NAME, A_LEN, &dimid_a)) ERR;
      if (dimid_b != B_DIMID || dimid_a != A_DIMID) ERR;

      /* Check out what we've got. */
      if (nc_inq_dim(ncid, dimid_a, name_in, &len_in)) ERR;
      if (len_in != A_LEN || strcmp(name_in, A_NAME)) ERR;
      if (nc_inq_dim(ncid, dimid_b, name_in, &len_in)) ERR;
      if (len_in != B_LEN || strcmp(name_in, B_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 2 || dimids_in[0] != 0 || dimids_in[1] != 1) ERR;

      if (nc_close(ncid)) ERR;

      /* Reopen and check it out again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

      if (nc_inq_dim(ncid, B_DIMID, name_in, &len_in)) ERR;
      if (len_in != B_LEN || strcmp(name_in, B_NAME)) ERR;
      if (nc_inq_dim(ncid, A_DIMID, name_in, &len_in)) ERR;
      if (len_in != A_LEN || strcmp(name_in, A_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 2 || dimids_in[0] != 0 ||
	  dimids_in[1] != 1) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing file with just one unlimited dimension and one var...");
   {
      int ncid, dimid, dimids[MAX_DIMS];
      int level_varid;
      int natts_in, ndims_in, dimids_in[MAX_DIMS];
      nc_type xtype_in;
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int unlimdimid_in;
      size_t start[MAX_DIMS], count[MAX_DIMS];
      int varid_in, nvars_in, nunlimdims_in;
      unsigned long long uint64_data[1] = {42};

      /* Create a file with one unlimied dim and nothing else. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, LEVEL_NAME, NC_UNLIMITED, &dimid)) ERR;
      if (dimid != 0) ERR;
      dimids[0] = dimid;
      if (nc_def_var(ncid, LEVEL_NAME, NC_UINT64, 1, dimids, &level_varid)) ERR;
      if (level_varid != 0) ERR;

      /* Check it out before enddef. */
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != 0 || strcmp(name_in, LEVEL_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_unlimdim(ncid, &unlimdimid_in)) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_inq_unlimdims(ncid, &nunlimdims_in, &unlimdimid_in)) ERR;
      if (nunlimdims_in != 1 || unlimdimid_in != 0) ERR;
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 1 || natts_in != 0 || unlimdimid_in != 0) ERR;
      if (nc_inq_varid(ncid, LEVEL_NAME, &varid_in)) ERR;
      if (varid_in != 0) ERR;
      if (nc_inq_var(ncid, 0, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LEVEL_NAME) || xtype_in != NC_UINT64 || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;
      if (nc_inq_varname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, LEVEL_NAME)) ERR;

      /* Now write one record of data to the var. */
      start[0] = 0;
      count[0] = 1;
      if (nc_put_vara_ulonglong(ncid, 0, start, count, uint64_data)) ERR;

      /* Check dimension informaiton again. Now the length of this
       * dimension should be one. */
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != 1 || strcmp(name_in, LEVEL_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
      if (len_in != 1) ERR;
      if (nc_inq_unlimdim(ncid, &unlimdimid_in)) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_inq_unlimdims(ncid, &nunlimdims_in, &unlimdimid_in)) ERR;
      if (nunlimdims_in != 1 || unlimdimid_in != 0) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 1 || natts_in != 0 || unlimdimid_in != 0) ERR;
      if (nc_inq_varid(ncid, LEVEL_NAME, &varid_in)) ERR;
      if (varid_in != 0) ERR;
      if (nc_inq_var(ncid, 0, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LEVEL_NAME) || xtype_in != NC_UINT64 || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;
      if (nc_inq_varname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, LEVEL_NAME)) ERR;

      /* Close the file. */
      if (nc_close(ncid)) ERR;

      /* Check it out. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != 1 || strcmp(name_in, LEVEL_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_unlimdim(ncid, &unlimdimid_in)) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_inq_unlimdims(ncid, &nunlimdims_in, &unlimdimid_in)) ERR;
      if (nunlimdims_in != 1 || unlimdimid_in != 0) ERR;
      if (unlimdimid_in != 0) ERR;
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 1 || natts_in != 0 || unlimdimid_in != 0) ERR;
      if (nc_inq_varid(ncid, LEVEL_NAME, &varid_in)) ERR;
      if (varid_in != 0) ERR;
      if (nc_inq_var(ncid, 0, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LEVEL_NAME) || xtype_in != NC_UINT64 || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;
      if (nc_inq_varname(ncid, 0, name_in)) ERR;
      if (strcmp(name_in, LEVEL_NAME)) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing adding a coordinate var to file with dimension...");
   {
      int ncid, dimid, dimids[MAX_DIMS];
      int natts_in, ndims_in, dimids_in[MAX_DIMS];
      nc_type xtype_in;
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int unlimdimid_in;
      int nvars_in, dim5_varid;

      /* Create a file with one dim and nothing else. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimid)) ERR;

      /* Check out what we've got. */
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 0 || natts_in != 0 ||
	 unlimdimid_in != -1) ERR;
      if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
      if (len_in != DIM5_LEN || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;

      if (nc_close(ncid)) ERR;

      /* Reopen and check it out again. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 0 || natts_in != 0 ||
	 unlimdimid_in != -1) ERR;
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != DIM5_LEN || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;

      /* Add a coordinate var for this dimension. */
      dimids[0] = 0;
      if (nc_def_var(ncid, DIM5_NAME, NC_FLOAT, 1, dimids, &dim5_varid)) ERR;

      /* Check it out. */
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 1 || natts_in != 0 ||
	 unlimdimid_in != -1) ERR;
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != DIM5_LEN || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_var(ncid, 0, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, DIM5_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;

      if (nc_close(ncid)) ERR;

      /* Reopen and check it out again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 1 || natts_in != 0 ||
	 unlimdimid_in != -1) ERR;
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != DIM5_LEN || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_var(ncid, 0, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, DIM5_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;

      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing adding a coordinate var to file with unlimited dimension...");
   {
      int ncid, dimid, dimids[MAX_DIMS];
      int natts_in, ndims_in, dimids_in[MAX_DIMS];
      nc_type xtype_in;
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int unlimdimid_in;
      size_t start[MAX_DIMS], count[MAX_DIMS], index[MAX_DIMS];
      unsigned short data[2] = {42, 24}, data_in[2];
      int nvars_in, hp_varid, dim5_varid;

      /* Create a file with one dim and one var. This time make
       * it an unlimited dim. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM5_NAME, NC_UNLIMITED, &dimid)) ERR;
      if (dimid != 0) ERR;
      dimids[0] = dimid;
      if (nc_def_var(ncid, HP_NAME, NC_USHORT, 1, dimids, &hp_varid)) ERR;
      if (hp_varid != 0) ERR;

      /* Check out what we've got. */
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 1 || natts_in != 0 ||
	 unlimdimid_in != 0) ERR;
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != 0 || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_var(ncid, 0, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, HP_NAME) || xtype_in != NC_USHORT || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;

      /* Add a record to the HP variable. */
      start[0] = 0;
      count[0] = 1;
      if (nc_put_vara(ncid, hp_varid, start, count, data)) ERR;

      /* Check to ensure dimension grew. */
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != 1 || strcmp(name_in, DIM5_NAME)) ERR;

      /* Reread the value just written. */
      index[0] = 0;
      if (nc_get_var1_ushort(ncid, hp_varid, index, data_in)) ERR;
      if (data_in[0] != data[0]) ERR;

      if (nc_close(ncid)) ERR;

      /* Reopen and check it out again. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 1 || natts_in != 0 ||
	 unlimdimid_in != 0) ERR;
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != 1 || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;

      /* Add a coordinate var for this dimension. */
      dimids[0] = 0;
      if (nc_def_var(ncid, DIM5_NAME, NC_FLOAT, 1, dimids, &dim5_varid)) ERR;

      /* Check it out. */
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 2 || natts_in != 0 ||
	 unlimdimid_in != 0) ERR;
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != 1 || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_var(ncid, dim5_varid, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, DIM5_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;

      if (nc_close(ncid)) ERR;

      /* Reopen and check it out again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims_in, &nvars_in, &natts_in, &unlimdimid_in)) ERR;
      if (ndims_in != 1 || nvars_in != 2 || natts_in != 0 ||
	 unlimdimid_in != 0) ERR;
      if (nc_inq_dim(ncid, 0, name_in, &len_in)) ERR;
      if (len_in != 1 || strcmp(name_in, DIM5_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1 || dimids_in[0] != 0) ERR;
      if (nc_inq_var(ncid, dim5_varid, name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, DIM5_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != 0 || natts_in != 0) ERR;

      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Creating file with 1 data var, 2 dims, and 2 coord. vars...");

   {
      int ncid, dimids[MAX_DIMS];
      int lat_dimid, lon_dimid, lat_varid, lon_varid;
      int pres_varid;
      char name_in[NC_MAX_NAME + 1];
      int natts_in, ndims_in, dimids_in[MAX_DIMS];
      nc_type xtype_in;
      size_t len_in;
      float lat[LAT_LEN], lon[LON_LEN];
      float lat_in[LAT_LEN], lon_in[LON_LEN];
      double pres[LAT_LEN][LON_LEN], pres_in[LAT_LEN][LON_LEN];
      int i, j;

      /* Lats and lons suitable for some South American data. */
      for (lat[0] = 40.0, i = 1; i < LAT_LEN; i++)
	 lat[i] = lat[i - 1] + .5;
      for (lon[0] = 20.0, i = 1; i < LON_LEN; i++)
	 lon[i] = lon[i - 1] + 1.5;

      /* Some phoney 2D pressure data. */
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    pres[i][j] = 1013.1 + j;

      /* Create a file. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;

      /* Define lat and lon dimensions, with associated variables. */
      if (nc_def_dim(ncid, LAT_NAME, LAT_LEN, &lat_dimid)) ERR;
      dimids[0] = lat_dimid;
      if (nc_def_var(ncid, LAT_NAME, NC_FLOAT, 1, dimids, &lat_varid)) ERR;
      if (nc_def_dim(ncid, LON_NAME, LON_LEN, &lon_dimid)) ERR;
      dimids[0] = lon_dimid;
      if (nc_def_var(ncid, LON_NAME, NC_FLOAT, 1, dimids, &lon_varid)) ERR;

      /* Define a 2D variable called pressure, with NC_DOUBLE on a lat
       * lon grid. */
      dimids[0] = lat_dimid;
      dimids[1] = lon_dimid;
      if (nc_def_var(ncid, PRES_NAME, NC_DOUBLE, 2, dimids, &pres_varid)) ERR;

      /* Check our dimensions. */
      if (nc_inq_dim(ncid, lat_dimid, name_in, &len_in)) ERR;
      if (len_in != LAT_LEN || strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dim(ncid, lon_dimid, name_in, &len_in)) ERR;
      if (len_in != LON_LEN || strcmp(name_in, LON_NAME)) ERR;
      if (nc_inq_var(ncid, lat_varid, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LAT_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != lat_dimid || natts_in != 0) ERR;
      if (nc_inq_var(ncid, lon_varid, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != lon_dimid || natts_in != 0) ERR;

      /* Check our data variable. */
      if (nc_inq_var(ncid, pres_varid, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, PRES_NAME) || xtype_in != NC_DOUBLE || ndims_in != 2 ||
	  dimids_in[0] != lat_dimid || dimids_in[1] != lon_dimid || natts_in != 0) ERR;

      /* Write our latitude and longitude values. This writes all
       * metadata to disk too. */
      if (nc_put_var_float(ncid, lat_varid, lat)) ERR;
      if (nc_put_var_float(ncid, lon_varid, lon)) ERR;

      /* Write our 2D pressure values. */
      if (nc_put_var_double(ncid, pres_varid, (double *)pres)) ERR;

      /* Check our latitude and longitude values. */
      if (nc_get_var(ncid, lat_varid, lat_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 if (lat[i] != lat_in[i]) ERR;
      if (nc_get_var_float(ncid, lon_varid, lon_in)) ERR;
      for (i = 0; i < LON_LEN; i++)
	 if (lon[i] != lon_in[i]) ERR;

      /* Check our pressure values. */
      if (nc_get_var_double(ncid, pres_varid, (double *)pres_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    if (pres[i][j] != pres_in[i][j]) ERR;

      /* Close the file. */
      if (nc_close(ncid)) ERR;

      /* Reopen the file and check it out again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

      /* Check our dimensions. */
      if (nc_inq_dim(ncid, lat_dimid, name_in, &len_in)) ERR;
      if (len_in != LAT_LEN || strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dim(ncid, lon_dimid, name_in, &len_in)) ERR;
      if (len_in != LON_LEN || strcmp(name_in, LON_NAME)) ERR;
      if (nc_inq_var(ncid, lat_varid, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LAT_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != lat_dimid || natts_in != 0) ERR;
      if (nc_inq_var(ncid, lon_varid, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != lon_dimid || natts_in != 0) ERR;

      /* Check our data variable. */
      if (nc_inq_var(ncid, pres_varid, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, PRES_NAME) || xtype_in != NC_DOUBLE || ndims_in != 2 ||
	  dimids_in[0] != lat_dimid || dimids_in[1] != lon_dimid || natts_in != 0) ERR;

      /* Check our latitude and longitude values. */
      if (nc_get_var(ncid, lat_varid, lat_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 if (lat[i] != lat_in[i]) ERR;
      if (nc_get_var_float(ncid, lon_varid, lon_in)) ERR;
      for (i = 0; i < LON_LEN; i++)
	 if (lon[i] != lon_in[i]) ERR;

      /* Check our pressure values. */
      if (nc_get_var_double(ncid, pres_varid, (double *)pres_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    if (pres[i][j] != pres_in[i][j]) ERR;

      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Creating file with 3 data vars, 4 dims, and 2 coord. vars...");

   {
      int ncid, lat_dimid, dimids[MAX_DIMS];
      int level_dimid, time_dimid, elev_varid;
      int lat_varid, lon_dimid, lon_varid, pres_varid, hp_varid;
      double pres[LAT_LEN][LON_LEN][LEVEL_LEN][TIME_LEN];
      double pres_in[LAT_LEN][LON_LEN][LEVEL_LEN][TIME_LEN];
      unsigned short hp[LAT_LEN][LON_LEN][TIME_LEN];
      unsigned short hp_in[LAT_LEN][LON_LEN][TIME_LEN];
      unsigned long long elev[LAT_LEN][LON_LEN], elev_in[LAT_LEN][LON_LEN];
      size_t start[4], count[4];
      int nvars, ndims, natts, unlimdimid;
      int natts_in, ndims_in, dimids_in[MAX_DIMS];
      nc_type xtype_in;
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      float lat[LAT_LEN], lon[LON_LEN];
      float lat_in[LAT_LEN], lon_in[LON_LEN];
      int i, j, k, l;

      /* Some phony 4D pressure data. */
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    for (k = 0; k < LEVEL_LEN; k++)
	       for (l = 0; l <TIME_LEN; l++)
		  pres[i][j][k][l] = 1013.1 + j;

      /* Some phony 3D hp data. */
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    for (l = 0; l <TIME_LEN; l++)
	       hp[i][j][l] = 100 + l;

      /* Some phony 2D elevaton data. */
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    elev[i][j] = 1010101022223333ULL  + i + j;

      /* Some phony 1D lats and lons. */
      for (i = 0; i < LAT_LEN; i++)
	 lat[i] = i * 5.;
      for (i = 0; i < LON_LEN; i++)
	 lon[i] = i * 5.;

      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;

      /* Define lat, lon, level, and timestep dimensions, with
       * associated coordinate variables for lat and lon only. Time is
       * an unlimited dimension. */
      if (nc_def_dim(ncid, LAT_NAME, LAT_LEN, &lat_dimid)) ERR;
      if (lat_dimid != LAT_DIMID) ERR;
      dimids[0] = lat_dimid;
      if (nc_def_var(ncid, LAT_NAME, NC_FLOAT, 1, dimids, &lat_varid)) ERR;
      if (lat_varid != LAT_VARID) ERR;
      if (nc_def_dim(ncid, LON_NAME, LON_LEN, &lon_dimid)) ERR;
      if (lon_dimid != LON_DIMID) ERR;
      dimids[0] = lon_dimid;
      if (nc_def_var(ncid, LON_NAME, NC_FLOAT, 1, dimids, &lon_varid)) ERR;
      if (lon_varid != LON_VARID) ERR;
      if (nc_def_dim(ncid, LEVEL_NAME, LEVEL_LEN, &level_dimid)) ERR;
      if (level_dimid != LEVEL_DIMID) ERR;
      if (nc_def_dim(ncid, TIME_NAME, NC_UNLIMITED, &time_dimid)) ERR;
      if (time_dimid != TIME_DIMID) ERR;

      /* Define a 4D NC_DOUBLE variable called pressure. */
      dimids[0] = lat_dimid;
      dimids[1] = lon_dimid;
      dimids[2] = level_dimid;
      dimids[3] = time_dimid;
      if (nc_def_var(ncid, PRES_NAME, NC_DOUBLE, 4, dimids, &pres_varid)) ERR;
      if (pres_varid != PRES_VARID) ERR;

      /* Define a 2D variable for surface elevation. Use NC_INT64
       * because our units for this is Angstroms from Earth's
       * Center. */
      if (nc_def_var(ncid, ELEV_NAME, NC_INT64, 2, dimids, &elev_varid)) ERR;
      if (elev_varid != ELEV_VARID) ERR;

      /* Define a 3D NC_USHORT variable to store the number of Harry
       * Potter books in this grid square at this time (ignore HP
       * books in airplanes, dirigibles, hot air balloons, space
       * capsules, hang-gliders, parachutes, and flying on brooms). */
      dimids[2] = time_dimid;
      if (nc_def_var(ncid, HP_NAME, NC_USHORT, 3, dimids, &hp_varid)) ERR;
      if (hp_varid != HP_VARID) ERR;

      /* Did all our stuff make it into the internal metadata model
       * intact? */
      /* Check our dimensions. */
      if (nc_inq_dim(ncid, LAT_DIMID, name_in, &len_in)) ERR;
      if (len_in != LAT_LEN || strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dim(ncid, LON_DIMID, name_in, &len_in)) ERR;
      if (len_in != LON_LEN || strcmp(name_in, LON_NAME)) ERR;
      if (nc_inq_dim(ncid, LEVEL_DIMID, name_in, &len_in)) ERR;
      if (len_in != LEVEL_LEN || strcmp(name_in, LEVEL_NAME)) ERR;
      if (nc_inq_dim(ncid, TIME_DIMID, name_in, &len_in)) ERR;
      if (len_in != 0 || strcmp(name_in, TIME_NAME)) ERR;

      /* Check our coordinate variables. */
      if (nc_inq_var(ncid, LAT_VARID, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LAT_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != LAT_DIMID || natts_in != 0) ERR;
      if (nc_inq_var(ncid, LON_VARID, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, LON_NAME) || xtype_in != NC_FLOAT || ndims_in != 1 ||
	  dimids_in[0] != LON_DIMID || natts_in != 0) ERR;

      /* Check our data variables. */
      if (nc_inq_var(ncid, PRES_VARID, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, PRES_NAME) || xtype_in != NC_DOUBLE || ndims_in != 4 ||
	  dimids_in[0] != LAT_DIMID || dimids_in[1] != LON_DIMID ||
	  dimids_in[2] != LEVEL_DIMID || dimids_in[3] != TIME_DIMID ||
	  natts_in != 0) ERR;
      if (nc_inq_var(ncid, ELEV_VARID, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, ELEV_NAME) || xtype_in != NC_INT64 || ndims_in != 2 ||
	  dimids_in[0] != LAT_DIMID || dimids_in[1] != LON_DIMID ||
	  natts_in != 0) ERR;
      if (nc_inq_var(ncid, HP_VARID, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (strcmp(name_in, HP_NAME) || xtype_in != NC_USHORT || ndims_in != 3 ||
	  dimids_in[0] != LAT_DIMID || dimids_in[1] != LON_DIMID ||
	  dimids_in[2] != TIME_DIMID || natts_in != 0) ERR;

      /* Write our latitude and longitude values. This writes all
       * metadata to disk too. */
      if (nc_put_var_float(ncid, lat_varid, lat)) ERR;
      if (nc_put_var_float(ncid, lon_varid, lon)) ERR;

      /* Write our 4D pressure, elevation, and hp data. But this
       * should do nothing for pressure and hp, because these are
       * record vars, and nc_put_var_* doesn't do anything to record
       * vars, because it doesn't know how big the var is supposed to
       * be. */
      if (nc_put_var_double(ncid, pres_varid, (double *)pres)) ERR;
      if (nc_put_var_ulonglong(ncid, elev_varid, (unsigned long long *)elev)) ERR;
      if (nc_put_var_ushort(ncid, hp_varid, (unsigned short *)hp)) ERR;

      /* Check our latitude and longitude values. */
      if (nc_get_var(ncid, lat_varid, lat_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 if (lat[i] != lat_in[i]) ERR;
      if (nc_get_var_float(ncid, lon_varid, lon_in)) ERR;
      for (i = 0; i < LON_LEN; i++)
	 if (lon[i] != lon_in[i]) ERR;

      /* Make sure our pressure and hp variables are still
       * empty. get_var calls will return no error, but fetch no
       * data. */
      if (nc_inq_var(ncid, pres_varid, name_in, &xtype_in, &ndims_in,
		     dimids_in, &natts_in)) ERR;
      if (nc_inq_dim(ncid, dimids_in[3], NULL, &len_in)) ERR;
      if (len_in != 0) ERR;
      memset(pres_in, 0, sizeof(pres_in));
      if (nc_get_var_double(ncid, pres_varid, (double *)pres_in)) ERR;

      /* Check our pressure values. */
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    for (k = 0; k < LEVEL_LEN; k++)
	       for (l = 0; l <TIME_LEN; l++)
		  if (0 != pres_in[i][j][k][l]) ERR;

      if (nc_inq_var(ncid, hp_varid, NULL, NULL, &ndims_in,
		     dimids_in, NULL)) ERR;
      if (nc_inq_dim(ncid, dimids_in[2], NULL, &len_in)) ERR;
      if (len_in != 0) ERR;
      memset(hp_in, 0, sizeof(hp_in));
      if (nc_get_var_ushort(ncid, hp_varid, (unsigned short *)hp_in)) ERR;

      /* Check our hp values. */
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    for (l = 0; l <TIME_LEN; l++)
	       if (0 != hp_in[i][j][l]) ERR;

      /* Now use nc_put_vara to really write pressure and hp
       * data. Write TIME_LEN (4) records of each. */
      start[0] = start[1] = start[2] = start[3] = 0;
      count[0] = LAT_LEN;
      count[1] = LON_LEN;
      count[2] = LEVEL_LEN;
      count[3] = TIME_LEN;
      if (nc_put_vara(ncid, pres_varid, start, count,
		      (double *)pres)) ERR;
      count[2] = TIME_LEN;
      if (nc_put_vara(ncid, hp_varid, start, count,
		      (double *)hp)) ERR;

      /* Check our pressure values. */
      if (nc_get_var_double(ncid, pres_varid, (double *)pres_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    for (k = 0; k < LEVEL_LEN; k++)
	       for (l = 0; l <TIME_LEN; l++)
		  if (pres[i][j][k][l] != pres_in[i][j][k][l]) ERR;

      /* Check our elevation values. */
      if (nc_get_var_ulonglong(ncid, elev_varid, (unsigned long long *)elev_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    if (elev[i][j] != elev_in[i][j]) ERR;

      /* Check our hp values. */
      if (nc_get_var_ushort(ncid, hp_varid, (unsigned short *)hp_in)) ERR;
      for (i = 0; i < LAT_LEN; i++)
	 for (j = 0; j < LON_LEN; j++)
	    for (l = 0; l <TIME_LEN; l++)
	       if (hp[i][j][l] != hp_in[i][j][l]) ERR;

      /* Close the file. */
      if (nc_close(ncid)) ERR;

      /* Reopen the file and check it out again. At the moment, we
       * can't count on the varids and dimids being the same. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
      if (ndims != 4 || nvars != 5 || natts != 0) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Testing file with dims and only some coordinate vars...");
#define NDIMS_EX 4
#define NLAT 6
#define NLON 12
#define LAT_NAME_EX "latitude"
#define LON_NAME_EX "longitude"
#define NREC 2
#define REC_NAME "time"
#define LVL_NAME "level"
#define NLVL 2

/* Names of things. */
#define PRES_NAME "pressure"
#define TEMP_NAME "temperature"
#define UNITS "units"
#define DEGREES_EAST "degrees_east"
#define DEGREES_NORTH "degrees_north"

/* There are 4 vars, two for data, two for coordinate data. */
#define NVARS_EX 4

/* These are used to construct some example data. */
#define SAMPLE_PRESSURE 900
#define SAMPLE_TEMP 9.0
#define START_LAT 25.0
#define START_LON -125.0

/* For the units attributes. */
#define UNITS "units"
#define PRES_UNITS "hPa"
#define TEMP_UNITS "celsius"
#define LAT_UNITS "degrees_north"
#define LON_UNITS "degrees_east"
#define MAX_ATT_LEN 80
   {
      /* IDs for the netCDF file, dimensions, and variables. */
      int ncid, lon_dimid, lat_dimid;
      int lon_varid;
      int ndims_in;
      int dimid[NDIMS_EX];
      char dim_name_in[NDIMS_EX][NC_MAX_NAME];
      int i;

      /* Create the file. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;

      /* Define the dimensions. */
      if (nc_def_dim(ncid, LAT_NAME_EX, NLAT, &lat_dimid)) ERR;
      if (nc_def_dim(ncid, LON_NAME_EX, NLON, &lon_dimid)) ERR;

      /* Define a coordinate var. */
      if (nc_def_var(ncid, LON_NAME_EX, NC_FLOAT, 1, &lon_dimid,
			       &lon_varid)) ERR;

      /* Close the file. */
      if (nc_close(ncid)) ERR;

      if (nc_open(FILE_NAME, 0, &ncid)) ERR;

      /* Check dimensions. */
      ndims_in = 0;
      if (nc_inq_dimids(ncid, &ndims_in, dimid, 0)) ERR;
      if (ndims_in != 2) ERR;
      for (i = 0; i < 2; i++)
      {
	 if (dimid[i] != i) ERR;
	 if (nc_inq_dimname(ncid, i, dim_name_in[i])) ERR;
      }
      if (strcmp(dim_name_in[0], LAT_NAME_EX) ||
	  strcmp(dim_name_in[1], LON_NAME_EX)) ERR;

      /* Close the file. */
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** Testing file with just one very long dimension...");
   {
#define VERY_LONG_LEN (size_t)4500000000LL
      int ncid, dimid;
      int ndims_in, dimids_in[MAX_DIMS];
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int varid_in;

      if (SIZEOF_SIZE_T == 8)
      {
	 /* Create a file with one dim and nothing else. */
	 if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
	 if (nc_def_dim(ncid, LAT_NAME, VERY_LONG_LEN, &dimid)) ERR;

	 /* Check it out. */
	 if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
	 if (len_in != ((SIZEOF_SIZE_T == 8) ? VERY_LONG_LEN : NC_MAX_UINT) ||
	     strcmp(name_in, LAT_NAME)) ERR;
	 if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
	 if (ndims_in != 1) ERR;
	 if (nc_inq_dimid(ncid, LAT_NAME, &varid_in)) ERR;
	 if (varid_in != 0) ERR;
	 if (nc_inq_dimname(ncid, 0, name_in)) ERR;
	 if (strcmp(name_in, LAT_NAME)) ERR;
	 if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
	 if (len_in != ((SIZEOF_SIZE_T == 8) ? VERY_LONG_LEN : NC_MAX_UINT)) ERR;
	 if (nc_inq_unlimdims(ncid, &ndims_in, dimids_in)) ERR;
	 if (ndims_in != 0) ERR;
	 if (nc_close(ncid)) ERR;

	 /* Reopen and check it out again. */
	 if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
	 /* Check it out. */
	 if (nc_inq_dim(ncid, dimid, name_in, &len_in)) ERR;
	 if (len_in != ((SIZEOF_SIZE_T == 8) ? VERY_LONG_LEN : NC_MAX_UINT) ||
	     strcmp(name_in, LAT_NAME)) ERR;
	 if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
	 if (ndims_in != 1) ERR;
	 if (nc_inq_dimid(ncid, LAT_NAME, &varid_in)) ERR;
	 if (varid_in != 0) ERR;
	 if (nc_inq_dimname(ncid, 0, name_in)) ERR;
	 if (strcmp(name_in, LAT_NAME)) ERR;
	 if (nc_inq_dimlen(ncid, 0, &len_in)) ERR;
	 if (len_in != ((SIZEOF_SIZE_T == 8) ? VERY_LONG_LEN : NC_MAX_UINT)) ERR;
	 if (nc_inq_unlimdims(ncid, &ndims_in, dimids_in)) ERR;
	 if (ndims_in != 0) ERR;
	 if (nc_close(ncid)) ERR;
      }
   }
   SUMMARIZE_ERR;
   printf("*** Testing reference file with just one very long dimension...");
   {
#define REF_FILE_NAME "ref_tst_dims.nc"
      int ncid, dimid = 0;
      int ndims_in, dimids_in[MAX_DIMS];
      size_t len_in;
      char name_in[NC_MAX_NAME + 1];
      int varid_in;
      char file_in[NC_MAX_NAME + 1];
      int ret;

      strcpy(file_in, "");
      if (getenv("srcdir"))
      {
	 strcat(file_in, getenv("srcdir"));
	 strcat(file_in, "/");
      }
      strcat(file_in, REF_FILE_NAME);

      /* Reopen and check it out again. */
      if (nc_open(file_in, NC_NOWRITE, &ncid)) ERR;

      /* Check it out. */
      ret = nc_inq_dim(ncid, dimid, name_in, &len_in);
      if ((SIZEOF_SIZE_T >= 8 && ret) ||
	  (SIZEOF_SIZE_T < 8 && ret != NC_EDIMSIZE)) ERR;
      if (SIZEOF_SIZE_T < 8)
      {
	 if (len_in != NC_MAX_UINT) ERR;
      }
      else
      {
	 if (len_in != VERY_LONG_LEN) ERR;
      }
      if (strcmp(name_in, LAT_NAME)) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != 1) ERR;
      if (nc_inq_dimid(ncid, LAT_NAME, &varid_in)) ERR;
      if (varid_in != 0) ERR;
      if (nc_inq_unlimdims(ncid, &ndims_in, dimids_in)) ERR;
      if (ndims_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   FINAL_RESULTS;
}
Ejemplo n.º 15
0
OSErr NetCDFWindMoverCurv::TextRead(char *path, TMap **newMap, char *topFilePath) // don't want a map  
{
	// this code is for curvilinear grids
	OSErr err = 0;
	long i,j, numScanned, indexOfStart = 0;
	int status, ncid, latIndexid, lonIndexid, latid, lonid, recid, timeid, numdims;
	size_t latLength, lonLength, recs, t_len, t_len2;
	float timeVal;
	char recname[NC_MAX_NAME], *timeUnits=0, month[10];	
	char dimname[NC_MAX_NAME], s[256], topPath[256];
	WORLDPOINTFH vertexPtsH=0;
	float *lat_vals=0,*lon_vals=0,yearShift=0.;
	static size_t timeIndex,ptIndex[2]={0,0};
	static size_t pt_count[2];
	Seconds startTime, startTime2;
	double timeConversion = 1.;
	char errmsg[256] = "",className[256]="";
	char fileName[64],*modelTypeStr=0;
	Point where;
	OSType typeList[] = { 'NULL', 'NULL', 'NULL', 'NULL' };
	MySFReply reply;
	Boolean bTopFile = false, fIsNavy = false;	// for now keep code around but probably don't need Navy curvilinear wind
	//VelocityFH velocityH = 0;
	char outPath[256];
	
	if (!path || !path[0]) return 0;
	strcpy(fPathName,path);
	
	strcpy(s,path);
	SplitPathFile (s, fileName);
	strcpy(fFileName, fileName); // maybe use a name from the file
	status = nc_open(path, NC_NOWRITE, &ncid);
	//if (status != NC_NOERR) {err = -1; goto done;}
	if (status != NC_NOERR) 
	{
#if TARGET_API_MAC_CARBON
		err = ConvertTraditionalPathToUnixPath((const char *) path, outPath, kMaxNameLen) ;
		status = nc_open(outPath, NC_NOWRITE, &ncid);
#endif
		if (status != NC_NOERR) {err = -1; goto done;}
	}
	// check number of dimensions - 2D or 3D
	status = nc_inq_ndims(ncid, &numdims);
	if (status != NC_NOERR) {err = -1; goto done;}
	
	status = nc_inq_attlen(ncid,NC_GLOBAL,"generating_model",&t_len2);
	if (status != NC_NOERR) {fIsNavy = false; /*goto done;*/}	
	else 
	{
		fIsNavy = true;
		// may only need to see keyword is there, since already checked grid type
		modelTypeStr = new char[t_len2+1];
		status = nc_get_att_text(ncid, NC_GLOBAL, "generating_model", modelTypeStr);
		if (status != NC_NOERR) {fIsNavy = false; goto done;}	
		modelTypeStr[t_len2] = '\0';
		
		strcpy(fFileName, modelTypeStr); 
	}
	GetClassName(className);
	if (!strcmp("NetCDF Wind",className))
		SetClassName(fFileName); //first check that name is now the default and not set by command file ("NetCDF Wind")
	
	//if (fIsNavy)
	{
		status = nc_inq_dimid(ncid, "time", &recid); //Navy
		//if (status != NC_NOERR) {err = -1; goto done;}
		if (status != NC_NOERR) 
		{	status = nc_inq_unlimdim(ncid, &recid);	// issue of time not being unlimited dimension
			if (status != NC_NOERR) {err = -1; goto done;}
		}			
	}
	/*else
	 {
	 status = nc_inq_unlimdim(ncid, &recid);	// issue of time not being unlimited dimension
	 if (status != NC_NOERR) {err = -1; goto done;}
	 }*/
	
	//if (fIsNavy)
	status = nc_inq_varid(ncid, "time", &timeid); 
	if (status != NC_NOERR) 
	{	
		status = nc_inq_varid(ncid, "ProjectionHr", &timeid); 
		if (status != NC_NOERR) {err = -1; goto done;}
	}			
	//	if (status != NC_NOERR) {/*err = -1; goto done;*/timeid=recid;} 
	
	//if (!fIsNavy)
	//status = nc_inq_attlen(ncid, recid, "units", &t_len);	// recid is the dimension id not the variable id
	//else	// LAS has them in order, and time is unlimited, but variable/dimension names keep changing so leave this way for now
	status = nc_inq_attlen(ncid, timeid, "units", &t_len);
	if (status != NC_NOERR) 
	{
		timeUnits = 0;	// files should always have this info
		timeConversion = 3600.;		// default is hours
		startTime2 = model->GetStartTime();	// default to model start time
		//err = -1; goto done;
	}
	else
	{
		DateTimeRec time;
		char unitStr[24], junk[10];
		
		timeUnits = new char[t_len+1];
		//if (!fIsNavy)
		//status = nc_get_att_text(ncid, recid, "units", timeUnits);	// recid is the dimension id not the variable id
		//else
		status = nc_get_att_text(ncid, timeid, "units", timeUnits);
		if (status != NC_NOERR) {err = -1; goto done;} 
		timeUnits[t_len] = '\0'; // moved this statement before StringSubstitute, JLM 5/2/10
		StringSubstitute(timeUnits, ':', ' ');
		StringSubstitute(timeUnits, '-', ' ');
		StringSubstitute(timeUnits, 'T', ' ');
		StringSubstitute(timeUnits, 'Z', ' ');
		
		numScanned=sscanf(timeUnits, "%s %s %hd %hd %hd %hd %hd %hd",
						  unitStr, junk, &time.year, &time.month, &time.day,
						  &time.hour, &time.minute, &time.second) ;
		if (numScanned==5)	
		{time.hour = 0; time.minute = 0; time.second = 0; }
		else if (numScanned==7) // has two extra time entries ??	
			time.second = 0;
		else if (numScanned<8)	
		//else if (numScanned!=8)	
		{ 
			//timeUnits = 0;	// files should always have this info
			//timeConversion = 3600.;		// default is hours
			//startTime2 = model->GetStartTime();	// default to model start time
			err = -1; TechError("NetCDFWindMoverCurv::TextRead()", "sscanf() == 8", 0); goto done;
		}
		else
		{
			// code goes here, trouble with the DAYS since 1900 format, since converts to seconds since 1904
			if (time.year ==1900) {time.year += 40; time.day += 1; /*for the 1900 non-leap yr issue*/ yearShift = 40.;}
			DateToSeconds (&time, &startTime2);	// code goes here, which start Time to use ??
			if (!strcmpnocase(unitStr,"HOURS") || !strcmpnocase(unitStr,"HOUR"))
				timeConversion = 3600.;
			else if (!strcmpnocase(unitStr,"MINUTES") || !strcmpnocase(unitStr,"MINUTE"))
				timeConversion = 60.;
			else if (!strcmpnocase(unitStr,"SECONDS") || !strcmpnocase(unitStr,"SECOND"))
				timeConversion = 1.;
			else if (!strcmpnocase(unitStr,"DAYS") || !strcmpnocase(unitStr,"DAY"))
				timeConversion = 24.*3600.;
		}
	} 
	
	if (fIsNavy)
	{
		status = nc_inq_dimid(ncid, "gridy", &latIndexid); //Navy
		if (status != NC_NOERR) {err = -1; goto done;}
		status = nc_inq_dimlen(ncid, latIndexid, &latLength);
		if (status != NC_NOERR) {err = -1; goto done;}
		status = nc_inq_dimid(ncid, "gridx", &lonIndexid);	//Navy
		if (status != NC_NOERR) {err = -1; goto done;}
		status = nc_inq_dimlen(ncid, lonIndexid, &lonLength);
		if (status != NC_NOERR) {err = -1; goto done;}
		// option to use index values?
		status = nc_inq_varid(ncid, "grid_lat", &latid);
		if (status != NC_NOERR) {err = -1; goto done;}
		status = nc_inq_varid(ncid, "grid_lon", &lonid);
		if (status != NC_NOERR) {err = -1; goto done;}
	}
	else
	{
		for (i=0;i<numdims;i++)
		{
			if (i == recid) continue;
			status = nc_inq_dimname(ncid,i,dimname);
			if (status != NC_NOERR) {err = -1; goto done;}
			if (!strncmpnocase(dimname,"X",1) || !strncmpnocase(dimname,"LON",3) || !strncmpnocase(dimname,"nx",2))
			{
				lonIndexid = i;
			}
			if (!strncmpnocase(dimname,"Y",1) || !strncmpnocase(dimname,"LAT",3) || !strncmpnocase(dimname,"ny",2))
			{
				latIndexid = i;
			}
		}
		
		status = nc_inq_dimlen(ncid, latIndexid, &latLength);
		if (status != NC_NOERR) {err = -1; goto done;}
		status = nc_inq_dimlen(ncid, lonIndexid, &lonLength);
		if (status != NC_NOERR) {err = -1; goto done;}
		
		status = nc_inq_varid(ncid, "LATITUDE", &latid);
		if (status != NC_NOERR) 
		{
			status = nc_inq_varid(ncid, "lat", &latid);
			if (status != NC_NOERR) 
			{
				status = nc_inq_varid(ncid, "latitude", &latid);
				if (status != NC_NOERR) {err = -1; goto done;}
			}
		}
		status = nc_inq_varid(ncid, "LONGITUDE", &lonid);
		if (status != NC_NOERR) 
		{
			status = nc_inq_varid(ncid, "lon", &lonid);
			if (status != NC_NOERR) 
			{
				status = nc_inq_varid(ncid, "longitude", &lonid);
				if (status != NC_NOERR) {err = -1; goto done;}
			}
		}
	}
	
	pt_count[0] = latLength;
	pt_count[1] = lonLength;
	vertexPtsH = (WorldPointF**)_NewHandleClear(latLength*lonLength*sizeof(WorldPointF));
	if (!vertexPtsH) {err = memFullErr; goto done;}
	lat_vals = new float[latLength*lonLength]; 
	lon_vals = new float[latLength*lonLength]; 
	if (!lat_vals || !lon_vals) {err = memFullErr; goto done;}
	status = nc_get_vara_float(ncid, latid, ptIndex, pt_count, lat_vals);
	if (status != NC_NOERR) {err = -1; goto done;}
	status = nc_get_vara_float(ncid, lonid, ptIndex, pt_count, lon_vals);
	if (status != NC_NOERR) {err = -1; goto done;}
	for (i=0;i<latLength;i++)
	{
		for (j=0;j<lonLength;j++)
		{
			//if (lat_vals[(latLength-i-1)*lonLength+j]==fill_value)	// this would be an error
			//lat_vals[(latLength-i-1)*lonLength+j]=0.;
			//if (lon_vals[(latLength-i-1)*lonLength+j]==fill_value)
			//lon_vals[(latLength-i-1)*lonLength+j]=0.;
			INDEXH(vertexPtsH,i*lonLength+j).pLat = lat_vals[(latLength-i-1)*lonLength+j];	
			INDEXH(vertexPtsH,i*lonLength+j).pLong = lon_vals[(latLength-i-1)*lonLength+j];
		}
	}
	fVertexPtsH	 = vertexPtsH;
	
	status = nc_inq_dim(ncid, recid, recname, &recs);
	if (status != NC_NOERR) {err = -1; goto done;}
	if (recs<=0) {strcpy(errmsg,"No times in file. Error opening NetCDF wind file"); err =  -1; goto done;}
	
	fTimeHdl = (Seconds**)_NewHandleClear(recs*sizeof(Seconds));
	if (!fTimeHdl) {err = memFullErr; goto done;}
	for (i=0;i<recs;i++)
	{
		Seconds newTime;
		// possible units are, HOURS, MINUTES, SECONDS,...
		timeIndex = i;
		//if (!fIsNavy)
		//status = nc_get_var1_float(ncid, recid, &timeIndex, &timeVal);	// recid is the dimension id not the variable id
		//else
		status = nc_get_var1_float(ncid, timeid, &timeIndex, &timeVal);
		if (status != NC_NOERR) {err = -1; goto done;}
		newTime = RoundDateSeconds(round(startTime2+timeVal*timeConversion));
		//INDEXH(fTimeHdl,i) = startTime2+(long)(timeVal*timeConversion -yearShift*3600.*24.*365.25);	// which start time where?
		//if (i==0) startTime = startTime2+(long)(timeVal*timeConversion -yearShift*3600.*24.*365.25);
		INDEXH(fTimeHdl,i) = newTime-yearShift*3600.*24.*365.25;	// which start time where?
		if (i==0) startTime = newTime-yearShift*3600.*24.*365.25;
	}
	if (model->GetStartTime() != startTime || model->GetModelTime()!=model->GetStartTime())
	{
		if (true)	// maybe use NOAA.ver here?
		{
			short buttonSelected;
			//buttonSelected  = MULTICHOICEALERT(1688,"Do you want to reset the model start time to the first time in the file?",FALSE);
			if(!gCommandFileRun)	// also may want to skip for location files...
				buttonSelected  = MULTICHOICEALERT(1688,"Do you want to reset the model start time to the first time in the file?",FALSE);
			else buttonSelected = 1;	// TAP user doesn't want to see any dialogs, always reset (or maybe never reset? or send message to errorlog?)
			switch(buttonSelected){
				case 1: // reset model start time
					//bTopFile = true;
					model->SetModelTime(startTime);
					model->SetStartTime(startTime);
					model->NewDirtNotification(DIRTY_RUNBAR); // must reset the runbar
					break;  
				case 3: // don't reset model start time
					//bTopFile = false;
					break;
				case 4: // cancel
					err=-1;// user cancel
					goto done;
			}
		}
		//model->SetModelTime(startTime);
		//model->SetStartTime(startTime);
		//model->NewDirtNotification(DIRTY_RUNBAR); // must reset the runbar
	}
	
	fNumRows = latLength;
	fNumCols = lonLength;
	
	status = nc_close(ncid);
	if (status != NC_NOERR) {err = -1; goto done;}
	
	//err = this -> SetInterval(errmsg);
	//if(err) goto done;
	
	// look for topology in the file
	// for now ask for an ascii file, output from Topology save option
	// need dialog to ask for file
	//if (fIsNavy)	// for now don't allow for wind files
	{if (topFilePath[0]) {err = ReadTopology(topFilePath,newMap); goto done;}}
	if (!gCommandFileRun)
	{
		short buttonSelected;
		buttonSelected  = MULTICHOICEALERT(1688,"Do you have an extended topology file to load?",FALSE);
		switch(buttonSelected){
			case 1: // there is an extended top file
				bTopFile = true;
				break;  
			case 3: // no extended top file
				bTopFile = false;
				break;
			case 4: // cancel
				err=-1;// stay at this dialog
				goto done;
		}
	}
	if(bTopFile)
	{
#if TARGET_API_MAC_CARBON
		mysfpgetfile(&where, "", -1, typeList,
					 (MyDlgHookUPP)0, &reply, M38c, MakeModalFilterUPP(STDFilter));
		if (!reply.good)/* return USERCANCEL;*/
		{
			/*if (recs>0)
				err = this -> ReadTimeData(indexOfStart,&velocityH,errmsg);
			else {strcpy(errmsg,"No times in file. Error opening NetCDF file"); err =  -1;}
			if(err) goto done;*/
			err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPoints(newMap,errmsg);	
			//err = ReorderPoints(fStartData.dataHdl,newMap,errmsg);	// if u, v input separately only do this once?
	 		goto done;
		}
		else
			strcpy(topPath, reply.fullPath);
		
#else
		where = CenteredDialogUpLeft(M38c);
		sfpgetfile(&where, "",
				   (FileFilterUPP)0,
				   -1, typeList,
				   (DlgHookUPP)0,
				   &reply, M38c,
				   (ModalFilterUPP)MakeUPP((ProcPtr)STDFilter, uppModalFilterProcInfo));
		if (!reply.good) 
		{
			/*if (recs>0)
				err = this -> ReadTimeData(indexOfStart,&velocityH,errmsg);
			else {strcpy(errmsg,"No times in file. Error opening NetCDF file"); err =  -1;}
			if(err) goto done;*/
			err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPoints(newMap,errmsg);	
			//err = ReorderPoints(fStartData.dataHdl,newMap,errmsg);	
	 		/*if (err)*/ goto done;
		}
		
		my_p2cstr(reply.fName);
		
#ifdef MAC
		GetFullPath(reply.vRefNum, 0, (char *)reply.fName, topPath);
#else
		strcpy(topPath, reply.fName);
#endif
#endif		
		strcpy (s, topPath);
		err = ReadTopology(topPath,newMap);	
		goto done;
	}
	
	/*if (recs>0)
		err = this -> ReadTimeData(indexOfStart,&velocityH,errmsg);
	else {strcpy(errmsg,"No times in file. Error opening NetCDF wind file"); err =  -1;}
	if(err) goto done;*/
	err = dynamic_cast<NetCDFWindMoverCurv *>(this)->ReorderPoints(newMap,errmsg);	
	//err = ReorderPoints(fStartData.dataHdl,newMap,errmsg);	
	
done:
	if (err)
	{
		printNote("Error opening NetCDF wind file");
		if(fGrid)
		{
			fGrid ->Dispose();
			delete fGrid;
			fGrid = 0;
		}
		if(vertexPtsH) {DisposeHandle((Handle)vertexPtsH); vertexPtsH = 0;	fVertexPtsH	 = 0;}
	}
	
	if (timeUnits) delete [] timeUnits;
	if (lat_vals) delete [] lat_vals;
	if (lon_vals) delete [] lon_vals;
	if (modelTypeStr) delete [] modelTypeStr;
	//if (velocityH) {DisposeHandle((Handle)velocityH); velocityH = 0;}
	return err;
}
Ejemplo n.º 16
0
int read_field(int fn, int lev, char var_name[], double **array,
               size_t *nlay, size_t *nx, size_t *ny, double st[2]) {
  static int ncid;
  size_t start[MAX_VAR_DIMS] = {0}, count[MAX_VAR_DIMS];
  int i, varid, ndims, dimids[MAX_VAR_DIMS], recdim, status;
  
  ncid = ncInid[fn];
  if (ncid < 0) {
    printf("ERROR: Required file (%d) for reading %s is not open.\n",fn,var_name);
    exit(-1);
  }

  // printf("Inquire unlimdim of %s - id %d.\n",in_file,ncid);
  status = nc_inq_unlimdim(ncid,&recdim);
  if (status != NC_NOERR) handle_error(status,var_name,status);
  // printf("Done opening %s.\n",in_file);

  status = nc_inq_varid(ncid,var_name,&varid);
  if (status != NC_NOERR) handle_error(status,var_name,status);
  status = nc_inq_varndims(ncid,varid,&ndims);
  if (status != NC_NOERR) handle_error(status,var_name,status);
  status = nc_inq_vardimid(ncid,varid,dimids);
  if (status != NC_NOERR) handle_error(status,var_name,status);
  // printf("Get %d dim lengths %s.\n",ndims,in_file);
  for (i=0;i<ndims;i++) {
    status = nc_inq_dimlen(ncid,dimids[i],&count[i]);
    if (status != NC_NOERR) handle_error(status,var_name,i);
  }
  if (dimids[0] == recdim) {
    if (count[0] < lev+1) return -1;
    start[0] = lev; count[0] = 1;
  } else if (lev > 0) return -1;
  
  for (i=ndims-2;i<ndims;i++) {
    char dimname[NC_MAX_NAME];
    int varid;
    size_t index = 0;
    status = nc_inq_dimname(ncid,dimids[i],dimname);
    if (status != NC_NOERR) handle_error(status,var_name,i);
    status = nc_inq_varid(ncid, dimname, &varid);
    if (status != NC_NOERR) handle_error(status,dimname,status);
    status = nc_get_var1_double(ncid, varid, &index, &st[i-ndims+2]);
    if (status != NC_NOERR) handle_error(status,dimname,status);
  }
  
  // printf("Done getting info about %s.\n",var_name);
  
  if (*array == NULL) {
    size_t sz = 1;
    for (i=0;i<ndims;i++) if (count[i] > 1) sz *= count[i]+1;
    // printf("Attempting to allocate array of size %ld.\n",(long) sz);
    *array = (double *) calloc(sz, sizeof(double));
    if (*array == NULL) printf("Unable to allocate array of size %ld for %s.\n",(long) sz,var_name);
  }
  
  *nlay = count[ndims-3];
  *nx = count[ndims-1];
  *ny = count[ndims-2];

  {
    size_t sz = 1;
    for (i=0;i<ndims;i++) if (count[i] > 1) sz *= count[i];
    // printf("Attempting to read array of size %ld.\n",(long) sz);
  }
  status = nc_get_vara_double(ncid,varid,start,count,*array);
  
  if (status != NC_NOERR) return -1;

  return 0;
}
Ejemplo n.º 17
0
void bi::InputNetCDFBuffer::map() {
  int ncDim, ncVar;
  Var* var;
  std::string name;
  VarType type;
  int i, k, id;

  /* ns dimension */
  nsDim = nc_inq_dimid(ncid, "ns");
  if (nsDim >= 0) {
    BI_ERROR_MSG(ns < (int )nc_inq_dimlen(ncid, nsDim),
        "Given index " << ns << " outside range of ns dimension");
  }

  /* np dimension */
  npDim = nc_inq_dimid(ncid, "np");
  if (npDim >= 0) {
    BI_ERROR_MSG(np < 0 || np < (int )nc_inq_dimlen(ncid, npDim),
        "Given index " << np << " outside range of np dimension");
  }

  /* record dimensions, time and coordinate variables */
  int nvars = nc_inq_nvars(ncid);
  for (i = 0; i < nvars; ++i) {
    ncVar = i;
    name = nc_inq_varname(ncid, i);

    if (name.find("time") == 0) {
      /* is a time variable */
      ncDim = mapTimeDim(ncVar);
      if (ncDim >= 0) {
        BOOST_AUTO(iter, std::find(recDims.begin(), recDims.end(), ncDim));
        if (iter == recDims.end()) {
          /* newly encountered record dimension */
          recDims.push_back(ncDim);
          timeVars.push_back(ncVar);
          coordVars.push_back(-1);
        } else {
          /* record dimension encountered before */
          k = std::distance(recDims.begin(), iter);
          BI_ASSERT_MSG(timeVars[k] < 0,
              "Time variables " << nc_inq_varname(ncid, timeVars[k]) << " and " << name << " cannot share the same record dimension " << nc_inq_dimname(ncid, *iter));
          timeVars[k] = ncVar;
        }
      }
    } else if (name.find("coord") == 0) {
      /* is a coordinate variable */
      ncDim = mapCoordDim(ncVar);
      if (ncDim >= 0) {
        BOOST_AUTO(iter, std::find(recDims.begin(), recDims.end(), ncDim));
        if (iter == recDims.end()) {
          /* newly encountered record dimension */
          recDims.push_back(ncDim);
          timeVars.push_back(-1);
          coordVars.push_back(ncVar);
        } else {
          /* record dimension encountered before */
          k = std::distance(recDims.begin(), iter);
          BI_ASSERT_MSG(coordVars[k] < 0,
              "Coordinate variables " << nc_inq_varname(ncid, coordVars[k]) << " and " << name << " cannot share the same record dimension " << nc_inq_dimname(ncid, *iter));
          coordVars[k] = ncVar;
        }
      }
    }
  }

  /* model variables */
  for (i = 0; i < NUM_VAR_TYPES; ++i) {
    type = static_cast<VarType>(i);

    /* initialise NetCDF variables for this type */
    vars[type].resize(m.getNumVars(type), -1);

    /* map model variables */
    for (id = 0; id < m.getNumVars(type); ++id) {
      var = m.getVar(type, id);
      if (var->hasInput()) {
        BOOST_AUTO(pair, mapVarDim(var));
        k = pair.first;
        ncVar = pair.second;

        if (ncVar >= 0) {
          vars[type][id] = ncVar;
        }
        modelVars.insert(std::make_pair(k, var));
      }
    }
  }

  /* preload random access tables */
  std::multimap<real,int> seq;
  std::vector<size_t> starts(recDims.size(), 0), lens(recDims.size(), 0);
  real tnxt;

  for (k = 0; k < int(recDims.size()); ++k) {
    if (timeVars[k] >= 0 && modelVars.count(k) > 0) {
      /* ^ ignores record dimensions with no associated time or model
       *   variables */
      readTime(timeVars[k], starts[k], &lens[k], &tnxt);
      seq.insert(std::make_pair(tnxt, k));
    }
  }
  while (!seq.empty()) {
    /* next in time */
    tnxt = seq.begin()->first;
    k = seq.begin()->second;
    seq.erase(seq.begin());

    ncDim = recDims[k];
    ncVar = timeVars[k];

    if (times.empty() || times.back() != tnxt) {
      times.push_back(tnxt);
      recStarts.push_back(std::vector < size_t > (recDims.size(), 0));
      recLens.push_back(std::vector < size_t > (recDims.size(), 0));
    }
    recStarts.back()[k] = starts[k];
    recLens.back()[k] = lens[k];

    /* read next time and range for this time variable */
    starts[k] += lens[k];
    if (starts[k] < nc_inq_dimlen(ncid, ncDim)) {
      /* more to come on this record dimension */
      readTime(ncVar, starts[k], &lens[k], &tnxt);
      seq.insert(std::make_pair(tnxt, k));
    }
  }
}
Ejemplo n.º 18
0
/* Given an ncid, check the file to make sure it has all the objects I
 * expect. */
int
check_nc4_file(int ncid)
{
   int varid, dimid, attnum, grpid, grpid2, grpid3, numgrps;
   int numtypes, enum_typeid, comp_typeid;
   int class_in;
   size_t att_len, size_in, num_mem, nfields_in;
   nc_type att_type, base_type_in;
   char name_in[NC_MAX_NAME + 1], strings_in[NC_MAX_NAME + 1], value;

   /* Check the group. */
   if (nc_inq_grps(ncid, &numgrps, &grpid)) ERR;
   if (numgrps != 1) ERR;
   name_in[0] = 0;
   if (nc_inq_grpname(grpid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;

   /* Check the variable. */
   if (nc_inq_varid(grpid, name_utf8, &varid)) ERR;
   if (nc_inq_varname(grpid, varid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;
   if (nc_inq_varid(grpid, norm_utf8, &varid)) ERR;
   name_in[0] = 0;
   if (nc_inq_varname(grpid, varid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;
   if (nc_get_var(grpid, varid, strings_in)) ERR;
   if (strncmp(name_utf8, strings_in, sizeof(name_utf8))) ERR;
   strings_in[0] = '\0'; /* Reset my string buffer. */

   /* Check the dimension. */
   if (nc_inq_dimid(grpid, name_utf8, &dimid)) ERR;
   if (nc_inq_dimname(grpid, dimid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;
   if (nc_inq_dimid(grpid, norm_utf8, &dimid)) ERR;
   if (nc_inq_dimname(grpid, dimid, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;

   /* Check the attribute.  We don't normalize data or attribute
    * values, so get exactly what was put for the value, but
    * normalized values for names. */
   if (nc_inq_attid(grpid, varid, norm_utf8, &attnum)) ERR;
   if (attnum) ERR;
   attnum = 99; /* Reset. */
   if (nc_inq_attid(grpid, varid, name_utf8, &attnum)) ERR;
   if (attnum) ERR;
   if (nc_inq_att(grpid, varid, norm_utf8, &att_type, &att_len)) ERR;
   if (att_type != NC_CHAR || att_len != sizeof(name_utf8)) ERR;
   if (nc_get_att_text(grpid, varid, norm_utf8, strings_in)) ERR;
   if (strncmp(name_utf8, strings_in, sizeof(name_utf8))) ERR;

   /* Check the enum type. */
   if (nc_inq_grps(grpid, &numgrps, &grpid2)) ERR;
   if (numgrps != 1) ERR;
   if (nc_inq_typeids(grpid2, &numtypes, &enum_typeid)) ERR;
   if (numtypes != 1) ERR;
   if (nc_inq_user_type(grpid2, enum_typeid, name_in, &size_in, &base_type_in,
			       &nfields_in, &class_in)) ERR;
   if (strncmp(norm_utf8, name_in, strlen(norm_utf8)) || size_in != 1 ||
       base_type_in != NC_BYTE || nfields_in != 1 || class_in != NC_ENUM) ERR;
   name_in[0] = size_in = base_type_in = 0;
   if (nc_inq_enum(grpid2, enum_typeid, name_in, &base_type_in, &size_in, &num_mem)) ERR;
   if (strncmp(norm_utf8, name_in, strlen(norm_utf8)) || size_in != 1 ||
       base_type_in != NC_BYTE || num_mem != 1) ERR;
   if (nc_inq_enum_member(grpid2, enum_typeid, 0, name_in, &value)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8)) || value != ENUM_VALUE) ERR;

   /* Check the compound type. */
   if (nc_inq_grps(grpid2, &numgrps, &grpid3)) ERR;
   if (numgrps != 1) ERR;
   if (nc_inq_typeids(grpid3, &numtypes, &comp_typeid)) ERR;
   if (numtypes != 1) ERR;
   name_in[0] = 0;
   if (nc_inq_user_type(grpid3, comp_typeid, name_in, &size_in, &base_type_in,
			&nfields_in, &class_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8)) || size_in != sizeof(struct comp) ||
       base_type_in != NC_NAT || nfields_in != 1 || class_in != NC_COMPOUND) ERR;
   size_in = nfields_in = 999;
   if (nc_inq_compound(grpid3, comp_typeid, name_in, &size_in, &nfields_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8)) || size_in != sizeof(struct comp) ||
       nfields_in != 1) ERR;
   name_in[0] = 0;
   if (nc_inq_compound_fieldname(grpid3, comp_typeid, 0, name_in)) ERR;
   if (strncmp(norm_utf8, name_in, sizeof(norm_utf8))) ERR;
   return NC_NOERR;
}
Ejemplo n.º 19
0
std::pair<int,int> bi::InputNetCDFBuffer::mapVarDim(const Var* var) {
  /* pre-condition */
  BI_ASSERT(var != NULL);

  const VarType type = var->getType();
  Dim* dim;
  int ncVar, ncDim, i, j = 0, k = -1;
  std::vector<int> dimids;
  BI_UNUSED bool canHaveTime, canHaveP;

  canHaveTime = type == D_VAR || type == R_VAR || type == F_VAR
      || type == O_VAR;

  ncVar = nc_inq_varid(ncid, var->getInputName());
  if (ncVar >= 0) {
    dimids = nc_inq_vardimid(ncid, ncVar);

    /* check for ns-dimension */
    if (nsDim >= 0 && j < static_cast<int>(dimids.size())
        && dimids[j] == nsDim) {
      ++j;
    }

    /* check for record dimension */
    if (j < static_cast<int>(dimids.size())) {
      BOOST_AUTO(iter, std::find(recDims.begin(), recDims.end(), dimids[j]));
      if (iter != recDims.end()) {
        k = std::distance(recDims.begin(), iter);
        ++j;
      }
    }

    /* check for np-dimension */
    if (npDim >= 0 && j < static_cast<int>(dimids.size())
        && dimids[j] == npDim) {
      ++j;
    } else if (j < static_cast<int>(dimids.size())) {
      /* check for model dimensions */
      for (i = var->getNumDims() - 1;
          i >= 0 && j < static_cast<int>(dimids.size()); --i, ++j) {
        dim = var->getDim(i);
        ncDim = dimids[j];

        BI_ERROR_MSG(dim->getName().compare(nc_inq_dimname(ncid, ncDim)) == 0,
            "Dimension " << j << " of variable " << var->getName() << " should be " << dim->getName() << " not " << nc_inq_dimname(ncid, ncDim) << ", in file " << file);
        BI_ERROR_MSG(k < 0 || coordVars[k] < 0,
            "Variable " << nc_inq_varname(ncid, ncVar) << " has both dense and sparse definitions, in file " << file);
      }
      BI_ERROR_MSG(i == -1,
          "Variable " << nc_inq_varname(ncid, ncVar) << " is missing one or more dimensions, in file " << file);

      /* check again for np dimension */
      if (npDim >= 0 && j < static_cast<int>(dimids.size())
          && dimids[j] == npDim) {
        ++j;
      }
    }
    BI_ERROR_MSG(j == static_cast<int>(dimids.size()),
        "Variable " << nc_inq_varname(ncid, ncVar) << " has extra dimensions, in file " << file);
  }

  return std::make_pair(k, ncVar);
}
Ejemplo n.º 20
0
int
main(int argc, char **argv)
{
   printf("\n*** Testing v3/v4 API versions of some v2 tests.\n");
   printf("*** testing simple dim rename...");
   {
#define PP1 "pp"
#define PP1_SIZE 7
#define P1_NAME "p"

      int ncid, pp_dimid, dimid_in;

      /* Create a file with one dimension. */
      if (nc_create(FILE_NAME, NC_CLOBBER, &ncid)) ERR;
      if (nc_def_dim(ncid, PP1, PP1_SIZE, &pp_dimid)) ERR;

      /* Renaming to shorter name is possible in data mode... */
      if (nc_enddef(ncid)) ERR;
      if (nc_rename_dim(ncid, pp_dimid, P1_NAME)) ERR;
      if (nc_inq_dimid(ncid, P1_NAME, &dimid_in)) ERR;
      if (dimid_in != pp_dimid) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing dim rename from nctest...");
   {
#define PP "pp"
#define PP_SIZE 7
#define QQ "qq"
#define QQ_SIZE 10
#define NEW_NAME "new_name"
#define ANOTHER_NAME "another_name"
#define P_NAME "p"

      int ncid, pp_dimid, qq_dimid, dimid_in;
      char name_in[NC_MAX_NAME + 1];

      /* Create the same file as nctest.c does. */
      if (create_file()) ERR;

      /* Open it and test renames of dimensions. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_redef(ncid)) ERR;
      if (nc_def_dim(ncid, PP, PP_SIZE, &pp_dimid)) ERR;
      if (nc_def_dim(ncid, QQ, QQ_SIZE, &qq_dimid)) ERR;
      if (nc_rename_dim(ncid, pp_dimid, NEW_NAME)) ERR;
      if (nc_inq_dimname(ncid, pp_dimid, name_in)) ERR;
      if (strcmp(NEW_NAME, name_in)) ERR;
      if (nc_rename_dim(ncid, pp_dimid, QQ) != NC_ENAMEINUSE) ERR;
      if (nc_rename_dim(ncid, -1, ANOTHER_NAME) != NC_EBADDIM) ERR;
      if (nc_rename_dim(ncid, 12, ANOTHER_NAME) != NC_EBADDIM) ERR;
      if (nc_enddef(ncid)) ERR;
      if (nc_rename_dim(ncid, pp_dimid, P_NAME)) ERR;
      if (nc_inq_dimid(ncid, P_NAME, &dimid_in)) ERR;
      if (dimid_in != pp_dimid) ERR;
      if (nc_inq_dimid(ncid, P_NAME, NULL)) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   FINAL_RESULTS;
}
Ejemplo n.º 21
0
int
main(int argc, char **argv)
{
   printf("\n*** Testing netcdf-4 coordinate dimensions and variables, some more.\n");

   printf("**** testing more complex 2D coordinate variable with dimensions defined in different order...");
   {
#define NDIMS 5
#define NVARS 4
#define LON_NAME "lon"
#define LAT_NAME "lat"
#define LVL_NAME "lvl"
#define TIME_NAME "time"
#define TEXT_LEN_NAME "text_len"
#define TEMP_NAME "temp"
#define PRES_NAME "pres"
#define LON_LEN 5
#define LAT_LEN 3
#define LVL_LEN 7
#define TIME_LEN 2
#define TEXT_LEN 15
#define TIME_NDIMS 2
#define DATA_NDIMS 4

      int ncid, nvars_in, varids_in[NVARS];
      int time_dimids[TIME_NDIMS];
      int dimids[NDIMS], time_id, lon_id, pres_id, temp_id;
      size_t time_count[NDIMS], time_index[NDIMS] = {0, 0};
      const char ttext[TEXT_LEN + 1]="20051224.150000";
      char ttext_in[TEXT_LEN + 1];
      int nvars, ndims, ngatts, unlimdimid;
      int ndims_in, natts_in, dimids_in[NDIMS];
      char var_name_in[NC_MAX_NAME + 1], dim_name_in[NC_MAX_NAME + 1];
      size_t len_in;
      nc_type xtype_in;
      int d;

      /* Create a netcdf-4 file. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;

      /* Define dimensions. */
      if (nc_def_dim(ncid, LON_NAME, LON_LEN, &dimids[0])) ERR;
      if (nc_def_dim(ncid, LAT_NAME, LAT_LEN, &dimids[1])) ERR;
      if (nc_def_dim(ncid, LVL_NAME, LVL_LEN, &dimids[2])) ERR;
      if (nc_def_dim(ncid, TIME_NAME, TIME_LEN, &dimids[3])) ERR;
      if (nc_def_dim(ncid, TEXT_LEN_NAME, TEXT_LEN, &dimids[4])) ERR;

      /* Define two coordinate variables out of order. */
      time_dimids[0] = dimids[3];
      time_dimids[1] = dimids[4];
      if (nc_def_var(ncid, TIME_NAME, NC_CHAR, TIME_NDIMS, time_dimids, &time_id)) ERR;
      if (nc_def_var(ncid, LON_NAME, NC_CHAR, 1, &dimids[0], &lon_id)) ERR;

      /* Write one time to the coordinate variable. */
      time_count[0] = 1;
      time_count[1] = TEXT_LEN;
      if (nc_put_vara_text(ncid, time_id, time_index, time_count, ttext)) ERR;

      /* Define two data variable. */
      if (nc_def_var(ncid, PRES_NAME, NC_CHAR, DATA_NDIMS, dimids, &pres_id)) ERR;
      if (nc_def_var(ncid, TEMP_NAME, NC_CHAR, DATA_NDIMS, dimids, &temp_id)) ERR;

      /* Check the data. */
      if (nc_get_vara_text(ncid, time_id, time_index, time_count, ttext_in)) ERR;
      if (strncmp(ttext, ttext_in, TEXT_LEN)) ERR;

      /* Check the metadata. */
      if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
      if (nvars != NVARS || ndims != NDIMS || ngatts != 0 || unlimdimid != -1) ERR;
      if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
      if (nvars_in != NVARS || varids_in[0] != 0 || varids_in[1] != 1 || 
	  varids_in[2] != 2 || varids_in[3] != 3) ERR;
      if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(var_name_in, TIME_NAME) || xtype_in != NC_CHAR || ndims_in != TIME_NDIMS ||
	dimids_in[0] != time_dimids[0] || dimids_in[1] != time_dimids[1] || natts_in != 0) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != NDIMS) ERR;
      for (d = 0; d < NDIMS; d++)
	 if (dimids_in[d] != dimids[d]) ERR;
      if (nc_inq_dim(ncid, 0, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, LON_NAME) || len_in != LON_LEN) ERR;
      if (nc_inq_dim(ncid, 1, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, LAT_NAME) || len_in != LAT_LEN) ERR;
      if (nc_inq_dim(ncid, 2, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, LVL_NAME) || len_in != LVL_LEN) ERR;
      if (nc_inq_dim(ncid, 3, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, TIME_NAME) || len_in != TIME_LEN) ERR;
      if (nc_inq_dim(ncid, 4, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, TEXT_LEN_NAME) || len_in != TEXT_LEN) ERR;

      /* Close up. */
      if (nc_close(ncid)) ERR;

      /* Open the file and check the order of variables and dimensions. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
      if (nvars != NVARS || ndims != NDIMS || ngatts != 0 || unlimdimid != -1) ERR;
      if (nc_inq_varids(ncid, &nvars_in, varids_in)) ERR;
      if (nvars_in != NVARS || varids_in[0] != 0 || varids_in[1] != 1 || 
	  varids_in[2] != 2 || varids_in[3] != 3) ERR;
      if (nc_inq_var(ncid, 0, var_name_in, &xtype_in, &ndims_in, dimids_in, &natts_in)) ERR;
      if (strcmp(var_name_in, TIME_NAME) || xtype_in != NC_CHAR || ndims_in != TIME_NDIMS ||
	dimids_in[0] != time_dimids[0] || dimids_in[1] != time_dimids[1] || natts_in != 0) ERR;
      if (nc_inq_dimids(ncid, &ndims_in, dimids_in, 0)) ERR;
      if (ndims_in != NDIMS) ERR;
      for (d = 0; d < NDIMS; d++)
	 if (dimids_in[d] != dimids[d]) ERR;
      if (nc_inq_dim(ncid, 0, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, LON_NAME) || len_in != LON_LEN) ERR;
      if (nc_inq_dim(ncid, 1, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, LAT_NAME) || len_in != LAT_LEN) ERR;
      if (nc_inq_dim(ncid, 2, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, LVL_NAME) || len_in != LVL_LEN) ERR;
      if (nc_inq_dim(ncid, 3, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, TIME_NAME) || len_in != TIME_LEN) ERR;
      if (nc_inq_dim(ncid, 4, dim_name_in, &len_in)) ERR;
      if (strcmp(dim_name_in, TEXT_LEN_NAME) || len_in != TEXT_LEN) ERR;

      /* Check the data. */
      if (nc_get_vara_text(ncid, time_id, time_index, time_count, ttext_in)) ERR;
      if (strncmp(ttext, ttext_in, TEXT_LEN)) ERR;

      /* Close up. */
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("**** testing example from bug NCF-247, multidimensional coord variable in subgroup ...");
   {
#define GRPNAME "g1"
#define DIM0NAME "dim0"
#define DIM1NAME "dim1"
#define DIM2NAME "coord"
#define DIM3NAME "dim3"
#define VARNAME  DIM2NAME
#define VARRANK 2
       int  ncid, grpid, varid, var_dims[VARRANK], var_dims_in[VARRANK];
       char name2[NC_MAX_NAME], name3[NC_MAX_NAME];
       int dim0_dim, dim1_dim, dim2_dim, dim3_dim;
       size_t dim0_len = 3, dim1_len = 2, dim2_len = 5, dim3_len = 7;

       if (nc_create(FILE_NAME, NC_CLOBBER|NC_NETCDF4, &ncid)) ERR;
       if (nc_def_grp(ncid, GRPNAME, &grpid)) ERR;
       
       if (nc_def_dim(ncid, DIM0NAME, dim0_len, &dim0_dim)) ERR;
       if (nc_def_dim(ncid, DIM1NAME, dim1_len, &dim1_dim)) ERR;
       if (nc_def_dim(grpid, DIM2NAME, dim2_len, &dim2_dim)) ERR;
       if (nc_def_dim(grpid, DIM3NAME, dim3_len, &dim3_dim)) ERR;

       var_dims[0] = dim2_dim;
       var_dims[1] = dim3_dim;
       if (nc_def_var(grpid, VARNAME, NC_INT, VARRANK, var_dims, &varid)) ERR;
    
       if (nc_close(ncid)) ERR;
    
       if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
    
       if (nc_inq_grp_ncid(ncid, GRPNAME, &grpid)) ERR;
    
       if (nc_inq_varid(grpid, VARNAME, &varid)) ERR;
       if (nc_inq_vardimid(grpid, varid, var_dims_in)) ERR;
       if (nc_inq_dimname(grpid, var_dims_in[0], name2)) ERR;
       if (nc_inq_dimname(grpid, var_dims_in[1], name3)) ERR;
       if (strcmp(name2, DIM2NAME) != 0 || strcmp(name3, DIM3NAME) != 0) ERR;
       if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   FINAL_RESULTS;
}