/*! \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); }
/* Open/close the file with netCDF. */ int readfile(char *file_name, long long *delta, int do_inq, int num_vars) { int ncid; struct timeval starttime, endtime; long long startt, endt; int natts; int v; /* Start the clock. */ gettimeofday(&starttime, NULL); /* Open the file. */ if (nc_open(file_name, NC_NETCDF4, &ncid)) ERR; /* Do an inq if desired, triggering read of atts. */ for (v = 0; v < num_vars; v++) if (nc_inq_varnatts(ncid, v, &natts)) ERR; if (nc_inq_natts(ncid, &natts)) ERR; /* Close the file. */ if (nc_close(ncid)) ERR; gettimeofday(&endtime, NULL); /* Compute the time delta */ startt = (1000000 * starttime.tv_sec) + starttime.tv_usec; endt = (1000000 * endtime.tv_sec) + endtime.tv_usec; *delta = endt - startt; return 0; }
int NcVar::num_atts( void ) const // handles variable and global atts { int natt = 0; if (the_file->is_valid()) if (the_id == ncGlobal) natt = the_file->num_atts(); else NcError::set_err( nc_inq_varnatts(the_file->id(), the_id, &natt) ); return natt; }
/*! This function queries the number of global attributes given a location id and a variable id. \param [in] ncid Groupd id (or File Id) \param [in] varid the id of the variable \param [out] natts the number of global attributes \return Status code */ int CNetCdfInterface::inqVarNAtts(int ncid, int varid, int& natts) { int status = nc_inq_varnatts(ncid, varid, &natts); if (NC_NOERR != status) { StdString errormsg(nc_strerror(status)); StdStringStream sstr; sstr << "Error when calling function nc_inq_varnatts(ncid, varid, &natts)" << std::endl; sstr << errormsg << std::endl; sstr << "Unable to query the number of attributes given the location id:" << ncid << " and the variable id:" << varid << std::endl; StdString e = sstr.str(); throw CNetCdfException(e); } return status; }
/********************************************************************** 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 */
int NETCDF_setup(coordinateInfo *trajInfo, int *actualAtoms) { #ifdef BINTRAJ int err,spatial,i; netcdfTrajectoryInfo *NCInfo; char *filename; # ifdef MPI MPI_Offset ist; # else size_t ist; # endif if (prnlev>0) fprintf(stdout,"NETCDF_setup(): Setting up %s\n",trajInfo->filename); NCInfo=trajInfo->NCInfo; if (NCInfo == NULL) return 1; filename=trajInfo->filename; /* DAN ROE: For DEBUG of netcdf files, prints what vars are stored */ if (prnlev>3) dan_netcdf_debug(NCInfo->ncid); /* * Get global attributes (after initializing a structure to hold the data), */ trajInfo->title = netcdfGetAttributeText(NCInfo->ncid, NC_GLOBAL, "title"); trajInfo->application = netcdfGetAttributeText(NCInfo->ncid, NC_GLOBAL, "application"); trajInfo->program = netcdfGetAttributeText(NCInfo->ncid, NC_GLOBAL, "program"); trajInfo->version = netcdfGetAttributeText(NCInfo->ncid, NC_GLOBAL, "programVersion"); NCInfo->Conventions = netcdfGetAttributeText(NCInfo->ncid, NC_GLOBAL, "Conventions"); NCInfo->ConventionVersion = netcdfGetAttributeText(NCInfo->ncid, NC_GLOBAL, "ConventionVersion"); if (strstr(NCInfo->Conventions, "AMBER") == NULL) { printfone("WARNING: NetCDF file has Conventions that do not include the string \"AMBER\"\n"); } if (strcmp(NCInfo->ConventionVersion, "1.0") != 0) { printfone("WARNING: NetCDF file has ConventionVersion differing from \"1.0\"\n"); } /* * get the NetCDF dimension ID's and sizes for the frames, spatial and atoms */ NCInfo->frameDID = netcdfGetDimensionInfo(NCInfo->ncid, AMBER_NETCDF_FRAME, &(trajInfo->stop)); NCInfo->spatialDID = netcdfGetDimensionInfo(NCInfo->ncid, AMBER_NETCDF_SPATIAL, &spatial); NCInfo->atomDID = netcdfGetDimensionInfo(NCInfo->ncid, AMBER_NETCDF_ATOM, actualAtoms); if (spatial != 3) { printfone("ptraj cannot handle NetCDF files with other than 3 dims\n"); return 1; } /* * perform a sanity check on time variable and units. * DAN ROE: Should errors here really terminate ptraj? */ err = nc_inq_varid(NCInfo->ncid, AMBER_NETCDF_TIME, &NCInfo->timeVID); if (err != NC_NOERR) { printfone("Error: NetCDF time variable: %s", nc_strerror(err)); return 1; } // error(ROUTINE, "NetCDF time variable, error: %s", nc_strerror(err)); err = nc_inq_varnatts(NCInfo->ncid, NCInfo->timeVID, &i); if ( err != NC_NOERR ) { printfone("Error: Getting number of time attributes in NetCDF file %s\n", filename); return 1; } // error(ROUTINE, "Getting number of time attributes in NetCDF file %s\n", filename); if ( i != 1 ) { printfone("Error: Only one time attribute is expected in NetCDF file %s\n", filename); return 1; } // error(ROUTINE, "Only one time attribute is expected in NetCDF file %s\n", filename); err = nc_inq_attlen(NCInfo->ncid, NCInfo->timeVID, "units", &ist); if (err != NC_NOERR) { printfone("Error: Grabbing time units attribute length in NetCDF file: %s\n", nc_strerror(err)); return 1; } NCInfo->timeUnits = (char *) safe_malloc(sizeof(char) * (ist+1)); err = nc_get_att_text(NCInfo->ncid, NCInfo->timeVID, "units", NCInfo->timeUnits); if (err != NC_NOERR) { printfone("Error: Could not get time units from NetCDF file %s: %s", filename, nc_strerror(err)); safe_free(NCInfo->timeUnits); return 1; } if (strcmp("picosecond",NCInfo->timeUnits) != 0) printfone("WARNING: Expecting time units in picoseconds, got -%s-\n", NCInfo->timeUnits); err = nc_inq_varid(NCInfo->ncid, AMBER_NETCDF_SPATIAL, &NCInfo->spatialVID); if (err != NC_NOERR) { printfone("Error: Getting spatialVID in the NetCDF file %s: %s\n", filename, nc_strerror(err)); return 1; } /* * NETCDF: check to see what trajectory data is within the NetCDF file * and perform sanity checks... * * ARE COORDINATES PRESENT? */ err = nc_inq_varid(NCInfo->ncid, AMBER_NETCDF_COORDS, &NCInfo->coordinateVID); if (err != NC_NOERR) { printfone("Error: No coordinates are present in the NetCDF file %s\n", filename); return 1; } err = nc_inq_varnatts(NCInfo->ncid, NCInfo->coordinateVID, &i); if ( err != NC_NOERR ) { printfone("Error: Getting number of coordinate attributes in NetCDF file %s\n", filename); return 1; } if ( i != 1 ) { printfone("Error: Only a single coordinate attribute is expected in NetCDF file %s\n", filename); return 1; } err = nc_inq_attlen(NCInfo->ncid, NCInfo->coordinateVID, "units", &ist); if (err != NC_NOERR) { printfone("Error: Getting coordinateVID attribute length. %s\n",nc_strerror(err)); return 1; } NCInfo->coordinateUnits = (char *) safe_malloc(sizeof(char) * (ist+1)); err = nc_get_att_text(NCInfo->ncid, NCInfo->coordinateVID, "units", NCInfo->coordinateUnits); if (err != NC_NOERR) { printfone("Error: Could not get coordinate units from NetCDF file %s", filename); safe_free(NCInfo->coordinateUnits); return 1; } if (strcmp("angstrom",NCInfo->coordinateUnits) != 0) printfone("WARNING: Expecting coordinate units in angstroms, got %s\n", NCInfo->coordinateUnits); /* * ARE CELL_LENGTHS (i.e. box info) PRESENT? */ err = nc_inq_varid(NCInfo->ncid, "cell_angles", &NCInfo->cellAngleVID); if ((err != NC_NOERR)&&(prnlev>0)) printfone("Warning: NetCDF cell angle variable ID: %s\n", nc_strerror(err)); err = nc_inq_varid(NCInfo->ncid, "cell_lengths", &NCInfo->cellLengthVID); if ((err != NC_NOERR)&&(prnlev>0)) printfone("Warning: NetCDF cell length variable ID: %s\n", nc_strerror(err)); // Set up box information if (err == NC_NOERR) { // Angle information err = nc_inq_varnatts(NCInfo->ncid, NCInfo->cellAngleVID, &i); if ( i > 0 ) { err = nc_inq_attlen(NCInfo->ncid, NCInfo->cellAngleVID, "units", &ist); if (err == NC_NOERR) { NCInfo->cellAngleUnits = (char *) safe_malloc(sizeof(char) * (ist+1)); err=nc_get_att_text(NCInfo->ncid, NCInfo->cellAngleVID, "units", NCInfo->cellAngleUnits); } } // Cell length information err = nc_inq_varnatts(NCInfo->ncid, NCInfo->cellLengthVID, &i); if ( i > 0 ) { err = nc_inq_attlen(NCInfo->ncid, NCInfo->cellLengthVID, "units", &ist); if (err == NC_NOERR) { NCInfo->cellLengthUnits = (char *) safe_malloc(sizeof(char) * (ist+1)); err=nc_get_att_text(NCInfo->ncid, NCInfo->cellLengthVID, "units", NCInfo->cellLengthUnits); } } trajInfo->isBox = 1; } // End box information setup /* * ARE VELOCITIES PRESENT? */ err = nc_inq_varid(NCInfo->ncid, "velocities", &NCInfo->velocityVID); if (err == NC_NOERR) { trajInfo->isVelocity = 1; err = nc_inq_varnatts(NCInfo->ncid, NCInfo->velocityVID, &i); if ( i > 1 ) { err = nc_inq_attlen(NCInfo->ncid, NCInfo->velocityVID, "units", &ist); if (err == NC_NOERR) { NCInfo->velocityUnits = (char *) safe_malloc(sizeof(char) * (ist+1)); err = nc_get_att_text(NCInfo->ncid, NCInfo->velocityVID, "units", NCInfo->velocityUnits); } err = nc_get_att_double(NCInfo->ncid, NCInfo->velocityVID, "scale_factor", &NCInfo->velocityScale); } } /* * Are replica temperatures present? */ err= nc_inq_varid(NCInfo->ncid,"temp0",&NCInfo->TempVarID); if (err == NC_NOERR) { if (prnlev>0) printfone("\nNetCDF file has replica temperatures.\n"); } else { if (prnlev>0) printfone("\nNetCDF file does not have replica temperatures.\n"); NCInfo->TempVarID=-1; } return 0; #endif //BINTRAJ return 1; }
/* Test the creation of a system, and it's assignment to a data * variable. THis matches example 2 from John's document (with some of * the other attributes left out.) */ static void test_system_assign(const char *testfile) { int ncid, axis_varids[NDIMS], system_varid, dimids[NDIMS]; int nvars, ndims, natts, unlimdimid; int dimids_in[NDIMS], ndims_in; size_t len_in; char name_in[NC_MAX_NAME + 1]; char systems_in[NC_MAX_NAME + 1]; int naxes_in, axis_varids_in[NDIMS], natts_in; char *dim_name[] = {TIME, LEVEL, LAT, LON}; size_t dim_len[NDIMS] = {NC_UNLIMITED, LEVEL_LEN, LAT_LEN, LON_LEN}; int earth_varid, air_varid; int varid_in; nc_type type_in; int d; /* Create a file. */ if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR; /* Create 4 dimensions, and a coordinate var to go with each. */ for (d = 0; d < NDIMS; d++) { if (nc_def_dim(ncid, dim_name[d], dim_len[d], &dimids[d])) ERR; if (nc_def_var(ncid, dim_name[d], NC_FLOAT, 1, &dimids[d], &axis_varids[d])) ERR; } /* Create two data vars, earth and air. (Don't know what happened * to fire and water Aristotle!) */ if (nc_def_var(ncid, EARTH, NC_FLOAT, NDIMS, dimids, &earth_varid)) ERR; if (nc_def_var(ncid, AIR, NC_FLOAT, NDIMS, dimids, &air_varid)) ERR; /* Unite our 4 dims in a coordinate system. */ if (nccf_def_coord_system(ncid, LAT_LON_COORDINATE_SYSTEM, NDIMS, axis_varids, &system_varid)) ERR; /* Check things out. */ if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 4 && nvars != 7 && natts != 0 && unlimdimid != dimids[3]) ERR; if (nc_inq_varid(ncid, LAT_LON_COORDINATE_SYSTEM, &varid_in)) ERR; if (varid_in != system_varid) ERR; if (nc_inq_var(ncid, system_varid, name_in, &type_in, &ndims_in, dimids_in, &natts_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || type_in != NC_CHAR || ndims_in != 0 || natts_in != 1); if (nc_inq_att(ncid, system_varid, COORDINATE_AXES, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nccf_inq_coord_system(ncid, system_varid, name_in, &naxes_in, axis_varids_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || naxes_in != NDIMS) ERR; for (d = 0; d < NDIMS; d++) if (axis_varids_in[d] != axis_varids[d]) ERR; /* Assign the system to the earth and air data variables. */ if (nccf_assign_coord_system(ncid, earth_varid, system_varid)) ERR; if (nccf_assign_coord_system(ncid, air_varid, system_varid)) ERR; /* Check to ensure that the assignments happened. */ if (nc_inq_varnatts(ncid, earth_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_inq_att(ncid, earth_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_inq_varnatts(ncid, air_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_get_att_text(ncid, earth_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; if (nc_inq_att(ncid, air_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_get_att_text(ncid, air_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; /* Write the file. */ if (nc_close(ncid)) ERR; /* Reopen the file and check it. */ if (nc_open(testfile, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 4 && nvars != 7 && natts != 0 && unlimdimid != dimids[3]) ERR; if (nc_inq_var(ncid, system_varid, name_in, &type_in, &ndims_in, dimids_in, &natts_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || type_in != NC_CHAR || ndims_in != 0 || natts_in != 1); if (nc_inq_att(ncid, system_varid, COORDINATE_AXES, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nccf_inq_coord_system(ncid, system_varid, name_in, &naxes_in, axis_varids_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || naxes_in != NDIMS) ERR; for (d = 0; d < NDIMS; d++) if (axis_varids_in[d] != axis_varids[d]) ERR; /* Check to ensure that the assignments happened. */ if (nc_inq_varnatts(ncid, earth_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_inq_att(ncid, earth_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_inq_varnatts(ncid, air_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_get_att_text(ncid, earth_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; if (nc_inq_att(ncid, air_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_get_att_text(ncid, air_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; if (nc_close(ncid)) ERR; }
int check_attrs(int ncid, int obj) { int attid; int natts = 0; size_t len; nc_type type; char *vlstr; char fixstr[10]; int x; /* Check the object's attributes are OK */ if (nc_inq_varnatts(ncid, obj, &natts )) ERR_GOTO; if (natts != 6) ERR_GOTO; if (nc_inq_attid(ncid, obj, VSTR_ATT1_NAME, &attid)) ERR_GOTO; if (attid != 0) ERR_GOTO; if (nc_inq_atttype(ncid, obj, VSTR_ATT1_NAME, &type)) ERR_GOTO; if (type != NC_STRING) ERR_GOTO; if (nc_inq_attlen(ncid, obj, VSTR_ATT1_NAME, &len)) ERR_GOTO; if (len != 1) ERR_GOTO; vlstr = NULL; if (nc_get_att(ncid, obj, VSTR_ATT1_NAME, &vlstr)) ERR_GOTO; if (NULL != vlstr) ERR_GOTO; if (nc_inq_attid(ncid, obj, VSTR_ATT2_NAME, &attid)) ERR_GOTO; if (attid != 1) ERR_GOTO; if (nc_inq_atttype(ncid, obj, VSTR_ATT2_NAME, &type)) ERR_GOTO; if (type != NC_STRING) ERR_GOTO; if (nc_inq_attlen(ncid, obj, VSTR_ATT2_NAME, &len)) ERR_GOTO; if (len != 1) ERR_GOTO; vlstr = NULL; if (nc_get_att(ncid, obj, VSTR_ATT2_NAME, &vlstr)) ERR_GOTO; if (NULL != vlstr) ERR_GOTO; if (nc_inq_attid(ncid, obj, VSTR_ATT3_NAME, &attid)) ERR_GOTO; if (attid != 2) ERR_GOTO; if (nc_inq_atttype(ncid, obj, VSTR_ATT3_NAME, &type)) ERR_GOTO; if (type != NC_STRING) ERR_GOTO; if (nc_inq_attlen(ncid, obj, VSTR_ATT3_NAME, &len)) ERR_GOTO; if (len != 1) ERR_GOTO; vlstr = NULL; if (nc_get_att(ncid, obj, VSTR_ATT3_NAME, &vlstr)) ERR_GOTO; if (strcmp(vlstr, "")) ERR_GOTO; free(vlstr); if (nc_inq_attid(ncid, obj, VSTR_ATT4_NAME, &attid)) ERR_GOTO; if (attid != 3) ERR_GOTO; if (nc_inq_atttype(ncid, obj, VSTR_ATT4_NAME, &type)) ERR_GOTO; if (type != NC_STRING) ERR_GOTO; if (nc_inq_attlen(ncid, obj, VSTR_ATT4_NAME, &len)) ERR_GOTO; if (len != 1) ERR_GOTO; vlstr = NULL; if (nc_get_att(ncid, obj, VSTR_ATT4_NAME, &vlstr)) ERR_GOTO; if (strcmp(vlstr, "foo")) ERR_GOTO; free(vlstr); if (nc_inq_attid(ncid, obj, FSTR_ATT_NAME, &attid)) ERR_GOTO; if (attid != 4) ERR_GOTO; if (nc_inq_atttype(ncid, obj, FSTR_ATT_NAME, &type)) ERR_GOTO; if (type != NC_CHAR) ERR_GOTO; if (nc_inq_attlen(ncid, obj, FSTR_ATT_NAME, &len)) ERR_GOTO; if (len != 10) ERR_GOTO; memset(fixstr, 1, sizeof(fixstr)); if (nc_get_att(ncid, obj, FSTR_ATT_NAME, fixstr)) ERR_GOTO; if ('\0' != fixstr[0]) ERR_GOTO; if (nc_inq_attid(ncid, obj, INT_ATT_NAME, &attid)) ERR_GOTO; if (attid != 5) ERR_GOTO; if (nc_inq_atttype(ncid, obj, INT_ATT_NAME, &type)) ERR_GOTO; if (type != NC_INT) ERR_GOTO; if (nc_inq_attlen(ncid, obj, INT_ATT_NAME, &len)) ERR_GOTO; if (len != 1) ERR_GOTO; x = -1; if (nc_get_att(ncid, obj, INT_ATT_NAME, &x)) ERR_GOTO; if (0 != x) ERR_GOTO; return(0); error: return(-1); }
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; }
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); }