int ex_get_partial_one_attr( int   exoid,
		       ex_entity_type obj_type,
		       ex_entity_id   obj_id,
		       int64_t   start_num,
		       int64_t   num_ent,
		       int   attrib_index,
		       void* attrib )

{
  int status;
  int attrid, obj_id_ndx;
  int temp;
  size_t num_entries_this_obj, num_attr;
  size_t start[2], count[2];
  ptrdiff_t stride[2];
  char errmsg[MAX_ERR_LENGTH];
  const char* dnumobjent;
  const char* dnumobjatt;
  const char* vattrbname;

  exerrval = 0; /* clear error code */

  if (num_ent == 0)
    return 0;
  /* Determine index of obj_id in vobjids array */
  if (obj_type != EX_NODAL) {
    obj_id_ndx = ex_id_lkup(exoid,obj_type,obj_id);
    if (exerrval != 0) {
      if (exerrval == EX_NULLENTITY) {
	sprintf(errmsg,
		"Warning: no attributes found for NULL %s %"PRId64" in file id %d",
		ex_name_of_object(obj_type),obj_id,exoid);
	ex_err("ex_get_partial_one_attr",errmsg,EX_NULLENTITY);
	return (EX_WARN);              /* no attributes for this object */
      } else {
	sprintf(errmsg,
		"Warning: failed to locate %s id%"PRId64" in id array in file id %d",
		ex_name_of_object(obj_type),obj_id, exoid);
	ex_err("ex_get_partial_one_attr",errmsg,exerrval);
	return (EX_WARN);
      }
    }
  }

  switch (obj_type) {
  case EX_SIDE_SET:
    dnumobjent = DIM_NUM_SIDE_SS(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_SS(obj_id_ndx);
    vattrbname = VAR_SSATTRIB(obj_id_ndx);
    break;
  case EX_NODE_SET:
    dnumobjent = DIM_NUM_NOD_NS(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_NS(obj_id_ndx);
    vattrbname = VAR_NSATTRIB(obj_id_ndx);
    break;
  case EX_EDGE_SET:
    dnumobjent = DIM_NUM_EDGE_ES(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_ES(obj_id_ndx);
    vattrbname = VAR_ESATTRIB(obj_id_ndx);
    break;
  case EX_FACE_SET:
    dnumobjent = DIM_NUM_FACE_FS(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_FS(obj_id_ndx);
    vattrbname = VAR_FSATTRIB(obj_id_ndx);
    break;
  case EX_ELEM_SET:
    dnumobjent = DIM_NUM_ELE_ELS(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_ELS(obj_id_ndx);
    vattrbname = VAR_ELSATTRIB(obj_id_ndx);
    break;
  case EX_NODAL:
    dnumobjent = DIM_NUM_NODES;
    dnumobjatt = DIM_NUM_ATT_IN_NBLK;
    vattrbname = VAR_NATTRIB;
    break;
  case EX_EDGE_BLOCK:
    dnumobjent = DIM_NUM_ED_IN_EBLK(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_EBLK(obj_id_ndx);
    vattrbname = VAR_EATTRIB(obj_id_ndx);
    break;
  case EX_FACE_BLOCK:
    dnumobjent = DIM_NUM_FA_IN_FBLK(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_FBLK(obj_id_ndx);
    vattrbname = VAR_FATTRIB(obj_id_ndx);
    break;
  case EX_ELEM_BLOCK:
    dnumobjent = DIM_NUM_EL_IN_BLK(obj_id_ndx);
    dnumobjatt = DIM_NUM_ATT_IN_BLK(obj_id_ndx);
    vattrbname = VAR_ATTRIB(obj_id_ndx);
    break;
  default:
    exerrval = 1005;
    sprintf(errmsg,
	    "Internal Error: unrecognized object type in switch: %d in file id %d",
	    obj_type,exoid);
    ex_err("ex_get_partial_one_attr",errmsg,EX_MSG);
    return (EX_FATAL);              /* number of attributes not defined */
  }

  /* inquire id's of previously defined dimensions  */
  if (ex_get_dimension(exoid, dnumobjent,"entries", &num_entries_this_obj, &temp, "ex_get_partial_one_attr") != NC_NOERR)
    return EX_FATAL;
  
  if (start_num + num_ent -1 > num_entries_this_obj) {
    exerrval = EX_BADPARAM;
    sprintf(errmsg,
	    "Error: start index (%"PRId64") + count (%"PRId64") is larger than total number of entities (%"ST_ZU") in file id %d",
	    start_num, num_ent, num_entries_this_obj, exoid);
    ex_err("ex_get_partial_one_attr",errmsg,exerrval);
    return (EX_FATAL);
  }
  
  if (ex_get_dimension(exoid, dnumobjatt,"attributes", &num_attr, &temp, "ex_get_partial_one_attr") != NC_NOERR)
    return EX_FATAL;

  if (attrib_index < 1 || attrib_index > (int)num_attr) {
    exerrval = EX_FATAL;
    sprintf(errmsg,
            "Error: Invalid attribute index specified: %d.  Valid range is 1 to %d for %s %"PRId64" in file id %d",
            attrib_index, (int)num_attr, ex_name_of_object(obj_type), obj_id, exoid);
    ex_err("ex_get_partial_one_attr",errmsg,exerrval);
    return (EX_FATAL);
  }

  if ((status = nc_inq_varid(exoid, vattrbname, &attrid)) != NC_NOERR) {
    exerrval = status;
    sprintf(errmsg,
	    "Error: failed to locate attributes for %s %"PRId64" in file id %d",
	    ex_name_of_object(obj_type),obj_id,exoid);
    ex_err("ex_get_partial_one_attr",errmsg,exerrval);
    return (EX_FATAL);
  }

    
  /* read in the attributes */
  start[0] = start_num-1;
  start[1] = attrib_index-1;

  count[0] = num_ent;
  count[1] = 1;

  stride[0] = 1;
  stride[1] = num_attr;
  
  if (ex_comp_ws(exoid) == 4) {
    status = nc_get_vars_float(exoid, attrid, start, count, stride, attrib);
  } else {
    status = nc_get_vars_double(exoid, attrid, start, count, stride, attrib);
  }

  if (status != NC_NOERR) {
    exerrval = status;
    sprintf(errmsg,
            "Error: failed to get attribute %d for %s %"PRId64" in file id %d",
            attrib_index, ex_name_of_object(obj_type), obj_id,exoid);
    ex_err("ex_get_partial_one_attr",errmsg,exerrval);
    return (EX_FATAL);
  }
  return(EX_NOERR);
}
int
main()
{

    int ncid;
    int varid;
    int i;
    int ncstatus;
    size_t start[5], count[5];
    ptrdiff_t stride[5];
    int pass = 1;
    int nelems = XSIZE*YSIZE;
    int idim, ndim;
    float *dat = (float*)malloc(sizeof(float)*nelems);
    float sdat[10];
    char* svc;

    /* Find Test Server */
    svc = getenv("THREDDSTESTSERVER");
    if(svc != NULL) {
        const char* testserver[2];
	testserver[0] = svc;
	testserver[1] = NULL;
        svc = NC_findtestserver("thredds",testserver);
    } else 	
        svc = NC_findtestserver("thredds",NULL);

    if(svc == NULL) {
        fprintf(stderr,"Cannot locate test server\n");
	exit(0);
    }

    strcpy(url,URL);
    snprintf(url,sizeof(url),URL,svc);

    for (idim=0; idim<5; idim++) {
        start[idim] = 0;
        count[idim] = 1;
        stride[idim] = 1;
    }

    ndim=2;

    printf(" \n");
    printf("********************\n");
    printf("open URL %s\n",url);
    printf(" \n");

    ncstatus = nc_open(url, NC_NOWRITE, &ncid);

    if(ncstatus != NC_NOERR) {
	fprintf(stderr,"Could not open: %s; server may be down; test ignored\n",url);
	exit(0);
    }

    ncstatus = nc_inq_varid(ncid, VAR1, &varid);

    ndim=2;


#ifdef VERBOSE
    printf(" \n");
    printf("********************\n");
    printf("Read %s data w/o strides\n",VAR1);
    printf(" \n");
#endif

    start[0] = 0;
    start[1] = 0;
    start[2] = 0;
    start[3] = 0;

    count[0] =  XSIZE;
    count[1] =  YSIZE;

    stride[0] = 1;
    stride[1] = 1;

#ifdef VERBOSE
    for (idim=0; idim<ndim; idim++)
	printf("start[%1d]=%3lu count[%1d]=%3lu stride[%1d]=%3lu\n",
		idim,start[idim],idim,count[idim],idim,stride[idim]);
#endif

    ncstatus = nc_get_vars_float (ncid, varid, start, count, stride, (float*) dat);

#ifdef VERBOSE
    printf(" \n");
    printf("********************\n");
    printf("Print some of %s\n",VAR1);
    printf(" \n");

    for (i=0; i<10; i++)
        printf("%s[%d] = %f\n",VAR1,i,dat[i]);
    printf(" \n");


    for (i=(nelems-11); i<(nelems-1); i++)
        printf("%s[%d] = %f\n",VAR1,i,dat[i]);
    printf(" \n");
#endif

    memset((void*)dat,0,sizeof(dat));

    /* Read a second variable */

    ncstatus = nc_inq_varid(ncid, VAR2, &varid);

    ndim=2;

#ifdef VERBOSE
    printf(" \n");
    printf("********************\n");
    printf("Read %s data w/o strides\n",VAR2);
    printf(" \n");
#endif

    start[0] = 0;
    start[1] = 0;
    start[2] = 0;
    start[3] = 0;

    count[0] =  XSIZE;
    count[1] =  YSIZE;

    stride[0] = 1;
    stride[1] = 1;

#ifdef VERBOSE
    for (idim=0; idim<ndim; idim++)
        printf("start[%d]=%3lu count[%d]=%3lu stride[%d]=%3lu\n",
		idim, start[idim], idim, count[idim], idim, stride[idim]);
#endif

    ncstatus = nc_get_vars_float (ncid, varid, start, count, stride, (float*) dat);

#ifdef VERBOSE
    printf(" \n");
    printf("********************\n");
    printf("Print some of %s\n",VAR2);
    printf(" \n");
    for (i=0; i<10; i++)
        printf("%s[%d] = %f\n",VAR2,i,dat[i]);
    printf(" \n");

    printf(" \n");
    for (i=(nelems-11); i<(nelems-1); i++)
        printf("%s[%d] = %f\n",VAR2,i,dat[i]);
    printf(" \n");
#endif

    memset((void*)dat,0,sizeof(dat));

    /* close and reopen the dataset, then the below read is correct */

#ifdef VERBOSE
    printf(" \n");
    printf("********************\n");
    printf("Close and reopen the dataset\n");
#endif

    ncstatus = nc_close (ncid);
    ncstatus = nc_open(url, NC_NOWRITE, &ncid);

    /*  ----------------------------------------------------- */
    /* Read a subset of the data with strides */

    ncstatus = nc_inq_varid(ncid, VAR1, &varid);

#ifdef VERBOSE
    printf(" \n");
    printf("********************\n");
    printf("Read a subset of %s data with strides\n",VAR1);
    printf(" \n");
#endif

    start[0] = 250;
    start[1] = 704;

    count[0] =  5;
    count[1] =  2;

    stride[0] = 2;
    stride[1] = 4;

#ifdef VERBOSE
    for (idim=0; idim<ndim; idim++)
	printf("start[%1d]=%3lu count[%1d]=%3lu stride[%1d]=%3lu\n",
		idim,start[idim],idim,count[idim],idim,stride[idim]);
#endif

    memset((void*)sdat,0,sizeof(sdat));
    ncstatus = nc_get_vars_float (ncid, varid, start, count, stride,  (float*) sdat);

    printf("status = %d\n", ncstatus);

    /* Verify that all read values are 50 <= n < 51 */
    for (i=0; i<10; i++) {
	if(sdat[i] <= 50.0 || sdat[i] > 51.0) {
	    printf("Out of range: %s[%d] = %f\n",VAR1, i,sdat[i]);
	    pass = 0;
	}
    }

#ifdef VERBOSE
    printf(" \n");
    printf("********************\n");
    printf("Print  values read. They should all be 50.xxxx \n");
    printf(" \n");

    for (i=0; i<10; i++)
        printf("%s[%d] = %f\n",VAR1,i,sdat[i]);
#endif

    ncstatus = nc_close (ncid);

    if(!pass) {
	printf("*** FAIL: %s value out of range.\n",VAR1);
	exit(1);
    }

    printf("*** PASS\n");
    free(dat);
    exit(0);

}
int
main()
{

    int ncid;
    int varid;
    int i,fail;
    int err;
    size_t start[5], count[5];
    ptrdiff_t stride[5], imap[5];

    int idim, ndim;  
    float dat[20];

#ifdef DEBUG
    oc_loginit();
    oc_setlogging(1);
    oc_logopen(NULL);
#endif

    printf("*** Test: varm on URL: %s\n",URL);

    check(err = nc_open(URL, NC_NOWRITE, &ncid),__FILE__,__LINE__);
    check(err = nc_inq_varid(ncid, VAR, &varid),__FILE__,__LINE__);
    for (idim=0; idim<4; idim++) {
        start[idim] = 0;
        count[idim] = 1;
        stride[idim] = 1;
        imap[idim] = 1;
    }
    ndim=3;


    printf("*** Testing: stride case 1\n");
    start[1] = 44;
    start[2] = 66;
    count[0] = 12;

#ifdef STANDALONE
    printf("start = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)start[i]);
    printf("\n");
    printf("count = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)count[i]);
    printf("\n");
    printf("stride = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)stride[i]);
    printf("\n");
    printf("map = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)imap[i]);
    printf("\n");

    err = nc_get_vars_float (ncid, varid, start, count, stride,
			     (float*) dat);
    printf("vars: %s =",VAR);
    for(i=0;i<12;i++) printf(" %f",dat[i]);
    printf("\n");
#endif

    check(err = nc_get_varm_float (ncid, varid, start, count, stride, imap,
			     (float*) dat),__FILE__,__LINE__);
#ifdef STANDALONE
    printf("varm: %s =",VAR);
    for(i=0;i<12;i++) printf(" %f",dat[i]);
    printf("\n");
#endif
    fail=0;
    for(i=0;i<12;i++) {
	float delta = (dat[i] - expected_stride1[i]);
	if(delta > 0.0005 || delta < -0.0005) {
	    fprintf(stderr,"*** Failure: unexpected value: delta=%g dat[%d]=%g expected[%d]=%g\n",
		    delta, i, dat[i], i, expected_stride1[i]);
	     fail = 1;
	}
    }
    printf("*** %s: stride case 1\n",(fail?"Fail":"Pass"));

    printf("*** Testing: stride case 2\n");
    /* case with strides #1 where len % stride == 0 */
    start[1] = 44;
    start[2] = 66;
    count[0] =  6;
    stride[0] = 2;

#ifdef STANDALONE
    printf("start = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)start[i]);
    printf("\n");
    printf("count = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)count[i]);
    printf("\n");
    printf("stride = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)stride[i]);
    printf("\n");
    printf("map = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)imap[i]);
    printf("\n");

    check(err = nc_get_vars_float(ncid, varid, start, count, stride, 
                             (float*) dat),__FILE__,__LINE__);
    printf("strided.vars: %s =",VAR);
    for(i=0;i<6;i++) printf(" %f",dat[i]);
    printf("\n");
#endif
    check(err = nc_get_varm_float(ncid, varid, start, count, stride, imap,
                             (float*) dat),__FILE__,__LINE__);
#ifdef STANDALONE
    printf("strided.varm: %s =",VAR);
    for(i=0;i<6;i++) printf(" %f",dat[i]);
    printf("\n");
#endif
    fail=0;
    for(i=0;i<6;i++) {
	float delta = (dat[i] - expected_stride2[i]);
	if(delta > 0.0005 || delta < -0.0005) {
	    fprintf(stderr,"*** Failure: unexpected value: delta=%g dat[%d]=%g expected[%d]=%g\n",
		    delta, i, dat[i], i, expected_stride2[i]);
	    fail=1;
	}
    }
    printf("*** %s: stride case 2\n",(fail?"Fail":"Pass"));

    /* case with strides #2: len % stride != 0 */
    printf("*** Testing: stride case 3\n");
    start[1] = 44;
    start[2] = 66;
    count[0] =  3;
    stride[0] = 5;

#ifdef STANDALONE
    printf("start = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)start[i]);
    printf("\n");
    printf("count = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)count[i]);
    printf("\n");
    printf("stride = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)stride[i]);
    printf("\n");
    printf("map = ");
    for(i=0;i<ndim;i++) printf(" %d",(int)imap[i]);
    printf("\n");

    check(err = nc_get_vars_float(ncid, varid, start, count, stride, 
                             (float*) dat),__FILE__,__LINE__);
    printf("strided.vars: %s =",VAR);
    for(i=0;i<3;i++) printf(" %f",dat[i]);
    printf("\n");
#endif
    check(err = nc_get_varm_float(ncid, varid, start, count, stride, imap,
                             (float*) dat),__FILE__,__LINE__);
#ifdef STANDALONE
    printf("strided.varm: %s =",VAR);
    for(i=0;i<3;i++) printf(" %f",dat[i]);
    printf("\n");
#endif
    fail=0;
    for(i=0;i<3;i++) {
	float delta = (dat[i] - expected_stride3[i]);
	if(delta > 0.0005 || delta < -0.0005) {
	    fprintf(stderr,"*** Failure: stride case 2: unexpected value: delta=%g dat[%d]=%g expected[%d]=%g\n",
		    delta, i, dat[i], i, expected_stride3[i]);
	    fail=1;
	}
    }
    printf("*** %s: stride case 3\n",(fail?"Fail":"Pass"));

    return fail;

ncfail:
    printf("*** nc function failure: %d %s\n",err,nc_strerror(err));
    return 1;
}
Exemple #4
0
int
nc3d_getvarmx(int ncid, int varid,
	    const size_t *start,
	    const size_t *edges,
	    const ptrdiff_t* stride,
 	    const ptrdiff_t* map,
	    void* data,
	    nc_type dsttype0)
{
    NCerror ncstat = NC_NOERR;
    int i;
    NC* drno;
    NC* substrate;
    NC3_INFO* substrate3;
    NCDAPCOMMON* dapcomm;
    NC_var* var;
    CDFnode* cdfvar; /* cdf node mapping to var*/
    NClist* varnodes;
    nc_type dsttype;
    size_t externsize;
    size_t dimsizes[NC_MAX_VAR_DIMS];
    Dapodometer* odom = NULL;
    unsigned int ncrank;
    NClist* ncdims = NULL;
    size_t nelems;
#ifdef NEWVARM
    char* localcopy; /* of whole variable */
#endif

    ncstat = NC_check_id(ncid, (NC**)&drno);
    if(ncstat != NC_NOERR) goto done;
    dapcomm = (NCDAPCOMMON*)drno->dispatchdata;

    ncstat = NC_check_id(drno->substrate, &substrate);
    if(ncstat != NC_NOERR) goto done;
    substrate3 = (NC3_INFO*)drno->dispatchdata;

    var = NC_lookupvar(substrate3,varid);
    if(var == NULL) {ncstat = NC_ENOTVAR; goto done;}

    /* Locate var node via varid */
    varnodes = dapcomm->cdf.ddsroot->tree->varnodes;
    for(i=0;i<nclistlength(varnodes);i++) {
	CDFnode* node = (CDFnode*)nclistget(varnodes,i);
	if(node->array.basevar == NULL
           && node->nctype == NC_Atomic
           && node->ncid == varid) {
	    cdfvar = node;
	    break;
	}
    }

    ASSERT((cdfvar != NULL));
    ASSERT((strcmp(cdfvar->ncfullname,var->name->cp)==0));

    if(nclistlength(cdfvar->array.dimsetplus) == 0) {
       /* The variable is a scalar; consequently, there is only one
          thing to get and only one place to put it. */
	/* recurse with additional parameters */
        return THROW(nc3d_getvarx(ncid,varid,
		 NULL,NULL,NULL,
		 data,dsttype0));
    }
         
    dsttype = (dsttype0);

    /* Default to using the inquiry type for this var*/
    if(dsttype == NC_NAT) dsttype = cdfvar->externaltype;

    /* Validate any implied type conversion*/
    if(cdfvar->etype != dsttype && dsttype == NC_CHAR) {
	/* The only disallowed conversion is to/from char and non-byte
           numeric types*/
	switch (cdfvar->etype) {
	case NC_STRING: case NC_URL:
	case NC_CHAR: case NC_BYTE: case NC_UBYTE:
 	    break;
	default:
	    return THROW(NC_ECHAR);
	}
    }

    externsize = nctypesizeof(dsttype);

    /* Accumulate the dimension sizes and the total # of elements */
    ncdims = cdfvar->array.dimsetall;
    ncrank = nclistlength(ncdims);

    nelems = 1; /* also Compute the number of elements being retrieved */
    for(i=0;i<ncrank;i++) {
	CDFnode* dim = (CDFnode*)nclistget(ncdims,i);
	dimsizes[i] = dim->dim.declsize;
	nelems *= edges[i];
    }

    /* Originally, this code repeatedly extracted single values
       using get_var1. In an attempt to improve performance,
       I have converted to reading the whole variable at once
       and walking it locally.
    */

#ifdef NEWVARM
    localcopy = (char*)malloc(nelems*externsize);

    /* We need to use the varieties of get_vars in order to
       properly do conversion to the external type
    */

    switch (dsttype) {

    case NC_CHAR:
	ncstat = nc_get_vars_text(ncid,varid,start, edges, stride,
				  (char*)localcopy);
	break;
    case NC_BYTE:
	ncstat = nc_get_vars_schar(ncid,varid,start, edges, stride,
				   (signed char*)localcopy);
	break;
    case NC_SHORT:
	ncstat = nc_get_vars_short(ncid,varid, start, edges, stride,
			  	   (short*)localcopy);
	break;
    case NC_INT:
	ncstat = nc_get_vars_int(ncid,varid,start, edges, stride,
				 (int*)localcopy);
	break;
    case NC_FLOAT:
	ncstat = nc_get_vars_float(ncid,varid,start, edges, stride,
				   (float*)localcopy);
	break;
    case NC_DOUBLE:
	ncstat = nc_get_vars_double(ncid,varid,	start, edges, stride,
		 		    (double*)localcopy);
	break;
    default: break;
    }


    odom = dapodom_new(ncrank,start,edges,stride,NULL);

    /* Walk the local copy */
    for(i=0;i<nelems;i++) {
	size_t voffset = dapodom_varmcount(odom,map,dimsizes);
	void* dataoffset = (void*)(((char*)data) + (externsize*voffset));
	char* localpos = (localcopy + externsize*i);
	/* extract the indexset'th value from local copy */
	memcpy(dataoffset,(void*)localpos,externsize);
/*
fprintf(stderr,"new: %lu -> %lu  %f\n",
	(unsigned long)(i),
        (unsigned long)voffset,
	*(float*)localpos);
*/
	dapodom_next(odom);
    }    
#else
    odom = dapodom_new(ncrank,start,edges,stride,NULL);
    while(dapodom_more(odom)) {
	size_t* indexset = odom->index;
	size_t voffset = dapodom_varmcount(odom,map,dimsizes);
	char internalmem[128];
	char externalmem[128];
	void* dataoffset = (void*)(((char*)data) + (externsize*voffset));

	/* get the indexset'th value using variable's internal type */
	ncstat = nc_get_var1(ncid,varid,indexset,(void*)&internalmem);
        if(ncstat != NC_NOERR) goto done;
	/* Convert to external type */
	ncstat = dapconvert3(cdfvar->etype,dsttype,externalmem,internalmem);
        if(ncstat != NC_NOERR) goto done;
	memcpy(dataoffset,(void*)externalmem,externsize);
/*
fprintf(stderr,"old: %lu -> %lu  %f\n",
	(unsigned long)dapodom_count(odom),
        (unsigned long)voffset,
	*(float*)externalmem);
*/
	dapodom_next(odom);
    }    
#endif

done:
    return ncstat;
}
int
main()
{

    int ncid;
    int varid;
    int i;
    int ncstatus;
    size_t start[5], count[5];
    ptrdiff_t stride[5], tmp_ptrdiff_t;
    int pass = 1;

    int idim, ndim;
    //float dat[301060];
    float *dat = (float*)malloc(sizeof(float)*301060);
    float sdat[10];

    for (idim=0; idim<5; idim++) {
        start[idim] = 0;
        count[idim] = 1;
        stride[idim] = 1;
    }

    ndim=2;

    printf(" \n");
    printf("********************\n");
    printf("open URL %s\n",URL);
    printf(" \n");

    ncstatus = nc_open(URL, NC_NOWRITE, &ncid);

    if(ncstatus != NC_NOERR) {
	fprintf(stderr,"Could not open: %s; server may be down; test ignored\n",URL);
	exit(0);
    }

    ncstatus = nc_inq_varid(ncid, "lon_rho", &varid);

    ndim=2;


if(verbose) {
    printf(" \n");
    printf("********************\n");
    printf("Read lon_rho data w/o strides\n");
    printf(" \n");
}

    start[0] = 0;
    start[1] = 0;
    start[2] = 0;
    start[3] = 0;

    count[0] =  336;
    count[1] =  896;

    stride[0] = 1;
    stride[1] = 1;

if(verbose) {
    for (idim=0; idim<ndim; idim++)
	printf("start[%1d]=%3lu count[%1d]=%3lu stride[%1d]=%3lu\n",
		idim,start[idim],idim,count[idim],idim,stride[idim]);
}

    ncstatus = nc_get_vars_float (ncid, varid, start, count, stride, (float*) dat);

if(verbose) {
    printf(" \n");
    printf("********************\n");
    printf("Print some of lon_rho\n");
    printf(" \n");

    for (i=0; i<10; i++)
        printf("lon_rho[%d] = %f\n",i,dat[i]);
    printf(" \n");

    for (i=301045; i<301055; i++)
        printf("lon_rho[%d] = %f\n",i,dat[i]);
    printf(" \n");
}

    memset((void*)dat,0,sizeof(dat));

    /* Read a second variable */

    ncstatus = nc_inq_varid(ncid, "lat_rho", &varid);

    ndim=2;

if(verbose) {
    printf(" \n");
    printf("********************\n");
    printf("Read lat_rho data w/o strides\n");
    printf(" \n");
}

    start[0] = 0;
    start[1] = 0;
    start[2] = 0;
    start[3] = 0;

    count[0] =  336;
    count[1] =  896;

    stride[0] = 1;
    stride[1] = 1;

if(verbose) {
    for (idim=0; idim<ndim; idim++)
        printf("start[%d]=%3lu count[%d]=%3lu stride[%d]=%3lu\n",
		idim, start[idim], idim, count[idim], idim, stride[idim]);
}

    ncstatus = nc_get_vars_float (ncid, varid, start, count, stride, (float*) dat);

if(verbose) {
    printf(" \n");
    printf("********************\n");
    printf("Print some of lat_rho\n");
    printf(" \n");
    for (i=0; i<10; i++)
        printf("lat_rho[%d] = %f\n",i,dat[i]);
    printf(" \n");

    printf(" \n");
    for (i=301045; i<301055; i++)
        printf("lon_rho[%d] = %f\n",i,dat[i]);
    printf(" \n");
}

    memset((void*)dat,0,sizeof(dat));

    /* close and reopen the dataset, then the below read is correct */

if(verbose) {
    printf(" \n");
    printf("********************\n");
    printf("Close and reopen the dataset\n");
}

    ncstatus = nc_close (ncid);
    ncstatus = nc_open(URL, NC_NOWRITE, &ncid);

    /*  ----------------------------------------------------- */
    /* Read a subset of the data with strides */

    ncstatus = nc_inq_varid(ncid, "lon_rho", &varid);

if(verbose) {
    printf(" \n");
    printf("********************\n");
    printf("Read a subset of lon_rho data with strides\n");
    printf(" \n");
}

    start[0] = 250;
    start[1] = 704;

    count[0] =  5;
    count[1] =  2;

    stride[0] = 2;
    stride[1] = 4;

if(verbose) {
    for (idim=0; idim<ndim; idim++)
	printf("start[%1d]=%3lu count[%1d]=%3lu stride[%1d]=%3lu\n",
		idim,start[idim],idim,count[idim],idim,stride[idim]);
}

    memset((void*)sdat,0,sizeof(sdat));
    ncstatus = nc_get_vars_float (ncid, varid, start, count, stride,  (float*) sdat);

    printf("status = %d\n", ncstatus);

    /* Verify that all read values are 67 <= n < 68 */
    for (i=0; i<10; i++) {
	if(!(sdat[i] <= -67 && sdat[i] > -68)) {
	    printf("lon_rho[%d] = %f\n",i,sdat[i]);
	    pass = 0;
	}
    }
if(verbose) {
    printf(" \n");
    printf("********************\n");
    printf("Print  values read. They should all be -67.xxxx \n");
    printf(" \n");

    for (i=0; i<10; i++)
        printf("lon_rho[%d] = %f\n",i,sdat[i]);
}

    ncstatus = nc_close (ncid);

    if(!pass) {
	printf("*** FAIL: lon_rho value out of range.\n");
	exit(1);
    }

    printf("*** PASS\n");
    free(dat);
    exit(0);

}