Exemple #1
0
/**
@ingroup variables
@internal Get the number of record dimensions for a variable and an
array that identifies which of a variable's dimensions are record
dimensions. Intended to be used instead of NC_is_recvar(), which
doesn't work for netCDF-4 variables which have multiple unlimited
dimensions or an unlimited dimension that is not the first of a
variable's dimensions.

@param ncid File ID.
@param varid Variable ID.
@param nrecdimsp Pointer that gets number of record dims.
@param is_recdim Pointer that gets 1 if there is one or more record
dimensions, 0 if not.

@returns 0 if not a record var, 1 if it is.

Example use:
@code
int nrecdims;
int is_recdim[NC_MAX_VAR_DIMS];
  ...
status = NC_inq_recvar(ncid,varid,&nrecdims,is_recdim);
isrecvar = (nrecdims > 0);
@endcode
 */
int
NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim)
{
   int status = NC_NOERR;
   int unlimid;
   int nvardims;
   int dimset[NC_MAX_VAR_DIMS];
   int dim;
   int nrecdims = 0;

   status = nc_inq_varndims(ncid,varid,&nvardims);
   if(status != NC_NOERR) return status;
   if(nvardims == 0) return NC_NOERR; /* scalars have no dims */
   for(dim = 0; dim < nvardims; dim++)
     is_recdim[dim] = 0;
   status = nc_inq_unlimdim(ncid, &unlimid);
   if(status != NC_NOERR) return status;
   if(unlimid == -1) return status; /* no unlimited dims for any variables */
#ifdef USE_NETCDF4
   {
     int nunlimdims;
     int *unlimids;
     int recdim;
     status = nc_inq_unlimdims(ncid, &nunlimdims, NULL); /* for group or file, not variable */
     if(status != NC_NOERR) return status;
     if(nunlimdims == 0) return status;

     if (!(unlimids = malloc(nunlimdims * sizeof(int))))
       return NC_ENOMEM;
     status = nc_inq_unlimdims(ncid, &nunlimdims, unlimids); /* for group or file, not variable */
     if(status != NC_NOERR) {
       free(unlimids);
       return status;
     }
     status = nc_inq_vardimid(ncid, varid, dimset);
     if(status != NC_NOERR) {
       free(unlimids);
       return status;
     }
     for (dim = 0; dim < nvardims; dim++) { /* netCDF-4 rec dims need not be first dim for a rec var */
       for(recdim = 0; recdim < nunlimdims; recdim++) {
	 if(dimset[dim] == unlimids[recdim]) {
	   is_recdim[dim] = 1;
	   nrecdims++;
	 }
       }
     }
     free(unlimids);
   }
#else
   status = nc_inq_vardimid(ncid, varid, dimset);
   if(status != NC_NOERR) return status;
   if(dimset[0] == unlimid) {
     is_recdim[0] = 1;
     nrecdims++;
   }
#endif /* USE_NETCDF4 */
   if(nrecdimsp) *nrecdimsp = nrecdims;
   return status;
}
Exemple #2
0
 int CONetCDF4::getUnlimitedDimension(void)
 {
    int dimid = 0;
    int grpid = this->getCurrentGroup();
    CheckError(nc_inq_unlimdim (grpid, &dimid));
    return (dimid);
 }
Exemple #3
0
Fichier : ncdf.c Projet : cran/ncdf
void R_nc_inq_unlimdim( int *ncid, int *unlimdimid, int *retval )
{
	*retval = nc_inq_unlimdim(*ncid, unlimdimid );
	if( *retval != NC_NOERR ) 
		REprintf( "Error in R_nc_inq_unlimdim: %s\n", 
			nc_strerror(*retval) );
}
Exemple #4
0
int ncd_wdset(int ncid,char *path,char *name, void *val,  \
              enum ADIOS_TYPES type, int rank,              \
              struct adios_bp_dimension_struct *dims)
{
  int i,valid,retval;
  char fullname[100];
  char dimname[100];
  fullname[0]='\0';
  char *result=NULL; 
  int dimids[2];
  dimids[1]=0;

  strcpy(fullname,name);
  if(start[0]==0)
  {
     retval=nc_redef(ncid);
     sprintf(dimname,"%s_%d",name,0);
     retval=nc_inq_unlimdim(ncid,&dimids[1]);
     if(dimids[1]==-1)retval=nc_def_dim(ncid,"timesteps",NC_UNLIMITED,&dimids[0]);
     retval=nc_def_dim(ncid,dimname,dims[0].local_bound,&dimids[1]);
     if(type==adios_real)
        retval=nc_def_var(ncid,fullname,NC_FLOAT,2,dimids,&valid);
     if(type==adios_integer)
        retval=nc_def_var(ncid,fullname,NC_INT,2,dimids,&valid);
     if(type==adios_long)
        retval=nc_def_var(ncid,fullname,NC_LONG,2,dimids,&valid);
     if(type==adios_double)
     {
        retval=nc_def_var(ncid,fullname,NC_DOUBLE,2,dimids,&valid);
        ERR(retval);
     }
     //printf("\t RANK=%d, DIMS:%s[0]=%d dimids[1]=%d\n",rank,dimname,dims[0].local_bound,dimids[1]);
     retval=nc_enddef(ncid);
  }
  else
     retval=nc_inq_varid (ncid, fullname, &valid);
  
  start[1]=0;//dims[0].local_bound;
  count[0]=1;
  count[1]=dims[0].local_bound;

