Exemple #1
0
/*! \cond INTERNAL */
int cpy_att(int in_id,int out_id,int var_in_id,int var_out_id)
/*
   int in_id: input netCDF input-file ID
   int out_id: input netCDF output-file ID
   int var_in_id: input netCDF input-variable ID
   int var_out_id: input netCDF output-variable ID
 */
{
  /* Routine to copy all the attributes from the input netCDF
     file to the output netCDF file. If var_in_id == NC_GLOBAL,
     then the global attributes are copied. Otherwise the variable's
     attributes are copied. */

  int idx;
  int nbr_att;

  if(var_in_id == NC_GLOBAL) {
    (void)nc_inq_natts(in_id,&nbr_att);
  } else {
    (void)nc_inq_varnatts(in_id, var_in_id, &nbr_att);
  }

  /* Get the attributes names, types, lengths, and values */
  for (idx=0; idx<nbr_att; idx++) {
    char att_nm[MAX_VAR_NAME_LENGTH];

    (void)nc_inq_attname(in_id, var_in_id, idx, att_nm);
    (void)nc_copy_att(in_id, var_in_id, att_nm, out_id, var_out_id);
  } 

  return(EX_NOERR);
} 
Exemple #2
0
void R_nc4_inq_attname( int *ncid, int *varid, int *attnum, char **attname, int *retval )
{
	*retval = nc_inq_attname( *ncid, *varid, *attnum, attname[0] );
	if( *retval != NC_NOERR ) {
		Rprintf( "Error in R_nc4_inq_attname: %s\n",
			nc_strerror(*retval) );
		}
}
Exemple #3
0
NcToken NcVar::attname( int attnum ) const // caller must delete[]
{
    if (attnum < 0 || attnum >= num_atts())
      return 0;
    char aname[NC_MAX_NAME];
    if (NcError::set_err(
			 nc_inq_attname(the_file->id(), the_id, attnum, aname)
			 ) != NC_NOERR)
      return 0;
    char* rname = new char[1 + strlen(aname)];
    strcpy(rname, aname);
    return rname;
}
Exemple #4
0
int NcVar::attnum( NcToken attrname ) const
{
    int num;
    for(num=0; num < num_atts(); num++) {
	char aname[NC_MAX_NAME];
	NcError::set_err(
			 nc_inq_attname(the_file->id(), the_id, num, aname)
			 );
	if (strcmp(aname, attrname) == 0)
	  break;
    }
    return num;			// num_atts() if no such attribute
}
Exemple #5
0
int
ncattname(
    int		ncid,
    int		varid,
    int		attnum,
    char*	name
)
{
	const int status = nc_inq_attname(ncid, varid, attnum, name);
	if(status != NC_NOERR)
	{
		nc_advise("ncattname", status, "ncid %d", ncid);
		return -1;
	}
	return attnum;
}
Exemple #6
0
static void
pr_att(
    int ncid,
    int varid,
    const char *varname,
    int ia
    )
{
    struct ncatt att;		/* attribute */
	    
    NC_CHECK( nc_inq_attname(ncid, varid, ia, att.name) );

    Printf ("\t\t%s:%s = ", varname, att.name);

    NC_CHECK( nc_inq_att(ncid, varid, att.name, &att.type, &att.len) );

    if (att.len == 0) {	/* show 0-length attributes as empty strings */
	att.type = NC_CHAR;
	att.len = 1;
    }
    switch (att.type) {
    case NC_CHAR:
	att.string = (char *) malloc(att.len);
	if (!att.string) {
	    error("Out of memory!");
	    NC_CHECK( nc_close(ncid) );
	    return;
	}
	NC_CHECK( nc_get_att_text(ncid, varid, att.name, att.string ) );
	pr_att_string(att.len, att.string);
	free(att.string);
	break;
    default:
	att.vals = (double *) malloc(att.len * sizeof(double));
	if (!att.vals) {
	    error("Out of memory!");
	    NC_CHECK( nc_close(ncid) );
	    return;
	}
	NC_CHECK( nc_get_att_double(ncid, varid, att.name, att.vals ) );
	pr_att_vals(att.type, att.len, att.vals);
	free(att.vals);
	break;
    }
    Printf (" ;\n");
}
Exemple #7
0
NCstate NCdataCopyAttributes(int inNCid, int inVarid, int outNCid, int outVarid, bool overwrite) {
    bool redef;
    int status, att = 0, attId;
    char attName[NC_MAX_NAME];

    redef = nc_redef(outNCid) == NC_NOERR;
    while ((status = nc_inq_attname(inNCid, inVarid, att++, attName)) == NC_NOERR) {
        if (overwrite || (nc_inq_attid(outNCid, outVarid, attName, &attId) != NC_NOERR)) {
            if ((status = nc_copy_att(inNCid, inVarid, attName, outNCid, outVarid)) != NC_NOERR) {
                NCprintNCError (status, "_NCdataCopyAttributes");
                return (NCfailed);
            }
        }
    }
    if (redef) nc_enddef(outNCid);
    return (NCsucceeded);
}
Exemple #8
0
/**********************************************************************
  void mpp_copy_var_att(fid_in, fid_out)
  copy all the field attribute from infile to outfile
**********************************************************************/
void mpp_copy_var_att(int fid_in, int vid_in, int fid_out, int vid_out)
{
  int natt, status, i, ncid_in, ncid_out, fldid_in, fldid_out;
  char name[256];
  char errmsg[512];

  if( mpp_pe() != mpp_root_pe() ) return;
  
  if(fid_in<0 || fid_in >=nfiles) mpp_error("mpp_io(mpp_copy_var_att): invalid fid_in number, fid should be "
				      "a nonnegative integer that less than nfiles");
  if(fid_out<0 || fid_out >=nfiles) mpp_error("mpp_io(mpp_copy_var_att): invalid fid_out number, fid should be "
				      "a nonnegative integer that less than nfiles");
        
  ncid_in   = files[fid_in].ncid;
  ncid_out  = files[fid_out].ncid;  
  fldid_in  = files[fid_in].var[vid_in].fldid;
  fldid_out = files[fid_out].var[vid_out].fldid;
  
  status = nc_inq_varnatts(ncid_in, fldid_in, &natt);
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_copy_var_att): Error in inquiring natts of var %s of file %s",
	    files[fid_in].var[vid_in].name, files[fid_in].name );
    netcdf_error(errmsg, status);
  }
  
  for(i=0; i<natt; i++) {
    status = nc_inq_attname(ncid_in, fldid_in, i, name);
    if(status != NC_NOERR) {
      sprintf(errmsg, "mpp_io(mpp_copy_var_att): Error in inquiring %d attname of var %s of file %s", i, 
	      files[fid_in].var[vid_in].name, files[fid_in].name );
      netcdf_error(errmsg, status);
    }
    status = nc_copy_att(ncid_in, fldid_in, name, ncid_out, fldid_out);
    if(status != NC_NOERR) {
      sprintf(errmsg, "mpp_io(mpp_copy_var_att): Error in copying att %s of var %s of file %s", name,  
	      files[fid_in].var[vid_in].name, files[fid_in].name );
      netcdf_error(errmsg, status);
    }
  }

}; /* mpp_copy_field_att */
//! Query the name of an attribute given a location id, a variable id and the attribute number
int CNetCdfInterface::inqAttName(int ncid, int varid, int attnum, StdString& name)
{
  std::vector<char> attName(NC_MAX_NAME + 1,' ');
  int status = nc_inq_attname(ncid, varid, attnum, &attName[0]);
  if (NC_NOERR != status)
  {
    StdString errormsg(nc_strerror(status));
    StdStringStream sstr;

    sstr << "Error when calling function nc_inq_attname(ncid, varid, attnum, attName)" << std::endl;
    sstr << errormsg << std::endl;
    sstr << "Unable to query the name: " << name << " of attribute " << attnum << " given the location id:" << ncid << " and the variable id:" << varid << std::endl;
    StdString e = sstr.str();
    throw CNetCdfException(e);
  }

  int nameSize = 0;
  while ((nameSize < NC_MAX_NAME) && (' ' != attName[nameSize] )) ++nameSize;
  name.resize(nameSize);
//  for (int idx = 0; idx < nameSize; ++idx) name.at(idx) = attName[idx];
  std::copy(&attName[0], &attName[nameSize-1], name.begin());

  return status;
}
Exemple #10
0
int
main(int argc, char **argv)
{
    printf("\n*** Testing 'Fileinfo attributes.\n");

    {
	hid_t fileid;
	hid_t fcplid;
	hid_t scalar_spaceid;

        printf("*** creating test file using HDF5 directly %s...", HDFFILE);

        /* Create scalar dataspace */
        if((scalar_spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;

        /* Set creation ordering for file, so we can revise its contents later */
        if((fcplid = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
        if(H5Pset_link_creation_order(fcplid, H5P_CRT_ORDER_TRACKED) < 0) ERR;
        if(H5Pset_attr_creation_order(fcplid, H5P_CRT_ORDER_TRACKED) < 0) ERR;

        /* Create new file, using default properties */
        if((fileid = H5Fcreate(HDFFILE, H5F_ACC_TRUNC, fcplid, H5P_DEFAULT)) < 0) ERR;
        /* Close file creation property list */
        if(H5Pclose(fcplid) < 0) ERR;

        /* Add attributes to root group */
        {
            hid_t scalar_spaceid = -1;
            hid_t attid = -1;

            /* Create scalar dataspace */
            if((scalar_spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;

            /* Create attribute with native integer datatype on object */
            if((attid = H5Acreate2(fileid, INT_ATT_NAME, H5T_NATIVE_INT, scalar_spaceid, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
            if(H5Aclose(attid) < 0) ERR;

            /* Clean up objects created */
            if(H5Sclose(scalar_spaceid) < 0) ERR;
        }

        /* Close rest */
        if(H5Sclose(scalar_spaceid) < 0) ERR;
        if(H5Fclose(fileid) < 0) ERR;
    }

    {
	int root, grpid, varid, stat, natts, id;
	int data = 17;
	const char* sdata = "text";
	char ncprops[8192];
	size_t len;
	int dimid;
        nc_type xtype;
	char name[NC_MAX_NAME];

        printf("\n*** creating netcdf-4 test file using netCDF %s...", NC4FILE);

	if(nc_create(NC4FILE,NC_WRITE|NC_CLOBBER|NC_NETCDF4,&root)!=0) ERR;
	/* Create global attribute */
	if(nc_put_att_int(root,NC_GLOBAL,INT_ATT_NAME,NC_INT,1,&data)!=0) ERR;
	/* Create global variable */
	if(nc_def_var(root,INT_VAR_NAME,NC_INT,0,NULL,&varid)!=0) ERR;
	/* Create attribute on var */
	if(nc_put_att_int(root,varid,INT_ATT_NAME,NC_INT,1,&data)!=0) ERR;
	/* Create global subgroup */
	if(nc_def_grp(root,GROUPNAME,&grpid)!=0) ERR;
	/* Create global attribute in the group */
	if(nc_put_att_int(grpid,NC_GLOBAL,INT_ATT_NAME,NC_INT,1,&data)!=0) ERR;
	/* Create _NCProperties as var attr and as subgroup attribute */
	if(nc_put_att_text(grpid,NC_GLOBAL,NCPROPS,strlen(sdata),sdata)!=0) ERR;
	if(nc_put_att_text(root,varid,NCPROPS,strlen(sdata),sdata)!=0) ERR;
	/* Create var + dimension to cause e.g. dimscales to appear */
	if(nc_def_dim(root,DIMNAME,(size_t)4,&dimid)!=0) ERR;
	if(nc_def_var(root,DIMNAME,NC_INT,1,&dimid,&varid)!=0) ERR; /* same name */
	/* Close, then re-open */
	if(nc_close(root)) ERR;
	if(nc_open(NC4FILE,NC_WRITE|NC_NETCDF4,&root)!=0) ERR;

	/* Is all invisible attributes actually invisible vis-a-vis nc_inq? */
        if(nc_inq(root,NULL,NULL,&natts,NULL)!=0) ERR;
	if(natts != 1) ERR;

	/* Now, fiddle with the NCPROPS attribute */

	/* Get its metadata */
	if(nc_inq_att(root,NC_GLOBAL,NCPROPS,&xtype,&len)!=0) ERR;
	if(xtype != NC_CHAR) ERR;

	/* Read in two ways */
	if(nc_get_att_text(root,NC_GLOBAL,NCPROPS,ncprops)!=0) ERR;
	if(strlen(ncprops) != len) ERR;

	/* Attempt to get attribute metadata piecemeal; some will fail */
	id = -1;
	stat = nc_inq_attid(root,NC_GLOBAL,NCPROPS,&id);
	if(stat == NC_NOERR) ERR;
	stat = nc_inq_attname(root,NC_GLOBAL,id,name);
	if(stat == NC_NOERR) ERR;
	if(nc_inq_atttype(root,NC_GLOBAL,NCPROPS,&xtype)!=0) ERR;
	if(xtype != NC_CHAR) ERR;
	if(nc_inq_attlen(root,NC_GLOBAL,NCPROPS,&len)!=0) ERR;
	if(len != strlen(ncprops)) ERR;

	/*Overwrite _NCProperties root attribute; should fail */
	stat = nc_put_att_text(root,NC_GLOBAL,NCPROPS,strlen(sdata),sdata);
	if(stat == NC_NOERR) ERR;

	/* Delete; should fail */
	stat = nc_del_att(root,NC_GLOBAL,NCPROPS);
        if(stat != NC_ENOTATT) ERR;

	/* Ditto _SuperblockVersion */

	/* Get its metadata */
	if(nc_inq_att(root,NC_GLOBAL,SUPERBLOCKATT,&xtype,&len)!=0) ERR;
	if(xtype != NC_INT) ERR;
	if(len != 1) ERR;

	if(nc_get_att_int(root,NC_GLOBAL,SUPERBLOCKATT,&data)!=0) ERR;

	/* Attempt to get attribute metadata piecemeal */
	stat = nc_inq_attid(root,NC_GLOBAL,SUPERBLOCKATT,&id);
	if(stat == NC_NOERR) ERR;
	stat = nc_inq_attname(root,NC_GLOBAL,id,name);
	if(stat == NC_NOERR) ERR;
	if(nc_inq_atttype(root,NC_GLOBAL,SUPERBLOCKATT,&xtype)!=0) ERR;
	if(xtype != NC_INT) ERR;
	if(nc_inq_attlen(root,NC_GLOBAL,SUPERBLOCKATT,&len)!=0) ERR;
	if(len != 1) ERR;

	/*Overwrite; should fail */
	stat = nc_put_att_int(root,NC_GLOBAL,NCPROPS,NC_INT,1,&data);
	if(stat == NC_NOERR) ERR;

	/* Delete; should fail */
	stat = nc_del_att(root,NC_GLOBAL,SUPERBLOCKATT);
        if(stat == NC_NOERR) ERR;

	/* Ditto _IsNetcdf4 */

	/* Get its metadata */
	if(nc_inq_att(root,NC_GLOBAL,ISNETCDF4ATT,&xtype,&len)!=0) ERR;
	if(xtype != NC_INT) ERR;
	if(len != 1) ERR;

	if(nc_get_att_int(root,NC_GLOBAL,ISNETCDF4ATT,&data)!=0) ERR;

	/* Attempt to get attribute metadata piecemeal */
	stat = nc_inq_attid(root,NC_GLOBAL,ISNETCDF4ATT,&id);
	if(stat == NC_NOERR) ERR;
	stat = nc_inq_attname(root,NC_GLOBAL,id,name);
	if(stat == NC_NOERR) ERR;
	if(nc_inq_atttype(root,NC_GLOBAL,ISNETCDF4ATT,&xtype)!=0) ERR;
	if(xtype != NC_INT) ERR;
	if(nc_inq_attlen(root,NC_GLOBAL,ISNETCDF4ATT,&len)!=0) ERR;
	if(len != 1) ERR;

	/*Overwrite; should fail */
	stat = nc_put_att_int(root,NC_GLOBAL,ISNETCDF4ATT,NC_INT,1,&data);
	if(stat == NC_NOERR) ERR;

	/* Delete; should fail */
	stat = nc_del_att(root,NC_GLOBAL,ISNETCDF4ATT);
        if(stat == NC_NOERR) ERR;

	if(nc_close(root)!=0) ERR;
    }

    SUMMARIZE_ERR;
    FINAL_RESULTS;
}
Exemple #11
0
int ex_copy (int in_exoid, int out_exoid)
{
   int status;
   int ndims;                   /* number of dimensions */
   int nvars;                   /* number of variables */
   int ngatts;                  /* number of global attributes */
   int recdimid;                /* id of unlimited dimension */
   int dimid;                   /* dimension id */
   int dim_out_id;              /* dimension id */
   int varid;                   /* variable id */
   int var_out_id;              /* variable id */
   struct ncvar var;            /* variable */
   struct ncatt att;            /* attribute */
   nc_type att_type = NC_NAT;
   size_t att_len = 0;
   size_t i;
   size_t numrec;
   size_t dim_sz;
   char dim_nm[NC_MAX_NAME];
   int in_large, out_large;
   char errmsg[MAX_ERR_LENGTH];

   exerrval = 0; /* clear error code */

   /*
    * Get exodus_large_model setting on both input and output
    * databases so know how to handle coordinates.
    */
   in_large  = ex_large_model(in_exoid);
   out_large = ex_large_model(out_exoid);
   
   /*
    * get number of dimensions, number of variables, number of global
    * atts, and dimension id of unlimited dimension, if any
    */

   (void)nc_inq(in_exoid, &ndims, &nvars, &ngatts, &recdimid);
   (void)nc_inq_dimlen(in_exoid, recdimid, &numrec);

   /* put output file into define mode */
   (void)nc_redef(out_exoid);

   /* copy global attributes */
   for (i = 0; i < (size_t)ngatts; i++) {

     (void)nc_inq_attname(in_exoid, NC_GLOBAL, i, att.name);
        
     /* if attribute exists in output file, don't overwrite it; compute 
      * word size, I/O word size etc. are global attributes stored when
      * file is created with ex_create;  we don't want to overwrite those
      */
     if ((status = nc_inq_att(out_exoid, NC_GLOBAL, att.name, &att.type, &att.len)) != NC_NOERR) {

        /* The "last_written_time" attribute is a special attribute
           used by the Sierra IO system to determine whether a
           timestep has been fully written to the database in order to
           try to detect a database crash that happens in the middle
           of a database output step. Don't want to copy that attribute.
        */
        if (strcmp(att.name,"last_written_time") != 0) {
          /* attribute doesn't exist in new file so OK to create it */
          nc_copy_att(in_exoid,NC_GLOBAL,att.name,out_exoid,NC_GLOBAL);
        }
      }
   }

   /* copy dimensions */

   /* Get the dimension sizes and names */

   for(dimid = 0; dimid < ndims; dimid++){

     (void)nc_inq_dim(in_exoid,dimid,dim_nm,&dim_sz);

     /* If the dimension isn't one we specifically don't want 
      * to copy (ie, number of QA or INFO records) and it 
      * hasn't been defined, copy it */
     
     if ( ( strcmp(dim_nm,DIM_NUM_QA)        != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_INFO)      != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_NOD_VAR)   != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_EDG_VAR)   != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_FAC_VAR)   != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_ELE_VAR)   != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_NSET_VAR)  != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_ESET_VAR)  != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_FSET_VAR)  != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_SSET_VAR)  != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_ELSET_VAR) != 0) &&
	  ( strcmp(dim_nm,DIM_NUM_GLO_VAR)   != 0) ) {
       
       /* See if the dimension has already been defined */
       status = nc_inq_dimid(out_exoid, dim_nm, &dim_out_id);
       
       if(status != NC_NOERR) {
	 if(dimid != recdimid) {
	   status = nc_def_dim(out_exoid, dim_nm, dim_sz,       &dim_out_id);
	 } else {
	   status = nc_def_dim(out_exoid, dim_nm, NC_UNLIMITED, &dim_out_id);
	 } /* end else */
	 if (status != NC_NOERR) {
	   exerrval = status;
	   sprintf(errmsg,
		   "Error: failed to define %s dimension in file id %d",
		   dim_nm, out_exoid);
	   ex_err("ex_copy",errmsg,exerrval);
	   return (EX_FATAL);
	 }
       } /* end if */
     } /* end if */
   } /* end loop over dim */

   /* DIM_STR_NAME is a newly added dimension required by current API.
    * If it doesn't exist on the source database, we need to add it to
    * the target...
    */
   status = nc_inq_dimid(in_exoid, DIM_STR_NAME, &dim_out_id);
   if (status != NC_NOERR) {
     /* Not found; set to default value of 32+1. */
     if ((status = nc_def_dim(out_exoid, DIM_STR_NAME, 33, &dim_out_id)) != NC_NOERR) {
       exerrval = status;
       sprintf(errmsg,
	       "Error: failed to define string name dimension in file id %d",
	       out_exoid);
       ex_err("ex_copy",errmsg,exerrval);
       return (EX_FATAL);
     }
   }

   status = nc_inq_att(in_exoid, NC_GLOBAL, ATT_MAX_NAME_LENGTH, &att_type, &att_len);
   if (status != NC_NOERR) {
      int max_so_far = 32;
      nc_put_att_int(out_exoid, NC_GLOBAL, ATT_MAX_NAME_LENGTH, NC_INT, 1, &max_so_far);
    }

   /* copy variable definitions and variable attributes */
   for (varid = 0; varid < nvars; varid++) {

     (void)nc_inq_var(in_exoid, varid, var.name, &var.type, &var.ndims, 
		 var.dims, &var.natts);

      /* we don't want to copy some variables because there is not a
       * simple way to add to them;
       * QA records, info records and all results variables (nodal
       * element, and global results) are examples
       */

      if ( ( strcmp(var.name,VAR_QA_TITLE)      != 0) &&
           ( strcmp(var.name,VAR_INFO)          != 0) &&
           ( strcmp(var.name,VAR_EBLK_TAB)      != 0) &&
           ( strcmp(var.name,VAR_FBLK_TAB)      != 0) &&
           ( strcmp(var.name,VAR_ELEM_TAB)      != 0) &&
           ( strcmp(var.name,VAR_ELSET_TAB)     != 0) &&
           ( strcmp(var.name,VAR_SSET_TAB)      != 0) &&
           ( strcmp(var.name,VAR_FSET_TAB)      != 0) &&
           ( strcmp(var.name,VAR_ESET_TAB)      != 0) &&
           ( strcmp(var.name,VAR_NSET_TAB)      != 0) &&
           ( strcmp(var.name,VAR_NAME_GLO_VAR)  != 0) &&
           ( strcmp(var.name,VAR_GLO_VAR)       != 0) &&
           ( strcmp(var.name,VAR_NAME_NOD_VAR)  != 0) &&
           ( strcmp(var.name,VAR_NOD_VAR)       != 0) &&
           ( strcmp(var.name,VAR_NAME_EDG_VAR)  != 0) &&
           ( strcmp(var.name,VAR_NAME_FAC_VAR)  != 0) &&
           ( strcmp(var.name,VAR_NAME_ELE_VAR)  != 0) &&
           ( strcmp(var.name,VAR_NAME_NSET_VAR) != 0) &&
           ( strcmp(var.name,VAR_NAME_ESET_VAR) != 0) &&
           ( strcmp(var.name,VAR_NAME_FSET_VAR) != 0) &&
           ( strcmp(var.name,VAR_NAME_SSET_VAR) != 0) &&
           ( strcmp(var.name,VAR_NAME_ELSET_VAR) != 0)&&
           ( strncmp(var.name,"vals_elset_var", 14) != 0) &&
           ( strncmp(var.name,"vals_sset_var",  13) != 0) &&
           ( strncmp(var.name,"vals_fset_var",  13) != 0) &&
           ( strncmp(var.name,"vals_eset_var",  13) != 0) &&
           ( strncmp(var.name,"vals_nset_var",  13) != 0) &&
           ( strncmp(var.name,"vals_nod_var",   12) != 0) &&
           ( strncmp(var.name,"vals_edge_var",  13) != 0) &&
           ( strncmp(var.name,"vals_face_var",  13) != 0) &&
           ( strncmp(var.name,"vals_elem_var",  13) != 0) ) {

        if (strncmp(var.name,VAR_COORD,5) == 0) {
          var_out_id = cpy_coord_def (in_exoid, out_exoid, recdimid, var.name,
                                      in_large, out_large);
        } else {
          var_out_id = cpy_var_def (in_exoid, out_exoid, recdimid, var.name);
        }

         /* copy the variable's attributes */
         (void) cpy_att (in_exoid, out_exoid, varid, var_out_id);

      }
   }

   /* take the output file out of define mode */
   if ((exerrval=nc_enddef (out_exoid)) != NC_NOERR) {
     sprintf(errmsg,
	     "Error: failed to complete definition in file id %d", 
	     out_exoid);
     ex_err("ex_copy",errmsg,exerrval);
     return (EX_FATAL);
   }

   /* output variable data */

   for (varid = 0; varid < nvars; varid++) {
     (void)nc_inq_var(in_exoid, varid, var.name, &var.type, &var.ndims,
		 var.dims, &var.natts);

      /* we don't want to copy some variable values;
       * QA records and info records shouldn't be copied because there
       * isn't an easy way to add to them;
       * the time value array ("time_whole") and any results variables
       * (nodal, elemental, or global) shouldn't be copied 
       */

      if ( ( strcmp(var.name,VAR_QA_TITLE) != 0)        &&
           ( strcmp(var.name,VAR_INFO) != 0)            &&
           ( strcmp(var.name,VAR_EBLK_TAB) != 0)        &&
           ( strcmp(var.name,VAR_FBLK_TAB) != 0)        &&
           ( strcmp(var.name,VAR_ELEM_TAB) != 0)        &&
           ( strcmp(var.name,VAR_ELSET_TAB) != 0)       &&
           ( strcmp(var.name,VAR_SSET_TAB) != 0)        &&
           ( strcmp(var.name,VAR_FSET_TAB) != 0)        &&
           ( strcmp(var.name,VAR_ESET_TAB) != 0)        &&
           ( strcmp(var.name,VAR_NSET_TAB) != 0)        &&
           ( strcmp(var.name,VAR_NAME_GLO_VAR) != 0)    &&
           ( strcmp(var.name,VAR_GLO_VAR) != 0)         &&
           ( strcmp(var.name,VAR_NAME_NOD_VAR) != 0)    &&
           ( strcmp(var.name,VAR_NOD_VAR) != 0)         &&
           ( strcmp(var.name,VAR_NAME_EDG_VAR) != 0)    &&
           ( strcmp(var.name,VAR_NAME_FAC_VAR) != 0)    &&
           ( strcmp(var.name,VAR_NAME_ELE_VAR) != 0)    &&
           ( strcmp(var.name,VAR_NAME_NSET_VAR) != 0)   &&
           ( strcmp(var.name,VAR_NAME_ESET_VAR) != 0)   &&
           ( strcmp(var.name,VAR_NAME_FSET_VAR) != 0)   &&
           ( strcmp(var.name,VAR_NAME_SSET_VAR) != 0)   &&
           ( strcmp(var.name,VAR_NAME_ELSET_VAR) != 0)  &&
           ( strncmp(var.name,"vals_elset_var", 14) != 0)&&
           ( strncmp(var.name,"vals_sset_var", 13) != 0)&&
           ( strncmp(var.name,"vals_fset_var", 13) != 0)&&
           ( strncmp(var.name,"vals_eset_var", 13) != 0)&&
           ( strncmp(var.name,"vals_nset_var", 13) != 0)&&
           ( strncmp(var.name,"vals_nod_var", 12) != 0) &&
           ( strncmp(var.name,"vals_edge_var",13) != 0) &&
           ( strncmp(var.name,"vals_face_var",13) != 0) &&
           ( strncmp(var.name,"vals_elem_var",13) != 0) &&
           ( strcmp(var.name,VAR_WHOLE_TIME) != 0) ) {

        if (strncmp(var.name,VAR_COORD,5) == 0) {
          (void) cpy_coord_val (in_exoid, out_exoid, var.name,
                                in_large, out_large);
        } else {
          (void) cpy_var_val (in_exoid, out_exoid, var.name);
        }

      }
   }

   /* ensure internal data structures are updated */

   /* if number of blocks > 0 */
   update_internal_structs( out_exoid, EX_INQ_EDGE_BLK, ex_get_counter_list(EX_EDGE_BLOCK));
   update_internal_structs( out_exoid, EX_INQ_FACE_BLK, ex_get_counter_list(EX_FACE_BLOCK));
   update_internal_structs( out_exoid, EX_INQ_ELEM_BLK, ex_get_counter_list(EX_ELEM_BLOCK));

   /* if number of sets > 0 */
   update_internal_structs( out_exoid, EX_INQ_NODE_SETS, ex_get_counter_list(EX_NODE_SET));
   update_internal_structs( out_exoid, EX_INQ_EDGE_SETS, ex_get_counter_list(EX_EDGE_SET));
   update_internal_structs( out_exoid, EX_INQ_FACE_SETS, ex_get_counter_list(EX_FACE_SET));
   update_internal_structs( out_exoid, EX_INQ_SIDE_SETS, ex_get_counter_list(EX_SIDE_SET));
   update_internal_structs( out_exoid, EX_INQ_ELEM_SETS, ex_get_counter_list(EX_ELEM_SET));

   /* if number of maps > 0 */
   update_internal_structs( out_exoid, EX_INQ_NODE_MAP, ex_get_counter_list(EX_NODE_MAP));
   update_internal_structs( out_exoid, EX_INQ_EDGE_MAP, ex_get_counter_list(EX_EDGE_MAP));
   update_internal_structs( out_exoid, EX_INQ_FACE_MAP, ex_get_counter_list(EX_FACE_MAP));
   update_internal_structs( out_exoid, EX_INQ_ELEM_MAP, ex_get_counter_list(EX_ELEM_MAP));

   return(EX_NOERR);
}
Exemple #12
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);
}
Exemple #13
0
int
main(int argc, char **argv)
{
    (void) signal(SIGFPE, SIG_IGN);

   printf("\n*** Testing netcdf-4 attribute functions.\n");
   printf("*** testing really simple global atts...");
#define NUM_SIMPLE_ATTS 9
   {
      int ncid;
      char name[NUM_SIMPLE_ATTS][ATT_MAX_NAME + 1] = {"Gc", "Gb", "Gs", "Gi", "Gf", 
						      "Gd", "G7", "G8", "G9"};
      char name_in[NC_MAX_NAME];
      int j;

      /* Create a file with some global atts. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLOBBER, &ncid)) ERR;
      for (j = 0; j < NUM_SIMPLE_ATTS; j++)
	 if (nc_put_att_int(ncid, NC_GLOBAL, name[j], NC_INT, 0, NULL)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and check the order. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      for (j = 0; j < NUM_SIMPLE_ATTS; j++)
      {
	 if (nc_inq_attname(ncid, NC_GLOBAL, j, name_in)) ERR;
	 if (strcmp(name_in, name[j])) ERR;
      }

      /* Close up shop. */
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing simple global atts...");
   {      
      int ncid;
      nc_type att_type;
      size_t att_len;
      int i;

      char *speech_in;
      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      unsigned char uchar_in[ATT_LEN], uchar_out[ATT_LEN] = {0, 128, NC_MAX_CHAR};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
      unsigned short ushort_in[ATT_LEN], ushort_out[ATT_LEN] = {0, 128, NC_MAX_USHORT};
      unsigned int uint_in[ATT_LEN], uint_out[ATT_LEN] = {0, 128, NC_MAX_UINT};
      unsigned long long uint64_in[ATT_LEN], uint64_out[ATT_LEN] = {0, 128, 18446744073709551612ULL};
      long long int64_in[ATT_LEN], int64_out[ATT_LEN] = {NC_MIN_INT64, 128, NC_MAX_INT64};


      /* This won't work, because classic files can't create these types. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_put_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, NC_USHORT, ATT_LEN, 
			    ushort_out) != NC_ESTRICTNC3) ERR;      
      if (nc_put_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, NC_UINT, ATT_LEN, 
			  uint_out) != NC_ESTRICTNC3) ERR;      
      if (nc_put_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, NC_INT64, ATT_LEN, 
			      int64_out) != NC_ESTRICTNC3) ERR;      
      if (nc_put_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, NC_UINT64, ATT_LEN, 
			       uint64_out) != NC_ESTRICTNC3) ERR;      
      if (nc_close(ncid)) ERR;

      /* Create a file with a global attribute of each type. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;      
      if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UBYTE, ATT_LEN, uchar_out)) ERR;
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out)) ERR;      
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out)) ERR;      
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out)) ERR;      
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out)) ERR;      
      if (nc_put_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, NC_USHORT, ATT_LEN, ushort_out)) ERR;      
      if (nc_put_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, NC_UINT, ATT_LEN, uint_out)) ERR;      
      if (nc_put_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, NC_INT64, ATT_LEN, int64_out)) ERR;      
      if (nc_put_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, NC_UINT64, ATT_LEN, uint64_out)) ERR;      
      if (nc_close(ncid)) ERR;

      /* Open the file and check attributes. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      /* Check text. */
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len))
	 ERR;
      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
      if (!(speech_in = malloc(att_len + 1))) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in)) ERR;      
      if (strcmp(speech, speech_in)) ERR;
      free(speech_in);
      /* Check numeric values. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != schar_out[i]) ERR;
      if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, uchar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (uchar_in[i] != uchar_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != short_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != int_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != float_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != double_out[i]) ERR;
      if (nc_get_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, ushort_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (ushort_in[i] != ushort_out[i]) ERR;
      if (nc_get_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, uint_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (uint_in[i] != uint_out[i]) ERR;
      if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, int64_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int64_in[i] != int64_out[i]) ERR;
      if (nc_get_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, uint64_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (uint64_in[i] != uint64_out[i]) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing attribute data type conversions...");

   {
      int ncid;
      int i;

      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
      unsigned short ushort_in[ATT_LEN];
      unsigned int uint_in[ATT_LEN];
      unsigned long long uint64_in[ATT_LEN];
      long long int64_in[ATT_LEN];

      /* Reopen the file and try different type conversions. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;

      /* No text conversions are allowed, and people who try them shold
       * be locked up, away from decent folk! */
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_TEXT_NAME, short_in) != NC_ECHAR) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_TEXT_NAME, int_in) != NC_ECHAR) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_TEXT_NAME, float_in) != NC_ECHAR) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_TEXT_NAME, double_in) != NC_ECHAR) ERR;
/*   if (nc_get_att_ubyte(ncid, NC_GLOBAL, ATT_TEXT_NAME, uchar_in) != NC_ECHAR) ERR;*/
      if (nc_get_att_ushort(ncid, NC_GLOBAL, ATT_TEXT_NAME, ushort_in) != NC_ECHAR) ERR;
      if (nc_get_att_uint(ncid, NC_GLOBAL, ATT_TEXT_NAME, uint_in) != NC_ECHAR) ERR;
      if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_TEXT_NAME, int64_in) != NC_ECHAR) ERR;
      if (nc_get_att_ulonglong(ncid, NC_GLOBAL, ATT_TEXT_NAME, uint64_in) != NC_ECHAR) ERR;

      /* Read all atts (except text) as double. */
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_SCHAR_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != schar_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_SHORT_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != short_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_INT_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != int_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_FLOAT_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != float_out[i]) ERR;
      /* Read all atts (except text) as float. */
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_SCHAR_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != schar_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_SHORT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != short_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_INT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != (float)int_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != (float)double_out[i]) ERR;
      /* Read all atts (except text) as int. */
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_SCHAR_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != schar_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_SHORT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != short_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_FLOAT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != (int)float_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != (int)double_out[i]) ERR;
      /* Read all atts (except text) as short. */
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SCHAR_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != schar_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_INT_NAME, short_in) != NC_ERANGE) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != (short)int_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_FLOAT_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != (short)float_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != (short)double_out[i]) ERR;
      /* Read all atts (except text) as schar. Some range errors will
       * result converting to schar. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in) != NC_ERANGE) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)short_out[i]) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in) != NC_ERANGE) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)int_out[i]) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)float_out[i]) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)double_out[i]) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing simple variable atts...");
   {
      int ncid, varid, dimids[2];
      nc_type att_type;
      size_t att_len;
      int i, v;

      char *speech_in;
      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};

      /* Create a file with two vars, attaching to each an attribute of
       * each type. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
      if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
      if (nc_put_att_text(ncid, varid, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, varid, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;      
      if (nc_put_att_short(ncid, varid, ATT_SHORT_NAME, NC_SHORT, 3, short_out)) ERR;      
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_put_att_float(ncid, varid, ATT_FLOAT_NAME, NC_FLOAT, 3, float_out)) ERR;      
      if (nc_put_att_double(ncid, varid, ATT_DOUBLE_NAME, NC_DOUBLE, 3, double_out)) ERR;      
      if (nc_def_var(ncid, VAR2_NAME, NC_UINT, 2, dimids, &varid)) ERR;
      if (nc_put_att_text(ncid, varid, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, varid, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR; 
      if (nc_put_att_short(ncid, varid, ATT_SHORT_NAME, NC_SHORT, 3, short_out)) ERR;           
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_put_att_float(ncid, varid, ATT_FLOAT_NAME, NC_FLOAT, 3, float_out)) ERR;      
      if (nc_put_att_double(ncid, varid, ATT_DOUBLE_NAME, NC_DOUBLE, 3, double_out)) ERR;      
      if (nc_close(ncid)) ERR;

      /* Open the file and check attributes. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      for (v=0; v<2; v++)
      {
	 if (nc_inq_att(ncid, v, ATT_TEXT_NAME, &att_type, &att_len)) ERR;
	 if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
	 if (!(speech_in = malloc(att_len + 1))) ERR;
	 if (nc_get_att_text(ncid, v, ATT_TEXT_NAME, speech_in)) ERR;      
	 if (strcmp(speech, speech_in)) ERR;
	 free(speech_in);
	 if (nc_get_att_schar(ncid, v, ATT_SCHAR_NAME, schar_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (schar_in[i] != schar_out[i]) ERR;
	 if (nc_get_att_short(ncid, v, ATT_SHORT_NAME, short_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (short_in[i] != short_out[i]) ERR;
	 if (nc_get_att_int(ncid, v, ATT_INT_NAME, int_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (int_in[i] != int_out[i]) ERR;
	 if (nc_get_att_float(ncid, v, ATT_FLOAT_NAME, float_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (float_in[i] != float_out[i]) ERR;
	 if (nc_get_att_double(ncid, v, ATT_DOUBLE_NAME, double_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (double_in[i] != double_out[i]) ERR;
      }
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing zero-length attributes...");
   {
      int ncid;

      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/

      /* Create a file with a global attribute of each type of zero length. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR;
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR;
/*   if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UCHAR, ATT_LEN, uchar_out)) ERR;*/
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR;
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR;
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL)) ERR;
      if (nc_close(ncid)) ERR;
   }

   /* Make sure we can read all these zero-length atts. */
   {
      int ncid;
      signed char schar_in[ATT_LEN];
      short short_in[ATT_LEN];
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN];
      float float_in[ATT_LEN];
      double double_in[ATT_LEN];
      size_t len;
      nc_type xtype;

      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_CHAR) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_BYTE) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_SHORT) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_INT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_INT) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_FLOAT) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_DOUBLE) ERR;
      /* Conversions no longer result in range errors, since there's no data. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in)) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing zero-length attributes and redef...(this test skipped for HDF5-1.8.0 beta1");
   {
      int ncid;
      signed char schar_in[ATT_LEN];
      short short_in[ATT_LEN];
      int int_in[ATT_LEN];
      float float_in[ATT_LEN];
      double double_in[ATT_LEN];


      /* Create a file with a global attribute of each type of zero length. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_enddef(ncid)) ERR;
      if (nc_redef(ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR;
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR;
/*   if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UCHAR, ATT_LEN, uchar_out)) ERR;*/
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR;
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR;
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL)) ERR;
      if (nc_close(ncid)) ERR;

      /* Make sure we can read all these zero-length atts added during a
       * redef. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
      /* Conversions no longer result in range errors, since there's no data. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in)) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;

   printf("*** testing attribute deletes and renames...");
   {
      int ncid, varid, dimids[2];
      nc_type att_type;
      size_t att_len;
      char *speech_in;
      char name_in[NC_MAX_NAME + 1];
      int attid_in, natts_in;
      int int_out[ATT_LEN] = {-100000, 128, 100000};

      /* Create a file with a global attribute. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, 
			  speech)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Rename it. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_attid(ncid, NC_GLOBAL, ATT_TEXT_NAME, &attid_in)) ERR;
      if (attid_in != 0) ERR;
      if (nc_inq_attname(ncid, NC_GLOBAL, attid_in, name_in)) ERR;
      if (strcmp(name_in, ATT_TEXT_NAME)) ERR;
      if (nc_rename_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ATT_TEXT_NAME2)) ERR;      
      if (nc_inq_attname(ncid, NC_GLOBAL, attid_in, name_in)) ERR;
      if (strcmp(name_in, ATT_TEXT_NAME2)) ERR;
      if (nc_close(ncid)) ERR;

      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2, &att_type, &att_len)) ERR;
      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
      if (!(speech_in = malloc(att_len + 1))) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME2, speech_in)) ERR;      
      if (strcmp(speech, speech_in)) ERR;
      free(speech_in);
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in) != NC_ENOTATT) ERR;      
      if (nc_close(ncid)) ERR;

      /* Now delete the att. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_del_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2)) ERR;
      if (nc_close(ncid)) ERR;

      /* Now create a file with a variable, which has an att. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
      if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and delete it. Make sure it's gone. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_del_att(ncid, 0, ATT_INT_NAME)) ERR;
      if (nc_close(ncid)) ERR;

      /* Reopen the file and readd the attribute. Enddef and redef,
       * and delete it, then check to make sure it's gone. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_enddef(ncid)) ERR;
      if (nc_redef(ncid)) ERR;
      if (nc_del_att(ncid, 0, ATT_INT_NAME)) ERR;
      if (nc_inq_varnatts(ncid, 0, &natts_in)) ERR;
      if (natts_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing attribute create order...");

#define ATT0 "Maturin"
#define ATT1 "Aubery"
   {
      int ncid, varid, dimids[2];
      int attid_in;
      const int number = 42;

      /* Create a file with several global attributes. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT0, NC_INT, 1, &number)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT1, NC_INT, 1, &number)) ERR;
      if (nc_close(ncid)) ERR;
      
      /* Open it and check the order. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_attid(ncid, NC_GLOBAL, ATT0, &attid_in)) ERR;
      if (attid_in != 0) ERR;
      if (nc_inq_attid(ncid, NC_GLOBAL, ATT1, &attid_in)) ERR;
      if (attid_in != 1) ERR;
      if (nc_close(ncid)) ERR;

      /* Now create a file with a variable, which has two atts. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
      if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
      if (nc_put_att_int(ncid, varid, ATT0, NC_INT, 1, &number)) ERR;
      if (nc_put_att_int(ncid, varid, ATT1, NC_INT, 1, &number)) ERR;
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and check the order of the attributes on the var. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_attid(ncid, 0, ATT0, &attid_in)) ERR;
      if (attid_in != 0) ERR;
      if (nc_inq_attid(ncid, 0, ATT1, &attid_in)) ERR;
      if (attid_in != 1) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing attribute ordering some more...");

#define VAR_NAME "i"
#define A1_NAME "i"      
#define A2_NAME "f"      
#define A3_NAME "d"      
#define A1_LEN 3
#define A2_LEN 4
#define A3_LEN 5
   {
      int ncid;
      int varid, natts, nvars;
      double dvalue[] = {999.99, 999.99, 999.99, 999.99, 999.99};
      int varids[1];
      char name_in[NC_MAX_NAME + 1];

      /* Create a file with one var, and attach three atts to it. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_def_var(ncid, VAR_NAME, NC_INT, 0, NULL, &varid)) ERR;
      if (nc_put_att_double(ncid, varid, A1_NAME, NC_INT, A1_LEN, dvalue)) ERR;      
      if (nc_put_att_double(ncid, varid, A2_NAME, NC_INT, A2_LEN, dvalue)) ERR;      
      if (nc_put_att_double(ncid, varid, A3_NAME, NC_INT, A3_LEN, dvalue)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and check. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      if (nc_inq_varids(ncid, &nvars, varids)) ERR;
      if (nvars != 1 || varids[0] != 0) ERR;
      if (nc_inq_varnatts(ncid, 0, &natts)) ERR;
      if (natts != 3) ERR;
      if (nc_inq_attname(ncid, 0, 0, name_in)) ERR;
      if (strcmp(name_in, A1_NAME)) ERR;
      if (nc_inq_attname(ncid, 0, 1, name_in)) ERR;
      if (strcmp(name_in, A2_NAME)) ERR;
      if (nc_inq_attname(ncid, 0, 2, name_in)) ERR;
      if (strcmp(name_in, A3_NAME)) ERR;

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

   SUMMARIZE_ERR;
   printf("*** testing attribute ordering even more...");

   /* Test the ordering of atts for each cmode. */
   if (tst_att_ordering(NC_CLOBBER)) ERR;
   if (tst_att_ordering(NC_CLOBBER|NC_64BIT_OFFSET)) ERR;
   if (tst_att_ordering(NC_CLOBBER|NC_NETCDF4)) ERR;
   if (tst_att_ordering(NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL)) ERR;

   SUMMARIZE_ERR;
   printf("*** testing attributes and enddef/redef...");

