Example #1
0
/*******************************************************************************
   void get_string_data(const char *file, const char *name, char *data)
   get string data of field with "name" from "file".
******************************************************************************/
void get_string_data(const char *file, const char *name, char *data)
{
  int ncid, varid, status;
  char msg[512];

#ifdef use_netCDF    
  status = nc_open(file, NC_NOWRITE, &ncid);
  if(status != NC_NOERR) {
    sprintf(msg, "in opening file %s", file);
    handle_netcdf_error(msg, status);
  }
  status = nc_inq_varid(ncid, name, &varid);
  if(status != NC_NOERR) {
    sprintf(msg, "in getting varid of %s from file %s.", name, file);
    handle_netcdf_error(msg, status);
  }     
  status = nc_get_var_text(ncid, varid, data);
  if(status != NC_NOERR) {
    sprintf(msg, "in getting data of %s from file %s.", name, file);
    handle_netcdf_error(msg, status);
  }
  status = nc_close(ncid);
  if(status != NC_NOERR) {
    sprintf(msg, "in closing file %s.", file);
    handle_netcdf_error(msg, status);
  }  
#else
  error_handler("read_mosaic: Add flag -Duse_netCDF when compiling");
#endif
  
}; /* get_string_data */
Example #2
0
/* Test a small file with one var and one att. */
static int
test_one_with_att(const char *testfile)
{
   int ncid, dimid, varid;
   char data = 'h', data_in;
   int ndims, nvars, natts, unlimdimid;
   size_t start[NDIMS], count[NDIMS];

   /* Create a file with one ulimited dimensions, and one var. */
   if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR;
   if (nc_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, &dimid)) ERR;
   if (nc_def_var(ncid, VAR_NAME, NC_CHAR, 1, &dimid, &varid)) ERR;
   if (nc_put_att_text(ncid, NC_GLOBAL, ATT_NAME, 1, &data)) ERR;
   if (nc_enddef(ncid)) ERR;

   /* Write one record of var data, a single character. */
   count[0] = 1;
   start[0] = 0;
   if (nc_put_vara_text(ncid, varid, start, count, &data)) ERR;

   /* We're done! */
   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 != 1 && nvars != 1 && natts != 0 && unlimdimid != 0) ERR;
   if (nc_get_var_text(ncid, varid, &data_in)) ERR;
   if (data_in != data) ERR;
   if (nc_get_att_text(ncid, NC_GLOBAL, ATT_NAME, &data_in)) ERR;
   if (data_in != data) ERR;
   if (nc_close(ncid)) ERR; 
   return 0;
}
Example #3
0
/* Test a small file with an unlimited dimension. NOTE: Normally I
 * write a NULL terminator for my attributes and text strings, but
 * this reproduces a bug that a fortran user sent us. So string data
 * are written to the file without null terminators. - Ed */
static int
test_small_unlim(const char *testfile)
{
   int ncid, dimids[NDIMS], varid;
   char data[NUM_VALS][STR_LEN + 1], data_in[NUM_VALS][STR_LEN];
   int ndims, nvars, natts, unlimdimid;
   size_t i, start[NDIMS], count[NDIMS];

   /* Create null-terminated text strings of correct length. */
   /*for (i = 0; i < NUM_VALS; i++)
     strcpy(data[i], source);*/
   strcpy(data[0], "2005-04-11_12:00:00");
   strcpy(data[1], "2005-04-11_13:00:00");
   
   /* Create a file with two dimensions, one unlimited, and one
    * var, and a global att. */
   if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR;
   if (nc_def_dim(ncid, DIM1_NAME, NC_UNLIMITED, dimids)) ERR;
   if (nc_def_dim(ncid, DIM2_NAME, STR_LEN, &dimids[1])) ERR;
   if (nc_def_var(ncid, VAR_NAME, NC_CHAR, 2, dimids, &varid)) ERR;
   if (nc_put_att_text(ncid, NC_GLOBAL, ATT_NAME2, strlen(TITLE), TITLE)) ERR;
   if (nc_enddef(ncid)) ERR;

   /* Write some records of var data. */
   count[0] = 1;
   count[1] = STR_LEN;
   start[1] = 0;
   for (start[0] = 0; start[0] < NUM_VALS; start[0]++)
      if (nc_put_vara_text(ncid, varid, start, count, data[start[0]])) ERR;

   /* We're done! */
   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 != 2 && nvars != 1 && natts != 0 && unlimdimid != 0) ERR;
   if (nc_get_var_text(ncid, varid, (char *)data_in)) ERR;
   for (i = 0; i < NUM_VALS; i++)
      if (strncmp(data[i], data_in[i], STR_LEN)) ERR;
   if (nc_close(ncid)) ERR; 
   return 0;
}
Example #4
0
/* Given an ncid, check the file to make sure it has all the objects I
 * expect. */