  if(type==adios_double)
     retval=nc_put_vara_double(ncid,valid,start,count,val);
  if(type==adios_real)
     retval=nc_put_vara_float(ncid,valid,start,count,val);
  if(type==adios_integer)
     retval=nc_put_vara_int(ncid,valid,start,count,val);
  if(type==adios_long)
     retval=nc_put_vara_long(ncid,valid,start,count,val);
//#if DEBUG
  //printf("create dataset:%s\n",fullname);
  //printf("start:%dx%d. count:%dx%d\n",start[0],start[1],count[0],count[1]);
  //printf("-------------------\n");
//#endif
  return;
}
Exemple #5
0
NcBool NcDim::is_unlimited( void ) const
{
    if (!the_file)
      return FALSE;
    int recdim;
    NcError::set_err(
		     nc_inq_unlimdim(the_file->id(), &recdim)
		     );
    return the_id == recdim;
}
Exemple #6
0
NcDim* NcFile::rec_dim( ) const
{
    if (! is_valid())
      return 0;
    int recdim;
    if(NcError::set_err(
			nc_inq_unlimdim(the_id, &recdim)
			) != NC_NOERR)
	return 0;
    return get_dim(recdim);
}
Exemple #7
0
static int
NC3_inq_unlimdims(int ncid, int *ndimsp, int *unlimdimidsp)
{
    int retval;
    int unlimid;

    if ((retval = nc_inq_unlimdim(ncid, &unlimid)))
        return retval;
    if (unlimid != -1) {
        if(ndimsp) *ndimsp = 1;
        if (unlimdimidsp)
            unlimdimidsp[0] = unlimid;
    } else
        if(ndimsp) *ndimsp = 0;
    return NC_NOERR;
}
/*!
This function makes a request to netcdf with a netCdf dimension name then return ncid of the named dimension
\param [in] ncid Groupd id (or File Id)
\param [in/out] dimId Dimension id if this dimension is found
\return Status code
*/
int CNetCdfInterface::inqUnLimDim(int ncid, int& dimId)
{
  int status = nc_inq_unlimdim(ncid, &dimId);
  if (NC_NOERR != status)
  {
    StdString errormsg(nc_strerror(status));
    StdStringStream sstr;

    sstr << "Error when calling function nc_inq_dimid" << std::endl
      << errormsg << std::endl
      << "Unable to get id of unlimited dimension " << std::endl;
    StdString e = sstr.str();
    throw CNetCdfException(e);
 }

  return status;
}
Exemple #9
0
/*
 * Retrieves the number of record variables, the record variable ids, and the
 * record size of each record variable.  If any pointer to info to be returned
 * is null, the associated information is not returned.  Returns -1 on error.
 */
int
nc_inq_rec(
	int ncid,
	size_t *nrecvarsp,
	int *recvarids,
	size_t *recsizes)
{
    int status;
    int nvars = 0;
    int recdimid;
    int varid;
    int rvarids[MAX_NC_VARS];
    int nrvars = 0;

    status = nc_inq_nvars(ncid, &nvars); 
    if(status != NC_NOERR)
	return status;

    status = nc_inq_unlimdim(ncid, &recdimid); 
    if(status != NC_NOERR)
	return status;

    *nrecvarsp = 0;
    if (recdimid == -1)
	return NC_NOERR;
    
    status = numrecvars(ncid, &nrvars, rvarids);
    if(status != NC_NOERR)
	return status;

    if (nrecvarsp != NULL)
	*nrecvarsp = nrvars;
    if (recvarids != NULL)
	for (varid = 0; varid < nrvars; varid++)
	    recvarids[varid] = rvarids[varid];

    if (recsizes != NULL)
	for (varid = 0; varid < nrvars; varid++) {
	    size_t rsize;
	    status = ncrecsize(ncid, rvarids[varid], &rsize);
	    if (status != NC_NOERR)
		return status;
	    recsizes[varid] = rsize;
	}
	return NC_NOERR;
}
Exemple #10
0
int ncd_wscalar(int ncid,char *path,char *name, void *val,  \
              enum ADIOS_TYPES type)
{
  int i,valid,retval;
  char fullname[100];
  char dimname[100];
  fullname[0]='\0';
  char *result=NULL; 
  int dimids[1];
  dimids[0]=0;

  strcpy(fullname,name);
  if(start[0]==0)
  {
     retval=nc_redef(ncid);
     sprintf(dimname,"%s_%d",name,0);
     retval=nc_inq_unlimdim(ncid,&dimids[0]);

     if(dimids[0]==-1)retval=nc_def_dim(ncid,"timesteps",NC_UNLIMITED,&dimids[0]);
    
     if(type==adios_real)
        retval=nc_def_var(ncid,fullname,NC_FLOAT,1,dimids,&valid);
     else if(type==adios_double)
        retval=nc_def_var(ncid,fullname,NC_DOUBLE,1,dimids,&valid);
     else if(type==adios_integer)
        retval=nc_def_var(ncid,fullname,NC_INT,1,dimids,&valid);
     else if(type==adios_long)
        retval=nc_def_var(ncid,fullname,NC_LONG,1,dimids,&valid);
     retval=nc_enddef(ncid);
  }
  else
     retval=nc_inq_varid (ncid, fullname, &valid);
  if(type==adios_real)
     retval=nc_put_vara_float(ncid,valid,start_scalar,count_scalar,val);
  else if(type==bp_double)
     retval=nc_put_vara_double(ncid,valid,start_scalar,count_scalar,val);
  else if(type==adios_integer)
     retval=nc_put_vara_int(ncid,valid,start_scalar,count_scalar,val);
  else if(type==adios_long)
     retval=nc_put_vara_long(ncid,valid,start_scalar,count_scalar,val);
  ERR(retval);
  return 0;
}
Exemple #11
0
/**
@ingroup variables
@internal Does a variable have a record dimension?

@param ncid File ID.
@param varid Variable ID.
@param nrecs Pointer that gets number of records.

@returns 0 if not a record var, 1 if it is.
 */
int
NC_is_recvar(int ncid, int varid, size_t* nrecs)
{
   int status = NC_NOERR;
   int unlimid;
   int ndims;
   int dimset[NC_MAX_VAR_DIMS];

   status = nc_inq_unlimdim(ncid,&unlimid);
   if(status != NC_NOERR) return 0; /* no unlimited defined */
   status = nc_inq_varndims(ncid,varid,&ndims);
   if(status != NC_NOERR) return 0; /* no unlimited defined */
   if(ndims == 0) return 0; /* scalar */
   status = nc_inq_vardimid(ncid,varid,dimset);
   if(status != NC_NOERR) return 0; /* no unlimited defined */
   status = nc_inq_dim(ncid,dimset[0],NULL,nrecs);
   if(status != NC_NOERR) return 0;
   return (dimset[0] == unlimid ? 1: 0);
}
Exemple #12
0
/*
 * return 1 if varid identifies a record variable
 * else return 0
 */