#define ATT_1 "a"
#define ATT_2 "b"
#define ATT_3 "c"
   {
      int ncid, att = 1;

      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL|NC_CLOBBER, &ncid)) ERR;
      if (nc_enddef(ncid)) ERR;
      if (nc_redef(ncid)) ERR;
      if (nc_put_att(ncid, NC_GLOBAL, ATT_1, NC_INT, 1, &att)) ERR;
      if (nc_put_att(ncid, NC_GLOBAL, ATT_2, NC_INT, 1, &att)) ERR;
      if (nc_put_att(ncid, NC_GLOBAL, ATT_3, NC_INT, 1, &att)) ERR;

      if (nc_close(ncid)) ERR;

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

   SUMMARIZE_ERR;
   printf("*** testing copy of simple global atts...");
   {      
      int ncid, ncid2;
      nc_type att_type;
      size_t att_len;
      int i;

      char *speech_in;
      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      unsigned char uchar_in[ATT_LEN], uchar_out[ATT_LEN] = {0, 128, NC_MAX_CHAR};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
      unsigned short ushort_in[ATT_LEN], ushort_out[ATT_LEN] = {0, 128, NC_MAX_USHORT};
      unsigned int uint_in[ATT_LEN], uint_out[ATT_LEN] = {0, 128, NC_MAX_UINT};
      unsigned long long uint64_in[ATT_LEN], uint64_out[ATT_LEN] = {0, 128, 18446744073709551612ULL};
      long long int64_in[ATT_LEN], int64_out[ATT_LEN] = {NC_MIN_INT64, 128, NC_MAX_INT64};

      /* Create a file with a global attribute of each type. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;      
      if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UBYTE, ATT_LEN, uchar_out)) ERR;
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out)) ERR;      
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out)) ERR;      
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out)) ERR;      
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out)) ERR;      
      if (nc_put_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, NC_USHORT, ATT_LEN, ushort_out)) ERR;      
      if (nc_put_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, NC_UINT, ATT_LEN, uint_out)) ERR;      
      if (nc_put_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, NC_INT64, ATT_LEN, int64_out)) ERR;      
      if (nc_put_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, NC_UINT64, ATT_LEN, uint64_out)) ERR;      

      /* Create another file and copy all the attributes. */
      if (nc_create(FILE_NAME2, NC_NETCDF4, &ncid2)) ERR;      
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_UCHAR_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_INT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_USHORT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_UINT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_INT64_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_UINT64_NAME, ncid2, NC_GLOBAL)) ERR;

      /* Close both files. */
      if (nc_close(ncid)) ERR;
      if (nc_close(ncid2)) ERR;

      /* Open the file and check attributes. */
      if (nc_open(FILE_NAME2, 0, &ncid)) ERR;
      /* Check text. */
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len)) ERR;
      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
      if (!(speech_in = malloc(att_len + 1))) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in)) ERR;      
      if (strcmp(speech, speech_in)) ERR;
      free(speech_in);
      /* Check numeric values. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != schar_out[i]) ERR;
      if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, uchar_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (uchar_in[i] != uchar_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != short_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != int_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != float_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != double_out[i]) ERR;
      if (nc_get_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, ushort_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (ushort_in[i] != ushort_out[i]) ERR;
      if (nc_get_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, uint_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (uint_in[i] != uint_out[i]) ERR;
      if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, int64_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (int64_in[i] != int64_out[i]) ERR;
      if (nc_get_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, uint64_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (uint64_in[i] != uint64_out[i]) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   FINAL_RESULTS;
}
Exemple #14
0
str
NCDFattach(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	mvc *m = NULL;
	sql_schema *sch = NULL;
	sql_table *tfiles = NULL, *tdims = NULL, *tvars = NULL, *tvardim = NULL, *tattrs = NULL;
	sql_column *col;
	str msg = MAL_SUCCEED;
	str fname = *(str*)getArgReference(stk, pci, 1);
	char buf[BUFSIZ], *s= buf;
	oid fid, rid = oid_nil;
	sql_trans *tr;

	int ncid;   /* dataset id */
	int ndims, nvars, ngatts, unlimdim;
	int didx, vidx, vndims, vnatts, i, aidx, coord_dim_id = -1;
	int vdims[NC_MAX_VAR_DIMS];

	size_t dlen, alen;
	char dname[NC_MAX_NAME+1], vname[NC_MAX_NAME+1], aname[NC_MAX_NAME +1], 
	  abuf[80], *aval;
	char **dims = NULL;
	nc_type vtype, atype; /* == int */

	int retval, avalint;
	float avalfl;
	double avaldbl;

	msg = getSQLContext(cntxt, mb, &m, NULL);
	if (msg)
        return msg;

	tr = m->session->tr;
	sch = mvc_bind_schema(m, "sys");
	if ( !sch )
        return createException(MAL, "netcdf.attach", "Cannot get schema sys\n");

	tfiles = mvc_bind_table(m, sch, "netcdf_files");
	tdims = mvc_bind_table(m, sch, "netcdf_dims");
	tvars = mvc_bind_table(m, sch, "netcdf_vars");
	tvardim = mvc_bind_table(m, sch, "netcdf_vardim");
	tattrs = mvc_bind_table(m, sch, "netcdf_attrs");

	if (tfiles == NULL || tdims == NULL || tvars == NULL || 
	    tvardim == NULL || tattrs == NULL)
        return createException(MAL, "netcdf.attach", "Catalog table missing\n");

	/* check if the file is already attached */
	col = mvc_bind_column(m, tfiles, "location");
	rid = table_funcs.column_find_row(m->session->tr, col, fname, NULL);
	if (rid != oid_nil) 
	    return createException(SQL, "netcdf.attach", "File %s is already attached\n", fname);

	/* Open NetCDF file  */
	if ((retval = nc_open(fname, NC_NOWRITE, &ncid)))
        return createException(MAL, "netcdf.test", "Cannot open NetCDF \
file %s: %s", fname, nc_strerror(retval));

	if ((retval = nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdim)))
        return createException(MAL, "netcdf.test", "Cannot read NetCDF \
header: %s", nc_strerror(retval));

	/* Insert row into netcdf_files table */
	col = mvc_bind_column(m, tfiles, "file_id");
	fid = store_funcs.count_col(tr, col, 1) + 1;

	snprintf(buf, BUFSIZ, INSFILE, (int)fid, fname);
	if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE, FALSE, NULL))
	        != MAL_SUCCEED )
	    goto finish;

	/* Read dimensions from NetCDF header and insert a row for each one into netcdf_dims table */

	dims = (char **)GDKzalloc(sizeof(char *) * ndims);
	for (didx = 0; didx < ndims; didx++){
	    if ((retval = nc_inq_dim(ncid, didx, dname, &dlen)))
	        return createException(MAL, "netcdf.attach", "Cannot read dimension %d : %s", didx, nc_strerror(retval));

	    snprintf(buf, BUFSIZ, INSDIM, didx, (int)fid, dname, (int)dlen);
	    if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE, FALSE, NULL))
    	 != MAL_SUCCEED )
	        goto finish;

	    dims[didx] = GDKstrdup(dname);
	}

	/* Read variables and attributes from the header and insert rows in netcdf_vars, netcdf_vardims, and netcdf_attrs tables */
	for (vidx = 0; vidx < nvars; vidx++){
	    if ( (retval = nc_inq_var(ncid, vidx, vname, &vtype, &vndims, vdims, &vnatts)))
	        return createException(MAL, "netcdf.attach", 
			     "Cannot read variable %d : %s", 
			     vidx, nc_strerror(retval));

    	/* Check if this is coordinate variable */
        if ( (vndims == 1) && ( strcmp(vname, dims[vdims[0]]) == 0 ))
	        coord_dim_id = vdims[0];
        else coord_dim_id = -1;

	    snprintf(buf, BUFSIZ, INSVAR, vidx, (int)fid, vname, prim_type_name(vtype), vndims, coord_dim_id);
	    if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE, FALSE, NULL))
	        != MAL_SUCCEED )
            goto finish;

	    if ( coord_dim_id < 0 ){
	        for (i = 0; i < vndims; i++){
                snprintf(buf, BUFSIZ, INSVARDIM, vidx, vdims[i], (int)fid, i);
                if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE, FALSE, NULL))
            	   != MAL_SUCCEED )
                	goto finish;
	        }
	    }

    	if ( vnatts > 0 ) { /* fill in netcdf_attrs table */

            for (aidx = 0; aidx < vnatts; aidx++){
                if ((retval = nc_inq_attname(ncid,vidx,aidx,aname)))
                    return createException(MAL, "netcdf.attach",
                        "Cannot read attribute %d of variable %d: %s",
                        aidx, vidx, nc_strerror(retval));

	            if ((retval = nc_inq_att(ncid,vidx,aname,&atype,&alen)))
                    return createException(MAL, "netcdf.attach",
	                    "Cannot read attribute %s type and length: %s",
	                    aname, nc_strerror(retval));


        	switch ( atype ) {
        	case NC_CHAR:
                aval = (char *) GDKzalloc(alen + 1);
                if ((retval = nc_get_att_text(ncid,vidx,aname,aval)))
                    return createException(MAL, "netcdf.attach",
	                    "Cannot read attribute %s value: %s",
	                    aname, nc_strerror(retval));
		fix_quote(aval, alen);
                aval[alen] = '\0';
                snprintf(buf, BUFSIZ, INSATTR, vname, aname, "string", aval, (int)fid, "root");
                GDKfree(aval);
            break;

        	case NC_INT:
	            if ((retval = nc_get_att_int(ncid,vidx,aname,&avalint)))
	                return createException(MAL, "netcdf.attach",
	                    "Cannot read attribute %s value: %s",
	                    aname, nc_strerror(retval));
                snprintf(abuf,80,"%d",avalint);
                snprintf(buf, BUFSIZ, INSATTR, vname, aname, prim_type_name(atype), abuf, (int)fid, "root");
	        break;
	
        	case NC_FLOAT:
	            if ((retval = nc_get_att_float(ncid,vidx,aname,&avalfl)))
	                return createException(MAL, "netcdf.attach",
	                    "Cannot read attribute %s value: %s",
	                    aname, nc_strerror(retval));
	            snprintf(abuf,80,"%7.2f",avalfl);
	            snprintf(buf, BUFSIZ, INSATTR, vname, aname, prim_type_name(atype), abuf, (int)fid, "root");
	        break;

	        case NC_DOUBLE:
	            if ((retval = nc_get_att_double(ncid,vidx,aname,&avaldbl)))
        	        return createException(MAL, "netcdf.attach",
	                    "Cannot read attribute %s value: %s",
	                    aname, nc_strerror(retval));
    	        snprintf(abuf,80,"%7.2e",avaldbl);
	            snprintf(buf, BUFSIZ, INSATTR, vname, aname, prim_type_name(atype), abuf, (int)fid, "root");
	        break;

        	default: continue; /* next attribute */
	        }

		printf("statement: '%s'\n", s);
        	if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE, FALSE, NULL))
	            != MAL_SUCCEED )
                goto finish;

	        } /* attr loop */

	    }
	} /* var loop */

	/* Extract global attributes */

	for (aidx = 0; aidx < ngatts; aidx++){
	    if ((retval = nc_inq_attname(ncid,NC_GLOBAL,aidx,aname)))
	        return createException(MAL, "netcdf.attach",
                "Cannot read global attribute %d: %s",
                aidx, nc_strerror(retval));

	    if ((retval = nc_inq_att(ncid,NC_GLOBAL,aname,&atype,&alen)))
	        return createException(MAL, "netcdf.attach",
                "Cannot read global attribute %s type and length: %s",
                aname, nc_strerror(retval));
    	switch ( atype ) {
	        case NC_CHAR:
	            aval = (char *) GDKzalloc(alen + 1);
	            if ((retval = nc_get_att_text(ncid,NC_GLOBAL,aname,aval)))
	                return createException(MAL, "netcdf.attach",
	                    "Cannot read global attribute %s value: %s",
    	                aname, nc_strerror(retval));
		    fix_quote(aval, alen);
	            aval[alen] = '\0';
	            snprintf(buf, BUFSIZ, INSATTR, "GLOBAL", aname, "string", aval, (int)fid, "root");
	            GDKfree(aval);
	            break;

            case NC_INT:
	            if ((retval = nc_get_att_int(ncid,NC_GLOBAL,aname,&avalint)))
	                return createException(MAL, "netcdf.attach",
			    	    "Cannot read global attribute %s of type %s : %s",
	                    aname, prim_type_name(atype), nc_strerror(retval));
    	        snprintf(abuf,80,"%d",avalint);
	            snprintf(buf, BUFSIZ, INSATTR, "GLOBAL", aname, prim_type_name(atype), abuf, (int)fid, "root");
	            break;

    	    case NC_FLOAT:
	            if ((retval = nc_get_att_float(ncid,NC_GLOBAL,aname,&avalfl)))
	                return createException(MAL, "netcdf.attach",
	                    "Cannot read global attribute %s of type %s: %s",
	                    aname, prim_type_name(atype), nc_strerror(retval));
    	        snprintf(abuf,80,"%7.2f",avalfl);
	            snprintf(buf, BUFSIZ, INSATTR, "GLOBAL", aname, prim_type_name(atype), abuf, (int)fid, "root");
	            break;

            case NC_DOUBLE:
    	        if ((retval = nc_get_att_double(ncid,NC_GLOBAL,aname,&avaldbl)))
	                return createException(MAL, "netcdf.attach",
	                    "Cannot read global attribute %s value: %s",
	                    aname, nc_strerror(retval));
	            snprintf(abuf,80,"%7.2e",avaldbl);
    	        snprintf(buf, BUFSIZ, INSATTR, "GLOBAL", aname, prim_type_name(atype), abuf, (int)fid, "root");
	            break;

            default: continue; /* next attribute */
        }

	printf("global: '%s'\n", s);
        if ( ( msg = SQLstatementIntern(cntxt, &s, "netcdf.attach", TRUE, FALSE, NULL))
	          != MAL_SUCCEED )
	        goto finish;

    } /* global attr loop */


 finish:
    nc_close(ncid);

    if (dims != NULL ){
        for (didx = 0; didx < ndims; didx++)
            GDKfree(dims[didx]);
        GDKfree(dims);
    }

	return msg;
}
Exemple #15
0
/* Copy a netCDF file, changing cmode if desired. */
static
int copy_file(char *file_name_in, char *file_name_out, int cmode_out,
	      int *chunking, int *deflate)
{
   int ncid_in, ncid_out;
   int natts, nvars, ndims, unlimdimid;
   char name[NC_MAX_NAME + 1];
   size_t len;
   int a, v, d;

   if (nc_open(file_name_in, NC_NOWRITE, &ncid_in)) ERR;
   if (nc_create(file_name_out, cmode_out, &ncid_out)) ERR;
      
   if (nc_inq(ncid_in, &ndims, &nvars, &natts, &unlimdimid)) ERR;

   /* Copy dims. */
   for (d = 0; d < ndims; d++)
   {
      if (nc_inq_dim(ncid_in, d, name, &len)) ERR;
      if (nc_def_dim(ncid_out, name, len, NULL)) ERR;
   }

   /* Copy global atts. */
   for (a = 0; a < natts; a++)
   {
      if (nc_inq_attname(ncid_in, NC_GLOBAL, a, name)) ERR;
      if (nc_copy_att(ncid_in, NC_GLOBAL, name, ncid_out, NC_GLOBAL)) ERR;
   }

   /* Copy the variable metadata. */
   for (v = 0; v < nvars; v++)
   {
      char name[NC_MAX_NAME + 1];
      char att_name[NC_MAX_NAME + 1];
      nc_type xtype;
      int ndims, dimids[NC_MAX_VAR_DIMS], natts;
      int varid_out;
      int a;
      int retval = NC_NOERR;

      /* Learn about this var. */
      if ((retval = nc_inq_var(ncid_in, v, name, &xtype, &ndims, dimids, &natts)))
	 return retval;

      /* Create the output var. */
      if (nc_def_var(ncid_out, name, xtype, ndims, dimids, &varid_out)) ERR;

      /* Except for 1D vars, sent chunking and compression. */
      if (ndims != 1)
      {
	 if (chunking)
	    if (nc_def_var_chunking(ncid_out, v, NC_CHUNKED, chunking)) ERR;
	 if (deflate)
	    if (nc_def_var_deflate(ncid_out, v, NC_NOSHUFFLE, *deflate, *deflate)) ERR;
      }

      /* Copy the attributes. */
      for (a=0; a<natts; a++)
      {
	 if (nc_inq_attname(ncid_in, v, a, att_name)) ERR;
	 if (nc_copy_att(ncid_in, v, att_name, ncid_out, varid_out)) ERR;
      }
   }

   /* Copy the variable data. */
   for (v = 0; v < nvars; v++)
   {
      char name[NC_MAX_NAME + 1];
      nc_type xtype;
      int ndims, dimids[NC_MAX_VAR_DIMS], natts, real_ndims;
      int d;
      void *data = NULL;
      size_t *count = NULL, *start = NULL;
      size_t reclen = 1;
      size_t *dimlen = NULL;
      int retval = NC_NOERR;
      size_t type_size;
      char type_name[NC_MAX_NAME+1];

      /* Learn about this var. */
      if ((retval = nc_inq_var(ncid_in, v, name, &xtype, &ndims, dimids, &natts)))
	 return retval;

      /* Later on, we will need to know the size of this type. */
      if ((retval = nc_inq_type(ncid_in, xtype, type_name, &type_size)))
	 return retval;
      LOG((3, "type %s has size %d", type_name, type_size));

      /* Allocate memory for our start and count arrays. If ndims = 0
	 this is a scalar, which I will treat as a 1-D array with one
	 element. */
      real_ndims = ndims ? ndims : 1;
      if (!(start = nc_malloc(real_ndims * sizeof(size_t))))
	 BAIL(NC_ENOMEM);
      if (!(count = nc_malloc(real_ndims * sizeof(size_t))))
	 BAIL(NC_ENOMEM);

      /* The start array will be all zeros, except the first element,
	 which will be the record number. Count will be the dimension
	 size, except for the first element, which will be one, because
	 we will copy one record at a time. For this we need the var
	 shape. */
      if (!(dimlen = nc_malloc(real_ndims * sizeof(size_t))))
	 BAIL(NC_ENOMEM);

      /* Find out how much data. */
      for (d=0; d<ndims; d++)
      {
	 if ((retval = nc_inq_dimlen(ncid_in, dimids[d], &dimlen[d])))
	    BAIL(retval);
	 LOG((4, "nc_copy_var: there are %d data", dimlen[d]));
      }

      /* If this is really a scalar, then set the dimlen to 1. */
      if (ndims == 0)
	 dimlen[0] = 1;

      for (d=0; d<real_ndims; d++)
      {
	 start[d] = 0;
	 count[d] = d ? dimlen[d] : 1;
	 if (d) reclen *= dimlen[d];
      }

      /* If there are no records, we're done. */
      if (!dimlen[0])
	 goto exit;

      /* Allocate memory for one record. */
      if (!(data = nc_malloc(reclen * type_size)))
	 return NC_ENOMEM;
   
      /* Copy the var data one record at a time. */
      for (start[0]=0; !retval && start[0]<(size_t)dimlen[0]; start[0]++)
      {
	 if (nc_get_vara(ncid_in, v, start, count, data)) ERR;
	 if (nc_put_vara(ncid_out, v, start, count, data)) ERR;
      }
    
     exit:
      if (data) nc_free(data);
      if (dimlen) nc_free(dimlen);
      if (start) nc_free(start);
      if (count) nc_free(count);

   }

   if (nc_close(ncid_in)) ERR;
   if (nc_close(ncid_out)) ERR;

   return NC_NOERR;
}
Exemple #16
0
int
dumpmetadata(int ncid, NChdr** hdrp)
{
    int stat,i,j,k;
    NChdr* hdr = (NChdr*)calloc(1,sizeof(NChdr));
    MEMCHECK(hdr,NC_ENOMEM);
    hdr->ncid = ncid;
    hdr->content = ncbytesnew();
    if(hdrp) *hdrp = hdr;

    stat = nc_inq(hdr->ncid,
		  &hdr->ndims,
		  &hdr->nvars,
		  &hdr->ngatts,
		  &hdr->unlimid);
    CHECK(stat);
    if(ncdap3debug > 0) {
        fprintf(stdout,"ncid=%d ngatts=%d ndims=%d nvars=%d unlimid=%d\n",
		hdr->ncid,hdr->ngatts,hdr->ndims,hdr->nvars,hdr->unlimid);
    }
    hdr->gatts = (NCattribute*)calloc(1,hdr->ngatts*sizeof(NCattribute));
    MEMCHECK(hdr->gatts,NC_ENOMEM);
    if(hdr->ngatts > 0)
	fprintf(stdout,"global attributes:\n");
    for(i=0;i<hdr->ngatts;i++) {
	NCattribute* att = &hdr->gatts[i];
        char attname[NC_MAX_NAME];
	nc_type nctype;
	size_t typesize;
        size_t nvalues;

        stat = nc_inq_attname(hdr->ncid,NC_GLOBAL,i,attname);
        CHECK(stat);
	att->name = nulldup(attname);
	stat = nc_inq_att(hdr->ncid,NC_GLOBAL,att->name,&nctype,&nvalues);
        CHECK(stat);
	att->etype = nctypetodap(nctype);
 	typesize = nctypesizeof(att->etype);
	fprintf(stdout,"\t[%d]: name=%s type=%s values(%lu)=",
			i,att->name,nctypetostring(octypetonc(att->etype)),
                        (unsigned long)nvalues);
	if(nctype == NC_CHAR) {
	    size_t len = typesize*nvalues;
	    char* values = (char*)malloc(len+1);/* for null terminate*/
	    MEMCHECK(values,NC_ENOMEM);
	    stat = nc_get_att(hdr->ncid,NC_GLOBAL,att->name,values);
            CHECK(stat);
	    values[len] = '\0';
	    fprintf(stdout," '%s'",values);
	} else {
	    size_t len = typesize*nvalues;
	    char* values = (char*)malloc(len);
	    MEMCHECK(values,NC_ENOMEM);
	    stat = nc_get_att(hdr->ncid,NC_GLOBAL,att->name,values);
            CHECK(stat);
	    for(k=0;k<nvalues;k++) {
		fprintf(stdout," ");
		dumpdata1(octypetonc(att->etype),k,values);
	    }
	}
	fprintf(stdout,"\n");
    }

    hdr->dims = (Dim*)malloc(hdr->ndims*sizeof(Dim));
    MEMCHECK(hdr->dims,NC_ENOMEM);
    for(i=0;i<hdr->ndims;i++) {
	hdr->dims[i].dimid = i;
        stat = nc_inq_dim(hdr->ncid,
	                  hdr->dims[i].dimid,
	                  hdr->dims[i].name,
	                  &hdr->dims[i].size);
        CHECK(stat);
	fprintf(stdout,"dim[%d]: name=%s size=%lu\n",
		i,hdr->dims[i].name,(unsigned long)hdr->dims[i].size);
    }    
    hdr->vars = (Var*)malloc(hdr->nvars*sizeof(Var));
    MEMCHECK(hdr->vars,NC_ENOMEM);
    for(i=0;i<hdr->nvars;i++) {
	Var* var = &hdr->vars[i];
	nc_type nctype;
	var->varid = i;
        stat = nc_inq_var(hdr->ncid,
	                  var->varid,
	                  var->name,
			  &nctype,
			  &var->ndims,
			  var->dimids,
	                  &var->natts);
        CHECK(stat);
	var->nctype = (nctype);
	fprintf(stdout,"var[%d]: name=%s type=%s |dims|=%d",
		i,
		var->name,
		nctypetostring(var->nctype),
		var->ndims);
	fprintf(stdout," dims={");
	for(j=0;j<var->ndims;j++) {
	    fprintf(stdout," %d",var->dimids[j]);
	}
	fprintf(stdout,"}\n");
	var->atts = (NCattribute*)malloc(var->natts*sizeof(NCattribute));
        MEMCHECK(var->atts,NC_ENOMEM);
        for(j=0;j<var->natts;j++) {
	    NCattribute* att = &var->atts[j];
	    char attname[NC_MAX_NAME];
	    size_t typesize;
	    char* values;
	    nc_type nctype;
	    size_t nvalues;
            stat = nc_inq_attname(hdr->ncid,var->varid,j,attname);
	    CHECK(stat);
	    att->name = nulldup(attname);
	    stat = nc_inq_att(hdr->ncid,var->varid,att->name,&nctype,&nvalues);
	    CHECK(stat);
	    att->etype = nctypetodap(nctype);
	    typesize = nctypesizeof(att->etype);
	    values = (char*)malloc(typesize*nvalues);
	    MEMCHECK(values,NC_ENOMEM);
	    stat = nc_get_att(hdr->ncid,var->varid,att->name,values);
            CHECK(stat);
	    fprintf(stdout,"\tattr[%d]: name=%s type=%s values(%lu)=",
			j,att->name,nctypetostring(octypetonc(att->etype)),(unsigned long)nvalues);
	    for(k=0;k<nvalues;k++) {
		fprintf(stdout," ");
		dumpdata1(octypetonc(att->etype),k,values);
	    }
	    fprintf(stdout,"\n");
	}
    }    
    fflush(stdout);
    return NC_NOERR;
}
Exemple #17
0
/*ARGSUSED*/
int
main(int argc, char *argv[])
{
	int cmode=NC_CLOBBER, omode, ret;
	int	 id;
	char buf[256];
#ifdef SYNCDEBUG
	char *str = "one";
#endif
	int ii;
	size_t ui;
	const struct tcdfvar *tvp = testvars;
	union getret got;
	const size_t initialsz = 8192;
	size_t chunksz = 8192;
	size_t align = 8192/32;

	MPI_Init(&argc, &argv);

        /* cmode |= NC_PNETCDF |NC_64BIT_OFFSET; */
        cmode != NC_PNETCDF |NC_64BIT_DATA;
	ret = nc_create_par(fname,cmode, MPI_COMM_WORLD, MPI_INFO_NULL, &id);
	if(ret != NC_NOERR)  {
		fprintf(stderr,"Error %s in file %s at line %d\n",nc_strerror(ret),__FILE__,__LINE__);
		exit(ret);
        }
	
	assert( nc_put_att_text(id, NC_GLOBAL,
		"TITLE", 12, "another name") == NC_NOERR);
	assert( nc_get_att_text(id, NC_GLOBAL,
		"TITLE", buf) == NC_NOERR);
/*	(void) printf("title 1 \"%s\"\n", buf); */
	assert( nc_put_att_text(id, NC_GLOBAL,
		"TITLE", strlen(fname), fname) == NC_NOERR);
	assert( nc_get_att_text(id, NC_GLOBAL,
		"TITLE", buf) == NC_NOERR);
	buf[strlen(fname)] = 0;
/*	(void) printf("title 2 \"%s\"\n", buf); */
	assert( strcmp(fname, buf) == 0);

	createtestdims(id, NUM_DIMS, sizes, dim_names);
	testdims(id, NUM_DIMS, sizes, dim_names);

	createtestvars(id, testvars, NUM_TESTVARS); 

 	{
 	int ifill = -1; double dfill = -9999;
 	assert( nc_put_att_int(id, Long_id,
 		_FillValue, NC_INT, 1, &ifill) == NC_NOERR);
 	assert( nc_put_att_double(id, Double_id,
 		_FillValue, NC_DOUBLE, 1, &dfill) == NC_NOERR);
 	}

#ifdef REDEF
	assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR );
	assert( nc_put_var1_int(id, Long_id, indices[3], &birthday) 
		== NC_NOERR );
	fill_seq(id);
	assert( nc_redef(id) == NC_NOERR );