int
check_classic_file(int ncid)
{
   int varid, dimid, attnum;
   size_t att_len;
   nc_type att_type;
   char name_in[sizeof(name_utf8) + 1], strings_in[sizeof(name_utf8) + 1];

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

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

   /* Check the attribute.  We don't normalize data or attribute
    * values, so get exactly what was put for the value, but
    * normalized values for names. */
   if (nc_inq_attid(ncid, varid, norm_utf8, &attnum)) ERR;
   if (attnum) ERR;
   attnum = 99; /* Reset. */
   if (nc_inq_attid(ncid, varid, name_utf8, &attnum)) ERR;
   if (attnum) ERR;
   if (nc_inq_att(ncid, varid, norm_utf8, &att_type, &att_len)) ERR;
   if (att_type != NC_CHAR || att_len != sizeof(name_utf8)) ERR;
   if (nc_get_att_text(ncid, varid, norm_utf8, strings_in)) ERR;
   if (strncmp(name_utf8, strings_in, sizeof(name_utf8))) ERR;
   return NC_NOERR;
}
Example #5
0
File: mpp_io.c Project: djibi2/AM3
/*********************************************************************
  void mpp_get_var_value(int fid, int vid, void *data)
  read part of var data, the part is defined by start and nread.
*********************************************************************/
void mpp_get_var_value(int fid, int vid, void *data)
{
  int status;
  int *data_i4;
  short *data_i2;
  float *data_r4;
  char errmsg[512];
  
  if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_var_value_block): invalid fid number, fid should be "
				    "a nonnegative integer that less than nfiles");
  if(vid<0 || vid >=files[fid].nvar) mpp_error("mpp_io(mpp_get_var_value_block): invalid vid number, vid should be "
				    "a nonnegative integer that less than nvar");

  switch(files[fid].var[vid].type) {
  case NC_DOUBLE:case NC_FLOAT:
    status = nc_get_var_double(files[fid].ncid, files[fid].var[vid].fldid, data);
    break;
  case NC_INT:
    status = nc_get_var_int(files[fid].ncid, files[fid].var[vid].fldid, data);
    break;
  case NC_SHORT:
    status = nc_get_var_short(files[fid].ncid, files[fid].var[vid].fldid, data);
    break;    
  case NC_CHAR:
    status = nc_get_var_text(files[fid].ncid, files[fid].var[vid].fldid, data);
    break; 
  default:
    sprintf(errmsg, "mpp_io(mpp_get_var_value): field %s in file %s has an invalid type, "
	    "the type should be NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT or NC_CHAR",
	    files[fid].var[vid].name, files[fid].name );
    mpp_error(errmsg);
  }    
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_get_var_value): Error in getting value of variable %s from file %s",
	    files[fid].var[vid].name, files[fid].name );
    netcdf_error(errmsg, status);
  }
  
}; /* mpp_get_var_value */
Example #6
0
NCtable_t *NCtableOpen(int ncid, char *tablename)
{
	int status, *dimids, dimid, i = 0, j = 0;
	int ndims, nvars;
	size_t nrecords;
	size_t len;
	char varname [NC_MAX_NAME];
	nc_type type;
	NCfield_t *field = (NCfield_t *) NULL;
	NCtable_t *tbl   = (NCtable_t *) NULL;

	if((status = nc_inq_dimid  (ncid,tablename,&dimid)) != NC_NOERR)
	{ NCprintNCError (status,"NCtableOpen"); return ((NCtable_t *) NULL); }
	if((status = nc_inq_dimlen (ncid,dimid,&nrecords))  != NC_NOERR)
	{ NCprintNCError (status,"NCtableOpen"); return ((NCtable_t *) NULL); }
	if((status = nc_inq_nvars  (ncid,&nvars))           != NC_NOERR)
	{ NCprintNCError (status,"NCtableOpen"); return ((NCtable_t *) NULL); }
	if(nc_inq_ndims(ncid,&ndims) != NC_NOERR)
	{ NCprintNCError (status,"NCtableOpen"); return ((NCtable_t *) NULL); }
	if ((dimids = (int *) malloc(sizeof(int) * ndims)) == (int *) NULL)
	{ CMmsgPrint (CMmsgSysError, "Memory allocation error in: %s %d",__FILE__,__LINE__); return (NCtable_t *) NULL; }

	if ((tbl = (NCtable_t *) malloc(sizeof(NCtable_t))) == (NCtable_t *) NULL)
	{ CMmsgPrint (CMmsgSysError, "Memory allocation error in: %s %d",__FILE__,__LINE__); free (dimids); return ((NCtable_t *) NULL); }
	if ((tbl->Name = (char *) malloc (strlen(tablename) + 1)) == (char *) NULL)
	{ CMmsgPrint (CMmsgSysError, "Memory allocation error in: %s %d",__FILE__,__LINE__); free (dimids); free (tbl); return ((NCtable_t *) NULL); }
	strcpy(tbl->Name,tablename);
	tbl->NFields  = 0;
	tbl->Fields   = (NCfield_t *) NULL;

	for(i = 0; i < nvars; i++)
	{
		if ((status = nc_inq_vartype(ncid,i,&type)) != NC_NOERR)
		{ NCprintNCError (status,"NCtableOpen"); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
		if ((len = _NCtableVarLen(ncid,i,dimid,dimids)) == NCfailed) continue;
		if ((type != NC_CHAR) && (len > 1)) continue;

		if((status = nc_inq_varname(ncid,i,varname)) != NC_NOERR)
		{ NCprintNCError (status,"NCtableOpen"); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }

		if ((tbl->Fields = (NCfield_t *) realloc (tbl->Fields, sizeof (NCfield_t) * (tbl->NFields + 1))) == (NCfield_t *) NULL)
		{ CMmsgPrint (CMmsgSysError, "Error allocating memory in: %s %d",__FILE__,__LINE__); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
		field = tbl->Fields + tbl->NFields;
		tbl->NFields += 1;
		field->NRecords = nrecords;
		field->Data = (void *) NULL;
		field->Name = (char *) NULL;
		field->Type = type;
		field->Len  = len;

		if ((field->Name = malloc (strlen (varname) + 1)) == (char *) NULL)
		{ CMmsgPrint (CMmsgSysError, "Error allocating memory in: %s %d",__FILE__,__LINE__); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
		strcpy (field->Name,varname);

		if (nc_get_att_double (ncid,i,NCnameVAScaleFactor,&field->Scale)      != NC_NOERR) field->Scale      = 1.0;
		if (nc_get_att_double (ncid,i,NCnameVAAddOffset,  &field->Offset)     != NC_NOERR) field->Offset     = 0.0;

		switch(field->Type)
		{
			case NC_CHAR:
				if ((field->Data = (void *) malloc(field->NRecords * field->Len * sizeof (char)))   == (void *) NULL)
				{ CMmsgPrint (CMmsgSysError, "Error allocating memory in: %s %d",__FILE__,__LINE__); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
				if((status = nc_get_var_text(ncid,i,(char *) (field->Data))) != NC_NOERR)
				{ NCprintNCError (status,"NCtableOpen"); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
				break;
			case NC_BYTE:
			case NC_SHORT:
			case NC_INT:
				if ((field->Data = (void *) malloc(field->NRecords * field->Len * sizeof (int)))   == (void *) NULL)
				{ CMmsgPrint (CMmsgSysError, "Error allocating memory in: %s %d",__FILE__,__LINE__); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
				if((status = nc_get_var_int(ncid,i,(int *) (field->Data))) != NC_NOERR)
				{ NCprintNCError (status,"NCtableOpen"); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
				if (nc_get_att_int    (ncid,i,NCnameVAFillValue,  &field->FillValue.Int)  != NC_NOERR) field->FillValue.Int  = INT_NOVALUE;
				if (nc_get_att_double (ncid,i,NCnameVAMissingVal, &field->MissingVal)     != NC_NOERR) field->MissingVal     = FLOAT_NOVALUE;
				break;
			case NC_FLOAT:
			case NC_DOUBLE:
				if ((field->Data = (void *) malloc(field->NRecords * field->Len * sizeof (double))) == (void *) NULL)
				{ CMmsgPrint (CMmsgSysError, "Error allocating memory in: %s %d",__FILE__,__LINE__); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
				if((status = nc_get_var_double(ncid,i,(double *) (field->Data))) != NC_NOERR)
				{ NCprintNCError (status,"NCtableOpen"); free (dimids); NCtableClose (tbl); return ((NCtable_t *) NULL); }
				if (nc_get_att_double (ncid,i,NCnameVAFillValue,  &field->FillValue.Float)  != NC_NOERR) field->FillValue.Float = FLOAT_NOVALUE;
				if (nc_get_att_double (ncid,i,NCnameVAMissingVal, &field->MissingVal)       != NC_NOERR) field->MissingVal      = FLOAT_NOVALUE;
				break;
			default:        field->Data = (void *) NULL; break;
		}
		if(GetDebug()) CMmsgPrint (CMmsgUsrError, "Loaded: %s(dimid: %d)\n",field->Name,dimid);
	}

	if(GetDebug())
	{
		CMmsgPrint (CMmsgUsrError, "Dim: %d Name: %s Cols: %d Rows: %d\n",dimid,tbl->Name,tbl->NFields,field->NRecords);
		for(i = 0; i < tbl->NFields; i++)
		{
			field = tbl->Fields + i;
			CMmsgPrint (CMmsgUsrError, "\tField: %d Name: %s ",i,field->Name);
			switch(field->Type)
			{
				case NC_CHAR:
					if(field->Len == 1)
					{
						CMmsgPrint (CMmsgUsrError, "Type: char\n");
						for(j = 0; j < 5; j++) CMmsgPrint (CMmsgUsrError, "\t\t%d %c\n",j,((char *) (field->Data)) [j]);
					}
					else
					{
						CMmsgPrint (CMmsgUsrError, "Type: string\n");
						for(j = 0; j < 5; j++) CMmsgPrint (CMmsgUsrError, "\t\t%d %s\n",j,((char *) (field->Data)) + j * field->Len);
					}
					break;
				case NC_BYTE:
				case NC_SHORT:
				case NC_INT:
					CMmsgPrint (CMmsgUsrError, "Type: int\n");
					for(j = 0; j < 5; j++) CMmsgPrint (CMmsgUsrError, "\t\t%d %i\n",j,((int *)    (field->Data)) [j]);
					break;
				case NC_FLOAT:
				case NC_DOUBLE:
					CMmsgPrint (CMmsgUsrError, "Type: double\n");
					for(j = 0; j < 5; j++) CMmsgPrint (CMmsgUsrError, "\t\t%d %f\n",j,((double *) (field->Data)) [j]);
					break;
				default: break;
			}
		}
	}
	return (tbl);
}
Example #7
0
/*! \internal */
int
cpy_var_val(int in_id,int out_id,char *var_nm)
/*
   int in_id: input netCDF input-file ID
   int out_id: input netCDF output-file ID
   char *var_nm: input variable name
 */
{
  /* Routine to copy the variable data from an input netCDF file
   * to an output netCDF file. 
   */

  int *dim_id;
  int idx;
  int nbr_dim;
  int var_in_id;
  int var_out_id;
  size_t *dim_cnt;
  size_t *dim_sz;
  size_t *dim_srt;
  size_t var_sz=1L;
  nc_type var_type_in, var_type_out;

  void *void_ptr = NULL;

  /* Get the var_id for the requested variable from both files. */
  (void)nc_inq_varid(in_id, var_nm, &var_in_id);
  (void)nc_inq_varid(out_id,var_nm, &var_out_id);
 
  /* Get the number of dimensions for the variable. */
  (void)nc_inq_vartype( out_id, var_out_id, &var_type_out);
  (void)nc_inq_varndims(out_id, var_out_id, &nbr_dim);

  (void)nc_inq_vartype( in_id,   var_in_id, &var_type_in);
  (void)nc_inq_varndims(in_id,   var_in_id, &nbr_dim);
 
  /* Allocate space to hold the dimension IDs */
  dim_cnt = malloc(nbr_dim*sizeof(size_t));

  dim_id=malloc(nbr_dim*sizeof(int));

  dim_sz=malloc(nbr_dim*sizeof(size_t));

  dim_srt=malloc(nbr_dim*sizeof(size_t));
 
  /* Get the dimension IDs from the input file */
  (void)nc_inq_vardimid(in_id, var_in_id, dim_id);
 
  /* Get the dimension sizes and names from the input file */
  for(idx=0;idx<nbr_dim;idx++){
  /* NB: For the unlimited dimension, ncdiminq() returns the maximum
     value used so far in writing data for that dimension.
     Thus if you read the dimension sizes from the output file, then
     the ncdiminq() returns dim_sz=0 for the unlimited dimension
     until a variable has been written with that dimension. This is
     the reason for always reading the input file for the dimension
     sizes. */

    (void)nc_inq_dimlen(in_id,dim_id[idx],dim_cnt+idx);

    /* Initialize the indicial offset and stride arrays */
    dim_srt[idx]=0L;
    var_sz*=dim_cnt[idx];
  } /* end loop over dim */

  /* Allocate enough space to hold the variable */
  if (var_sz > 0)
      void_ptr=malloc(var_sz * type_size(var_type_in));

  /* Get the variable */

  /* if variable is float or double, convert if necessary */

  if(nbr_dim==0){  /* variable is a scalar */

    if (var_type_in == NC_INT && var_type_out == NC_INT) {
      nc_get_var1_int(in_id,  var_in_id,  0L, void_ptr);
      nc_put_var1_int(out_id, var_out_id, 0L, void_ptr);
    }

    else if (var_type_in == NC_INT64 && var_type_out == NC_INT64) {
      nc_get_var1_longlong(in_id,  var_in_id,  0L, void_ptr);
      nc_put_var1_longlong(out_id, var_out_id, 0L, void_ptr);
    }

    else if (var_type_in == NC_FLOAT) {
      nc_get_var1_float(in_id,  var_in_id,  0L, void_ptr);
      nc_put_var1_float(out_id, var_out_id, 0L, void_ptr);
    }

    else if (var_type_in == NC_DOUBLE) {
      nc_get_var1_double(in_id,  var_in_id,  0L, void_ptr);
      nc_put_var1_double(out_id, var_out_id, 0L, void_ptr);
    }

    else if (var_type_in == NC_CHAR) {
      nc_get_var1_text(in_id,  var_in_id,  0L, void_ptr);
      nc_put_var1_text(out_id, var_out_id, 0L, void_ptr);
    }

    else {
      assert(1==0);
    }
  } else { /* variable is a vector */

    if (var_type_in == NC_INT && var_type_out == NC_INT) {
      (void)nc_get_var_int(in_id,  var_in_id,  void_ptr);
      (void)nc_put_var_int(out_id, var_out_id, void_ptr);
    }

    else if (var_type_in == NC_INT64 && var_type_out == NC_INT64) {
      (void)nc_get_var_longlong(in_id,  var_in_id,  void_ptr);
      (void)nc_put_var_longlong(out_id, var_out_id, void_ptr);
    }

    else if (var_type_in == NC_FLOAT) {
      (void)nc_get_var_float(in_id,  var_in_id,  void_ptr);
      (void)nc_put_var_float(out_id, var_out_id, void_ptr);
    }

    else if (var_type_in == NC_DOUBLE) {
      (void)nc_get_var_double(in_id,  var_in_id,  void_ptr);
      (void)nc_put_var_double(out_id, var_out_id, void_ptr);
    }

    else if (var_type_in == NC_CHAR) {
      (void)nc_get_var_text(in_id,  var_in_id,  void_ptr);
      (void)nc_put_var_text(out_id, var_out_id, void_ptr);
    }

    else {
      assert(1==0);
    }
  } /* end if variable is an array */

  /* Free the space that held the dimension IDs */
  (void)free(dim_cnt);
  (void)free(dim_id);
  (void)free(dim_sz);
  (void)free(dim_srt);

  /* Free the space that held the variable */
  (void)free(void_ptr);

  return(EX_NOERR);

} /* end cpy_var_val() */
Example #8
0
static int read_variable(harp_product *product, int ncid, int varid, netcdf_dimensions *dimensions)
{
    harp_variable *variable;
    harp_data_type data_type;
    int num_dimensions;
    harp_dimension_type dimension_type[HARP_MAX_NUM_DIMS];
    long dimension[HARP_MAX_NUM_DIMS];
    char netcdf_name[NC_MAX_NAME + 1];
    nc_type netcdf_data_type;
    int netcdf_num_dimensions;
    int netcdf_dim_id[NC_MAX_VAR_DIMS];
    int result;
    long i;

    result = nc_inq_var(ncid, varid, netcdf_name, &netcdf_data_type, &netcdf_num_dimensions, netcdf_dim_id, NULL);
    if (result != NC_NOERR)
    {
        harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result));
        return -1;
    }

    if (get_harp_type(netcdf_data_type, &data_type) != 0)
    {
        harp_add_error_message(" (variable '%s')", netcdf_name);
        return -1;
    }

    num_dimensions = netcdf_num_dimensions;

    if (data_type == harp_type_string)
    {
        if (num_dimensions == 0)
        {
            harp_set_error(HARP_ERROR_IMPORT, "variable '%s' of type '%s' has 0 dimensions; expected >= 1",
                           netcdf_name, harp_get_data_type_name(harp_type_string));
        }

        if (dimensions->type[netcdf_dim_id[num_dimensions - 1]] != netcdf_dimension_string)
        {
            harp_set_error(HARP_ERROR_IMPORT, "inner-most dimension of variable '%s' is of type '%s'; expected '%s'",
                           netcdf_name, get_dimension_type_name(dimensions->type[netcdf_dim_id[num_dimensions - 1]]),
                           get_dimension_type_name(netcdf_dimension_string));
            return -1;
        }

        num_dimensions--;
    }

    if (num_dimensions > HARP_MAX_NUM_DIMS)
    {
        harp_set_error(HARP_ERROR_IMPORT, "variable '%s' has too many dimensions", netcdf_name);
        return -1;
    }

    for (i = 0; i < num_dimensions; i++)
    {
        if (get_harp_dimension_type(dimensions->type[netcdf_dim_id[i]], &dimension_type[i]) != 0)
        {
            harp_add_error_message(" (variable '%s')", netcdf_name);
            return -1;
        }
    }

    for (i = 0; i < num_dimensions; i++)
    {
        dimension[i] = dimensions->length[netcdf_dim_id[i]];
    }

    if (harp_variable_new(netcdf_name, data_type, num_dimensions, dimension_type, dimension, &variable) != 0)
    {
        return -1;
    }

    if (harp_product_add_variable(product, variable) != 0)
    {
        harp_variable_delete(variable);
        return -1;
    }

    /* Read data. */
    if (data_type == harp_type_string)
    {
        char *buffer;
        long length;

        assert(netcdf_num_dimensions > 0);
        length = dimensions->length[netcdf_dim_id[netcdf_num_dimensions - 1]];

        buffer = malloc(variable->num_elements * length * sizeof(char));
        if (buffer == NULL)
        {
            harp_set_error(HARP_ERROR_OUT_OF_MEMORY, "out of memory (could not allocate %lu bytes) (%s:%u)",
                           variable->num_elements * length * sizeof(char), __FILE__, __LINE__);
            return -1;
        }

        result = nc_get_var_text(ncid, varid, buffer);
        if (result != NC_NOERR)
        {
            harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result));
            free(buffer);
            return -1;
        }

        for (i = 0; i < variable->num_elements; i++)
        {
            char *str;

            str = malloc((length + 1) * sizeof(char));
            if (str == NULL)
            {
                harp_set_error(HARP_ERROR_OUT_OF_MEMORY, "out of memory (could not allocate %lu bytes) (%s:%u)",
                               (length + 1) * sizeof(char), __FILE__, __LINE__);
                free(buffer);
                return -1;
            }

            memcpy(str, &buffer[i * length], length);
            str[length] = '\0';
            variable->data.string_data[i] = str;
        }

        free(buffer);
    }
    else
    {
        switch (data_type)
        {
            case harp_type_int8:
                result = nc_get_var_schar(ncid, varid, variable->data.int8_data);
                break;
            case harp_type_int16:
                result = nc_get_var_short(ncid, varid, variable->data.int16_data);
                break;
            case harp_type_int32:
                result = nc_get_var_int(ncid, varid, variable->data.int32_data);
                break;
            case harp_type_float:
                result = nc_get_var_float(ncid, varid, variable->data.float_data);
                break;
            case harp_type_double:
                result = nc_get_var_double(ncid, varid, variable->data.double_data);
                break;
            default:
                assert(0);
                exit(1);
        }

        if (result != NC_NOERR)
        {
            harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result));
            return -1;
        }
    }

    /* Read attributes. */
    result = nc_inq_att(ncid, varid, "description", NULL, NULL);
    if (result == NC_NOERR)
    {
        if (read_string_attribute(ncid, varid, "description", &variable->description) != 0)
        {
            harp_add_error_message(" (variable '%s')", netcdf_name);
            return -1;
        }
    }
    else if (result != NC_ENOTATT)
    {
        harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result));
        return -1;
    }

    result = nc_inq_att(ncid, varid, "units", NULL, NULL);
    if (result == NC_NOERR)
    {
        if (read_string_attribute(ncid, varid, "units", &variable->unit) != 0)
        {
            harp_add_error_message(" (variable '%s')", netcdf_name);
            return -1;
        }
    }
    else if (result != NC_ENOTATT)
    {
        harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result));
        return -1;
    }

    result = nc_inq_att(ncid, varid, "valid_min", NULL, NULL);
    if (result == NC_NOERR)
    {
        harp_data_type attr_data_type;

        if (read_numeric_attribute(ncid, varid, "valid_min", &attr_data_type, &variable->valid_min) != 0)
        {
            harp_add_error_message(" (variable '%s')", netcdf_name);
            return -1;
        }

        if (attr_data_type != data_type)
        {
            harp_set_error(HARP_ERROR_IMPORT, "attribute 'valid_min' of variable '%s' has invalid type", netcdf_name);
            return -1;
        }
    }
    else if (result != NC_ENOTATT)
    {
        harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result));
        return -1;
    }

    result = nc_inq_att(ncid, varid, "valid_max", NULL, NULL);
    if (result == NC_NOERR)
    {
        harp_data_type attr_data_type;

        if (read_numeric_attribute(ncid, varid, "valid_max", &attr_data_type, &variable->valid_max) != 0)
        {
            harp_add_error_message(" (variable '%s')", netcdf_name);
            return -1;
        }

        if (attr_data_type != data_type)
        {
            harp_set_error(HARP_ERROR_IMPORT, "attribute 'valid_max' of variable '%s' has invalid type", netcdf_name);
            return -1;
        }
    }
    else if (result != NC_ENOTATT)
    {
        harp_set_error(HARP_ERROR_NETCDF, "%s", nc_strerror(result));
        return -1;
    }

    return 0;
}
Example #9
0
int main()
{
    int ncid, varid;
    int ncstat = NC_NOERR;
    char* url;
    char* topsrcdir;
    size_t len;
#ifndef USE_NETCDF4
    int i,j;
#endif

    /* location of our target url: use file:// to avoid remote
	server downtime issues
     */

    /* Assume that TESTS_ENVIRONMENT was set */
    topsrcdir = getenv("TOPSRCDIR");
    if(topsrcdir == NULL) {
        fprintf(stderr,"*** FAIL: $abs_top_srcdir not defined: location= %s:%d\n",__FILE__,__LINE__);
        exit(1);
    }
    len = strlen("file://") + strlen(topsrcdir) + strlen("/ncdap_test/testdata3/test.02") + 1;
#ifdef DEBUG
    len += strlen("[log][show=fetch]");
#endif
    url = (char*)malloc(len);
    url[0] = '\0';

#ifdef DEBUG
    strcat(url,"[log][show=fetch]");
#endif

    strcat(url,"file://");
    strcat(url,topsrcdir);
    strcat(url,"/ncdap_test/testdata3/test.02");

    printf("*** Test: var conversions on URL: %s\n",url);

    /* open file, get varid */
    CHECK(nc_open(url, NC_NOWRITE, &ncid));
    /* extract the string case for netcdf-3*/
#ifndef USE_NETCDF4
    CHECK(nc_inq_varid(ncid, "s", &varid));
    CHECK(nc_get_var_text(ncid,varid,(char*)string3));
#ifdef GENERATE
    printf("static %s string3_data[DIMSIZE][STRLEN]={","char");
    for(i=0;i<DIMSIZE;i++) {
	int j;
	/* Do simple escape */
	for(j=0;j<STRLEN;j++) {
	    if(string3[i][j] > 0
	       && string3[i][j] != '\n'
	       && string3[i][j] != '\r'
	       && string3[i][j] != '\t'
	       &&(string3[i][j] < ' ' || string3[i][j] >= '\177'))
		string3[i][j] = '?';
	}
	printf("%s\"%s\"",COMMA,string3[i]);
    }
    printf("};\n");
#else
 	fprintf(stdout,"*** testing: %s\n","string3");
	for(i=0;i<DIMSIZE;i++) {
   	    for(j=0;j<STRLEN;j++) {
	        if(string3[i][j] != string3_data[i][j]) {report(i,"string3",__LINE__); break;}
	    }
	}
#endif
#endif

    CHECK(nc_inq_varid(ncid, "b", &varid));
    CHECK(nc_get_var_text(ncid,varid,ch));
#ifdef GENERATE
    printf("static %s ch_data[DIMSIZE]={","char");
    for(i=0;i<DIMSIZE;i++) printf("%s'\\%03hho'",COMMA,ch[i]);
    printf("};\n");
#else
    COMPARE(NC_CHAR,NC_CHAR,ch,ch_data);
#endif

    CHECK(nc_inq_varid(ncid, "b", &varid));
    CHECK(nc_get_var_schar(ncid,varid,int8v));
#ifdef GENERATE
    printf("static %s int8_data[DIMSIZE]={","signed char");
    for(i=0;i<DIMSIZE;i++) printf("%s%hhd",COMMA,int8v[i]);
    printf("};\n");
#else
    COMPARE(NC_BYTE,NC_BYTE,int8v,int8_data);
#endif

    CHECK(nc_inq_varid(ncid, "b", &varid));
    CHECK(nc_get_var_uchar(ncid,varid,uint8v));
#ifdef GENERATE
    printf("static %s uint8_data[DIMSIZE]={","unsigned char");
    for(i=0;i<DIMSIZE;i++) printf("%s%hhu",COMMA,uint8v[i]);
    printf("};\n");
#else
    COMPARE(NC_UBYTE,NC_UBYTE,uint8v,uint8_data);
#endif

    CHECK(nc_inq_varid(ncid, "b", &varid));
    CHECK(nc_get_var_int(ncid,varid,int32v));
#ifdef GENERATE
    printf("static %s int8toint32_data[DIMSIZE]={","int");
    for(i=0;i<DIMSIZE;i++) printf("%s%d",COMMA,int32v[i]);
    printf("};\n");
#else
    COMPARE(NC_BYTE,NC_INT,int32v,int8toint32_data);
#endif

    CHECK(nc_inq_varid(ncid, "b", &varid));
    CHECK(nc_get_var_float(ncid,varid,float32v));
#ifdef GENERATE
    printf("static %s int82float32_data[DIMSIZE]={","float");
    for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
    printf("};\n");
#else
    COMPARE(NC_FLOAT,NC_FLOAT,float32v,int82float32_data);
#endif

    CHECK(nc_inq_varid(ncid, "i16", &varid));
    CHECK(nc_get_var_short(ncid,varid,int16v));
#ifdef GENERATE
    printf("static %s int16_data[DIMSIZE]={","short");
    for(i=0;i<DIMSIZE;i++) printf("%s%hd",COMMA,int16v[i]);
    printf("};\n");
#else
    COMPARE(NC_SHORT,NC_SHORT,int16v,int16_data);
#endif

    CHECK(nc_inq_varid(ncid, "i16", &varid));
    CHECK(nc_get_var_int(ncid,varid,int32v));
#ifdef GENERATE
    printf("static %s int16toint32_data[DIMSIZE]={","int");
    for(i=0;i<DIMSIZE;i++) printf("%s%d",COMMA,int32v[i]);
    printf("};\n");
#else
    COMPARE(NC_SHORT,NC_INT,int32v,int16toint32_data);
#endif

    CHECK(nc_inq_varid(ncid, "i16", &varid));
    CHECK(nc_get_var_float(ncid,varid,float32v));
#ifdef GENERATE
    printf("static %s int162float32_data[DIMSIZE]={","float");
    for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
    printf("};\n");
#else
    COMPARE(NC_SHORT,NC_FLOAT,float32v,int162float32_data);
#endif

    CHECK(nc_inq_varid(ncid, "i32", &varid));
    CHECK(nc_get_var_int(ncid,varid,int32v));
#ifdef GENERATE
    printf("static %s int32_data[DIMSIZE]={","int");
    for(i=0;i<DIMSIZE;i++) printf("%s%d",COMMA,int32v[i]);
    printf("};\n");
#else
    COMPARE(NC_INT,NC_INT,int32v,int32_data);
#endif

    CHECK(nc_inq_varid(ncid, "i32", &varid));
    CHECK(nc_get_var_float(ncid,varid,float32v));
#ifdef GENERATE
    printf("static %s int32tofloat32_data[DIMSIZE]={","float");
    for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
    printf("};\n");
#else
    COMPARE(NC_INT,NC_FLOAT,float32v,int32tofloat32_data);
#endif

    CHECK(nc_inq_varid(ncid, "i32", &varid));
    CHECK(nc_get_var_long(ncid,varid,ilong));
#ifdef GENERATE
    printf("static %s int32toilong_data[DIMSIZE]={","long");
    for(i=0;i<DIMSIZE;i++) printf("%s%ld",COMMA,ilong[i]);
    printf("};\n");
#else
    COMPARE(NC_INT,NC_NAT,ilong,int32toilong_data);
#endif

    CHECK(nc_inq_varid(ncid, "f32", &varid));
    CHECK(nc_get_var_float(ncid,varid,float32v));
#ifdef GENERATE
    printf("static %s float32_data[DIMSIZE]={","float");
    for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float32v[i]);
    printf("};\n");