int
isrecvar(int ncid, int varid)
{
    int ndims;
    int is_recvar = 0;
    int *dimids;

    NC_CHECK( nc_inq_varndims(ncid, varid, &ndims) );
#ifdef USE_NETCDF4
    if (ndims > 0) {
	int nunlimdims;
	int *recdimids;
	int dim, recdim;
	dimids = (int *) emalloc((ndims + 1) * sizeof(int));
	NC_CHECK( nc_inq_vardimid(ncid, varid, dimids) );
	NC_CHECK( nc_inq_unlimdims(ncid, &nunlimdims, NULL) );
	recdimids = (int *) emalloc((nunlimdims + 1) * sizeof(int));
	NC_CHECK( nc_inq_unlimdims(ncid, NULL, recdimids) );
	for (dim = 0; dim < ndims && is_recvar == 0; dim++) {
	    for(recdim = 0; recdim < nunlimdims; recdim++) {
		if(dimids[dim] == recdimids[recdim]) {
		    is_recvar = 1;
		    break;
		}		
	    }
	}
	free(dimids);
	free(recdimids);
    }
#else
    if (ndims > 0) {
	int recdimid;
	dimids = (int *) emalloc((ndims + 1) * sizeof(int));
	NC_CHECK( nc_inq_vardimid(ncid, varid, dimids) );
	NC_CHECK( nc_inq_unlimdim(ncid, &recdimid) );
	if(dimids[0] == recdimid)
	    is_recvar = 1;
	free(dimids);
    }
#endif /* USE_NETCDF4 */
    return is_recvar;
}
Exemple #13
0
/*
 * Computes number of record variables in an open netCDF file, and an array of
 * the record variable ids, if the array parameter is non-null.
 */
static int
numrecvars(int ncid, int *nrecvarsp, int *recvarids)
{
    int status;
    int nvars = 0;
    int ndims = 0;
    int nrecvars = 0;
    int varid;
    int recdimid;
    int dimids[MAX_NC_DIMS];

    status = nc_inq_nvars(ncid, &nvars); 
    if(status != NC_NOERR)
	return status;

    status = nc_inq_unlimdim(ncid, &recdimid); 
    if(status != NC_NOERR)
	return status;

    if (recdimid == -1) {
	*nrecvarsp = 0;
	return NC_NOERR;
    }
    nrecvars = 0;
    for (varid = 0; varid < nvars; varid++) {
	status = nc_inq_varndims(ncid, varid, &ndims); 
	if(status != NC_NOERR)
	    return status;
	status = nc_inq_vardimid(ncid, varid, dimids); 
	if(status != NC_NOERR)
	    return status;
	if (ndims > 0 && dimids[0] == recdimid) {
	    if (recvarids != NULL)
	      recvarids[nrecvars] = varid;
	    nrecvars++;
	}
    }
    *nrecvarsp = nrecvars;
    return NC_NOERR;
}
Exemple #14
0
/*
 * Computes record size (in bytes) of the record variable with a specified
 * variable id.  Returns size as 0 if not a record variable.
 */
static int
ncrecsize(int ncid, int varid, size_t *recsizep)
{
    int status;
    int recdimid;
    nc_type type;
    int ndims;
    int dimids[MAX_NC_DIMS];
    int id;
    size_t size;

    *recsizep = 0;
    status = nc_inq_unlimdim(ncid, &recdimid); 
    if(status != NC_NOERR)
	return status;
    status = nc_inq_vartype(ncid, varid, &type); 
    if(status != NC_NOERR)
	return status;
    status = nc_inq_varndims(ncid, varid, &ndims); 
    if(status != NC_NOERR)
	return status;
    status = nc_inq_vardimid(ncid, varid, dimids); 
    if(status != NC_NOERR)
	return status;
    if (ndims == 0 || dimids[0] != recdimid) {
	return NC_NOERR;
    }
    size = nctypelen(type);
    for (id = 1; id < ndims; id++) {
	size_t len;
	status = nc_inq_dimlen(ncid, dimids[id], &len);
	if(status != NC_NOERR)
		return status;
	size *= len;
    }
    *recsizep = size;
    return NC_NOERR;
}
Exemple #15
0
Fichier : ncdf.c Projet : cran/ncdf
/* Returns 1 if this var has an unlimited dimension, 0 otherwise */
void R_nc_inq_varunlim( int *ncid, int *varid, int *isunlim, int *retval )
{
	int	i, ndims, unlimdimid, dimids[MAX_NC_DIMS];

	/* Get the unlimited dim id */
	*retval = nc_inq_unlimdim( *ncid, &unlimdimid );
	if( *retval != NC_NOERR ) {
		REprintf(  "Error in R_nc_inq_varunlim while getting unlimdimid: %s\n", 
			nc_strerror(*retval) );
		return;
		}

	/* Get this var's ndims */
	*retval = nc_inq_varndims( *ncid, *varid, &ndims );
	if( *retval != NC_NOERR ) {
		REprintf( "Error in R_nc_inq_varunlim while getting ndims: %s\n", 
			nc_strerror(*retval) );
		REprintf( "Using ncid=%d and varid=%d\n", 
			*ncid, *varid );
		return;
		}

	/* Get this var's dims */
	*retval = nc_inq_vardimid( *ncid, *varid, dimids );
	if( *retval != NC_NOERR ) {
		REprintf( "Error in R_nc_inq_varunlim while getting dimids: %s\n", 
			nc_strerror(*retval) );
		return;
		}

	*isunlim = 0;
	for( i=0; i<ndims; i++ )
		if( dimids[i] == unlimdimid ) {
			*isunlim = 1;
			break;
			}
}
Exemple #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;
}
Exemple #17
0
/**
 * Create or open an existing netCdf-file
 * 
 * If i_baseName appended with the ".nc" extension represents an existing
 * NetCDF file, the file is opened and it is tried to append to the 
 * file (e.g. open a checkpoint-file of a previously crashed run)
 *
 * @param i_baseName base name of the netCDF-file to which the data will be written to.
 * @param i_nX number of cells in the horizontal direction.
 * @param i_nY number of cells in the vertical direction.
 * @param i_dX cell size in x-direction.
 * @param i_dY cell size in y-direction.
 * @param i_originX
 * @param i_originY
 * @param i_coarseness The coarseness factor
 * @param i_flush If > 0, flush data to disk every i_flush write operation
 * @param i_dynamicBathymetry
 */