/*	assert( nc_rename_dim(id,2, "a long dim name") == NC_NOERR); */
#endif

	assert( nc_rename_dim(id,1, "IXX") == NC_NOERR);
	assert( nc_inq_dim(id, 1, buf, &ui) == NC_NOERR);
	/* (void) printf("dimrename: %s\n", buf); */
	assert( nc_rename_dim(id,1, dim_names[1]) == NC_NOERR);

#ifdef ATTRX
	assert( nc_rename_att(id, 1, "UNITS", "units") == NC_NOERR);
	assert( nc_del_att(id, 4, "FIELDNAM")== NC_NOERR);
	assert( nc_del_att(id, 2, "SCALEMIN")== NC_NOERR);
	assert( nc_del_att(id, 2, "SCALEMAX")== NC_NOERR);
#endif /* ATTRX */

	assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR );

#ifndef REDEF
	fill_seq(id);
	assert( nc_put_var1_int(id, Long_id, indices[3], &birthday)== NC_NOERR );
#endif

	assert( nc_put_vara_schar(id, Byte_id, s_start, s_edges,
		(signed char *)sentence)
		== NC_NOERR);
	assert( nc_put_var1_schar(id, Byte_id, indices[6], (signed char *)(chs+1))
		== NC_NOERR);
	assert( nc_put_var1_schar(id, Byte_id, indices[5], (signed char *)chs)
		== NC_NOERR);

	assert( nc_put_vara_text(id, Char_id, s_start, s_edges, sentence)
		== NC_NOERR);
	assert( nc_put_var1_text(id, Char_id, indices[6], (chs+1))
		== NC_NOERR) ;
	assert( nc_put_var1_text(id, Char_id, indices[5], chs)
		== NC_NOERR);

	assert( nc_put_var1_short(id, Short_id, indices[4], shs)
		== NC_NOERR);

	assert( nc_put_var1_float(id, Float_id, indices[2], &e)
		== NC_NOERR);

	assert( nc_put_var1_double(id, Double_id, indices[1], &zed)
		== NC_NOERR);
	assert( nc_put_var1_double(id, Double_id, indices[0], &pinot)
		== NC_NOERR);