#else
    COMPARE(NC_FLOAT,NC_FLOAT,float32v,float32_data);
#endif

    CHECK(nc_inq_varid(ncid, "f64", &varid));
    CHECK(nc_get_var_double(ncid,varid,float64v));
#ifdef GENERATE
    printf("static %s float64_data[DIMSIZE]={","double");
    for(i=0;i<DIMSIZE;i++) printf("%s%1.3f",COMMA,float64v[i]);
    printf("};\n");
#else
    COMPARE(NC_DOUBLE,NC_DOUBLE,float64v,float64_data);
#endif

    if(failure) {
        printf("ncstat=%d %s",ncstat,nc_strerror(ncstat));
        exit(1);
    }
    return 0;
}
Example #10
0
int ex_get_var_names (int   exoid,
                      const char *var_type,
                      int   num_vars,
                      char *var_names[])
{
  int i, varid, status;
  char errmsg[MAX_ERR_LENGTH];
  int vartyp;
  const char* tname;
  const char* vvarname;

  exerrval = 0; /* clear error code */

  vartyp = tolower( *var_type );

  switch (vartyp) {
  case 'g':
    tname = "global";
    vvarname = VAR_NAME_GLO_VAR;
    break;
  case 'n':
    tname = "nodal";
    vvarname = VAR_NAME_NOD_VAR;
    break;
  case 'l':
    tname = "edge block";
    vvarname = VAR_NAME_EDG_VAR;
    break;
  case 'f':
    tname = "face block";
    vvarname = VAR_NAME_FAC_VAR;
    break;
  case 'e':
    tname = "element block";
    vvarname = VAR_NAME_ELE_VAR;
    break;
  case 'm':
    tname = "node set";
    vvarname = VAR_NAME_NSET_VAR;
    break;
  case 'd':
    tname = "edge set";
    vvarname = VAR_NAME_ESET_VAR;
    break;
  case 'a':
    tname = "face set";
    vvarname = VAR_NAME_FSET_VAR;
    break;
  case 's':
    tname = "side set";
    vvarname = VAR_NAME_SSET_VAR;
    break;
  case 't':
    tname = "element set";
    vvarname = VAR_NAME_ELSET_VAR;
    break;
  default:
    exerrval = EX_BADPARAM;
    sprintf(errmsg,
      "Warning: invalid variable type %c requested from file id %d",
      *var_type, exoid);
    ex_err("ex_get_var_param",errmsg,exerrval);
    return (EX_WARN);
  }

  /* inquire previously defined variables  */
  if ((varid = ncvarid (exoid, vvarname)) == -1) {
    exerrval = ncerr;
    sprintf(errmsg, "Warning: no %s variables names stored in file id %d", tname,exoid);
    ex_err("ex_get_var_names",errmsg,exerrval);
    return (EX_WARN);
  }

  /* read the variable names */

  /*
   * See if reading into contiguous memory in which case we can load 
   * all values in one call.  If not, we must load each name individually.
   */
  if (&var_names[num_vars-1][0] - &var_names[0][0] ==
      sizeof(char)*(MAX_STR_LENGTH+1)*(num_vars-1)) {
    status = nc_get_var_text(exoid, varid, &var_names[0][0]);
    if (status == -1) {
      exerrval = ncerr;
      sprintf(errmsg,
              "Error: failed to get results variable names from file id %d", exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_FATAL);
    }
  } else {
    for (i=0; i<num_vars; i++) {
      size_t start[2];
      size_t count[2];
      start[0] = i;  count[0] = 1;
      start[1] = 0;  count[1] = MAX_STR_LENGTH+1;
      status = nc_get_vara_text(exoid, varid, start, count, var_names[i]);
      if (status == -1) {
        exerrval = ncerr;
        sprintf(errmsg,
                "Error: failed to get results variable names from file id %d", exoid);
        ex_err("ex_get_var_names",errmsg,exerrval);
        return (EX_FATAL);
      }
    }
  }
  return (EX_NOERR);
}
Example #11
0
int
main(int argc, char **argv)
{
    size_t sizehint = 2100000;	/* default if not set on command line,
				 * exposes bug.  It turns out any
				 * value between 2091953 and 2150032
				 * triggers bug, whereas all other
				 * values work fine. */

    if (argc > 1) {
	char *endptr, *str = argv[1];
	errno = 0;
	sizehint = strtol(str, &endptr, 0);
	/* check for various possible errors */
	if ((errno == ERANGE && (sizehint == LONG_MAX || sizehint == LONG_MIN))
                   || (errno != 0 && sizehint == 0)) {
               perror("strtol");
               exit(EXIT_FAILURE);
	}
	if (endptr == str) {
	    fprintf(stderr, "No digits were found\n");
	    exit(EXIT_FAILURE);
	}
    }
   printf("\n*** Testing nofill mode.\n");
   {
       printf("*** Create file in nofill mode, writing all values...");
       if (create_file(FILE_NAME1, NC_NOFILL, &sizehint)) ERR;
       SUMMARIZE_ERR;
   }
   {
       printf("*** Create file with same data in fill mode, writing all values...");
       if (create_file(FILE_NAME2, NC_FILL, &sizehint)) ERR;
       SUMMARIZE_ERR;
   }
   {
       int ncid1, ncid2;
       int nvars1, nvars2;
       int varid;
       int badvars;

       printf("*** Compare values in nofill mode and fill mode files...");
       /* compare data in two files created with nofill mode and fill
	* mode, which should be identical if all the data were written */
       if (nc_open(FILE_NAME1, NC_NOWRITE, &ncid1)) ERR;
       if (nc_open(FILE_NAME2, NC_NOWRITE, &ncid2)) ERR;
       if (nc_inq_nvars(ncid1, &nvars1)) ERR;
       if (nc_inq_nvars(ncid2, &nvars2)) ERR;
       if (nvars1 != nvars2) ERR;
       badvars = 0;
       for(varid = 0; varid < nvars1; varid++) {
	   size_t nvals, nn;
	   int ndims, *dimids, dim;
	   nc_type vtype;
	   char varname1[NC_MAX_NAME];		   
	   char varname2[NC_MAX_NAME];
	   /* How many values in this variable to compare? */
	   if (nc_inq_varndims(ncid1, varid, &ndims)) ERR;
	   dimids = malloc((ndims + 1) * sizeof(int));
	   if (!dimids) ERR;
	   if (nc_inq_vardimid (ncid1, varid, dimids)) ERR;
	   nvals = 1;
	   for(dim = 0; dim < ndims; dim++) {
	       size_t len;
	       if (nc_inq_dimlen(ncid1, dimids[dim], &len)) ERR;
	       nvals *= len;
	   }
	   if (nc_inq_vartype(ncid1, varid, &vtype)) ERR;
	   if (nc_inq_varname(ncid1, varid, varname1)) ERR;
	   if (nc_inq_varname(ncid1, varid, varname2)) ERR;
	   
	   if (vtype != NC_CHAR) {  /* numeric data, just read in as doubles */
	       double *data1, *data2;
	       /* Allocate space to hold values in both files */
	       data1 = malloc((nvals + 1) * sizeof(double));
	       if (!data1) ERR;
	       data2 = malloc((nvals + 1) * sizeof(double));
	       if (!data2) ERR;
	       /* Read in values */
	       if (nc_get_var_double(ncid1, varid, data1)) ERR;
	       if (nc_get_var_double(ncid2, varid, data2)) ERR;
	       /* Compare values */
	       for(nn = 0; nn < nvals; nn++) {
		   if (data1[nn] != data2[nn]) {
		       badvars++;
		       fprintf(stderr, 
			       "\tFrom nofill file, %s[%d] = %.15g\tFrom fill file, %s[%d] = %.15g\n", 
			       varname1, nn, data1[nn], varname2, nn, data2[nn]);
		       break;
		   };
	       }
	       free(data1);
	       free(data2);
	   } else {		/* character data */
	       char *data1, *data2;
	       /* Allocate space to hold values in both files */
	       data1 = malloc((nvals + 1) * sizeof(char));
	       if (!data1) ERR;
	       data2 = malloc((nvals + 1) * sizeof(char));
	       if (!data2) ERR;
	       /* Read in values */
	       if (nc_get_var_text(ncid1, varid, data1)) ERR;
	       if (nc_get_var_text(ncid2, varid, data2)) ERR;
	       /* Compare values */
	       for(nn = 0; nn < nvals; nn++) {
		   if (data1[nn] != data2[nn]) {
		       badvars++;
		       fprintf(stderr, 
			       "\tFrom nofill file, %s[%d] = %d\tFrom fill file, %s[%d] = %d\n", 
			       varname1, nn, data1[nn], varname2, nn, data2[nn]);
		       break;
		   };
	       }
	       free(data1);
	       free(data2);
	   }
	   free(dimids);
       }
       if(badvars > 0) ERR;
       if (nc_close(ncid1)) ERR;
       if (nc_close(ncid2)) ERR;
       SUMMARIZE_ERR;
   }
   FINAL_RESULTS;
}
Example #12
0
int main (int argc, char** argv)
{
	//define some generic loop indices
	int i, j;
	
	//make sure a filename was provided
	if (argc < 2)
	{
		puts("NetCDF filename argument required");
		return -1;
	}
	
	//loop through every input file
	int argIndex;
	for (argIndex = 1; argIndex < argc; argIndex++)
	{
		char* filename = argv[argIndex];
		size_t filenameLength = strlen(filename);
		
		//allocate space for the flt.dat filename, plus some room for the longer extension, etc
		char *fltDatFilename = malloc((filenameLength + 7)*sizeof(char));
		strcpy(fltDatFilename, filename);
		char *periodLocation = strrchr(fltDatFilename, '.');
		*periodLocation = '\0';
		strcat(fltDatFilename, "flt.dat");
		
		//open the NetCDF file/dataset
		int datasetID;
		int ncResult;
		ncResult = nc_open(filename, NC_NOWRITE, &datasetID);
		if (ncResult != NC_NOERR) HandleNCError("nc_open", ncResult);
		
		printf("opened NetCDF file: %s", filename);
		printf("output flt.dat filename: %s\n", fltDatFilename);
		
		//get basic information about the NetCDF file
		int numDims, numVars, numGlobalAtts, unlimitedDimID;
		ncResult = nc_inq(datasetID, &numDims, &numVars, &numGlobalAtts, &unlimitedDimID);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq", ncResult);
		int formatVersion;
		ncResult = nc_inq_format(datasetID, &formatVersion);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_format", ncResult);
		
		if (numDims != 1)
		{
			puts("error: only 1-dimensional NetCDF files are supported for now");
			return -1;
		}
		
		//show some of the NetCDF file information on the console
		printf("# dims: %d\n# vars: %d\n# global atts: %d\n", numDims, numVars, numGlobalAtts);
		if (unlimitedDimID != -1) puts("contains unlimited dimension");
		switch (formatVersion)
		{
			case NC_FORMAT_CLASSIC:
				puts("classic file format");
				break;
			case NC_FORMAT_64BIT:
				puts("64-bit file format");
				break;
			case NC_FORMAT_NETCDF4:
				puts("netcdf4 file format");
				break;
			case NC_FORMAT_NETCDF4_CLASSIC:
				puts("netcdf4 classic format");
				break;
			default:
				puts("unrecognized file format");
				return -1;
				break;
		}
		
		//int dimID;
		//for (dimID = 0; dimID < numDims; dimID++)
		//{
		//get dimension names and lengths
		char dimName[NC_MAX_NAME+1];
		size_t dimLength;
		ncResult = nc_inq_dim(datasetID, 0, dimName, &dimLength);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_dim", ncResult);
		
		printf("dimension: %s length: %d\n", dimName, dimLength);
		//}
		
		//open/create the flt.dat file for outputting data
		//todo: better file name
		FILE *fltFile = fopen(fltDatFilename, "w");
		
		//get the current GMT date/time
		time_t currentTime;
		time(&currentTime);
		struct tm *currentTimeStruct = gmtime(&currentTime);
		
		printf("current gmt time: %d/%d/%d %d:%d:%d\n", currentTimeStruct->tm_year+1900, currentTimeStruct->tm_mon+1, currentTimeStruct->tm_mday, 
			currentTimeStruct->tm_hour, currentTimeStruct->tm_min, currentTimeStruct->tm_sec);
		
		//get the launch date/time attribute
		char launchTimeStr[100];
		ncResult = nc_get_att_text(datasetID, NC_GLOBAL, "g.Ascent.StartTime", launchTimeStr);
		if (ncResult != NC_NOERR) HandleNCError("nc_get_att_text", ncResult);
		//split the launch date/time string into token strings
		char yearStr[10];
		substr(yearStr, launchTimeStr, 0, 4);
		char monStr[10];
		substr(monStr, launchTimeStr, 5, 2);
		char dayStr[10];
		substr(dayStr, launchTimeStr, 8, 2);
		char hourStr[10];
		substr(hourStr, launchTimeStr, 11, 2);
		char minStr[10];
		substr(minStr, launchTimeStr, 14, 2);
		char secStr[10];
		substr(secStr, launchTimeStr, 17, 2);
		//convert the launch date/time into a tm structure
		struct tm launchTimeStruct;
		int launchYear = atoi(yearStr);
		int launchMonth = atoi(monStr);
		int launchDay = atoi(dayStr);
		int launchHour = atoi(hourStr);
		int launchMinute = atoi(minStr);
		int launchSecond = atoi(secStr);
		
		printf("launch gmt time: %d/%d/%d %d:%d:%d\n", launchYear, launchMonth, launchDay, launchHour, launchMinute, launchSecond);
		
		//output the flt.dat header
		fprintf(fltFile, "Extended NOAA/GMD preliminary data %02d-%02d-%04d %02d:%02d:%02d [GMT], nc2fltdat version %.3f\r\n", 
			currentTimeStruct->tm_mday, currentTimeStruct->tm_mon+1, currentTimeStruct->tm_year+1900, currentTimeStruct->tm_hour, currentTimeStruct->tm_min, currentTimeStruct->tm_sec, VERSION);
		
		fprintf(fltFile, "Software written by Allen Jordan, NOAA\r\n");
		fprintf(fltFile, "               Header lines = 16\r\n");
		fprintf(fltFile, "               Data columns = 12\r\n");
		fprintf(fltFile, "                 Date [GMT] = %02d-%02d-%04d\r\n", launchDay, launchMonth, launchYear);
		fprintf(fltFile, "                 Time [GMT] = %02d:%02d:%02d\r\n", launchHour, launchMinute, launchSecond);
		fprintf(fltFile, "            Instrument type = Vaisala RS92\r\n");
		fprintf(fltFile, "\r\n\r\n");
		fprintf(fltFile, "    THE DATA CONTAINED IN THIS FILE ARE PRELIMINARY\r\n");
		fprintf(fltFile, "     AND SUBJECT TO REPROCESSING AND VERIFICATION\r\n");
		fprintf(fltFile, "\r\n\r\n\r\n");
		fprintf(fltFile, "      Time,     Press,       Alt,      Temp,        RH,     TFp V,   GPS lat,   GPS lon,   GPS alt,      Wind,  Wind Dir,        Fl\r\n");
		fprintf(fltFile, "     [min],     [hpa],      [km],   [deg C],       [%%],   [deg C],     [deg],     [deg],      [km],     [m/s],     [deg],        []\r\n");
		
		//storage for all variables in the NetCDF file
		//todo: watch out for segfaults, maybe use nc_get_vara_ to get pieces instead of whole variables
		VariableData **variableDataList = (VariableData **)malloc(numVars * sizeof(VariableData*));
		char **standardNameList = (char **)malloc(numVars * sizeof(char*));
		//char **longNameList = (char **)malloc(numVars * sizeof(char*));
		//char **unitStringList = (char **)malloc(numVars * sizeof(char*));
		
		//loop through all the variables
		int varID;
		for (varID=0; varID<numVars; varID++)
		{
			//get information about the variable
			char varName[NC_MAX_NAME+1];
			nc_type varType;
			int numVarDims;
			int varDimIDs[NC_MAX_VAR_DIMS];
			int numVarAtts;
			ncResult = nc_inq_var(datasetID, varID, varName, &varType, &numVarDims, varDimIDs, &numVarAtts);
			if (ncResult != NC_NOERR) HandleNCError("nc_inq_var", ncResult);
			
			//output variable info to console
			printf("variable: %s # dims: %d # atts: %d type: %d\n", varName, numVarDims, numVarAtts, (int)varType);
			
			//output variable name to the flt.dat file
			//fprintf(fltFile, "%s", varName);
			//if (varID != (numVars-1)) fprintf(fltFile, ", ");
			
			/*//see if there is an attribute for the variable standard name, and store it if there is
			int standardNameAttLen = 0;
			ncResult = nc_inq_attlen(datasetID, varID, "standard_name", &standardNameAttLen);
			if (ncResult == NC_NOERR)
			{
				//allocate enough space for the units string
				char *standardNameValueStr = (char *) malloc(standardNameAttLen + 1);
				ncResult = nc_get_att_text(datasetID, varID, "standard_name", standardNameValueStr);
				if (ncResult != NC_NOERR) HandleNCError("nc_get_att_text", ncResult);
				//make sure the string is null terminated (sometimes it won't be, apparently)
				standardNameValueStr[standardNameAttLen] = '\0';
				standardNameList[varID] = standardNameValueStr;
			}
			else
			{
				char *emptyHeapStr = malloc(1*sizeof(char));
				emptyHeapStr[0] = '\0';
				standardNameList[varID] = emptyHeapStr;
			}
			
			//see if there is an attribute for the variable long name, and store it if there is
			int longNameAttLen = 0;
			ncResult = nc_inq_attlen(datasetID, varID, "long_name", &longNameAttLen);
			if (ncResult == NC_NOERR)
			{
				//allocate enough space for the units string
				char *longNameValueStr = (char *) malloc(longNameAttLen + 1);
				ncResult = nc_get_att_text(datasetID, varID, "long_name", longNameValueStr);
				if (ncResult != NC_NOERR) HandleNCError("nc_get_att_text", ncResult);
				//make sure the string is null terminated (sometimes it won't be, apparently)
				longNameValueStr[longNameAttLen] = '\0';
				longNameList[varID] = longNameValueStr;
			}
			else
			{
				char *emptyHeapStr = malloc(1*sizeof(char));
				emptyHeapStr[0] = '\0';
				longNameList[varID] = emptyHeapStr;
			}
			
			//see if there is an attribute for the variable units description, and store it if there is
			int unitsAttLen = 0;
			ncResult = nc_inq_attlen(datasetID, varID, "units", &unitsAttLen);
			if (ncResult == NC_NOERR)
			{
				//allocate enough space for the units string
				char *unitsValueStr = (char *) malloc(unitsAttLen + 1);
				ncResult = nc_get_att_text(datasetID, varID, "units", unitsValueStr);
				if (ncResult != NC_NOERR) HandleNCError("nc_get_att_text", ncResult);
				//make sure the string is null terminated (sometimes it won't be, apparently)
				unitsValueStr[unitsAttLen] = '\0';
				unitStringList[varID] = unitsValueStr;
			}
			else
			{
				char *emptyHeapStr = malloc(1*sizeof(char));
				emptyHeapStr[0] = '\0';
				unitStringList[varID] = emptyHeapStr;
			}*/
			
			
			//make sure the variable only has 1 dimension
			if (numVarDims != 1) puts("warning: only 1-dimensional variables are supported for now... skipping");
			else
			{
				//storage for this variable's data structure
				VariableData *variableData = (VariableData *)malloc(sizeof(VariableData));
				variableData->type = varType;
				
				//depending on the type, allocate storage for this variable's raw data contained in the structure
				switch (varType)
				{
					case NC_BYTE:
					{
						variableData->data = malloc(dimLength * sizeof(unsigned char));
						ncResult = nc_get_var_uchar(datasetID, varID, (unsigned char*)variableData->data);
						if (ncResult != NC_NOERR) HandleNCError("nc_get_var", ncResult);
						break;
					}
					case NC_CHAR:
					{
						variableData->data = malloc(dimLength * sizeof(char));
						ncResult = nc_get_var_text(datasetID, varID, (char*)variableData->data);
						if (ncResult != NC_NOERR) HandleNCError("nc_get_var", ncResult);
						break;
					}
					case NC_SHORT:
					{
						variableData->data = malloc(dimLength * sizeof(short));
						ncResult = nc_get_var_short(datasetID, varID, (short*)variableData->data);
						if (ncResult != NC_NOERR) HandleNCError("nc_get_var", ncResult);
						break;
					}
					case NC_INT:
					{
						variableData->data = malloc(dimLength * sizeof(int));
						ncResult = nc_get_var_int(datasetID, varID, (int*)variableData->data);
						if (ncResult != NC_NOERR) HandleNCError("nc_get_var", ncResult);
						break;
					}
					case NC_FLOAT:
					{
						variableData->data = malloc(dimLength * sizeof(float));
						ncResult = nc_get_var_float(datasetID, varID, (float*)variableData->data);
						if (ncResult != NC_NOERR) HandleNCError("nc_get_var", ncResult);
						break;
					}
					case NC_DOUBLE:
					{
						variableData->data = malloc(dimLength * sizeof(double));
						ncResult = nc_get_var_double(datasetID, varID, (double*)variableData->data);
						if (ncResult != NC_NOERR) HandleNCError("nc_get_var", ncResult);
						break;
					}
					default:
					{
						puts("warning: invalid variable type");
						break;
					}
				}//end of type switch
				
				//store the variable data structure in the list of all variable data structures, to be used later when outputting
				variableDataList[varID] = variableData;
				
			}//end of num var dimensions check
		}//end of variable loop
		
		//output a newline after the variable names flt.dat header line
		//fprintf(fltFile, "\r\n");
		
		/*//output the variable standard names
		for (i=0; i<numVars; i++)
		{
			fprintf(fltFile, "%s", standardNameList[i]);
			if (i != (numVars-1)) fprintf(fltFile, ", ");
		}
		fprintf(fltFile, "\r\n");
		
		//output the variable long names
		for (i=0; i<numVars; i++)
		{
			fprintf(fltFile, "%s", longNameList[i]);
			if (i != (numVars-1)) fprintf(fltFile, ", ");
		}
		fprintf(fltFile, "\r\n");
		
		//output the variable units
		for (i=0; i<numVars; i++)
		{
			char *unitsName = unitStringList[i];
			if (unitsName[0] != '[')
				fprintf(fltFile, "[");
			
			fprintf(fltFile, "%s", unitsName);
			
			if (unitsName[strlen(unitsName)-1] != ']')
				fprintf(fltFile, "]");
			
			if (i != (numVars-1)) fprintf(fltFile, ", ");
		}
		fprintf(fltFile, "\r\n");*/
		
		
		
		
		
		
		
		int timeIndex;
		ncResult = nc_inq_varid(datasetID, "time", &timeIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (time)", ncResult);
		int pressureIndex;
		ncResult = nc_inq_varid(datasetID, "press", &pressureIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (press)", ncResult);
		int temperatureIndex;
		ncResult = nc_inq_varid(datasetID, "temp", &temperatureIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (temp)", ncResult);
		int vaisRHIndex;
		ncResult = nc_inq_varid(datasetID, "rh", &vaisRHIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (rh)", ncResult);
		int windDirIndex;
		ncResult = nc_inq_varid(datasetID, "wdir", &windDirIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (wdir)", ncResult);
		int windSpeedIndex;
		ncResult = nc_inq_varid(datasetID, "wspeed", &windSpeedIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (wspeed)", ncResult);
		int geopotAltIndex;
		ncResult = nc_inq_varid(datasetID, "geopot", &geopotAltIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (geopot)", ncResult);
		int lonIndex;
		ncResult = nc_inq_varid(datasetID, "lon", &lonIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (lon)", ncResult);
		int latIndex;
		ncResult = nc_inq_varid(datasetID, "lat", &latIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (lat)", ncResult);
		int gpsAltIndex;
		ncResult = nc_inq_varid(datasetID, "alt", &gpsAltIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (alt)", ncResult);
		int vaisFPIndex;
		ncResult = nc_inq_varid(datasetID, "FP", &vaisFPIndex);
		if (ncResult != NC_NOERR) HandleNCError("nc_inq_varid (FP)", ncResult);
		
		for (i = 0; i < dimLength; i++)
		{
			if (variableDataList[timeIndex]->type != NC_FLOAT) 
			{
				printf("Invalid NetCDF type for outputting to flt.dat: %d\r\n", variableDataList[timeIndex]->type);
			}
			fprintf(fltFile, "%10.5f,%10.2f,%10.4f,%10.2f,%10.2f,%10.2f,%10.5f,%10.5f,%10.4f,%10.2f,%10.2f,%10d\r\n", 
				((float*)variableDataList[timeIndex]->data)[i] / 60.0, ((float*)variableDataList[pressureIndex]->data)[i], ((float*)variableDataList[geopotAltIndex]->data)[i] / 1000,
				((float*)variableDataList[temperatureIndex]->data)[i] - 273.15, ((float*)variableDataList[vaisRHIndex]->data)[i]*100, ((float*)variableDataList[vaisFPIndex]->data)[i] - 273.15,
				((float*)variableDataList[latIndex]->data)[i], ((float*)variableDataList[lonIndex]->data)[i], ((float*)variableDataList[gpsAltIndex]->data)[i]/1000, ((float*)variableDataList[windSpeedIndex]->data)[i], ((float*)variableDataList[windDirIndex]->data)[i], 1);
		}
		
		/*
		//output variable data to the flt.dat file
		for (i=0; i<dimLength; i++)
		{
			for (j=0; j<numVars; j++)
			{
				VariableData *variableData = variableDataList[j];
				//write data in the correct format for the variable's type
				switch (variableData->type)
				{
					case NC_BYTE:
					{
						unsigned char *byteList = (unsigned char *)variableData->data;
						fprintf(fltFile, "%u", byteList[i]);
						break;
					}
					case NC_CHAR:
					{
						char *byteList = (char *)variableData->data;
						fprintf(fltFile, "%c", byteList[i]);
						break;
					}
					case NC_SHORT:
					{
						short *byteList = (short *)variableData->data;
						fprintf(fltFile, "%d", byteList[i]);
						break;
					}
					case NC_INT:
					{
						int *byteList = (int *)variableData->data;
						fprintf(fltFile, "%d", byteList[i]);
						break;
					}
					case NC_FLOAT:
					{
						float *byteList = (float *)variableData->data;
						fprintf(fltFile, "%f", byteList[i]);
						break;
					}
					case NC_DOUBLE:
					{
						double *byteList = (double *)variableData->data;
						fprintf(fltFile, "%f", byteList[i]);
						break;
					}
					default:
						break;
				}
				
				if (j != (numVars-1)) fprintf(fltFile, ", ");
			}
			fprintf(fltFile, "\r\n");
		}*/
		
		//free up heap memory
		/*for (i=0; i<numVars; i++)
		{
			free(standardNameList[i]);
		}
		free(standardNameList);
		for (i=0; i<numVars; i++)
		{
			free(longNameList[i]);
		}
		free(longNameList);
		for (i=0; i<numVars; i++)
		{
			free(unitStringList[i]);
		}
		free(unitStringList);*/
		for (i=0; i<numVars; i++)
		{
			free(variableDataList[i]->data);
		}
		free(variableDataList);
		free(fltDatFilename);
		
		//close the flt.dat file
		fclose(fltFile);
		
		//close the NetCDF file
		ncResult = nc_close(datasetID);
		if (ncResult != NC_NOERR) HandleNCError("nc_close", ncResult);
		
		printf("\r\n");
		
	}//end of input file for loop
	
	/*DIR *dp;
	struct dirent *ep;
	dp = opendir ("./");

	if (dp != NULL)
	{
		while (ep = readdir (dp))
			puts (ep->d_name);
		
		(void) closedir (dp);
	}
	else
	perror ("Couldn't open the directory");*/

	return 0;
}
Example #13
0
int ex_get_variable_names (int   exoid,
                           ex_entity_type obj_type,
                           int   num_vars,
                           char *var_names[])
{
  int i, varid, status;
  char errmsg[MAX_ERR_LENGTH];
  const char* vvarname;

  exerrval = 0; /* clear error code */

  switch (obj_type) {
  case EX_NODAL:
    vvarname = VAR_NAME_NOD_VAR;
    break;
  case EX_EDGE_BLOCK:
    vvarname = VAR_NAME_EDG_VAR;
    break;
  case EX_FACE_BLOCK:
    vvarname = VAR_NAME_FAC_VAR;
    break;
  case EX_ELEM_BLOCK:
    vvarname = VAR_NAME_ELE_VAR;
    break;
  case EX_NODE_SET:
    vvarname = VAR_NAME_NSET_VAR;
    break;
  case EX_EDGE_SET:
    vvarname = VAR_NAME_ESET_VAR;
    break;
  case EX_FACE_SET:
    vvarname = VAR_NAME_FSET_VAR;
    break;
  case EX_SIDE_SET:
    vvarname = VAR_NAME_SSET_VAR;
    break;
  case EX_ELEM_SET:
    vvarname = VAR_NAME_ELSET_VAR;
    break;
  case EX_GLOBAL:
    vvarname = VAR_NAME_GLO_VAR;
    break;
  default:
    exerrval = EX_BADPARAM;
    sprintf(errmsg,
      "Warning: invalid variable type %d requested from file id %d",
            obj_type, exoid);
    ex_err("ex_get_var_param",errmsg,exerrval);
    return (EX_WARN);
  }

  /* inquire previously defined variables  */
  if ((status = nc_inq_varid(exoid, vvarname, &varid)) != NC_NOERR) {
    exerrval = status;
    sprintf(errmsg, "Warning: no %s variables names stored in file id %d",
            ex_name_of_object(obj_type),exoid);
    ex_err("ex_get_variable_names",errmsg,exerrval);
    return (EX_WARN);
  }

  /* read the variable names */

  /*
   * See if reading into contiguous memory in which case we can load 
   * all values in one call.  If not, we must load each name individually.
   */
  if ((size_t)(&var_names[num_vars-1][0] - &var_names[0][0]) ==
      sizeof(char)*(MAX_STR_LENGTH+1)*(num_vars-1)) {
    status = nc_get_var_text(exoid, varid, &var_names[0][0]);
    if (status != NC_NOERR) {
      exerrval = status;
      sprintf(errmsg,
              "Error: failed to get results variable names from file id %d", exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_FATAL);
    }
  } else {
    for (i=0; i<num_vars; i++) {
      size_t start[2];
      size_t count[2];
      start[0] = i;  count[0] = 1;
      start[1] = 0;  count[1] = MAX_STR_LENGTH+1;
      status = nc_get_vara_text(exoid, varid, start, count, var_names[i]);
      if (status != NC_NOERR) {
        exerrval = status;
        sprintf(errmsg,
                "Error: failed to get results variable names from file id %d", exoid);
        ex_err("ex_get_var_names",errmsg,exerrval);
        return (EX_FATAL);
      }
    }
  }
  return (EX_NOERR);
}
Example #14
0
int ex_get_var_names (int   exoid,
                      const char *var_type,
                      int   num_vars,
                      char *var_names[])
{
  int i, varid, status;
  char errmsg[MAX_ERR_LENGTH];

  exerrval = 0; /* clear error code */

  /* inquire previously defined variables  */
  if (*var_type == 'g' || *var_type == 'G') {
    if ((varid = ncvarid (exoid, VAR_NAME_GLO_VAR)) == -1) {
      exerrval = ncerr;
      sprintf(errmsg,
              "Warning: no global variables names stored in file id %d", exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_WARN);
    }
  }

  else if (*var_type == 'n' || *var_type == 'N') {
    if ((varid = ncvarid (exoid, VAR_NAME_NOD_VAR)) == -1) {
      exerrval = ncerr;
      sprintf(errmsg,
              "Warning: no nodal variable names stored in file id %d",
              exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_WARN);
    }

  }

  else if (*var_type == 'e' || *var_type == 'E') {

    if ((varid = ncvarid (exoid, VAR_NAME_ELE_VAR)) == -1) {
      exerrval = ncerr;
      sprintf(errmsg,
              "Warning: no element variable names stored in file id %d",
              exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_WARN);
    }
  }

  else if (*var_type == 'm' || *var_type == 'M') {

    if ((varid = ncvarid (exoid, VAR_NAME_NSET_VAR)) == -1) {
      exerrval = ncerr;
      sprintf(errmsg,
              "Warning: no nodset variable names stored in file id %d",
              exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_WARN);
    }
  }

  else if (*var_type == 's' || *var_type == 'S') {

    if ((varid = ncvarid (exoid, VAR_NAME_SSET_VAR)) == -1) {
      exerrval = ncerr;
      sprintf(errmsg,
              "Warning: no sideset variable names stored in file id %d",
              exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_WARN);
    }
  }

  else       /* invalid variable type */
    {
      exerrval = EX_BADPARAM;
      sprintf(errmsg,
              "Error: Invalid variable type %c specified in file id %d",
              *var_type, exoid);
      ex_err("ex_put_var_names",errmsg,exerrval);
      return (EX_WARN);
    }


  /* read the variable names */

  /*
   * See if reading into contiguous memory in which case we can load 
   * all values in one call.  If not, we must load each name individually.
   */
  if (&var_names[num_vars-1][0] - &var_names[0][0] ==
      sizeof(char)*(MAX_STR_LENGTH+1)*(num_vars-1)) {
    status = nc_get_var_text(exoid, varid, &var_names[0][0]);
    if (status == -1) {
      exerrval = ncerr;
      sprintf(errmsg,
              "Error: failed to get results variable names from file id %d", exoid);
      ex_err("ex_get_var_names",errmsg,exerrval);
      return (EX_FATAL);
    }
  } else {
    for (i=0; i<num_vars; i++) {
      size_t start[2];
      size_t count[2];
      start[0] = i;  count[0] = 1;
      start[1] = 0;  count[1] = MAX_STR_LENGTH+1;
      status = nc_get_vara_text(exoid, varid, start, count, var_names[i]);
      if (status == -1) {
        exerrval = ncerr;
        sprintf(errmsg,
                "Error: failed to get results variable names from file id %d", exoid);
        ex_err("ex_get_var_names",errmsg,exerrval);
        return (EX_FATAL);
      }
    }
  }
  return (EX_NOERR);
}
Example #15
0
int
main(int argc, char **argv) 
{			/* create tst_classic_fills.nc */
   printf("\n*** Testing fill values.\n");
   printf("*** testing empty fill values of a string var...");
   {
#define STRING_VAR_NAME "The_String"
#define NDIMS_STRING 1
#define FILLVALUE_LEN 1 /* There is 1 string, the empty one. */
#define DATA_START 2 /* Real data here. */

      int  ncid, varid, dimid, varid_in;
      const char *missing_val[FILLVALUE_LEN] = {""};
      const char *missing_val_in[FILLVALUE_LEN];
      const char *data_out[1] = {"The evil that men do lives after them; "
				 "the good is oft interred with their bones."};
      char **data_in;
      size_t index = DATA_START;
      int i;

      /* Create file with a 1D string var. Set its fill value to the
       * empty string. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, "rec", NC_UNLIMITED, &dimid)) ERR;
      if (nc_def_var(ncid, STRING_VAR_NAME, NC_STRING, NDIMS_STRING, &dimid, &varid)) ERR;
      if (nc_put_att_string(ncid, varid, "_FillValue", FILLVALUE_LEN, missing_val)) ERR;

      /* Check it out. */
      if (nc_inq_varid(ncid, STRING_VAR_NAME, &varid_in)) ERR;
      if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR;
      if (strcmp(missing_val[0], missing_val_in[0])) ERR;
      if (nc_free_string(FILLVALUE_LEN, (char **)missing_val_in)) ERR;

      /* Write one string, leaving some blank records which will then
       * get the fill value. */
      if (nc_put_var1_string(ncid, varid_in, &index, data_out)) ERR;

      /* Get all the data from the variable. */
      if (!(data_in = malloc((DATA_START + 1) * sizeof(char *)))) ERR;
      if (nc_get_var_string(ncid, varid_in, data_in)) ERR;

      /* First there should be fill values, then the data value we
       * wrote. */
      for (i = 0; i < DATA_START; i++)
	 if (strcmp(data_in[i], "")) ERR;
      if (strcmp(data_in[DATA_START], data_out[0])) ERR;

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

      /* Now re-open file, read data, and check values again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_varid(ncid, STRING_VAR_NAME, &varid_in)) ERR;
      if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR;
      if (strcmp(missing_val[0], missing_val_in[0])) ERR;
      if (nc_free_string(FILLVALUE_LEN, (char **)missing_val_in)) ERR;
      if (nc_close(ncid)) ERR;
      free(data_in);
   }

   SUMMARIZE_ERR;
   printf("*** testing non-empty fill values of a string var...");
   {
#define STRING_VAR_NAME2 "CASSIUS"
#define FILLVALUE_LEN2 1 /* There is 1 string in the fillvalue array. */
#define DATA_START2 9 /* Real data starts here. */

      int  ncid, varid, dimid, varid_in;
      const char *missing_val[FILLVALUE_LEN2] = {"I know that virtue to be in you, Brutus"};
      const char *missing_val_in[FILLVALUE_LEN2];
      const char *data_out[1] = {"The evil that men do lives after them; "
				 "the good is oft interred with their bones."};
      char **data_in;
      size_t index = DATA_START2;
      int i;

      /* Create file with a 1D string var. Set its fill value to the
       * a non-empty string. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, "rec", NC_UNLIMITED, &dimid)) ERR;
      if (nc_def_var(ncid, STRING_VAR_NAME2, NC_STRING, NDIMS_STRING, &dimid, &varid)) ERR;
      if (nc_put_att_string(ncid, varid, "_FillValue", FILLVALUE_LEN2, missing_val)) ERR;

      /* Check it out. */
      if (nc_inq_varid(ncid, STRING_VAR_NAME2, &varid_in)) ERR;
      if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR;
      if (strcmp(missing_val[0], missing_val_in[0])) ERR;
      if (nc_free_string(FILLVALUE_LEN2, (char **)missing_val_in)) ERR;

      /* Write one string, leaving some blank records which will then
       * get the fill value. */
      if (nc_put_var1_string(ncid, varid_in, &index, data_out)) ERR;

      /* Get all the data from the variable. */
      if (!(data_in = malloc((DATA_START2 + 1) * sizeof(char *)))) ERR;
      if (nc_get_var_string(ncid, varid_in, data_in)) ERR;

      /* First there should be fill values, then the data value we
       * wrote. */
      for (i = 0; i < DATA_START2; i++)
	 if (strcmp(data_in[i], missing_val[0])) ERR;
      if (strcmp(data_in[DATA_START2], data_out[0])) ERR;

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

      /* Now re-open file, read data, and check values again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;
      if (nc_inq_varid(ncid, STRING_VAR_NAME2, &varid_in)) ERR;
      if (nc_get_att_string(ncid, varid_in, "_FillValue", (char **)missing_val_in)) ERR;
      if (strcmp(missing_val[0], missing_val_in[0])) ERR;
      if (nc_free_string(FILLVALUE_LEN2, (char **)missing_val_in)) ERR;
      if (nc_close(ncid)) ERR;
      free(data_in);
   }

   SUMMARIZE_ERR;
   printf("*** testing fill values of one var...");
   {
#define V1_NAME "v1"
#define MAX_VALS 10
      int  ncid, varid, rec_id, dims[2];
      static int rec[1] = {1};
      size_t start[2] = {0, 0};
      size_t count[2] = {1, MAX_VALS};
      char vals[MAX_VALS];
      int i;

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

      /* Define dimensions and two vars, a 1D coordinate var for
       * unlimited dimension, and a 2D var which uses the unlimited
       * dimension. */
      if (nc_def_dim(ncid, "rec", NC_UNLIMITED, &dims[0])) ERR;
      if (nc_def_dim(ncid, "len", MAX_VALS, &dims[1])) ERR;
      if (nc_def_var(ncid, "rec", NC_INT, 1, dims, &rec_id)) ERR;
      if (nc_def_var(ncid, V1_NAME, NC_CHAR, 2, dims, &varid)) ERR;

      /* Extend record dimension by 1. */
      if (nc_put_vara_int(ncid, rec_id, start, count, rec)) ERR;

      /* Read the other variable; it must have only fill values. */
      if (nc_get_vara_text(ncid, 1, start, count, vals)) ERR;
      for (i = 0; i < MAX_VALS; i++)
	 if(vals[i] != NC_FILL_CHAR) ERR;

      if (nc_close(ncid)) ERR;

      /* Now re-open file, read data, and check values again. */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

      /* Read the other variable; it must have only fill values. */
      if (nc_get_vara_text(ncid, 1, start, count, vals)) ERR;
      for (i = 0; i < MAX_VALS; i++)
	 if(vals[i] != NC_FILL_CHAR) ERR;

      if(nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing fill values of lots of vars...");

   {
      int  ncid;			/* netCDF id */

#define NVALS 10		/* values per fixed-size variable or record */
#define NFIXVARS 6		/* number of fixed-size vars, one of each type */
#define NRECVARS 6		/* number of record vars, one of each type */
#define RANK_REC 1
#define RANK_FIXVARS 1
#define RANK_RECVARS 2

      /* dimension ids */
      int rec_dim;
      int len_dim;

      /* dimension lengths */
      size_t rec_len = NC_UNLIMITED;
      size_t len_len = NVALS;

      /* variable ids */
      int rec_id;
      int fixvar_ids[NFIXVARS];
      int recvar_ids[NRECVARS];
      int rec_dims[RANK_REC];
      int fixvar_dims[RANK_FIXVARS];
      int recvar_dims[RANK_RECVARS];
      int fixvar, recvar, i;

      char *fnames[] = {"c", "b", "s", "i", "f", "d"};
      char *rnames[] = {"cr", "br", "sr", "ir", "fr", "dr"};
      nc_type types[] = {NC_CHAR, NC_BYTE, NC_SHORT, NC_INT, NC_FLOAT, NC_DOUBLE};

      /*if (nc_set_default_format(format + 1, NULL)) ERR;*/
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;

      /* define dimensions */
      if (nc_def_dim(ncid, "rec", rec_len, &rec_dim)) ERR;
      if (nc_def_dim(ncid, "len", len_len, &len_dim)) ERR;

      rec_dims[0] = rec_dim;
      if (nc_def_var(ncid, "rec", NC_INT, RANK_REC, rec_dims, &rec_id)) ERR;

      /* define fixed and record variables of all 6 primitive types */
      fixvar_dims[0] = len_dim;
      for (fixvar = 0; fixvar < NFIXVARS; fixvar++)
	 if (nc_def_var(ncid, fnames[fixvar], types[fixvar], RANK_FIXVARS,
			fixvar_dims, &fixvar_ids[fixvar])) ERR;

      recvar_dims[0] = rec_dim;
      recvar_dims[1] = len_dim;
      for (recvar = 0; recvar < NRECVARS; recvar++)
	 if (nc_def_var(ncid, rnames[recvar], types[recvar], RANK_RECVARS,
			recvar_dims, &recvar_ids[recvar])) ERR;

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

      {			/* store rec */
	 static size_t rec_start[RANK_REC];
	 static size_t rec_count[RANK_REC];
	 static int rec[] = {1};
	 rec_len = 1;			/* number of records of rec data */
	 rec_start[0] = 0;
	 rec_count[0] = rec_len;
	 if (nc_put_vara_int(ncid, rec_id, rec_start, rec_count, rec)) ERR;
      }
      if (nc_close(ncid)) ERR;

      /* Now re-open file, read data, and check values */
      if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR;

      /* Check that fixed-size variables are full of fill values */
      for (fixvar = 0; fixvar < NFIXVARS; fixvar++) {
	 int varid;
	 nc_type type;

	 if (nc_inq_varid(ncid, fnames[fixvar], &varid)) ERR;
	 if (nc_inq_vartype(ncid, varid, &type)) ERR;
	 switch(type) {
	    case NC_CHAR:
	    {
	       char vals[NVALS];
	       if (nc_get_var_text(ncid, varid, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_CHAR) ERR;
	    }
	    break;
	    case NC_BYTE:
	    {
	       signed char vals[NVALS];
	       if (nc_get_var_schar(ncid, varid, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_BYTE) ERR;
	    }
	    break;
	    case NC_SHORT:
	    {
	       short vals[NVALS];
	       if (nc_get_var_short(ncid, varid, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_SHORT) ERR;
	    }
	    break;
	    case NC_INT:
	    {
	       int vals[NVALS];
	       if (nc_get_var_int(ncid, varid, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_INT) ERR;
	    }
	    break;
	    case NC_FLOAT:
	    {
	       float vals[NVALS];
	       if (nc_get_var_float(ncid, varid, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_FLOAT) ERR;
	    }
	    break;
	    case NC_DOUBLE:
	    {
	       double vals[NVALS];
	       if (nc_get_var_double(ncid, varid, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if (vals[i] != NC_FILL_DOUBLE) ERR;
	    }
	    break;
	    default:
	       ERR;
	 }
      }

      /* Read record, check record variables have only fill values */
      for (recvar = 0; recvar < NRECVARS; recvar++) {
	 int varid;
	 nc_type type;
	 size_t start[] = {0, 0};
	 size_t count[] = {1, NVALS};

	 if (nc_inq_varid(ncid, rnames[recvar], &varid)) ERR;
	 if (nc_inq_vartype(ncid, varid, &type)) ERR;
	 switch(type) {
	    case NC_CHAR:
	    {
	       char vals[NVALS];
	       if (nc_get_vara_text(ncid, varid, start, count, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_CHAR) ERR;
	    }
	    break;
	    case NC_BYTE:
	    {
	       signed char vals[NVALS];
	       if (nc_get_vara_schar(ncid, varid, start, count, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_BYTE) ERR;
	    }
	    break;
	    case NC_SHORT:
	    {
	       short vals[NVALS];
	       if (nc_get_vara_short(ncid, varid, start, count, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_SHORT) ERR;
	    }
	    break;
	    case NC_INT:
	    {
	       int vals[NVALS];
	       if (nc_get_vara_int(ncid, varid, start, count, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_INT) ERR;
	    }
	    break;
	    case NC_FLOAT:
	    {
	       float vals[NVALS];
	       if (nc_get_vara_float(ncid, varid, start, count, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_FLOAT) ERR;
	    }
	    break;
	    case NC_DOUBLE:
	    {
	       double vals[NVALS];
	       if (nc_get_vara_double(ncid, varid, start, count, vals)) ERR;
	       for (i = 0; i < NVALS; i++)
		  if(vals[i] != NC_FILL_DOUBLE) ERR;
	    }
	    break;
	    default:
	       ERR;
	 }
      }

      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   FINAL_RESULTS;

   return 0;
}