io::NetCdfWriter::NetCdfWriter( const std::string &i_baseName,
		const Float2D &i_b,
		const BoundarySize &i_boundarySize,
		int i_nX, int i_nY,
		float i_dX, float i_dY,
		float i_originX, float i_originY,
		float i_coarseness,
        unsigned int i_flush) :
		//const bool  &i_dynamicBathymetry) : //!TODO
  io::Writer(i_baseName + ".nc", i_b, i_boundarySize, i_nX, i_nY, i_coarseness),
  flush(i_flush)
{
	int status;
    
	// variables (TODO: add rest of CF-1.5)
	int l_xVar, l_yVar;
    
	// dimensions
	int l_timeDim, l_xDim, l_yDim;
    
    // Try to open the file (to see if it is an existing checkpoint file)
    status = nc_open(fileName.c_str(), NC_WRITE, &dataFile);
    
    if(status == NC_NOERR) {
        // File exists and is a NetCDF file we can write to
        // Read ID for time, x, y, h, hu, hv and b dimensions and variables
        status = nc_inq_unlimdim(dataFile, &l_timeDim);
        status = nc_inq_dimid(dataFile, "x", &l_xDim);
        status = nc_inq_dimid(dataFile, "y", &l_yDim);
        status = nc_inq_varid(dataFile, "time", &timeVar);
        status = nc_inq_varid(dataFile, "x", &l_xVar);
        status = nc_inq_varid(dataFile, "y", &l_yVar);
        status = nc_inq_varid(dataFile, "h", &hVar);
        status = nc_inq_varid(dataFile, "hu", &huVar);
        status = nc_inq_varid(dataFile, "hv", &hvVar);
        status = nc_inq_varid(dataFile, "b", &bVar);
        
        // Read Dimensions for x and y variable
        size_t l_xLen, l_yLen;
        status = nc_inq_dimlen(dataFile, l_xDim, &l_xLen);
        status = nc_inq_dimlen(dataFile, l_yDim, &l_yLen);
        
        // Set next timeStep
        status = nc_inq_dimlen(dataFile, l_timeDim, &timeStep);
        
        // Check actual dimensions in file against supplied dimensions
        assert(l_xLen == coarseX); assert(l_yLen == coarseY);
    } else {
        // File does not exist or is not a valid NetCDF file
    	//create a netCDF-file, an existing file will be replaced
    	status = nc_create(fileName.c_str(), NC_NETCDF4, &dataFile);

        //check if the netCDF-file creation constructor succeeded.
    	if (status != NC_NOERR) {
    		assert(false);
    		return;
    	}

#ifdef PRINT_NETCDFWRITER_INFORMATION
    	std::cout << "   *** io::NetCdfWriter::createNetCdfFile" << std::endl;
    	std::cout << "     created/replaced: " << fileName << std::endl;
    	std::cout << "     internal dimensions(nx, ny): " << nX << ", " << nY << std::endl;
        std::cout << "     dimensions(nx, ny): " << coarseX << ", " << coarseY << std::endl;
        std::cout << "     coarseness: " << coarseness << std::endl;
    	std::cout << "     cell width(dx,dy): " << i_dX << ", " << i_dY << std::endl;
    	std::cout << "     origin(x,y): " << i_originX << ", " << i_originY << std::endl;
#endif

    	nc_def_dim(dataFile, "time", NC_UNLIMITED, &l_timeDim);
    	nc_def_dim(dataFile, "x", coarseX, &l_xDim);
    	nc_def_dim(dataFile, "y", coarseY, &l_yDim);

    	nc_def_var(dataFile, "time", NC_FLOAT, 1, &l_timeDim, &timeVar);
    	ncPutAttText(timeVar, "long_name", "Time");
    	ncPutAttText(timeVar, "units", "seconds since simulation start"); // the word "since" is important for the paraview reader
    	nc_def_var(dataFile, "x", NC_FLOAT, 1, &l_xDim, &l_xVar);
    	nc_def_var(dataFile, "y", NC_FLOAT, 1, &l_yDim, &l_yVar);

    	//variables, fastest changing index is on the right (C syntax), will be mirrored by the library
    	int dims[] = {l_timeDim, l_yDim, l_xDim};
    	nc_def_var(dataFile, "h",  NC_FLOAT, 3, dims, &hVar);
    	nc_def_var(dataFile, "hu", NC_FLOAT, 3, dims, &huVar);
    	nc_def_var(dataFile, "hv", NC_FLOAT, 3, dims, &hvVar);
    	nc_def_var(dataFile, "b",  NC_FLOAT, 2, &dims[1], &bVar);

    	//set attributes to match CF-1.5 convention
    	ncPutAttText(NC_GLOBAL, "Conventions", "CF-1.5");
    	ncPutAttText(NC_GLOBAL, "title", "Computed tsunami solution");
    	ncPutAttText(NC_GLOBAL, "history", "SWE");
    	ncPutAttText(NC_GLOBAL, "institution", "Technische Universitaet Muenchen, Department of Informatics, Chair of Scientific Computing");
    	ncPutAttText(NC_GLOBAL, "source", "Bathymetry and displacement data.");
    	ncPutAttText(NC_GLOBAL, "references", "http://www5.in.tum.de/SWE");
    	ncPutAttText(NC_GLOBAL, "comment", "SWE is free software and licensed under the GNU General Public License. Remark: In general this does not hold for the used input data.");

    	//setup grid size
    	float gridPosition = i_originX + (float).5 * i_dX;
    	for(size_t i = 0; i < coarseX; i++) {
    		nc_put_var1_float(dataFile, l_xVar, &i, &gridPosition);

    		gridPosition += i_dX;
    	}

    	gridPosition = i_originY + (float).5 * i_dY;
    	for(size_t j = 0; j < coarseY; j++) {
    		nc_put_var1_float(dataFile, l_yVar, &j, &gridPosition);

        	gridPosition += i_dY;
    	}
    }
}
Exemple #18
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;
}
Exemple #19
0
int
Ensemble::getTimes(std::string &str)
{
  // reading netcdf files
  int ncid, dimid, varid, status;

  size_t recSize, len;
  size_t index=0;
  double val ;
  int retVal=0;

  std::string begStr;
  std::string endStr;

  for( size_t i=0 ; i < member.size() ; ++i )
  {
     if( nc_open( member[i]->getFile().c_str(), 0, &ncid) )
     {
       isInvalid = true;
       member[i]->state = "could not open file";
       continue;
     }

     nc_inq_unlimdim(ncid, &dimid) ;

     if( dimid == -1 )
        // try for a regular dimension time
        nc_inq_dimid(ncid, "time", &dimid);

     // no unlimited variable found; this is not
     // neccessarily an error.
     if( dimid == -1 )
     {
       isNoRec = true;
       nc_close(ncid);

       if( sz == 1 )
       	 return 0; // a single file
       else
         retVal=4;

       isInvalid = true;
       member[i]->state += "missing time dimension";
       continue;
     }

     if( (status = nc_inq_dimlen(ncid, dimid, &recSize) ) )
     {
       isInvalid = true;
       member[i]->state = "could not read time dimension";
       nc_close(ncid);
       continue;
     }

     if( status == 0 && recSize == 0 )
     {
       // this could be wrong
       // or just a fixed variable with time dimension defined.
       isNoRec = true;
       nc_close(ncid);

       if( sz == 1 )
      	  return 0;

       isInvalid = true;
       member[i]->state = "no time values available";
       continue;
     }

     if( (status = nc_inq_varid(ncid, "time", &varid) ) )
     {
       isNoRec = true;
       nc_close(ncid);

       if( sz == 1 )
      	  return 0;

       member[i]->state = "missing time variable";
       continue;
     }

     // reference calendar
     std::vector<std::string> vs;

     if( getAttText(ncid, varid, "calendar", vs) )
     {  // failure
       member[i]->state = "missing or invalid calendar attribute";
       nc_close(ncid);
       continue;
     }
     else
       // successful reading of calendar
       member[i]->refDate.setCalendar(vs[0]) ;

       // reference date
     if( getAttText(ncid, varid, "units", vs) )
     {  // failure
         member[i]->state = "missing or invalid units attribute";
         nc_close(ncid);
         continue;
     }
     else
     {
       if( vs[0].find("%Y") < std::string::npos )
          member[i]->refDate.setFormattedDate();
       else
          member[i]->refDate = vs[0] ;
     }

     // time values: fist and last
     index=0;
     if( (status = nc_get_var1_double(ncid, varid, &index, &val) ) )
     {
        if( sz > 1 )
        {
          isInvalid = true;
          member[i]->state = "could not read first time value";
          nc_close(ncid);
          continue;
        }
     }

     // any reasonable values available?
     nc_type var_type ;
     status = nc_inq_vartype(ncid, varid, &var_type) ;

     // return value type is double
     double fV;
     int noFill=0;
     int statusF = nc_inq_var_fill(ncid, varid, &noFill, &fV);

     if( noFill != 1 && (statusF || val == fV) )
     {
        isInvalid = true;
        member[i]->state = "first time value equals _FillValue";
        nc_close(ncid);
        continue;
     }

     if(member[i]->refDate.isValid(val))
       member[i]->setBegin( member[i]->refDate.getDate(val) );
     else
     {
       isInvalid=true;
       retVal=5;
       member[i]->putState("invalid data, found " + hdhC::double2String(val), false);
       nc_close(ncid);
       continue;
     }

     index=recSize-1;
     if( (status = nc_get_var1_double(ncid, varid, &index, &val) ) )
     {
        if( sz > 1 )
        {
          isInvalid = true;
          member[i]->putState("could not read last time value");
          nc_close(ncid);
        }
     }

     if( noFill != 1 && (statusF || val == fV) )
     {
        isInvalid = true;
        member[i]->putState("last time value equals _FillValue");
        nc_close(ncid);
        continue;
     }

     if(member[i]->refDate.isValid(val))
       member[i]->setEnd( member[i]->refDate.getDate(val) );
     else
     {
       isInvalid=true;
       retVal=5;
       member[i]->putState("invalid data, found " + hdhC::double2String(val), false);
     }

     nc_close(ncid);
  }

  // any serious conditions
  if( isInvalid )
  {
     // only files with annotations
     enablePrintOnlyMarked();
     str = getOutput();

    if( retVal )
      return retVal;
    else
      return 3 ;  // unspecific error
  }

  // get modification times of files
  for(size_t i=0 ; i < member.size() ; ++i )
    member[i]->getModificationTime() ;

  // sorted vector of pointers of dates
  sortDate();

  return 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;
}
Exemple #21
0
void write_output(char out_file[], char in_file[][FILE_NAME_SZ], char depth_file[],
     size_t nz, char var_names[MAX_VARS][NC_MAX_NAME], char time_names[2][NC_MAX_NAME], 
     char depth_names[2][NC_MAX_NAME], int *num_var,
     char arglist[]) {
  int i, j, v;
  int ncid, nc_den_id, status, ndims, ndim, nvariables, ngatt, recdim;
  int use_dim[NC_MAX_DIMS];
  int dv_id[NC_MAX_DIMS], dim2id[NC_MAX_DIMS], dim2vid[NC_MAX_DIMS];
  int dimids[NC_MAX_VAR_DIMS], dd2id[2];
  int ddvid[2], dd2vid[2];
  int num_att;
  int use_file[MAX_FILES], max_file;
  char dim_name[10][NC_MAX_NAME];
  char att_name[NC_MAX_NAME];
  nc_type xtype;

  size_t dim_len[NC_MAX_DIMS], ddim_len[2], max_dim_len = 0;
    
  status = nc_open(in_file[0],NC_NOWRITE, &ncid);
  if (status != NC_NOERR) handle_error(status,in_file[0],status);
  ncInid[0] = ncid; use_file[0] = 1;

  status = nc_inq(ncid,&ndims,&nvariables,&ngatt,&recdim);
  if (status != NC_NOERR) handle_error(status,in_file[0],status);
  strcpy(master_in_file,in_file[0]);

  for (i=1;i<MAX_FILES;i++) { ncInid[i] = -1; use_file[i] = 0;}
  for (i=0;i<MAX_FILES;i++) if (strlen(in_file[i]) == 0) break;
  max_file = i;

/* Determine which dimensions need to be created. */
  for (i=0;i<ndims;i++) use_dim[i] = 0.0;
  for (v=0;v<*num_var;v++) {
    int vin_id, fn = 0, id;
    for (fn=0;fn<max_file;fn++) {
      if (ncInid[fn] < 0) {
        status = nc_open(in_file[fn],NC_NOWRITE, &ncInid[fn]);
        if (status != NC_NOERR) handle_error(status,in_file[fn],status);
      }
      status = nc_inq_varid(ncInid[fn], var_names[v], &vin_id);
      if (status == NC_NOERR) break;
    }
    if (fn==max_file) {
      printf("ERROR: Unable to find variable %s in any of %d files.\n",var_names[v],max_file);
      handle_error(status, var_names[v], v);
    }
    id = ncInid[fn];
    status = nc_inq_var(id, vin_id, att_name, &xtype, &ndim, dimids, &num_att);
    if (status != NC_NOERR) handle_error(status, var_names[v], v);

    if (ndim < 2) printf("Variable %s has only 2 dimensions and will be excluded.\n", var_names[v]);
    else {
      use_dim[find_dimid(id,dimids[ndim-1],ncid)] = 1;
      use_dim[find_dimid(id,dimids[ndim-2],ncid)] = 1;
      if (ndim > 4) {
        printf("ERROR: Variable %s has %d dimensions. This program only works with up to 4 dimensions.\n",
                var_names[v],ndim);
        exit(-1);
      }
      if (ndim == 4) {
        int frecdim; status = nc_inq_unlimdim(id,&frecdim);
        if (status != NC_NOERR) handle_error(status,"Finding record dimid",status);
        if (dimids[0] = frecdim) use_dim[recdim] = 1;
        else {
          printf("ERROR: Variable %s has 4 non-record dimensions. This program only works with 3 such dimensions.\n",
                  var_names[v]);
          exit(-1);
        }
      }
      
      var_file[v] = fn;
      use_file[fn] = 1;
    }
  }

  // Close any unneeded files.
  for (i=1;i<max_file;i++) if ((use_file[i] == 0) && (ncInid[i] >= 0)) {
    nc_close(ncInid[i]); ncInid[i] = -1;
  }
  
  status = nc_create(out_file, 0, &ncOutid);
  if (status != NC_NOERR) handle_error(status,out_file,status);
  status = nc_set_fill(ncOutid,NC_NOFILL,&j);
  if (status != NC_NOERR) handle_error(status,out_file,status);

  // printf("Created file %s with id %d.\n",out_file,ncOutid);
    
  // Copy all of the global attributes over.
  for (j=0;j<ngatt;j++) {
    status = nc_inq_attname (ncid, NC_GLOBAL, j, att_name);
    if (status != NC_NOERR) handle_error(status,"Global",j);    
    status = nc_copy_att(ncid, NC_GLOBAL, att_name, ncOutid, NC_GLOBAL);
    if (status != NC_NOERR) handle_error(status,att_name,j);
  }
  {
    char hist[1000];
    status = nc_get_att_text(ncid, NC_GLOBAL,"history",hist);
    if (status == NC_NOERR) {strcat(hist,"\n"); strcat(hist,arglist);}
    else strcpy(hist,arglist);
    status = nc_put_att_text(ncOutid, NC_GLOBAL,"history",strlen(hist),hist);
  }
  
  // Copy all appropriate dimensions over.
  for (i=0;i<ndims;i++) if (use_dim[i]) {
    status = nc_inq_dim(ncid, i, dim_name[i], &dim_len[i]);
    if (status != NC_NOERR) handle_error(status, "", i);
    if (dim_len[i] > max_dim_len) max_dim_len = dim_len[i];

    if (i==recdim)
      status = nc_def_dim(ncOutid, dim_name[i], NC_UNLIMITED, &dim2id[i]);
    else
      status = nc_def_dim(ncOutid, dim_name[i], dim_len[i], &dim2id[i]);
    if (status != NC_NOERR) handle_error(status,dim_name[i],i);

    // Get information about the coordinate variable.
    status = nc_inq_varid (ncid, dim_name[i], &dv_id[i]);
    if (status != NC_NOERR) handle_error(status, dim_name[i], i);
    status = nc_inq_vartype(ncid, dv_id[i], &xtype);
    if (status != NC_NOERR) handle_error(status, dim_name[i], i);
    status = nc_inq_varnatts(ncid, dv_id[i], &num_att);
    if (status != NC_NOERR) handle_error(status,dim_name[i],i);

    // Create the coordinate variables.
    status = nc_def_var (ncOutid, dim_name[i], xtype, 1, &dim2id[i], &dim2vid[i]);
    if (status != NC_NOERR) handle_error(status, dim_name[i],i);    
    // Copy all of the attributes over.
    for (j=0;j<num_att;j++) {
      status = nc_inq_attname (ncid, dv_id[i], j, att_name);
      if (status != NC_NOERR) handle_error(status,att_name,j);
      status = nc_copy_att(ncid, dv_id[i], att_name, ncOutid, dim2vid[i]);
      if (status != NC_NOERR) handle_error(status,att_name,j);
    }
  }
  
  // Copy the vertical dimensions over from depth_file.
  //    if (strlen(depth_file) > 1)
  status = nc_open(depth_file,NC_NOWRITE, &nc_den_id);
  if (status != NC_NOERR) handle_error(status,depth_file,status);

  for (i=0;i<2;i++) {
    int ddid;
    status = nc_inq_dimid (nc_den_id, depth_names[i], &ddid);
    if (status != NC_NOERR) handle_error(status,depth_names[i],0);
    status = nc_inq_dimlen(nc_den_id, ddid, &ddim_len[i]);
    if (status != NC_NOERR) handle_error(status,depth_names[i], i);

    status = nc_def_dim(ncOutid, depth_names[i], ddim_len[i], &dd2id[i]);
    if (status != NC_NOERR) handle_error(status,depth_names[i],i);

    // Get information about the coordinate variable.
    status = nc_inq_varid (nc_den_id, depth_names[i], &ddvid[i]);
    if (status != NC_NOERR) handle_error(status, depth_names[i], i);
    status = nc_inq_vartype(nc_den_id, ddvid[i], &xtype);
    if (status != NC_NOERR) handle_error(status, depth_names[i], i);
    status = nc_inq_varnatts(nc_den_id, ddvid[i], &num_att);
    if (status != NC_NOERR) handle_error(status,depth_names[i],i);

    // Create the coordinate variables.
    status = nc_def_var (ncOutid, depth_names[i], xtype, 1, &dd2id[i], &dd2vid[i]);
    if (status != NC_NOERR) handle_error(status, depth_names[i],i);    
    // Copy all of the attributes over.
    for (j=0;j<num_att;j++) {
      status = nc_inq_attname (nc_den_id, ddvid[i], j, att_name);
      if (status != NC_NOERR) handle_error(status,att_name,j);
      status = nc_copy_att(nc_den_id, ddvid[i], att_name, ncOutid, dd2vid[i]);
      if (status != NC_NOERR) handle_error(status,att_name,j);
    }
  }


  // Create the auxiliary time variable (if it exists) and store the time indices.
  if (recdim != -1) {
    // If there is a record dimension, it must be one of the two named
    // time dimensions.  If none are named, the name of the record
    // dimension is copied into it.
    if ((strcmp(dim_name[recdim],time_names[0]) != 0) &&
        (strcmp(dim_name[recdim],time_names[1]) != 0)) {
      if (strlen(time_names[0]) == 0) strcpy(time_names[0],dim_name[recdim]);
      else if (strlen(time_names[1]) == 0) strcpy(time_names[1],dim_name[recdim]);
      else {
        printf("ERROR: The specified time variables %s and %s do not agree\n"
               "\twith the record variable, %s.\n",time_names[0],time_names[1],
               dim_name[recdim]);
        exit(-1);
      }
    }
  }
  for (v=0;v<2;v++) {
    status = nc_inq_varid(ncOutid, time_names[v], &time_out_id[v]);
    if (status != NC_NOERR) {
      if (strlen(time_names[v]) > 0)  {
        int out_dim;
        status = nc_inq_varid(ncid, time_names[v], &time_in_id[v]);
        if (status != NC_NOERR) handle_error(status, time_names[v], v);
        status = nc_inq_var(ncid, time_in_id[v], att_name, &xtype, &ndim,
                            dimids, &num_att);
        if (status != NC_NOERR) handle_error(status, time_names[v], v);
        if (ndim > 1) {
          printf("ERROR: Time variable %s has %d dimensions in %s.\n",time_names[v],ndim,in_file[0]);
          exit(-1);
        }
        out_dim = dim2id[dimids[0]];

        status = nc_def_var(ncOutid, time_names[v], xtype, ndim, &out_dim, &time_out_id[v]);
        if (status != NC_NOERR) handle_error(status, time_names[v],v);
        // Copy all of the attributes over.
        for (j=0;j<num_att;j++) {
          status = nc_inq_attname(ncid, time_in_id[v], j, att_name);
          if (status != NC_NOERR) handle_error(status,att_name,j);
          status = nc_copy_att(ncid, time_in_id[v], att_name, ncOutid, time_out_id[v]);
          if (status != NC_NOERR) handle_error(status,att_name,j);
        }
      }
    } else {
      status = nc_inq_varid(ncid, time_names[v], &time_in_id[v]);
      if (status != NC_NOERR) handle_error(status, time_names[v], v);
    }
  }

  // Create the output variables, while checking the validity of the list.
  for (v=0;v<*num_var;v++) {
    int id, vin_id, frecdim, valid = 1;
    for (i=0;i<2;i++) if (strcmp(var_names[v],time_names[i])==0) valid = 0;
    for (i=0;i<ndims;i++) if (strcmp(var_names[v],dim_name[i])==0) valid = 0;
    for (i=0;i<2;i++) if (strcmp(var_names[v],depth_names[i])==0) valid = 0;
    
    if (valid) {
      id = ncInid[var_file[v]];
      
      if (var_file[v] == 0) frecdim = recdim;
      else {
        status = nc_inq_unlimdim(id,&frecdim);
        if (status != NC_NOERR) handle_error(status,"Finding record dimid",status);
      }

      status = nc_inq_varid(id, var_names[v], &vin_id);
      if (status != NC_NOERR) handle_error(status, var_names[v], v);
      status = nc_inq_var(id, vin_id, att_name, &xtype, &ndim,
                          dimids, &num_att);
      if (status != NC_NOERR) handle_error(status, var_names[v], v);

      if (ndim <= 2) {
        printf("Variable %s has only 2 dimensions and will be excluded.\n", var_names[v]);
        valid = 0;
      } else if ((ndim == 3) && (dimids[0] == frecdim)) {
        printf("Variable %s uses the record dimension as 3rd dimension and will be excluded.\n", var_names[v]);
        valid = 0;
      }
    }

    if (valid) {
      // Get information about the variable.
      int out_dimids[4];
      if (dimids[0] != frecdim) {
        out_dimids[0] = dd2id[0]; var_count[v][0] = ddim_len[0];
        static_var[v] = 1; i = 1;
      } else {
        out_dimids[0] = dim2id[recdim]; out_dimids[1] = dd2id[0];
        var_count[v][0] = 1; var_count[v][1] = ddim_len[0];
        static_var[v] = 0; i = 2;
      }
      var_size[v] = ddim_len[0];
      for (;i<ndim;i++) {
        int did;
        did = find_dimid(id,dimids[i],ncid);
        out_dimids[i] = dim2id[did];
        var_count[v][i] = dim_len[did];
        var_size[v] *= var_count[v][i];
      }

      status = nc_def_var(ncOutid, var_names[v], xtype, ndim, out_dimids, &var_id[v]);
      if (status != NC_NOERR) handle_error(status, var_names[v],v);
      // Copy all of the attributes over.
      for (j=0;j<num_att;j++) {
        status = nc_inq_attname(id, vin_id, j, att_name);
        if (status != NC_NOERR) handle_error(status,att_name,j);
        status = nc_copy_att(id, vin_id, att_name, ncOutid, var_id[v]);
        if (status != NC_NOERR) handle_error(status,att_name,j);
      }
      status = nc_get_att_double(id, vin_id,"missing_value",&missing_val[v]);
      if (status != NC_NOERR) {
        missing_val[v] = -1.0e34;
        status = nc_put_att_double(ncOutid,var_id[v],"missing_value",xtype,1,&missing_val[v]);
        if (status != NC_NOERR) handle_error(status,"missing_value",v);
      }
    } else {
      for (i=v;i<*num_var-1;i++) strcpy(var_names[i],var_names[i+1]);
      (*num_var)--; v--;
    }
  }

  status = nc_enddef(ncOutid);
  if (status != NC_NOERR) handle_error(status,out_file,status);
  // printf("Finished define mode for %s.\n",out_file);
    
    
    
    
/*
    // Create the vertical coordinates. //
    status = nc_def_dim(ncOutid, zc_name, nz, &layerid);
    if (status != NC_NOERR) handle_error(status,zc_name,0);
    status = nc_def_var (ncOutid, zc_name, NC_DOUBLE, 1, &layerid, &layervid);
    if (status != NC_NOERR) handle_error(status,zc_name,0);

    status = nc_def_dim(ncOutid, ze_name, (size_t) (nz+1), &intid);
    if (status != NC_NOERR) handle_error(status,ze_name,0);
    status = nc_def_var (ncOutid, ze_name, NC_DOUBLE, 1, &intid, &intvid);
    if (status != NC_NOERR) handle_error(status,ze_name,0);
    status = nc_put_att_text(ncOutid, intvid, "units", 2, "m");
    if (status != NC_NOERR) handle_error(status,"Units Interface",0);

    dims[0] = layervid;
    {
      strcpy(att[0][0],"long_name"); strcpy(att[0][1],"Depth of Layer Center");
//      strcpy(att[1][0],"units"); strcpy(att[1][1],"m");
      strcpy(att[1][0],"units"); strcpy(att[1][1],"cm");
      strcpy(att[2][0],"positive"); strcpy(att[2][1],"down");
      strcpy(att[3][0],"edges"); strcpy(att[2][1],ze_name);
      for (j=0;j<=2;j++) {
        status = nc_put_att_text(ncOutid, layervid, att[j][0],
            strlen(att[j][1]), att[j][1]);
        if (status != NC_NOERR) handle_error(status,att[j][0],j);
      }
    
      strcpy(att[0][0],"long_name"); strcpy(att[0][1],"Depth of edges");
//      strcpy(att[1][0],"units"); strcpy(att[1][1],"m");
      strcpy(att[1][0],"units"); strcpy(att[1][1],"cm");
      strcpy(att[2][0],"positive"); strcpy(att[2][1],"down");
      for (j=0;j<=2;j++) {
        status = nc_put_att_text(ncOutid, intvid, att[j][0],
            strlen(att[j][1]), att[j][1]);
        if (status != NC_NOERR) handle_error(status,att[j][0],j);    
      }
    }
*/
     
    // Copy the axis values from the first file.
  {
    double *coord_array;
    coord_array = malloc(sizeof(double)*(max_dim_len));
    for (i=0;i<ndims;i++) if (use_dim[i] && (i!=recdim)) {
      status = nc_get_var_double(ncid,dv_id[i],coord_array);
      if (status != NC_NOERR) handle_error(status,"Read Coordinate Variable",i);
      
      status = nc_put_var_double(ncOutid,dim2vid[i],coord_array);
      if (status != NC_NOERR) handle_error(status,"Write Coordinate Variable",i);
    }
    
    // Copy the vertical axis values from the depth file.
    for (i=0;i<2;i++) {
      status = nc_get_var_double(nc_den_id,ddvid[i],coord_array);
      if (status != NC_NOERR) handle_error(status,"Read Coordinate Variable",i);
      
      status = nc_put_var_double(ncOutid,dd2vid[i],coord_array);
      if (status != NC_NOERR) handle_error(status,"Write Coordinate Variable",i);
    }

    free(coord_array);
  }

    /*
    {
      double *z;
      z = (double *) calloc((size_t) (nz+1), sizeof(double));
      for (i=0;i<=nz;i++) z[i] = (-100.0)*int_depth[i];
      status = nc_put_var_double(ncOutid,intid,z);
      if (status != NC_NOERR) handle_error(status,"Interface Coordinate",0);

      for (i=0;i<nz;i++) z[i] = (-100.0)*lay_depth[i];
      status = nc_put_var_double(ncOutid,layerid,z);
      if (status != NC_NOERR) handle_error(status,"Layer Coordinate",0);
    }
    */

  nc_close(nc_den_id);
}