#ifdef SYNCDEBUG
	(void) printf("Hit Return to sync\n");
	gets(str);
	nc_sync(id,0);
	(void) printf("Sync done. Hit Return to continue\n");
	gets(str);
#endif /* SYNCDEBUG */

	ret = nc_close(id);
	/* (void) printf("nc_close ret = %d\n\n", ret); */


/*
 *	read it
 */
        omode = NC_NOWRITE;
        omode = NC_NOWRITE | NC_PNETCDF;
	if(ret != NC_NOERR)
	{
   	    (void) printf("Could not open %s: %s\n", fname,
			nc_strerror(ret));
   	    exit(1);
	}
	/* (void) printf("reopen id = %d for filename %s\n", */
	/* 	id, fname); */

	/*	NC	*/ 
	/* (void) printf("NC "); */
	assert( nc_inq(id, &(cdesc->num_dims), &(cdesc->num_vars),
		&(cdesc->num_attrs), &(cdesc->xtendim) ) == NC_NOERR);
	assert((size_t) cdesc->num_dims == num_dims);
	assert(cdesc->num_attrs == 1);
	assert(cdesc->num_vars == NUM_TESTVARS);
	/* (void) printf("done\n"); */
	
	/*	GATTR	*/
	/* (void) printf("GATTR "); */

	assert( nc_inq_attname(id, NC_GLOBAL, 0, adesc->mnem) == 0);
	assert(strcmp("TITLE",adesc->mnem) == 0);
	assert( nc_inq_att(id, NC_GLOBAL, adesc->mnem, &(adesc->type), &(adesc->len))== NC_NOERR);
	assert( adesc->type == NC_CHAR );
	assert( adesc->len == strlen(fname) );
	assert( nc_get_att_text(id, NC_GLOBAL, "TITLE", buf)== NC_NOERR);
	buf[adesc->len] = 0;
	assert( strcmp(fname, buf) == 0);

	/*	VAR	*/
	/* (void) printf("VAR "); */
	assert( cdesc->num_vars == NUM_TESTVARS );

	for(ii = 0; ii < cdesc->num_vars; ii++, tvp++ ) 
	{
		int jj;
		assert( nc_inq_var(id, ii,
			vdesc->mnem,
			&(vdesc->type),
			&(vdesc->ndims),
			vdesc->dims,
			&(vdesc->num_attrs)) == NC_NOERR);
		if(strcmp(tvp->mnem , vdesc->mnem) != 0)
		{
			(void) printf("attr %d mnem mismatch %s, %s\n",
				ii, tvp->mnem, vdesc->mnem);
			continue;
		}
		if(tvp->type != vdesc->type)
		{
			(void) printf("attr %d type mismatch %d, %d\n",
				ii, (int)tvp->type, (int)vdesc->type);
			continue;
		}
		for(jj = 0; jj < vdesc->ndims; jj++ )
		{
			if(tvp->dims[jj] != vdesc->dims[jj] )
			{
		(void) printf(
		"inconsistent dim[%d] for variable %d: %d != %d\n",
		jj, ii, tvp->dims[jj], vdesc->dims[jj] );
			continue;
			}
		}

		/* VATTR */
		/* (void) printf("VATTR\n"); */
		for(jj=0; jj<vdesc->num_attrs; jj++ ) 
		{
			assert( nc_inq_attname(id, ii, jj, adesc->mnem) == NC_NOERR);
			if( strcmp(adesc->mnem, reqattr[jj]) != 0 )
			{
				(void) printf("var %d attr %d mismatch %s != %s\n",
					ii, jj, adesc->mnem, reqattr[jj] );
				break;
			}
		}

		if( nc_inq_att(id, ii, reqattr[0], &(adesc->type), &(adesc->len))
			!= -1) {
		assert( adesc->type == NC_CHAR );
		assert( adesc->len == strlen(tvp->units) );
	 	assert( nc_get_att_text(id,ii,reqattr[0],buf)== NC_NOERR); 
		buf[adesc->len] = 0;
		assert( strcmp(tvp->units, buf) == 0);
		}

		if(
			nc_inq_att(id, ii, reqattr[1], &(adesc->type), &(adesc->len))
			!= -1)
		{
		assert( adesc->type == NC_DOUBLE );
		assert( adesc->len == 1 );
	 	assert( nc_get_att_double(id, ii, reqattr[1], &got.dbl)== NC_NOERR);
		chkgot(adesc->type, got, tvp->validmin);
		}

		if(
			nc_inq_att(id, ii, reqattr[2], &(adesc->type), &(adesc->len))
			!= -1)
		{
		assert( adesc->type == NC_DOUBLE );
		assert( adesc->len == 1 );
	 	assert( nc_get_att_double(id, ii, reqattr[2], &got.dbl)== NC_NOERR);
		chkgot(adesc->type, got, tvp->validmax);
		}

		if(
			nc_inq_att(id, ii, reqattr[3], &(adesc->type), &(adesc->len))
			!= -1)
		{
		assert( adesc->type == NC_DOUBLE );
		assert( adesc->len ==1 );
	 	assert( nc_get_att_double(id, ii, reqattr[3], &got.dbl)== NC_NOERR);
		chkgot(adesc->type, got, tvp->scalemin);
		}

		if(
			nc_inq_att(id, ii, reqattr[4], &(adesc->type), &(adesc->len))
			!= -1)
		{
		assert( adesc->type == NC_DOUBLE );
		assert( adesc->len == 1 );
	 	assert( nc_get_att_double(id, ii, reqattr[4], &got.dbl)== NC_NOERR);
		chkgot(adesc->type, got, tvp->scalemax);
		}

		if( nc_inq_att(id, ii, reqattr[5], &(adesc->type), &(adesc->len))== NC_NOERR)
		{
		assert( adesc->type == NC_CHAR );
		assert( adesc->len == strlen(tvp->fieldnam) );
	 	assert( nc_get_att_text(id,ii,reqattr[5],buf)== NC_NOERR); 
		buf[adesc->len] = 0;
		assert( strcmp(tvp->fieldnam, buf) == 0);
		}
	}

	/* (void) printf("fill_seq "); */
	check_fill_seq(id);
	/* (void) printf("Done\n"); */

	assert( nc_get_var1_double(id, Double_id, indices[0], &got.dbl)== NC_NOERR);
	/* (void) printf("got val = %f\n", got.dbl ); */

	assert( nc_get_var1_double(id, Double_id, indices[1], &got.dbl)== NC_NOERR);
	/* (void) printf("got val = %f\n", got.dbl ); */

	assert( nc_get_var1_float(id, Float_id, indices[2], &got.fl[0])== NC_NOERR);
	/* (void) printf("got val = %f\n", got.fl[0] ); */

	assert( nc_get_var1_int(id, Long_id, indices[3], &got.in[0])== NC_NOERR);
	/* (void) printf("got val = %d\n", got.in[0] ); */

	assert( nc_get_var1_short(id, Short_id, indices[4], &got.sh[0])== NC_NOERR);
	/* (void) printf("got val = %d\n", got.sh[0] ); */

	assert( nc_get_var1_text(id, Char_id, indices[5], &got.by[0]) == NC_NOERR);
	/* (void) printf("got NC_CHAR val = %c (0x%02x) \n", */
		 /* got.by[0] , got.by[0]); */

	assert( nc_get_var1_text(id, Char_id, indices[6], &got.by[0]) == NC_NOERR);
	/* (void) printf("got NC_CHAR val = %c (0x%02x) \n", */
	/* 	 got.by[0], got.by[0] ); */

	(void) memset(buf,0,sizeof(buf));
	assert( nc_get_vara_text(id, Char_id, s_start, s_edges, buf) == NC_NOERR);
	/* (void) printf("got NC_CHAR val = \"%s\"\n", buf); */

	assert( nc_get_var1_schar(id, Byte_id, indices[5],
			(signed char *)&got.by[0])== NC_NOERR);
	/* (void) printf("got val = %c (0x%02x) \n", got.by[0] , got.by[0]); */

	assert( nc_get_var1_schar(id, Byte_id, indices[6],
			(signed char *)&got.by[0])== NC_NOERR);
	/* (void) printf("got val = %c (0x%02x) \n", got.by[0], got.by[0] ); */

	(void) memset(buf,0,sizeof(buf));
	assert( nc_get_vara_schar(id, Byte_id, s_start, s_edges,
			(signed char *)buf)== NC_NOERR );
	/* (void) printf("got val = \"%s\"\n", buf); */

	{
		double dbuf[NUM_RECS * SIZE_1 * SIZE_2];
		assert(nc_get_var_double(id, Float_id, dbuf) == NC_NOERR);
		/* (void) printf("got vals = %f ... %f\n", dbuf[0], */
		/* 	 dbuf[NUM_RECS * SIZE_1 * SIZE_2 -1] ); */
	}

	ret = nc_close(id);
	/* (void) printf("re nc_close ret = %d\n", ret); */

	MPI_Finalize();
	return 0;
}