diff --git a/ChangeLog b/ChangeLog index e9c44ad794106924d04d6de78a17ec37029c2f1c..1497b64429eb72c8393f9839cc7150a7dbd1db66 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,25 @@ -2016-06-?? Uwe Schulzweida +2016-08-01 Uwe Schulzweida + + * grb, grb2 write: added support for projection CDI_PROJ_RLL + * grb, grb2, ieg read: added support for projection CDI_PROJ_RLL + +2016-07-30 Uwe Schulzweida + + * ieg write: added support for projection CDI_PROJ_RLL + +2016-07-28 Uwe Schulzweida + + * iegWriteVarSliceDP: does not work (bug fix) + +2016-07-02 Uwe Schulzweida + + * streamOpenAppend: call to gribContainersNew() missing (bug fix) [Bug #6944] + +2016-06-17 Uwe Schulzweida + + * netCDF4: added support for attribute type NC_BYTE, NC_UBYTE, NC_USHORT and NC_UINT + +2016-06-10 Uwe Schulzweida * Version 1.7.2 released diff --git a/Makefile.in b/Makefile.in index 2639d34bde9936c847829c430476bf27ba135b48..d48da22c245fd13e195dff256ab8fe4f4f1c3d6b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -293,11 +293,9 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JASPER_LIBS = @JASPER_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -321,7 +319,6 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENJPEG_LIBS = @OPENJPEG_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -403,7 +400,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -openjpeg_LIBS = @openjpeg_LIBS@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/Obsolate_functions b/Obsolate_functions new file mode 100644 index 0000000000000000000000000000000000000000..2ba106352f1d46e9658d4bac7a94a577f5eee149 --- /dev/null +++ b/Obsolate_functions @@ -0,0 +1,12 @@ +gridDefXname(gridID, xname) -> cdiGridDefKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname) +gridDefXlongname(gridID, xlongname) -> cdiGridDefKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname) +gridDefXunits(gridID, xunits) -> cdiGridDefKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits) +gridDefYname(gridID, yname) -> cdiGridDefKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname) +gridDefYlongname(gridID, ylongname) -> cdiGridDefKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname) +gridDefYunits(gridID, yunits) -> cdiGridDefKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits) +gridInqXname(gridID, xname) -> cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname) +gridInqXlongname(gridID, xlongname) -> cdiGridInqKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname) +gridInqXunits(gridID, xunits) -> cdiGridInqKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits) +gridInqYname(gridID, yname) -> cdiGridInqKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname) +gridInqYlongname(gridID, ylongname) -> cdiGridInqKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname) +gridInqYunits(gridID, yunits) -> cdiGridInqKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits) diff --git a/app/Makefile.in b/app/Makefile.in index 1c1baf6dae7278d5aaa26172f980308cdf3b6913..bcaa36a56d5f324229b67cdbb6f55ac13656f37b 100644 --- a/app/Makefile.in +++ b/app/Makefile.in @@ -266,11 +266,9 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JASPER_LIBS = @JASPER_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -294,7 +292,6 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENJPEG_LIBS = @OPENJPEG_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -376,7 +373,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -openjpeg_LIBS = @openjpeg_LIBS@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/app/cdi.c b/app/cdi.c index 399b9b02ef39eaebce81b7d9c6751cacc10a28fd..b1c3341814a6a757ef9d408560892e3a01f8a0c6 100644 --- a/app/cdi.c +++ b/app/cdi.c @@ -66,7 +66,7 @@ static int DefaultFileType = CDI_UNDEFID; static int DefaultDataType = CDI_UNDEFID; static int DefaultByteorder = CDI_UNDEFID; -static int comptype = COMPRESS_NONE; // Compression type +static int comptype = CDI_COMPRESS_NONE; // Compression type static int complevel = 0; // Compression level enum datamode {SP_MODE, DP_MODE}; @@ -277,7 +277,7 @@ void printInfo(int vdate, int vtime, char *varname, double level, fprintf(stdout, " - (%#12.5g,%#12.5g) -", arrmean_r, arrmean_i); } - fprintf(stdout, " : %-11s\n", varname); + fprintf(stdout, " : %-14s\n", varname); if ( imiss != nmiss && nmiss > 0 ) fprintf(stdout, "Found %d of %d missing values!\n", imiss, nmiss); @@ -435,7 +435,7 @@ void printShortinfo(int streamID, int vlistID, int vardis) fprintf(stdout, " %-3s", pstr); - if ( vlistInqVarCompType(vlistID, varID) == COMPRESS_NONE ) + if ( vlistInqVarCompType(vlistID, varID) == CDI_COMPRESS_NONE ) fprintf(stdout, " "); else fprintf(stdout, "z "); @@ -448,10 +448,10 @@ void printShortinfo(int streamID, int vlistID, int vardis) if (vardis) { vlistInqVarName(vlistID, varID, varname); - fprintf(stdout, "%-11s", varname); + fprintf(stdout, "%-14s", varname); } else - fprintf(stdout, "%-11s", paramstr); + fprintf(stdout, "%-14s", paramstr); fprintf(stdout, "\n"); } @@ -712,20 +712,20 @@ void defineCompress(const char *arg) if ( strncmp(arg, "szip", len) == 0 ) { - comptype = COMPRESS_SZIP; + comptype = CDI_COMPRESS_SZIP; } else if ( strncmp(arg, "jpeg", len) == 0 ) { - comptype = COMPRESS_JPEG; + comptype = CDI_COMPRESS_JPEG; } else if ( strncmp(arg, "gzip", len) == 0 ) { - comptype = COMPRESS_GZIP; + comptype = CDI_COMPRESS_GZIP; complevel = 6; } else if ( strncmp(arg, "zip", 3) == 0 ) { - comptype = COMPRESS_ZIP; + comptype = CDI_COMPRESS_ZIP; if ( len == 5 && arg[3] == '_' && isdigit(arg[4]) ) complevel = atoi(&arg[4]); else @@ -923,7 +923,7 @@ int main(int argc, char *argv[]) if ( DefaultByteorder != CDI_UNDEFID ) streamDefByteorder(streamID2, DefaultByteorder); - if ( comptype != COMPRESS_NONE ) + if ( comptype != CDI_COMPRESS_NONE ) { streamDefCompType(streamID2, comptype); streamDefCompLevel(streamID2, complevel); diff --git a/app/printinfo.h b/app/printinfo.h index 3a10ffeb3e90950ada48e81126dc418f3096b84b..f91f37c9e95a008d07f56b6711366878cefd3c1e 100644 --- a/app/printinfo.h +++ b/app/printinfo.h @@ -9,6 +9,14 @@ #define DATE_FORMAT "%5.4d-%2.2d-%2.2d" #define TIME_FORMAT "%2.2d:%2.2d:%2.2d" +void my_reset_text_color(FILE *fp) +{ + (void)fp; +#ifdef CDO + reset_text_color(fp); +#endif +} + void datetime2str(int date, int time, char *datetimestr, int maxlen) { int year, month, day; @@ -107,9 +115,9 @@ void printFiletype(int streamID, int vlistID) comptype = vlistInqVarCompType(vlistID, varID); if ( comptype ) { - if ( comptype == COMPRESS_SZIP ) + if ( comptype == CDI_COMPRESS_SZIP ) printf(" SZIP"); - else if ( comptype == COMPRESS_ZIP ) + else if ( comptype == CDI_COMPRESS_ZIP ) printf(" ZIP"); break; @@ -126,7 +134,7 @@ void printFiletype(int streamID, int vlistID) comptype = vlistInqVarCompType(vlistID, varID); if ( comptype ) { - if ( comptype == COMPRESS_JPEG ) + if ( comptype == CDI_COMPRESS_JPEG ) printf(" JPEG"); break; @@ -138,246 +146,373 @@ void printFiletype(int streamID, int vlistID) } static -void printGridInfo(int vlistID) +void print_xvals(int gridID, int dig) { - char xname[CDI_MAX_NAME], yname[CDI_MAX_NAME], xunits[CDI_MAX_NAME], yunits[CDI_MAX_NAME]; - unsigned char uuidOfHGrid[CDI_UUID_SIZE]; + int xsize = gridInqXsize(gridID); + if ( xsize > 0 && gridInqXvals(gridID, NULL) ) + { + char xname[CDI_MAX_NAME], xunits[CDI_MAX_NAME]; + gridInqXname(gridID, xname); + gridInqXunits(gridID, xunits); - int ngrids = vlistNgrids(vlistID); - for ( int index = 0; index < ngrids; index++ ) + double xfirst = gridInqXval(gridID, 0); + double xlast = gridInqXval(gridID, xsize-1); + double xinc = gridInqXinc(gridID); + fprintf(stdout, "%33s : %.*g", xname, dig, xfirst); + if ( xsize > 1 ) + { + fprintf(stdout, " to %.*g", dig, xlast); + if ( IS_NOT_EQUAL(xinc, 0) ) + fprintf(stdout, " by %.*g", dig, xinc); + } + fprintf(stdout, " %s", xunits); + if ( gridIsCircular(gridID) ) fprintf(stdout, " circular"); + fprintf(stdout, "\n"); + } +} + +static +void print_yvals(int gridID, int dig) +{ + int ysize = gridInqYsize(gridID); + if ( ysize > 0 && gridInqYvals(gridID, NULL) ) { - int gridID = vlistGrid(vlistID, index); - int gridtype = gridInqType(gridID); - int trunc = gridInqTrunc(gridID); - int gridsize = gridInqSize(gridID); - int xsize = gridInqXsize(gridID); - int ysize = gridInqYsize(gridID); - int xysize = xsize*ysize; - int prec = gridInqPrec(gridID); + char yname[CDI_MAX_NAME], yunits[CDI_MAX_NAME]; + gridInqYname(gridID, yname); + gridInqYunits(gridID, yunits); - int dig = (prec == DATATYPE_FLT64) ? 15 : 7; + double yfirst = gridInqYval(gridID, 0); + double ylast = gridInqYval(gridID, ysize-1); + double yinc = gridInqYinc(gridID); + fprintf(stdout, "%33s : %.*g", yname, dig, yfirst); + if ( ysize > 1 ) + { + int gridtype = gridInqType(gridID); + fprintf(stdout, " to %.*g", dig, ylast); + if ( IS_NOT_EQUAL(yinc, 0) && gridtype != GRID_GAUSSIAN && gridtype != GRID_GAUSSIAN_REDUCED ) + fprintf(stdout, " by %.*g", dig, yinc); + } + fprintf(stdout, " %s", yunits); + fprintf(stdout, "\n"); + } +} +static +void print_xyvals2D(int gridID, int dig) +{ + if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) ) + { + char xname[CDI_MAX_NAME], yname[CDI_MAX_NAME], xunits[CDI_MAX_NAME], yunits[CDI_MAX_NAME]; gridInqXname(gridID, xname); gridInqYname(gridID, yname); gridInqXunits(gridID, xunits); gridInqYunits(gridID, yunits); - fprintf(stdout, " %4d : %-24s", index+1, gridNamePtr(gridtype)); + int gridsize = gridInqSize(gridID); + double *xvals2D = (double*) malloc((size_t)gridsize*sizeof(double)); + double *yvals2D = (double*) malloc((size_t)gridsize*sizeof(double)); - if ( gridtype == GRID_LONLAT || - gridtype == GRID_LCC2 || - gridtype == GRID_LAEA || - gridtype == GRID_SINUSOIDAL || - gridtype == GRID_GENERIC || - gridtype == GRID_GAUSSIAN || - gridtype == GRID_GAUSSIAN_REDUCED ) - { - double yfirst = gridInqYval(gridID, 0); - double ylast = gridInqYval(gridID, ysize-1); - double yinc = gridInqYinc(gridID); + gridInqXvals(gridID, xvals2D); + gridInqYvals(gridID, yvals2D); - fprintf(stdout, " : points=%d", gridsize); - if ( gridtype == GRID_GAUSSIAN_REDUCED ) - fprintf(stdout, " nlat=%d", ysize); - else if ( xysize ) - fprintf(stdout, " (%dx%d)", xsize, ysize); + double xfirst = xvals2D[0]; + double xlast = xvals2D[0]; + double yfirst = yvals2D[0]; + double ylast = yvals2D[0]; + for ( int i = 1; i < gridsize; i++ ) + { + if ( xvals2D[i] < xfirst ) xfirst = xvals2D[i]; + if ( xvals2D[i] > xlast ) xlast = xvals2D[i]; + if ( yvals2D[i] < yfirst ) yfirst = yvals2D[i]; + if ( yvals2D[i] > ylast ) ylast = yvals2D[i]; + } - if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED ) - fprintf(stdout, " np=%d", gridInqNP(gridID)); + double xinc = 0; + double yinc = 0; + int gridtype = gridInqType(gridID); + if ( gridtype == GRID_CURVILINEAR ) + { + int xsize = gridInqXsize(gridID); + if ( xsize > 1 ) + { + double *xvals = (double*) malloc(xsize*sizeof(double)); + for ( int i = 0; i < xsize; ++i ) xvals[i] = xvals2D[i]; + xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1); + for ( int i = 2; i < xsize; i++ ) + if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc ) { xinc = 0; break; } + free(xvals); + } + int ysize = gridInqYsize(gridID); + if ( ysize > 1 ) + { + double *yvals = (double*) malloc(ysize*sizeof(double)); + for ( int i = 0; i < ysize; ++i ) yvals[i] = yvals2D[i*xsize]; + yinc = fabs(yvals[ysize-1] - yvals[0])/(ysize-1); + for ( int i = 2; i < ysize; i++ ) + if ( fabs(fabs(yvals[i-1] - yvals[i]) - yinc) > 0.01*yinc ) { yinc = 0; break; } + free(yvals); + } + } - fprintf(stdout, "\n"); + fprintf(stdout, "%33s : %.*g to %.*g", xname, dig, xfirst, dig, xlast); + if ( IS_NOT_EQUAL(xinc, 0) ) + fprintf(stdout, " by %.*g", dig, xinc); + fprintf(stdout, " %s", xunits); + if ( gridIsCircular(gridID) ) fprintf(stdout, " circular"); + fprintf(stdout, "\n"); + fprintf(stdout, "%33s : %.*g to %.*g", yname, dig, yfirst, dig, ylast); + if ( IS_NOT_EQUAL(yinc, 0) ) + fprintf(stdout, " by %.*g", dig, yinc); + fprintf(stdout, " %s", xunits); + fprintf(stdout, "\n"); - bool lxcoord = true, lycoord = true; - if ( gridInqXvals(gridID, NULL) == 0 ) lxcoord = false; - if ( gridInqYvals(gridID, NULL) == 0 ) lycoord = false; + free(xvals2D); + free(yvals2D); + } +} - if ( xsize > 0 && lxcoord ) - { - double xfirst = gridInqXval(gridID, 0); - double xlast = gridInqXval(gridID, xsize-1); - double xinc = gridInqXinc(gridID); - fprintf(stdout, "%33s : %.*g", xname, dig, xfirst); - if ( xsize > 1 ) - { - fprintf(stdout, " to %.*g", dig, xlast); - if ( IS_NOT_EQUAL(xinc, 0) ) - fprintf(stdout, " by %.*g", dig, xinc); - } - fprintf(stdout, " %s", xunits); - if ( gridIsCircular(gridID) ) fprintf(stdout, " circular"); - fprintf(stdout, "\n"); - } +static +void printGridInfoKernel(int gridID, int index, bool lproj) +{ + int gridtype = gridInqType(gridID); - if ( ysize > 0 && lycoord ) - { - fprintf(stdout, "%33s : %.*g", yname, dig, yfirst); - if ( ysize > 1 ) - { - fprintf(stdout, " to %.*g", dig, ylast); - if ( IS_NOT_EQUAL(yinc, 0) && gridtype != GRID_GAUSSIAN && gridtype != GRID_GAUSSIAN_REDUCED ) - fprintf(stdout, " by %.*g", dig, yinc); - } - fprintf(stdout, " %s", yunits); - fprintf(stdout, "\n"); - } + if ( lproj && gridtype != GRID_PROJECTION ) + fprintf(stderr, "Internal problem (%s): sub grid not equal GRID_PROJECTION!\n", __func__); - if ( gridIsRotated(gridID) ) - { - double lonpole = gridInqXpole(gridID); - double latpole = gridInqYpole(gridID); - double angle = gridInqAngle(gridID); - fprintf(stdout, "%33s : lon=%.*g lat=%.*g", "northpole", dig, lonpole, dig, latpole); - if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, " angle=%.*g", dig, angle); - fprintf(stdout, "\n"); - } + int trunc = gridInqTrunc(gridID); + int gridsize = gridInqSize(gridID); + int xsize = gridInqXsize(gridID); + int ysize = gridInqYsize(gridID); + int xysize = xsize*ysize; - if ( gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) ) - { - fprintf(stdout, "%33s :", "available"); - if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds"); - if ( gridHasArea(gridID) ) fprintf(stdout, " area"); - if ( gridInqMask(gridID, NULL) ) fprintf(stdout, " mask"); - fprintf(stdout, "\n"); - } + // int prec = gridInqPrec(gridID); + // int dig = (prec == DATATYPE_FLT64) ? 15 : 7; + int dig = 7; - if ( gridtype == GRID_LAEA ) - { - double a, lon_0, lat_0; - gridInqLaea(gridID, &a, &lon_0, &lat_0); - fprintf(stdout, "%33s : a=%g lon_0=%g lat_0=%g\n", "projpar", a, lon_0, lat_0); - } + if ( !lproj ) + { + fprintf(stdout, " %4d : ", index+1); +#ifdef CDO + set_text_color(stdout, RESET, BLUE); +#endif + fprintf(stdout, "%-24s", gridNamePtr(gridtype)); + my_reset_text_color(stdout); + fprintf(stdout, " : "); + } - if ( gridtype == GRID_LCC2 ) - { - double a, lon_0, lat_0, lat_1, lat_2; - gridInqLcc2(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2); - fprintf(stdout, "%33s : a=%7.0f lon_0=%g lat_0=%g lat_1=%g lat_2=%g\n", - "projpar", a, lon_0, lat_0, lat_1, lat_2); - } - } - else if ( gridtype == GRID_SPECTRAL ) - { - fprintf(stdout, " : points=%d nsp=%d truncation=%d", gridsize, gridsize/2, trunc); - if ( gridInqComplexPacking(gridID) ) fprintf(stdout, " complexPacking"); - fprintf(stdout, "\n"); - } - else if ( gridtype == GRID_FOURIER ) - { - fprintf(stdout, " : points=%d nfc=%d truncation=%d\n", gridsize, gridsize/2, trunc); - } - else if ( gridtype == GRID_GME ) - { - int ni = gridInqGMEni(gridID); - int nd = gridInqGMEnd(gridID); - fprintf(stdout, " : points=%d nd=%d ni=%d\n", gridsize, nd, ni); - } - else if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED ) - { - if ( gridtype == GRID_CURVILINEAR ) - fprintf(stdout, " : points=%d (%dx%d)", gridsize, xsize, ysize); - else - fprintf(stdout, " : points=%d", gridsize); + if ( gridtype == GRID_LONLAT || + gridtype == GRID_LCC2 || + gridtype == GRID_LAEA || + gridtype == GRID_SINUSOIDAL || + gridtype == GRID_PROJECTION || + gridtype == GRID_GENERIC || + gridtype == GRID_GAUSSIAN || + gridtype == GRID_GAUSSIAN_REDUCED ) + { + if ( !lproj ) + { +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + fprintf(stdout, "points=%d", gridsize); + if ( gridtype == GRID_GAUSSIAN_REDUCED ) + fprintf(stdout, " nlat=%d", ysize); + else if ( xysize ) + fprintf(stdout, " (%dx%d)", xsize, ysize); - if ( gridtype == GRID_UNSTRUCTURED && gridInqNvertex(gridID) > 0 ) - fprintf(stdout, " nvertex=%d", gridInqNvertex(gridID)); + if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED ) + fprintf(stdout, " np=%d", gridInqNP(gridID)); + my_reset_text_color(stdout); fprintf(stdout, "\n"); + } - if ( gridtype == GRID_UNSTRUCTURED ) - { - int number = gridInqNumber(gridID); - int position = gridInqPosition(gridID); + char name[CDI_MAX_NAME]; name[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, name); + if ( gridtype == GRID_PROJECTION || name[0] ) + { + if ( name[0] == 0 ) strcpy(name, "undefined"); +#ifdef CDO + set_text_color(stdout, RESET, BLUE); +#endif + fprintf(stdout, " %24s", "mapping"); + my_reset_text_color(stdout); + fprintf(stdout, " : "); +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + fprintf(stdout, "%s\n", name); + my_reset_text_color(stdout); + } - if ( number > 0 ) - { - fprintf(stdout, "%33s : number=%d position=%d\n", "grid", number, position); - } + print_xvals(gridID, dig); + print_yvals(gridID, dig); - if ( gridInqReference(gridID, NULL) ) - { - char reference_link[8192]; - gridInqReference(gridID, reference_link); - fprintf(stdout, "%33s : %s\n", "uri", reference_link); - } - } + if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) ) + { + double lonpole = gridInqXpole(gridID); + double latpole = gridInqYpole(gridID); + double angle = gridInqAngle(gridID); + fprintf(stdout, "%33s : lon=%.*g lat=%.*g", "northpole", dig, lonpole, dig, latpole); + if ( IS_NOT_EQUAL(angle, 0) ) fprintf(stdout, " angle=%.*g", dig, angle); + fprintf(stdout, "\n"); + } - if ( gridInqXvals(gridID, NULL) && gridInqYvals(gridID, NULL) ) - { - double *xvals = (double*) malloc((size_t)gridsize*sizeof(double)); - double *yvals = (double*) malloc((size_t)gridsize*sizeof(double)); - - gridInqXvals(gridID, xvals); - gridInqYvals(gridID, yvals); - - double xfirst = xvals[0]; - double xlast = xvals[0]; - double yfirst = yvals[0]; - double ylast = yvals[0]; - for ( int i = 1; i < gridsize; i++ ) - { - if ( xvals[i] < xfirst ) xfirst = xvals[i]; - if ( xvals[i] > xlast ) xlast = xvals[i]; - if ( yvals[i] < yfirst ) yfirst = yvals[i]; - if ( yvals[i] > ylast ) ylast = yvals[i]; - } - - fprintf(stdout, "%33s : %.*g to %.*g %s", xname, dig, xfirst, dig, xlast, xunits); - if ( gridIsCircular(gridID) ) fprintf(stdout, " circular"); - fprintf(stdout, "\n"); - fprintf(stdout, "%33s : %.*g to %.*g %s\n", yname, dig, yfirst, dig, ylast, yunits); - - free(xvals); - free(yvals); - } - } - else if ( gridtype == GRID_LCC ) - { - double originLon, originLat, lonParY, lat1, lat2, xincm, yincm; - int projflag, scanflag; + if ( gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) ) + { + fprintf(stdout, "%33s :", "available"); + if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds"); + if ( gridHasArea(gridID) ) fprintf(stdout, " area"); + if ( gridInqMask(gridID, NULL) ) fprintf(stdout, " mask"); + fprintf(stdout, "\n"); + } - gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm, - &projflag, &scanflag); + if ( gridtype == GRID_LAEA ) + { + double a, lon_0, lat_0; + gridInqLaea(gridID, &a, &lon_0, &lat_0); + fprintf(stdout, "%33s : a=%g lon_0=%g lat_0=%g\n", "projpar", a, lon_0, lat_0); + } - fprintf(stdout, " : points=%d (%dx%d) ", gridsize, xsize, ysize); - if ( (projflag&128) == 0 ) - fprintf(stdout, "North Pole\n"); - else - fprintf(stdout, "South Pole\n"); + if ( gridtype == GRID_LCC2 ) + { + double a, lon_0, lat_0, lat_1, lat_2; + gridInqLcc2(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2); + fprintf(stdout, "%33s : a=%7.0f lon_0=%g lat_0=%g lat_1=%g lat_2=%g\n", + "projpar", a, lon_0, lat_0, lat_1, lat_2); + } + } + else if ( gridtype == GRID_SPECTRAL ) + { +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + fprintf(stdout, "points=%d nsp=%d truncation=%d", gridsize, gridsize/2, trunc); + if ( gridInqComplexPacking(gridID) ) fprintf(stdout, " complexPacking"); + my_reset_text_color(stdout); + fprintf(stdout, "\n"); + } + else if ( gridtype == GRID_FOURIER ) + { +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + fprintf(stdout, "points=%d nfc=%d truncation=%d\n", gridsize, gridsize/2, trunc); + my_reset_text_color(stdout); + } + else if ( gridtype == GRID_GME ) + { + int ni = gridInqGMEni(gridID); + int nd = gridInqGMEnd(gridID); +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + fprintf(stdout, "points=%d nd=%d ni=%d\n", gridsize, nd, ni); + my_reset_text_color(stdout); + } + else if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED ) + { +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + if ( gridtype == GRID_CURVILINEAR ) + fprintf(stdout, "points=%d (%dx%d)", gridsize, xsize, ysize); + else + fprintf(stdout, "points=%d", gridsize); - fprintf(stdout, "%33s : originLon=%g originLat=%g lonParY=%g\n", " ", originLon, originLat, lonParY); - fprintf(stdout, "%33s : lat1=%g lat2=%g xinc=%g m yinc=%g m\n", " ", lat1, lat2, xincm, yincm); - } - else /* if ( gridtype == GRID_GENERIC ) */ - { - if ( ysize == 0 ) - fprintf(stdout, " : points=%d\n", gridsize); - else - fprintf(stdout, " : points=%d (%dx%d)\n", gridsize, xsize, ysize); - } + if ( gridtype == GRID_UNSTRUCTURED && gridInqNvertex(gridID) > 0 ) + fprintf(stdout, " nvertex=%d", gridInqNvertex(gridID)); + my_reset_text_color(stdout); - if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED || gridtype == GRID_LCC ) - { - if ( gridHasArea(gridID) || - gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) ) - { - fprintf(stdout, "%33s :", "available"); - if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds"); - if ( gridHasArea(gridID) ) fprintf(stdout, " area"); - if ( gridInqMask(gridID, NULL) ) fprintf(stdout, " mask"); - fprintf(stdout, "\n"); - } - } + fprintf(stdout, "\n"); - gridInqUUID(gridID, uuidOfHGrid); - if ( !cdiUUIDIsNull(uuidOfHGrid) ) + if ( gridtype == GRID_UNSTRUCTURED ) { - char uuidOfHGridStr[37]; - cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr); - if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 ) + int number = gridInqNumber(gridID); + int position = gridInqPosition(gridID); + if ( number > 0 ) + fprintf(stdout, "%33s : number=%d position=%d\n", "grid", number, position); + + if ( gridInqReference(gridID, NULL) ) { - fprintf(stdout, "%33s : %s\n", "uuid", uuidOfHGridStr); + char reference_link[8192]; + gridInqReference(gridID, reference_link); + fprintf(stdout, "%33s : %s\n", "uri", reference_link); } } + + print_xyvals2D(gridID, dig); + } + else if ( gridtype == GRID_LCC ) + { + double originLon, originLat, lonParY, lat1, lat2, xincm, yincm; + int projflag, scanflag; + + gridInqLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm, + &projflag, &scanflag); + +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + fprintf(stdout, "points=%d (%dx%d) ", gridsize, xsize, ysize); + if ( (projflag&128) == 0 ) + fprintf(stdout, "North Pole\n"); + else + fprintf(stdout, "South Pole\n"); + my_reset_text_color(stdout); + + fprintf(stdout, "%33s : originLon=%g originLat=%g lonParY=%g\n", " ", originLon, originLat, lonParY); + fprintf(stdout, "%33s : lat1=%g lat2=%g xinc=%g m yinc=%g m\n", " ", lat1, lat2, xincm, yincm); + } + else /* if ( gridtype == GRID_GENERIC ) */ + { +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif + if ( ysize == 0 ) + fprintf(stdout, "points=%d\n", gridsize); + else + fprintf(stdout, "points=%d (%dx%d)\n", gridsize, xsize, ysize); + my_reset_text_color(stdout); + } + + if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED || gridtype == GRID_LCC ) + { + if ( gridHasArea(gridID) || + gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) ) + { + fprintf(stdout, "%33s :", "available"); + if ( gridInqXbounds(gridID, NULL) && gridInqYbounds(gridID, NULL) ) fprintf(stdout, " cellbounds"); + if ( gridHasArea(gridID) ) fprintf(stdout, " area"); + if ( gridInqMask(gridID, NULL) ) fprintf(stdout, " mask"); + fprintf(stdout, "\n"); + } + } + + unsigned char uuidOfHGrid[CDI_UUID_SIZE]; + gridInqUUID(gridID, uuidOfHGrid); + if ( !cdiUUIDIsNull(uuidOfHGrid) ) + { + char uuidOfHGridStr[37]; + cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr); + if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 ) + { + fprintf(stdout, "%33s : %s\n", "uuid", uuidOfHGridStr); + } + } +} + +static +void printGridInfo(int vlistID) +{ + int ngrids = vlistNgrids(vlistID); + for ( int index = 0; index < ngrids; index++ ) + { + int gridID = vlistGrid(vlistID, index); + printGridInfoKernel(gridID, index, false); + int projID = gridInqProj(gridID); + if ( projID != CDI_UNDEFID ) + printGridInfoKernel(projID, index, true); } } @@ -403,12 +538,23 @@ void printZaxisInfo(int vlistID) zaxisInqUnits(zaxisID, zunits); zunits[12] = 0; + fprintf(stdout, " %4d : ", vlistZaxisIndex(vlistID, zaxisID)+1); +#ifdef CDO + set_text_color(stdout, RESET, BLUE); +#endif if ( zaxistype == ZAXIS_GENERIC && ltype != 0 ) - fprintf(stdout, " %4d : %-12s (ltype=%3d) :", vlistZaxisIndex(vlistID, zaxisID)+1, zaxisname, ltype); + fprintf(stdout, "%-12s (ltype=%3d) :", zaxisname, ltype); else - fprintf(stdout, " %4d : %-24s :", vlistZaxisIndex(vlistID, zaxisID)+1, zaxisname); + fprintf(stdout, "%-24s", zaxisname); + my_reset_text_color(stdout); + + fprintf(stdout, " :"); +#ifdef CDO + set_text_color(stdout, RESET, GREEN); +#endif fprintf(stdout, " levels=%d", levelsize); + my_reset_text_color(stdout); fprintf(stdout, "\n"); double *levels = (double*) malloc((size_t)levelsize*sizeof(double)); diff --git a/configure b/configure index b3db107b05b85416c2ff4217e35cb2a3e43b0094..a56e2e2134edc353bc4d2556895c6e465f8dcdfb 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for cdi 1.7.2. +# Generated by GNU Autoconf 2.68 for cdi 1.8.0rc1. # # Report bugs to <http://mpimet.mpg.de/cdi>. # @@ -570,8 +570,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='cdi' PACKAGE_TARNAME='cdi' -PACKAGE_VERSION='1.7.2' -PACKAGE_STRING='cdi 1.7.2' +PACKAGE_VERSION='1.8.0rc1' +PACKAGE_STRING='cdi 1.8.0rc1' PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdi' PACKAGE_URL='' @@ -688,10 +688,6 @@ HAVE_LIBGRIB_API_FALSE HAVE_LIBGRIB_API_TRUE GRIB_API_LIBS GRIB_API_INCLUDE -LIBPNG_LIBS -OPENJPEG_LIBS -openjpeg_LIBS -JASPER_LIBS NETCDF_LIBS NETCDF_INCLUDE NETCDF_ROOT @@ -862,9 +858,6 @@ enable_largefile with_threads with_szlib with_netcdf -with_jasper -with_openjpeg -with_libpng with_grib_api enable_grib enable_cgribex @@ -1467,7 +1460,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures cdi 1.7.2 to adapt to many kinds of systems. +\`configure' configures cdi 1.8.0rc1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1537,7 +1530,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of cdi 1.7.2:";; + short | recursive ) echo "Configuration of cdi 1.8.0rc1:";; esac cat <<\_ACEOF @@ -1592,16 +1585,6 @@ Optional Packages: NETCDF4 compression --with-netcdf=<yes|no|directory> (default=no) location of NetCDF library (lib and include subdirs) - --with-jasper=<directory> - Specify location of JASPER library. You must specify - its location if GRIB_API was built with JASPER. - --with-openjpeg=<directory> - Specify location of openjpeg library. You must - specify its location if GRIB_API was built with - openjpeg. - --with-libpng=<directory> - Specify location of LIBPNG library. You must specify - its location if GRIB_API was built with LIBPNG. --with-grib_api=<yes|no|directory> library for grib2 compression; if a directory is given, it will be used as a value for @@ -1740,7 +1723,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -cdi configure 1.7.2 +cdi configure 1.8.0rc1 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -2585,7 +2568,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by cdi $as_me 1.7.2, which was +It was created by cdi $as_me 1.8.0rc1, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -3537,7 +3520,7 @@ fi # Define the identity of the package. PACKAGE='cdi' - VERSION='1.7.2' + VERSION='1.8.0rc1' cat >>confdefs.h <<_ACEOF @@ -23406,7 +23389,7 @@ Usage: $0 [OPTIONS] Report bugs to <bug-libtool@gnu.org>." lt_cl_version="\ -cdi config.lt 1.7.2 +cdi config.lt 1.8.0rc1 configured by $0, generated by GNU Autoconf 2.68. Copyright (C) 2011 Free Software Foundation, Inc. @@ -27528,507 +27511,6 @@ fi -# ---------------------------------------------------------------------- -# Link application with JASPER library (needed for GRIB2 compression) -JASPER_LIBS='' - -# Check whether --with-jasper was given. -if test "${with_jasper+set}" = set; then : - withval=$with_jasper; case "$with_jasper" in #( - no) : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jasper library" >&5 -$as_echo_n "checking for jasper library... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5 -$as_echo "suppressed" >&6; } ;; #( - yes) : - for ac_header in jasper.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "jasper.h" "ac_cv_header_jasper_h" "$ac_includes_default" -if test "x$ac_cv_header_jasper_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_JASPER_H 1 -_ACEOF - -fi - -done - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing jas_init" >&5 -$as_echo_n "checking for library containing jas_init... " >&6; } -if ${ac_cv_search_jas_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char jas_init (); -int -main () -{ -return jas_init (); - ; - return 0; -} -_ACEOF -for ac_lib in '' jasper; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_jas_init=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_jas_init+:} false; then : - break -fi -done -if ${ac_cv_search_jas_init+:} false; then : - -else - ac_cv_search_jas_init=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_jas_init" >&5 -$as_echo "$ac_cv_search_jas_init" >&6; } -ac_res=$ac_cv_search_jas_init -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -$as_echo "#define HAVE_LIBJASPER 1" >>confdefs.h - -else - as_fn_error $? "Could not link to jasper library! Required for GRIB_API" "$LINENO" 5 -fi - - JASPER_LIBS=" -ljasper" - ;; #( - *) : - JASPER_ROOT=$with_jasper - if test -d "$JASPER_ROOT"; then : - LDFLAGS="$LDFLAGS -L$JASPER_ROOT/lib" - CPPFLAGS="$CPPFLAGS -I$JASPER_ROOT/include" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing jas_stream_memopen" >&5 -$as_echo_n "checking for library containing jas_stream_memopen... " >&6; } -if ${ac_cv_search_jas_stream_memopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char jas_stream_memopen (); -int -main () -{ -return jas_stream_memopen (); - ; - return 0; -} -_ACEOF -for ac_lib in '' jasper; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_jas_stream_memopen=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_jas_stream_memopen+:} false; then : - break -fi -done -if ${ac_cv_search_jas_stream_memopen+:} false; then : - -else - ac_cv_search_jas_stream_memopen=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_jas_stream_memopen" >&5 -$as_echo "$ac_cv_search_jas_stream_memopen" >&6; } -ac_res=$ac_cv_search_jas_stream_memopen -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -$as_echo "#define HAVE_LIBJASPER 1" >>confdefs.h - -else - as_fn_error $? "Could not link to jasper library! Required for GRIB_API" "$LINENO" 5 -fi - - JASPER_LIBS=" -L$JASPER_ROOT/lib -ljasper" -else - as_fn_error $? "$JASPER_ROOT is not a directory! JASPER suppressed" "$LINENO" 5 -fi ;; #( - *) : - ;; -esac -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the JASPER library" >&5 -$as_echo_n "checking for the JASPER library... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5 -$as_echo "suppressed" >&6; } -fi - - -# ---------------------------------------------------------------------- -# Link application with openjpeg library (needed for GRIB2 compression) -OPENJPEG_LIBS='' - -# Check whether --with-openjpeg was given. -if test "${with_openjpeg+set}" = set; then : - withval=$with_openjpeg; case "$with_openjpeg" in #( - no) : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openjpeg library" >&5 -$as_echo_n "checking for openjpeg library... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5 -$as_echo "suppressed" >&6; } ;; #( - yes) : - for ac_header in openjpeg.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "openjpeg.h" "ac_cv_header_openjpeg_h" "$ac_includes_default" -if test "x$ac_cv_header_openjpeg_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_OPENJPEG_H 1 -_ACEOF - -fi - -done - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opj_image_create" >&5 -$as_echo_n "checking for library containing opj_image_create... " >&6; } -if ${ac_cv_search_opj_image_create+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char opj_image_create (); -int -main () -{ -return opj_image_create (); - ; - return 0; -} -_ACEOF -for ac_lib in '' openjpeg; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_opj_image_create=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_opj_image_create+:} false; then : - break -fi -done -if ${ac_cv_search_opj_image_create+:} false; then : - -else - ac_cv_search_opj_image_create=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opj_image_create" >&5 -$as_echo "$ac_cv_search_opj_image_create" >&6; } -ac_res=$ac_cv_search_opj_image_create -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -$as_echo "#define HAVE_LIBOPENJPEG 1" >>confdefs.h - -else - as_fn_error $? "Could not link to openjpeg library! Required for GRIB_API" "$LINENO" 5 -fi - - openjpeg_LIBS=" -lopenjpeg" - ;; #( - *) : - OPENJPEG_ROOT=$with_openjpeg - if test -d "$OPENJPEG_ROOT"; then : - LDFLAGS="$LDFLAGS -L$OPENJPEG_ROOT/lib" - CPPFLAGS="$CPPFLAGS -I$OPENJPEG_ROOT/include" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opj_image_create" >&5 -$as_echo_n "checking for library containing opj_image_create... " >&6; } -if ${ac_cv_search_opj_image_create+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char opj_image_create (); -int -main () -{ -return opj_image_create (); - ; - return 0; -} -_ACEOF -for ac_lib in '' openjpeg; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_opj_image_create=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_opj_image_create+:} false; then : - break -fi -done -if ${ac_cv_search_opj_image_create+:} false; then : - -else - ac_cv_search_opj_image_create=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opj_image_create" >&5 -$as_echo "$ac_cv_search_opj_image_create" >&6; } -ac_res=$ac_cv_search_opj_image_create -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -$as_echo "#define HAVE_LIBOPENJPEG 1" >>confdefs.h - -else - as_fn_error $? "Could not link to openjpeg library! Required for GRIB_API" "$LINENO" 5 -fi - - OPENJPEG_LIBS=" -L$OPENJPEG_ROOT/lib -lopenjpeg" -else - as_fn_error $? "$OPENJPEG_ROOT is not a directory! openjpeg suppressed" "$LINENO" 5 -fi ;; #( - *) : - ;; -esac -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the openjpeg library" >&5 -$as_echo_n "checking for the openjpeg library... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5 -$as_echo "suppressed" >&6; } -fi - - -# ---------------------------------------------------------------------- -# Link application with LIBPNG library (needed for GRIB2 compression) -LIBPNG_LIBS='' - -# Check whether --with-libpng was given. -if test "${with_libpng+set}" = set; then : - withval=$with_libpng; case "$with_libpng" in #( - no) : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpng library" >&5 -$as_echo_n "checking for libpng library... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5 -$as_echo "suppressed" >&6; } ;; #( - yes) : - for ac_header in png.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "png.h" "ac_cv_header_png_h" "$ac_includes_default" -if test "x$ac_cv_header_png_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_PNG_H 1 -_ACEOF - -fi - -done - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing png_warning" >&5 -$as_echo_n "checking for library containing png_warning... " >&6; } -if ${ac_cv_search_png_warning+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char png_warning (); -int -main () -{ -return png_warning (); - ; - return 0; -} -_ACEOF -for ac_lib in '' png; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_png_warning=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_png_warning+:} false; then : - break -fi -done -if ${ac_cv_search_png_warning+:} false; then : - -else - ac_cv_search_png_warning=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_png_warning" >&5 -$as_echo "$ac_cv_search_png_warning" >&6; } -ac_res=$ac_cv_search_png_warning -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -$as_echo "#define HAVE_LIBLIBPNG 1" >>confdefs.h - -else - as_fn_error $? "Could not link to libpng library! Required for GRIB_API" "$LINENO" 5 -fi - - LIBPNG_LIBS=" -lpng" - ;; #( - *) : - LIBPNG_ROOT=$with_libpng - if test -d "$LIBPNG_ROOT"; then : - LDFLAGS="$LDFLAGS -L$LIBPNG_ROOT/lib" - CPPFLAGS="$CPPFLAGS -I$LIBPNG_ROOT/include" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing png_warning" >&5 -$as_echo_n "checking for library containing png_warning... " >&6; } -if ${ac_cv_search_png_warning+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char png_warning (); -int -main () -{ -return png_warning (); - ; - return 0; -} -_ACEOF -for ac_lib in '' png; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_png_warning=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_png_warning+:} false; then : - break -fi -done -if ${ac_cv_search_png_warning+:} false; then : - -else - ac_cv_search_png_warning=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_png_warning" >&5 -$as_echo "$ac_cv_search_png_warning" >&6; } -ac_res=$ac_cv_search_png_warning -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -$as_echo "#define HAVE_LIBLIBPNG 1" >>confdefs.h - -else - as_fn_error $? "Could not link to libpng library! Required for GRIB_API" "$LINENO" 5 -fi - - LIBPNG_LIBS=" -L$LIBPNG_ROOT/lib -lpng" -else - as_fn_error $? "$LIBPNG_ROOT is not a directory! LIBPNG suppressed" "$LINENO" 5 -fi ;; #( - *) : - ;; -esac -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the LIBPNG library" >&5 -$as_echo_n "checking for the LIBPNG library... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: suppressed" >&5 -$as_echo "suppressed" >&6; } -fi - - # ---------------------------------------------------------------------- # Compile application with GRIB_API library (for GRIB2 support) GRIB_API_INCLUDE='' @@ -31040,7 +30522,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by cdi $as_me 1.7.2, which was +This file was extended by cdi $as_me 1.8.0rc1, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -31106,7 +30588,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -cdi config.status 1.7.2 +cdi config.status 1.8.0rc1 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 578f31c9db39a617be87130a87fffdcf210f37db..aefe783d596fb66cda50b5afac4b8e810ddca27f 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ # autoconf 2.68 # libtool 2.4.2 -AC_INIT([cdi], [1.7.2], [http://mpimet.mpg.de/cdi]) +AC_INIT([cdi], [1.8.0rc1], [http://mpimet.mpg.de/cdi]) AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version]) diff --git a/doc/Gridmapping b/doc/Gridmapping new file mode 100644 index 0000000000000000000000000000000000000000..f6015886b1fef92c8bdb4b509a1e7bdf4ef08a53 --- /dev/null +++ b/doc/Gridmapping @@ -0,0 +1,151 @@ + +======================================= +Example 1: rotated_latitude_longitude +======================================= + + rlon = 106 ; + rlat = 111 ; + float lon(rlat, rlon) ; + lon:long_name = "longitude" ; + lon:units = "degrees_east" ; + lon:standard_name = "grid_longitude" ; + float lat(rlat, rlon) ; + lat:long_name = "latitude" ; + lat:units = "degrees_north" ; + lat:standard_name = "grid_latitude" ; + float rlat(rlat) ; + rlat:standard_name = "grid_latitude" ; + rlat:long_name = "rotated latitude" ; + rlat:units = "degrees" ; + float rlon(rlon) ; + rlon:standard_name = "grid_longitude" ; + rlon:long_name = "rotated longitude" ; + rlon:units = "degrees" ; + char rotated_pole ; + rotated_pole:long_name = "coordinates of the rotated North Pole" ; + rotated_pole:grid_mapping_name = "rotated_latitude_longitude" ; + rotated_pole:grid_north_pole_latitude = 39.25f ; + rotated_pole:grid_north_pole_longitude = -162.f ; + float T_2M_AV(time, height_2m, rlat, rlon) ; + T_2M_AV:standard_name = "air_temperature" ; + T_2M_AV:units = "K" ; + T_2M_AV:coordinates = "lon lat" ; + +gridtype = GRIB_CURVILINEAR +xsize = 106 +ysize = 111 +xname = lon +xvals = ... +yname = lat +yvals = ... +xdimname = rlon +ydimname = rlat +projection = rotated_latitude_longitude +pname = rotated_pole +pxvals = .... +pyvals = .... +grid_north_pole_latitude = 39.25f +grid_north_pole_longitude = -162.f +long_name = "coordinates of the rotated North Pole" + +gridID = gridCreate(GRID_CURVILINEAR, size) +gridDefXsize(gridID, xsize) +gridDefYsize(gridID, ysize) +gridDefXvals(gridID, xvals) +gridDefYvals(gridID, yvals) +.... +projID = gridCreate(GRIB_PROJECTION, size) +gridDefKeyStr(projID, CDI_KEY_MAPPINGNAME, len, string) +gridDefKeyStr(projID, CDI_KEY_PNAME, len, string) +gridDefXsize(projID, xsize) +gridDefYsize(projID, ysize) +gridDefXvals(projID, xvals) +gridDefYvals(projID, yvals) +gridDefAttStr(projID, NAME, len, string); +gridDefAttFlt(projID, NAME, len, array); +.... +gridDefProjection(gridID, projID); + +======================================= +Example 2: lambert_azimuthal_equal_area +======================================= + + x = 334 ; + y = 334 ; + + double x(x) ; + x:standard_name = "projection_x_coordinate" ; + x:units = "m" ; + x:axis = "X" ; + double y(y) ; + y:standard_name = "projection_y_coordinate" ; + y:units = "m" ; + y:axis = "Y" ; + char laea ; + laea:grid_mapping_name = "lambert_azimuthal_equal_area" ; + laea:earth_radius = 6370997. ; + laea:longitude_of_projection_origin = 0. ; + laea:latitude_of_projection_origin = 90. ; + float CFC_FC_F(time, y, x) ; + CFC_FC_F:grid_mapping = "laea" ; + +gridtype = GRIB_CURVILINEAR +xsize = 334 +ysize = 334 +projection = lambert_azimuthal_equal_area +pxvals = .... +pyvals = .... +earth_radius = 6370997. +longitude_of_projection_origin = 0. +latitude_of_projection_origin = 90. + +cdo gen_geoloc ifile ofile +//cdo del_geoloc ifile ofile + +gridtype = GRIB_CURVILINEAR +xsize = 334 +ysize = 334 +xvals = .... +yvals = .... +xbounds = .... +ybounds = .... +projection = lambert_azimuthal_equal_area +pxvals = .... +pyvals = .... +earth_radius = 6370997. +longitude_of_projection_origin = 0. +latitude_of_projection_origin = 90. + +cdo del_proj ifile ofile + +gridtype = GRIB_CURVILINEAR +xsize = 334 +ysize = 334 +xvals = .... +yvals = .... +xbounds = .... +ybounds = .... + +======================================= +Example 3: Latitude and longitude on a spherical Earth +======================================= + +dimensions: + lat = 18 ; + lon = 36 ; +variables: + double lat(lat) ; + double lon(lon) ; + float temp(lat, lon) ; + temp:long_name = "temperature" ; + temp:units = "K" ; + temp:grid_mapping = "crs" ; + int crs ; + crs:grid_mapping_name = "latitude_longitude" + crs:semi_major_axis = 6371000.0 ; + crs:inverse_flattening = 0 ; + +LONLAT grid with projection parameter +GENERIC grid " +CURVILINEAR grid " +UNSTRUCTURED grid " diff --git a/doc/tex/FUNCTIONS b/doc/tex/FUNCTIONS index c82c852cf5c571b40674b65f34ecf7d9b60f3bd8..c8cbc9f36b28e8f6ae5d804c193a08f60cf56efb 100644 --- a/doc/tex/FUNCTIONS +++ b/doc/tex/FUNCTIONS @@ -71,16 +71,16 @@ Function catalog: vlistDefVarMissval Define the missing value of a Variable vlistInqVarMissval Get the missing value of a Variable ------------------------------------------------------------- - vlist_att -------------------------------------------------------------- - vlistInqNatts Get number of variable attributes - vlistInqAtt Get information about an attribute - vlistDefAttInt Define an integer attribute - vlistInqAttInt Get the value(s) of an integer attribute - vlistDefAttFlt Define a floating point attribute - vlistInqAttFlt Get the value(s) of a floating point attribute - vlistDefAttTxt Define a text attribute - vlistInqAttTxt Get the value(s) of a text attribute + cdi_att +------------------------------------------------------------- + cdiInqNatts Get number of attributes + cdiInqAtt Get information about an attribute + cdiDefAttInt Define an integer attribute + cdiInqAttInt Get the value(s) of an integer attribute + cdiDefAttFlt Define a floating point attribute + cdiInqAttFlt Get the value(s) of a floating point attribute + cdiDefAttTxt Define a text attribute + cdiInqAttTxt Get the value(s) of a text attribute ------------------------------------------------------------- grid ------------------------------------------------------------- diff --git a/doc/tex/Modules b/doc/tex/Modules index 61e3fb93137feb700c7effc66778c75a5d8a1aa9..1c1577b721fb30b0a2f08e57c59473fe7344ac33 100644 --- a/doc/tex/Modules +++ b/doc/tex/Modules @@ -50,15 +50,15 @@ vlistDefVarDatatype vlist_var vlistInqVarDatatype vlist_var vlistDefVarMissval vlist_var vlistInqVarMissval vlist_var -vlistInqNatts vlist_att -vlistInqAtt vlist_att -vlistDelAtt vlist_att -vlistDefAttInt vlist_att -vlistInqAttInt vlist_att -vlistDefAttFlt vlist_att -vlistInqAttFlt vlist_att -vlistDefAttTxt vlist_att -vlistInqAttTxt vlist_att +cdiInqNatts cdi_att +cdiInqAtt cdi_att +cdiDelAtt cdi_att +cdiDefAttInt cdi_att +cdiInqAttInt cdi_att +cdiDefAttFlt cdi_att +cdiInqAttFlt cdi_att +cdiDefAttTxt cdi_att +cdiInqAttTxt cdi_att gridCreate grid gridDestroy grid gridDuplicate grid diff --git a/doc/tex/c_cdi_att.tex b/doc/tex/c_cdi_att.tex new file mode 100644 index 0000000000000000000000000000000000000000..51b93783cc226c4c6bfb73cc110e210efabc81b3 --- /dev/null +++ b/doc/tex/c_cdi_att.tex @@ -0,0 +1,238 @@ + + +\subsection{Get number of attributes: {\tt cdiInqNatts}} +\index{cdiInqNatts} +\label{cdiInqNatts} + +The function {\tt cdiInqNatts} gets the number of attributes assigned to this variable. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiInqNatts(int cdiID, int varID, int *nattsp); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt nattsp\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt nattsp}] +Pointer to location for returned number of attributes. + +\end{deflist} +\end{minipage} + + +\subsection{Get information about an attribute: {\tt cdiInqAtt}} +\index{cdiInqAtt} +\label{cdiInqAtt} + +The function {\tt cdiInqAtt} gets information about an attribute. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt attnum\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt attnum}] +Attribute number (from 0 to natts-1). +\item[{\tt name}] +Pointer to the location for the returned attribute name. The caller must allocate space for the + returned string. The maximum possible length, in characters, of + the string is given by the predefined constant {\tt CDI\_MAX\_NAME}. +\item[{\tt typep}] +Pointer to location for returned attribute type. +\item[{\tt lenp}] +Pointer to location for returned attribute number. + +\end{deflist} +\end{minipage} + + +\subsection{Define an integer attribute: {\tt cdiDefAttInt}} +\index{cdiDefAttInt} +\label{cdiDefAttInt} + +The function {\tt cdiDefAttInt} defines an integer attribute. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, + const int *ip); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt cdiID\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt gridCreate}{gridCreate}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt name}] +Attribute name. +\item[{\tt type}] +External data type ({\tt DATATYPE\_INT16} or {\tt DATATYPE\_INT32}). +\item[{\tt len}] +Number of values provided for the attribute. +\item[{\tt ip}] +Pointer to one or more integer values. + +\end{deflist} +\end{minipage} + + +\subsection{Get the value(s) of an integer attribute: {\tt cdiInqAttInt}} +\index{cdiInqAttInt} +\label{cdiInqAttInt} + +The function {\tt cdiInqAttInt} gets the values(s) of an integer attribute. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt cdiID\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt name}] +Attribute name. +\item[{\tt mlen}] +Number of allocated values provided for the attribute. +\item[{\tt ip}] +Pointer location for returned integer attribute value(s). + +\end{deflist} +\end{minipage} + + +\subsection{Define a floating point attribute: {\tt cdiDefAttFlt}} +\index{cdiDefAttFlt} +\label{cdiDefAttFlt} + +The function {\tt cdiDefAttFlt} defines a floating point attribute. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, + const double *dp); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt cdiID\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt gridCreate}{gridCreate}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt name}] +Attribute name. +\item[{\tt type}] +External data type ({\tt DATATYPE\_FLT32} or {\tt DATATYPE\_FLT64}). +\item[{\tt len}] +Number of values provided for the attribute. +\item[{\tt dp}] +Pointer to one or more floating point values. + +\end{deflist} +\end{minipage} + + +\subsection{Get the value(s) of a floating point attribute: {\tt cdiInqAttFlt}} +\index{cdiInqAttFlt} +\label{cdiInqAttFlt} + +The function {\tt cdiInqAttFlt} gets the values(s) of a floating point attribute. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt cdiID\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt name}] +Attribute name. +\item[{\tt mlen}] +Number of allocated values provided for the attribute. +\item[{\tt dp}] +Pointer location for returned floating point attribute value(s). + +\end{deflist} +\end{minipage} + + +\subsection{Define a text attribute: {\tt cdiDefAttTxt}} +\index{cdiDefAttTxt} +\label{cdiDefAttTxt} + +The function {\tt cdiDefAttTxt} defines a text attribute. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt cdiID\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt gridCreate}{gridCreate}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt name}] +Attribute name. +\item[{\tt len}] +Number of values provided for the attribute. +\item[{\tt tp}] +Pointer to one or more character values. + +\end{deflist} +\end{minipage} + + +\subsection{Get the value(s) of a text attribute: {\tt cdiInqAttTxt}} +\index{cdiInqAttTxt} +\label{cdiInqAttTxt} + +The function {\tt cdiInqAttTxt} gets the values(s) of a text attribute. + +\subsubsection*{Usage} + +\begin{verbatim} + int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp); +\end{verbatim} + +\hspace*{4mm}\begin{minipage}[]{15cm} +\begin{deflist}{\tt cdiID\ } +\item[{\tt cdiID}] +CDI ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}, {\htmlref{\tt gridCreate}{gridCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. +\item[{\tt varID}] +Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. +\item[{\tt name}] +Attribute name. +\item[{\tt mlen}] +Number of allocated values provided for the attribute. +\item[{\tt tp}] +Pointer location for returned text attribute value(s). + +\end{deflist} +\end{minipage} diff --git a/doc/tex/c_quick_ref.tex b/doc/tex/c_quick_ref.tex index 343bd5b7621048088b6bb455c59ea74d90048fd5..3b7eb8f4b248ece1b9f3ccdfe69cd30b25e1cae9 100644 --- a/doc/tex/c_quick_ref.tex +++ b/doc/tex/c_quick_ref.tex @@ -22,6 +22,83 @@ Clear the list of additional GRIB keys.. Register an additional GRIB key which is read when file is opened.. +\section*{\tt \htmlref{cdiDefAttFlt}{cdiDefAttFlt}} + +\begin{verbatim} + int cdiDefAttFlt (int cdiID, int varID, const char *name, int type, int len, + const double dp[]); +\end{verbatim} + +Define a floating point attribute. + + +\section*{\tt \htmlref{cdiDefAttInt}{cdiDefAttInt}} + +\begin{verbatim} + int cdiDefAttInt (int cdiID, int varID, const char *name, int type, int len, + const int ip[]); +\end{verbatim} + +Define an integer attribute. + + +\section*{\tt \htmlref{cdiDefAttTxt}{cdiDefAttTxt}} + +\begin{verbatim} + int cdiDefAttTxt (int cdiID, int varID, const char *name, int len, + const char *tp_cbuf); +\end{verbatim} + +Define a text attribute. + + +\section*{\tt \htmlref{cdiInqAtt}{cdiInqAtt}} + +\begin{verbatim} + int cdiInqAtt (int cdiID, int varID, int attrnum, char *name, int *typep, + int *lenp); +\end{verbatim} + +Get information about an attribute. + + +\section*{\tt \htmlref{cdiInqAttFlt}{cdiInqAttFlt}} + +\begin{verbatim} + int cdiInqAttFlt (int cdiID, int varID, const char *name, int mlen, double dp[]); +\end{verbatim} + +Get the value(s) of a floating point attribute. + + +\section*{\tt \htmlref{cdiInqAttInt}{cdiInqAttInt}} + +\begin{verbatim} + int cdiInqAttInt (int cdiID, int varID, const char *name, int mlen, int ip[]); +\end{verbatim} + +Get the value(s) of an integer attribute. + + +\section*{\tt \htmlref{cdiInqAttTxt}{cdiInqAttTxt}} + +\begin{verbatim} + int cdiInqAttTxt (int cdiID, int varID, const char *name, int mlen, + char *tp_cbuf); +\end{verbatim} + +Get the value(s) of a text attribute. + + +\section*{\tt \htmlref{cdiInqNatts}{cdiInqNatts}} + +\begin{verbatim} + int cdiInqNatts (int cdiID, int varID, int *nattsp); +\end{verbatim} + +Get number of attributes assigned to this variable. + + \section*{\tt \htmlref{gridCreate}{gridCreate}} \begin{verbatim} @@ -76,6 +153,24 @@ Define the position of grid in the reference file. Define the precision of a Grid. +\section*{\tt \htmlref{gridDefProj}{gridDefProj}} + +\begin{verbatim} + void gridDefProj (int gridID, int projID); +\end{verbatim} + +Define the projection ID of a Grid. + + +\section*{\tt \htmlref{gridDefProjType}{gridDefProjType}} + +\begin{verbatim} + void gridDefProjType (int gridID, int projtype); +\end{verbatim} + +Define the projection type. + + \section*{\tt \htmlref{gridDefReference}{gridDefReference}} \begin{verbatim} @@ -265,6 +360,24 @@ Get the position of grid in the reference file. Get the precision of a Grid. +\section*{\tt \htmlref{gridInqProj}{gridInqProj}} + +\begin{verbatim} + int gridInqProj (int gridID); +\end{verbatim} + +Get the projection ID of a Grid. + + +\section*{\tt \htmlref{gridInqProjType}{gridInqProjType}} + +\begin{verbatim} + int gridInqProjType (int gridID); +\end{verbatim} + +Get the projection type. + + \section*{\tt \htmlref{gridInqReference}{gridInqReference}} \begin{verbatim} @@ -889,36 +1002,6 @@ Safe and convenient version of vlistInqVarName. Create a variable list. -\section*{\tt \htmlref{vlistDefAttFlt}{vlistDefAttFlt}} - -\begin{verbatim} - int vlistDefAttFlt (int vlistID, int varID, const char *name, int type, int len, - const double dp[]); -\end{verbatim} - -Define a floating point attribute. - - -\section*{\tt \htmlref{vlistDefAttInt}{vlistDefAttInt}} - -\begin{verbatim} - int vlistDefAttInt (int vlistID, int varID, const char *name, int type, int len, - const int ip[]); -\end{verbatim} - -Define an integer attribute. - - -\section*{\tt \htmlref{vlistDefAttTxt}{vlistDefAttTxt}} - -\begin{verbatim} - int vlistDefAttTxt (int vlistID, int varID, const char *name, int len, - const char *tp_cbuf); -\end{verbatim} - -Define a text attribute. - - \section*{\tt \htmlref{vlistDefTaxis}{vlistDefTaxis}} \begin{verbatim} @@ -1073,54 +1156,6 @@ Duplicate a variable list. returns 1 if meta-data key was read, 0 otherwise.. -\section*{\tt \htmlref{vlistInqAtt}{vlistInqAtt}} - -\begin{verbatim} - int vlistInqAtt (int vlistID, int varID, int attrnum, char *name, int *typep, - int *lenp); -\end{verbatim} - -Get information about an attribute. - - -\section*{\tt \htmlref{vlistInqAttFlt}{vlistInqAttFlt}} - -\begin{verbatim} - int vlistInqAttFlt (int vlistID, int varID, const char *name, int mlen, - double dp[]); -\end{verbatim} - -Get the value(s) of a floating point attribute. - - -\section*{\tt \htmlref{vlistInqAttInt}{vlistInqAttInt}} - -\begin{verbatim} - int vlistInqAttInt (int vlistID, int varID, const char *name, int mlen, int ip[]); -\end{verbatim} - -Get the value(s) of an integer attribute. - - -\section*{\tt \htmlref{vlistInqAttTxt}{vlistInqAttTxt}} - -\begin{verbatim} - int vlistInqAttTxt (int vlistID, int varID, const char *name, int mlen, - char *tp_cbuf); -\end{verbatim} - -Get the value(s) of a text attribute. - - -\section*{\tt \htmlref{vlistInqNatts}{vlistInqNatts}} - -\begin{verbatim} - int vlistInqNatts (int vlistID, int varID, int *nattsp); -\end{verbatim} - -Get number of variable attributes assigned to this variable. - - \section*{\tt \htmlref{vlistInqTaxis}{vlistInqTaxis}} \begin{verbatim} diff --git a/doc/tex/c_ref.tex b/doc/tex/c_ref.tex index d2f2700719da5658f18555e21576236753a57f70..1eeceb6017d33f66c478528794ab8687cc3cf36d 100644 --- a/doc/tex/c_ref.tex +++ b/doc/tex/c_ref.tex @@ -1,5 +1,127 @@ +\section*{\tt +\ifpdf +\hyperref[cdiDefAttFlt]{cdiDefAttFlt} +\else +cdiDefAttFlt +\fi +} +\begin{verbatim} + int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, + const double *dp); +\end{verbatim} + +Define a floating point attribute +\ifpdfoutput{}{(\ref{cdiDefAttFlt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiDefAttInt]{cdiDefAttInt} +\else +cdiDefAttInt +\fi +} +\begin{verbatim} + int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, + const int *ip); +\end{verbatim} + +Define an integer attribute +\ifpdfoutput{}{(\ref{cdiDefAttInt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiDefAttTxt]{cdiDefAttTxt} +\else +cdiDefAttTxt +\fi +} +\begin{verbatim} + int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp); +\end{verbatim} + +Define a text attribute +\ifpdfoutput{}{(\ref{cdiDefAttTxt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAtt]{cdiInqAtt} +\else +cdiInqAtt +\fi +} +\begin{verbatim} + int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp); +\end{verbatim} + +Get information about an attribute +\ifpdfoutput{}{(\ref{cdiInqAtt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAttFlt]{cdiInqAttFlt} +\else +cdiInqAttFlt +\fi +} +\begin{verbatim} + int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp); +\end{verbatim} + +Get the value(s) of a floating point attribute +\ifpdfoutput{}{(\ref{cdiInqAttFlt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAttInt]{cdiInqAttInt} +\else +cdiInqAttInt +\fi +} +\begin{verbatim} + int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip); +\end{verbatim} + +Get the value(s) of an integer attribute +\ifpdfoutput{}{(\ref{cdiInqAttInt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAttTxt]{cdiInqAttTxt} +\else +cdiInqAttTxt +\fi +} +\begin{verbatim} + int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp); +\end{verbatim} + +Get the value(s) of a text attribute +\ifpdfoutput{}{(\ref{cdiInqAttTxt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqNatts]{cdiInqNatts} +\else +cdiInqNatts +\fi +} +\begin{verbatim} + int cdiInqNatts(int cdiID, int varID, int *nattsp); +\end{verbatim} + +Get number of attributes +\ifpdfoutput{}{(\ref{cdiInqNatts})} + + \section*{\tt \ifpdf \hyperref[gridCreate]{gridCreate} @@ -1114,53 +1236,6 @@ Create a variable list \ifpdfoutput{}{(\ref{vlistCreate})} -\section*{\tt -\ifpdf -\hyperref[vlistDefAttFlt]{vlistDefAttFlt} -\else -vlistDefAttFlt -\fi -} -\begin{verbatim} - int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, - const double *dp); -\end{verbatim} - -Define a floating point attribute -\ifpdfoutput{}{(\ref{vlistDefAttFlt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistDefAttInt]{vlistDefAttInt} -\else -vlistDefAttInt -\fi -} -\begin{verbatim} - int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, - const int *ip); -\end{verbatim} - -Define an integer attribute -\ifpdfoutput{}{(\ref{vlistDefAttInt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistDefAttTxt]{vlistDefAttTxt} -\else -vlistDefAttTxt -\fi -} -\begin{verbatim} - int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp); -\end{verbatim} - -Define a text attribute -\ifpdfoutput{}{(\ref{vlistDefAttTxt})} - - \section*{\tt \ifpdf \hyperref[vlistDefTaxis]{vlistDefTaxis} @@ -1326,81 +1401,6 @@ Duplicate a variable list \ifpdfoutput{}{(\ref{vlistDuplicate})} -\section*{\tt -\ifpdf -\hyperref[vlistInqAtt]{vlistInqAtt} -\else -vlistInqAtt -\fi -} -\begin{verbatim} - int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp); -\end{verbatim} - -Get information about an attribute -\ifpdfoutput{}{(\ref{vlistInqAtt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqAttFlt]{vlistInqAttFlt} -\else -vlistInqAttFlt -\fi -} -\begin{verbatim} - int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp); -\end{verbatim} - -Get the value(s) of a floating point attribute -\ifpdfoutput{}{(\ref{vlistInqAttFlt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqAttInt]{vlistInqAttInt} -\else -vlistInqAttInt -\fi -} -\begin{verbatim} - int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip); -\end{verbatim} - -Get the value(s) of an integer attribute -\ifpdfoutput{}{(\ref{vlistInqAttInt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqAttTxt]{vlistInqAttTxt} -\else -vlistInqAttTxt -\fi -} -\begin{verbatim} - int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp); -\end{verbatim} - -Get the value(s) of a text attribute -\ifpdfoutput{}{(\ref{vlistInqAttTxt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqNatts]{vlistInqNatts} -\else -vlistInqNatts -\fi -} -\begin{verbatim} - int vlistInqNatts(int vlistID, int varID, int *nattsp); -\end{verbatim} - -Get number of variable attributes -\ifpdfoutput{}{(\ref{vlistInqNatts})} - - \section*{\tt \ifpdf \hyperref[vlistInqTaxis]{vlistInqTaxis} diff --git a/doc/tex/c_vlist_att.tex b/doc/tex/c_vlist_att.tex deleted file mode 100644 index ab6ac2793929e10bb50cb55cf49ee20695784968..0000000000000000000000000000000000000000 --- a/doc/tex/c_vlist_att.tex +++ /dev/null @@ -1,238 +0,0 @@ - - -\subsection{Get number of variable attributes: {\tt vlistInqNatts}} -\index{vlistInqNatts} -\label{vlistInqNatts} - -The function {\tt vlistInqNatts} gets the number of variable attributes assigned to this variable. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistInqNatts(int vlistID, int varID, int *nattsp); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt nattsp}] -Pointer to location for returned number of variable attributes. - -\end{deflist} -\end{minipage} - - -\subsection{Get information about an attribute: {\tt vlistInqAtt}} -\index{vlistInqAtt} -\label{vlistInqAtt} - -The function {\tt vlistInqAtt} gets information about an attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt attnum}] -Attribute number (from 0 to natts-1). -\item[{\tt name}] -Pointer to the location for the returned attribute name. The caller must allocate space for the - returned string. The maximum possible length, in characters, of - the string is given by the predefined constant {\tt CDI\_MAX\_NAME}. -\item[{\tt typep}] -Pointer to location for returned attribute type. -\item[{\tt lenp}] -Pointer to location for returned attribute number. - -\end{deflist} -\end{minipage} - - -\subsection{Define an integer attribute: {\tt vlistDefAttInt}} -\index{vlistDefAttInt} -\label{vlistDefAttInt} - -The function {\tt vlistDefAttInt} defines an integer attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, - const int *ip); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt type}] -External data type ({\tt DATATYPE\_INT16} or {\tt DATATYPE\_INT32}). -\item[{\tt len}] -Number of values provided for the attribute. -\item[{\tt ip}] -Pointer to one or more integer values. - -\end{deflist} -\end{minipage} - - -\subsection{Get the value(s) of an integer attribute: {\tt vlistInqAttInt}} -\index{vlistInqAttInt} -\label{vlistInqAttInt} - -The function {\tt vlistInqAttInt} gets the values(s) of an integer attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt mlen}] -Number of allocated values provided for the attribute. -\item[{\tt ip}] -Pointer location for returned integer attribute value(s). - -\end{deflist} -\end{minipage} - - -\subsection{Define a floating point attribute: {\tt vlistDefAttFlt}} -\index{vlistDefAttFlt} -\label{vlistDefAttFlt} - -The function {\tt vlistDefAttFlt} defines a floating point attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, - const double *dp); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt type}] -External data type ({\tt DATATYPE\_FLT32} or {\tt DATATYPE\_FLT64}). -\item[{\tt len}] -Number of values provided for the attribute. -\item[{\tt dp}] -Pointer to one or more floating point values. - -\end{deflist} -\end{minipage} - - -\subsection{Get the value(s) of a floating point attribute: {\tt vlistInqAttFlt}} -\index{vlistInqAttFlt} -\label{vlistInqAttFlt} - -The function {\tt vlistInqAttFlt} gets the values(s) of a floating point attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt mlen}] -Number of allocated values provided for the attribute. -\item[{\tt dp}] -Pointer location for returned floating point attribute value(s). - -\end{deflist} -\end{minipage} - - -\subsection{Define a text attribute: {\tt vlistDefAttTxt}} -\index{vlistDefAttTxt} -\label{vlistDefAttTxt} - -The function {\tt vlistDefAttTxt} defines a text attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt len}] -Number of values provided for the attribute. -\item[{\tt tp}] -Pointer to one or more character values. - -\end{deflist} -\end{minipage} - - -\subsection{Get the value(s) of a text attribute: {\tt vlistInqAttTxt}} -\index{vlistInqAttTxt} -\label{vlistInqAttTxt} - -The function {\tt vlistInqAttTxt} gets the values(s) of a text attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp); -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt mlen}] -Number of allocated values provided for the attribute. -\item[{\tt tp}] -Pointer location for returned text attribute value(s). - -\end{deflist} -\end{minipage} diff --git a/doc/tex/cdi_cman.tex b/doc/tex/cdi_cman.tex index f319228a45c9377d41db8c9dea145b2cca783a62..31c8bdabe96a367d42775d367c87b988d1b1f379 100644 --- a/doc/tex/cdi_cman.tex +++ b/doc/tex/cdi_cman.tex @@ -135,7 +135,7 @@ \end{picture} \begin{flushright} -{\large\bfseries Climate Data Interface \\ Version 1.7.1 \\ February 2016} +{\large\bfseries Climate Data Interface \\ Version 1.8.0 \\ October 2016} \end{flushright} \vfill @@ -193,7 +193,7 @@ \newpage \section{Attributes} \input{attribute} -\input{c_vlist_att} +\input{c_cdi_att} \newpage diff --git a/doc/tex/cdi_fman.tex b/doc/tex/cdi_fman.tex index 31b030028a1c06be8f098a6f1c152b55e4163bcb..d3735879dc068711871136641f1f17e23fc4f976 100644 --- a/doc/tex/cdi_fman.tex +++ b/doc/tex/cdi_fman.tex @@ -132,7 +132,7 @@ \end{picture} \begin{flushright} -{\large\bfseries Climate Data Interface \\ Version 1.7.1 \\ February 2016} +{\large\bfseries Climate Data Interface \\ Version 1.8.0 \\ October 2016} \end{flushright} \vfill @@ -190,7 +190,7 @@ \newpage \section{Attributes} \input{attribute} -\input{f_vlist_att} +\input{f_cdi_att} \newpage diff --git a/doc/tex/f_quick_ref.tex b/doc/tex/f_quick_ref.tex index f4fb0987db509f6408c2a246c1de432f5996d0ff..641ba5fa7920622142758b24b4a0e1fb81b98e30 100644 --- a/doc/tex/f_quick_ref.tex +++ b/doc/tex/f_quick_ref.tex @@ -22,6 +22,85 @@ Clear the list of additional GRIB keys.. Register an additional GRIB key which is read when file is opened.. +\section*{\tt \htmlref{cdiDefAttFlt}{cdiDefAttFlt}} + +\begin{verbatim} + INTEGER FUNCTION cdiDefAttFlt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER type, INTEGER len, DOUBLEPRECISION dp(*)) +\end{verbatim} + +Define a floating point attribute. + + +\section*{\tt \htmlref{cdiDefAttInt}{cdiDefAttInt}} + +\begin{verbatim} + INTEGER FUNCTION cdiDefAttInt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER type, INTEGER len, INTEGER ip(*)) +\end{verbatim} + +Define an integer attribute. + + +\section*{\tt \htmlref{cdiDefAttTxt}{cdiDefAttTxt}} + +\begin{verbatim} + INTEGER FUNCTION cdiDefAttTxt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER len, CHARACTER*(*) tp_cbuf) +\end{verbatim} + +Define a text attribute. + + +\section*{\tt \htmlref{cdiInqAtt}{cdiInqAtt}} + +\begin{verbatim} + INTEGER FUNCTION cdiInqAtt (INTEGER cdiID, INTEGER varID, INTEGER attrnum, + CHARACTER*(*) name, INTEGER typep, INTEGER lenp) +\end{verbatim} + +Get information about an attribute. + + +\section*{\tt \htmlref{cdiInqAttFlt}{cdiInqAttFlt}} + +\begin{verbatim} + INTEGER FUNCTION cdiInqAttFlt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER mlen, DOUBLEPRECISION dp(*)) +\end{verbatim} + +Get the value(s) of a floating point attribute. + + +\section*{\tt \htmlref{cdiInqAttInt}{cdiInqAttInt}} + +\begin{verbatim} + INTEGER FUNCTION cdiInqAttInt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER mlen, INTEGER ip(*)) +\end{verbatim} + +Get the value(s) of an integer attribute. + + +\section*{\tt \htmlref{cdiInqAttTxt}{cdiInqAttTxt}} + +\begin{verbatim} + INTEGER FUNCTION cdiInqAttTxt (INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER mlen, CHARACTER*(*) tp_cbuf) +\end{verbatim} + +Get the value(s) of a text attribute. + + +\section*{\tt \htmlref{cdiInqNatts}{cdiInqNatts}} + +\begin{verbatim} + INTEGER FUNCTION cdiInqNatts (INTEGER cdiID, INTEGER varID, INTEGER nattsp) +\end{verbatim} + +Get number of attributes assigned to this variable. + + \section*{\tt \htmlref{gridCreate}{gridCreate}} \begin{verbatim} @@ -76,6 +155,24 @@ Define the position of grid in the reference file. Define the precision of a Grid. +\section*{\tt \htmlref{gridDefProj}{gridDefProj}} + +\begin{verbatim} + SUBROUTINE gridDefProj (INTEGER gridID, INTEGER projID) +\end{verbatim} + +Define the projection ID of a Grid. + + +\section*{\tt \htmlref{gridDefProjType}{gridDefProjType}} + +\begin{verbatim} + SUBROUTINE gridDefProjType (INTEGER gridID, INTEGER projtype) +\end{verbatim} + +Define the projection type. + + \section*{\tt \htmlref{gridDefReference}{gridDefReference}} \begin{verbatim} @@ -265,6 +362,24 @@ Get the position of grid in the reference file. Get the precision of a Grid. +\section*{\tt \htmlref{gridInqProj}{gridInqProj}} + +\begin{verbatim} + INTEGER FUNCTION gridInqProj (INTEGER gridID) +\end{verbatim} + +Get the projection ID of a Grid. + + +\section*{\tt \htmlref{gridInqProjType}{gridInqProjType}} + +\begin{verbatim} + INTEGER FUNCTION gridInqProjType (INTEGER gridID) +\end{verbatim} + +Get the projection type. + + \section*{\tt \htmlref{gridInqReference}{gridInqReference}} \begin{verbatim} @@ -892,39 +1007,6 @@ Safe and convenient version of vlistInqVarName. Create a variable list. -\section*{\tt \htmlref{vlistDefAttFlt}{vlistDefAttFlt}} - -\begin{verbatim} - INTEGER FUNCTION vlistDefAttFlt (INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER type, INTEGER len, - DOUBLEPRECISION dp(*)) -\end{verbatim} - -Define a floating point attribute. - - -\section*{\tt \htmlref{vlistDefAttInt}{vlistDefAttInt}} - -\begin{verbatim} - INTEGER FUNCTION vlistDefAttInt (INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER type, INTEGER len, - INTEGER ip(*)) -\end{verbatim} - -Define an integer attribute. - - -\section*{\tt \htmlref{vlistDefAttTxt}{vlistDefAttTxt}} - -\begin{verbatim} - INTEGER FUNCTION vlistDefAttTxt (INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER len, - CHARACTER*(*) tp_cbuf) -\end{verbatim} - -Define a text attribute. - - \section*{\tt \htmlref{vlistDefTaxis}{vlistDefTaxis}} \begin{verbatim} @@ -1087,57 +1169,6 @@ Duplicate a variable list. returns 1 if meta-data key was read, 0 otherwise.. -\section*{\tt \htmlref{vlistInqAtt}{vlistInqAtt}} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAtt (INTEGER vlistID, INTEGER varID, INTEGER attrnum, - CHARACTER*(*) name, INTEGER typep, INTEGER lenp) -\end{verbatim} - -Get information about an attribute. - - -\section*{\tt \htmlref{vlistInqAttFlt}{vlistInqAttFlt}} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAttFlt (INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, - DOUBLEPRECISION dp(*)) -\end{verbatim} - -Get the value(s) of a floating point attribute. - - -\section*{\tt \htmlref{vlistInqAttInt}{vlistInqAttInt}} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAttInt (INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, INTEGER ip(*)) -\end{verbatim} - -Get the value(s) of an integer attribute. - - -\section*{\tt \htmlref{vlistInqAttTxt}{vlistInqAttTxt}} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAttTxt (INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, - CHARACTER*(*) tp_cbuf) -\end{verbatim} - -Get the value(s) of a text attribute. - - -\section*{\tt \htmlref{vlistInqNatts}{vlistInqNatts}} - -\begin{verbatim} - INTEGER FUNCTION vlistInqNatts (INTEGER vlistID, INTEGER varID, INTEGER nattsp) -\end{verbatim} - -Get number of variable attributes assigned to this variable. - - \section*{\tt \htmlref{vlistInqTaxis}{vlistInqTaxis}} \begin{verbatim} diff --git a/doc/tex/f_ref.tex b/doc/tex/f_ref.tex index aa39d317df9aa237c2c95f9205f879d96d110ffa..6ab0656612e84621b380050b538227c82fe7fd92 100644 --- a/doc/tex/f_ref.tex +++ b/doc/tex/f_ref.tex @@ -1,5 +1,132 @@ +\section*{\tt +\ifpdf +\hyperref[cdiDefAttFlt]{cdiDefAttFlt} +\else +cdiDefAttFlt +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiDefAttFlt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER type, INTEGER len, REAL*8 dp) +\end{verbatim} + +Define a floating point attribute +\ifpdfoutput{}{(\ref{cdiDefAttFlt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiDefAttInt]{cdiDefAttInt} +\else +cdiDefAttInt +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiDefAttInt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER type, INTEGER len, INTEGER ip) +\end{verbatim} + +Define an integer attribute +\ifpdfoutput{}{(\ref{cdiDefAttInt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiDefAttTxt]{cdiDefAttTxt} +\else +cdiDefAttTxt +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiDefAttTxt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER len, CHARACTER*(*) tp) +\end{verbatim} + +Define a text attribute +\ifpdfoutput{}{(\ref{cdiDefAttTxt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAtt]{cdiInqAtt} +\else +cdiInqAtt +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiInqAtt(INTEGER cdiID, INTEGER varID, INTEGER attnum, + CHARACTER*(*) name, INTEGER typep, INTEGER lenp) +\end{verbatim} + +Get information about an attribute +\ifpdfoutput{}{(\ref{cdiInqAtt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAttFlt]{cdiInqAttFlt} +\else +cdiInqAttFlt +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiInqAttFlt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER mlen, REAL*8 dp) +\end{verbatim} + +Get the value(s) of a floating point attribute +\ifpdfoutput{}{(\ref{cdiInqAttFlt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAttInt]{cdiInqAttInt} +\else +cdiInqAttInt +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiInqAttInt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER mlen, INTEGER ip) +\end{verbatim} + +Get the value(s) of an integer attribute +\ifpdfoutput{}{(\ref{cdiInqAttInt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqAttTxt]{cdiInqAttTxt} +\else +cdiInqAttTxt +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiInqAttTxt(INTEGER cdiID, INTEGER varID, CHARACTER*(*) name, + INTEGER mlen, CHARACTER*(*) tp) +\end{verbatim} + +Get the value(s) of a text attribute +\ifpdfoutput{}{(\ref{cdiInqAttTxt})} + + +\section*{\tt +\ifpdf +\hyperref[cdiInqNatts]{cdiInqNatts} +\else +cdiInqNatts +\fi +} +\begin{verbatim} + INTEGER FUNCTION cdiInqNatts(INTEGER cdiID, INTEGER varID, INTEGER nattsp) +\end{verbatim} + +Get number of attributes +\ifpdfoutput{}{(\ref{cdiInqNatts})} + + \section*{\tt \ifpdf \hyperref[gridCreate]{gridCreate} @@ -1118,57 +1245,6 @@ Create a variable list \ifpdfoutput{}{(\ref{vlistCreate})} -\section*{\tt -\ifpdf -\hyperref[vlistDefAttFlt]{vlistDefAttFlt} -\else -vlistDefAttFlt -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistDefAttFlt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER type, INTEGER len, - REAL*8 dp) -\end{verbatim} - -Define a floating point attribute -\ifpdfoutput{}{(\ref{vlistDefAttFlt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistDefAttInt]{vlistDefAttInt} -\else -vlistDefAttInt -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistDefAttInt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER type, INTEGER len, - INTEGER ip) -\end{verbatim} - -Define an integer attribute -\ifpdfoutput{}{(\ref{vlistDefAttInt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistDefAttTxt]{vlistDefAttTxt} -\else -vlistDefAttTxt -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistDefAttTxt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER len, - CHARACTER*(*) tp) -\end{verbatim} - -Define a text attribute -\ifpdfoutput{}{(\ref{vlistDefAttTxt})} - - \section*{\tt \ifpdf \hyperref[vlistDefTaxis]{vlistDefTaxis} @@ -1337,86 +1413,6 @@ Duplicate a variable list \ifpdfoutput{}{(\ref{vlistDuplicate})} -\section*{\tt -\ifpdf -\hyperref[vlistInqAtt]{vlistInqAtt} -\else -vlistInqAtt -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistInqAtt(INTEGER vlistID, INTEGER varID, INTEGER attnum, - CHARACTER*(*) name, INTEGER typep, INTEGER lenp) -\end{verbatim} - -Get information about an attribute -\ifpdfoutput{}{(\ref{vlistInqAtt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqAttFlt]{vlistInqAttFlt} -\else -vlistInqAttFlt -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistInqAttFlt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, REAL*8 dp) -\end{verbatim} - -Get the value(s) of a floating point attribute -\ifpdfoutput{}{(\ref{vlistInqAttFlt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqAttInt]{vlistInqAttInt} -\else -vlistInqAttInt -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistInqAttInt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, INTEGER ip) -\end{verbatim} - -Get the value(s) of an integer attribute -\ifpdfoutput{}{(\ref{vlistInqAttInt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqAttTxt]{vlistInqAttTxt} -\else -vlistInqAttTxt -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistInqAttTxt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, - CHARACTER*(*) tp) -\end{verbatim} - -Get the value(s) of a text attribute -\ifpdfoutput{}{(\ref{vlistInqAttTxt})} - - -\section*{\tt -\ifpdf -\hyperref[vlistInqNatts]{vlistInqNatts} -\else -vlistInqNatts -\fi -} -\begin{verbatim} - INTEGER FUNCTION vlistInqNatts(INTEGER vlistID, INTEGER varID, INTEGER nattsp) -\end{verbatim} - -Get number of variable attributes -\ifpdfoutput{}{(\ref{vlistInqNatts})} - - \section*{\tt \ifpdf \hyperref[vlistInqTaxis]{vlistInqTaxis} diff --git a/doc/tex/f_vlist_att.tex b/doc/tex/f_vlist_att.tex deleted file mode 100644 index c60a032d416cd620ffa69d0b5e7ef3e7b2ba8365..0000000000000000000000000000000000000000 --- a/doc/tex/f_vlist_att.tex +++ /dev/null @@ -1,247 +0,0 @@ - - -\subsection{Get number of variable attributes: {\tt vlistInqNatts}} -\index{vlistInqNatts} -\label{vlistInqNatts} - -The function {\tt vlistInqNatts} gets the number of variable attributes assigned to this variable. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistInqNatts(INTEGER vlistID, INTEGER varID, INTEGER nattsp) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt nattsp}] -Pointer to location for returned number of variable attributes. - -\end{deflist} -\end{minipage} - - -\subsection{Get information about an attribute: {\tt vlistInqAtt}} -\index{vlistInqAtt} -\label{vlistInqAtt} - -The function {\tt vlistInqAtt} gets information about an attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAtt(INTEGER vlistID, INTEGER varID, INTEGER attnum, - CHARACTER*(*) name, INTEGER typep, INTEGER lenp) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt attnum}] -Attribute number (from 0 to natts-1). -\item[{\tt name}] -Pointer to the location for the returned attribute name. The caller must allocate space for the - returned string. The maximum possible length, in characters, of - the string is given by the predefined constant {\tt CDI\_MAX\_NAME}. -\item[{\tt typep}] -Pointer to location for returned attribute type. -\item[{\tt lenp}] -Pointer to location for returned attribute number. - -\end{deflist} -\end{minipage} - - -\subsection{Define an integer attribute: {\tt vlistDefAttInt}} -\index{vlistDefAttInt} -\label{vlistDefAttInt} - -The function {\tt vlistDefAttInt} defines an integer attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistDefAttInt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER type, INTEGER len, - INTEGER ip) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt type}] -External data type ({\tt DATATYPE\_INT16} or {\tt DATATYPE\_INT32}). -\item[{\tt len}] -Number of values provided for the attribute. -\item[{\tt ip}] -Pointer to one or more integer values. - -\end{deflist} -\end{minipage} - - -\subsection{Get the value(s) of an integer attribute: {\tt vlistInqAttInt}} -\index{vlistInqAttInt} -\label{vlistInqAttInt} - -The function {\tt vlistInqAttInt} gets the values(s) of an integer attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAttInt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, INTEGER ip) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt mlen}] -Number of allocated values provided for the attribute. -\item[{\tt ip}] -Pointer location for returned integer attribute value(s). - -\end{deflist} -\end{minipage} - - -\subsection{Define a floating point attribute: {\tt vlistDefAttFlt}} -\index{vlistDefAttFlt} -\label{vlistDefAttFlt} - -The function {\tt vlistDefAttFlt} defines a floating point attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistDefAttFlt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER type, INTEGER len, - REAL*8 dp) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt type}] -External data type ({\tt DATATYPE\_FLT32} or {\tt DATATYPE\_FLT64}). -\item[{\tt len}] -Number of values provided for the attribute. -\item[{\tt dp}] -Pointer to one or more floating point values. - -\end{deflist} -\end{minipage} - - -\subsection{Get the value(s) of a floating point attribute: {\tt vlistInqAttFlt}} -\index{vlistInqAttFlt} -\label{vlistInqAttFlt} - -The function {\tt vlistInqAttFlt} gets the values(s) of a floating point attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAttFlt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, REAL*8 dp) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt mlen}] -Number of allocated values provided for the attribute. -\item[{\tt dp}] -Pointer location for returned floating point attribute value(s). - -\end{deflist} -\end{minipage} - - -\subsection{Define a text attribute: {\tt vlistDefAttTxt}} -\index{vlistDefAttTxt} -\label{vlistDefAttTxt} - -The function {\tt vlistDefAttTxt} defines a text attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistDefAttTxt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER len, - CHARACTER*(*) tp) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt len}] -Number of values provided for the attribute. -\item[{\tt tp}] -Pointer to one or more character values. - -\end{deflist} -\end{minipage} - - -\subsection{Get the value(s) of a text attribute: {\tt vlistInqAttTxt}} -\index{vlistInqAttTxt} -\label{vlistInqAttTxt} - -The function {\tt vlistInqAttTxt} gets the values(s) of a text attribute. - -\subsubsection*{Usage} - -\begin{verbatim} - INTEGER FUNCTION vlistInqAttTxt(INTEGER vlistID, INTEGER varID, - CHARACTER*(*) name, INTEGER mlen, - CHARACTER*(*) tp) -\end{verbatim} - -\hspace*{4mm}\begin{minipage}[]{15cm} -\begin{deflist}{\tt vlistID\ } -\item[{\tt vlistID}] -Variable list ID, from a previous call to {\htmlref{\tt vlistCreate}{vlistCreate}} or {\htmlref{\tt streamInqVlist}{streamInqVlist}}. -\item[{\tt varID}] -Variable identifier, or {\tt CDI\_GLOBAL} for a global attribute. -\item[{\tt name}] -Attribute name. -\item[{\tt mlen}] -Number of allocated values provided for the attribute. -\item[{\tt tp}] -Pointer location for returned text attribute value(s). - -\end{deflist} -\end{minipage} diff --git a/examples/Makefile.in b/examples/Makefile.in index 49afd2628e9024792dce33f2cc98053c4b8396bb..906edcab0bf34d1fd73a267b897047155ffe2e73 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -314,11 +314,9 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JASPER_LIBS = @JASPER_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -342,7 +340,6 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENJPEG_LIBS = @OPENJPEG_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -424,7 +421,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -openjpeg_LIBS = @openjpeg_LIBS@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/examples/pio/Makefile.in b/examples/pio/Makefile.in index 1536458295266d33fa2ed9d9b5715fdcc9080852..5f27b589a10f670eec89094c1ad771d9a3278b13 100644 --- a/examples/pio/Makefile.in +++ b/examples/pio/Makefile.in @@ -308,11 +308,9 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JASPER_LIBS = @JASPER_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -336,7 +334,6 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENJPEG_LIBS = @OPENJPEG_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -418,7 +415,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -openjpeg_LIBS = @openjpeg_LIBS@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/interfaces/Makefile.in b/interfaces/Makefile.in index a7c5b60d9147d558d4a54ba07aa76f80ef61197c..49bc17892e09fdd44e4e509b88fd988c54a02bd0 100644 --- a/interfaces/Makefile.in +++ b/interfaces/Makefile.in @@ -292,11 +292,9 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JASPER_LIBS = @JASPER_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -320,7 +318,6 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENJPEG_LIBS = @OPENJPEG_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -402,7 +399,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -openjpeg_LIBS = @openjpeg_LIBS@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/m4/acx_options.m4 b/m4/acx_options.m4 index 8782e5893883b0c57738dbc5c76303fd15394c35..ed3ebb4548ecac6acbc9e6fd9f9da85891bd1938 100644 --- a/m4/acx_options.m4 +++ b/m4/acx_options.m4 @@ -151,84 +151,6 @@ AC_SUBST([NETCDF_ROOT]) AC_SUBST([NETCDF_INCLUDE]) AC_SUBST([NETCDF_LIBS]) # ---------------------------------------------------------------------- -# Link application with JASPER library (needed for GRIB2 compression) -JASPER_LIBS='' -AC_ARG_WITH([jasper], - [AS_HELP_STRING([--with-jasper=<directory>], - [Specify location of JASPER library. You must specify its location if GRIB_API was built with JASPER.])], - [AS_CASE(["$with_jasper"], - [no],[AC_MSG_CHECKING([for jasper library]) - AC_MSG_RESULT([suppressed])], - [yes],[AC_CHECK_HEADERS([jasper.h]) - AC_SEARCH_LIBS([jas_init],[jasper],[AC_DEFINE([HAVE_LIBJASPER],[1],[Define to 1 for JPEG compression for GRIB2])], - [AC_MSG_ERROR([Could not link to jasper library! Required for GRIB_API])]) - AC_SUBST([JASPER_LIBS],[" -ljasper"])], - [*],[JASPER_ROOT=$with_jasper - AS_IF([test -d "$JASPER_ROOT"], - [LDFLAGS="$LDFLAGS -L$JASPER_ROOT/lib" - CPPFLAGS="$CPPFLAGS -I$JASPER_ROOT/include" - AC_SEARCH_LIBS([jas_stream_memopen], - [jasper], - [AC_DEFINE([HAVE_LIBJASPER],[1],[Define to 1 for JPEG compression for GRIB2])], - [AC_MSG_ERROR([Could not link to jasper library! Required for GRIB_API])]) - JASPER_LIBS=" -L$JASPER_ROOT/lib -ljasper"], - [AC_MSG_ERROR([$JASPER_ROOT is not a directory! JASPER suppressed])])])], - [AC_MSG_CHECKING([for the JASPER library]) - AC_MSG_RESULT([suppressed])]) -AC_SUBST([JASPER_LIBS]) -# ---------------------------------------------------------------------- -# Link application with openjpeg library (needed for GRIB2 compression) -OPENJPEG_LIBS='' -AC_ARG_WITH([openjpeg], - [AS_HELP_STRING([--with-openjpeg=<directory>], - [Specify location of openjpeg library. You must specify its location if GRIB_API was built with openjpeg.])], - [AS_CASE(["$with_openjpeg"], - [no],[AC_MSG_CHECKING([for openjpeg library]) - AC_MSG_RESULT([suppressed])], - [yes],[AC_CHECK_HEADERS([openjpeg.h]) - AC_SEARCH_LIBS([opj_image_create],[openjpeg],[AC_DEFINE([HAVE_LIBOPENJPEG],[1],[Define to 1 for JPEG compression for GRIB2])], - [AC_MSG_ERROR([Could not link to openjpeg library! Required for GRIB_API])]) - AC_SUBST([openjpeg_LIBS],[" -lopenjpeg"])], - [*],[OPENJPEG_ROOT=$with_openjpeg - AS_IF([test -d "$OPENJPEG_ROOT"], - [LDFLAGS="$LDFLAGS -L$OPENJPEG_ROOT/lib" - CPPFLAGS="$CPPFLAGS -I$OPENJPEG_ROOT/include" - AC_SEARCH_LIBS([opj_image_create], - [openjpeg], - [AC_DEFINE([HAVE_LIBOPENJPEG],[1],[Define to 1 for JPEG compression for GRIB2])], - [AC_MSG_ERROR([Could not link to openjpeg library! Required for GRIB_API])]) - OPENJPEG_LIBS=" -L$OPENJPEG_ROOT/lib -lopenjpeg"], - [AC_MSG_ERROR([$OPENJPEG_ROOT is not a directory! openjpeg suppressed])])])], - [AC_MSG_CHECKING([for the openjpeg library]) - AC_MSG_RESULT([suppressed])]) -AC_SUBST([OPENJPEG_LIBS]) -# ---------------------------------------------------------------------- -# Link application with LIBPNG library (needed for GRIB2 compression) -LIBPNG_LIBS='' -AC_ARG_WITH([libpng], - [AS_HELP_STRING([--with-libpng=<directory>], - [Specify location of LIBPNG library. You must specify its location if GRIB_API was built with LIBPNG.])], - [AS_CASE(["$with_libpng"], - [no],[AC_MSG_CHECKING([for libpng library]) - AC_MSG_RESULT([suppressed])], - [yes],[AC_CHECK_HEADERS([png.h]) - AC_SEARCH_LIBS([png_warning],[png],[AC_DEFINE([HAVE_LIBLIBPNG],[1],[Define to 1 for PNG compression for GRIB2])], - [AC_MSG_ERROR([Could not link to libpng library! Required for GRIB_API])]) - AC_SUBST([LIBPNG_LIBS],[" -lpng"])], - [*],[LIBPNG_ROOT=$with_libpng - AS_IF([test -d "$LIBPNG_ROOT"], - [LDFLAGS="$LDFLAGS -L$LIBPNG_ROOT/lib" - CPPFLAGS="$CPPFLAGS -I$LIBPNG_ROOT/include" - AC_SEARCH_LIBS([png_warning], - [png], - [AC_DEFINE([HAVE_LIBLIBPNG],[1],[Define to 1 for PNG compression for GRIB2])], - [AC_MSG_ERROR([Could not link to libpng library! Required for GRIB_API])]) - LIBPNG_LIBS=" -L$LIBPNG_ROOT/lib -lpng"], - [AC_MSG_ERROR([$LIBPNG_ROOT is not a directory! LIBPNG suppressed])])])], - [AC_MSG_CHECKING([for the LIBPNG library]) - AC_MSG_RESULT([suppressed])]) -AC_SUBST([LIBPNG_LIBS]) -# ---------------------------------------------------------------------- # Compile application with GRIB_API library (for GRIB2 support) GRIB_API_INCLUDE='' GRIB_API_LIBS='' diff --git a/src/Makefile.am b/src/Makefile.am index bc78a1e965687f6810074ff676b09db9f3bb966d..0bdb6c46247208c9b485f72b221b5208ba493c64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,6 +24,8 @@ libcdi_la_SOURCES = \ cdf.h \ cdf_int.c \ cdf_int.h \ + cdf_util.c \ + cdf_util.h \ cdi.h \ cdi_error.c \ cdi_limits.h \ @@ -71,7 +73,8 @@ libcdi_la_SOURCES = \ resource_handle.h\ service.h \ servicelib.c \ - stream_cdf.c \ + stream_cdf_i.c \ + stream_cdf_o.c \ stream_cdf.h \ stream_cgribex.c \ stream_cgribex.h \ @@ -83,8 +86,6 @@ libcdi_la_SOURCES = \ stream_history.c \ stream_ieg.c \ stream_ieg.h \ - stream_fcommon.c \ - stream_fcommon.h \ cdi_int.c \ cdi_int.h \ stream_record.c \ @@ -95,6 +96,8 @@ libcdi_la_SOURCES = \ grb_read.c \ cdf_write.c \ cdf_read.c \ + cdf_lazy_grid.c \ + cdf_lazy_grid.h \ subtype.c \ subtype.h \ swap.h \ @@ -112,8 +115,8 @@ libcdi_la_SOURCES = \ version.c \ vlist.c \ vlist.h \ - vlist_att.c \ - vlist_att.h \ + cdi_att.c \ + cdi_att.h \ vlist_var.c \ vlist_var.h \ zaxis.c \ diff --git a/src/Makefile.in b/src/Makefile.in index ec0a5dfcc0832e90f2e27022889cb27b0372b949..234a5d46f45d3ac46d56f25594a163057b0e4ff5 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -168,26 +168,27 @@ LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libcdi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__libcdi_la_SOURCES_DIST = basetime.c basetime.h binary.c binary.h \ - calendar.c calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdi.h \ - cdi_error.c cdi_limits.h cdi_util.c cgribex.h cgribexlib.c \ - datetime.h dmemory.c dmemory.h cksum.c cksum.h cdi_cksum.c \ - cdi_cksum.h cdi_uuid.h dtypes.h error.c error.h exse.h extra.h \ - extralib.c file.c file.h gaussgrid.c gaussgrid.h gribapi.c \ - gribapi.h gribapi_utilities.h grid.c grid.h ieg.h ieglib.c \ - input_file.c input_file.h institution.c institution.h model.c \ - model.h namespace.c namespace.h serialize.h serialize.c \ + calendar.c calendar.h cdf.c cdf.h cdf_int.c cdf_int.h \ + cdf_util.c cdf_util.h cdi.h cdi_error.c cdi_limits.h \ + cdi_util.c cgribex.h cgribexlib.c datetime.h dmemory.c \ + dmemory.h cksum.c cksum.h cdi_cksum.c cdi_cksum.h cdi_uuid.h \ + dtypes.h error.c error.h exse.h extra.h extralib.c file.c \ + file.h gaussgrid.c gaussgrid.h gribapi.c gribapi.h \ + gribapi_utilities.h grid.c grid.h ieg.h ieglib.c input_file.c \ + input_file.h institution.c institution.h model.c model.h \ + namespace.c namespace.h serialize.h serialize.c \ referenceCounting.c referenceCounting.h resource_handle.c \ - resource_handle.h service.h servicelib.c stream_cdf.c \ - stream_cdf.h stream_cgribex.c stream_cgribex.h stream_ext.c \ - stream_ext.h stream_grb.c stream_grb.h stream_gribapi.h \ - stream_history.c stream_ieg.c stream_ieg.h stream_fcommon.c \ - stream_fcommon.h cdi_int.c cdi_int.h stream_record.c \ - stream_srv.c stream_srv.h stream_var.c grb_write.c grb_read.c \ - cdf_write.c cdf_read.c subtype.c subtype.h swap.h table.c \ - table.h tablepar.h taxis.c taxis.h timebase.c timebase.h \ - tsteps.c util.c varscan.c varscan.h version.c vlist.c vlist.h \ - vlist_att.c vlist_att.h vlist_var.c vlist_var.h zaxis.c \ - zaxis.h stream.c stream_write.c stream_read.c swap.c \ + resource_handle.h service.h servicelib.c stream_cdf_i.c \ + stream_cdf_o.c stream_cdf.h stream_cgribex.c stream_cgribex.h \ + stream_ext.c stream_ext.h stream_grb.c stream_grb.h \ + stream_gribapi.h stream_history.c stream_ieg.c stream_ieg.h \ + cdi_int.c cdi_int.h stream_record.c stream_srv.c stream_srv.h \ + stream_var.c grb_write.c grb_read.c cdf_write.c cdf_read.c \ + cdf_lazy_grid.c cdf_lazy_grid.h subtype.c subtype.h swap.h \ + table.c table.h tablepar.h taxis.c taxis.h timebase.c \ + timebase.h tsteps.c util.c varscan.c varscan.h version.c \ + vlist.c vlist.h cdi_att.c cdi_att.h vlist_var.c vlist_var.h \ + zaxis.c zaxis.h stream.c stream_write.c stream_read.c swap.c \ iterator.c iterator.h iterator_fallback.c iterator_fallback.h \ iterator_grib.c iterator_grib.h cfortran.h cdiFortran.c \ gribapi_utilities.c stream_gribapi.c @@ -196,20 +197,20 @@ am__objects_1 = cdiFortran.lo am__objects_3 = gribapi_utilities.lo stream_gribapi.lo @HAVE_LIBGRIB_API_TRUE@am__objects_4 = $(am__objects_3) am_libcdi_la_OBJECTS = basetime.lo binary.lo calendar.lo cdf.lo \ - cdf_int.lo cdi_error.lo cdi_util.lo cgribexlib.lo dmemory.lo \ - cksum.lo cdi_cksum.lo error.lo extralib.lo file.lo \ + cdf_int.lo cdf_util.lo cdi_error.lo cdi_util.lo cgribexlib.lo \ + dmemory.lo cksum.lo cdi_cksum.lo error.lo extralib.lo file.lo \ gaussgrid.lo gribapi.lo grid.lo ieglib.lo input_file.lo \ institution.lo model.lo namespace.lo serialize.lo \ referenceCounting.lo resource_handle.lo servicelib.lo \ - stream_cdf.lo stream_cgribex.lo stream_ext.lo stream_grb.lo \ - stream_history.lo stream_ieg.lo stream_fcommon.lo cdi_int.lo \ - stream_record.lo stream_srv.lo stream_var.lo grb_write.lo \ - grb_read.lo cdf_write.lo cdf_read.lo subtype.lo table.lo \ - taxis.lo timebase.lo tsteps.lo util.lo varscan.lo version.lo \ - vlist.lo vlist_att.lo vlist_var.lo zaxis.lo stream.lo \ - stream_write.lo stream_read.lo swap.lo iterator.lo \ - iterator_fallback.lo iterator_grib.lo $(am__objects_2) \ - $(am__objects_4) + stream_cdf_i.lo stream_cdf_o.lo stream_cgribex.lo \ + stream_ext.lo stream_grb.lo stream_history.lo stream_ieg.lo \ + cdi_int.lo stream_record.lo stream_srv.lo stream_var.lo \ + grb_write.lo grb_read.lo cdf_write.lo cdf_read.lo \ + cdf_lazy_grid.lo subtype.lo table.lo taxis.lo timebase.lo \ + tsteps.lo util.lo varscan.lo version.lo vlist.lo cdi_att.lo \ + vlist_var.lo zaxis.lo stream.lo stream_write.lo stream_read.lo \ + swap.lo iterator.lo iterator_fallback.lo iterator_grib.lo \ + $(am__objects_2) $(am__objects_4) libcdi_la_OBJECTS = $(am_libcdi_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -377,11 +378,9 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JASPER_LIBS = @JASPER_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -405,7 +404,6 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENJPEG_LIBS = @OPENJPEG_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -487,7 +485,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -openjpeg_LIBS = @openjpeg_LIBS@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ @@ -511,29 +508,29 @@ noinst_LTLIBRARIES = libcdiresunpack.la $(am__append_1) \ @ENABLE_CDI_LIB_TRUE@include_HEADERS = cdi.h cdi.inc $(am__append_5) AM_CFLAGS = $(PPM_CORE_CFLAGS) $(YAXT_CFLAGS) $(MPI_C_INCLUDE) libcdi_la_SOURCES = basetime.c basetime.h binary.c binary.h calendar.c \ - calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdi.h cdi_error.c \ - cdi_limits.h cdi_util.c cgribex.h cgribexlib.c datetime.h \ - dmemory.c dmemory.h cksum.c cksum.h cdi_cksum.c cdi_cksum.h \ - cdi_uuid.h dtypes.h error.c error.h exse.h extra.h extralib.c \ - file.c file.h gaussgrid.c gaussgrid.h gribapi.c gribapi.h \ - gribapi_utilities.h grid.c grid.h ieg.h ieglib.c input_file.c \ - input_file.h institution.c institution.h model.c model.h \ - namespace.c namespace.h serialize.h serialize.c \ - referenceCounting.c referenceCounting.h resource_handle.c \ - resource_handle.h service.h servicelib.c stream_cdf.c \ + calendar.h cdf.c cdf.h cdf_int.c cdf_int.h cdf_util.c \ + cdf_util.h cdi.h cdi_error.c cdi_limits.h cdi_util.c cgribex.h \ + cgribexlib.c datetime.h dmemory.c dmemory.h cksum.c cksum.h \ + cdi_cksum.c cdi_cksum.h cdi_uuid.h dtypes.h error.c error.h \ + exse.h extra.h extralib.c file.c file.h gaussgrid.c \ + gaussgrid.h gribapi.c gribapi.h gribapi_utilities.h grid.c \ + grid.h ieg.h ieglib.c input_file.c input_file.h institution.c \ + institution.h model.c model.h namespace.c namespace.h \ + serialize.h serialize.c referenceCounting.c \ + referenceCounting.h resource_handle.c resource_handle.h \ + service.h servicelib.c stream_cdf_i.c stream_cdf_o.c \ stream_cdf.h stream_cgribex.c stream_cgribex.h stream_ext.c \ stream_ext.h stream_grb.c stream_grb.h stream_gribapi.h \ - stream_history.c stream_ieg.c stream_ieg.h stream_fcommon.c \ - stream_fcommon.h cdi_int.c cdi_int.h stream_record.c \ - stream_srv.c stream_srv.h stream_var.c grb_write.c grb_read.c \ - cdf_write.c cdf_read.c subtype.c subtype.h swap.h table.c \ - table.h tablepar.h taxis.c taxis.h timebase.c timebase.h \ - tsteps.c util.c varscan.c varscan.h version.c vlist.c vlist.h \ - vlist_att.c vlist_att.h vlist_var.c vlist_var.h zaxis.c \ - zaxis.h stream.c stream_write.c stream_read.c swap.c \ - iterator.c iterator.h iterator_fallback.c iterator_fallback.h \ - iterator_grib.c iterator_grib.h $(am__append_2) \ - $(am__append_3) + stream_history.c stream_ieg.c stream_ieg.h cdi_int.c cdi_int.h \ + stream_record.c stream_srv.c stream_srv.h stream_var.c \ + grb_write.c grb_read.c cdf_write.c cdf_read.c cdf_lazy_grid.c \ + cdf_lazy_grid.h subtype.c subtype.h swap.h table.c table.h \ + tablepar.h taxis.c taxis.h timebase.c timebase.h tsteps.c \ + util.c varscan.c varscan.h version.c vlist.c vlist.h cdi_att.c \ + cdi_att.h vlist_var.c vlist_var.h zaxis.c zaxis.h stream.c \ + stream_write.c stream_read.c swap.c iterator.c iterator.h \ + iterator_fallback.c iterator_fallback.h iterator_grib.c \ + iterator_grib.h $(am__append_2) $(am__append_3) # cfortran.h is an optional part of libcdi libcdi_la_USE_FC_extra_sources = \ @@ -692,9 +689,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/calendar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_int.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_lazy_grid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_read.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdf_write.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdiFortran.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_att.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_cksum.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdi_int.Plo@am__quote@ @@ -747,10 +747,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serialize.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/servicelib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cdf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cdf_i.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cdf_o.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_cgribex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_ext.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_fcommon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_grb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_gribapi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream_history.Plo@am__quote@ @@ -770,7 +770,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varscan.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vlist.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vlist_att.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vlist_var.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zaxis.Plo@am__quote@ diff --git a/src/basetime.c b/src/basetime.c index 3d4d5e3661934d471ff905ef30ed5c41a3e6f4e0..ff4cd8aad7fb405d0cd3e736f4671007a9fae9b8 100644 --- a/src/basetime.c +++ b/src/basetime.c @@ -3,6 +3,7 @@ #endif #include <stdio.h> +#include <stdbool.h> #include "error.h" #include "cdi.h" @@ -20,7 +21,7 @@ void basetimeInit(basetime_t *basetime) basetime->ncdimid = UNDEFID; basetime->ncvarboundsid = UNDEFID; basetime->leadtimeid = UNDEFID; - basetime->lwrf = 0; + basetime->lwrf = false; basetime->timevar_cache = NULL; } /* diff --git a/src/basetime.h b/src/basetime.h index 8a56f5a7e88761ea68306a61db147ff078913b8c..a5a96316fe01d2bd47dd2ac2a48e8a843d2a2c9b 100644 --- a/src/basetime.h +++ b/src/basetime.h @@ -1,6 +1,8 @@ #ifndef _BASETIME_H #define _BASETIME_H +#include <stdbool.h> + //#define USE_TIMECACHE 1 #define MAX_TIMECACHE_SIZE 1024 @@ -17,7 +19,7 @@ typedef struct { int ncdimid; int ncvarboundsid; int leadtimeid; - int lwrf; /* TRUE for time axis in WRF format */ + bool lwrf; /* true for time axis in WRF format */ timecache_t *timevar_cache; } basetime_t; diff --git a/src/cdf.c b/src/cdf.c index 6fb0a85528b16425f3164919830fe574ccf99373..ce640b9e84dc69eeeb2c8efb7b175aca78d89db4 100644 --- a/src/cdf.c +++ b/src/cdf.c @@ -129,7 +129,7 @@ static int cdfOpenFile(const char *filename, const char *mode, int *filetype) #endif cdf_create(filename, writemode, &ncid); if ( CDI_Version_Info ) cdfComment(ncid); - cdf_put_att_text(ncid, NC_GLOBAL, "Conventions", 6, "CF-1.4"); + cdf_put_att_text(ncid, NC_GLOBAL, "Conventions", 6, "CF-1.6"); break; case 'a': cdf_open(filename, NC_WRITE, &ncid); diff --git a/src/cdf_lazy_grid.c b/src/cdf_lazy_grid.c new file mode 100644 index 0000000000000000000000000000000000000000..41d26bf32eb5dd752b74b684be91353631b14bbf --- /dev/null +++ b/src/cdf_lazy_grid.c @@ -0,0 +1,528 @@ +#include "stream_cdf.h" +#include "cdf_lazy_grid.h" + + +static struct gridVirtTable cdfLazyGridVtable; +double *cdfPendingLoad; +#ifdef HAVE_LIBPTHREAD +static pthread_once_t cdfLazyInitialized = PTHREAD_ONCE_INIT; +#else +static bool cdfLazyInitialized; +#endif + + +#ifdef HAVE_LIBPTHREAD +#define lock_lazy_load(plGrid) pthread_mutex_lock(&((plGrid)->loadSerialize)) +#define unlock_lazy_load(plGrid) pthread_mutex_unlock(&((plGrid)->loadSerialize)) +#define destroy_lazy_load_lock(plGrid) pthread_mutex_destroy(&((plGrid)->loadSerialize)) +#define init_lazy_load_lock(plGrid) pthread_mutex_init(&((plGrid)->loadSerialize), NULL) +#else +#define lock_lazy_load(plGrid) +#define unlock_lazy_load(plGrid) +#define destroy_lazy_load_lock(plGrid) +#define init_lazy_load_lock(plGrid) +#endif + + +void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid) +{ + if (lazyGrid->base.area == cdfPendingLoad) lazyGrid->base.area = NULL; + if (lazyGrid->base.x.vals == cdfPendingLoad) lazyGrid->base.x.vals = NULL; + if (lazyGrid->base.y.vals == cdfPendingLoad) lazyGrid->base.y.vals = NULL; + if (lazyGrid->base.x.bounds == cdfPendingLoad) lazyGrid->base.x.bounds = NULL; + if (lazyGrid->base.y.bounds == cdfPendingLoad) lazyGrid->base.y.bounds = NULL; + destroy_lazy_load_lock(lazyGrid); +} + +static void cdfLazyGridDelete(grid_t *grid) +{ + struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; + void (*baseDestroy)(grid_t *grid) = cdfGrid->baseVtable->destroy; + cdfLazyGridDestroy(cdfGrid); + baseDestroy(grid); +} + +static void cdfLazyGridDestroyOnce(void) +{ + /* +#ifdef HAVE_MMAP + size_t pgSize = cdiGetPageSize(false); + munmap(cdfPendingLoad, pgSize); +#endif + */ +} + +static void +cdfLazyGridDefArea(grid_t *grid, const double *area) +{ + struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(cdfGrid); + if (grid->area == cdfPendingLoad) + grid->area = NULL; + cdfGrid->cellAreaGet.datasetNCId = -1; + cdfGrid->cellAreaGet.varNCId = -1; + cdfGrid->baseVtable->defArea(grid, area); + unlock_lazy_load(cdfGrid); +} + + +static const double * +cdfLazyGridInqAreaPtr(grid_t *grid) +{ + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(lazyGrid); + if (grid->area == cdfPendingLoad) + { + grid->area = (double *)Malloc((size_t)grid->size * sizeof(double)); + cdf_get_var_double(lazyGrid->cellAreaGet.datasetNCId, + lazyGrid->cellAreaGet.varNCId, grid->area); + } + unlock_lazy_load(lazyGrid); + return lazyGrid->baseVtable->inqAreaPtr(grid); +} + +static void +cdfLazyGridInqArea(grid_t *grid, double *area) +{ + grid->vtable->inqAreaPtr(grid); + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lazyGrid->baseVtable->inqArea(grid, area); +} + + +static void +cdfLazyLoadXYVals(struct xyValGet *valsGet, double **valsp) +{ + double *grid_vals + = (double *)Malloc(valsGet->size * sizeof (double)); + *valsp = grid_vals; + if ( valsGet->ndims == 3 ) + cdf_get_vara_double(valsGet->datasetNCId, valsGet->varNCId, + valsGet->start, valsGet->count, grid_vals); + else + cdf_get_var_double(valsGet->datasetNCId, valsGet->varNCId, grid_vals); + cdf_scale_add(valsGet->size, grid_vals, valsGet->addoffset, valsGet->scalefactor); +} + +static const double * +cdfLazyGridInqXValsPtr(grid_t *grid) +{ + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(lazyGrid); + if (grid->x.vals == cdfPendingLoad) + cdfLazyLoadXYVals(&lazyGrid->xValsGet, &grid->x.vals); + unlock_lazy_load(lazyGrid); + return lazyGrid->baseVtable->inqXValsPtr(grid); +} + +static const double * +cdfLazyGridInqYValsPtr(grid_t *grid) +{ + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(lazyGrid); + if (grid->y.vals == cdfPendingLoad) + cdfLazyLoadXYVals(&lazyGrid->yValsGet, &grid->y.vals); + unlock_lazy_load(lazyGrid); + return lazyGrid->baseVtable->inqYValsPtr(grid); +} + +static double +cdfLazyGridInqXYVal(grid_t *grid, size_t index, + const struct xyValGet *valsGet, double *vals, + const double *(*inqValsPtr)(grid_t *gridptr)) +{ + size_t size = valsGet->size; + double v; + if ( vals == cdfPendingLoad ) + { + /* prevent full load if only first/last values get inspected */ + if ( index == 0 || index == size - 1 ) + { + size_t indexND[3]; + if ( valsGet->ndims == 3 ) + { + indexND[0] = 0; + indexND[1] = index / valsGet->count[2]; + indexND[2] = index % valsGet->count[2]; + } + else if ( valsGet->ndims == 2) + { + indexND[0] = index / (size_t)grid->x.size; + indexND[1] = index % (size_t)grid->x.size; + } + else + indexND[0] = index; + cdf_get_var1_double(valsGet->datasetNCId, valsGet->varNCId, indexND, &v); + } + else + { + const double *grid_vals = inqValsPtr(grid); + v = grid_vals[index]; + } + } + else if ( vals ) + v = vals[index]; + else + v = 0.0; + return v; +} + +static void +cdfLazyGridDefXVals(grid_t *grid, const double *vals) +{ + struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(cdfGrid); + if (grid->x.vals == cdfPendingLoad) + grid->x.vals = NULL; + cdfGrid->xValsGet.datasetNCId = -1; + cdfGrid->xValsGet.varNCId = -1; + cdfGrid->baseVtable->defXVals(grid, vals); + unlock_lazy_load(cdfGrid); +} + +static void +cdfLazyGridDefYVals(grid_t *grid, const double *vals) +{ + struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(cdfGrid); + if (grid->y.vals == cdfPendingLoad) + grid->y.vals = NULL; + cdfGrid->yValsGet.datasetNCId = -1; + cdfGrid->yValsGet.varNCId = -1; + cdfGrid->baseVtable->defYVals(grid, vals); + unlock_lazy_load(cdfGrid); +} + +static double +cdfLazyGridInqXVal(grid_t *grid, int index) +{ + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(lazyGrid); + double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->xValsGet, + grid->x.vals, grid->vtable->inqXValsPtr); + unlock_lazy_load(lazyGrid); + return rv; +} + +static double +cdfLazyGridInqYVal(grid_t *grid, int index) +{ + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(lazyGrid); + double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->yValsGet, + grid->y.vals, grid->vtable->inqYValsPtr); + unlock_lazy_load(lazyGrid); + return rv; +} + +static bool +cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef, + struct cdfLazyGrid *lazyGridTest) +{ + struct xyValGet *valsGetXRef = &lazyGridRef->xValsGet, + *valsGetYRef = &lazyGridRef->yValsGet, + *valsGetXTest = &lazyGridTest->xValsGet, + *valsGetYTest = &lazyGridTest->yValsGet; + if (valsGetXRef->datasetNCId == -1 + || valsGetXTest->datasetNCId == -1 + || valsGetYRef->datasetNCId == -1 + || valsGetYTest->datasetNCId == -1) + return lazyGridRef->baseVtable->compareXYFull(&lazyGridRef->base, + &lazyGridTest->base); + return valsGetXRef->datasetNCId != valsGetXTest->datasetNCId + || valsGetXRef->varNCId != valsGetXTest->varNCId + || valsGetYRef->datasetNCId != valsGetYTest->datasetNCId + || valsGetYRef->varNCId != valsGetYTest->varNCId; +} + +static bool +cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest) +{ + bool diff; + struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef; + if (gridTest->vtable == &cdfLazyGridVtable) + diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest); + else + diff = lazyGridRef->baseVtable->compareXYFull(gridRef, gridTest); + return diff; +} + +static bool +cdfLazyCompareXYAO(grid_t *gridRef, grid_t *gridTest) +{ + bool diff; + struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef; + if (gridTest->vtable == &cdfLazyGridVtable) + diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest); + else + diff = lazyGridRef->baseVtable->compareXYAO(gridRef, gridTest); + return diff; +} + + +static const double * +cdfLazyGridInqXBoundsPtr(grid_t *grid) +{ + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(lazyGrid); + if (grid->x.bounds == cdfPendingLoad) + { + grid->x.bounds = (double *)Malloc((size_t)grid->nvertex + * (size_t)grid->size * sizeof(double)); + cdf_get_var_double(lazyGrid->xBoundsGet.datasetNCId, + lazyGrid->xBoundsGet.varNCId, grid->x.bounds); + } + unlock_lazy_load(lazyGrid); + return lazyGrid->baseVtable->inqXBoundsPtr(grid); +} + +static void +cdfLazyGridDefXBounds(grid_t *grid, const double *xbounds) +{ + struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(cdfGrid); + if (grid->x.bounds == cdfPendingLoad) + grid->x.bounds = NULL; + cdfGrid->xBoundsGet.datasetNCId = -1; + cdfGrid->xBoundsGet.varNCId = -1; + cdfGrid->baseVtable->defXBounds(grid, xbounds); + unlock_lazy_load(cdfGrid); +} + +static void +cdfLazyGridDefYBounds(grid_t *grid, const double *ybounds) +{ + struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(cdfGrid); + if (grid->y.bounds == cdfPendingLoad) + grid->y.bounds = NULL; + cdfGrid->yBoundsGet.datasetNCId = -1; + cdfGrid->yBoundsGet.varNCId = -1; + cdfGrid->baseVtable->defYBounds(grid, ybounds); + unlock_lazy_load(cdfGrid); +} + +static const double * +cdfLazyGridInqYBoundsPtr(grid_t *grid) +{ + struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; + lock_lazy_load(lazyGrid); + if (grid->y.bounds == cdfPendingLoad) + { + grid->y.bounds = (double *)Malloc((size_t)grid->nvertex + * (size_t)grid->size * sizeof(double)); + cdf_get_var_double(lazyGrid->yBoundsGet.datasetNCId, + lazyGrid->yBoundsGet.varNCId, grid->y.bounds); + } + unlock_lazy_load(lazyGrid); + return lazyGrid->baseVtable->inqYBoundsPtr(grid); +} + +static void +cdfLazyGridCopyScalarFields(grid_t *gridptrOrig, grid_t *gridptrDup) +{ + struct cdfLazyGrid *lazyGridDup = (struct cdfLazyGrid *)gridptrDup, + *lazyGridOrig = (struct cdfLazyGrid *)gridptrOrig; + lazyGridOrig->baseVtable->copyScalarFields(gridptrOrig, &lazyGridDup->base); + lazyGridDup->baseVtable = lazyGridOrig->baseVtable; + lazyGridDup->cellAreaGet = lazyGridOrig->cellAreaGet; + lazyGridDup->xBoundsGet = lazyGridOrig->xBoundsGet; + lazyGridDup->yBoundsGet = lazyGridOrig->yBoundsGet; + lazyGridDup->xValsGet = lazyGridOrig->xValsGet; + lazyGridDup->yValsGet = lazyGridOrig->yValsGet; + init_lazy_load_lock(lazyGridDup); +} + +static void +cdfLazyGridCopyArrayFields(grid_t *gridptrOrig, grid_t *gridptrDup) +{ + size_t nrowlon = (size_t)gridptrOrig->nrowlon; + size_t gridsize = (size_t)gridptrOrig->size; + int gridtype = gridptrOrig->type; + int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED; + if ( nrowlon ) + { + gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int)); + memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int)); + } + + if ( gridptrOrig->x.vals != NULL && gridptrOrig->x.vals != cdfPendingLoad ) + { + size_t size = irregular ? gridsize : (size_t)gridptrOrig->x.size; + + gridptrDup->x.vals = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->x.vals, gridptrOrig->x.vals, size * sizeof (double)); + } + + if ( gridptrOrig->y.vals != NULL && gridptrOrig->y.vals != cdfPendingLoad ) + { + size_t size = irregular ? gridsize : (size_t)gridptrOrig->y.size; + + gridptrDup->y.vals = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->y.vals, gridptrOrig->y.vals, size * sizeof (double)); + } + + if ( gridptrOrig->x.bounds != NULL && gridptrOrig->x.bounds != cdfPendingLoad ) + { + size_t size = (irregular ? gridsize : (size_t)gridptrOrig->x.size) + * (size_t)gridptrOrig->nvertex; + + gridptrDup->x.bounds = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->x.bounds, gridptrOrig->x.bounds, size * sizeof (double)); + } + + if ( gridptrOrig->y.bounds != NULL && gridptrOrig->y.bounds != cdfPendingLoad ) + { + size_t size = (irregular ? gridsize : (size_t)gridptrOrig->y.size) + * (size_t)gridptrOrig->nvertex; + + gridptrDup->y.bounds = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->y.bounds, gridptrOrig->y.bounds, size * sizeof (double)); + } + + { + if ( gridptrOrig->area != NULL && gridptrOrig->area != cdfPendingLoad ) + { + size_t size = gridsize; + + gridptrDup->area = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->area, gridptrOrig->area, size * sizeof (double)); + } + } + + if ( gridptrOrig->mask != NULL ) + { + size_t size = gridsize; + + gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t)); + memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t)); + } + + if ( gridptrOrig->mask_gme != NULL ) + { + size_t size = gridsize; + + gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t)); + memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t)); + } +} + +static grid_t * +cdfLazyGridCopy(grid_t *gridptrOrig) +{ + struct cdfLazyGrid *lazyGridDup + = (struct cdfLazyGrid *)Malloc(sizeof (*lazyGridDup)); + gridptrOrig->vtable->copyScalarFields(gridptrOrig, &lazyGridDup->base); + gridptrOrig->vtable->copyArrayFields(gridptrOrig, &lazyGridDup->base); + return &lazyGridDup->base; +} + +static void +cdfLazyGridInitOnce(void) +{ + cdfLazyGridVtable = cdiGridVtable; + cdfLazyGridVtable.destroy = cdfLazyGridDelete; + cdfLazyGridVtable.copy = cdfLazyGridCopy; + cdfLazyGridVtable.copyScalarFields = cdfLazyGridCopyScalarFields; + cdfLazyGridVtable.copyArrayFields = cdfLazyGridCopyArrayFields; + cdfLazyGridVtable.defArea = cdfLazyGridDefArea; + cdfLazyGridVtable.inqAreaPtr = cdfLazyGridInqAreaPtr; + cdfLazyGridVtable.inqArea = cdfLazyGridInqArea; + cdfLazyGridVtable.inqXValsPtr = cdfLazyGridInqXValsPtr; + cdfLazyGridVtable.inqYValsPtr = cdfLazyGridInqYValsPtr; + cdfLazyGridVtable.inqXVal = cdfLazyGridInqXVal; + cdfLazyGridVtable.inqYVal = cdfLazyGridInqYVal; + cdfLazyGridVtable.defXVals = cdfLazyGridDefXVals; + cdfLazyGridVtable.defYVals = cdfLazyGridDefYVals; + cdfLazyGridVtable.compareXYFull = cdfLazyCompareXYFull; + cdfLazyGridVtable.compareXYAO = cdfLazyCompareXYAO; + cdfLazyGridVtable.defXBounds = cdfLazyGridDefXBounds; + cdfLazyGridVtable.defYBounds = cdfLazyGridDefYBounds; + cdfLazyGridVtable.inqXBoundsPtr = cdfLazyGridInqXBoundsPtr; + cdfLazyGridVtable.inqYBoundsPtr = cdfLazyGridInqYBoundsPtr; + /* create inaccessible memory area, if possible, this serves as + * dummy value for pointers to data not yet loaded */ + /* +#ifdef HAVE_MMAP + { + size_t pgSize = cdiGetPageSize(false); + static const char devZero[] = "/dev/zero"; + int fd = open(devZero, O_RDWR); + if (fd == -1) + SysError("Could not open %s to map anonymous memory", devZero); + void *cdfInvalid = mmap(NULL, pgSize, PROT_NONE, MAP_PRIVATE, fd, 0); + if (cdfInvalid == MAP_FAILED) + SysError("Could not mmap anonymous memory"); + cdfPendingLoad = cdfInvalid; + int rc = close(fd); + if (rc == -1) + SysError("Could not close %s file handle %d after mapping anonymous" + " memory", devZero, fd); + } +#else + */ + cdfPendingLoad = (double *)&cdfPendingLoad; + //#endif + atexit(cdfLazyGridDestroyOnce); +#ifndef HAVE_LIBPTHREAD + cdfLazyInitialized = true; +#endif +} + +static void +cdfBaseGridInit(grid_t *grid, int gridtype) +{ + grid_init(grid); + cdiGridTypeInit(grid, gridtype, 0); +} + +static void +cdfLazyGridInit(struct cdfLazyGrid *grid, int gridtype) +{ +#ifdef HAVE_LIBPTHREAD + pthread_once(&cdfLazyInitialized, cdfLazyGridInitOnce); +#else + if (cdfLazyInitialized) ; else cdfLazyGridInitOnce(); +#endif + cdfBaseGridInit(&grid->base, gridtype); + grid->baseVtable = grid->base.vtable; + grid->cellAreaGet.datasetNCId = -1; + grid->cellAreaGet.varNCId = -1; + grid->xValsGet.datasetNCId = -1; + grid->xValsGet.varNCId = -1; + grid->yValsGet.datasetNCId = -1; + grid->yValsGet.varNCId = -1; + grid->xBoundsGet.datasetNCId = -1; + grid->xBoundsGet.varNCId = -1; + grid->yBoundsGet.datasetNCId = -1; + grid->yBoundsGet.varNCId = -1; + grid->base.vtable = &cdfLazyGridVtable; + init_lazy_load_lock(grid); +} + + +void cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype) +{ + struct cdfLazyGrid *restrict grid = *gridpptr; + if (!grid) + *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (*grid)); + cdfLazyGridInit(grid, gridtype); +} + + +void cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype) +{ + struct cdfLazyGrid *restrict grid = *gridpptr; + if (!grid) + *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (grid_t)); + cdfBaseGridInit((grid_t*)grid, gridtype); +} +/* + * Local Variables: + * c-file-style: "Java" + * c-basic-offset: 2 + * indent-tabs-mode: nil + * show-trailing-whitespace: t + * require-trailing-newline: t + * End: + */ diff --git a/src/cdf_lazy_grid.h b/src/cdf_lazy_grid.h new file mode 100644 index 0000000000000000000000000000000000000000..3da5ca0d791edb6c455a63b8e193a7213aedd1b6 --- /dev/null +++ b/src/cdf_lazy_grid.h @@ -0,0 +1,60 @@ +#ifndef CDF_LAZY_GRID_H_ +#define CDF_LAZY_GRID_H_ + +#if defined (HAVE_CONFIG_H) +#include "config.h" +#endif + +#ifdef HAVE_MMAP +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#endif +#ifdef HAVE_LIBPTHREAD +#include <pthread.h> +#endif + +#include <string.h> + +#include "dmemory.h" +#include "cdf_int.h" +#include "grid.h" + +struct cdfLazyGrid +{ + grid_t base; + const struct gridVirtTable *baseVtable; + struct cdfLazyGridIds { + int datasetNCId, varNCId; + } cellAreaGet, xBoundsGet, yBoundsGet; + struct xyValGet { + double scalefactor, addoffset; + size_t start[3], count[3], size, dimsize; + int datasetNCId, varNCId; + short ndims; + } xValsGet, yValsGet; +#ifdef HAVE_LIBPTHREAD + pthread_mutex_t loadSerialize; +#endif +}; + + +extern double *cdfPendingLoad; + +void cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype); +void cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype); + +void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid); + +#endif +/* + * Local Variables: + * c-file-style: "Java" + * c-basic-offset: 2 + * indent-tabs-mode: nil + * show-trailing-whitespace: t + * require-trailing-newline: t + * End: + */ diff --git a/src/cdf_util.c b/src/cdf_util.c new file mode 100644 index 0000000000000000000000000000000000000000..43ac749898b2339880e81b2f4d4179f2189aa429 --- /dev/null +++ b/src/cdf_util.c @@ -0,0 +1,332 @@ +#include <string.h> +#include <ctype.h> +#include "dmemory.h" +#include "cdi.h" +#include "cdf_util.h" +#include "error.h" + + +void str_tolower(char *str) +{ + if ( str ) + for ( size_t i = 0; str[i]; ++i ) + str[i] = (char)tolower((int)str[i]); +} + + +int get_timeunit(size_t len, const char *ptu) +{ + int timeunit = -1; + + if ( len > 2 ) + { + if ( memcmp(ptu, "sec", 3) == 0 ) timeunit = TUNIT_SECOND; + else if ( memcmp(ptu, "minute", 6) == 0 ) timeunit = TUNIT_MINUTE; + else if ( memcmp(ptu, "hour", 4) == 0 ) timeunit = TUNIT_HOUR; + else if ( memcmp(ptu, "day", 3) == 0 ) timeunit = TUNIT_DAY; + else if ( memcmp(ptu, "month", 5) == 0 ) timeunit = TUNIT_MONTH; + else if ( memcmp(ptu, "calendar_month", 14) == 0 ) timeunit = TUNIT_MONTH; + else if ( memcmp(ptu, "year", 4) == 0 ) timeunit = TUNIT_YEAR; + } + else if ( len == 1 ) + { + if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND; + } + + return timeunit; +} + + +bool is_time_units(const char *timeunits) +{ + bool status = strncmp(timeunits, "sec", 3) == 0 + || strncmp(timeunits, "minute", 6) == 0 + || strncmp(timeunits, "hour", 4) == 0 + || strncmp(timeunits, "day", 3) == 0 + || strncmp(timeunits, "month", 5) == 0; + + return status; +} + + +bool is_timeaxis_units(const char *timeunits) +{ + bool status = false; + + size_t len = strlen(timeunits); + char *tu = (char *) Malloc((len+1)*sizeof(char)); + memcpy(tu, timeunits, (len+1) * sizeof(char)); + char *ptu = tu; + + for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]); + + int timeunit = get_timeunit(len, ptu); + if ( timeunit != -1 ) + { + while ( ! isspace(*ptu) && *ptu != 0 ) ptu++; + if ( *ptu ) + { + while ( isspace(*ptu) ) ptu++; + + int timetype = memcmp(ptu, "as", 2) == 0 ? TAXIS_ABSOLUTE : + memcmp(ptu, "since", 5) == 0 ? TAXIS_RELATIVE : -1; + + status = timetype != -1; + } + } + + Free(tu); + + return status; +} + + +bool is_height_units(const char *units) +{ + bool status = false; + int u0 = units[0]; + + if ( (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0)) || + (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k')) ) + { + status = true; + } + + return status; +} + + +bool is_pressure_units(const char *units) +{ + bool status = false; + + if ( strncmp(units, "millibar", 8) == 0 || + strncmp(units, "mb", 2) == 0 || + strncmp(units, "hectopas", 8) == 0 || + strncmp(units, "hPa", 3) == 0 || + strncmp(units, "Pa", 2) == 0 ) + { + status = true; + } + + return status; +} + + +bool is_DBL_axis(/*const char *units,*/ const char *longname) +{ + bool status = false; + + if ( strcmp(longname, "depth below land") == 0 || + strcmp(longname, "depth_below_land") == 0 || + strcmp(longname, "levels below the surface") == 0 ) + { + /* + if ( strcmp(ncvars[ncvarid].units, "cm") == 0 || + strcmp(ncvars[ncvarid].units, "dm") == 0 || + strcmp(ncvars[ncvarid].units, "m") == 0 ) + */ + status = true; + } + + return status; +} + + +bool is_depth_axis(const char *stdname, const char *longname) +{ + bool status = false; + + if ( strcmp(stdname, "depth") == 0 ) + status = true; + else + if ( strcmp(longname, "depth_below_sea") == 0 || + strcmp(longname, "depth below sea") == 0 ) + { + status = true; + } + + return status; +} + + +bool is_height_axis(const char *stdname, const char *longname) +{ + bool status = false; + + if ( strcmp(stdname, "height") == 0 ) + status = true; + else + if ( strcmp(longname, "height") == 0 || + strcmp(longname, "height above the surface") == 0 ) + { + status = true; + } + + return status; +} + + +bool is_lon_axis(const char *units, const char *stdname) +{ + bool status = false; + char lc_units[16]; + + memcpy(lc_units, units, 15); + lc_units[15] = 0; + str_tolower(lc_units); + + if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) && + (memcmp(stdname, "grid_longitude", 14) == 0 || memcmp(stdname, "longitude", 9) == 0)) ) + { + status = true; + } + + if ( status == false && + memcmp(stdname, "grid_latitude", 13) && memcmp(stdname, "latitude", 8) && + memcmp(lc_units, "degree", 6) == 0 ) + { + int ioff = 6; + if ( lc_units[ioff] == 's' ) ioff++; + if ( lc_units[ioff] == '_' ) ioff++; + if ( lc_units[ioff] == 'e' ) status = true; + } + + return status; +} + + +bool is_lat_axis(const char *units, const char *stdname) +{ + bool status = false; + char lc_units[16]; + + memcpy(lc_units, units, 15); + lc_units[15] = 0; + str_tolower(lc_units); + + if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) && + (memcmp(stdname, "grid_latitude", 13) == 0 || memcmp(stdname, "latitude", 8) == 0)) ) + { + status = true; + } + + if ( status == false && + memcmp(stdname, "grid_longitude", 14) && memcmp(stdname, "longitude", 9) && + memcmp(lc_units, "degree", 6) == 0 ) + { + int ioff = 6; + if ( lc_units[ioff] == 's' ) ioff++; + if ( lc_units[ioff] == '_' ) ioff++; + if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = true; + } + + return status; +} + + +bool is_x_axis(const char *units, const char *stdname) +{ + bool status = false; + + if ( strcmp(stdname, "projection_x_coordinate") == 0 ) status = true; + + return status; +} + + +bool is_y_axis(const char *units, const char *stdname) +{ + bool status = false; + + if ( strcmp(stdname, "projection_y_coordinate") == 0 ) status = true; + + return status; +} + + +void set_gridtype(const char *attstring, int *gridtype) +{ + if ( strcmp(attstring, "gaussian reduced") == 0 ) + *gridtype = GRID_GAUSSIAN_REDUCED; + else if ( strcmp(attstring, "gaussian") == 0 ) + *gridtype = GRID_GAUSSIAN; + else if ( strncmp(attstring, "spectral", 8) == 0 ) + *gridtype = GRID_SPECTRAL; + else if ( strncmp(attstring, "fourier", 7) == 0 ) + *gridtype = GRID_FOURIER; + else if ( strcmp(attstring, "trajectory") == 0 ) + *gridtype = GRID_TRAJECTORY; + else if ( strcmp(attstring, "generic") == 0 ) + *gridtype = GRID_GENERIC; + else if ( strcmp(attstring, "cell") == 0 ) + *gridtype = GRID_UNSTRUCTURED; + else if ( strcmp(attstring, "unstructured") == 0 ) + *gridtype = GRID_UNSTRUCTURED; + else if ( strcmp(attstring, "curvilinear") == 0 ) + *gridtype = GRID_CURVILINEAR; + else if ( strcmp(attstring, "sinusoidal") == 0 ) + ; + else if ( strcmp(attstring, "laea") == 0 ) + ; + else if ( strcmp(attstring, "lcc2") == 0 ) + ; + else if ( strcmp(attstring, "linear") == 0 ) // ignore grid type linear + ; + else + { + static bool warn = true; + if ( warn ) + { + warn = false; + Warning("NetCDF attribute grid_type='%s' unsupported!", attstring); + } + } +} + + +void set_zaxistype(const char *attstring, int *zaxistype) +{ + if ( strcmp(attstring, "toa") == 0 ) *zaxistype = ZAXIS_TOA; + else if ( strcmp(attstring, "cloudbase") == 0 ) *zaxistype = ZAXIS_CLOUD_BASE; + else if ( strcmp(attstring, "cloudtop") == 0 ) *zaxistype = ZAXIS_CLOUD_TOP; + else if ( strcmp(attstring, "isotherm0") == 0 ) *zaxistype = ZAXIS_ISOTHERM_ZERO; + else if ( strcmp(attstring, "seabottom") == 0 ) *zaxistype = ZAXIS_SEA_BOTTOM; + else if ( strcmp(attstring, "lakebottom") == 0 ) *zaxistype = ZAXIS_LAKE_BOTTOM; + else if ( strcmp(attstring, "sedimentbottom") == 0 ) *zaxistype = ZAXIS_SEDIMENT_BOTTOM; + else if ( strcmp(attstring, "sedimentbottomta") == 0 ) *zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; + else if ( strcmp(attstring, "sedimentbottomtw") == 0 ) *zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; + else if ( strcmp(attstring, "mixlayer") == 0 ) *zaxistype = ZAXIS_MIX_LAYER; + else if ( strcmp(attstring, "atmosphere") == 0 ) *zaxistype = ZAXIS_ATMOSPHERE; + else + { + static bool warn = true; + if ( warn ) + { + warn = false; + Warning("NetCDF attribute level_type='%s' unsupported!", attstring); + } + } +} + + +void set_calendar(const char *attstring, int *calendar) +{ + if ( memcmp(attstring, "standard", 8) == 0 || + memcmp(attstring, "gregorian", 9) == 0 ) + *calendar = CALENDAR_STANDARD; + else if ( memcmp(attstring, "none", 4) == 0 ) + *calendar = CALENDAR_NONE; + else if ( memcmp(attstring, "proleptic", 9) == 0 ) + *calendar = CALENDAR_PROLEPTIC; + else if ( memcmp(attstring, "360", 3) == 0 ) + *calendar = CALENDAR_360DAYS; + else if ( memcmp(attstring, "365", 3) == 0 || + memcmp(attstring, "noleap", 6) == 0 ) + *calendar = CALENDAR_365DAYS; + else if ( memcmp(attstring, "366", 3) == 0 || + memcmp(attstring, "all_leap", 8) == 0 ) + *calendar = CALENDAR_366DAYS; + else + Warning("calendar >%s< unsupported!", attstring); +} diff --git a/src/cdf_util.h b/src/cdf_util.h new file mode 100644 index 0000000000000000000000000000000000000000..ab9473c374177de53084bb39eba335dc49fffc6e --- /dev/null +++ b/src/cdf_util.h @@ -0,0 +1,29 @@ +#ifndef CDF_UTIL_H_ +#define CDF_UTIL_H_ + +#include <stdbool.h> + +void str_tolower(char *str); + +int get_timeunit(size_t len, const char *ptu); + +bool is_time_units(const char *timeunits); +bool is_timeaxis_units(const char *timeunits); + +bool is_height_units(const char *units); +bool is_pressure_units(const char *units); +bool is_DBL_axis(/*const char *units,*/ const char *longname); +bool is_depth_axis(const char *stdname, const char *longname); +bool is_height_axis(const char *stdname, const char *longname); + +bool is_lon_axis(const char *units, const char *stdname); +bool is_lat_axis(const char *units, const char *stdname); + +bool is_x_axis(const char *units, const char *stdname); +bool is_y_axis(const char *units, const char *stdname); + +void set_gridtype(const char *attstring, int *gridtype); +void set_zaxistype(const char *attstring, int *zaxistype); +void set_calendar(const char *attstring, int *calendar); + +#endif diff --git a/src/cdf_write.c b/src/cdf_write.c index 942f0c7e4cbf10e9d7ef83e7558d98494cda803a..32ce625fb68a646e50bcc15fe970441da50401a5 100644 --- a/src/cdf_write.c +++ b/src/cdf_write.c @@ -32,7 +32,6 @@ void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level) Error("nc_def_var_deflate failed, status = %d", retval); } #else - static int lwarn = TRUE; if ( lwarn ) { @@ -164,8 +163,8 @@ void *resizeBuf(void **buf, size_t *bufSize, size_t reqSize) return *buf; } -static -void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID) + +void cdfDefineAttributes(int cdiID, int varID, int fileID, int ncvarID) { int atttype, attlen; size_t len; @@ -174,11 +173,11 @@ void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID) size_t attBufSize = 0; int natts; - vlistInqNatts(vlistID, varID, &natts); + cdiInqNatts(cdiID, varID, &natts); - for ( int iatt = 0; iatt < natts; iatt++ ) + for ( int iatt = 0; iatt < natts; ++iatt ) { - vlistInqAtt(vlistID, varID, iatt, attname, &atttype, &attlen); + cdiInqAtt(cdiID, varID, iatt, attname, &atttype, &attlen); if ( attlen == 0 ) continue; @@ -186,23 +185,33 @@ void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID) { size_t attSize = (size_t)attlen*sizeof(char); char *atttxt = (char *)resizeBuf(&attBuf, &attBufSize, attSize); - vlistInqAttTxt(vlistID, varID, attname, attlen, atttxt); + cdiInqAttTxt(cdiID, varID, attname, attlen, atttxt); len = (size_t)attlen; cdf_put_att_text(fileID, ncvarID, attname, len, atttxt); } - else if ( atttype == DATATYPE_INT16 || atttype == DATATYPE_INT32 ) + else if ( atttype == DATATYPE_INT8 || atttype == DATATYPE_UINT8 || + atttype == DATATYPE_INT16 || atttype == DATATYPE_UINT16 || + atttype == DATATYPE_INT32 || atttype == DATATYPE_UINT32 ) { size_t attSize = (size_t)attlen*sizeof(int); int *attint = (int *)resizeBuf(&attBuf, &attBufSize, attSize); - vlistInqAttInt(vlistID, varID, attname, attlen, &attint[0]); + cdiInqAttInt(cdiID, varID, attname, attlen, &attint[0]); len = (size_t)attlen; - cdf_put_att_int(fileID, ncvarID, attname, atttype == DATATYPE_INT16 ? NC_SHORT : NC_INT, len, attint); + nc_type xtype = (atttype == DATATYPE_INT8) ? NC_BYTE : + (atttype == DATATYPE_INT16) ? NC_SHORT : +#if defined (HAVE_NETCDF4) + (atttype == DATATYPE_UINT8) ? NC_UBYTE : + (atttype == DATATYPE_UINT16) ? NC_USHORT : + (atttype == DATATYPE_UINT32) ? NC_UINT : +#endif + NC_INT; + cdf_put_att_int(fileID, ncvarID, attname, xtype, len, attint); } else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 ) { size_t attSize = (size_t)attlen * sizeof(double); double *attflt = (double *)resizeBuf(&attBuf, &attBufSize, attSize); - vlistInqAttFlt(vlistID, varID, attname, attlen, attflt); + cdiInqAttFlt(cdiID, varID, attname, attlen, attflt); len = (size_t)attlen; if ( atttype == DATATYPE_FLT32 ) { @@ -214,7 +223,7 @@ void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID) cdf_put_att_double(fileID, ncvarID, attname, NC_DOUBLE, len, attflt); } } - + Free(attBuf); } @@ -230,7 +239,7 @@ void cdfDefGlobalAtts(stream_t *streamptr) cdfDefInstitut(streamptr); int natts; - vlistInqNatts(vlistID, CDI_GLOBAL, &natts); + cdiInqNatts(vlistID, CDI_GLOBAL, &natts); if ( natts > 0 && streamptr->ncmode == 2 ) cdf_redef(fileID); @@ -272,6 +281,41 @@ void cdfDefLocalAtts(stream_t *streamptr) if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); } +static +void cdf_get_gmapvarname(int gridID, char *gmapvarname) +{ + int pgridID = gridID; + char mapping[CDI_MAX_NAME]; mapping[0] = 0; + cdiGridInqKeyStr(pgridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping); + + if ( !mapping[0] ) + { + int projID = gridInqProj(gridID); + if ( projID != CDI_UNDEFID ) + { + pgridID = projID; + cdiGridInqKeyStr(pgridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping); + } + } + + if ( mapping[0] ) + cdiGridInqKeyStr(pgridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, gmapvarname); +} + +static +int nc_grid_index(stream_t *streamptr, int gridID) +{ + int index = 0; + int vlistID = streamptr->vlistID; + int ngrids = vlistNgrids(vlistID); + for ( index = 0; index < ngrids; ++index ) + if ( streamptr->ncgrid[index].gridID == gridID ) break; + + assert(index < ngrids); + + return index; +} + static int cdfDefVar(stream_t *streamptr, int varID) { @@ -314,19 +358,19 @@ int cdfDefVar(stream_t *streamptr, int varID) int gridsize = gridInqSize(gridID); if ( gridsize > 1 ) lchunk = TRUE; int gridtype = gridInqType(gridID); - int gridindex = vlistGridIndex(vlistID, gridID); + int gridindex = nc_grid_index(streamptr, gridID); if ( gridtype != GRID_TRAJECTORY ) { - xid = streamptr->xdimID[gridindex]; - yid = streamptr->ydimID[gridindex]; + xid = streamptr->ncgrid[gridindex].xdimID; + yid = streamptr->ncgrid[gridindex].ydimID; if ( xid != UNDEFID ) cdf_inq_dimlen(fileID, xid, &xsize); if ( yid != UNDEFID ) cdf_inq_dimlen(fileID, yid, &ysize); } int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); int zid = streamptr->zaxisID[zaxisindex]; - int zaxis_is_scalar = FALSE; - if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID); + bool zaxis_is_scalar = false; + if ( zid == UNDEFID ) zaxis_is_scalar = zaxisInqScalar(zaxisID) > 0; if ( dimorder[0] != 3 ) lchunk = FALSE; /* ZYX and ZXY */ @@ -367,7 +411,7 @@ int cdfDefVar(stream_t *streamptr, int varID) } else if ( dimorder[id] == 2 && yid != UNDEFID ) { - if ( chunktype == CHUNK_LINES ) + if ( chunktype == CDI_CHUNK_LINES ) chunks[ndims] = 1; else chunks[ndims] = ysize; @@ -473,7 +517,7 @@ int cdfDefVar(stream_t *streamptr, int varID) #if defined (HAVE_NETCDF4) if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) ) { - if ( chunktype == CHUNK_AUTO ) + if ( chunktype == CDI_CHUNK_AUTO ) retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL); else retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks); @@ -482,7 +526,7 @@ int cdfDefVar(stream_t *streamptr, int varID) } #endif - if ( streamptr->comptype == COMPRESS_ZIP ) + if ( streamptr->comptype == CDI_COMPRESS_ZIP ) { if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) ) { @@ -503,7 +547,7 @@ int cdfDefVar(stream_t *streamptr, int varID) } } - if ( streamptr->comptype == COMPRESS_SZIP ) + if ( streamptr->comptype == CDI_COMPRESS_SZIP ) { if ( lchunk && (streamptr->filetype == FILETYPE_NC4 || streamptr->filetype == FILETYPE_NC4C) ) { @@ -557,8 +601,7 @@ int cdfDefVar(stream_t *streamptr, int varID) cdf_put_att_int(fileID, ncvarid, "table", NC_INT, 1, &tablenum); } - char coordinates[CDI_MAX_NAME]; - coordinates[0] = 0; + char coordinates[CDI_MAX_NAME]; coordinates[0] = 0; if ( zaxis_is_scalar ) { @@ -571,42 +614,32 @@ int cdfDefVar(stream_t *streamptr, int varID) } } - if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT && gridtype != GRID_CURVILINEAR ) + if ( gridtype != GRID_GENERIC && gridtype != GRID_LONLAT && + gridtype != GRID_PROJECTION && gridtype != GRID_CURVILINEAR ) { size_t len = strlen(gridNamePtr(gridtype)); if ( len > 0 ) cdf_put_att_text(fileID, ncvarid, "grid_type", len, gridNamePtr(gridtype)); } - if ( gridIsRotated(gridID) ) - { - char mapping[] = "rotated_pole"; - cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping); - } + char gmapvarname[CDI_MAX_NAME]; gmapvarname[0] = 0; - if ( gridtype == GRID_SINUSOIDAL ) - { - char mapping[] = "sinusoidal"; - cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping); - } - else if ( gridtype == GRID_LAEA ) - { - char mapping[] = "laea"; - cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping); - } - else if ( gridtype == GRID_LCC2 ) - { - char mapping[] = "Lambert_Conformal"; - cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(mapping), mapping); - } - else if ( gridtype == GRID_TRAJECTORY ) + if ( gridtype == GRID_SINUSOIDAL ) strcpy(gmapvarname, "Sinusoidal"); + else if ( gridtype == GRID_LAEA ) strcpy(gmapvarname, "Lambert_AEA"); + else if ( gridtype == GRID_LCC2 ) strcpy(gmapvarname, "Lambert_CC"); + else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) ) strcpy(gmapvarname, "rotated_pole"); + else cdf_get_gmapvarname(gridID, gmapvarname); + + if ( gmapvarname[0] ) cdf_put_att_text(fileID, ncvarid, "grid_mapping", strlen(gmapvarname), gmapvarname); + + if ( gridtype == GRID_TRAJECTORY ) { cdf_put_att_text(fileID, ncvarid, "coordinates", 9, "tlon tlat" ); } else if ( gridtype == GRID_LONLAT && xid == UNDEFID && yid == UNDEFID && gridsize == 1 ) { - int ncxvarID = streamptr->ncxvarID[gridindex]; - int ncyvarID = streamptr->ncyvarID[gridindex]; + int ncxvarID = streamptr->ncgrid[gridindex].xvarID; + int ncyvarID = streamptr->ncgrid[gridindex].yvarID; if ( ncyvarID != CDI_UNDEFID ) { size_t len = strlen(coordinates); @@ -623,9 +656,9 @@ int cdfDefVar(stream_t *streamptr, int varID) else if ( gridtype == GRID_UNSTRUCTURED || gridtype == GRID_CURVILINEAR ) { char cellarea[CDI_MAX_NAME] = "area: "; - int ncxvarID = streamptr->ncxvarID[gridindex]; - int ncyvarID = streamptr->ncyvarID[gridindex]; - int ncavarID = streamptr->ncavarID[gridindex]; + int ncxvarID = streamptr->ncgrid[gridindex].xvarID; + int ncyvarID = streamptr->ncgrid[gridindex].yvarID; + int ncavarID = streamptr->ncgrid[gridindex].avarID; if ( ncyvarID != CDI_UNDEFID ) { size_t len = strlen(coordinates); @@ -731,14 +764,6 @@ int cdfDefVar(stream_t *streamptr, int varID) cdf_put_att_int(fileID, ncvarid, "realization", NC_INT, 1, &ensID); cdf_put_att_int(fileID, ncvarid, "ensemble_members", NC_INT, 1, &ensCount); cdf_put_att_int(fileID, ncvarid, "forecast_init_type", NC_INT, 1, &forecast_type); - -#ifdef DBG - if( DBG ) - { - fprintf( stderr, "cdfDefVar :\n EnsID %d\n Enscount %d\n Forecast init type %d\n", ensID, - ensCount, forecast_type ); - } -#endif } /* Attributes */ @@ -779,18 +804,16 @@ void cdfEndDef(stream_t *streamptr) static void cdfWriteGridTraj(stream_t *streamptr, int gridID) { - int vlistID = streamptr->vlistID; - int fileID = streamptr->fileID; - - int gridindex = vlistGridIndex(vlistID, gridID); - int lonID = streamptr->xdimID[gridindex]; - int latID = streamptr->ydimID[gridindex]; + int gridindex = nc_grid_index(streamptr, gridID); + int lonID = streamptr->ncgrid[gridindex].xdimID; + int latID = streamptr->ncgrid[gridindex].ydimID; double xlon = gridInqXval(gridID, 0); double xlat = gridInqYval(gridID, 0); int tsID = streamptr->curTsID; size_t index = (size_t)tsID; + int fileID = streamptr->fileID; cdf_put_var1_double(fileID, lonID, &index, &xlon); cdf_put_var1_double(fileID, latID, &index, &xlat); } @@ -941,7 +964,7 @@ void cdf_write_var_data(int fileID, int vlistID, int varID, int ncvarid, int dty } } - if ( swapxy ) // implemented only for cdf_write_var_slice() + if ( swapxy ) // implemented only for cdf_write_var_slice() { size_t gridsize = xsize*ysize; if ( memtype == MEMTYPE_FLOAT ) @@ -1009,9 +1032,9 @@ void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data } else { - int gridindex = vlistGridIndex(vlistID, gridID); - xid = streamptr->xdimID[gridindex]; - yid = streamptr->ydimID[gridindex]; + int gridindex = nc_grid_index(streamptr, gridID); + xid = streamptr->ncgrid[gridindex].xdimID; + yid = streamptr->ncgrid[gridindex].ydimID; } int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); @@ -1107,9 +1130,9 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype, } else { - int gridindex = vlistGridIndex(vlistID, gridID); - xid = streamptr->xdimID[gridindex]; - yid = streamptr->ydimID[gridindex]; + int gridindex = nc_grid_index(streamptr, gridID); + xid = streamptr->ncgrid[gridindex].xdimID; + yid = streamptr->ncgrid[gridindex].ydimID; } int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); @@ -1205,9 +1228,9 @@ void cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtyp } else { - int gridindex = vlistGridIndex(vlistID, gridID); - xid = streamptr->xdimID[gridindex]; - yid = streamptr->ydimID[gridindex]; + int gridindex = nc_grid_index(streamptr, gridID); + xid = streamptr->ncgrid[gridindex].xdimID; + yid = streamptr->ncgrid[gridindex].ydimID; } int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); @@ -1270,3 +1293,13 @@ void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nm } #endif + +/* + * Local Variables: + * c-file-style: "Java" + * c-basic-offset: 2 + * indent-tabs-mode: nil + * show-trailing-whitespace: t + * require-trailing-newline: t + * End: + */ diff --git a/src/cdi.h b/src/cdi.h index 69b253d8ad0ae5879c89d32aeeb7885644cc7aea..8496fe9e007365962a3e15ef4324a82f3a73ea3a 100644 --- a/src/cdi.h +++ b/src/cdi.h @@ -57,12 +57,12 @@ extern "C" { /* Compress types */ -#define COMPRESS_NONE 0 -#define COMPRESS_SZIP 1 -#define COMPRESS_GZIP 2 -#define COMPRESS_BZIP2 3 -#define COMPRESS_ZIP 4 -#define COMPRESS_JPEG 5 +#define CDI_COMPRESS_NONE 0 +#define CDI_COMPRESS_SZIP 1 +#define CDI_COMPRESS_GZIP 2 +#define CDI_COMPRESS_BZIP2 3 +#define CDI_COMPRESS_ZIP 4 +#define CDI_COMPRESS_JPEG 5 /* external data types */ @@ -120,9 +120,9 @@ extern "C" { /* Chunks */ -#define CHUNK_AUTO 1 /* use default chunk size */ -#define CHUNK_GRID 2 -#define CHUNK_LINES 3 +#define CDI_CHUNK_AUTO 1 /* use default chunk size */ +#define CDI_CHUNK_GRID 2 +#define CDI_CHUNK_LINES 3 /* GRID types */ @@ -140,7 +140,12 @@ extern "C" { #define GRID_LCC2 12 /* Lambert Conformal Conic (PROJ) */ #define GRID_LAEA 13 /* Lambert Azimuthal Equal Area */ #define GRID_SINUSOIDAL 14 /* Sinusoidal */ -#define GRID_PROJECTION 15 /* Projected coordiantes */ +#define GRID_PROJECTION 15 /* Projected coordinates */ + +#define CDI_PROJ_RLL 21 /* Rotated Latitude Longitude */ +#define CDI_PROJ_LCC 22 /* Lambert Conformal Conic */ +#define CDI_PROJ_LAEA 23 /* Lambert Azimuthal Equal Area */ +#define CDI_PROJ_SINU 24 /* Sinusoidal */ /* ZAXIS types */ @@ -673,27 +678,27 @@ const char *vlistInqVarNamePtr(int vlistID, int varID); const char *vlistInqVarLongnamePtr(int vlistID, int varID); const char *vlistInqVarUnitsPtr(int vlistID, int varID); -/* VLIST attributes */ +/* CDI attributes */ -/* vlistInqNatts: Get number of variable attributes assigned to this variable */ -int vlistInqNatts(int vlistID, int varID, int *nattsp); -/* vlistInqAtt: Get information about an attribute */ -int vlistInqAtt(int vlistID, int varID, int attrnum, char *name, int *typep, int *lenp); -int vlistDelAtt(int vlistID, int varID, const char *name); +/* cdiInqNatts: Get number of attributes assigned to this variable */ +int cdiInqNatts(int cdiID, int varID, int *nattsp); +/* cdiInqAtt: Get information about an attribute */ +int cdiInqAtt(int cdiID, int varID, int attrnum, char *name, int *typep, int *lenp); +int cdiDelAtt(int cdiID, int varID, const char *name); -/* vlistDefAttInt: Define an integer attribute */ -int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int ip[]); -/* vlistDefAttFlt: Define a floating point attribute */ -int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double dp[]); -/* vlistDefAttTxt: Define a text attribute */ -int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp_cbuf); +/* cdiDefAttInt: Define an integer attribute */ +int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int ip[]); +/* cdiDefAttFlt: Define a floating point attribute */ +int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double dp[]); +/* cdiDefAttTxt: Define a text attribute */ +int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp_cbuf); -/* vlistInqAttInt: Get the value(s) of an integer attribute */ -int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int ip[]); -/* vlistInqAttFlt: Get the value(s) of a floating point attribute */ -int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double dp[]); -/* vlistInqAttTxt: Get the value(s) of a text attribute */ -int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp_cbuf); +/* cdiInqAttInt: Get the value(s) of an integer attribute */ +int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int ip[]); +/* cdiInqAttFlt: Get the value(s) of a floating point attribute */ +int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double dp[]); +/* cdiInqAttTxt: Get the value(s) of a text attribute */ +int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp_cbuf); /* GRID routines */ @@ -720,6 +725,18 @@ void gridDestroy(int gridID); /* gridDuplicate: Duplicate a Grid */ int gridDuplicate(int gridID); +/* gridDefProj: Define the projection ID of a Grid */ +void gridDefProj(int gridID, int projID); + +/* gridInqProj: Get the projection ID of a Grid */ +int gridInqProj(int gridID); + +/* gridDefProjType: Define the projection type */ +void gridDefProjType(int gridID, int projtype); + +/* gridInqProjType: Get the projection type */ +int gridInqProjType(int gridID); + /* gridInqType: Get the type of a Grid */ int gridInqType(int gridID); @@ -757,21 +774,23 @@ void gridDefYvals(int gridID, const double yvals[]); int gridInqYvals(int gridID, double yvals[]); /* CDI grid string key values */ -#define CDI_GRID_XNAME 901 // X-axis name -#define CDI_GRID_YNAME 902 // Y-axis name -#define CDI_GRID_XDIMNAME 903 // X-axis dimension name -#define CDI_GRID_YDIMNAME 904 // Y-axis dimension name -#define CDI_GRID_VDIMNAME 905 // Vertex dimension name -#define CDI_GRID_XLONGNAME 906 // X-axis longname -#define CDI_GRID_YLONGNAME 907 // Y-axis longname -#define CDI_GRID_XUNITS 908 // X-axis units -#define CDI_GRID_YUNITS 909 // Y-axis units - -// cdiGridDefString: Define a CDI grid string value from a key -int cdiGridDefString(int gridID, int key, int size, const char *mesg); - -// cdiGridInqString: Get a CDI grid string value from a key -int cdiGridInqString(int gridID, int key, int size, char *mesg); +#define CDI_KEY_XNAME 901 // X-axis name +#define CDI_KEY_YNAME 902 // Y-axis name +#define CDI_KEY_XDIMNAME 903 // X-axis dimension name +#define CDI_KEY_YDIMNAME 904 // Y-axis dimension name +#define CDI_KEY_VDIMNAME 905 // Vertex dimension name +#define CDI_KEY_XLONGNAME 906 // X-axis longname +#define CDI_KEY_YLONGNAME 907 // Y-axis longname +#define CDI_KEY_XUNITS 908 // X-axis units +#define CDI_KEY_YUNITS 909 // Y-axis units +#define CDI_KEY_MAPNAME 920 // Grid mapping var name +#define CDI_KEY_MAPPING 921 // Grid mapping name + +// cdiGridDefKeyStr: Define a CDI grid string value from a key +int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg); + +// cdiGridInqKeyStr: Get a CDI grid string value from a key +int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg); /* gridDefXname: Define the name of a X-axis */ void gridDefXname(int gridID, const char *xname); @@ -832,6 +851,10 @@ double gridInqYinc(int gridID); int gridIsCircular(int gridID); int gridIsRotated(int gridID); + +void gridInqProjParamRLL(int gridID, double *xpole, double *ypole, double *angle); +void gridDefProjParamRLL(int gridID, double xpole, double ypole, double angle); + void gridDefXpole(int gridID, double xpole); double gridInqXpole(int gridID); void gridDefYpole(int gridID, double ypole); diff --git a/src/cdi.inc b/src/cdi.inc index 333e1e2b7462425d6039b4d0da41e13e6963fff4..5dcb37032584fcdcd6b116fe2b0357232a6c11db 100644 --- a/src/cdi.inc +++ b/src/cdi.inc @@ -1,10 +1,10 @@ ! This file was automatically generated, don't edit! ! -! Fortran interface for CDI library version 1.7.2 +! Fortran interface for CDI library version 1.8.0 ! ! Author: ! ------- -! Uwe Schulzweida, MPI-MET, Hamburg, April 2016 +! Uwe Schulzweida, MPI-MET, Hamburg, August 2016 ! INTEGER CDI_MAX_NAME @@ -75,18 +75,18 @@ ! ! Compress types ! - INTEGER COMPRESS_NONE - PARAMETER (COMPRESS_NONE = 0) - INTEGER COMPRESS_SZIP - PARAMETER (COMPRESS_SZIP = 1) - INTEGER COMPRESS_GZIP - PARAMETER (COMPRESS_GZIP = 2) - INTEGER COMPRESS_BZIP2 - PARAMETER (COMPRESS_BZIP2 = 3) - INTEGER COMPRESS_ZIP - PARAMETER (COMPRESS_ZIP = 4) - INTEGER COMPRESS_JPEG - PARAMETER (COMPRESS_JPEG = 5) + INTEGER CDI_COMPRESS_NONE + PARAMETER (CDI_COMPRESS_NONE = 0) + INTEGER CDI_COMPRESS_SZIP + PARAMETER (CDI_COMPRESS_SZIP = 1) + INTEGER CDI_COMPRESS_GZIP + PARAMETER (CDI_COMPRESS_GZIP = 2) + INTEGER CDI_COMPRESS_BZIP2 + PARAMETER (CDI_COMPRESS_BZIP2 = 3) + INTEGER CDI_COMPRESS_ZIP + PARAMETER (CDI_COMPRESS_ZIP = 4) + INTEGER CDI_COMPRESS_JPEG + PARAMETER (CDI_COMPRESS_JPEG = 5) ! ! external data types ! @@ -194,12 +194,12 @@ ! ! Chunks ! - INTEGER CHUNK_AUTO - PARAMETER (CHUNK_AUTO = 1) - INTEGER CHUNK_GRID - PARAMETER (CHUNK_GRID = 2) - INTEGER CHUNK_LINES - PARAMETER (CHUNK_LINES = 3) + INTEGER CDI_CHUNK_AUTO + PARAMETER (CDI_CHUNK_AUTO = 1) + INTEGER CDI_CHUNK_GRID + PARAMETER (CDI_CHUNK_GRID = 2) + INTEGER CDI_CHUNK_LINES + PARAMETER (CDI_CHUNK_LINES = 3) ! ! GRID types ! @@ -233,6 +233,14 @@ PARAMETER (GRID_SINUSOIDAL = 14) INTEGER GRID_PROJECTION PARAMETER (GRID_PROJECTION = 15) + INTEGER CDI_PROJ_RLL + PARAMETER (CDI_PROJ_RLL = 21) + INTEGER CDI_PROJ_LCC + PARAMETER (CDI_PROJ_LCC = 22) + INTEGER CDI_PROJ_LAEA + PARAMETER (CDI_PROJ_LAEA = 23) + INTEGER CDI_PROJ_SINU + PARAMETER (CDI_PROJ_SINU = 24) ! ! ZAXIS types ! @@ -1340,78 +1348,78 @@ EXTERNAL vlistInqVarUnitsPtr ! -! VLIST attributes +! CDI attributes ! - INTEGER vlistInqNatts -! (INTEGER vlistID, + INTEGER cdiInqNatts +! (INTEGER cdiID, ! INTEGER varID, ! INTEGER nattsp) - EXTERNAL vlistInqNatts + EXTERNAL cdiInqNatts - INTEGER vlistInqAtt -! (INTEGER vlistID, + INTEGER cdiInqAtt +! (INTEGER cdiID, ! INTEGER varID, ! INTEGER attrnum, ! CHARACTER*(*) name, ! INTEGER typep, ! INTEGER lenp) - EXTERNAL vlistInqAtt + EXTERNAL cdiInqAtt - INTEGER vlistDelAtt -! (INTEGER vlistID, + INTEGER cdiDelAtt +! (INTEGER cdiID, ! INTEGER varID, ! CHARACTER*(*) name) - EXTERNAL vlistDelAtt + EXTERNAL cdiDelAtt - INTEGER vlistDefAttInt -! (INTEGER vlistID, + INTEGER cdiDefAttInt +! (INTEGER cdiID, ! INTEGER varID, ! CHARACTER*(*) name, ! INTEGER type, ! INTEGER len, ! INTEGER ip(*)) - EXTERNAL vlistDefAttInt + EXTERNAL cdiDefAttInt - INTEGER vlistDefAttFlt -! (INTEGER vlistID, + INTEGER cdiDefAttFlt +! (INTEGER cdiID, ! INTEGER varID, ! CHARACTER*(*) name, ! INTEGER type, ! INTEGER len, ! DOUBLEPRECISION dp(*)) - EXTERNAL vlistDefAttFlt + EXTERNAL cdiDefAttFlt - INTEGER vlistDefAttTxt -! (INTEGER vlistID, + INTEGER cdiDefAttTxt +! (INTEGER cdiID, ! INTEGER varID, ! CHARACTER*(*) name, ! INTEGER len, ! CHARACTER*(*) tp_cbuf) - EXTERNAL vlistDefAttTxt + EXTERNAL cdiDefAttTxt - INTEGER vlistInqAttInt -! (INTEGER vlistID, + INTEGER cdiInqAttInt +! (INTEGER cdiID, ! INTEGER varID, ! CHARACTER*(*) name, ! INTEGER mlen, ! INTEGER ip(*)) - EXTERNAL vlistInqAttInt + EXTERNAL cdiInqAttInt - INTEGER vlistInqAttFlt -! (INTEGER vlistID, + INTEGER cdiInqAttFlt +! (INTEGER cdiID, ! INTEGER varID, ! CHARACTER*(*) name, ! INTEGER mlen, ! DOUBLEPRECISION dp(*)) - EXTERNAL vlistInqAttFlt + EXTERNAL cdiInqAttFlt - INTEGER vlistInqAttTxt -! (INTEGER vlistID, + INTEGER cdiInqAttTxt +! (INTEGER cdiID, ! INTEGER varID, ! CHARACTER*(*) name, ! INTEGER mlen, ! CHARACTER*(*) tp_cbuf) - EXTERNAL vlistInqAttTxt + EXTERNAL cdiInqAttTxt ! ! GRID routines @@ -1468,6 +1476,24 @@ ! (INTEGER gridID) EXTERNAL gridDuplicate +! gridDefProj +! (INTEGER gridID, +! INTEGER projID) + EXTERNAL gridDefProj + + INTEGER gridInqProj +! (INTEGER gridID) + EXTERNAL gridInqProj + +! gridDefProjType +! (INTEGER gridID, +! INTEGER projtype) + EXTERNAL gridDefProjType + + INTEGER gridInqProjType +! (INTEGER gridID) + EXTERNAL gridInqProjType + INTEGER gridInqType ! (INTEGER gridID) EXTERNAL gridInqType @@ -1526,37 +1552,41 @@ ! ! CDI grid string key values ! - INTEGER CDI_GRID_XNAME - PARAMETER (CDI_GRID_XNAME = 901) - INTEGER CDI_GRID_YNAME - PARAMETER (CDI_GRID_YNAME = 902) - INTEGER CDI_GRID_XDIMNAME - PARAMETER (CDI_GRID_XDIMNAME = 903) - INTEGER CDI_GRID_YDIMNAME - PARAMETER (CDI_GRID_YDIMNAME = 904) - INTEGER CDI_GRID_VDIMNAME - PARAMETER (CDI_GRID_VDIMNAME = 905) - INTEGER CDI_GRID_XLONGNAME - PARAMETER (CDI_GRID_XLONGNAME = 906) - INTEGER CDI_GRID_YLONGNAME - PARAMETER (CDI_GRID_YLONGNAME = 907) - INTEGER CDI_GRID_XUNITS - PARAMETER (CDI_GRID_XUNITS = 908) - INTEGER CDI_GRID_YUNITS - PARAMETER (CDI_GRID_YUNITS = 909) - INTEGER cdiGridDefString + INTEGER CDI_KEY_XNAME + PARAMETER (CDI_KEY_XNAME = 901) + INTEGER CDI_KEY_YNAME + PARAMETER (CDI_KEY_YNAME = 902) + INTEGER CDI_KEY_XDIMNAME + PARAMETER (CDI_KEY_XDIMNAME = 903) + INTEGER CDI_KEY_YDIMNAME + PARAMETER (CDI_KEY_YDIMNAME = 904) + INTEGER CDI_KEY_VDIMNAME + PARAMETER (CDI_KEY_VDIMNAME = 905) + INTEGER CDI_KEY_XLONGNAME + PARAMETER (CDI_KEY_XLONGNAME = 906) + INTEGER CDI_KEY_YLONGNAME + PARAMETER (CDI_KEY_YLONGNAME = 907) + INTEGER CDI_KEY_XUNITS + PARAMETER (CDI_KEY_XUNITS = 908) + INTEGER CDI_KEY_YUNITS + PARAMETER (CDI_KEY_YUNITS = 909) + INTEGER CDI_KEY_MAPNAME + PARAMETER (CDI_KEY_MAPNAME = 920) + INTEGER CDI_KEY_MAPPING + PARAMETER (CDI_KEY_MAPPING = 921) + INTEGER cdiGridDefKeyStr ! (INTEGER gridID, ! INTEGER key, ! INTEGER size, ! CHARACTER*(*) mesg) - EXTERNAL cdiGridDefString + EXTERNAL cdiGridDefKeyStr - INTEGER cdiGridInqString + INTEGER cdiGridInqKeyStr ! (INTEGER gridID, ! INTEGER key, ! INTEGER size, ! CHARACTER*(*) mesg) - EXTERNAL cdiGridInqString + EXTERNAL cdiGridInqKeyStr ! gridDefXname ! (INTEGER gridID, @@ -1663,6 +1693,20 @@ ! (INTEGER gridID) EXTERNAL gridIsRotated +! gridInqProjParamRLL +! (INTEGER gridID, +! DOUBLEPRECISION xpole, +! DOUBLEPRECISION ypole, +! DOUBLEPRECISION angle) + EXTERNAL gridInqProjParamRLL + +! gridDefProjParamRLL +! (INTEGER gridID, +! DOUBLEPRECISION xpole, +! DOUBLEPRECISION ypole, +! DOUBLEPRECISION angle) + EXTERNAL gridDefProjParamRLL + ! gridDefXpole ! (INTEGER gridID, ! DOUBLEPRECISION xpole) diff --git a/src/cdiFortran.c b/src/cdiFortran.c index 2b83d7036fd11dc1013dbfbe652b3849bb669e06..527c0bd0befc79a5349d4307bf5e9e3731d630b2 100644 --- a/src/cdiFortran.c +++ b/src/cdiFortran.c @@ -287,17 +287,17 @@ FCALLSCFUN2 (STRING, vlistInqVarNamePtr, VLISTINQVARNAMEPTR, vlistinqvarnameptr, FCALLSCFUN2 (STRING, vlistInqVarLongnamePtr, VLISTINQVARLONGNAMEPTR, vlistinqvarlongnameptr, INT, INT) FCALLSCFUN2 (STRING, vlistInqVarUnitsPtr, VLISTINQVARUNITSPTR, vlistinqvarunitsptr, INT, INT) -/* VLIST attributes */ - -FCALLSCFUN3 (INT, vlistInqNatts, VLISTINQNATTS, vlistinqnatts, INT, INT, PINT) -FCALLSCFUN6 (INT, vlistInqAtt, VLISTINQATT, vlistinqatt, INT, INT, INT, PSTRING, PINT, PINT) -FCALLSCFUN3 (INT, vlistDelAtt, VLISTDELATT, vlistdelatt, INT, INT, STRING) -FCALLSCFUN6 (INT, vlistDefAttInt, VLISTDEFATTINT, vlistdefattint, INT, INT, STRING, INT, INT, INTV) -FCALLSCFUN6 (INT, vlistDefAttFlt, VLISTDEFATTFLT, vlistdefattflt, INT, INT, STRING, INT, INT, DOUBLEV) -FCALLSCFUN5 (INT, vlistDefAttTxt, VLISTDEFATTTXT, vlistdefatttxt, INT, INT, STRING, INT, PPSTRING) -FCALLSCFUN5 (INT, vlistInqAttInt, VLISTINQATTINT, vlistinqattint, INT, INT, STRING, INT, INTV) -FCALLSCFUN5 (INT, vlistInqAttFlt, VLISTINQATTFLT, vlistinqattflt, INT, INT, STRING, INT, DOUBLEV) -FCALLSCFUN5 (INT, vlistInqAttTxt, VLISTINQATTTXT, vlistinqatttxt, INT, INT, STRING, INT, PPSTRING) +/* CDI attributes */ + +FCALLSCFUN3 (INT, cdiInqNatts, CDIINQNATTS, cdiinqnatts, INT, INT, PINT) +FCALLSCFUN6 (INT, cdiInqAtt, CDIINQATT, cdiinqatt, INT, INT, INT, PSTRING, PINT, PINT) +FCALLSCFUN3 (INT, cdiDelAtt, CDIDELATT, cdidelatt, INT, INT, STRING) +FCALLSCFUN6 (INT, cdiDefAttInt, CDIDEFATTINT, cdidefattint, INT, INT, STRING, INT, INT, INTV) +FCALLSCFUN6 (INT, cdiDefAttFlt, CDIDEFATTFLT, cdidefattflt, INT, INT, STRING, INT, INT, DOUBLEV) +FCALLSCFUN5 (INT, cdiDefAttTxt, CDIDEFATTTXT, cdidefatttxt, INT, INT, STRING, INT, PPSTRING) +FCALLSCFUN5 (INT, cdiInqAttInt, CDIINQATTINT, cdiinqattint, INT, INT, STRING, INT, INTV) +FCALLSCFUN5 (INT, cdiInqAttFlt, CDIINQATTFLT, cdiinqattflt, INT, INT, STRING, INT, DOUBLEV) +FCALLSCFUN5 (INT, cdiInqAttTxt, CDIINQATTTXT, cdiinqatttxt, INT, INT, STRING, INT, PPSTRING) /* GRID routines */ @@ -312,6 +312,10 @@ FCALLSCSUB3 (gridPrint, GRIDPRINT, gridprint, INT, INT, INT) FCALLSCFUN2 (INT, gridCreate, GRIDCREATE, gridcreate, INT, INT) FCALLSCSUB1 (gridDestroy, GRIDDESTROY, griddestroy, INT) FCALLSCFUN1 (INT, gridDuplicate, GRIDDUPLICATE, gridduplicate, INT) +FCALLSCSUB2 (gridDefProj, GRIDDEFPROJ, griddefproj, INT, INT) +FCALLSCFUN1 (INT, gridInqProj, GRIDINQPROJ, gridinqproj, INT) +FCALLSCSUB2 (gridDefProjType, GRIDDEFPROJTYPE, griddefprojtype, INT, INT) +FCALLSCFUN1 (INT, gridInqProjType, GRIDINQPROJTYPE, gridinqprojtype, INT) FCALLSCFUN1 (INT, gridInqType, GRIDINQTYPE, gridinqtype, INT) FCALLSCFUN1 (INT, gridInqSize, GRIDINQSIZE, gridinqsize, INT) FCALLSCSUB2 (gridDefXsize, GRIDDEFXSIZE, griddefxsize, INT, INT) @@ -327,8 +331,8 @@ FCALLSCFUN2 (INT, gridInqYvals, GRIDINQYVALS, gridinqyvals, INT, DOUBLEV) /* CDI grid string key values */ -FCALLSCFUN4 (INT, cdiGridDefString, CDIGRIDDEFSTRING, cdigriddefstring, INT, INT, INT, STRING) -FCALLSCFUN4 (INT, cdiGridInqString, CDIGRIDINQSTRING, cdigridinqstring, INT, INT, INT, PSTRING) +FCALLSCFUN4 (INT, cdiGridDefKeyStr, CDIGRIDDEFKEYSTR, cdigriddefkeystr, INT, INT, INT, STRING) +FCALLSCFUN4 (INT, cdiGridInqKeyStr, CDIGRIDINQKEYSTR, cdigridinqkeystr, INT, INT, INT, PSTRING) FCALLSCSUB2 (gridDefXname, GRIDDEFXNAME, griddefxname, INT, STRING) FCALLSCSUB2 (gridInqXname, GRIDINQXNAME, gridinqxname, INT, PSTRING) FCALLSCSUB2 (gridDefXlongname, GRIDDEFXLONGNAME, griddefxlongname, INT, STRING) @@ -351,6 +355,8 @@ FCALLSCFUN1 (DOUBLE, gridInqXinc, GRIDINQXINC, gridinqxinc, INT) FCALLSCFUN1 (DOUBLE, gridInqYinc, GRIDINQYINC, gridinqyinc, INT) FCALLSCFUN1 (INT, gridIsCircular, GRIDISCIRCULAR, gridiscircular, INT) FCALLSCFUN1 (INT, gridIsRotated, GRIDISROTATED, gridisrotated, INT) +FCALLSCSUB4 (gridInqProjParamRLL, GRIDINQPROJPARAMRLL, gridinqprojparamrll, INT, PDOUBLE, PDOUBLE, PDOUBLE) +FCALLSCSUB4 (gridDefProjParamRLL, GRIDDEFPROJPARAMRLL, griddefprojparamrll, INT, DOUBLE, DOUBLE, DOUBLE) FCALLSCSUB2 (gridDefXpole, GRIDDEFXPOLE, griddefxpole, INT, DOUBLE) FCALLSCFUN1 (DOUBLE, gridInqXpole, GRIDINQXPOLE, gridinqxpole, INT) FCALLSCSUB2 (gridDefYpole, GRIDDEFYPOLE, griddefypole, INT, DOUBLE) diff --git a/src/vlist_att.c b/src/cdi_att.c similarity index 55% rename from src/vlist_att.c rename to src/cdi_att.c index aea66506f8a78eec256b85840a111424bf24533a..156d9c1f0226e8233a68525a35032c63f457d831 100644 --- a/src/vlist_att.c +++ b/src/cdi_att.c @@ -1,5 +1,5 @@ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif #include <assert.h> @@ -12,9 +12,12 @@ #include "cdi.h" #include "cdi_int.h" #include "vlist.h" -#include "vlist_att.h" +#include "cdi_att.h" #include "error.h" #include "serialize.h" +#include "grid.h" +#include "resource_unpack.h" + static cdi_atts_t *get_attsp(vlist_t *vlistptr, int varID) @@ -31,7 +34,7 @@ cdi_atts_t *get_attsp(vlist_t *vlistptr, int varID) attsp = &(vlistptr->vars[varID].atts); } - return (attsp); + return attsp; } static @@ -49,27 +52,24 @@ cdi_att_t *find_att(cdi_atts_t *attsp, const char *name) { cdi_att_t *attp = atts + attid; if ( attp->namesz == slen && memcmp(attp->name, name, slen) == 0 ) - return (attp); /* Normal return */ + return attp; /* Normal return */ } - return (NULL); + return NULL; } static cdi_att_t *new_att(cdi_atts_t *attsp, const char *name) { - cdi_att_t *attp; - size_t slen; - xassert(attsp != NULL); xassert(name != NULL); - if ( attsp->nelems == attsp->nalloc ) return (NULL); + if ( attsp->nelems == attsp->nalloc ) return NULL; - attp = &(attsp->value[attsp->nelems]); + cdi_att_t *attp = &(attsp->value[attsp->nelems]); attsp->nelems++; - slen = strlen(name); + size_t slen = strlen(name); if ( slen > CDI_MAX_NAME ) slen = CDI_MAX_NAME; attp->name = (char *) Malloc(slen+1); @@ -77,7 +77,7 @@ cdi_att_t *new_att(cdi_atts_t *attsp, const char *name) attp->namesz = slen; attp->xvalue = NULL; - return (attp); + return attp; } static @@ -97,44 +97,59 @@ void fill_att(cdi_att_t *attp, int indtype, int exdtype, size_t nelems, size_t x } } +static +cdi_atts_t *cdi_get_attsp(int objID, int varID) +{ + cdi_atts_t *attsp = NULL; + + if ( varID == CDI_GLOBAL && reshGetTxCode(objID) == GRID ) + { + grid_t *gridptr = gridID2Ptr(objID); + attsp = &gridptr->atts; + } + else + { + vlist_t *vlistptr = vlist_to_pointer(objID); + attsp = get_attsp(vlistptr, varID); + } + + return attsp; +} + /* -@Function vlistInqNatts -@Title Get number of variable attributes +@Function cdiInqNatts +@Title Get number of attributes -@Prototype int vlistInqNatts(int vlistID, int varID, int *nattsp) +@Prototype int cdiInqNatts(int cdiID, int varID, int *nattsp) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. - @Item nattsp Pointer to location for returned number of variable attributes. + @Item nattsp Pointer to location for returned number of attributes. @Description -The function @func{vlistInqNatts} gets the number of variable attributes assigned to this variable. +The function @func{cdiInqNatts} gets the number of attributes assigned to this variable. @EndFunction */ -int vlistInqNatts(int vlistID, int varID, int *nattsp) +int cdiInqNatts(int cdiID, int varID, int *nattsp) { int status = CDI_NOERR; - vlist_t *vlistptr; - cdi_atts_t *attsp; - vlistptr = vlist_to_pointer(vlistID); - - attsp = get_attsp(vlistptr, varID); + cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID); xassert(attsp != NULL); *nattsp = (int)attsp->nelems; - return (status); + return status; } /* -@Function vlistInqAtt +@Function cdiInqAtt @Title Get information about an attribute -@Prototype int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp) +@Prototype int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. @Item attnum Attribute number (from 0 to natts-1). @Item name Pointer to the location for the returned attribute name. The caller must allocate space for the @@ -144,22 +159,20 @@ int vlistInqNatts(int vlistID, int varID, int *nattsp) @Item lenp Pointer to location for returned attribute number. @Description -The function @func{vlistInqAtt} gets information about an attribute. +The function @func{cdiInqAtt} gets information about an attribute. @EndFunction */ -int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int *lenp) +int cdiInqAtt(int cdiID, int varID, int attnum, char *name, int *typep, int *lenp) { int status = CDI_NOERR; - cdi_att_t *attp = NULL; xassert(name != NULL); - vlist_t *vlistptr = vlist_to_pointer(vlistID); - - cdi_atts_t *attsp = get_attsp(vlistptr, varID); + cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID); xassert(attsp != NULL); + cdi_att_t *attp = NULL; if ( attnum >= 0 && attnum < (int)attsp->nelems ) attp = &(attsp->value[attnum]); @@ -177,102 +190,79 @@ int vlistInqAtt(int vlistID, int varID, int attnum, char *name, int *typep, int status = -1; } - return (status); + return status; } -int vlistDelAtts(int vlistID, int varID) +int cdiDelAtts(int cdiID, int varID) { int status = CDI_NOERR; - vlist_t *vlistptr; - cdi_att_t *attp = NULL; - cdi_atts_t *attsp; - int attid; - - vlistptr = vlist_to_pointer(vlistID); - attsp = get_attsp(vlistptr, varID); + cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID); xassert(attsp != NULL); - for ( attid = 0; attid < (int)attsp->nelems; attid++ ) + for ( int attid = 0; attid < (int)attsp->nelems; attid++ ) { - attp = &(attsp->value[attid]); + cdi_att_t *attp = &(attsp->value[attid]); if ( attp->name ) Free(attp->name); if ( attp->xvalue ) Free(attp->xvalue); } attsp->nelems = 0; - return (status); + return status; } -int vlistDelAtt(int vlistID, int varID, const char *name) +int cdiDelAtt(int cdiID, int varID, const char *name) { int status = CDI_NOERR; - UNUSED(vlistID); + UNUSED(cdiID); UNUSED(varID); UNUSED(name); - fprintf(stderr, "vlistDelAtt not implemented!\n"); + fprintf(stderr, "cdiDelAtt not implemented!\n"); - return (status); + return status; } static -int vlist_def_att(int indtype, int exdtype, int vlistID, int varID, const char *name, size_t len, size_t xsz, const void *xp) +int cdi_def_att(int indtype, int exdtype, int cdiID, int varID, const char *name, size_t len, size_t xsz, const void *xp) { int status = CDI_NOERR; - vlist_t *vlistptr; - cdi_att_t *attp; - cdi_atts_t *attsp; if ( len != 0 && xp == NULL ) /* Null arg */ - { - return (CDI_EINVAL); - } + return CDI_EINVAL; - vlistptr = vlist_to_pointer(vlistID); - - attsp = get_attsp(vlistptr, varID); + cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID); xassert(attsp != NULL); - attp = find_att(attsp, name); - if ( attp == NULL ) - attp = new_att(attsp, name); + cdi_att_t *attp = find_att(attsp, name); + if ( attp == NULL ) attp = new_att(attsp, name); - if ( attp != NULL ) - fill_att(attp, indtype, exdtype, len, xsz, xp); + if ( attp != NULL ) fill_att(attp, indtype, exdtype, len, xsz, xp); - return (status); + return status; } static -int vlist_inq_att(int indtype, int vlistID, int varID, const char *name, size_t mxsz, void *xp) +int cdi_inq_att(int indtype, int cdiID, int varID, const char *name, size_t mxsz, void *xp) { int status = CDI_NOERR; - vlist_t *vlistptr; - cdi_att_t *attp; - cdi_atts_t *attsp; - size_t xsz; if ( mxsz != 0 && xp == NULL ) /* Null arg */ - { - return (CDI_EINVAL); - } + return CDI_EINVAL; - vlistptr = vlist_to_pointer(vlistID); - - attsp = get_attsp(vlistptr, varID); + cdi_atts_t *attsp = cdi_get_attsp(cdiID, varID); xassert(attsp != NULL); - attp = find_att(attsp, name); + cdi_att_t *attp = find_att(attsp, name); if ( attp != NULL ) /* name in use */ { if ( attp->indtype == indtype ) { - xsz = attp->xsz; + size_t xsz = attp->xsz; if ( mxsz < xsz ) xsz = mxsz; if ( xsz > 0 ) memcpy(xp, attp->xvalue, xsz); @@ -289,40 +279,34 @@ int vlist_inq_att(int indtype, int vlistID, int varID, const char *name, size_t status = -1; } - return (status); + return status; } -int vlistCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2) +int cdiCopyVarAtts(int cdiID1, int varID_1, int cdiID2, int varID_2) { int status = CDI_NOERR; - vlist_t *vlistptr1; - cdi_att_t *attp = NULL; - cdi_atts_t *attsp1; - int attid; - - vlistptr1 = vlist_to_pointer(vlistID1); - attsp1 = get_attsp(vlistptr1, varID_1); + cdi_atts_t *attsp1 = cdi_get_attsp(cdiID1, varID_1); xassert(attsp1 != NULL); - for ( attid = 0; attid < (int)attsp1->nelems; attid++ ) + for ( int attid = 0; attid < (int)attsp1->nelems; attid++ ) { - attp = &(attsp1->value[attid]); - vlist_def_att(attp->indtype, attp->exdtype, vlistID2, varID_2, attp->name, attp->nelems, attp->xsz, attp->xvalue); + cdi_att_t *attp = &(attsp1->value[attid]); + cdi_def_att(attp->indtype, attp->exdtype, cdiID2, varID_2, attp->name, attp->nelems, attp->xsz, attp->xvalue); } - return (status); + return status; } /* -@Function vlistDefAttInt +@Function cdiDefAttInt @Title Define an integer attribute -@Prototype int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int *ip) +@Prototype int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. @Item name Attribute name. @Item type External data type (@func{DATATYPE_INT16} or @func{DATATYPE_INT32}). @@ -330,23 +314,23 @@ int vlistCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2) @Item ip Pointer to one or more integer values. @Description -The function @func{vlistDefAttInt} defines an integer attribute. +The function @func{cdiDefAttInt} defines an integer attribute. @EndFunction */ -int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, const int *ip) +int cdiDefAttInt(int cdiID, int varID, const char *name, int type, int len, const int *ip) { - return vlist_def_att(DATATYPE_INT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (int), ip); + return cdi_def_att(DATATYPE_INT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(int), ip); } /* -@Function vlistDefAttFlt +@Function cdiDefAttFlt @Title Define a floating point attribute -@Prototype int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double *dp) +@Prototype int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. @Item name Attribute name. @Item type External data type (@func{DATATYPE_FLT32} or @func{DATATYPE_FLT64}). @@ -354,110 +338,110 @@ int vlistDefAttInt(int vlistID, int varID, const char *name, int type, int len, @Item dp Pointer to one or more floating point values. @Description -The function @func{vlistDefAttFlt} defines a floating point attribute. +The function @func{cdiDefAttFlt} defines a floating point attribute. @EndFunction */ -int vlistDefAttFlt(int vlistID, int varID, const char *name, int type, int len, const double *dp) +int cdiDefAttFlt(int cdiID, int varID, const char *name, int type, int len, const double *dp) { - return vlist_def_att(DATATYPE_FLT, type, vlistID, varID, name, (size_t)len, (size_t)len * sizeof (double), dp); + return cdi_def_att(DATATYPE_FLT, type, cdiID, varID, name, (size_t)len, (size_t)len * sizeof(double), dp); } /* -@Function vlistDefAttTxt +@Function cdiDefAttTxt @Title Define a text attribute -@Prototype int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp) +@Prototype int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate} or @fref{gridCreate}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. @Item name Attribute name. @Item len Number of values provided for the attribute. @Item tp Pointer to one or more character values. @Description -The function @func{vlistDefAttTxt} defines a text attribute. +The function @func{cdiDefAttTxt} defines a text attribute. @EndFunction */ -int vlistDefAttTxt(int vlistID, int varID, const char *name, int len, const char *tp) +int cdiDefAttTxt(int cdiID, int varID, const char *name, int len, const char *tp) { - return vlist_def_att(DATATYPE_TXT, DATATYPE_TXT, vlistID, varID, name, (size_t)len, (size_t)len, tp); + return cdi_def_att(DATATYPE_TXT, DATATYPE_TXT, cdiID, varID, name, (size_t)len, (size_t)len, tp); } /* -@Function vlistInqAttInt +@Function cdiInqAttInt @Title Get the value(s) of an integer attribute -@Prototype int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip) +@Prototype int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. @Item name Attribute name. @Item mlen Number of allocated values provided for the attribute. @Item ip Pointer location for returned integer attribute value(s). @Description -The function @func{vlistInqAttInt} gets the values(s) of an integer attribute. +The function @func{cdiInqAttInt} gets the values(s) of an integer attribute. @EndFunction */ -int vlistInqAttInt(int vlistID, int varID, const char *name, int mlen, int *ip) +int cdiInqAttInt(int cdiID, int varID, const char *name, int mlen, int *ip) { - return vlist_inq_att(DATATYPE_INT, vlistID, varID, name, (size_t)mlen * sizeof (int), ip); + return cdi_inq_att(DATATYPE_INT, cdiID, varID, name, (size_t)mlen * sizeof(int), ip); } /* -@Function vlistInqAttFlt +@Function cdiInqAttFlt @Title Get the value(s) of a floating point attribute -@Prototype int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp) +@Prototype int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. @Item name Attribute name. @Item mlen Number of allocated values provided for the attribute. @Item dp Pointer location for returned floating point attribute value(s). @Description -The function @func{vlistInqAttFlt} gets the values(s) of a floating point attribute. +The function @func{cdiInqAttFlt} gets the values(s) of a floating point attribute. @EndFunction */ -int vlistInqAttFlt(int vlistID, int varID, const char *name, int mlen, double *dp) +int cdiInqAttFlt(int cdiID, int varID, const char *name, int mlen, double *dp) { - return vlist_inq_att(DATATYPE_FLT, vlistID, varID, name, (size_t)mlen * sizeof (double), dp); + return cdi_inq_att(DATATYPE_FLT, cdiID, varID, name, (size_t)mlen * sizeof(double), dp); } /* -@Function vlistInqAttTxt +@Function cdiInqAttTxt @Title Get the value(s) of a text attribute -@Prototype int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp) +@Prototype int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp) @Parameter - @Item vlistID Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}. + @Item cdiID CDI ID, from a previous call to @fref{vlistCreate}, @fref{gridCreate} or @fref{streamInqVlist}. @Item varID Variable identifier, or @func{CDI_GLOBAL} for a global attribute. @Item name Attribute name. @Item mlen Number of allocated values provided for the attribute. @Item tp Pointer location for returned text attribute value(s). @Description -The function @func{vlistInqAttTxt} gets the values(s) of a text attribute. +The function @func{cdiInqAttTxt} gets the values(s) of a text attribute. @EndFunction */ -int vlistInqAttTxt(int vlistID, int varID, const char *name, int mlen, char *tp) +int cdiInqAttTxt(int cdiID, int varID, const char *name, int mlen, char *tp) { - return vlist_inq_att(DATATYPE_TXT, vlistID, varID, name, (size_t)mlen * sizeof (char), tp); + return cdi_inq_att(DATATYPE_TXT, cdiID, varID, name, (size_t)mlen * sizeof(char), tp); } enum { - vlist_att_nints = 4, /* namesz, exdtype, indtype, nelems */ + cdi_att_nints = 4, /* namesz, exdtype, indtype, nelems */ }; -static inline int -vlistAttTypeLookup(cdi_att_t *attp) +static inline +int cdiAttTypeLookup(cdi_att_t *attp) { int type; switch (attp->indtype) @@ -477,8 +461,7 @@ vlistAttTypeLookup(cdi_att_t *attp) } -int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, - int attnum) +int cdi_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum) { cdi_atts_t *attspa = get_attsp(a, varIDA), *attspb = get_attsp(b, varIDB); @@ -502,8 +485,8 @@ int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, } -static int -vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context) +static +int cdiAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context) { cdi_atts_t *attsp; cdi_att_t *attp; @@ -511,30 +494,31 @@ vlistAttGetSize(vlist_t *vlistptr, int varID, int attnum, void *context) xassert(attsp = get_attsp(vlistptr, varID)); xassert(attnum >= 0 && attnum < (int)attsp->nelems); attp = &(attsp->value[attnum]); - int txsize = serializeGetSize(vlist_att_nints, DATATYPE_INT, context) + int txsize = serializeGetSize(cdi_att_nints, DATATYPE_INT, context) + serializeGetSize((int)attp->namesz, DATATYPE_TXT, context); - txsize += serializeGetSize((int)attp->nelems, vlistAttTypeLookup(attp), context); + txsize += serializeGetSize((int)attp->nelems, cdiAttTypeLookup(attp), context); return txsize; } -int -vlistAttsGetSize(vlist_t *p, int varID, void *context) + +int cdiAttsGetSize(void *vp, int varID, void *context) { + vlist_t *p = (vlist_t*) vp; cdi_atts_t *attsp = get_attsp(p, varID); int txsize = serializeGetSize(1, DATATYPE_INT, context); size_t numAtts = attsp->nelems; for (size_t i = 0; i < numAtts; ++i) - txsize += vlistAttGetSize(p, varID, (int)i, context); + txsize += cdiAttGetSize(p, varID, (int)i, context); return txsize; } -static void -vlistAttPack(vlist_t *vlistptr, int varID, int attnum, - void * buf, int size, int *position, void *context) +static +void cdiAttPack(vlist_t *vlistptr, int varID, int attnum, + void *buf, int size, int *position, void *context) { cdi_atts_t *attsp; cdi_att_t *attp; - int tempbuf[vlist_att_nints]; + int tempbuf[cdi_att_nints]; xassert(attsp = get_attsp(vlistptr, varID)); xassert(attnum >= 0 && attnum < (int)attsp->nelems); @@ -543,33 +527,32 @@ vlistAttPack(vlist_t *vlistptr, int varID, int attnum, tempbuf[1] = attp->exdtype; tempbuf[2] = attp->indtype; tempbuf[3] = (int)attp->nelems; - serializePack(tempbuf, vlist_att_nints, DATATYPE_INT, buf, size, position, context); + serializePack(tempbuf, cdi_att_nints, DATATYPE_INT, buf, size, position, context); serializePack(attp->name, (int)attp->namesz, DATATYPE_TXT, buf, size, position, context); - serializePack(attp->xvalue, (int)attp->nelems, vlistAttTypeLookup(attp), + serializePack(attp->xvalue, (int)attp->nelems, cdiAttTypeLookup(attp), buf, size, position, context); } -void -vlistAttsPack(vlist_t *p, int varID, - void * buf, int size, int *position, void *context) + +void cdiAttsPack(void *vp, int varID, void *buf, int size, int *position, void *context) { + vlist_t *p = (vlist_t*) vp; cdi_atts_t *attsp = get_attsp(p, varID); size_t numAtts = attsp->nelems; int numAttsI = (int)numAtts; xassert(numAtts <= INT_MAX); serializePack(&numAttsI, 1, DATATYPE_INT, buf, size, position, context); for (size_t i = 0; i < numAtts; ++i) - vlistAttPack(p, varID, (int)i, buf, size, position, context); + cdiAttPack(p, varID, (int)i, buf, size, position, context); } -static void -vlistAttUnpack(int vlistID, int varID, - void * buf, int size, int *position, void *context) +static +void cdiAttUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context) { - int tempbuf[vlist_att_nints]; + int tempbuf[cdi_att_nints]; serializeUnpack(buf, size, position, - tempbuf, vlist_att_nints, DATATYPE_INT, context); + tempbuf, cdi_att_nints, DATATYPE_INT, context); char *attName = (char *) Malloc((size_t)tempbuf[0] + 1); serializeUnpack(buf, size, position, attName, tempbuf[0], DATATYPE_TXT, context); attName[tempbuf[0]] = '\0'; @@ -595,22 +578,19 @@ vlistAttUnpack(int vlistID, int varID, } void *attData = (void *) Malloc(elemSize * (size_t)tempbuf[3]); serializeUnpack(buf, size, position, attData, tempbuf[3], attVDt, context); - vlist_def_att(tempbuf[2], tempbuf[1], vlistID, varID, attName, - (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData); + cdi_def_att(tempbuf[2], tempbuf[1], cdiID, varID, attName, + (size_t)tempbuf[3], (size_t)tempbuf[3] * elemSize, attData); Free(attName); Free(attData); } -void -vlistAttsUnpack(int vlistID, int varID, - void * buf, int size, int *position, void *context) + +void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context) { - int numAtts, i; + int numAtts; serializeUnpack(buf, size, position, &numAtts, 1, DATATYPE_INT, context); - for (i = 0; i < numAtts; ++i) - { - vlistAttUnpack(vlistID, varID, buf, size, position, context); - } + for ( int i = 0; i < numAtts; ++i ) + cdiAttUnpack(cdiID, varID, buf, size, position, context); } /* diff --git a/src/cdi_att.h b/src/cdi_att.h new file mode 100644 index 0000000000000000000000000000000000000000..8c8799bbf516f310887b5d52e8cb6b86bffa2f79 --- /dev/null +++ b/src/cdi_att.h @@ -0,0 +1,53 @@ +#ifndef CDI_ATT_H +#define CDI_ATT_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef _CDI_LIMITS_H +#include "cdi_limits.h" +#endif + +/* + * CDI attribute + */ +typedef struct { + size_t xsz; /* amount of space at xvalue */ + size_t namesz; /* size of name */ + char *name; /* attribute name */ + int indtype; /* internal data type of xvalue (INT, FLT or TXT) */ + int exdtype; /* external data type */ + /* indtype exdtype */ + /* TXT TXT */ + /* INT INT16, INT32 */ + /* FLT FLT32, FLT64 */ + size_t nelems; /* number of elements */ + void *xvalue; /* the actual data */ +} cdi_att_t; + + +typedef struct { + size_t nalloc; /* number allocated >= nelems */ + size_t nelems; /* length of the array */ + cdi_att_t value[MAX_ATTRIBUTES]; +} cdi_atts_t; + + +int cdiAttsGetSize(void *p, int varID, void *context); + +void cdiAttsPack(void *p, int varID, void *buf, int size, int *position, void *context); + +void cdiAttsUnpack(int cdiID, int varID, void *buf, int size, int *position, void *context); + +#endif + +/* + * Local Variables: + * c-file-style: "Java" + * c-basic-offset: 2 + * indent-tabs-mode: nil + * show-trailing-whitespace: t + * require-trailing-newline: t + * End: + */ diff --git a/src/cdi_int.c b/src/cdi_int.c index 50507091f62e5270a9b49320d03c9dff5c174929..03873850ffc2cb5deea634a04b682f948d0eee7d 100644 --- a/src/cdi_int.c +++ b/src/cdi_int.c @@ -28,7 +28,7 @@ int cdiDefaultModelID = CDI_UNDEFID; int cdiDefaultTableID = CDI_UNDEFID; //int cdiNcMissingValue = CDI_UNDEFID; int cdiNcChunksizehint = CDI_UNDEFID; -int cdiChunkType = CHUNK_GRID; +int cdiChunkType = CDI_CHUNK_GRID; int cdiSplitLtype105 = CDI_UNDEFID; int cdiIgnoreAttCoordinates = FALSE; @@ -237,9 +237,9 @@ void cdiSetChunk(const char *chunkAlgo) //size_t len = strlen(chunkAlgo); int algo = -1; - if ( strcmp("auto", chunkAlgo) == 0 ) algo = CHUNK_AUTO; - else if ( strcmp("grid", chunkAlgo) == 0 ) algo = CHUNK_GRID; - else if ( strcmp("lines", chunkAlgo) == 0 ) algo = CHUNK_LINES; + if ( strcmp("auto", chunkAlgo) == 0 ) algo = CDI_CHUNK_AUTO; + else if ( strcmp("grid", chunkAlgo) == 0 ) algo = CDI_CHUNK_GRID; + else if ( strcmp("lines", chunkAlgo) == 0 ) algo = CDI_CHUNK_LINES; /* else if ( (pch = strstr(chunkAlgo,"x")) != 0 ) { diff --git a/src/cdi_int.h b/src/cdi_int.h index f558ac682bb3ea655b54324006aa211a74644643..67670e5449a1a96f4067a0700838e6c53f2e953c 100644 --- a/src/cdi_int.h +++ b/src/cdi_int.h @@ -208,6 +208,17 @@ typedef struct { } VCT; +#ifdef HAVE_LIBNETCDF +typedef struct { + int gridID; + int xdimID; + int ydimID; + int xvarID; + int yvarID; + int avarID; +} +ncgrid_t; +#endif typedef struct { int self; @@ -233,17 +244,17 @@ typedef struct { basetime_t basetime; int ncmode; int vlistID; - int xdimID[MAX_GRIDS_PS]; //Warning: synchronous array to vlist_to_pointer(vlistID)->gridIDs - int ydimID[MAX_GRIDS_PS]; //Warning: synchronous array to vlist_to_pointer(vlistID)->gridIDs +#ifdef HAVE_LIBNETCDF + ncgrid_t *ncgrid; + int xdimID[MAX_GRIDS_PS]; + int ydimID[MAX_GRIDS_PS]; int zaxisID[MAX_ZAXES_PS]; //Warning: synchronous array to vlist_to_pointer(vlistID)->zaxisIDs int nczvarID[MAX_ZAXES_PS]; - int ncxvarID[MAX_GRIDS_PS]; - int ncyvarID[MAX_GRIDS_PS]; - int ncavarID[MAX_GRIDS_PS]; + VCT vct; +#endif int historyID; int globalatts; int localatts; - VCT vct; int unreduced; int sortname; int have_missval; @@ -366,6 +377,8 @@ void vlist_check_contents(int vlistID); void cdi_create_records(stream_t *streamptr, int tsID); +void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name); + int recordNewEntry(stream_t *streamptr, int tsID); void cdiCreateTimesteps(stream_t *streamptr); diff --git a/src/cgribexlib.c b/src/cgribexlib.c index 87395924d59455a56900f71b70cb0deb4a8f075a..3e9c76036cb25d5bb8fdbe4038799ee2a8a05733 100644 --- a/src/cgribexlib.c +++ b/src/cgribexlib.c @@ -139,8 +139,8 @@ int correct_bdslen(int bdslen, long recsize, long gribpos); /* param format: DDDCCCNNN */ -void cdiDecodeParam(int param, int *dis, int *cat, int *num); -int cdiEncodeParam(int dis, int cat, int num); +void cdiDecodeParam(int param, int *pnum, int *pcat, int *pdis); +int cdiEncodeParam(int pnum, int pcat, int pdis); /* date format: YYYYMMDD */ /* time format: hhmmss */ diff --git a/src/config.h.in b/src/config.h.in index 8f6932de4a47db0698cb1c59cf9fa5520b51ad15..8c9bcb778df2aa883ffd9efb1d2b7d810cb3e66f 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -85,9 +85,6 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the <jasper.h> header file. */ -#undef HAVE_JASPER_H - /* Define to 1 for GRIB1 decoding/encoding with cgribex */ #undef HAVE_LIBCGRIBEX @@ -103,12 +100,6 @@ /* Define to 1 for IEG interface */ #undef HAVE_LIBIEG -/* Define to 1 for JPEG compression for GRIB2 */ -#undef HAVE_LIBJASPER - -/* Define to 1 for PNG compression for GRIB2 */ -#undef HAVE_LIBLIBPNG - /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM @@ -121,9 +112,6 @@ /* Define to 1 for NetCDF support */ #undef HAVE_LIBNETCDF -/* Define to 1 for JPEG compression for GRIB2 */ -#undef HAVE_LIBOPENJPEG - /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD @@ -163,15 +151,9 @@ /* Define to 1 if you have the <netcdf_par.h> header file. */ #undef HAVE_NETCDF_PAR_H -/* Define to 1 if you have the <openjpeg.h> header file. */ -#undef HAVE_OPENJPEG_H - /* netCDF library does support MPI parallel invocations */ #undef HAVE_PARALLEL_NC4 -/* Define to 1 if you have the <png.h> header file. */ -#undef HAVE_PNG_H - /* ScalES PPM C core library is available */ #undef HAVE_PPM_CORE diff --git a/src/file.c b/src/file.c index 529732e12048c04dfadaf1f013fe68e9f02e4d92..4ea2e816134b0bb99d0cda2f3a5b701572ac734a 100644 --- a/src/file.c +++ b/src/file.c @@ -6,7 +6,7 @@ #include <ctype.h> #include <errno.h> #include <fcntl.h> -#include <limits.h> +#include <stdint.h> #include <stdarg.h> #include <stdio.h> #include <string.h> @@ -915,7 +915,7 @@ int file_fill_buffer(bfile_t *fileptr) } else { - xassert(fileptr->bufferSize <= SSIZE_MAX); + xassert(fileptr->bufferSize <= SIZE_MAX); nread = (ssize_t)fileptr->bufferSize; if ( (nread + fileptr->bufferPos) > fileptr->size ) nread = fileptr->size - fileptr->bufferPos; diff --git a/src/gaussgrid.c b/src/gaussgrid.c index 2ae1b9fe690755c16796b5fc3dc4b1fa9ddfbd4a..a26e1d7a44b4ec7b8fcaaf38c7944b31a0efa46d 100644 --- a/src/gaussgrid.c +++ b/src/gaussgrid.c @@ -10,44 +10,26 @@ #include "dmemory.h" #include "gaussgrid.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 /* pi */ -#endif - -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880 -#endif +#include "cdi_int.h" static -void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag, +void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag, double *pw, double *pdxn, double *pxmod) { - double zdlk; - double zdlldn; - double zdlx; - double zdlmod; - double zdlxn; - - size_t ik; - /* 1.0 Newton iteration step */ - zdlx = pdx; - zdlk = 0.0; - if (kodd == 0) - { - zdlk = 0.5*pfn[0]; - } - zdlxn = 0.0; - zdlldn = 0.0; + double zdlx = pdx; + double zdlk = 0.0; + if ( kodd == 0 ) zdlk = 0.5*pfn[0]; + double zdlxn = 0.0; + double zdlldn = 0.0; - ik = 1; + size_t ik = 1; - if (kflag == 0) + if ( kflag == 0 ) { - for(size_t jn = 2-kodd; jn <= kn; jn += 2) + for ( size_t jn = 2-kodd; jn <= kn; jn += 2 ) { /* normalised ordinary Legendre polynomial == \overbar{p_n}^0 */ zdlk = zdlk + pfn[ik]*cos((double)(jn)*zdlx); @@ -56,7 +38,7 @@ void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag, ik++; } /* Newton method */ - zdlmod = -(zdlk/zdlldn); + double zdlmod = -(zdlk/zdlldn); zdlxn = zdlx + zdlmod; *pdxn = zdlxn; *pxmod = zdlmod; @@ -64,9 +46,9 @@ void cpledn(size_t kn, size_t kodd, double *pfn, double pdx, int kflag, /* 2.0 Compute weights */ - if (kflag == 1) + if ( kflag == 1 ) { - for(size_t jn = 2-kodd; jn <= kn; jn += 2) + for ( size_t jn = 2-kodd; jn <= kn; jn += 2 ) { /* normalised derivative */ zdlldn = zdlldn - pfn[ik]*(double)(jn)*sin((double)(jn)*zdlx); @@ -82,24 +64,21 @@ static void gawl(double *pfn, double *pl, double *pw, size_t kn) { double pmod = 0; - int iflag; - int itemax; double zw = 0; - double zdlx; double zdlxn = 0; /* 1.0 Initizialization */ - iflag = 0; - itemax = 20; + int iflag = 0; + int itemax = 20; size_t iodd = (kn % 2); - zdlx = *pl; + double zdlx = *pl; /* 2.0 Newton iteration */ - for (int jter = 1; jter <= itemax+1; jter++) + for ( int jter = 1; jter <= itemax+1; jter++ ) { cpledn(kn, iodd, pfn, zdlx, iflag, &zw, &zdlxn, &pmod); zdlx = zdlxn; @@ -114,7 +93,7 @@ void gawl(double *pfn, double *pl, double *pw, size_t kn) } static -void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw) +void gauaw(size_t kn, double *restrict pl, double *restrict pw) { /* * 1.0 Initialize Fourier coefficients for ordinary Legendre polynomials @@ -122,26 +101,22 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw) * Belousov, Swarztrauber, and ECHAM use zfn(0,0) = sqrt(2) * IFS normalisation chosen to be 0.5*Integral(Pnm**2) = 1 (zfn(0,0) = 2.0) */ - double *zfn, *zfnlat; - - double z, zfnn; - - zfn = (double *) Malloc((kn+1) * (kn+1) * sizeof(double)); - zfnlat = (double *) Malloc((kn/2+1+1)*sizeof(double)); + double *zfn = (double *) Malloc((kn+1) * (kn+1) * sizeof(double)); + double *zfnlat = (double *) Malloc((kn/2+1+1)*sizeof(double)); zfn[0] = M_SQRT2; - for (size_t jn = 1; jn <= kn; jn++) + for ( size_t jn = 1; jn <= kn; jn++ ) { - zfnn = zfn[0]; + double zfnn = zfn[0]; for (size_t jgl = 1; jgl <= jn; jgl++) { - zfnn *= sqrt(1.0-0.25/((double)(jgl*jgl))); + zfnn *= sqrt(1.0-0.25/((double)(jgl*jgl))); } zfn[jn*(kn+1)+jn] = zfnn; size_t iodd = jn % 2; - for (size_t jgl = 2; jgl <= jn-iodd; jgl += 2) + for ( size_t jgl = 2; jgl <= jn-iodd; jgl += 2 ) { zfn[jn*(kn+1)+jn-jgl] = zfn[jn*(kn+1)+jn-jgl+2] *((double)((jgl-1)*(2*jn-jgl+2)))/((double)(jgl*(2*jn-jgl+1))); @@ -153,11 +128,11 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw) size_t iodd = kn % 2; size_t ik = iodd; - for (size_t jgl = iodd; jgl <= kn; jgl += 2) + for ( size_t jgl = iodd; jgl <= kn; jgl += 2 ) { zfnlat[ik] = zfn[kn*(kn+1)+jgl]; ik++; - } + } /* * 2.1 Find first approximation of the roots of the @@ -165,16 +140,17 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw) */ size_t ins2 = kn/2+(kn % 2); + double z; - for (size_t jgl = 1; jgl <= ins2; jgl++) + for ( size_t jgl = 1; jgl <= ins2; jgl++ ) { - z = ((double)(4*jgl-1))*M_PI/((double)(4*kn+2)); + z = ((double)(4*jgl-1))*M_PI/((double)(4*kn+2)); pl[jgl-1] = z+1.0/(tan(z)*((double)(8*kn*kn))); } /* 2.2 Computes roots and weights for transformed theta */ - for (size_t jgl = ins2; jgl >= 1 ; jgl--) + for ( size_t jgl = ins2; jgl >= 1 ; jgl-- ) { size_t jglm1 = jgl-1; gawl(zfnlat, &(pl[jglm1]), &(pw[jglm1]), kn); @@ -182,12 +158,12 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw) /* convert to physical latitude */ - for (size_t jgl = 0; jgl < ins2; jgl++) + for ( size_t jgl = 0; jgl < ins2; jgl++ ) { pl[jgl] = cos(pl[jgl]); } - for (size_t jgl = 1; jgl <= kn/2; jgl++) + for ( size_t jgl = 1; jgl <= kn/2; jgl++ ) { size_t jglm1 = jgl-1; size_t isym = kn-jgl; @@ -201,103 +177,48 @@ void gauaw(size_t kn, double *__restrict__ pl, double *__restrict__ pw) return; } -#if 0 -static -void gauaw_old(double *pa, double *pw, int nlat) -{ - /* - * Compute Gaussian latitudes. On return pa contains the - * sine of the latitudes starting closest to the north pole and going - * toward the south - * - */ - - const int itemax = 20; - - int isym, iter, ins2, jn, j; - double za, zw, zan; - double z, zk, zkm1, zkm2, zx, zxn, zldn, zmod; - /* - * Perform the Newton loop - * Find 0 of Legendre polynomial with Newton loop - */ - - ins2 = nlat/2 + nlat%2; - - for ( j = 0; j < ins2; j++ ) - { - z = (double) (4*(j+1)-1)*M_PI / (double) (4*nlat+2); - pa[j] = cos(z + 1.0/(tan(z)*(double)(8*nlat*nlat))); - } - - for ( j = 0; j < ins2; j++ ) - { - - za = pa[j]; +void gaussaw(double *restrict pa, double *restrict pw, size_t nlat) +{ + //gauaw_old(pa, pw, nlat); + gauaw(nlat, pa, pw); +} - iter = 0; - do - { - iter++; - zk = 0.0; - - /* Newton iteration step */ - - zkm2 = 1.0; - zkm1 = za; - zx = za; - for ( jn = 2; jn <= nlat; jn++ ) - { - zk = ((double) (2*jn-1)*zx*zkm1-(double)(jn-1)*zkm2) / (double)(jn); - zkm2 = zkm1; - zkm1 = zk; - } - zkm1 = zkm2; - zldn = ((double) (nlat)*(zkm1-zx*zk)) / (1.-zx*zx); - zmod = -zk/zldn; - zxn = zx+zmod; - zan = zxn; - - /* computes weight */ - - zkm2 = 1.0; - zkm1 = zxn; - zx = zxn; - for ( jn = 2; jn <= nlat; jn++ ) - { - zk = ((double) (2*jn-1)*zx*zkm1-(double)(jn-1)*zkm2) / (double) (jn); - zkm2 = zkm1; - zkm1 = zk; - } - zkm1 = zkm2; - zw = (1.0-zx*zx) / ((double) (nlat*nlat)*zkm1*zkm1); - za = zan; - } - while ( iter <= itemax && fabs(zmod) >= DBL_EPSILON ); - pa[j] = zan; - pw[j] = 2.0*zw; - } +bool isGaussGrid(size_t ysize, double yinc, const double *yvals) +{ + bool lgauss = false; -#if defined (SX) -#pragma vdir nodep -#endif - for (j = 0; j < nlat/2; j++) + if ( IS_EQUAL(yinc, 0) && ysize > 2 ) /* check if gaussian */ { - isym = nlat-(j+1); - pa[isym] = -pa[j]; - pw[isym] = pw[j]; + size_t i; + double *yv = (double *) Malloc(ysize*sizeof(double)); + double *yw = (double *) Malloc(ysize*sizeof(double)); + gaussaw(yv, yw, ysize); + Free(yw); + for ( i = 0; i < ysize; i++ ) + yv[i] = asin(yv[i])/M_PI*180.0; + + for ( i = 0; i < ysize; i++ ) + if ( fabs(yv[i] - yvals[i]) > + ((yv[0] - yv[1])/500) ) break; + + if ( i == ysize ) lgauss = true; + + /* check S->N */ + if ( lgauss == false ) + { + for ( i = 0; i < ysize; i++ ) + if ( fabs(yv[i] - yvals[ysize-i-1]) > + ((yv[0] - yv[1])/500) ) break; + + if ( i == ysize ) lgauss = true; + } + + Free(yv); } - return; -} -#endif - -void gaussaw(double *restrict pa, double *restrict pw, size_t nlat) -{ - //gauaw_old(pa, pw, nlat); - gauaw(nlat, pa, pw); + return lgauss; } /* @@ -312,7 +233,6 @@ int main (int rgc, char *argv[]) int i; gauaw(ngl, pl, pw); - gauaw_old(plo, pwo, ngl); for (i = 0; i < ngl; i++) { pl[i] = asin(pl[i])/M_PI*180.0; diff --git a/src/gaussgrid.h b/src/gaussgrid.h index e33df5ed6ea26ed2b46870499fa27ebe74e36ba7..3973a6375fe83f9873bbe6f3cda4c773db77fe81 100644 --- a/src/gaussgrid.h +++ b/src/gaussgrid.h @@ -1,11 +1,14 @@ #ifndef _GAUSSGRID_H #define _GAUSSGRID_H +#include <stdbool.h> + #ifdef __cplusplus extern "C" { #endif void gaussaw(double *restrict pa, double *restrict pw, size_t nlat); +bool isGaussGrid(size_t ysize, double yinc, const double *yvals); #if defined (__cplusplus) } diff --git a/src/getline.c b/src/getline.c index 8001390453e06859e979cff71db78ca2079928e8..a77178678d0260c141a8443059516966e1da646d 100644 --- a/src/getline.c +++ b/src/getline.c @@ -30,9 +30,10 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <limits.h> +#include <stdint.h> #include <unistd.h> #include <string.h> +#include <limits.h> /* read until end of line or end of file */ ssize_t @@ -82,7 +83,7 @@ getline(char **linebuf, size_t *linebuf_size, FILE *fp) && (len += strlen(buf + len)) > old_len && buf[len-1] != '\n'); } - status = len > SSIZE_MAX ? SSIZE_MAX : (ssize_t)len; + status = len > SIZE_MAX ? SIZE_MAX : (ssize_t)len; } if (linebuf_size) *linebuf_size = buf_size; diff --git a/src/grb_write.c b/src/grb_write.c index f47eb68a1f5e840e45649be56eb543171c468b46..9dc61db2a2b30129a6fa6e441d618c880d98cfe6 100644 --- a/src/grb_write.c +++ b/src/grb_write.c @@ -121,7 +121,7 @@ void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1) long unzipsize; int izip = gribGetZip((long)recsize, gribbuffer, &unzipsize); - if ( izip == 0 && streamptr2->comptype == COMPRESS_SZIP ) + if ( izip == 0 && streamptr2->comptype == CDI_COMPRESS_SZIP ) nbytes = grbSzip(filetype, gribbuffer, nbytes); } @@ -178,9 +178,9 @@ void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtyp #endif } - if ( comptype != COMPRESS_JPEG && comptype != COMPRESS_SZIP ) comptype = COMPRESS_NONE; + if ( comptype != CDI_COMPRESS_JPEG && comptype != CDI_COMPRESS_SZIP ) comptype = CDI_COMPRESS_NONE; - if ( filetype == FILETYPE_GRB && comptype == COMPRESS_JPEG ) + if ( filetype == FILETYPE_GRB && comptype == CDI_COMPRESS_JPEG ) { static int ljpeg_warn = 1; if ( ljpeg_warn ) Warning("JPEG compression of GRIB1 records not available!"); @@ -190,7 +190,7 @@ void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtyp size_t nbytes = grbEncode(filetype, memtype, varID, levelID, vlistID, gridID, zaxisID, date, time, tsteptype, numavg, datasize, data, nmiss, &gribbuffer, comptype, gc); - if ( filetype == FILETYPE_GRB && streamptr->comptype == COMPRESS_SZIP ) + if ( filetype == FILETYPE_GRB && streamptr->comptype == CDI_COMPRESS_SZIP ) nbytes = grbSzip(filetype, gribbuffer, nbytes); size_t (*myFileWrite)(int fileID, const void *restrict buffer, diff --git a/src/gribapi.c b/src/gribapi.c index 675816ecf4c926eaec39264588844eb0f1b1c258..a032dda698e6f69d87c1e853f3f2a62bc0e4dbda 100644 --- a/src/gribapi.c +++ b/src/gribapi.c @@ -53,12 +53,10 @@ const char *gribapiLibraryVersionString(void) void gribContainersNew(stream_t * streamptr) { - int editionNumber = 2; + int editionNumber = (streamptr->filetype == FILETYPE_GRB) ? 1 : 2; - if ( streamptr->filetype == FILETYPE_GRB ) editionNumber = 1; - (void)editionNumber; #if defined (HAVE_LIBCGRIBEX) - if ( streamptr->filetype == FILETYPE_GRB ) + if ( editionNumber == 1 ) { } else diff --git a/src/gribapi_utilities.c b/src/gribapi_utilities.c index 9bdcaf66075a12275c0c2877bf5816527797abe1..6c53fde888975cd584f0cc3bae56b4b7594e4af7 100644 --- a/src/gribapi_utilities.c +++ b/src/gribapi_utilities.c @@ -276,7 +276,7 @@ static int getAvailabilityOfRelativeTimes(grib_handle* gh, bool* outHaveForecast return 0; //case 55 and case 40455 are the same: 55 is the proposed standard value, 40455 is the value in the local use range that is used by the dwd until the standard is updated. - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 55: case 60: case 1000: case 1002: case 1100: case 40033: case 40455: + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 15: case 32: case 33: case 40: case 41: case 44: case 45: case 48: case 51: case 53: case 54: case 55: case 56: case 60: case 1000: case 1002: case 1100: case 40033: case 40455: case 40456: *outHaveForecastTime = true, *outHaveTimeRange = false; return 0; @@ -429,7 +429,11 @@ int gribapiGetGridType(grib_handle *gh) gridtype = ( gribGetLong(gh, "Ni") == (long) GRIB_MISSING_LONG ) ? GRID_GAUSSIAN_REDUCED : GRID_GAUSSIAN; break; +#ifdef TEST_PROJECTION + case GRIB2_GTYPE_LATLON_ROT: gridtype = GRID_PROJECTION; break; +#else case GRIB2_GTYPE_LATLON_ROT: gridtype = GRID_LONLAT; break; +#endif case GRIB2_GTYPE_LCC: gridtype = GRID_LCC; break; case GRIB2_GTYPE_SPECTRAL: gridtype = GRID_SPECTRAL; break; case GRIB2_GTYPE_GME: gridtype = GRID_GME; break; @@ -450,6 +454,7 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid) { long editionNumber = gribEditionNumber(gh); int gridtype = gribapiGetGridType(gh); + int projtype = (gridtype == GRID_PROJECTION && gribapiGetIsRotated(gh)) ? CDI_PROJ_RLL : CDI_UNDEFID; /* if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED ) { @@ -466,306 +471,267 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid) long numberOfPoints; FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfPoints", &numberOfPoints); - switch (gridtype) + long lpar; + + if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL ) { - case GRID_LONLAT: - case GRID_GAUSSIAN: - { - long nlon, nlat; - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &nlon); - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &nlat); + long nlon, nlat; + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ni", &nlon); + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &nlat); - if ( gridtype == GRID_GAUSSIAN ) - { - long lpar; - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar); - grid->np = (int)lpar; - } + if ( gridtype == GRID_GAUSSIAN ) + { + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar); + grid->np = (int)lpar; + } - if ( numberOfPoints != nlon*nlat ) - Error("numberOfPoints (%ld) and gridSize (%ld) differ!", numberOfPoints, nlon*nlat); - - /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */ - grid->size = (int)numberOfPoints; - grid->xsize = (int)nlon; - grid->ysize = (int)nlat; - grid->xinc = 0; - grid->yinc = 0; - grid->xdef = 0; - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->xfirst); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees", &grid->xlast); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->yfirst); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees", &grid->ylast); - if ( nlon > 1 ) - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc); - if ( gridtype == GRID_LONLAT && nlat > 1 ) - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "jDirectionIncrementInDegrees", &grid->yinc); - - if ( grid->xinc < -999 || grid->xinc > 999 ) grid->xinc = 0; - if ( grid->yinc < -999 || grid->yinc > 999 ) grid->yinc = 0; - - if ( grid->yinc > 0 && grid->yfirst > grid->ylast ) grid->yinc = -grid->yinc; - - /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */ + if ( numberOfPoints != nlon*nlat ) + Error("numberOfPoints (%ld) and gridSize (%ld) differ!", numberOfPoints, nlon*nlat); + + grid->size = (int)numberOfPoints; + grid->x.size = (int)nlon; + grid->y.size = (int)nlat; + grid->x.inc = 0; + grid->y.inc = 0; + grid->x.flag = 0; + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->x.first); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees", &grid->x.last); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->y.first); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees", &grid->y.last); + if ( nlon > 1 ) + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->x.inc); + if ( gridtype == GRID_LONLAT && nlat > 1 ) + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "jDirectionIncrementInDegrees", &grid->y.inc); + + if ( grid->x.inc < -999 || grid->x.inc > 999 ) grid->x.inc = 0; + if ( grid->y.inc < -999 || grid->y.inc > 999 ) grid->y.inc = 0; + + if ( grid->y.inc > 0 && grid->y.first > grid->y.last ) grid->y.inc = -grid->y.inc; + + /* if ( IS_NOT_EQUAL(grid->x.first, 0) || IS_NOT_EQUAL(grid->x.last, 0) ) */ + { + if ( grid->x.size > 1 ) { - if ( grid->xsize > 1 ) - { - if ( (grid->xfirst >= grid->xlast) && (grid->xfirst >= 180) ) grid->xfirst -= 360; + if ( (grid->x.first >= grid->x.last) && (grid->x.first >= 180) ) grid->x.first -= 360; - if ( editionNumber <= 1 ) + if ( editionNumber <= 1 ) + { + /* correct xinc if necessary */ + if ( IS_EQUAL(grid->x.first, 0) && grid->x.last > 354 ) { - /* correct xinc if necessary */ - if ( IS_EQUAL(grid->xfirst, 0) && grid->xlast > 354 ) + double xinc = 360. / grid->x.size; + if ( fabs(grid->x.inc-xinc) > 0.0 ) { - double xinc = 360. / grid->xsize; - - if ( fabs(grid->xinc-xinc) > 0.0 ) - { - grid->xinc = xinc; - if ( CDI_Debug ) Message("set xinc to %g", grid->xinc); - } + grid->x.inc = xinc; + if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc); } } } - grid->xdef = 2; } - grid->ydef = 0; - /* if ( IS_NOT_EQUAL(grid->yfirst, 0) || IS_NOT_EQUAL(grid->ylast, 0) ) */ + grid->x.flag = 2; + } + grid->y.flag = 0; + /* if ( IS_NOT_EQUAL(grid->y.first, 0) || IS_NOT_EQUAL(grid->y.last, 0) ) */ + { + if ( grid->y.size > 1 ) { - if ( grid->ysize > 1 ) + if ( editionNumber <= 1 ) { - if ( editionNumber <= 1 ) - { - } } - grid->ydef = 2; } - break; + grid->y.flag = 2; } - case GRID_GAUSSIAN_REDUCED: + } + else if ( gridtype == GRID_GAUSSIAN_REDUCED ) + { + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar); + grid->np = (int)lpar; + + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &lpar); + int nlat = (int)lpar; + + grid->size = (int)numberOfPoints; + + grid->nrowlon = nlat; + grid->rowlon = (int *) Malloc((size_t)nlat * sizeof (int)); + long *pl = (long *) Malloc((size_t)nlat * sizeof (long)); + size_t dummy = (size_t)nlat; + FAIL_ON_GRIB_ERROR(grib_get_long_array, gh, "pl", pl, &dummy); + for ( int i = 0; i < nlat; ++i ) grid->rowlon[i] = (int)pl[i]; + Free(pl); + + grid->y.size = nlat; + grid->x.inc = 0; + grid->y.inc = 0; + grid->x.flag = 0; + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->x.first); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees", &grid->x.last); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->y.first); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees", &grid->y.last); + + // FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->x.inc); + // if ( IS_EQUAL(grid->x.inc, GRIB_MISSING_DOUBLE) ) grid->x.inc = 0; + + /* if ( IS_NOT_EQUAL(grid->x.first, 0) || IS_NOT_EQUAL(grid->x.last, 0) ) */ { - long lpar; - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "numberOfParallelsBetweenAPoleAndTheEquator", &lpar); - /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */ - grid->np = (int)lpar; - - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nj", &lpar); - /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */ - int nlat = (int)lpar; - - /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */ - grid->size = (int)numberOfPoints; - - grid->nrowlon = nlat; - grid->rowlon = (int *) Malloc((size_t)nlat * sizeof (int)); - long *pl = (long *) Malloc((size_t)nlat * sizeof (long)); - size_t dummy = (size_t)nlat; - FAIL_ON_GRIB_ERROR(grib_get_long_array, gh, "pl", pl, &dummy); - /* FIXME: assert(pl[i] >= INT_MIN && pl[i] <= INT_MIN) */ - for ( int i = 0; i < nlat; ++i ) grid->rowlon[i] = (int)pl[i]; - Free(pl); - - grid->ysize = nlat; - grid->xinc = 0; - grid->yinc = 0; - grid->xdef = 0; - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->xfirst); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfLastGridPointInDegrees", &grid->xlast); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->yfirst); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfLastGridPointInDegrees", &grid->ylast); - - // FAIL_ON_GRIB_ERROR(grib_get_double, gh, "iDirectionIncrementInDegrees", &grid->xinc); - // if ( IS_EQUAL(grid->xinc, GRIB_MISSING_DOUBLE) ) grid->xinc = 0; - - /* if ( IS_NOT_EQUAL(grid->xfirst, 0) || IS_NOT_EQUAL(grid->xlast, 0) ) */ + if ( grid->x.size > 1 ) { - if ( grid->xsize > 1 ) - { - if ( (grid->xfirst > grid->xlast) && (grid->xfirst >= 180) ) grid->xfirst -= 360; + if ( (grid->x.first > grid->x.last) && (grid->x.first >= 180) ) grid->x.first -= 360; - if ( editionNumber <= 1 ) + if ( editionNumber <= 1 ) + { + /* correct xinc if necessary */ + if ( IS_EQUAL(grid->x.first, 0) && grid->x.last > 354 ) { - /* correct xinc if necessary */ - if ( IS_EQUAL(grid->xfirst, 0) && grid->xlast > 354 ) + double xinc = 360. / grid->x.size; + if ( fabs(grid->x.inc-xinc) > 0.0 ) { - double xinc = 360. / grid->xsize; - - if ( fabs(grid->xinc-xinc) > 0.0 ) - { - grid->xinc = xinc; - if ( CDI_Debug ) Message("set xinc to %g", grid->xinc); - } + grid->x.inc = xinc; + if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc); } } } - grid->xdef = 2; } - grid->ydef = 0; - /* if ( IS_NOT_EQUAL(grid->yfirst, 0) || IS_NOT_EQUAL(grid->ylast, 0) ) */ + grid->x.flag = 2; + } + grid->y.flag = 0; + /* if ( IS_NOT_EQUAL(grid->y.first, 0) || IS_NOT_EQUAL(grid->y.last, 0) ) */ + { + if ( grid->y.size > 1 ) { - if ( grid->ysize > 1 ) + if ( editionNumber <= 1 ) { - if ( editionNumber <= 1 ) - { - } } - grid->ydef = 2; } - break; + grid->y.flag = 2; } - case GRID_LCC: - { - int nlon, nlat; - long lpar; - - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nx", &lpar); - nlon = (int)lpar; - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ny", &lpar); - nlat = (int)lpar; - - if ( numberOfPoints != nlon*nlat ) - Error("numberOfPoints (%d) and gridSize (%d) differ!", (int)numberOfPoints, nlon*nlat); - - grid->size = (int)numberOfPoints; - grid->xsize = nlon; - grid->ysize = nlat; - - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DxInMetres", &grid->lcc_xinc); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DyInMetres", &grid->lcc_yinc); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->lcc_originLon); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->lcc_originLat); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "LoVInDegrees", &grid->lcc_lonParY); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin1InDegrees", &grid->lcc_lat1); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin2InDegrees", &grid->lcc_lat2); - - if ( editionNumber <= 1 ) - { - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "projectionCenterFlag", &lpar); - grid->lcc_projflag = (int) lpar; - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "scanningMode", &lpar); - grid->lcc_scanflag = (int) lpar; - } - - grid->xdef = 0; - grid->ydef = 0; + } + else if ( gridtype == GRID_LCC ) + { + int nlon, nlat; + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nx", &lpar); + nlon = (int)lpar; + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ny", &lpar); + nlat = (int)lpar; + + if ( numberOfPoints != nlon*nlat ) + Error("numberOfPoints (%d) and gridSize (%d) differ!", (int)numberOfPoints, nlon*nlat); + + grid->size = (int)numberOfPoints; + grid->x.size = nlon; + grid->y.size = nlat; + + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DxInMetres", &grid->lcc.xinc); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DyInMetres", &grid->lcc.yinc); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->lcc.originLon); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->lcc.originLat); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "LoVInDegrees", &grid->lcc.lonParY); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin1InDegrees", &grid->lcc.lat1); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin2InDegrees", &grid->lcc.lat2); + + if ( editionNumber <= 1 ) + { + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "projectionCenterFlag", &lpar); + grid->lcc.projflag = (int) lpar; + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "scanningMode", &lpar); + grid->lcc.scanflag = (int) lpar; + } - break; - } - case GRID_SPECTRAL: - { - size_t len = 256; - char typeOfPacking[256]; - FAIL_ON_GRIB_ERROR(grib_get_string, gh, "packingType", typeOfPacking, &len); - grid->lcomplex = 0; - if ( strncmp(typeOfPacking, "spectral_complex", len) == 0 ) grid->lcomplex = 1; - - /* FIXME: assert(datasize >= INT_MIN && datasize <= INT_MAX) */ - grid->size = (int)datasize; - long lpar; - FAIL_ON_GRIB_ERROR(grib_get_long, gh, "J", &lpar); - /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */ - grid->trunc = (int)lpar; + grid->x.flag = 0; + grid->y.flag = 0; + } + else if ( gridtype == GRID_SPECTRAL ) + { + size_t len = 256; + char typeOfPacking[256]; + FAIL_ON_GRIB_ERROR(grib_get_string, gh, "packingType", typeOfPacking, &len); + grid->lcomplex = 0; + if ( strncmp(typeOfPacking, "spectral_complex", len) == 0 ) grid->lcomplex = 1; - break; - } - case GRID_GME: - { - /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */ - grid->size = (int)numberOfPoints; - long lpar; - /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */ - if ( grib_get_long(gh, "nd", &lpar) == 0 ) grid->nd = (int)lpar; - /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */ - if ( grib_get_long(gh, "Ni", &lpar) == 0 ) grid->ni = (int)lpar; - /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */ - if ( grib_get_long(gh, "n2", &lpar) == 0 ) grid->ni2 = (int)lpar; - /* FIXME: assert(lpar >= INT_MIN && lpar <= INT_MAX) */ - if ( grib_get_long(gh, "n3", &lpar) == 0 ) grid->ni3 = (int)lpar; + grid->size = (int)datasize; - break; - } - case GRID_UNSTRUCTURED: - { - unsigned char uuid[CDI_UUID_SIZE]; - /* + FAIL_ON_GRIB_ERROR(grib_get_long, gh, "J", &lpar); + grid->trunc = (int)lpar; + } + else if ( gridtype == GRID_GME ) + { + grid->size = (int)numberOfPoints; + if ( grib_get_long(gh, "nd", &lpar) == 0 ) grid->gme.nd = (int)lpar; + if ( grib_get_long(gh, "Ni", &lpar) == 0 ) grid->gme.ni = (int)lpar; + if ( grib_get_long(gh, "n2", &lpar) == 0 ) grid->gme.ni2 = (int)lpar; + if ( grib_get_long(gh, "n3", &lpar) == 0 ) grid->gme.ni3 = (int)lpar; + } + else if ( gridtype == GRID_UNSTRUCTURED ) + { + unsigned char uuid[CDI_UUID_SIZE]; + /* char reference_link[8192]; size_t len = sizeof(reference_link); reference_link[0] = 0; - */ + */ + grid->size = (int)numberOfPoints; - /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */ - grid->size = (int)numberOfPoints; - long lpar; - if ( grib_get_long(gh, "numberOfGridUsed", &lpar) == 0 ) - { - /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */ - grid->number = (int)lpar; - /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */ - if ( grib_get_long(gh, "numberOfGridInReference", &lpar) == 0 ) - grid->position = (int)lpar; - /* + if ( grib_get_long(gh, "numberOfGridUsed", &lpar) == 0 ) + { + grid->number = (int)lpar; + if ( grib_get_long(gh, "numberOfGridInReference", &lpar) == 0 ) + grid->position = (int)lpar; + /* if ( grib_get_string(gh, "gridDescriptionFile", reference_link, &len) == 0 ) - { - if ( strncmp(reference_link, "file://", 7) == 0 ) - grid->reference = strdupx(reference_link); - } - */ - size_t len = (size_t)CDI_UUID_SIZE; - if ( grib_get_bytes(gh, "uuidOfHGrid", uuid, &len) == 0) - { - memcpy(grid->uuid, uuid, CDI_UUID_SIZE); - } - } - break; - } - case GRID_GENERIC: - { - int nlon = 0, nlat = 0; - long lpar; - /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */ - if ( grib_get_long(gh, "Ni", &lpar) == 0 ) nlon = (int)lpar; - /* FIXME: assert(lpar <= INT_MAX && lpar >= INT_MIN) */ - if ( grib_get_long(gh, "Nj", &lpar) == 0 ) nlat = (int)lpar; - - /* FIXME: assert(numberOfPoints <= INT_MAX && numberOfPoints >= INT_MIN) */ - grid->size = (int)numberOfPoints; + { + if ( strncmp(reference_link, "file://", 7) == 0 ) + grid->reference = strdupx(reference_link); + } + */ + size_t len = (size_t)CDI_UUID_SIZE; + if ( grib_get_bytes(gh, "uuidOfHGrid", uuid, &len) == 0) + { + memcpy(grid->uuid, uuid, CDI_UUID_SIZE); + } + } + } + else if ( gridtype == GRID_GENERIC ) + { + int nlon = 0, nlat = 0; + if ( grib_get_long(gh, "Ni", &lpar) == 0 ) nlon = (int)lpar; + if ( grib_get_long(gh, "Nj", &lpar) == 0 ) nlat = (int)lpar; - if ( nlon > 0 && nlat > 0 && nlon*nlat == grid->size ) - { - grid->xsize = nlon; - grid->ysize = nlat; - } - else - { - grid->xsize = 0; - grid->ysize = 0; - } + grid->size = (int)numberOfPoints; - break; - } - default: - { - Error("Unsupported grid type: %s", gridNamePtr(gridtype)); - break; - } + if ( nlon > 0 && nlat > 0 && nlon*nlat == grid->size ) + { + grid->x.size = nlon; + grid->y.size = nlat; + } + else + { + grid->x.size = 0; + grid->y.size = 0; + } + } + else + { + Error("Unsupported grid type: %s", gridNamePtr(gridtype)); } grid->isRotated = FALSE; if ( gribapiGetIsRotated(gh) ) { + double xpole = 0, ypole = 0, angle = 0; grid->isRotated = TRUE; - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfSouthernPoleInDegrees", &grid->ypole); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfSouthernPoleInDegrees", &grid->xpole); - FAIL_ON_GRIB_ERROR(grib_get_double, gh, "angleOfRotation", &grid->angle); - /* change from south to north pole */ - if ( fabs(grid->ypole) > 0 ) grid->ypole = -grid->ypole; - grid->xpole = grid->xpole - 180; - if ( fabs(grid->angle) > 0 ) grid->angle = -grid->angle; + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfSouthernPoleInDegrees", &ypole); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfSouthernPoleInDegrees", &xpole); + FAIL_ON_GRIB_ERROR(grib_get_double, gh, "angleOfRotation", &angle); + xpole = xpole - 180; + if ( fabs(ypole) > 0 ) ypole = -ypole; // change from south to north pole + if ( fabs(angle) > 0 ) angle = -angle; + grid->rll.xpole = xpole; + grid->rll.ypole = ypole; + grid->rll.angle = angle; } - grid->xvals = NULL; - grid->yvals = NULL; grid->type = gridtype; + grid->projtype = projtype; } #endif /* diff --git a/src/grid.c b/src/grid.c index 9a681357874c878322c950790e5baab960920893..99a41cbd97169630cfaba20f49f4db4d87311194 100644 --- a/src/grid.c +++ b/src/grid.c @@ -94,79 +94,90 @@ void grid_init(grid_t *gridptr) gridptr->self = CDI_UNDEFID; gridptr->type = CDI_UNDEFID; gridptr->proj = CDI_UNDEFID; + gridptr->projtype = CDI_UNDEFID; gridptr->mask = NULL; gridptr->mask_gme = NULL; - gridptr->xvals = NULL; - gridptr->yvals = NULL; + gridptr->x.vals = NULL; + gridptr->y.vals = NULL; + gridptr->x.bounds = NULL; + gridptr->y.bounds = NULL; gridptr->area = NULL; - gridptr->xbounds = NULL; - gridptr->ybounds = NULL; gridptr->rowlon = NULL; gridptr->nrowlon = 0; - gridptr->xfirst = 0.0; - gridptr->xlast = 0.0; - gridptr->xinc = 0.0; - gridptr->yfirst = 0.0; - gridptr->ylast = 0.0; - gridptr->yinc = 0.0; - gridptr->lcc_originLon = 0.0; - gridptr->lcc_originLat = 0.0; - gridptr->lcc_lonParY = 0.0; - gridptr->lcc_lat1 = 0.0; - gridptr->lcc_lat2 = 0.0; - gridptr->lcc_xinc = 0.0; - gridptr->lcc_yinc = 0.0; - gridptr->lcc_projflag = 0; - gridptr->lcc_scanflag = 0; - gridptr->lcc_defined = FALSE; - gridptr->lcc2_lon_0 = 0.0; - gridptr->lcc2_lat_0 = 0.0; - gridptr->lcc2_lat_1 = 0.0; - gridptr->lcc2_lat_2 = 0.0; - gridptr->lcc2_a = 0.0; - gridptr->lcc2_defined = FALSE; - gridptr->laea_lon_0 = 0.0; - gridptr->laea_lat_0 = 0.0; - gridptr->laea_a = 0.0; - gridptr->laea_defined = FALSE; + + gridptr->x.first = 0.0; + gridptr->x.last = 0.0; + gridptr->x.inc = 0.0; + gridptr->y.first = 0.0; + gridptr->y.last = 0.0; + gridptr->y.inc = 0.0; + + gridptr->lcc.originLon = 0.0; + gridptr->lcc.originLat = 0.0; + gridptr->lcc.lonParY = 0.0; + gridptr->lcc.lat1 = 0.0; + gridptr->lcc.lat2 = 0.0; + gridptr->lcc.xinc = 0.0; + gridptr->lcc.yinc = 0.0; + gridptr->lcc.projflag = 0; + gridptr->lcc.scanflag = 0; + gridptr->lcc.defined = FALSE; + gridptr->lcc2.lon_0 = 0.0; + gridptr->lcc2.lat_0 = 0.0; + gridptr->lcc2.lat_1 = 0.0; + gridptr->lcc2.lat_2 = 0.0; + gridptr->lcc2.a = 0.0; + gridptr->lcc2.defined = FALSE; + + gridptr->laea.lon_0 = 0.0; + gridptr->laea.lat_0 = 0.0; + gridptr->laea.a = 0.0; + gridptr->laea.defined = FALSE; + + gridptr->gme.nd = 0; + gridptr->gme.ni = 0; + gridptr->gme.ni2 = 0; + gridptr->gme.ni3 = 0; + + gridptr->isRotated = FALSE; + gridptr->rll.xpole = 0.0; + gridptr->rll.ypole = 0.0; + gridptr->rll.angle = 0.0; + gridptr->trunc = 0; gridptr->nvertex = 0; - gridptr->nd = 0; - gridptr->ni = 0; - gridptr->ni2 = 0; - gridptr->ni3 = 0; gridptr->number = 0; gridptr->position = 0; gridptr->reference = NULL; gridptr->prec = 0; gridptr->size = 0; - gridptr->xsize = 0; - gridptr->ysize = 0; + gridptr->x.size = 0; + gridptr->y.size = 0; gridptr->np = 0; - gridptr->xdef = 0; - gridptr->ydef = 0; + gridptr->x.flag = 0; + gridptr->y.flag = 0; gridptr->isCyclic = CDI_UNDEFID; - gridptr->isRotated = FALSE; - gridptr->xpole = 0.0; - gridptr->ypole = 0.0; - gridptr->angle = 0.0; - gridptr->lcomplex = 0; - gridptr->hasdims = TRUE; - gridptr->xdimname[0] = 0; - gridptr->ydimname[0] = 0; + + gridptr->lcomplex = false; + gridptr->hasdims = true; + gridptr->x.dimname[0] = 0; + gridptr->y.dimname[0] = 0; + gridptr->x.name[0] = 0; + gridptr->y.name[0] = 0; + gridptr->x.longname[0] = 0; + gridptr->y.longname[0] = 0; + gridptr->x.units[0] = 0; + gridptr->y.units[0] = 0; + gridptr->x.stdname = NULL; + gridptr->y.stdname = NULL; gridptr->vdimname[0] = 0; - gridptr->xname[0] = 0; - gridptr->yname[0] = 0; - gridptr->xlongname[0] = 0; - gridptr->ylongname[0] = 0; - gridptr->xunits[0] = 0; - gridptr->yunits[0] = 0; - gridptr->xstdname = NULL; - gridptr->ystdname = NULL; + gridptr->mapname[0] = 0; + gridptr->mapping[0] = 0; memset(gridptr->uuid, 0, CDI_UUID_SIZE); gridptr->name = NULL; gridptr->vtable = &cdiGridVtable; - gridptr->extraData = NULL; + gridptr->atts.nalloc = MAX_ATTRIBUTES; + gridptr->atts.nelems = 0; } @@ -174,12 +185,13 @@ static void grid_free_components(grid_t *gridptr) { void *p2free[] = { gridptr->mask, gridptr->mask_gme, - gridptr->xvals, gridptr->yvals, - gridptr->xbounds, gridptr->ybounds, - gridptr->rowlon, gridptr->area, - gridptr->reference, gridptr->name }; - for (size_t i = 0; i < sizeof (p2free) / sizeof (p2free[0]); ++i) - if (p2free[i]) Free(p2free[i]); + gridptr->x.vals, gridptr->y.vals, + gridptr->x.bounds, gridptr->y.bounds, + gridptr->rowlon, gridptr->area, + gridptr->reference, gridptr->name}; + + for (size_t i = 0; i < sizeof(p2free)/sizeof(p2free[0]); ++i) + if ( p2free[i] ) Free(p2free[i]); } void grid_free(grid_t *gridptr) @@ -188,11 +200,12 @@ void grid_free(grid_t *gridptr) grid_init(gridptr); } -static grid_t * -gridNewEntry(cdiResH resH) +static +grid_t *gridNewEntry(cdiResH resH) { grid_t *gridptr = (grid_t*) Malloc(sizeof(grid_t)); grid_init(gridptr); + if (resH == CDI_UNDEFID) gridptr->self = reshPut(gridptr, &gridOps); else @@ -200,6 +213,7 @@ gridNewEntry(cdiResH resH) gridptr->self = resH; reshReplace(resH, gridptr, &gridOps); } + return gridptr; } @@ -256,100 +270,72 @@ void gridGetString(char *name, const char *gridstrname, size_t len) name[len - 1] = 0; } -static inline void -gridSetName(char *gridstrname, const char *name) +static inline +void gridSetName(char *gridstrname, const char *name) { strncpy(gridstrname, name, CDI_MAX_NAME); gridstrname[CDI_MAX_NAME - 1] = 0; } -void -cdiGridTypeInit(grid_t *gridptr, int gridtype, int size) + +void cdiGridTypeInit(grid_t *gridptr, int gridtype, int size) { gridptr->type = gridtype; gridptr->size = size; + if ( gridtype == GRID_CURVILINEAR ) gridptr->nvertex = 4; + else if ( gridtype == GRID_UNSTRUCTURED ) gridptr->x.size = size; + switch (gridtype) { - case GRID_CURVILINEAR: - gridptr->nvertex = 4; - /* Fall through */ case GRID_LONLAT: case GRID_GAUSSIAN: case GRID_GAUSSIAN_REDUCED: case GRID_TRAJECTORY: + case GRID_CURVILINEAR: + case GRID_UNSTRUCTURED: + case GRID_GME: { if ( gridtype == GRID_TRAJECTORY ) { - if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "tlon"); - if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "tlat"); + if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "tlon"); + if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "tlat"); } else { - if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon"); - if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat"); + if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "lon"); + if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "lat"); } - gridSetName(gridptr->xlongname, "longitude"); - gridSetName(gridptr->ylongname, "latitude"); - /* - if ( gridtype == GRID_CURVILINEAR ) - { - gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0]; - gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1]; - gridDefXunits(gridID, "degrees"); - gridDefYunits(gridID, "degrees"); - } - else - */ - { - gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0]; - gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1]; - gridSetName(gridptr->xunits, "degrees_east"); - gridSetName(gridptr->yunits, "degrees_north"); - } + gridSetName(gridptr->x.longname, "longitude"); + gridSetName(gridptr->y.longname, "latitude"); - break; - } - case GRID_UNSTRUCTURED: - gridptr->xsize = size; - /* Fall through */ - case GRID_GME: - { - if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "lon"); - if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "lat"); - gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0]; - gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1]; - gridSetName(gridptr->xunits, "degrees_east"); - gridSetName(gridptr->yunits, "degrees_north"); - break; - } - case GRID_GENERIC: - { + gridptr->x.stdname = xystdname_tab[grid_xystdname_latlon][0]; + gridptr->y.stdname = xystdname_tab[grid_xystdname_latlon][1]; + gridSetName(gridptr->x.units, "degrees_east"); + gridSetName(gridptr->y.units, "degrees_north"); - /* gridptr->xsize = size; */ - if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x"); - if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y"); - /* - strcpy(gridptr->xstdname, "grid_longitude"); - strcpy(gridptr->ystdname, "grid_latitude"); - gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0]; - gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1]; - gridDefXunits(gridID, "degrees"); - gridDefYunits(gridID, "degrees"); - */ break; } + case GRID_GENERIC: + case GRID_PROJECTION: case GRID_LCC2: case GRID_SINUSOIDAL: case GRID_LAEA: { - if ( gridptr->xname[0] == 0 ) gridSetName(gridptr->xname, "x"); - if ( gridptr->yname[0] == 0 ) gridSetName(gridptr->yname, "y"); - gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0]; - gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1]; - gridSetName(gridptr->xunits, "m"); - gridSetName(gridptr->yunits, "m"); + if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "x"); + if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "y"); + if ( gridtype == GRID_PROJECTION ) + { + gridSetName(gridptr->mapname, "Projection"); + } + if ( gridtype != GRID_GENERIC ) + { + gridptr->x.stdname = xystdname_tab[grid_xystdname_projection][0]; + gridptr->y.stdname = xystdname_tab[grid_xystdname_projection][1]; + gridSetName(gridptr->x.units, "m"); + gridSetName(gridptr->y.units, "m"); + } break; } } @@ -551,11 +537,9 @@ int gridCreate(int gridtype, int size) static void gridDestroyKernel( grid_t * gridptr ) { - int id; - xassert ( gridptr ); - id = gridptr->self; + int id = gridptr->self; grid_free_components(gridptr); Free( gridptr ); @@ -579,6 +563,7 @@ void gridDestroy(int gridID) gridptr->vtable->destroy(gridptr); } + void gridDestroyP ( void * gridptr ) { ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr); @@ -601,25 +586,33 @@ void gridName(int gridtype, char *gridname) } static -char *grid_key_to_string(grid_t *gridptr, int key) +void *grid_key_to_ptr(grid_t *gridptr, int key) { - char *gridstring = NULL; + void *keyptr = NULL; switch (key) { - case CDI_GRID_XDIMNAME: gridstring = gridptr->xdimname; break; - case CDI_GRID_YDIMNAME: gridstring = gridptr->ydimname; break; - case CDI_GRID_VDIMNAME: gridstring = gridptr->vdimname; break; + case CDI_KEY_XNAME: keyptr = (void*)gridptr->x.name; break; + case CDI_KEY_XLONGNAME: keyptr = (void*)gridptr->x.longname; break; + case CDI_KEY_XUNITS: keyptr = (void*)gridptr->x.units; break; + case CDI_KEY_YNAME: keyptr = (void*)gridptr->y.name; break; + case CDI_KEY_YLONGNAME: keyptr = (void*)gridptr->y.longname; break; + case CDI_KEY_YUNITS: keyptr = (void*)gridptr->y.units; break; + case CDI_KEY_XDIMNAME: keyptr = (void*)gridptr->x.dimname; break; + case CDI_KEY_YDIMNAME: keyptr = (void*)gridptr->y.dimname; break; + case CDI_KEY_VDIMNAME: keyptr = (void*)gridptr->vdimname; break; + case CDI_KEY_MAPNAME: keyptr = (void*)gridptr->mapname; break; + case CDI_KEY_MAPPING: keyptr = (void*)gridptr->mapping; break; } - return gridstring; + return keyptr; } /* -@Function cdiGridDefString +@Function cdiGridDefKeyStr @Title Define a CDI grid string value from a key -@Prototype int cdiGridDefString(int gridID, int key, int size, const char *mesg) +@Prototype int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg) @Parameter @Item gridID Grid ID, from a previous call to @fref{gridCreate}. @Item key The key to be searched @@ -627,20 +620,20 @@ char *grid_key_to_string(grid_t *gridptr, int key) @Item mesg The address of a string where the data will be read @Description -The function @func{cdiGridDefString} defines a CDI grid string value from a key. +The function @func{cdiGridDefKeyStr} defines a CDI grid string value from a key. @Result -@func{cdiGridDefString} returns 0 if OK and integer value on error. +@func{cdiGridDefKeyStr} returns 0 if OK and integer value on error. @EndFunction */ -int cdiGridDefString(int gridID, int key, int size, const char *mesg) +int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg) { if ( size < 1 || mesg == NULL || *mesg == 0 ) return -1; grid_t *gridptr = gridID2Ptr(gridID); - char *gridstring = grid_key_to_string(gridptr, key); + char *gridstring = (char*)grid_key_to_ptr(gridptr, key); if ( gridstring == NULL ) { Warning("CDI grid string key %d not supported!", key); @@ -654,10 +647,10 @@ int cdiGridDefString(int gridID, int key, int size, const char *mesg) } /* -@Function cdiGridInqString +@Function cdiGridInqKeyStr @Title Get a CDI grid string value from a key -@Prototype int cdiGridInqString(int gridID, int key, int size, char *mesg) +@Prototype int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg) @Parameter @Item gridID Grid ID, from a previous call to @fref{gridCreate}. @Item key The key to be searched. @@ -668,19 +661,19 @@ int cdiGridDefString(int gridID, int key, int size, const char *mesg) is given by the predefined constant @func{CDI_MAX_NAME}. @Description -The function @func{cdiGridInqString} return a CDI grid string value from a key. +The function @func{cdiGridInqKeyStr} return a CDI grid string value from a key. @Result -@func{cdiGridInqString} returns 0 if OK and integer value on error. +@func{cdiGridInqKeyStr} returns 0 if OK and integer value on error. @EndFunction */ -int cdiGridInqString(int gridID, int key, int size, char *mesg) +int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg) { if ( size < 1 || mesg == NULL ) return -1; grid_t *gridptr = gridID2Ptr(gridID); - const char *gridstring = grid_key_to_string(gridptr, key); + const char *gridstring = (const char*)grid_key_to_ptr(gridptr, key); if ( gridstring == NULL) { Warning("CDI grid string key %d not supported!", key); @@ -708,12 +701,7 @@ The function @func{gridDefXname} defines the name of a X-axis. */ void gridDefXname(int gridID, const char *xname) { - if ( xname && *xname ) - { - grid_t *gridptr = gridID2Ptr(gridID); - gridSetName(gridptr->xname, xname); - gridMark4Update(gridID); - } + (void)cdiGridDefKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname); } /* @@ -732,12 +720,7 @@ The function @func{gridDefXlongname} defines the longname of a X-axis. */ void gridDefXlongname(int gridID, const char *xlongname) { - if ( xlongname ) - { - grid_t *gridptr = gridID2Ptr(gridID); - gridSetName(gridptr->xlongname, xlongname); - gridMark4Update(gridID); - } + (void)cdiGridDefKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname); } /* @@ -756,12 +739,7 @@ The function @func{gridDefXunits} defines the units of a X-axis. */ void gridDefXunits(int gridID, const char *xunits) { - if ( xunits ) - { - grid_t *gridptr = gridID2Ptr(gridID); - gridSetName(gridptr->xunits, xunits); - gridMark4Update(gridID); - } + (void)cdiGridDefKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits); } /* @@ -780,12 +758,7 @@ The function @func{gridDefYname} defines the name of a Y-axis. */ void gridDefYname(int gridID, const char *yname) { - if ( yname && *yname ) - { - grid_t *gridptr = gridID2Ptr(gridID); - gridSetName(gridptr->yname, yname); - gridMark4Update(gridID); - } + (void)cdiGridDefKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname); } /* @@ -804,12 +777,7 @@ The function @func{gridDefYlongname} defines the longname of a Y-axis. */ void gridDefYlongname(int gridID, const char *ylongname) { - if ( ylongname ) - { - grid_t *gridptr = gridID2Ptr(gridID); - gridSetName(gridptr->ylongname, ylongname); - gridMark4Update(gridID); - } + (void)cdiGridDefKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname); } /* @@ -828,12 +796,7 @@ The function @func{gridDefYunits} defines the units of a Y-axis. */ void gridDefYunits(int gridID, const char *yunits) { - if ( yunits ) - { - grid_t *gridptr = gridID2Ptr(gridID); - gridSetName(gridptr->yunits, yunits); - gridMark4Update(gridID); - } + (void)cdiGridDefKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits); } /* @@ -857,15 +820,7 @@ The function @func{gridInqXname} returns the name of a X-axis. */ void gridInqXname(int gridID, char *xname) { - grid_t *gridptr = gridID2Ptr(gridID); - - strcpy(xname, gridptr->xname); -} - -const char *gridInqXnamePtr(int gridID) -{ - grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->xname; + (void)cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname); } /* @@ -889,9 +844,7 @@ The function @func{gridInqXlongname} returns the longname of a X-axis. */ void gridInqXlongname(int gridID, char *xlongname) { - grid_t *gridptr = gridID2Ptr(gridID); - - strcpy(xlongname, gridptr->xlongname); + (void)cdiGridInqKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname); } /* @@ -915,17 +868,15 @@ The function @func{gridInqXunits} returns the units of a X-axis. */ void gridInqXunits(int gridID, char *xunits) { - grid_t *gridptr = gridID2Ptr(gridID); - - strcpy(xunits, gridptr->xunits); + (void)cdiGridInqKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits); } void gridInqXstdname(int gridID, char *xstdname) { grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->xstdname ) - strcpy(xstdname, gridptr->xstdname); + if ( gridptr->x.stdname ) + strcpy(xstdname, gridptr->x.stdname); else xstdname[0] = 0; } @@ -951,15 +902,7 @@ The function @func{gridInqYname} returns the name of a Y-axis. */ void gridInqYname(int gridID, char *yname) { - grid_t *gridptr = gridID2Ptr(gridID); - - strcpy(yname, gridptr->yname); -} - -const char *gridInqYnamePtr(int gridID) -{ - grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->yname; + (void)cdiGridInqKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname); } /* @@ -983,9 +926,7 @@ The function @func{gridInqYlongname} returns the longname of a Y-axis. */ void gridInqYlongname(int gridID, char *ylongname) { - grid_t *gridptr = gridID2Ptr(gridID); - - strcpy(ylongname, gridptr->ylongname); + (void)cdiGridInqKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname); } /* @@ -1009,20 +950,81 @@ The function @func{gridInqYunits} returns the units of a Y-axis. */ void gridInqYunits(int gridID, char *yunits) { - grid_t *gridptr = gridID2Ptr(gridID); - - strcpy(yunits, gridptr->yunits); + (void)cdiGridInqKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits); } + void gridInqYstdname(int gridID, char *ystdname) { grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->ystdname ) - strcpy(ystdname, gridptr->ystdname); + if ( gridptr->y.stdname ) + strcpy(ystdname, gridptr->y.stdname); else ystdname[0] = 0; } + +void gridDefProj(int gridID, int projID) +{ + grid_t *gridptr = gridID2Ptr(gridID); + gridptr->proj = projID; + + if ( gridptr->type == GRID_CURVILINEAR ) + { + grid_t *projptr = gridID2Ptr(projID); + if ( projptr->x.name[0] ) strcpy(gridptr->x.dimname, projptr->x.name); + if ( projptr->y.name[0] ) strcpy(gridptr->y.dimname, projptr->y.name); + } +} + + +int gridInqProj(int gridID) +{ + grid_t *gridptr = gridID2Ptr(gridID); + return gridptr->proj; +} + + +int gridInqProjType(int gridID) +{ + grid_t *gridptr = gridID2Ptr(gridID); + + int projtype = gridptr->projtype; + + if ( projtype == -1 ) + { + char mapping[CDI_MAX_NAME]; mapping[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping); + if ( mapping[0] ) + { + if ( strcmp(mapping, "rotated_latitude_longitude") == 0 ) projtype = CDI_PROJ_RLL; + else if ( strcmp(mapping, "lambert_azimuthal_equal_area") == 0 ) projtype = CDI_PROJ_LAEA; + else if ( strcmp(mapping, "lambert_conformal_conic") == 0 ) projtype = CDI_PROJ_LCC; + else if ( strcmp(mapping, "sinusoidal") == 0 ) projtype = CDI_PROJ_SINU; + + gridptr->projtype = projtype; + } + } + + return projtype; +} + + +void gridVerifyProj(int gridID) +{ + grid_t *gridptr = gridID2Ptr(gridID); + + int projtype = gridInqProjType(gridID); + + if ( projtype == CDI_PROJ_RLL ) + { + gridptr->x.stdname = xystdname_tab[grid_xystdname_grid_latlon][0]; + gridptr->y.stdname = xystdname_tab[grid_xystdname_grid_latlon][1]; + gridSetName(gridptr->x.units, "degrees"); + gridSetName(gridptr->y.units, "degrees"); + } +} + /* @Function gridInqType @Title Get the type of a Grid @@ -1075,8 +1077,8 @@ int gridInqSize(int gridID) if ( size == 0 ) { - int xsize = gridptr->xsize; - int ysize = gridptr->ysize; + int xsize = gridptr->x.size; + int ysize = gridptr->y.size; if ( ysize ) size = xsize * ysize; @@ -1113,7 +1115,7 @@ int gridInqTrunc(int gridID) gridptr->trunc = nsp2trunc(gridptr->size); /* else if ( gridptr->type == GRID_GAUSSIAN ) - gridptr->trunc = nlat2trunc(gridptr->ysize); + gridptr->trunc = nlat2trunc(gridptr->y.size); */ } @@ -1158,18 +1160,18 @@ void gridDefXsize(int gridID, int xsize) if ( gridType == GRID_UNSTRUCTURED && xsize != gridSize ) Error("xsize %d must be equal to gridsize %d for gridtype: UNSTRUCTURED", xsize, gridSize); - if ( gridptr->xsize != xsize ) + if ( gridptr->x.size != xsize ) { gridMark4Update(gridID); - gridptr->xsize = xsize; + gridptr->x.size = xsize; } - if ( gridType != GRID_UNSTRUCTURED ) + if ( gridType != GRID_UNSTRUCTURED && gridType != GRID_PROJECTION ) { - long axisproduct = gridptr->xsize*gridptr->ysize; + long axisproduct = gridptr->x.size*gridptr->y.size; if ( axisproduct > 0 && axisproduct != gridSize ) Error("Inconsistent grid declaration! (xsize=%d ysize=%d gridsize=%d)", - gridptr->xsize, gridptr->ysize, gridSize); + gridptr->x.size, gridptr->y.size, gridSize); } } @@ -1231,7 +1233,7 @@ int gridInqXsize(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->xsize; + return gridptr->x.size; } /* @@ -1257,21 +1259,22 @@ void gridDefYsize(int gridID, int ysize) if ( ysize > gridSize ) Error("ysize %d is greater then gridsize %d", ysize, gridSize); - if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ysize != gridSize ) + int gridType = gridInqType(gridID); + if ( gridType == GRID_UNSTRUCTURED && ysize != gridSize ) Error("ysize %d must be equal gridsize %d for gridtype: UNSTRUCTURED", ysize, gridSize); - if ( gridptr->ysize != ysize ) + if ( gridptr->y.size != ysize ) { gridMark4Update(gridID); - gridptr->ysize = ysize; + gridptr->y.size = ysize; } - if ( gridInqType(gridID) != GRID_UNSTRUCTURED ) + if ( gridType != GRID_UNSTRUCTURED && gridType != GRID_PROJECTION ) { - long axisproduct = gridptr->xsize*gridptr->ysize; + long axisproduct = gridptr->x.size*gridptr->y.size; if ( axisproduct > 0 && axisproduct != gridSize ) Error("Inconsistent grid declaration! (xsize=%d ysize=%d gridsize=%d)", - gridptr->xsize, gridptr->ysize, gridSize); + gridptr->x.size, gridptr->y.size, gridSize); } } @@ -1295,7 +1298,7 @@ int gridInqYsize(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->ysize; + return gridptr->y.size; } /* @@ -1503,12 +1506,12 @@ gridInqXValsSerial(grid_t *gridptr, double *xvals) else if ( gridptr->type == GRID_GAUSSIAN_REDUCED ) size = 2; else - size = gridptr->xsize; + size = gridptr->x.size; if ( CDI_Debug && size == 0 ) Warning("size undefined for gridID = %d", gridptr->self); - if ( gridptr->xvals ) + if ( gridptr->x.vals ) { if ( size && xvals ) { @@ -1560,16 +1563,16 @@ gridDefXValsSerial(grid_t *gridptr, const double *xvals) else if ( gridtype == GRID_GAUSSIAN_REDUCED ) size = 2; else - size = gridptr->xsize; + size = gridptr->x.size; if ( size == 0 ) Error("Size undefined for gridID = %d", gridptr->self); - if (gridptr->xvals && CDI_Debug) + if (gridptr->x.vals && CDI_Debug) Warning("values already defined!"); - gridptr->xvals = (double *)Realloc(gridptr->xvals, + gridptr->x.vals = (double *)Realloc(gridptr->x.vals, (size_t)size * sizeof(double)); - memcpy(gridptr->xvals, xvals, (size_t)size * sizeof (double)); + memcpy(gridptr->x.vals, xvals, (size_t)size * sizeof (double)); } /* @@ -1599,12 +1602,12 @@ gridInqYValsSerial(grid_t *gridptr, double *yvals) int gridtype = gridptr->type; long size = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED) - ? gridptr->size : gridptr->ysize; + ? gridptr->size : gridptr->y.size; if ( CDI_Debug && size == 0 ) Warning("size undefined for gridID = %d!", gridptr->self); - if ( gridptr->yvals ) + if ( gridptr->y.vals ) { if ( size && yvals ) { @@ -1650,16 +1653,16 @@ gridDefYValsSerial(grid_t *gridptr, const double *yvals) int gridtype = gridptr->type; long size = (gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED) - ? gridptr->size : gridptr->ysize; + ? gridptr->size : gridptr->y.size; if ( size == 0 ) Error("Size undefined for gridID = %d!", gridptr->self); - if (gridptr->yvals && CDI_Debug) + if (gridptr->y.vals && CDI_Debug) Warning("Values already defined!"); - gridptr->yvals = (double *)Realloc(gridptr->yvals, (size_t)size * sizeof (double)); - memcpy(gridptr->yvals, yvals, (size_t)size * sizeof (double)); + gridptr->y.vals = (double *)Realloc(gridptr->y.vals, (size_t)size * sizeof (double)); + memcpy(gridptr->y.vals, yvals, (size_t)size * sizeof (double)); } @@ -1687,7 +1690,7 @@ void gridDefYvals(int gridID, const double *yvals) static double gridInqXValSerial(grid_t *gridptr, int index) { - double xval = gridptr->xvals ? gridptr->xvals[index] : 0; + double xval = gridptr->x.vals ? gridptr->x.vals[index] : 0; return xval; } @@ -1701,7 +1704,7 @@ double gridInqXval(int gridID, int index) static double gridInqYValSerial(grid_t *gridptr, int index) { - double yval = gridptr->yvals ? gridptr->yvals[index] : 0; + double yval = gridptr->y.vals ? gridptr->y.vals[index] : 0; return yval; } @@ -1734,23 +1737,23 @@ double gridInqYval(int gridID, int index) double gridInqXinc(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - double xinc = gridptr->xinc; + double xinc = gridptr->x.inc; const double *restrict xvals = gridptr->vtable->inqXValsPtr(gridptr); if ( (! (fabs(xinc) > 0)) && xvals ) { - int xsize = gridptr->xsize; + int xsize = gridptr->x.size; if ( xsize > 1 ) { xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1); - for (size_t i = 2; i < (size_t)xsize; i++ ) + for ( int i = 2; i < xsize; i++ ) if ( fabs(fabs(xvals[i-1] - xvals[i]) - xinc) > 0.01*xinc ) { xinc = 0; break; } - gridptr->xinc = xinc; + gridptr->x.inc = xinc; } } @@ -1770,12 +1773,12 @@ double gridInqXinc(int gridID) double gridInqYinc(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - double yinc = gridptr->yinc; + double yinc = gridptr->y.inc; const double *yvals = gridptr->vtable->inqYValsPtr(gridptr); if ( (! (fabs(yinc) > 0)) && yvals ) { - int ysize = gridptr->ysize; + int ysize = gridptr->y.size; if ( ysize > 1 ) { yinc = yvals[1] - yvals[0]; @@ -1787,13 +1790,67 @@ double gridInqYinc(int gridID) break; } - gridptr->yinc = yinc; + gridptr->y.inc = yinc; } } return yinc; } + +void gridInqProjParamRLL(int gridID, double *xpole, double *ypole, double *angle) +{ + *xpole = 0; *ypole = 0; *angle = 0; + + const char *projection = "rotated_latitude_longitude"; + char mapping[CDI_MAX_NAME]; mapping[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping); + if ( mapping[0] && strcmp(mapping, projection) == 0 ) + { + int atttype, attlen; + char attname[CDI_MAX_NAME+1]; + + int natts; + cdiInqNatts(gridID, CDI_GLOBAL, &natts); + + for ( int iatt = 0; iatt < natts; ++iatt ) + { + cdiInqAtt(gridID, CDI_GLOBAL, iatt, attname, &atttype, &attlen); + + if ( attlen != 1 ) continue; + + if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 ) + { + double attflt; + cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, &attflt); + if ( strcmp(attname, "grid_north_pole_longitude") == 0 ) *xpole = attflt; + else if ( strcmp(attname, "grid_north_pole_latitude") == 0 ) *ypole = attflt; + else if ( strcmp(attname, "north_pole_grid_longitude") == 0 ) *angle = attflt; + } + } + } + else + Warning("%s mapping parameter missing!", projection); +} + + +void gridDefProjParamRLL(int gridID, double xpole, double ypole, double angle) +{ + cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, "rotated_pole"); + + const char *mapping = "rotated_latitude_longitude"; + cdiGridDefKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping); + cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", strlen(mapping), mapping); + cdiDefAttFlt(gridID, CDI_GLOBAL, "grid_north_pole_longitude", DATATYPE_FLT64, 1, &xpole); + cdiDefAttFlt(gridID, CDI_GLOBAL, "grid_north_pole_latitude", DATATYPE_FLT64, 1, &ypole); + if ( IS_NOT_EQUAL(angle, 0) ) cdiDefAttFlt(gridID, CDI_GLOBAL, "north_pole_grid_longitude", DATATYPE_FLT64, 1, &angle); + + grid_t *gridptr = gridID2Ptr(gridID); + gridptr->projtype = CDI_PROJ_RLL; + + gridVerifyProj(gridID); +} + /* @Function @Title @@ -1809,7 +1866,7 @@ double gridInqXpole(int gridID) // Xpole -> grid_north_pole_longitude grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->xpole; + return gridptr->rll.xpole; } /* @@ -1827,13 +1884,13 @@ void gridDefXpole(int gridID, double xpole) // Xpole -> grid_north_pole_longitude grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->xstdname && memcmp(gridptr->xstdname, "grid", 4) != 0 ) - gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0]; + if ( gridptr->x.stdname && memcmp(gridptr->x.stdname, "grid", 4) != 0 ) + gridptr->x.stdname = xystdname_tab[grid_xystdname_grid_latlon][0]; - if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->xpole, xpole) ) + if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->rll.xpole, xpole) ) { gridptr->isRotated = TRUE; - gridptr->xpole = xpole; + gridptr->rll.xpole = xpole; gridMark4Update(gridID); } } @@ -1853,7 +1910,7 @@ double gridInqYpole(int gridID) // Ypole -> grid_north_pole_latitude grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->ypole; + return gridptr->rll.ypole; } /* @@ -1871,13 +1928,13 @@ void gridDefYpole(int gridID, double ypole) // Ypole -> grid_north_pole_latitude grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->ystdname && memcmp(gridptr->ystdname, "grid", 4) != 0 ) - gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1]; + if ( gridptr->y.stdname && memcmp(gridptr->y.stdname, "grid", 4) != 0 ) + gridptr->y.stdname = xystdname_tab[grid_xystdname_grid_latlon][1]; - if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->ypole, ypole) ) + if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->rll.ypole, ypole) ) { gridptr->isRotated = TRUE; - gridptr->ypole = ypole; + gridptr->rll.ypole = ypole; gridMark4Update(gridID); } } @@ -1897,7 +1954,7 @@ double gridInqAngle(int gridID) // Angle -> north_pole_grid_longitude grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->angle; + return gridptr->rll.angle; } /* @@ -1915,10 +1972,10 @@ void gridDefAngle(int gridID, double angle) // Angle -> north_pole_grid_longitude grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->angle, angle) ) + if ( gridptr->isRotated != TRUE || IS_NOT_EQUAL(gridptr->rll.angle, angle) ) { gridptr->isRotated = TRUE; - gridptr->angle = angle; + gridptr->rll.angle = angle; gridMark4Update(gridID); } } @@ -1937,7 +1994,7 @@ int gridInqGMEnd(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->nd; + return gridptr->gme.nd; } /* @@ -1954,9 +2011,9 @@ void gridDefGMEnd(int gridID, int nd) { grid_t *gridptr = gridID2Ptr(gridID); - if (gridptr->nd != nd) + if (gridptr->gme.nd != nd) { - gridptr->nd = nd; + gridptr->gme.nd = nd; gridMark4Update(gridID); } } @@ -1975,7 +2032,7 @@ int gridInqGMEni(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->ni; + return gridptr->gme.ni; } /* @@ -1992,9 +2049,9 @@ void gridDefGMEni(int gridID, int ni) { grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->ni != ni ) + if ( gridptr->gme.ni != ni ) { - gridptr->ni = ni; + gridptr->gme.ni = ni; gridMark4Update(gridID); } } @@ -2013,7 +2070,7 @@ int gridInqGMEni2(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->ni2; + return gridptr->gme.ni2; } /* @@ -2030,9 +2087,9 @@ void gridDefGMEni2(int gridID, int ni2) { grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->ni2 != ni2 ) + if ( gridptr->gme.ni2 != ni2 ) { - gridptr->ni2 = ni2; + gridptr->gme.ni2 = ni2; gridMark4Update(gridID); } } @@ -2051,16 +2108,16 @@ int gridInqGMEni3(int gridID) { grid_t *gridptr = gridID2Ptr(gridID); - return gridptr->ni3; + return gridptr->gme.ni3; } void gridDefGMEni3(int gridID, int ni3) { grid_t *gridptr = gridID2Ptr(gridID); - if ( gridptr->ni3 != ni3 ) + if ( gridptr->gme.ni3 != ni3 ) { - gridptr->ni3 = ni3; + gridptr->gme.ni3 = ni3; gridMark4Update(gridID); } } @@ -2094,8 +2151,8 @@ void grid_check_cyclic(grid_t *gridptr) { gridptr->isCyclic = FALSE; enum { numVertices = 4 }; - size_t xsize = gridptr->xsize >= 0 ? (size_t)gridptr->xsize : 0, - ysize = gridptr->ysize >= 0 ? (size_t)gridptr->ysize : 0; + size_t xsize = gridptr->x.size >= 0 ? (size_t)gridptr->x.size : 0, + ysize = gridptr->y.size >= 0 ? (size_t)gridptr->y.size : 0; const double *xvals = gridptr->vtable->inqXValsPtr(gridptr), (*xbounds)[numVertices] = (const double (*)[numVertices])gridptr->vtable->inqXBoundsPtr(gridptr); @@ -2201,7 +2258,7 @@ bool compareXYvals(grid_t *gridRef, grid_t *gridTest) { bool differ = false; - int xsizeTest = gridTest->xsize, ysizeTest = gridTest->ysize; + int xsizeTest = gridTest->x.size, ysizeTest = gridTest->y.size; if ( !differ && xsizeTest > 0 && xsizeTest == gridRef->vtable->inqXVals(gridRef, NULL) ) { const double *restrict xvalsRef = gridRef->vtable->inqXValsPtr(gridRef), @@ -2235,8 +2292,8 @@ bool compareXYvals2(grid_t *gridRef, grid_t *gridTest) { int gridsize = gridTest->size; bool differ - = ((gridTest->xvals == NULL) ^ (gridRef->xvals == NULL)) - || ((gridTest->yvals == NULL) ^ (gridRef->yvals == NULL)); + = ((gridTest->x.vals == NULL) ^ (gridRef->x.vals == NULL)) + || ((gridTest->y.vals == NULL) ^ (gridRef->y.vals == NULL)); typedef double (*inqVal)(grid_t *grid, int index); inqVal inqXValRef = gridRef->vtable->inqXVal, @@ -2244,11 +2301,11 @@ bool compareXYvals2(grid_t *gridRef, grid_t *gridTest) inqXValTest = gridTest->vtable->inqXVal, inqYValTest = gridTest->vtable->inqYVal; - if ( !differ && gridTest->xvals ) + if ( !differ && gridTest->x.vals ) differ = fabs(inqXValTest(gridTest, 0) - inqXValRef(gridRef, 0)) > 1.e-9 || fabs(inqXValTest(gridTest, gridsize-1) - inqXValRef(gridRef, gridsize-1)) > 1.e-9; - if ( !differ && gridTest->yvals ) + if ( !differ && gridTest->y.vals ) differ = fabs(inqYValTest(gridTest, 0) - inqYValRef(gridRef, 0)) > 1.e-9 || fabs(inqYValTest(gridTest, gridsize-1) - inqYValRef(gridRef, gridsize-1)) > 1.e-9; @@ -2266,49 +2323,49 @@ bool gridCompare(int gridID, const grid_t *grid) if ( grid->size == gridRef->size ) { differ = false; - if ( grid->type == GRID_LONLAT ) + if ( grid->type == GRID_LONLAT || grid->type == GRID_PROJECTION ) { /* printf("gridID %d\n", gridID); - printf("grid.xdef %d\n", grid->xdef); - printf("grid.ydef %d\n", grid->ydef); - printf("grid.xsize %d\n", grid->xsize); - printf("grid.ysize %d\n", grid->ysize); - printf("grid.xfirst %f\n", grid->xfirst); - printf("grid.yfirst %f\n", grid->yfirst); + printf("grid.xdef %d\n", grid->x.flag); + printf("grid.ydef %d\n", grid->y.flag); + printf("grid.xsize %d\n", grid->x.size); + printf("grid.ysize %d\n", grid->y.size); + printf("grid.xfirst %f\n", grid->x.first); + printf("grid.yfirst %f\n", grid->y.first); printf("grid.xfirst %f\n", gridInqXval(gridID, 0)); printf("grid.yfirst %f\n", gridInqYval(gridID, 0)); - printf("grid.xinc %f\n", grid->xinc); - printf("grid.yinc %f\n", grid->yinc); + printf("grid.xinc %f\n", grid->x.inc); + printf("grid.yinc %f\n", grid->y.inc); printf("grid.xinc %f\n", gridInqXinc(gridID)); printf("grid.yinc %f\n", gridInqYinc(gridID)); */ - if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize ) + if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size ) { - if ( grid->xdef == 2 && grid->ydef == 2 ) + if ( grid->x.flag == 2 && grid->y.flag == 2 ) { - if ( ! (IS_EQUAL(grid->xfirst, 0) && IS_EQUAL(grid->xlast, 0) && IS_EQUAL(grid->xinc, 0)) && - ! (IS_EQUAL(grid->yfirst, 0) && IS_EQUAL(grid->ylast, 0) && IS_EQUAL(grid->yinc, 0)) && - IS_NOT_EQUAL(grid->xfirst, grid->xlast) && IS_NOT_EQUAL(grid->yfirst, grid->ylast) ) + if ( ! (IS_EQUAL(grid->x.first, 0) && IS_EQUAL(grid->x.last, 0) && IS_EQUAL(grid->x.inc, 0)) && + ! (IS_EQUAL(grid->y.first, 0) && IS_EQUAL(grid->y.last, 0) && IS_EQUAL(grid->y.inc, 0)) && + IS_NOT_EQUAL(grid->x.first, grid->x.last) && IS_NOT_EQUAL(grid->y.first, grid->y.last) ) { - if ( IS_NOT_EQUAL(grid->xfirst, gridInqXval(gridID, 0)) || - IS_NOT_EQUAL(grid->yfirst, gridInqYval(gridID, 0))) + if ( IS_NOT_EQUAL(grid->x.first, gridInqXval(gridID, 0)) || + IS_NOT_EQUAL(grid->y.first, gridInqYval(gridID, 0))) { differ = true; } - if ( !differ && fabs(grid->xinc) > 0 && - fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000)) + if ( !differ && fabs(grid->x.inc) > 0 && + fabs(fabs(grid->x.inc) - fabs(gridRef->x.inc)) > fabs(grid->x.inc/1000)) { differ = true; } - if ( !differ && fabs(grid->yinc) > 0 && - fabs(fabs(grid->yinc) - fabs(gridRef->yinc)) > fabs(grid->yinc/1000)) + if ( !differ && fabs(grid->y.inc) > 0 && + fabs(fabs(grid->y.inc) - fabs(gridRef->y.inc)) > fabs(grid->y.inc/1000)) { differ = true; } } } - else if ( grid->xvals && grid->yvals ) + else if ( grid->x.vals && grid->y.vals ) differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid); } else @@ -2316,14 +2373,14 @@ bool gridCompare(int gridID, const grid_t *grid) } else if ( grid->type == GRID_GENERIC ) { - if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize ) + if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size ) { - if ( grid->xdef == 1 && grid->ydef == 1 - && grid->xvals && grid->yvals ) + if ( grid->x.flag == 1 && grid->y.flag == 1 + && grid->x.vals && grid->y.vals ) differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid); } - else if ( (grid->ysize == 0 || grid->ysize == 1) && - grid->xsize == gridRef->xsize*gridRef->ysize ) + else if ( (grid->y.size == 0 || grid->y.size == 1) && + grid->x.size == gridRef->x.size*gridRef->y.size ) { } else @@ -2331,20 +2388,20 @@ bool gridCompare(int gridID, const grid_t *grid) } else if ( grid->type == GRID_GAUSSIAN ) { - if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize ) + if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size ) { - if ( grid->xdef == 2 && grid->ydef == 2 ) + if ( grid->x.flag == 2 && grid->y.flag == 2 ) { - if ( ! (IS_EQUAL(grid->xfirst, 0) && IS_EQUAL(grid->xlast, 0) && IS_EQUAL(grid->xinc, 0)) && - ! (IS_EQUAL(grid->yfirst, 0) && IS_EQUAL(grid->ylast, 0)) ) - if ( fabs(grid->xfirst - gridInqXval(gridID, 0)) > 0.0015 || - fabs(grid->yfirst - gridInqYval(gridID, 0)) > 0.0015 || - (fabs(grid->xinc)>0 && fabs(fabs(grid->xinc) - fabs(gridRef->xinc)) > fabs(grid->xinc/1000)) ) + if ( ! (IS_EQUAL(grid->x.first, 0) && IS_EQUAL(grid->x.last, 0) && IS_EQUAL(grid->x.inc, 0)) && + ! (IS_EQUAL(grid->y.first, 0) && IS_EQUAL(grid->y.last, 0)) ) + if ( fabs(grid->x.first - gridInqXval(gridID, 0)) > 0.0015 || + fabs(grid->y.first - gridInqYval(gridID, 0)) > 0.0015 || + (fabs(grid->x.inc)>0 && fabs(fabs(grid->x.inc) - fabs(gridRef->x.inc)) > fabs(grid->x.inc/1000)) ) { differ = true; } } - else if ( grid->xvals && grid->yvals ) + else if ( grid->x.vals && grid->y.vals ) differ = gridRef->vtable->compareXYFull(gridRef, (grid_t *)grid); } else @@ -2354,20 +2411,20 @@ bool gridCompare(int gridID, const grid_t *grid) { /* printf("gridID %d\n", gridID); - printf("grid.xsize %d\n", grid->xsize); - printf("grid.ysize %d\n", grid->ysize); - printf("grid.xfirst %f\n", grid->xvals[0]); - printf("grid.yfirst %f\n", grid->yvals[0]); + printf("grid.xsize %d\n", grid->x.size); + printf("grid.ysize %d\n", grid->y.size); + printf("grid.xfirst %f\n", grid->x.vals[0]); + printf("grid.yfirst %f\n", grid->y.vals[0]); printf("grid xfirst %f\n", gridInqXval(gridID, 0)); printf("grid yfirst %f\n", gridInqYval(gridID, 0)); - printf("grid.xlast %f\n", grid->xvals[grid->size-1]); - printf("grid.ylast %f\n", grid->yvals[grid->size-1]); + printf("grid.xlast %f\n", grid->x.vals[grid->size-1]); + printf("grid.ylast %f\n", grid->y.vals[grid->size-1]); printf("grid xlast %f\n", gridInqXval(gridID, grid->size-1)); printf("grid ylast %f\n", gridInqYval(gridID, grid->size-1)); printf("grid.nv %d\n", grid->nvertex); printf("grid nv %d\n", gridInqNvertex(gridID)); */ - if ( grid->xsize == gridRef->xsize && grid->ysize == gridRef->ysize ) + if ( grid->x.size == gridRef->x.size && grid->y.size == gridRef->y.size ) differ = gridRef->vtable->compareXYAO(gridRef, (grid_t *)grid); } else if ( grid->type == GRID_UNSTRUCTURED ) @@ -2377,8 +2434,8 @@ bool gridCompare(int gridID, const grid_t *grid) differ = differ || ( gridRef->uuid[0] && grid->uuid[0] && memcmp(gridRef->uuid, grid->uuid, CDI_UUID_SIZE) != 0 ); if ( !differ && - ((grid->xvals == NULL) ^ (gridRef->xvals == NULL)) && - ((grid->yvals == NULL) ^ (gridRef->yvals == NULL)) ) + ((grid->x.vals == NULL) ^ (gridRef->x.vals == NULL)) && + ((grid->y.vals == NULL) ^ (gridRef->y.vals == NULL)) ) { int nvertexA, nvertexB, numberA, numberB; differ = ( (nvertexA = grid->nvertex) @@ -2419,53 +2476,53 @@ int gridCompareP ( void * gridptr1, void * gridptr2 ) if ( g1->type != g2->type ) return differ; if ( g1->prec != g2->prec ) return differ; - if ( g1->lcc_projflag != g2->lcc_projflag ) return differ; - if ( g1->lcc_scanflag != g2->lcc_scanflag ) return differ; - if ( g1->lcc_defined != g2->lcc_defined ) return differ; - if ( g1->lcc2_defined != g2->lcc2_defined ) return differ; - if ( g1->laea_defined != g2->laea_defined ) return differ; + if ( g1->lcc.projflag != g2->lcc.projflag ) return differ; + if ( g1->lcc.scanflag != g2->lcc.scanflag ) return differ; + if ( g1->lcc.defined != g2->lcc.defined ) return differ; + if ( g1->lcc2.defined != g2->lcc2.defined ) return differ; + if ( g1->laea.defined != g2->laea.defined ) return differ; if ( g1->isCyclic != g2->isCyclic ) return differ; if ( g1->isRotated != g2->isRotated ) return differ; - if ( g1->xdef != g2->xdef ) return differ; - if ( g1->ydef != g2->ydef ) return differ; - if ( g1->nd != g2->nd ) return differ; - if ( g1->ni != g2->ni ) return differ; - if ( g1->ni2 != g2->ni2 ) return differ; - if ( g1->ni3 != g2->ni3 ) return differ; + if ( g1->x.flag != g2->x.flag ) return differ; + if ( g1->y.flag != g2->y.flag ) return differ; + if ( g1->gme.nd != g2->gme.nd ) return differ; + if ( g1->gme.ni != g2->gme.ni ) return differ; + if ( g1->gme.ni2 != g2->gme.ni2 ) return differ; + if ( g1->gme.ni3 != g2->gme.ni3 ) return differ; if ( g1->number != g2->number ) return differ; if ( g1->position != g2->position ) return differ; if ( g1->trunc != g2->trunc ) return differ; if ( g1->nvertex != g2->nvertex ) return differ; if ( g1->nrowlon != g2->nrowlon ) return differ; if ( g1->size != g2->size ) return differ; - if ( g1->xsize != g2->xsize ) return differ; - if ( g1->ysize != g2->ysize ) return differ; + if ( g1->x.size != g2->x.size ) return differ; + if ( g1->y.size != g2->y.size ) return differ; if ( g1->lcomplex != g2->lcomplex ) return differ; - if ( IS_NOT_EQUAL(g1->xfirst , g2->xfirst) ) return differ; - if ( IS_NOT_EQUAL(g1->yfirst , g2->yfirst) ) return differ; - if ( IS_NOT_EQUAL(g1->xlast , g2->xlast) ) return differ; - if ( IS_NOT_EQUAL(g1->ylast , g2->ylast) ) return differ; - if ( IS_NOT_EQUAL(g1->xinc , g2->xinc) ) return differ; - if ( IS_NOT_EQUAL(g1->yinc , g2->yinc) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc_originLon , g2->lcc_originLon) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc_originLat , g2->lcc_originLat) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc_lonParY , g2->lcc_lonParY) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc_lat1 , g2->lcc_lat1) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc_lat2 , g2->lcc_lat2) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc_xinc , g2->lcc_xinc) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc_yinc , g2->lcc_yinc) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc2_lon_0 , g2->lcc2_lon_0) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc2_lat_0 , g2->lcc2_lat_0) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc2_lat_1 , g2->lcc2_lat_1) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc2_lat_2 , g2->lcc2_lat_2) ) return differ; - if ( IS_NOT_EQUAL(g1->lcc2_a , g2->lcc2_a) ) return differ; - if ( IS_NOT_EQUAL(g1->laea_lon_0 , g2->laea_lon_0) ) return differ; - if ( IS_NOT_EQUAL(g1->laea_lat_0 , g2->laea_lat_0) ) return differ; - if ( IS_NOT_EQUAL(g1->laea_a , g2->laea_a) ) return differ; - if ( IS_NOT_EQUAL(g1->xpole , g2->xpole) ) return differ; - if ( IS_NOT_EQUAL(g1->ypole , g2->ypole) ) return differ; - if ( IS_NOT_EQUAL(g1->angle , g2->angle) ) return differ; + if ( IS_NOT_EQUAL(g1->x.first , g2->x.first) ) return differ; + if ( IS_NOT_EQUAL(g1->y.first , g2->y.first) ) return differ; + if ( IS_NOT_EQUAL(g1->x.last , g2->x.last) ) return differ; + if ( IS_NOT_EQUAL(g1->y.last , g2->y.last) ) return differ; + if ( IS_NOT_EQUAL(g1->x.inc , g2->x.inc) ) return differ; + if ( IS_NOT_EQUAL(g1->y.inc , g2->y.inc) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc.originLon , g2->lcc.originLon) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc.originLat , g2->lcc.originLat) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc.lonParY , g2->lcc.lonParY) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc.lat1 , g2->lcc.lat1) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc.lat2 , g2->lcc.lat2) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc.xinc , g2->lcc.xinc) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc.yinc , g2->lcc.yinc) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc2.lon_0 , g2->lcc2.lon_0) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc2.lat_0 , g2->lcc2.lat_0) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc2.lat_1 , g2->lcc2.lat_1) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc2.lat_2 , g2->lcc2.lat_2) ) return differ; + if ( IS_NOT_EQUAL(g1->lcc2.a , g2->lcc2.a) ) return differ; + if ( IS_NOT_EQUAL(g1->laea.lon_0 , g2->laea.lon_0) ) return differ; + if ( IS_NOT_EQUAL(g1->laea.lat_0 , g2->laea.lat_0) ) return differ; + if ( IS_NOT_EQUAL(g1->laea.a , g2->laea.a) ) return differ; + if ( IS_NOT_EQUAL(g1->rll.xpole , g2->rll.xpole) ) return differ; + if ( IS_NOT_EQUAL(g1->rll.ypole , g2->rll.ypole) ) return differ; + if ( IS_NOT_EQUAL(g1->rll.angle , g2->rll.angle) ) return differ; const double *restrict g1_xvals = g1->vtable->inqXValsPtr(g1), *restrict g2_xvals = g2->vtable->inqXValsPtr(g2); @@ -2474,7 +2531,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 ) if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR ) size = g1->size; else - size = g1->xsize; + size = g1->x.size; xassert ( size ); if ( !g2_xvals ) return differ; @@ -2492,7 +2549,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 ) if ( g1->type == GRID_UNSTRUCTURED || g1->type == GRID_CURVILINEAR ) size = g1->size; else - size = g1->ysize; + size = g1->y.size; xassert ( size ); if ( !g2_yvals ) return differ; @@ -2525,7 +2582,7 @@ int gridCompareP ( void * gridptr1, void * gridptr2 ) if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED ) size = g1->nvertex * g1->size; else - size = g1->nvertex * g1->xsize; + size = g1->nvertex * g1->x.size; xassert ( size ); if ( !(g2_xbounds = g2->vtable->inqXBoundsPtr(g2)) ) return differ; @@ -2545,26 +2602,28 @@ int gridCompareP ( void * gridptr1, void * gridptr2 ) if ( g1->type == GRID_CURVILINEAR || g1->type == GRID_UNSTRUCTURED ) size = g1->nvertex * g1->size; else - size = g1->nvertex * g1->ysize; + size = g1->nvertex * g1->y.size; xassert ( size ); if ( ! (g2_ybounds = g2->vtable->inqYBoundsPtr(g2)) ) return differ; for ( i = 0; i < size; i++ ) - if ( IS_NOT_EQUAL(g1->ybounds[i], g2->ybounds[i]) ) return differ; + if ( IS_NOT_EQUAL(g1->y.bounds[i], g2->y.bounds[i]) ) return differ; } else if ( g2->vtable->inqYBoundsPtr(g2) ) return differ; } - if (strcmp(g1->xname, g2->xname)) return differ; - if (strcmp(g1->yname, g2->yname)) return differ; - if (strcmp(g1->xlongname, g2->xlongname)) return differ; - if (strcmp(g1->ylongname, g2->ylongname)) return differ; - if (g1->xstdname != g2->xstdname) return differ; - if (g1->ystdname != g2->ystdname) return differ; - if (strcmp(g1->xunits, g2->xunits)) return differ; - if (strcmp(g1->yunits, g2->yunits)) return differ; + if (strcmp(g1->x.name, g2->x.name)) return differ; + if (strcmp(g1->y.name, g2->y.name)) return differ; + if (strcmp(g1->x.longname, g2->x.longname)) return differ; + if (strcmp(g1->y.longname, g2->y.longname)) return differ; + if (g1->x.stdname != g2->x.stdname) return differ; + if (g1->y.stdname != g2->y.stdname) return differ; + if (strcmp(g1->x.units, g2->x.units)) return differ; + if (strcmp(g1->y.units, g2->y.units)) return differ; + + if (strcmp(g1->mapping, g2->mapping)) return differ; if ( g1->reference ) { @@ -2598,7 +2657,8 @@ int gridCompareP ( void * gridptr1, void * gridptr2 ) return equal; } -static void gridComplete(grid_t *grid) +static +void gridComplete(grid_t *grid) { int gridID = grid->self; gridDefPrec(gridID, grid->prec); @@ -2617,78 +2677,74 @@ static void gridComplete(grid_t *grid) case GRID_LAEA: case GRID_PROJECTION: { - if ( grid->xsize > 0 ) gridDefXsize(gridID, grid->xsize); - if ( grid->ysize > 0 ) gridDefYsize(gridID, grid->ysize); + if ( grid->x.size > 0 ) gridDefXsize(gridID, grid->x.size); + if ( grid->y.size > 0 ) gridDefYsize(gridID, grid->y.size); if ( gridtype == GRID_GAUSSIAN ) gridDefNP(gridID, grid->np); if ( grid->nvertex > 0 ) gridDefNvertex(gridID, grid->nvertex); - if ( grid->xdef == 2 ) + if ( grid->x.flag == 2 ) { - assert(gridtype != GRID_UNSTRUCTURED - && gridtype != GRID_CURVILINEAR); - double *xvals - = (double *) Malloc((size_t)grid->xsize * sizeof (double)); - gridGenXvals(grid->xsize, grid->xfirst, grid->xlast, grid->xinc, xvals); - grid->xvals = xvals; + assert(gridtype != GRID_UNSTRUCTURED && gridtype != GRID_CURVILINEAR); + double *xvals = (double *) Malloc((size_t)grid->x.size * sizeof (double)); + gridGenXvals(grid->x.size, grid->x.first, grid->x.last, grid->x.inc, xvals); + grid->x.vals = xvals; /* - gridDefXinc(gridID, grid->xinc); + gridDefXinc(gridID, grid->x.inc); */ } - if ( grid->ydef == 2 ) + if ( grid->y.flag == 2 ) { - assert(gridtype != GRID_UNSTRUCTURED - && gridtype != GRID_CURVILINEAR); - double *yvals - = (double *) Malloc((size_t)grid->ysize * sizeof (double)); - gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals); - grid->yvals = yvals; + assert(gridtype != GRID_UNSTRUCTURED && gridtype != GRID_CURVILINEAR); + double *yvals = (double *) Malloc((size_t)grid->y.size * sizeof (double)); + gridGenYvals(gridtype, grid->y.size, grid->y.first, grid->y.last, grid->y.inc, yvals); + grid->y.vals = yvals; /* - gridDefYinc(gridID, grid->yinc); + gridDefYinc(gridID, grid->y.inc); */ } - if ( grid->isRotated ) + if ( grid->isRotated || grid->projtype == CDI_PROJ_RLL ) { - gridDefXname(gridID, "rlon"); - gridDefYname(gridID, "rlat"); - gridDefXlongname(gridID, "longitude in rotated pole grid"); - gridDefYlongname(gridID, "latitude in rotated pole grid"); - grid->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0]; - grid->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1]; - gridDefXunits(gridID, "degrees"); - gridDefYunits(gridID, "degrees"); - - gridDefXpole(gridID, grid->xpole); - gridDefYpole(gridID, grid->ypole); - gridDefAngle(gridID, grid->angle); + if ( grid->x.name[0] == 0 || grid->x.name[0] == 'x' ) gridDefXname(gridID, "rlon"); + if ( grid->y.name[0] == 0 || grid->y.name[0] == 'y' ) gridDefYname(gridID, "rlat"); + if ( grid->x.longname[0] == 0 ) gridDefXlongname(gridID, "longitude in rotated pole grid"); + if ( grid->y.longname[0] == 0 ) gridDefYlongname(gridID, "latitude in rotated pole grid"); + grid->x.stdname = xystdname_tab[grid_xystdname_grid_latlon][0]; + grid->y.stdname = xystdname_tab[grid_xystdname_grid_latlon][1]; + if ( grid->x.units[0] == 0 ) gridDefXunits(gridID, "degrees"); + if ( grid->y.units[0] == 0 ) gridDefYunits(gridID, "degrees"); + + if ( grid->isRotated ) + { + gridDefXpole(gridID, grid->rll.xpole); + gridDefYpole(gridID, grid->rll.ypole); + gridDefAngle(gridID, grid->rll.angle); + } } switch (gridtype) { case GRID_LAEA: - gridDefLaea(gridID, grid->laea_a, grid->laea_lon_0, grid->laea_lat_0); + gridDefLaea(gridID, grid->laea.a, grid->laea.lon_0, grid->laea.lat_0); break; case GRID_LCC2: - gridDefLcc2(gridID, grid->lcc2_a, grid->lcc2_lon_0, grid->lcc2_lat_0, grid->lcc2_lat_1, grid->lcc2_lat_2); + gridDefLcc2(gridID, grid->lcc2.a, grid->lcc2.lon_0, grid->lcc2.lat_0, grid->lcc2.lat_1, grid->lcc2.lat_2); break; case GRID_LCC: - gridDefLCC(gridID, grid->lcc_originLon, grid->lcc_originLat, grid->lcc_lonParY, - grid->lcc_lat1, grid->lcc_lat2, grid->lcc_xinc, grid->lcc_yinc, - grid->lcc_projflag, grid->lcc_scanflag); + gridDefLCC(gridID, grid->lcc.originLon, grid->lcc.originLat, grid->lcc.lonParY, + grid->lcc.lat1, grid->lcc.lat2, grid->lcc.xinc, grid->lcc.yinc, + grid->lcc.projflag, grid->lcc.scanflag); break; case GRID_UNSTRUCTURED: { int number = grid->number; int position = grid->position >= 0 ? grid->position : 0; - if ( number > 0 ) - { - gridDefNumber(gridID, number); - gridDefPosition(gridID, position); - } + if ( number > 0 ) gridDefNumber(gridID, number); + gridDefPosition(gridID, position); } break; } @@ -2698,21 +2754,20 @@ static void gridComplete(grid_t *grid) case GRID_GAUSSIAN_REDUCED: { gridDefNP(gridID, grid->np); - gridDefYsize(gridID, grid->ysize); - if ( grid->xdef == 2 ) + gridDefYsize(gridID, grid->y.size); + if ( grid->x.flag == 2 ) { - double xvals[2] = { grid->xfirst, grid->xlast }; + double xvals[2] = { grid->x.first, grid->x.last }; gridDefXvals(gridID, xvals); } - if ( grid->ydef == 2 ) + if ( grid->y.flag == 2 ) { - double *yvals - = (double *) Malloc((size_t)grid->ysize * sizeof (double)); - gridGenYvals(gridtype, grid->ysize, grid->yfirst, grid->ylast, grid->yinc, yvals); - grid->yvals = yvals; + double *yvals = (double *) Malloc((size_t)grid->y.size * sizeof (double)); + gridGenYvals(gridtype, grid->y.size, grid->y.first, grid->y.last, grid->y.inc, yvals); + grid->y.vals = yvals; /* - gridDefYinc(gridID, grid->yinc); + gridDefYinc(gridID, grid->y.inc); */ } break; @@ -2730,21 +2785,21 @@ static void gridComplete(grid_t *grid) } case GRID_GME: { - gridDefGMEnd(gridID, grid->nd); - gridDefGMEni(gridID, grid->ni); - gridDefGMEni2(gridID, grid->ni2); - gridDefGMEni3(gridID, grid->ni3); + gridDefGMEnd(gridID, grid->gme.nd); + gridDefGMEni(gridID, grid->gme.ni); + gridDefGMEni2(gridID, grid->gme.ni2); + gridDefGMEni3(gridID, grid->gme.ni3); break; } /* case GRID_GENERIC: { - if ( grid->xsize > 0 && grid->ysize > 0 ) + if ( grid->x.size > 0 && grid->y.size > 0 ) { - gridDefXsize(gridID, grid->xsize); - gridDefYsize(gridID, grid->ysize); - if ( grid->xvals ) gridDefXvals(gridID, grid->xvals); - if ( grid->yvals ) gridDefYvals(gridID, grid->yvals); + gridDefXsize(gridID, grid->x.size); + gridDefYsize(gridID, grid->y.size); + if ( grid->x.vals ) gridDefXvals(gridID, grid->x.vals); + if ( grid->y.vals ) gridDefYvals(gridID, grid->y.vals); } break; } @@ -2762,18 +2817,18 @@ static void gridComplete(grid_t *grid) } } - grid->xname[CDI_MAX_NAME - 1] = 0; - grid->xlongname[CDI_MAX_NAME - 1] = 0; - grid->xunits[CDI_MAX_NAME - 1] = 0; - grid->yname[CDI_MAX_NAME - 1] = 0; - grid->ylongname[CDI_MAX_NAME - 1] = 0; - grid->yunits[CDI_MAX_NAME - 1] = 0; + grid->x.name[CDI_MAX_NAME - 1] = 0; + grid->x.longname[CDI_MAX_NAME - 1] = 0; + grid->x.units[CDI_MAX_NAME - 1] = 0; + grid->y.name[CDI_MAX_NAME - 1] = 0; + grid->y.longname[CDI_MAX_NAME - 1] = 0; + grid->y.units[CDI_MAX_NAME - 1] = 0; } -#define GRID_STR_SERIALIZE(gridP) { gridP->xdimname, gridP->ydimname, \ - gridP->vdimname, gridP->xname, gridP->yname, \ - gridP->xlongname, gridP->ylongname, \ - gridP->xunits, gridP->yunits } +#define GRID_STR_SERIALIZE(gridP) { gridP->x.dimname, gridP->y.dimname, \ + gridP->vdimname, gridP->x.name, gridP->y.name, \ + gridP->x.longname, gridP->y.longname, \ + gridP->x.units, gridP->y.units } int gridGenerate(const grid_t *grid) { @@ -2781,11 +2836,11 @@ int gridGenerate(const grid_t *grid) int gridID = gridCreate(gridtype, grid->size); grid_t *restrict gridptr = gridID2Ptr(gridID); gridptr->prec = grid->prec; - gridptr->xsize = grid->xsize; - gridptr->ysize = grid->ysize; + gridptr->x.size = grid->x.size; + gridptr->y.size = grid->y.size; gridptr->np = grid->np; gridptr->nvertex = grid->nvertex; - gridptr->xdef = grid->xdef; + gridptr->x.flag = grid->x.flag; int valdef_group1 = 0; static const int valdef_group1_tab[] = { GRID_LONLAT, GRID_GAUSSIAN, GRID_UNSTRUCTURED, GRID_CURVILINEAR, @@ -2794,48 +2849,48 @@ int gridGenerate(const grid_t *grid) }; for ( size_t i = 0; i < sizeof (valdef_group1_tab) / sizeof (valdef_group1_tab[0]); ++i) valdef_group1 |= (gridtype == valdef_group1_tab[i]); - if ( valdef_group1 && grid->xdef == 1 ) + if ( valdef_group1 && grid->x.flag == 1 ) { - gridDefXvals(gridID, grid->xvals); - if ( grid->xbounds ) - gridDefXbounds(gridID, grid->xbounds); + gridDefXvals(gridID, grid->x.vals); + if ( grid->x.bounds ) + gridDefXbounds(gridID, grid->x.bounds); } - gridptr->xfirst = grid->xfirst; - gridptr->xlast = grid->xlast; - gridptr->xinc = grid->xinc; - gridptr->ydef = grid->ydef; - if ( (valdef_group1 || gridtype == GRID_GAUSSIAN_REDUCED) && grid->ydef == 1) + gridptr->x.first = grid->x.first; + gridptr->x.last = grid->x.last; + gridptr->x.inc = grid->x.inc; + gridptr->y.flag = grid->y.flag; + if ( (valdef_group1 || gridtype == GRID_GAUSSIAN_REDUCED) && grid->y.flag == 1) { - gridDefYvals(gridID, grid->yvals); - if ( grid->ybounds ) - gridDefYbounds(gridID, grid->ybounds); + gridDefYvals(gridID, grid->y.vals); + if ( grid->y.bounds ) + gridDefYbounds(gridID, grid->y.bounds); } - gridptr->yfirst = grid->yfirst; - gridptr->ylast = grid->ylast; - gridptr->yinc = grid->yinc; + gridptr->y.first = grid->y.first; + gridptr->y.last = grid->y.last; + gridptr->y.inc = grid->y.inc; gridptr->isRotated = grid->isRotated; - gridptr->xpole = grid->xpole; - gridptr->ypole = grid->ypole; - gridptr->angle = grid->angle; + gridptr->rll.xpole = grid->rll.xpole; + gridptr->rll.ypole = grid->rll.ypole; + gridptr->rll.angle = grid->rll.angle; if ( valdef_group1 && grid->area) gridDefArea(gridID, grid->area); - gridptr->laea_a = grid->laea_a; - gridptr->laea_lon_0 = grid->laea_lon_0; - gridptr->laea_lat_0 = grid->laea_lat_0; - gridptr->lcc2_a = grid->lcc2_a; - gridptr->lcc2_lon_0 = grid->lcc2_lon_0; - gridptr->lcc2_lat_0 = grid->lcc2_lat_0; - gridptr->lcc2_lat_1 = grid->lcc2_lat_1; - gridptr->lcc2_lat_2 = grid->lcc2_lat_2; - gridptr->lcc_originLon = grid->lcc_originLon; - gridptr->lcc_originLat = grid->lcc_originLat; - gridptr->lcc_lonParY = grid->lcc_lonParY; - gridptr->lcc_lat1 = grid->lcc_lat1; - gridptr->lcc_lat2 = grid->lcc_lat2; - gridptr->lcc_xinc = grid->lcc_xinc; - gridptr->lcc_yinc = grid->lcc_yinc; - gridptr->lcc_projflag = grid->lcc_projflag; - gridptr->lcc_scanflag = grid->lcc_scanflag; + gridptr->laea.a = grid->laea.a; + gridptr->laea.lon_0 = grid->laea.lon_0; + gridptr->laea.lat_0 = grid->laea.lat_0; + gridptr->lcc2.a = grid->lcc2.a; + gridptr->lcc2.lon_0 = grid->lcc2.lon_0; + gridptr->lcc2.lat_0 = grid->lcc2.lat_0; + gridptr->lcc2.lat_1 = grid->lcc2.lat_1; + gridptr->lcc2.lat_2 = grid->lcc2.lat_2; + gridptr->lcc.originLon = grid->lcc.originLon; + gridptr->lcc.originLat = grid->lcc.originLat; + gridptr->lcc.lonParY = grid->lcc.lonParY; + gridptr->lcc.lat1 = grid->lcc.lat1; + gridptr->lcc.lat2 = grid->lcc.lat2; + gridptr->lcc.xinc = grid->lcc.xinc; + gridptr->lcc.yinc = grid->lcc.yinc; + gridptr->lcc.projflag = grid->lcc.projflag; + gridptr->lcc.scanflag = grid->lcc.scanflag; gridptr->number = grid->number; gridptr->position = grid->position; memcpy(gridptr->uuid, grid->uuid, CDI_UUID_SIZE); @@ -2844,19 +2899,20 @@ int gridGenerate(const grid_t *grid) if ( gridtype == GRID_PROJECTION ) gridptr->name = strdup(grid->name); if ( gridtype == GRID_GAUSSIAN_REDUCED ) - gridDefRowlon(gridID, grid->ysize, grid->rowlon); + gridDefRowlon(gridID, grid->y.size, grid->rowlon); gridptr->trunc = grid->trunc; gridptr->lcomplex = grid->lcomplex; - gridptr->nd = grid->nd; - gridptr->ni = grid->ni; - gridptr->ni2 = grid->ni2; - gridptr->ni3 = grid->ni3; + gridptr->gme.nd = grid->gme.nd; + gridptr->gme.ni = grid->gme.ni; + gridptr->gme.ni2 = grid->gme.ni2; + gridptr->gme.ni3 = grid->gme.ni3; const char *grid_str_tab[] = GRID_STR_SERIALIZE(grid); char *gridptr_str_tab[] = GRID_STR_SERIALIZE(gridptr); for (size_t i = 0; i < sizeof (grid_str_tab) / sizeof (grid_str_tab[0]); ++i) if ( grid_str_tab[i][0] ) memcpy(gridptr_str_tab[i], grid_str_tab[i], CDI_MAX_NAME); gridComplete(gridptr); + return gridID; } @@ -2873,38 +2929,38 @@ grid_copy_base_array_fields(grid_t *gridptrOrig, grid_t *gridptrDup) memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int)); } - if ( gridptrOrig->xvals != NULL ) + if ( gridptrOrig->x.vals != NULL ) { - size_t size = irregular ? gridsize : (size_t)gridptrOrig->xsize; + size_t size = irregular ? gridsize : (size_t)gridptrOrig->x.size; - gridptrDup->xvals = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double)); + gridptrDup->x.vals = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->x.vals, gridptrOrig->x.vals, size * sizeof (double)); } - if ( gridptrOrig->yvals != NULL ) + if ( gridptrOrig->y.vals != NULL ) { - size_t size = irregular ? gridsize : (size_t)gridptrOrig->ysize; + size_t size = irregular ? gridsize : (size_t)gridptrOrig->y.size; - gridptrDup->yvals = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double)); + gridptrDup->y.vals = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->y.vals, gridptrOrig->y.vals, size * sizeof (double)); } - if ( gridptrOrig->xbounds != NULL ) + if ( gridptrOrig->x.bounds != NULL ) { - size_t size = (irregular ? gridsize : (size_t)gridptrOrig->xsize) + size_t size = (irregular ? gridsize : (size_t)gridptrOrig->x.size) * (size_t)gridptrOrig->nvertex; - gridptrDup->xbounds = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double)); + gridptrDup->x.bounds = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->x.bounds, gridptrOrig->x.bounds, size * sizeof (double)); } - if ( gridptrOrig->ybounds != NULL ) + if ( gridptrOrig->y.bounds != NULL ) { - size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize) + size_t size = (irregular ? gridsize : (size_t)gridptrOrig->y.size) * (size_t)gridptrOrig->nvertex; - gridptrDup->ybounds = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double)); + gridptrDup->y.bounds = (double *)Malloc(size * sizeof (double)); + memcpy(gridptrDup->y.bounds, gridptrOrig->y.bounds, size * sizeof (double)); } { @@ -3012,12 +3068,12 @@ void gridCompress(int gridID) /* fprintf(stderr, "grid compress %d %d %d\n", i, j, gridsize); */ gridsize = nselect; gridptr->size = (int)gridsize; - gridptr->xsize = (int)gridsize; - gridptr->ysize = (int)gridsize; + gridptr->x.size = (int)gridsize; + gridptr->y.size = (int)gridsize; - double **resizeP[] = { &gridptr->xvals, &gridptr->yvals, + double **resizeP[] = { &gridptr->x.vals, &gridptr->y.vals, &gridptr->area, - &gridptr->xbounds, &gridptr->ybounds }; + &gridptr->x.bounds, &gridptr->y.bounds }; size_t newSize[] = { gridsize, gridsize, gridsize, nv*gridsize, nv*gridsize }; for ( size_t i = 0; i < sizeof (resizeP) / sizeof (resizeP[0]); ++i) @@ -3144,7 +3200,7 @@ gridDefBoundsGeneric(grid_t *gridptr, const double *bounds, int regularSize, static void gridDefXBoundsSerial(grid_t *gridptr, const double *xbounds) { - gridDefBoundsGeneric(gridptr, xbounds, gridptr->xsize, &gridptr->xbounds); + gridDefBoundsGeneric(gridptr, xbounds, gridptr->x.size, &gridptr->x.bounds); } /* @@ -3175,7 +3231,7 @@ gridInqXBoundsSerial(grid_t *gridptr, double *xbounds) int irregular = gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED; - size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->xsize); + size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->x.size); const double *gridptr_xbounds = gridptr->vtable->inqXBoundsPtr(gridptr); if ( gridptr_xbounds ) @@ -3218,7 +3274,7 @@ int gridInqXbounds(int gridID, double *xbounds) static const double * gridInqXBoundsPtrSerial(grid_t *gridptr) { - return gridptr->xbounds; + return gridptr->x.bounds; } @@ -3231,7 +3287,7 @@ const double *gridInqXboundsPtr(int gridID) static void gridDefYBoundsSerial(grid_t *gridptr, const double *ybounds) { - gridDefBoundsGeneric(gridptr, ybounds, gridptr->ysize, &gridptr->ybounds); + gridDefBoundsGeneric(gridptr, ybounds, gridptr->y.size, &gridptr->y.bounds); } /* @@ -3262,7 +3318,7 @@ gridInqYBoundsSerial(grid_t *gridptr, double *ybounds) int irregular = gridptr->type == GRID_CURVILINEAR || gridptr->type == GRID_UNSTRUCTURED; - size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->ysize); + size_t size = nvertex * (size_t)(irregular ? gridptr->size : gridptr->y.size); const double *gridptr_ybounds = gridptr->vtable->inqYBoundsPtr(gridptr); if ( gridptr_ybounds ) @@ -3306,7 +3362,7 @@ int gridInqYbounds(int gridID, double *ybounds) static const double * gridInqYBoundsPtrSerial(grid_t *gridptr) { - return gridptr->ybounds; + return gridptr->y.bounds; } @@ -3389,7 +3445,78 @@ printMask(FILE *fp, const char prefix[], size_t nbyte0, fputs("\n", fp); } -static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) +static inline +void *resizeBuffer(void **buf, size_t *bufSize, size_t reqSize) +{ + if (reqSize > *bufSize) + { + *buf = Realloc(*buf, reqSize); + *bufSize = reqSize; + } + return *buf; +} + +static +void gridPrintAttributes(FILE *fp, int gridID) +{ + int cdiID = gridID; + int varID = CDI_GLOBAL; + int atttype, attlen; + char attname[CDI_MAX_NAME+1]; + void *attBuf = NULL; + size_t attBufSize = 0; + + int natts; + cdiInqNatts(cdiID, varID, &natts); + + for ( int iatt = 0; iatt < natts; ++iatt ) + { + cdiInqAtt(cdiID, varID, iatt, attname, &atttype, &attlen); + + if ( attlen == 0 ) continue; + + if ( atttype == DATATYPE_TXT ) + { + size_t attSize = (size_t)(attlen+1)*sizeof(char); + char *atttxt = (char *)resizeBuffer(&attBuf, &attBufSize, attSize); + cdiInqAttTxt(cdiID, varID, attname, attlen, atttxt); + atttxt[attlen] = 0; + fprintf(fp, "ATTR_TXT: %s = \"%s\"\n", attname, atttxt); + } + else if ( atttype == DATATYPE_INT8 || atttype == DATATYPE_UINT8 || + atttype == DATATYPE_INT16 || atttype == DATATYPE_UINT16 || + atttype == DATATYPE_INT32 || atttype == DATATYPE_UINT32 ) + { + size_t attSize = (size_t)attlen*sizeof(int); + int *attint = (int *)resizeBuffer(&attBuf, &attBufSize, attSize); + cdiInqAttInt(cdiID, varID, attname, attlen, &attint[0]); + if ( attlen == 1 ) + fprintf(fp, "ATTR_INT: %s =", attname); + else + fprintf(fp, "ATTR_INT_%d: %s =", attlen, attname); + for ( int i = 0; i < attlen; ++i ) fprintf(fp, " %d", attint[i]); + fprintf(fp, "\n"); + } + else if ( atttype == DATATYPE_FLT32 || atttype == DATATYPE_FLT64 ) + { + size_t attSize = (size_t)attlen * sizeof(double); + double *attflt = (double *)resizeBuffer(&attBuf, &attBufSize, attSize); + int dig = (atttype == DATATYPE_FLT64) ? 15 : 7; + cdiInqAttFlt(cdiID, varID, attname, attlen, attflt); + if ( attlen == 1 ) + fprintf(fp, "ATTR_FLT: %s =", attname); + else + fprintf(fp, "ATTR_FLT_%d: %s =", attlen, attname); + for ( int i = 0; i < attlen; ++i ) fprintf(fp, " %.*g", dig, attflt[i]); + fprintf(fp, "\n"); + } + } + + Free(attBuf); +} + +static +void gridPrintKernel(grid_t *gridptr, int index, int opt, FILE *fp) { int xdim, ydim; unsigned char uuidOfHGrid[CDI_UUID_SIZE]; @@ -3410,6 +3537,9 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) int dig = (prec == DATATYPE_FLT64) ? 15 : 7; + struct gridaxis_t *xaxis = &gridptr->x; + struct gridaxis_t *yaxis = &gridptr->y; + fprintf(fp, "#\n" "# gridID %d\n" "#\n" @@ -3418,18 +3548,31 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) if ( type != GRID_GME ) { + if ( type != GRID_UNSTRUCTURED && type != GRID_SPECTRAL && type != GRID_FOURIER ) + { + if ( xsize > 0 ) fprintf(fp, "xsize = %d\n", xsize); + if ( ysize > 0 ) fprintf(fp, "ysize = %d\n", ysize); + } + if ( xvals ) { - if ( gridptr->xname[0] ) fprintf(fp, "xname = %s\n", gridptr->xname); - if ( gridptr->xlongname[0] ) fprintf(fp, "xlongname = %s\n", gridptr->xlongname); - if ( gridptr->xunits[0] ) fprintf(fp, "xunits = %s\n", gridptr->xunits); + if ( xaxis->name[0] ) fprintf(fp, "xname = %s\n", xaxis->name); + if ( xaxis->longname[0] ) fprintf(fp, "xlongname = %s\n", xaxis->longname); + if ( xaxis->units[0] ) fprintf(fp, "xunits = %s\n", xaxis->units); + if ( xaxis->dimname[0] && strcmp(xaxis->name, xaxis->dimname) ) + fprintf(fp, "xdimname = %s\n", xaxis->dimname); } if ( yvals ) { - if ( gridptr->yname[0] ) fprintf(fp, "yname = %s\n", gridptr->yname); - if ( gridptr->ylongname[0] ) fprintf(fp, "ylongname = %s\n", gridptr->ylongname); - if ( gridptr->yunits[0] ) fprintf(fp, "yunits = %s\n", gridptr->yunits); + if ( yaxis->name[0] ) fprintf(fp, "yname = %s\n", yaxis->name); + if ( yaxis->longname[0] ) fprintf(fp, "ylongname = %s\n", yaxis->longname); + if ( yaxis->units[0] ) fprintf(fp, "yunits = %s\n", yaxis->units); + if ( yaxis->dimname[0] && strcmp(yaxis->name, yaxis->dimname) ) + fprintf(fp, "ydimname = %s\n", yaxis->dimname); } + + if ( type == GRID_UNSTRUCTURED || type == GRID_CURVILINEAR ) + if ( gridptr->vdimname[0] ) fprintf(fp, "vdimname = %s\n", gridptr->vdimname); if ( type == GRID_UNSTRUCTURED && nvertex > 0 ) fprintf(fp, "nvertex = %d\n", nvertex); } @@ -3442,6 +3585,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) case GRID_LCC2: case GRID_SINUSOIDAL: case GRID_LAEA: + case GRID_PROJECTION: case GRID_CURVILINEAR: case GRID_UNSTRUCTURED: { @@ -3463,12 +3607,6 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) ydim = ysize; } - if ( type != GRID_UNSTRUCTURED ) - { - if ( xsize > 0 ) fprintf(fp, "xsize = %d\n", xsize); - if ( ysize > 0 ) fprintf(fp, "ysize = %d\n", ysize); - } - if ( type == GRID_UNSTRUCTURED ) { int number = gridInqNumber(gridID); @@ -3517,9 +3655,9 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) if ( gridptr->isRotated ) { - if ( xsize > 0 ) fprintf(fp, "xnpole = %.*g\n", dig, gridptr->xpole); - if ( ysize > 0 ) fprintf(fp, "ynpole = %.*g\n", dig, gridptr->ypole); - if ( IS_NOT_EQUAL(gridptr->angle, 0) ) fprintf(fp, "angle = %.*g\n", dig, gridptr->angle); + if ( xsize > 0 ) fprintf(fp, "xnpole = %.*g\n", dig, gridptr->rll.xpole); + if ( ysize > 0 ) fprintf(fp, "ynpole = %.*g\n", dig, gridptr->rll.ypole); + if ( IS_NOT_EQUAL(gridptr->rll.angle, 0) ) fprintf(fp, "angle = %.*g\n", dig, gridptr->rll.angle); } if ( xvals ) @@ -3527,6 +3665,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) double xfirst = 0.0, xinc = 0.0; if ( type == GRID_LONLAT || type == GRID_GAUSSIAN || + type == GRID_PROJECTION || type == GRID_GENERIC || type == GRID_LCC2 || type == GRID_SINUSOIDAL || type == GRID_LAEA ) { @@ -3559,7 +3698,9 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) { double yfirst = 0.0, yinc = 0.0; - if ( type == GRID_LONLAT || type == GRID_GENERIC || type == GRID_LCC2 || + if ( type == GRID_LONLAT || type == GRID_GENERIC || + type == GRID_PROJECTION || + type == GRID_GENERIC || type == GRID_LCC2 || type == GRID_SINUSOIDAL || type == GRID_LAEA ) { yfirst = gridInqYval(gridID, 0); @@ -3604,6 +3745,8 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) Free(rowlon); } + if ( type == GRID_PROJECTION ) gridPrintAttributes(fp, gridID); + break; } case GRID_LCC: @@ -3614,8 +3757,6 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) &projflag, &scanflag); fprintf(fp, - "xsize = %d\n" - "ysize = %d\n" "originLon = %.*g\n" "originLat = %.*g\n" "lonParY = %.*g\n" @@ -3624,7 +3765,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) "xinc = %.*g\n" "yinc = %.*g\n" "projection = %s\n", - xsize, ysize, dig, originLon, dig, originLat, dig, lonParY, + dig, originLon, dig, originLat, dig, lonParY, dig, lat1, dig, lat2, dig, xincm, dig, yincm, (projflag & 128) == 0 ? "northpole" : "southpole"); break; @@ -3642,7 +3783,7 @@ static void gridPrintKernel(grid_t * gridptr, int index, int opt, FILE *fp) } case GRID_GME: { - fprintf(fp, "ni = %d\n", gridptr->ni ); + fprintf(fp, "ni = %d\n", gridptr->gme.ni ); break; } default: @@ -3697,8 +3838,8 @@ void gridPrintP ( void * voidptr, FILE * fp ) "trunc = %d\n" "lcomplex = %d\n" "nrowlon = %d\n", - gridptr->prec, gridptr->nd, gridptr->ni, gridptr->ni2, - gridptr->ni3, gridptr->number, gridptr->position, gridptr->trunc, + gridptr->prec, gridptr->gme.nd, gridptr->gme.ni, gridptr->gme.ni2, + gridptr->gme.ni3, gridptr->number, gridptr->position, gridptr->trunc, gridptr->lcomplex, gridptr->nrowlon ); if ( gridptr->rowlon ) @@ -3720,7 +3861,7 @@ void gridPrintP ( void * voidptr, FILE * fp ) static const double *gridInqXValsPtrSerial(grid_t *gridptr) { - return gridptr->xvals; + return gridptr->x.vals; } const double *gridInqXvalsPtr(int gridID) @@ -3732,7 +3873,7 @@ const double *gridInqXvalsPtr(int gridID) static const double *gridInqYValsPtrSerial(grid_t *gridptr) { - return gridptr->yvals; + return gridptr->y.vals; } const double *gridInqYvalsPtr(int gridID) @@ -3774,16 +3915,16 @@ void gridDefLCC(int gridID, double originLon, double originLat, double lonParY, gridNamePtr(gridptr->type)); else { - gridptr->lcc_originLon = originLon; - gridptr->lcc_originLat = originLat; - gridptr->lcc_lonParY = lonParY; - gridptr->lcc_lat1 = lat1; - gridptr->lcc_lat2 = lat2; - gridptr->lcc_xinc = xinc; - gridptr->lcc_yinc = yinc; - gridptr->lcc_projflag = projflag; - gridptr->lcc_scanflag = scanflag; - gridptr->lcc_defined = TRUE; + gridptr->lcc.originLon = originLon; + gridptr->lcc.originLat = originLat; + gridptr->lcc.lonParY = lonParY; + gridptr->lcc.lat1 = lat1; + gridptr->lcc.lat2 = lat2; + gridptr->lcc.xinc = xinc; + gridptr->lcc.yinc = yinc; + gridptr->lcc.projflag = projflag; + gridptr->lcc.scanflag = scanflag; + gridptr->lcc.defined = TRUE; gridMark4Update(gridID); } } @@ -3821,17 +3962,17 @@ void gridInqLCC(int gridID, double *originLon, double *originLat, double *lonPar gridNamePtr(gridptr->type)); else { - if ( gridptr->lcc_defined ) + if ( gridptr->lcc.defined ) { - *originLon = gridptr->lcc_originLon; - *originLat = gridptr->lcc_originLat; - *lonParY = gridptr->lcc_lonParY; - *lat1 = gridptr->lcc_lat1; - *lat2 = gridptr->lcc_lat2; - *xinc = gridptr->lcc_xinc; - *yinc = gridptr->lcc_yinc; - *projflag = gridptr->lcc_projflag; - *scanflag = gridptr->lcc_scanflag; + *originLon = gridptr->lcc.originLon; + *originLat = gridptr->lcc.originLat; + *lonParY = gridptr->lcc.lonParY; + *lat1 = gridptr->lcc.lat1; + *lat2 = gridptr->lcc.lat2; + *xinc = gridptr->lcc.xinc; + *yinc = gridptr->lcc.yinc; + *projflag = gridptr->lcc.projflag; + *scanflag = gridptr->lcc.scanflag; } else Warning("Lambert Conformal grid undefined (gridID = %d)", gridID); @@ -3847,12 +3988,12 @@ void gridDefLcc2(int gridID, double earth_radius, double lon_0, double lat_0, do gridNamePtr(gridptr->type)); else { - gridptr->lcc2_a = earth_radius; - gridptr->lcc2_lon_0 = lon_0; - gridptr->lcc2_lat_0 = lat_0; - gridptr->lcc2_lat_1 = lat_1; - gridptr->lcc2_lat_2 = lat_2; - gridptr->lcc2_defined = TRUE; + gridptr->lcc2.a = earth_radius; + gridptr->lcc2.lon_0 = lon_0; + gridptr->lcc2.lat_0 = lat_0; + gridptr->lcc2.lat_1 = lat_1; + gridptr->lcc2.lat_2 = lat_2; + gridptr->lcc2.defined = TRUE; gridMark4Update(gridID); } } @@ -3867,13 +4008,13 @@ void gridInqLcc2(int gridID, double *earth_radius, double *lon_0, double *lat_0, gridNamePtr(gridptr->type)); else { - if ( gridptr->lcc2_defined ) + if ( gridptr->lcc2.defined ) { - *earth_radius = gridptr->lcc2_a; - *lon_0 = gridptr->lcc2_lon_0; - *lat_0 = gridptr->lcc2_lat_0; - *lat_1 = gridptr->lcc2_lat_1; - *lat_2 = gridptr->lcc2_lat_2; + *earth_radius = gridptr->lcc2.a; + *lon_0 = gridptr->lcc2.lon_0; + *lat_0 = gridptr->lcc2.lat_0; + *lat_1 = gridptr->lcc2.lat_1; + *lat_2 = gridptr->lcc2.lat_2; } else Warning("LCC2 grid undefined (gridID = %d)", gridID); @@ -3889,10 +4030,10 @@ void gridDefLaea(int gridID, double earth_radius, double lon_0, double lat_0) gridNamePtr(gridptr->type)); else { - gridptr->laea_a = earth_radius; - gridptr->laea_lon_0 = lon_0; - gridptr->laea_lat_0 = lat_0; - gridptr->laea_defined = TRUE; + gridptr->laea.a = earth_radius; + gridptr->laea.lon_0 = lon_0; + gridptr->laea.lat_0 = lat_0; + gridptr->laea.defined = TRUE; gridMark4Update(gridID); } } @@ -3907,11 +4048,11 @@ void gridInqLaea(int gridID, double *earth_radius, double *lon_0, double *lat_0) gridNamePtr(gridptr->type)); else { - if ( gridptr->laea_defined ) + if ( gridptr->laea.defined ) { - *earth_radius = gridptr->laea_a; - *lon_0 = gridptr->laea_lon_0; - *lat_0 = gridptr->laea_lat_0; + *earth_radius = gridptr->laea.a; + *lon_0 = gridptr->laea.lon_0; + *lat_0 = gridptr->laea.lat_0; } else Warning("LAEA grid undefined (gridID = %d)", gridID); @@ -3925,7 +4066,7 @@ void gridDefComplexPacking(int gridID, int lcomplex) if (gridptr->lcomplex != lcomplex) { - gridptr->lcomplex = (short)(lcomplex != 0); + gridptr->lcomplex = lcomplex != 0; gridMark4Update(gridID); } } @@ -3935,7 +4076,7 @@ int gridInqComplexPacking(int gridID) { grid_t* gridptr = gridID2Ptr(gridID); - return gridptr->lcomplex; + return (int)gridptr->lcomplex; } @@ -3955,7 +4096,7 @@ int gridInqHasDims(int gridID) { grid_t* gridptr = gridID2Ptr(gridID); - return gridptr->hasdims; + return (int)gridptr->hasdims; } /* @@ -4201,8 +4342,8 @@ static int gridGetComponentFlags(const grid_t * gridP) | (gridHasAreaFlag & (int)((unsigned)(gridP->vtable->inqAreaPtr((grid_t *)gridP) == NULL) - 1U)) - | (gridHasXBoundsFlag & (int)((unsigned)(gridP->xbounds == NULL) - 1U)) - | (gridHasYBoundsFlag & (int)((unsigned)(gridP->ybounds == NULL) - 1U)) + | (gridHasXBoundsFlag & (int)((unsigned)(gridP->x.bounds == NULL) - 1U)) + | (gridHasYBoundsFlag & (int)((unsigned)(gridP->y.bounds == NULL) - 1U)) | (gridHasReferenceFlag & (int)((unsigned)(gridP->reference == NULL) - 1U)) | (gridHasRowLonFlag & (int)((unsigned)(gridP->rowlon == NULL) - 1U)) | (gridHasUUIDFlag & (int)((unsigned)cdiUUIDIsNull(gridP->uuid) - 1U)); @@ -4232,7 +4373,7 @@ gridGetPackSize(void * voidP, void *context) if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR) count = gridP->size; else - count = gridP->xsize; + count = gridP->x.size; xassert(count); packBuffSize += serializeGetSize(count, DATATYPE_FLT64, context) + serializeGetSize(1, DATATYPE_UINT32, context); @@ -4243,7 +4384,7 @@ gridGetPackSize(void * voidP, void *context) if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR) count = gridP->size; else - count = gridP->ysize; + count = gridP->y.size; xassert(count); packBuffSize += serializeGetSize(count, DATATYPE_FLT64, context) + serializeGetSize(1, DATATYPE_UINT32, context); @@ -4257,26 +4398,26 @@ gridGetPackSize(void * voidP, void *context) + serializeGetSize(1, DATATYPE_UINT32, context); } - if (gridP->xbounds) + if (gridP->x.bounds) { xassert(gridP->nvertex); if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED) count = gridP->size; else - count = gridP->xsize; + count = gridP->x.size; xassert(count); packBuffSize += (serializeGetSize(gridP->nvertex * count, DATATYPE_FLT64, context) + serializeGetSize(1, DATATYPE_UINT32, context)); } - if (gridP->ybounds) + if (gridP->y.bounds) { xassert(gridP->nvertex); if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED) count = gridP->size; else - count = gridP->ysize; + count = gridP->y.size; xassert(count); packBuffSize += (serializeGetSize(gridP->nvertex * count, DATATYPE_FLT64, context) @@ -4345,31 +4486,31 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize, gridP->type = intBuffer[1]; gridP->prec = intBuffer[2]; - gridP->lcc_projflag = intBuffer[3]; - gridP->lcc_scanflag = intBuffer[4]; - gridP->lcc_defined = (short)intBuffer[5]; - gridP->lcc2_defined = (short)intBuffer[6]; - gridP->laea_defined = intBuffer[7]; + gridP->lcc.projflag = intBuffer[3]; + gridP->lcc.scanflag = intBuffer[4]; + gridP->lcc.defined = (short)intBuffer[5]; + gridP->lcc2.defined = (short)intBuffer[6]; + gridP->laea.defined = intBuffer[7]; gridP->isCyclic = (short)intBuffer[8]; gridP->isRotated = (short)intBuffer[9]; - gridP->xdef = (short)intBuffer[10]; - gridP->ydef = (short)intBuffer[11]; - gridP->nd = intBuffer[12]; - gridP->ni = intBuffer[13]; - gridP->ni2 = intBuffer[14]; - gridP->ni3 = intBuffer[15]; + gridP->x.flag = (short)intBuffer[10]; + gridP->y.flag = (short)intBuffer[11]; + gridP->gme.nd = intBuffer[12]; + gridP->gme.ni = intBuffer[13]; + gridP->gme.ni2 = intBuffer[14]; + gridP->gme.ni3 = intBuffer[15]; gridP->number = intBuffer[16]; gridP->position = intBuffer[17]; gridP->trunc = intBuffer[18]; gridP->nvertex = intBuffer[19]; gridP->nrowlon = intBuffer[20]; gridP->size = intBuffer[21]; - gridP->xsize = intBuffer[22]; - gridP->ysize = intBuffer[23]; - gridP->lcomplex = (short)intBuffer[24]; + gridP->x.size = intBuffer[22]; + gridP->y.size = intBuffer[23]; + gridP->lcomplex = (bool)intBuffer[24]; memberMask = intBuffer[25]; - gridP->xstdname = xystdname_tab[intBuffer[26]][0]; - gridP->ystdname = xystdname_tab[intBuffer[27]][1]; + gridP->x.stdname = xystdname_tab[intBuffer[26]][0]; + gridP->y.stdname = xystdname_tab[intBuffer[27]][1]; } if (memberMask & gridHasRowLonFlag) @@ -4391,56 +4532,56 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize, &d, 1, DATATYPE_UINT32, context); xassert(d == cdiCheckSum(DATATYPE_FLT, gridNdouble, doubleBuffer)); - gridP->xfirst = doubleBuffer[0]; - gridP->yfirst = doubleBuffer[1]; - gridP->xlast = doubleBuffer[2]; - gridP->ylast = doubleBuffer[3]; - gridP->xinc = doubleBuffer[4]; - gridP->yinc = doubleBuffer[5]; - gridP->lcc_originLon = doubleBuffer[6]; - gridP->lcc_originLat = doubleBuffer[7]; - gridP->lcc_lonParY = doubleBuffer[8]; - gridP->lcc_lat1 = doubleBuffer[9]; - gridP->lcc_lat2 = doubleBuffer[10]; - gridP->lcc_xinc = doubleBuffer[11]; - gridP->lcc_yinc = doubleBuffer[12]; - gridP->lcc2_lon_0 = doubleBuffer[13]; - gridP->lcc2_lat_0 = doubleBuffer[14]; - gridP->lcc2_lat_1 = doubleBuffer[15]; - gridP->lcc2_lat_2 = doubleBuffer[16]; - gridP->lcc2_a = doubleBuffer[17]; - gridP->laea_lon_0 = doubleBuffer[18]; - gridP->laea_lat_0 = doubleBuffer[19]; - gridP->laea_a = doubleBuffer[20]; - gridP->xpole = doubleBuffer[21]; - gridP->ypole = doubleBuffer[22]; - gridP->angle = doubleBuffer[23]; + gridP->x.first = doubleBuffer[0]; + gridP->y.first = doubleBuffer[1]; + gridP->x.last = doubleBuffer[2]; + gridP->y.last = doubleBuffer[3]; + gridP->x.inc = doubleBuffer[4]; + gridP->y.inc = doubleBuffer[5]; + gridP->lcc.originLon = doubleBuffer[6]; + gridP->lcc.originLat = doubleBuffer[7]; + gridP->lcc.lonParY = doubleBuffer[8]; + gridP->lcc.lat1 = doubleBuffer[9]; + gridP->lcc.lat2 = doubleBuffer[10]; + gridP->lcc.xinc = doubleBuffer[11]; + gridP->lcc.yinc = doubleBuffer[12]; + gridP->lcc2.lon_0 = doubleBuffer[13]; + gridP->lcc2.lat_0 = doubleBuffer[14]; + gridP->lcc2.lat_1 = doubleBuffer[15]; + gridP->lcc2.lat_2 = doubleBuffer[16]; + gridP->lcc2.a = doubleBuffer[17]; + gridP->laea.lon_0 = doubleBuffer[18]; + gridP->laea.lat_0 = doubleBuffer[19]; + gridP->laea.a = doubleBuffer[20]; + gridP->rll.xpole = doubleBuffer[21]; + gridP->rll.ypole = doubleBuffer[22]; + gridP->rll.angle = doubleBuffer[23]; } int irregular = gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR; if (memberMask & gridHasXValsFlag) { - size = irregular ? gridP->size : gridP->xsize; + size = irregular ? gridP->size : gridP->x.size; - gridP->xvals = (double *) Malloc((size_t)size * sizeof (double)); + gridP->x.vals = (double *) Malloc((size_t)size * sizeof (double)); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, - gridP->xvals, size, DATATYPE_FLT64, context); + gridP->x.vals, size, DATATYPE_FLT64, context); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, &d, 1, DATATYPE_UINT32, context); - xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->xvals) == d ); + xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->x.vals) == d ); } if (memberMask & gridHasYValsFlag) { - size = irregular ? gridP->size : gridP->ysize; + size = irregular ? gridP->size : gridP->y.size; - gridP->yvals = (double *) Malloc((size_t)size * sizeof (double)); + gridP->y.vals = (double *) Malloc((size_t)size * sizeof (double)); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, - gridP->yvals, size, DATATYPE_FLT64, context); + gridP->y.vals, size, DATATYPE_FLT64, context); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, &d, 1, DATATYPE_UINT32, context); - xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->yvals) == d); + xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->y.vals) == d); } if (memberMask & gridHasAreaFlag) @@ -4457,28 +4598,28 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize, if (memberMask & gridHasXBoundsFlag) { - size = gridP->nvertex * (irregular ? gridP->size : gridP->xsize); + size = gridP->nvertex * (irregular ? gridP->size : gridP->x.size); xassert(size); - gridP->xbounds = (double *) Malloc((size_t)size * sizeof (double)); + gridP->x.bounds = (double *) Malloc((size_t)size * sizeof (double)); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, - gridP->xbounds, size, DATATYPE_FLT64, context); + gridP->x.bounds, size, DATATYPE_FLT64, context); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, &d, 1, DATATYPE_UINT32, context); - xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->xbounds) == d); + xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->x.bounds) == d); } if (memberMask & gridHasYBoundsFlag) { - size = gridP->nvertex * (irregular ? gridP->size : gridP->ysize); + size = gridP->nvertex * (irregular ? gridP->size : gridP->y.size); xassert(size); - gridP->ybounds = (double *) Malloc((size_t)size * sizeof (double)); + gridP->y.bounds = (double *) Malloc((size_t)size * sizeof (double)); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, - gridP->ybounds, size, DATATYPE_FLT64, context); + gridP->y.bounds, size, DATATYPE_FLT64, context); serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, &d, 1, DATATYPE_UINT32, context); - xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->ybounds) == d); + xassert(cdiCheckSum(DATATYPE_FLT, size, gridP->y.bounds) == d); } { @@ -4548,32 +4689,32 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize, intBuffer[0] = gridP->self; intBuffer[1] = gridP->type; intBuffer[2] = gridP->prec; - intBuffer[3] = gridP->lcc_projflag; - intBuffer[4] = gridP->lcc_scanflag; - intBuffer[5] = gridP->lcc_defined; - intBuffer[6] = gridP->lcc2_defined; - intBuffer[7] = gridP->laea_defined; + intBuffer[3] = gridP->lcc.projflag; + intBuffer[4] = gridP->lcc.scanflag; + intBuffer[5] = gridP->lcc.defined; + intBuffer[6] = gridP->lcc2.defined; + intBuffer[7] = gridP->laea.defined; intBuffer[8] = gridP->isCyclic; intBuffer[9] = gridP->isRotated; - intBuffer[10] = gridP->xdef; - intBuffer[11] = gridP->ydef; - intBuffer[12] = gridP->nd; - intBuffer[13] = gridP->ni; - intBuffer[14] = gridP->ni2; - intBuffer[15] = gridP->ni3; + intBuffer[10] = gridP->x.flag; + intBuffer[11] = gridP->y.flag; + intBuffer[12] = gridP->gme.nd; + intBuffer[13] = gridP->gme.ni; + intBuffer[14] = gridP->gme.ni2; + intBuffer[15] = gridP->gme.ni3; intBuffer[16] = gridP->number; intBuffer[17] = gridP->position; intBuffer[18] = gridP->trunc; intBuffer[19] = gridP->nvertex; intBuffer[20] = gridP->nrowlon; intBuffer[21] = gridP->size; - intBuffer[22] = gridP->xsize; - intBuffer[23] = gridP->ysize; + intBuffer[22] = gridP->x.size; + intBuffer[23] = gridP->y.size; intBuffer[24] = gridP->lcomplex; intBuffer[25] = memberMask = gridGetComponentFlags(gridP); - intBuffer[26] = (int)((const char (*)[2][24])gridP->xstdname + intBuffer[26] = (int)((const char (*)[2][24])gridP->x.stdname - xystdname_tab); - intBuffer[27] = (int)((const char (*)[2][24])gridP->ystdname + intBuffer[27] = (int)((const char (*)[2][24])gridP->y.stdname - (const char (*)[2][24])xystdname_tab[0][1]); serializePack(intBuffer, gridNint, DATATYPE_INT, @@ -4597,30 +4738,30 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize, { double doubleBuffer[gridNdouble]; - doubleBuffer[0] = gridP->xfirst; - doubleBuffer[1] = gridP->yfirst; - doubleBuffer[2] = gridP->xlast; - doubleBuffer[3] = gridP->ylast; - doubleBuffer[4] = gridP->xinc; - doubleBuffer[5] = gridP->yinc; - doubleBuffer[6] = gridP->lcc_originLon; - doubleBuffer[7] = gridP->lcc_originLat; - doubleBuffer[8] = gridP->lcc_lonParY; - doubleBuffer[9] = gridP->lcc_lat1; - doubleBuffer[10] = gridP->lcc_lat2; - doubleBuffer[11] = gridP->lcc_xinc; - doubleBuffer[12] = gridP->lcc_yinc; - doubleBuffer[13] = gridP->lcc2_lon_0; - doubleBuffer[14] = gridP->lcc2_lat_0; - doubleBuffer[15] = gridP->lcc2_lat_1; - doubleBuffer[16] = gridP->lcc2_lat_2; - doubleBuffer[17] = gridP->lcc2_a; - doubleBuffer[18] = gridP->laea_lon_0; - doubleBuffer[19] = gridP->laea_lat_0; - doubleBuffer[20] = gridP->laea_a; - doubleBuffer[21] = gridP->xpole; - doubleBuffer[22] = gridP->ypole; - doubleBuffer[23] = gridP->angle; + doubleBuffer[0] = gridP->x.first; + doubleBuffer[1] = gridP->y.first; + doubleBuffer[2] = gridP->x.last; + doubleBuffer[3] = gridP->y.last; + doubleBuffer[4] = gridP->x.inc; + doubleBuffer[5] = gridP->y.inc; + doubleBuffer[6] = gridP->lcc.originLon; + doubleBuffer[7] = gridP->lcc.originLat; + doubleBuffer[8] = gridP->lcc.lonParY; + doubleBuffer[9] = gridP->lcc.lat1; + doubleBuffer[10] = gridP->lcc.lat2; + doubleBuffer[11] = gridP->lcc.xinc; + doubleBuffer[12] = gridP->lcc.yinc; + doubleBuffer[13] = gridP->lcc2.lon_0; + doubleBuffer[14] = gridP->lcc2.lat_0; + doubleBuffer[15] = gridP->lcc2.lat_1; + doubleBuffer[16] = gridP->lcc2.lat_2; + doubleBuffer[17] = gridP->lcc2.a; + doubleBuffer[18] = gridP->laea.lon_0; + doubleBuffer[19] = gridP->laea.lat_0; + doubleBuffer[20] = gridP->laea.a; + doubleBuffer[21] = gridP->rll.xpole; + doubleBuffer[22] = gridP->rll.ypole; + doubleBuffer[23] = gridP->rll.angle; serializePack(doubleBuffer, gridNdouble, DATATYPE_FLT64, packBuffer, packBufferSize, packBufferPos, context); @@ -4634,7 +4775,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize, if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR) size = gridP->size; else - size = gridP->xsize; + size = gridP->x.size; xassert(size); const double *gridP_xvals = gridP->vtable->inqXValsPtr(gridP); @@ -4650,7 +4791,7 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize, if (gridP->type == GRID_UNSTRUCTURED || gridP->type == GRID_CURVILINEAR ) size = gridP->size; else - size = gridP->ysize; + size = gridP->y.size; xassert(size); const double *gridP_yvals = gridP->vtable->inqYValsPtr(gridP); serializePack(gridP_yvals, size, DATATYPE_FLT64, @@ -4677,12 +4818,12 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize, if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED) size = gridP->nvertex * gridP->size; else - size = gridP->nvertex * gridP->xsize; + size = gridP->nvertex * gridP->x.size; xassert ( size ); - serializePack(gridP->xbounds, size, DATATYPE_FLT64, + serializePack(gridP->x.bounds, size, DATATYPE_FLT64, packBuffer, packBufferSize, packBufferPos, context); - d = cdiCheckSum(DATATYPE_FLT, size, gridP->xbounds); + d = cdiCheckSum(DATATYPE_FLT, size, gridP->x.bounds); serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context); } @@ -4693,12 +4834,12 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize, if (gridP->type == GRID_CURVILINEAR || gridP->type == GRID_UNSTRUCTURED) size = gridP->nvertex * gridP->size; else - size = gridP->nvertex * gridP->ysize; + size = gridP->nvertex * gridP->y.size; xassert ( size ); - serializePack(gridP->ybounds, size, DATATYPE_FLT64, + serializePack(gridP->y.bounds, size, DATATYPE_FLT64, packBuffer, packBufferSize, packBufferPos, context); - d = cdiCheckSum(DATATYPE_FLT, size, gridP->ybounds); + d = cdiCheckSum(DATATYPE_FLT, size, gridP->y.bounds); serializePack(&d, 1, DATATYPE_UINT32, packBuffer, packBufferSize, packBufferPos, context); } @@ -4771,12 +4912,13 @@ gridCompareSearch(int id, void *res, void *data) return CDI_APPLY_GO_ON; } -/* Add grid (which must be Malloc'ed to vlist if not already found */ -struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode) +/* Add grid (which must be Malloc'ed to vlist if not already found) */ +struct addIfNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode) { /* mode: 0 search in vlist and grid table 1 search in grid table only + 2 search in grid table only and don't store the grid in vlist */ bool gridglobdefined = false; bool griddefined = false; @@ -4799,20 +4941,18 @@ struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode) else Error("Internal problem: undefined gridID in vlist " "%d, position %u!", vlistID, index); - } if ( ! griddefined ) { struct gridCompareSearchState query; query.queryKey = grid;// = { .queryKey = grid }; - if ((gridglobdefined - = (cdiResHFilterApply(&gridOps, gridCompareSearch, &query) - == CDI_APPLY_STOP))) + if ( (gridglobdefined = (cdiResHFilterApply(&gridOps, gridCompareSearch, &query) + == CDI_APPLY_STOP)) ) gridID = query.resIDValue; if ( mode == 1 && gridglobdefined ) - for (unsigned index = 0; index < ngrids; index++ ) + for ( unsigned index = 0; index < ngrids; index++ ) if ( vlistptr->gridIDs[index] == gridID ) { gridglobdefined = false; @@ -4827,14 +4967,17 @@ struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode) grid->self = gridID = reshPut(grid, &gridOps); gridComplete(grid); } - vlistptr->gridIDs[ngrids] = gridID; - vlistptr->ngrids++; + if ( mode < 2 ) + { + vlistptr->gridIDs[ngrids] = gridID; + vlistptr->ngrids++; + } } - return (struct addIffNewRes){ .Id = gridID, - .isNew = !griddefined && !gridglobdefined }; + return (struct addIfNewRes){ .Id = gridID, .isNew = !griddefined && !gridglobdefined }; } + const struct gridVirtTable cdiGridVtable = { .destroy = gridDestroyKernel, diff --git a/src/grid.h b/src/grid.h index 5ae1682087df5886895aa5e66ec676e43b99a47d..5f36eae33f91b11e5e427378164c2905f9433d0f 100644 --- a/src/grid.h +++ b/src/grid.h @@ -4,6 +4,8 @@ #include "cdi.h" #include <stdbool.h> +#include "cdi_att.h" + typedef unsigned char mask_t; typedef struct grid_t grid_t; @@ -43,47 +45,77 @@ struct gridVirtTable const double *(*inqYBoundsPtr)(grid_t *gridptr); }; +struct gridaxis_t { + char name[CDI_MAX_NAME]; + char longname[CDI_MAX_NAME]; + char units[CDI_MAX_NAME]; + char dimname[CDI_MAX_NAME]; + const char *stdname; + int size; // number of values + short flag; // 0: undefined 1:vals 2:first+inc + double first, last, inc; + double *vals; + double *bounds; +}; + +// Lambert Conformal Conic +struct grid_lcc_t { + double originLon; + double originLat; + double lonParY; + double lat1; + double lat2; + double xinc; + double yinc; + int projflag; + int scanflag; + short defined; +}; + +// Lambert Conformal Conic 2 +struct grid_lcc2_t { + double lon_0; + double lat_0; + double lat_1; + double lat_2; + double a; + short defined; +}; + +// Lambert Azimuthal Equal Area +struct grid_laea_t { + double lon_0; + double lat_0; + double a; + short defined; +}; + +// GME Grid +struct grid_gme_t { + int nd, ni, ni2, ni3; /* parameter for GRID_GME */ +}; + +// Rotated LonLat +struct grid_rll_t { + double xpole, ypole, angle; /* rotated north pole */ +}; + struct grid_t { int self; int type; /* grid type */ int prec; /* grid precision */ int proj; /* grid projection */ + int projtype; /* grid projection type */ mask_t *mask; mask_t *mask_gme; - double *xvals; - double *yvals; double *area; - double *xbounds; - double *ybounds; - double xfirst, yfirst; - double xlast, ylast; - double xinc, yinc; - double lcc_originLon; /* Lambert Conformal Conic */ - double lcc_originLat; - double lcc_lonParY; - double lcc_lat1; - double lcc_lat2; - double lcc_xinc; - double lcc_yinc; - int lcc_projflag; - int lcc_scanflag; - short lcc_defined; - short lcc2_defined; - int laea_defined; - double lcc2_lon_0; /* Lambert Conformal Conic 2 */ - double lcc2_lat_0; - double lcc2_lat_1; - double lcc2_lat_2; - double lcc2_a; - double laea_lon_0; /* Lambert Azimuthal Equal Area */ - double laea_lat_0; - double laea_a; - double xpole, ypole, angle; /* rotated north pole */ + struct grid_lcc_t lcc; + struct grid_lcc2_t lcc2; + struct grid_laea_t laea; + struct grid_gme_t gme; + struct grid_rll_t rll; short isCyclic; /* TRUE for global cyclic grids */ short isRotated; /* TRUE for rotated grids */ - short xdef; /* 0: undefined 1:xvals 2:x0+xinc */ - short ydef; /* 0: undefined 1:yvals 2:y0+yinc */ - int nd, ni, ni2, ni3; /* parameter for GRID_GME */ int number, position; /* parameter for GRID_REFERENCE */ int trunc; /* parameter for GRID_SPECTEAL */ int nvertex; @@ -92,37 +124,30 @@ struct grid_t { int *rowlon; int nrowlon; int size; - int xsize; /* number of values along X */ - int ysize; /* number of values along Y */ int np; /* number of parallels between a pole and the equator */ - short lcomplex; - short hasdims; - const char *xstdname; - const char *ystdname; - char xdimname[CDI_MAX_NAME]; - char ydimname[CDI_MAX_NAME]; + bool lcomplex; + bool hasdims; char vdimname[CDI_MAX_NAME]; - char xname[CDI_MAX_NAME]; - char yname[CDI_MAX_NAME]; - char xlongname[CDI_MAX_NAME]; - char ylongname[CDI_MAX_NAME]; - char xunits[CDI_MAX_NAME]; - char yunits[CDI_MAX_NAME]; + char mapname[CDI_MAX_NAME]; + char mapping[CDI_MAX_NAME]; char *name; + struct gridaxis_t x; + struct gridaxis_t y; const struct gridVirtTable *vtable; - void *extraData; + cdi_atts_t atts; }; void grid_init(grid_t *gridptr); -void -cdiGridTypeInit(grid_t *gridptr, int gridtype, int size); +void cdiGridTypeInit(grid_t *gridptr, int gridtype, int size); void grid_free(grid_t *gridptr); grid_t *gridID2Ptr(int gridID); extern const struct gridVirtTable cdiGridVtable; unsigned cdiGridCount(void); +void gridVerifyProj(int gridID); + const double *gridInqXvalsPtr(int gridID); const double *gridInqYvalsPtr(int gridID); @@ -130,9 +155,6 @@ const double *gridInqXboundsPtr(int gridID); const double *gridInqYboundsPtr(int gridID); const double *gridInqAreaPtr(int gridID); -const char *gridInqXnamePtr(int gridID); -const char *gridInqYnamePtr(int gridID); - const char *gridInqReferencePtr(int gridID); int gridGenerate(const grid_t *grid); @@ -144,13 +166,13 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize, int * unpackBufferPos, int originNamespace, void *context, int force_id); -struct addIffNewRes +struct addIfNewRes { int Id; int isNew; }; -struct addIffNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode); +struct addIfNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode); #endif /* diff --git a/src/make_cdilib b/src/make_cdilib index 8527d91fe7d43832a7e95753c1421273f85f1978..a936a802cc01df1f7be8ff1989811ee2e045c252 100755 --- a/src/make_cdilib +++ b/src/make_cdilib @@ -94,6 +94,8 @@ files="basetime.c \ calendar.c \ cdf.c \ cdf_int.c \ + cdf_util.c \ + cdf_lazy_grid.c \ cdi_cksum.c \ cdi_error.c \ cdi_int.c \ @@ -123,10 +125,10 @@ files="basetime.c \ stream.c \ stream_write.c \ stream_read.c \ - stream_cdf.c \ + stream_cdf_i.c \ + stream_cdf_o.c \ stream_cgribex.c \ stream_ext.c \ - stream_fcommon.c \ stream_grb.c \ stream_gribapi.c \ stream_history.c \ @@ -147,7 +149,7 @@ files="basetime.c \ util.c \ varscan.c \ vlist.c \ - vlist_att.c \ + cdi_att.c \ vlist_var.c \ zaxis.c" diff --git a/src/make_fint.c b/src/make_fint.c index 45b72da6e34f08098745dd01c5c8ad6dfeccf622..64fdbceaa407d429251db4561bd6fb93611182e3 100644 --- a/src/make_fint.c +++ b/src/make_fint.c @@ -15,7 +15,7 @@ #endif //#include "config.h" -#define VERSION "1.7.2" +#define VERSION "1.8.0" typedef struct { size_t naline; diff --git a/src/pio_interface.c b/src/pio_interface.c index da371c63ff0ad3f73a4983bf95146d73cf01e017..37b2f033ae886ea919f708a2aa46b7bb0c9d38ef 100644 --- a/src/pio_interface.c +++ b/src/pio_interface.c @@ -2,7 +2,7 @@ # include "config.h" #endif -#include <limits.h> +#include <stdint.h> #include <stdarg.h> #include <stdbool.h> #include <stdlib.h> @@ -340,7 +340,7 @@ scatterGatherPackFunc(void *dataDesc, void *buf, int size, int *pos, unsigned char *dstBuf = (unsigned char *)buf + pos_, *bufEnd = (unsigned char *)buf + size; size_t elemSize = p->elemSize; - xassert(elemSize <= SSIZE_MAX); + xassert(elemSize <= SIZE_MAX); const unsigned char *data = p->data; unsigned copyCount = 0, numElems = p->numElems; for (unsigned j = 0; j < numBlocks && copyCount < numElems; ++j) @@ -356,7 +356,7 @@ scatterGatherPackFunc(void *dataDesc, void *buf, int size, int *pos, } size_t bsize = (size_t)bl * elemSize; xassert(dstBuf + bsize <= bufEnd); - memcpy(dstBuf, data + (ssize_t)elemSize * (ssize_t)disps[j], bsize); + memcpy(dstBuf, data + (size_t)elemSize * (size_t)disps[j], bsize); dstBuf += bsize; } } diff --git a/src/resource_handle.c b/src/resource_handle.c index 0685d61798716f5968f5d897b937b3d0c9a3d17e..d282f82d2b6b59230352094fde0ff4a6908666af 100644 --- a/src/resource_handle.c +++ b/src/resource_handle.c @@ -379,17 +379,15 @@ static listElem_t * reshGetElem(const char *caller, const char* expressionString, cdiResH resH, const resOps *ops) { listElem_t *listElem; - int nsp; - namespaceTuple_t nspT; xassert ( ops ); LIST_INIT(1); LIST_LOCK(); - nsp = namespaceGetActive (); + int nsp = namespaceGetActive (); - nspT = namespaceResHDecode ( resH ); + namespaceTuple_t nspT = namespaceResHDecode ( resH ); assert(nspT.idx >= 0); if (nspT.nsp == nsp && @@ -583,9 +581,35 @@ void reshPackBufferDestroy ( char ** buffer ) /**************************************************************/ +int reshGetTxCode(cdiResH resH) +{ + int type = 0; + + LIST_LOCK(); + + int nsp = namespaceGetActive (); + + namespaceTuple_t nspT = namespaceResHDecode ( resH ); + assert(nspT.idx >= 0); + + if (nspT.nsp == nsp && + nspT.idx < resHList[nsp].size) + { + listElem_t *listElem = resHList[nsp].resources + nspT.idx; + xassert ( listElem->res.v.ops ); + type = listElem->res.v.ops->valTxCode(); + } + + LIST_UNLOCK(); + + return type; +} + +/**************************************************************/ + int reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context) { - int i, packBufferPos = 0; + int packBufferPos = 0; int end = END; xassert ( packBuffer ); @@ -603,7 +627,7 @@ int reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context) } listElem_t *r = resHList[nsp].resources; - for ( i = 0; i < resHList[nsp].size; i++ ) + for ( int i = 0; i < resHList[nsp].size; i++ ) if (r[i].status & RESH_SYNC_BIT) { if (r[i].status == RESH_DESYNC_DELETED) @@ -630,6 +654,7 @@ int reshPackBufferCreate(char **packBuffer, int *packBufferSize, void *context) LIST_UNLOCK(); serializePack(&end, 1, DATATYPE_INT, pB, pBSize, &packBufferPos, context); + return packBufferPos; } diff --git a/src/resource_handle.h b/src/resource_handle.h index 88264ad4a18c8171c328f5ee67c9d5e164900359..44f8b63f5e9a8dc8bc2c0d06fb9ecabc49e565b7 100644 --- a/src/resource_handle.h +++ b/src/resource_handle.h @@ -99,6 +99,7 @@ enum reshListMismatch { int reshListCompare(int nsp0, int nsp1); void reshListPrint(FILE *fp); +int reshGetTxCode(cdiResH resH); #endif /* diff --git a/src/stream.c b/src/stream.c index c6467c288ebc3ffe5cc519461a23bef55b4f1c30..0cc02c1fb3bd09516d6110707eff505c23741e03 100644 --- a/src/stream.c +++ b/src/stream.c @@ -330,7 +330,7 @@ long cdiInqTimeSize(int streamID) } static -int cdiInqContents(stream_t * streamptr) +int cdiInqContents(stream_t *streamptr) { int status = 0; @@ -593,27 +593,26 @@ int streamOpenID(const char *filename, char filemode, int filetype, int resH) return streamID; } -static int streamOpen(const char *filename, const char *filemode, int filetype) +static +int streamOpen(const char *filename, const char *filemode, int filetype) { if (!filemode || strlen(filemode) != 1) return CDI_EINVAL; return streamOpenID(filename, (char)tolower(filemode[0]), filetype, CDI_UNDEFID); } -static int streamOpenA(const char *filename, const char *filemode, int filetype) +static +int streamOpenA(const char *filename, const char *filemode, int filetype) { - int fileID = CDI_UNDEFID; - int streamID = CDI_ESYSTEM; - int status; - stream_t *streamptr = stream_new_entry(CDI_UNDEFID); - vlist_t *vlistptr; - if ( CDI_Debug ) Message("Open %s file (mode=%c); filename: %s", strfiletype(filetype), (int) *filemode, filename); if ( CDI_Debug ) printf("streamOpenA: %s\n", filename); // seg fault without this line on thunder/squall with "cdo cat x y" if ( ! filename || ! filemode || filetype < 0 ) return CDI_EINVAL; + stream_t *streamptr = stream_new_entry(CDI_UNDEFID); + int fileID = CDI_UNDEFID; + { int (*streamOpenDelegate)(const char *filename, char filemode, int filetype, stream_t *streamptr, int recordBufIsToBeCreated) @@ -625,7 +624,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype) if ( fileID == CDI_UNDEFID || fileID == CDI_ELIBNAVAIL || fileID == CDI_ESYSTEM ) return fileID; - streamID = streamptr->self; + int streamID = streamptr->self; streamptr->filemode = tolower(*filemode); streamptr->filename = strdupx(filename); @@ -634,9 +633,9 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype) streamptr->vlistID = vlistCreate(); cdiVlistMakeInternal(streamptr->vlistID); /* cdiReadByteorder(streamID); */ - status = cdiInqContents(streamptr); + int status = cdiInqContents(streamptr); if ( status < 0 ) return status; - vlistptr = vlist_to_pointer(streamptr->vlistID); + vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID); vlistptr->ntsteps = (int)cdiInqTimeSize(streamID); if(!strcmp(filemode, "r")) cdiVlistMakeImmutable(streamptr->vlistID); @@ -655,6 +654,7 @@ static int streamOpenA(const char *filename, const char *filemode, int filetype) case FILETYPE_GRB2: { fileID = gribOpen(filename, filemode); + if ( fileID != CDI_UNDEFID ) gribContainersNew(streamptr); break; } #endif @@ -869,39 +869,40 @@ void streamDefaultValue ( stream_t * streamptr ) streamptr->vlistID = CDI_UNDEFID; streamptr->globalatts = 0; streamptr->localatts = 0; - streamptr->vct.ilev = 0; - streamptr->vct.mlev = 0; - streamptr->vct.ilevID = CDI_UNDEFID; - streamptr->vct.mlevID = CDI_UNDEFID; streamptr->unreduced = cdiDataUnreduced; streamptr->sortname = cdiSortName; streamptr->have_missval = cdiHaveMissval; - streamptr->comptype = COMPRESS_NONE; + streamptr->comptype = CDI_COMPRESS_NONE; streamptr->complevel = 0; basetimeInit(&streamptr->basetime); +#ifdef HAVE_LIBNETCDF int i; - for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->xdimID[i] = CDI_UNDEFID; - for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ydimID[i] = CDI_UNDEFID; + for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->xdimID[i] = CDI_UNDEFID; + for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ydimID[i] = CDI_UNDEFID; for ( i = 0; i < MAX_ZAXES_PS; i++ ) streamptr->zaxisID[i] = CDI_UNDEFID; for ( i = 0; i < MAX_ZAXES_PS; i++ ) streamptr->nczvarID[i] = CDI_UNDEFID; - for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncxvarID[i] = CDI_UNDEFID; - for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncyvarID[i] = CDI_UNDEFID; - for ( i = 0; i < MAX_GRIDS_PS; i++ ) streamptr->ncavarID[i] = CDI_UNDEFID; + + streamptr->ncgrid = NULL; + + streamptr->vct.ilev = 0; + streamptr->vct.mlev = 0; + streamptr->vct.ilevID = CDI_UNDEFID; + streamptr->vct.mlevID = CDI_UNDEFID; +#endif streamptr->gribContainers = NULL; } - -static stream_t *stream_new_entry(int resH) +static +stream_t *stream_new_entry(int resH) { - stream_t *streamptr; - cdiInitialize(); /* ***************** make MT version !!! */ - streamptr = (stream_t *) Malloc(sizeof(stream_t)); + stream_t *streamptr = (stream_t *) Malloc(sizeof(stream_t)); streamDefaultValue ( streamptr ); + if (resH == CDI_UNDEFID) streamptr->self = reshPut(streamptr, &streamOps); else @@ -914,8 +915,7 @@ static stream_t *stream_new_entry(int resH) } -void -cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted) +void cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted) { int fileID = streamptr->fileID; int filetype = streamptr->filetype; @@ -968,6 +968,7 @@ cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted) case FILETYPE_NC4C: { cdfClose(fileID); + if ( streamptr->ncgrid ) { Free(streamptr->ncgrid); streamptr->ncgrid = NULL; } break; } #endif @@ -980,7 +981,8 @@ cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDeleted) } -static void deallocate_sleveltable_t(sleveltable_t *entry) +static +void deallocate_sleveltable_t(sleveltable_t *entry) { if (entry->recordID) Free(entry->recordID); if (entry->lindex) Free(entry->lindex); @@ -1004,7 +1006,6 @@ The function @func{streamClose} closes an open dataset. */ void streamClose(int streamID) { - int index; stream_t *streamptr = stream_to_pointer(streamID); if ( CDI_Debug ) @@ -1029,7 +1030,7 @@ void streamClose(int streamID) streamptr->filetype = 0; if ( streamptr->filename ) Free(streamptr->filename); - for ( index = 0; index < streamptr->nvars; index++ ) + for ( int index = 0; index < streamptr->nvars; index++ ) { sleveltable_t *pslev = streamptr->vars[index].recordTable; unsigned nsub = streamptr->vars[index].subtypeSize >= 0 @@ -1043,7 +1044,7 @@ void streamClose(int streamID) Free(streamptr->vars); streamptr->vars = NULL; - for ( index = 0; index < streamptr->ntsteps; ++index ) + for ( int index = 0; index < streamptr->ntsteps; ++index ) { if ( streamptr->tsteps[index].records ) Free(streamptr->tsteps[index].records); @@ -1070,13 +1071,12 @@ void streamClose(int streamID) stream_delete_entry(streamptr); } -static void stream_delete_entry(stream_t *streamptr) +static +void stream_delete_entry(stream_t *streamptr) { - int idx; - xassert ( streamptr ); - idx = streamptr->self; + int idx = streamptr->self; Free( streamptr ); reshRemove ( idx, &streamOps ); @@ -1233,6 +1233,7 @@ int streamDefTimestep(int streamID, int tsID) return myStreamDefTimestep_(streamptr, tsID); } + int streamInqCurTimestepID(int streamID) { stream_t *streamptr = stream_to_pointer(streamID); @@ -1474,8 +1475,7 @@ void streamDefVlist(int streamID, int vlistID) } /* the single image implementation of streamDefVlist */ -void -cdiStreamDefVlist_(int streamID, int vlistID) +void cdiStreamDefVlist_(int streamID, int vlistID) { stream_t *streamptr = stream_to_pointer(streamID); @@ -1581,29 +1581,26 @@ int streamTxCode(void) return STREAM; } -void -cdiStreamSetupVlist(stream_t *streamptr, int vlistID) +void cdiStreamSetupVlist(stream_t *streamptr, int vlistID) { void (*myStreamSetupVlist)(stream_t *streamptr, int vlistID) - = (void (*)(stream_t *, int)) - namespaceSwitchGet(NSSWITCH_STREAM_SETUP_VLIST).func; + = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_SETUP_VLIST).func; myStreamSetupVlist(streamptr, vlistID); } -void -cdiStreamSetupVlist_(stream_t *streamptr, int vlistID) + +void cdiStreamSetupVlist_(stream_t *streamptr, int vlistID) { - int nvars = vlistNvars(vlistID); streamptr->vlistID = vlistID; - for (int varID = 0; varID < nvars; varID++ ) + int nvars = vlistNvars(vlistID); + for ( int varID = 0; varID < nvars; varID++ ) { int gridID = vlistInqVarGrid(vlistID, varID); int zaxisID = vlistInqVarZaxis(vlistID, varID); int tilesetID = vlistInqVarSubtype(vlistID, varID); stream_new_var(streamptr, gridID, zaxisID, tilesetID); if ( streamptr->have_missval ) - vlistDefVarMissval(vlistID, varID, - vlistInqVarMissval(vlistID, varID)); + vlistDefVarMissval(vlistID, varID, vlistInqVarMissval(vlistID, varID)); } if (streamptr->filemode == 'w') @@ -1616,8 +1613,7 @@ cdiStreamSetupVlist_(stream_t *streamptr, int vlistID) case FILETYPE_NC4C: { void (*myCdfDefVars)(stream_t *streamptr) - = (void (*)(stream_t *)) - namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func; + = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func; myCdfDefVars(streamptr); } break; diff --git a/src/stream_cdf.c b/src/stream_cdf.c deleted file mode 100644 index 90c5a1597b61221bcfd330ae8e38ade004af5077..0000000000000000000000000000000000000000 --- a/src/stream_cdf.c +++ /dev/null @@ -1,7180 +0,0 @@ -#if defined (HAVE_CONFIG_H) -# include "config.h" -#endif - -#ifdef HAVE_LIBNETCDF - -//#define TEST_GROUPS 1 - -#include <limits.h> -#include <ctype.h> -#include <math.h> -#include <float.h> -#ifdef HAVE_MMAP -#include <unistd.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#endif -#ifdef HAVE_LIBPTHREAD -#include <pthread.h> -#endif - -#include <netcdf.h> - -#include "dmemory.h" -#include "cdi.h" -#include "basetime.h" -#include "gaussgrid.h" -#include "cdi_int.h" -#include "cdi_uuid.h" -#include "stream_cdf.h" -#include "cdf.h" -#include "cdf_int.h" -#include "varscan.h" -#include "vlist.h" -#include "zaxis.h" - -//#define PROJECTION_TEST - -#undef UNDEFID -#define UNDEFID CDI_UNDEFID - -static const char bndsName[] = "bnds"; - -#define X_AXIS 1 -#define Y_AXIS 2 -#define Z_AXIS 3 -#define T_AXIS 4 - -#define POSITIVE_UP 1 -#define POSITIVE_DOWN 2 - -typedef struct { - int ncvarid; - int dimtype; - size_t len; - char name[CDI_MAX_NAME]; -} -ncdim_t; -#define MAX_COORDVARS 4 -#define MAX_AUXVARS 4 - -typedef struct { - int ncid; - int ignore; - short isvar; - short islon; - int islat; - int islev; - int istime; - int warn; - int tsteptype; - int param; - int code; - int tabnum; - int climatology; - int bounds; - int lformula; - int lformulaterms; - int gridID; - int zaxisID; - int gridtype; - int zaxistype; - int xdim; - int ydim; - int zdim; - int xvarid; - int yvarid; - int zvarid; - int tvarid; - int psvarid; - int p0varid; - int ncoordvars; - int coordvarids[MAX_COORDVARS]; - int nauxvars; - int auxvarids[MAX_AUXVARS]; - int cellarea; - int calendar; - int tableID; - int truncation; - int position; - int defmissval; - int deffillval; - int xtype; - int ndims; - int gmapid; - int positive; - int dimids[8]; - int dimtype[8]; - int chunks[8]; - int chunked; - int chunktype; - int natts; - int deflate; - int lunsigned; - int lvalidrange; - int *atts; - size_t vctsize; - double *vct; - double missval; - double fillval; - double addoffset; - double scalefactor; - double validrange[2]; - char name[CDI_MAX_NAME]; - char longname[CDI_MAX_NAME]; - char stdname[CDI_MAX_NAME]; - char units[CDI_MAX_NAME]; - char extra[CDI_MAX_NAME]; - ensinfo_t *ensdata; /* Ensemble information */ -} -ncvar_t; - -static -void strtolower(char *str) -{ - if ( str ) - for (size_t i = 0; str[i]; ++i) - str[i] = (char)tolower((int)str[i]); -} - -static -int get_timeunit(size_t len, const char *ptu) -{ - int timeunit = -1; - - if ( len > 2 ) - { - if ( memcmp(ptu, "sec", 3) == 0 ) timeunit = TUNIT_SECOND; - else if ( memcmp(ptu, "minute", 6) == 0 ) timeunit = TUNIT_MINUTE; - else if ( memcmp(ptu, "hour", 4) == 0 ) timeunit = TUNIT_HOUR; - else if ( memcmp(ptu, "day", 3) == 0 ) timeunit = TUNIT_DAY; - else if ( memcmp(ptu, "month", 5) == 0 ) timeunit = TUNIT_MONTH; - else if ( memcmp(ptu, "calendar_month", 14) == 0 ) timeunit = TUNIT_MONTH; - else if ( memcmp(ptu, "year", 4) == 0 ) timeunit = TUNIT_YEAR; - } - else if ( len == 1 ) - { - if ( ptu[0] == 's' ) timeunit = TUNIT_SECOND; - } - - return timeunit; -} - -static -bool isTimeUnits(const char *timeunits) -{ - bool status = strncmp(timeunits, "sec", 3) == 0 - || strncmp(timeunits, "minute", 6) == 0 - || strncmp(timeunits, "hour", 4) == 0 - || strncmp(timeunits, "day", 3) == 0 - || strncmp(timeunits, "month", 5) == 0; - return status; -} - -static -bool isTimeAxisUnits(const char *timeunits) -{ - bool status = false; - - size_t len = strlen(timeunits); - char *tu = (char *) Malloc((len+1)*sizeof(char)); - memcpy(tu, timeunits, (len+1) * sizeof(char)); - char *ptu = tu; - - for (size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int)ptu[i]); - - int timeunit = get_timeunit(len, ptu); - if ( timeunit != -1 ) - { - - while ( ! isspace(*ptu) && *ptu != 0 ) ptu++; - if ( *ptu ) - { - while ( isspace(*ptu) ) ptu++; - - int timetype = memcmp(ptu, "as", 2) == 0 ? TAXIS_ABSOLUTE : - memcmp(ptu, "since", 5) == 0 ? TAXIS_RELATIVE : -1; - - status = timetype != -1; - } - } - - Free(tu); - - return status; -} - -static -void scanTimeString(const char *ptu, int *rdate, int *rtime) -{ - int year = 1, month = 1, day = 1; - int hour = 0, minute = 0, second = 0; - int v1 = 1, v2 = 1, v3 = 1; - - *rdate = 0; - *rtime = 0; - - if ( *ptu ) - { - v1 = atoi(ptu); - if ( v1 < 0 ) ptu++; - while ( isdigit((int) *ptu) ) ptu++; - if ( *ptu ) - { - v2 = atoi(++ptu); - while ( isdigit((int) *ptu) ) ptu++; - if ( *ptu ) - { - v3 = atoi(++ptu); - while ( isdigit((int) *ptu) ) ptu++; - } - } - } - - if ( v3 > 999 && v1 < 32 ) - { year = v3; month = v2; day = v1; } - else - { year = v1; month = v2; day = v3; } - - while ( isspace((int) *ptu) ) ptu++; - - if ( *ptu ) - { - while ( ! isdigit((int) *ptu) ) ptu++; - - hour = atoi(ptu); - while ( isdigit((int) *ptu) ) ptu++; - if ( *ptu == ':' ) - { - ptu++; - minute = atoi(ptu); - while ( isdigit((int) *ptu) ) ptu++; - if ( *ptu == ':' ) - { - ptu++; - second = atoi(ptu); - } - } - } - - *rdate = cdiEncodeDate(year, month, day); - *rtime = cdiEncodeTime(hour, minute, second); -} - -static -int scanTimeUnit(const char *unitstr) -{ - size_t len = strlen(unitstr); - int timeunit = get_timeunit(len, unitstr); - if ( timeunit == -1 ) - Message("Unsupported TIMEUNIT: %s!", unitstr); - - return timeunit; -} - -static -void setForecastTime(const char *timestr, taxis_t *taxis) -{ - (*taxis).fdate = 0; - (*taxis).ftime = 0; - - int len = (int) strlen(timestr); - if ( len == 0 ) return; - - int fdate = 0, ftime = 0; - scanTimeString(timestr, &fdate, &ftime); - - (*taxis).fdate = fdate; - (*taxis).ftime = ftime; -} - -static -int setBaseTime(const char *timeunits, taxis_t *taxis) -{ - int timetype = TAXIS_ABSOLUTE; - int rdate = -1, rtime = -1; - - size_t len = strlen(timeunits); - char *tu = (char *) Malloc((len+1) * sizeof (char)); - memcpy(tu, timeunits, (len+1) * sizeof (char)); - char *ptu = tu; - - for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]); - - int timeunit = get_timeunit(len, ptu); - if ( timeunit == -1 ) - { - Message("Unsupported TIMEUNIT: %s!", timeunits); - return (1); - } - - while ( ! isspace(*ptu) && *ptu != 0 ) ptu++; - if ( *ptu ) - { - while ( isspace(*ptu) ) ptu++; - - if ( memcmp(ptu, "as", 2) == 0 ) - timetype = TAXIS_ABSOLUTE; - else if ( memcmp(ptu, "since", 5) == 0 ) - timetype = TAXIS_RELATIVE; - - while ( ! isspace(*ptu) && *ptu != 0 ) ptu++; - if ( *ptu ) - { - while ( isspace(*ptu) ) ptu++; - - if ( timetype == TAXIS_ABSOLUTE ) - { - if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY ) - { - Message("Unsupported format %s for TIMEUNIT day!", ptu); - timeunit = -1; - } - else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH ) - { - Message("Unsupported format %s for TIMEUNIT month!", ptu); - timeunit = -1; - } - } - else if ( timetype == TAXIS_RELATIVE ) - { - scanTimeString(ptu, &rdate, &rtime); - - (*taxis).rdate = rdate; - (*taxis).rtime = rtime; - - if ( CDI_Debug ) - Message("rdate = %d rtime = %d", rdate, rtime); - } - } - } - - (*taxis).type = timetype; - (*taxis).unit = timeunit; - - Free(tu); - - if ( CDI_Debug ) - Message("timetype = %d unit = %d", timetype, timeunit); - - return 0; -} - -static -void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int *attint) -{ - nc_type atttype; - size_t nc_attlen; - - *attint = 0; - - cdf_inq_atttype(fileID, ncvarid, attname, &atttype); - cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen); - - if ( atttype != NC_CHAR ) - { - int *pintatt = (int)nc_attlen > attlen - ? (int *)(Malloc(nc_attlen * sizeof (int))) : attint; - - cdf_get_att_int(fileID, ncvarid, attname, pintatt); - - if ( (int)nc_attlen > attlen ) - { - memcpy(attint, pintatt, (size_t)attlen * sizeof (int)); - Free(pintatt); - } - } -} - -static -void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble) -{ - nc_type atttype; - size_t nc_attlen; - - *attdouble = 0; - - cdf_inq_atttype(fileID, ncvarid, attname, &atttype); - cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen); - - if ( atttype != NC_CHAR ) - { - double *pdoubleatt = NULL; - - if ( (int)nc_attlen > attlen ) - pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double)); - else - pdoubleatt = attdouble; - - cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt); - - if ( (int)nc_attlen > attlen ) - { - memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double)); - Free(pdoubleatt); - } - } -} - -static -void cdfGetAttText(int fileID, int ncvarid,const char *attname, int attlen, char *atttext) -{ - nc_type atttype; - size_t nc_attlen; - - cdf_inq_atttype(fileID, ncvarid, attname, &atttype); - cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen); - - if ( atttype == NC_CHAR ) - { - char attbuf[65636]; - if ( nc_attlen < sizeof(attbuf) ) - { - cdf_get_att_text(fileID, ncvarid, attname, attbuf); - - if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1); - - attbuf[nc_attlen++] = 0; - memcpy(atttext, attbuf, nc_attlen); - } - else - { - atttext[0] = 0; - } - } -#if defined (HAVE_NETCDF4) - else if ( atttype == NC_STRING ) - { - if ( nc_attlen == 1 ) - { - char *attbuf = NULL; - cdf_get_att_string(fileID, ncvarid, attname, &attbuf); - - size_t ssize = strlen(attbuf) + 1; - - if ( ssize > (size_t)attlen ) ssize = (size_t)attlen; - memcpy(atttext, attbuf, ssize); - atttext[ssize - 1] = 0; - Free(attbuf); - } - else - { - atttext[0] = 0; - } - } -#endif -} - -static -int xtypeIsText(int xtype) -{ - int isText = FALSE; - - if ( xtype == NC_CHAR ) - isText = TRUE; -#if defined (HAVE_NETCDF4) - else if ( xtype == NC_STRING ) - isText = TRUE; -#endif - - return isText; -} - -static -int xtypeIsFloat(int xtype) -{ - int isFloat = xtype == NC_FLOAT || xtype == NC_DOUBLE; - return isFloat; -} - -static -int cdfInqDatatype(int xtype, int lunsigned) -{ - int datatype = -1; - -#if defined (HAVE_NETCDF4) - if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE; -#endif - - if ( xtype == NC_BYTE ) datatype = DATATYPE_INT8; - /* else if ( xtype == NC_CHAR ) datatype = DATATYPE_UINT8; */ - else if ( xtype == NC_SHORT ) datatype = DATATYPE_INT16; - else if ( xtype == NC_INT ) datatype = DATATYPE_INT32; - else if ( xtype == NC_FLOAT ) datatype = DATATYPE_FLT32; - else if ( xtype == NC_DOUBLE ) datatype = DATATYPE_FLT64; -#if defined (HAVE_NETCDF4) - else if ( xtype == NC_UBYTE ) datatype = DATATYPE_UINT8; - else if ( xtype == NC_LONG ) datatype = DATATYPE_INT32; - else if ( xtype == NC_USHORT ) datatype = DATATYPE_UINT16; - else if ( xtype == NC_UINT ) datatype = DATATYPE_UINT32; - else if ( xtype == NC_INT64 ) datatype = DATATYPE_FLT64; - else if ( xtype == NC_UINT64 ) datatype = DATATYPE_FLT64; -#endif - - return datatype; -} - - -void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1) -{ - int vlistID1 = streamptr1->vlistID; - int tsID = streamptr1->curTsID; - int vrecID = streamptr1->tsteps[tsID].curRecID; - int recID = streamptr1->tsteps[tsID].recIDs[vrecID]; - int ivarID = streamptr1->tsteps[tsID].records[recID].varID; - int gridID = vlistInqVarGrid(vlistID1, ivarID); - int datasize = gridInqSize(gridID); - int datatype = vlistInqVarDatatype(vlistID1, ivarID); - int memtype = datatype != DATATYPE_FLT32 ? MEMTYPE_DOUBLE : MEMTYPE_FLOAT; - - void *data - = Malloc((size_t)datasize - * (memtype == MEMTYPE_DOUBLE ? sizeof(double) : sizeof(float))); - - int nmiss; - cdf_read_record(streamptr1, memtype, data, &nmiss); - cdf_write_record(streamptr2, memtype, data, nmiss); - - Free(data); -} - -/* not used -int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID) -{ - int tsID, recID; - - recID = streamptr->tsteps[0].curRecID++; - printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID); - printf("cdfInqRecord tsID %d\n", streamptr->curTsID); - - if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs ) - { - streamptr->tsteps[0].curRecID = 0; - } - - *varID = streamptr->tsteps[0].records[recID].varID; - *levelID = streamptr->tsteps[0].records[recID].levelID; - - streamptr->record->varID = *varID; - streamptr->record->levelID = *levelID; - - if ( CDI_Debug ) - Message("recID = %d varID = %d levelID = %d", recID, *varID, *levelID); - - return (recID+1); -} -*/ - - -void cdfDefRecord(stream_t *streamptr) -{ - (void)streamptr; -} - -#if defined(NC_SZIP_NN_OPTION_MASK) -static -void cdfDefVarSzip(int ncid, int ncvarid) -{ - int retval; - /* Set options_mask and bits_per_pixel. */ - int options_mask = NC_SZIP_NN_OPTION_MASK; - int bits_per_pixel = 16; - - if ((retval = nc_def_var_szip(ncid, ncvarid, options_mask, bits_per_pixel))) - { - if ( retval == NC_EINVAL ) - { - static int lwarn = TRUE; - - if ( lwarn ) - { - lwarn = FALSE; - Warning("NetCDF4/Szip compression not compiled in!"); - } - } - else - Error("nc_def_var_szip failed, status = %d", retval); - } -} -#endif - -static -void cdfDefTimeValue(stream_t *streamptr, int tsID) -{ - int fileID = streamptr->fileID; - - if ( CDI_Debug ) - Message("streamID = %d, fileID = %d", streamptr->self, fileID); - - taxis_t *taxis = &streamptr->tsteps[tsID].taxis; - - if ( streamptr->ncmode == 1 ) - { - cdf_enddef(fileID); - streamptr->ncmode = 2; - } - - size_t index = (size_t)tsID; - - double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis); - if ( CDI_Debug ) Message("tsID = %d timevalue = %f", tsID, timevalue); - - int ncvarid = streamptr->basetime.ncvarid; - cdf_put_var1_double(fileID, ncvarid, &index, &timevalue); - - if ( taxis->has_bounds ) - { - size_t start[2], count[2]; - - ncvarid = streamptr->basetime.ncvarboundsid; - - timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis); - start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1; - cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue); - - timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis); - start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1; - cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue); - } - - ncvarid = streamptr->basetime.leadtimeid; - if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID ) - { - timevalue = taxis->fc_period; - cdf_put_var1_double(fileID, ncvarid, &index, &timevalue); - } - - /* -printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue); - */ -} - -static -int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *taxis_name, taxis_t* taxis) -{ - int time_bndsid = -1; - int dims[2]; - - dims[0] = nctimedimid; - - /* fprintf(stderr, "time has bounds\n"); */ - - if ( nc_inq_dimid(fileID, bndsName, &dims[1]) != NC_NOERR ) - cdf_def_dim(fileID, bndsName, 2, &dims[1]); - - const char *bndsAttName, *bndsAttVal; - size_t bndsAttValLen; - char tmpstr[CDI_MAX_NAME]; - if ( taxis->climatology ) - { - static const char climatology_bndsName[] = "climatology_bnds", - climatology_bndsAttName[] = "climatology"; - bndsAttName = climatology_bndsAttName; - bndsAttValLen = sizeof (climatology_bndsName) - 1; - bndsAttVal = climatology_bndsName; - } - else - { - size_t taxisnameLen = strlen(taxis_name); - memcpy(tmpstr, taxis_name, taxisnameLen); - tmpstr[taxisnameLen] = '_'; - memcpy(tmpstr + taxisnameLen + 1, bndsName, sizeof (bndsName)); - size_t tmpstrLen = taxisnameLen + sizeof (bndsName); - static const char generic_bndsAttName[] = "bounds"; - bndsAttName = generic_bndsAttName; - bndsAttValLen = tmpstrLen; - bndsAttVal = tmpstr; - } - cdf_def_var(fileID, bndsAttVal, NC_DOUBLE, 2, dims, &time_bndsid); - cdf_put_att_text(fileID, nctimevarid, bndsAttName, bndsAttValLen, bndsAttVal); - - return (time_bndsid); -} - -static -void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis) -{ - unitstr[0] = 0; - - if ( taxis0->type == TAXIS_ABSOLUTE ) - { - if ( taxis0->unit == TUNIT_YEAR ) - sprintf(unitstr, "year as %s", "%Y.%f"); - else if ( taxis0->unit == TUNIT_MONTH ) - sprintf(unitstr, "month as %s", "%Y%m.%f"); - else - sprintf(unitstr, "day as %s", "%Y%m%d.%f"); - } - else - { - int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR; - int rdate = taxis->rdate; - int rtime = taxis->rtime; - if ( rdate == -1 ) - { - rdate = taxis->vdate; - rtime = taxis->vtime; - } - - int year, month, day, hour, minute, second; - cdiDecodeDate(rdate, &year, &month, &day); - cdiDecodeTime(rtime, &hour, &minute, &second); - - if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE; - if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE; - if ( timeunit == TUNIT_3HOURS || - timeunit == TUNIT_6HOURS || - timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR; - - sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d", - tunitNamePtr(timeunit), year, month, day, hour, minute, second); - } -} - -static -void cdfDefForecastTimeUnits(char *unitstr, int timeunit) -{ - unitstr[0] = 0; - - if ( timeunit == -1 ) timeunit = TUNIT_HOUR; - - if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE; - if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE; - if ( timeunit == TUNIT_3HOURS || - timeunit == TUNIT_6HOURS || - timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR; - - strcpy(unitstr, tunitNamePtr(timeunit)); -} - -static -void cdfDefCalendar(int fileID, int ncvarid, int calendar) -{ - static const struct { int calCode; const char *calStr; } calTab[] = { - { CALENDAR_STANDARD, "standard" }, - { CALENDAR_PROLEPTIC, "proleptic_gregorian" }, - { CALENDAR_NONE, "none" }, - { CALENDAR_360DAYS, "360_day" }, - { CALENDAR_365DAYS, "365_day" }, - { CALENDAR_366DAYS, "366_day" }, - }; - enum { calTabSize = sizeof calTab / sizeof calTab[0] }; - - for (size_t i = 0; i < calTabSize; ++i) - if (calTab[i].calCode == calendar) - { - const char *calstr = calTab[i].calStr; - size_t len = strlen(calstr); - cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr); - break; - } -} - - -void cdfDefTime(stream_t* streamptr) -{ - int time_varid; - int time_dimid; - int time_bndsid = -1; - static const char default_name[] = "time"; - - if ( streamptr->basetime.ncvarid != UNDEFID ) return; - - int fileID = streamptr->fileID; - - if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1; - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - taxis_t *taxis = &streamptr->tsteps[0].taxis; - - const char *taxis_name = (taxis->name && taxis->name[0]) ? taxis->name : default_name ; - - cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid); - streamptr->basetime.ncdimid = time_dimid; - - cdf_def_var(fileID, taxis_name, NC_DOUBLE, 1, &time_dimid, &time_varid); - - streamptr->basetime.ncvarid = time_varid; - - { - static const char timeStr[] = "time"; - cdf_put_att_text(fileID, time_varid, "standard_name", sizeof(timeStr) - 1, timeStr); - } - - if ( taxis->longname && taxis->longname[0] ) - cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname); - - if ( taxis->has_bounds ) - { - time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis); - streamptr->basetime.ncvarboundsid = time_bndsid; - } - - { - char unitstr[CDI_MAX_NAME]; - cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis); - size_t len = strlen(unitstr); - if ( len ) - { - cdf_put_att_text(fileID, time_varid, "units", len, unitstr); - /* - if ( taxis->has_bounds ) - cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr); - */ - } - } - - if ( taxis->calendar != -1 ) - { - cdfDefCalendar(fileID, time_varid, taxis->calendar); - /* - if ( taxis->has_bounds ) - cdfDefCalendar(fileID, time_bndsid, taxis->calendar); - */ - } - - if ( taxis->type == TAXIS_FORECAST ) - { - int leadtimeid; - - cdf_def_var(fileID, "leadtime", NC_DOUBLE, 1, &time_dimid, &leadtimeid); - - streamptr->basetime.leadtimeid = leadtimeid; - - { - static const char stdname[] = "forecast_period"; - cdf_put_att_text(fileID, leadtimeid, "standard_name", sizeof(stdname) - 1, stdname); - } - - { - static const char lname[] = "Time elapsed since the start of the forecast"; - cdf_put_att_text(fileID, leadtimeid, "long_name", sizeof(lname) - 1, lname); - } - - { - char unitstr[CDI_MAX_NAME]; - cdfDefForecastTimeUnits(unitstr, taxis->fc_unit); - size_t len = strlen(unitstr); - if ( len ) - cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr); - } - } - - cdf_put_att_text(fileID, time_varid, "axis", 1, "T"); - - if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); -} - - -void cdfDefTimestep(stream_t *streamptr, int tsID) -{ - int vlistID = streamptr->vlistID; - - if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr); - - cdfDefTimeValue(streamptr, tsID); -} - -static -void cdfDefComplex(stream_t *streamptr, int gridID) -{ - static const char axisname[] = "nc2"; - int dimID = UNDEFID; - int vlistID = streamptr->vlistID; - int fileID = streamptr->fileID; - - int ngrids = vlistNgrids(vlistID); - - for ( int index = 0; index < ngrids; index++ ) - { - if ( streamptr->xdimID[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER ) - { - dimID = streamptr->xdimID[index]; - break; - } - } - } - - if ( dimID == UNDEFID ) - { - size_t dimlen = 2; - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - cdf_def_dim(fileID, axisname, dimlen, &dimID); - - cdf_enddef(fileID); - streamptr->ncmode = 2; - } - - int gridindex = vlistGridIndex(vlistID, gridID); - streamptr->xdimID[gridindex] = dimID; -} - -static void -cdfDefSPorFC(stream_t *streamptr, int gridID, - char *restrict axisname, int gridRefType) -{ - int index, iz = 0; - int dimID = UNDEFID; - - int vlistID = streamptr->vlistID; - - int ngrids = vlistNgrids(vlistID); - - size_t dimlen = (size_t)gridInqSize(gridID)/2; - - for ( index = 0; index < ngrids; index++ ) - { - if ( streamptr->ydimID[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == gridRefType ) - { - size_t dimlen0 = (size_t)gridInqSize(gridID0)/2; - if ( dimlen == dimlen0 ) - { - dimID = streamptr->ydimID[index]; - break; - } - else - iz++; - } - } - } - - if ( dimID == UNDEFID ) - { - int fileID = streamptr->fileID; - if ( iz == 0 ) axisname[3] = '\0'; - else sprintf(&axisname[3], "%1d", iz+1); - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - cdf_def_dim(fileID, axisname, dimlen, &dimID); - - cdf_enddef(fileID); - streamptr->ncmode = 2; - } - - int gridindex = vlistGridIndex(vlistID, gridID); - streamptr->ydimID[gridindex] = dimID; -} - -static -void cdfDefSP(stream_t *streamptr, int gridID) -{ - /* - char longname[] = "Spherical harmonic coefficient"; - */ - char axisname[5] = "nspX"; - cdfDefSPorFC(streamptr, gridID, axisname, GRID_SPECTRAL); -} - - -static -void cdfDefFC(stream_t *streamptr, int gridID) -{ - char axisname[5] = "nfcX"; - cdfDefSPorFC(streamptr, gridID, axisname, GRID_FOURIER); -} - -static const struct cdfDefGridAxisInqs { - int (*axisSize)(int gridID); - void (*axisName)(int gridID, char *dimname); - const char *(*axisNamePtr)(int gridID); - void (*axisStdname)(int gridID, char *dimstdname); - void (*axisLongname)(int gridID, char *dimlongname); - void (*axisUnits)(int gridID, char *dimunits); - double (*axisVal)(int gridID, int index); - const double *(*axisValsPtr)(int gridID); - const double *(*axisBoundsPtr)(int gridID); -} gridInqsX = { - .axisSize = gridInqXsize, - .axisName = gridInqXname, - .axisNamePtr = gridInqXnamePtr, - .axisStdname = gridInqXstdname, - .axisLongname = gridInqXlongname, - .axisUnits = gridInqXunits, - .axisVal = gridInqXval, - .axisValsPtr = gridInqXvalsPtr, - .axisBoundsPtr = gridInqXboundsPtr, -}, gridInqsY = { - .axisSize = gridInqYsize, - .axisName = gridInqYname, - .axisNamePtr = gridInqYnamePtr, - .axisStdname = gridInqYstdname, - .axisLongname = gridInqYlongname, - .axisUnits = gridInqYunits, - .axisVal = gridInqYval, - .axisValsPtr = gridInqYvalsPtr, - .axisBoundsPtr = gridInqYboundsPtr, -}, gridInqsZ = { - .axisStdname = zaxisInqStdname, - .axisLongname = zaxisInqLongname, - .axisUnits = zaxisInqUnits, -}; - -static void -cdfPutGridStdAtts(int fileID, int ncvarid, - int gridID, const struct cdfDefGridAxisInqs *inqs) -{ - size_t len; - { - char stdname[CDI_MAX_NAME]; - inqs->axisStdname(gridID, stdname); - if ( (len = strlen(stdname)) ) - cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname); - } - { - char longname[CDI_MAX_NAME]; - inqs->axisLongname(gridID, longname); - if ( (len = strlen(longname)) ) - cdf_put_att_text(fileID, ncvarid, "long_name", len, longname); - } - { - char units[CDI_MAX_NAME]; - inqs->axisUnits(gridID, units); - if ( (len = strlen(units)) ) - cdf_put_att_text(fileID, ncvarid, "units", len, units); - } -} - -static void -cdfDefTrajLatLon(stream_t *streamptr, int gridID, - const struct cdfDefGridAxisInqs *inqs, - int *dimID, const char *sizeName) -{ - nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE; - - int vlistID = streamptr->vlistID; - int dimlen = inqs->axisSize(gridID); - if ( dimlen != 1 ) - Error("%s isn't 1 for %s grid!", sizeName, gridNamePtr(gridInqType(gridID))); - - int gridindex = vlistGridIndex(vlistID, gridID); - int ncvarid = dimID[gridindex]; - - if ( ncvarid == UNDEFID ) - { - int dimNcID = streamptr->basetime.ncvarid; - int fileID = streamptr->fileID; - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - const char *axisname = inqs->axisNamePtr(gridID); - cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid); - cdfPutGridStdAtts(fileID, ncvarid, gridID, inqs); - cdf_enddef(fileID); - streamptr->ncmode = 2; - } - - dimID[gridindex] = ncvarid; /* var ID for trajectory !!! */ -} - -static -void cdfDefTrajLon(stream_t *streamptr, int gridID) -{ - cdfDefTrajLatLon(streamptr, gridID, &gridInqsX, streamptr->xdimID, "Xsize"); -} - - -static -void cdfDefTrajLat(stream_t *streamptr, int gridID) -{ - cdfDefTrajLatLon(streamptr, gridID, &gridInqsY, streamptr->ydimID, "Ysize"); -} - -static -int checkDimName(int fileID, size_t dimlen, char *dimname) -{ - /* check whether the dimenion name is already defined with the same length */ - unsigned iz = 0; - int dimid = UNDEFID; - char name[CDI_MAX_NAME]; - - size_t len = strlen(dimname); - memcpy(name, dimname, len + 1); - - do - { - if ( iz ) sprintf(name + len, "_%u", iz+1); - - int dimid0, status = nc_inq_dimid(fileID, name, &dimid0); - if ( status != NC_NOERR ) - break; - size_t dimlen0; - cdf_inq_dimlen(fileID, dimid0, &dimlen0); - if ( dimlen0 == dimlen ) - { - dimid = dimid0; - break; - } - iz++; - } - while ( iz <= 99 ); - - - if ( iz ) sprintf(dimname + len, "_%u", iz+1); - - return dimid; -} - -static -void checkGridName(char *axisname, int fileID, int vlistID, int gridID, int ngrids, int mode) -{ - int ncdimid; - char axisname2[CDI_MAX_NAME]; - - /* check that the name is not already defined */ - unsigned iz = 0; - - size_t axisnameLen = strlen(axisname); - memcpy(axisname2, axisname, axisnameLen + 1); - do - { - if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1); - - int status = nc_inq_varid(fileID, axisname2, &ncdimid); - - if ( status != NC_NOERR ) - { - if ( iz ) - { - /* check that the name does not exist for other grids */ - for ( int index = 0; index < ngrids; index++ ) - { - int gridID0 = vlistGrid(vlistID, index); - if ( gridID != gridID0 ) - { - /* mode X or Y */ - const char *(*query)(int) - = mode == 'X' ? gridInqXnamePtr : gridInqYnamePtr; - const char *axisname0 = query(gridID0); - if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix; - } - } - } - break; - } - nextSuffix: - ++iz; - } - while ( iz <= 99 ); - - - if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1); -} - -static -int checkZaxisName(char *axisname, int fileID, int vlistID, int zaxisID, int nzaxis) -{ - char axisname2[CDI_MAX_NAME]; - - /* check that the name is not already defined */ - unsigned iz = 0; - - size_t axisnameLen = strlen(axisname); - memcpy(axisname2, axisname, axisnameLen + 1); - do - { - if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1); - - int ncdimid, status = nc_inq_varid(fileID, axisname2, &ncdimid); - - if ( status != NC_NOERR ) - { - if ( iz ) - { - /* check that the name does not exist for other zaxes */ - for ( int index = 0; index < nzaxis; index++ ) - { - int zaxisID0 = vlistZaxis(vlistID, index); - if ( zaxisID != zaxisID0 ) - { - const char *axisname0 = zaxisInqNamePtr(zaxisID0); - if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix; - } - } - } - break; - } - nextSuffix: - ++iz; - } - while (iz <= 99); - - - if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1); - - return (int)iz; -} - -static void -cdfDefAxisCommon(stream_t *streamptr, int gridID, int ndims, - const struct cdfDefGridAxisInqs *gridAxisInq, - int *axisDimIDs, int dimKey, char axisLetter, - void (*finishCyclicBounds)(double *pbounds, size_t dimlen, - const double *pvals), - int *ncAxisVarIDs) -{ - int dimID = UNDEFID; - int ngrids = 0; - int ncvarid = UNDEFID, ncbvarid = UNDEFID; - int nvdimID = UNDEFID; - nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE; - - int vlistID = streamptr->vlistID; - int fileID = streamptr->fileID; - - if ( ndims ) ngrids = vlistNgrids(vlistID); - - size_t dimlen = (size_t)gridAxisInq->axisSize(gridID); - int gridindex = vlistGridIndex(vlistID, gridID); - - const char *axisname = gridAxisInq->axisNamePtr(gridID); - size_t axisnameLen = strlen(axisname); - - if ( axisname[0] == 0 ) Error("axis name undefined!"); - - for ( int index = 0; index < ngrids; index++ ) - { - if ( axisDimIDs[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == GRID_GAUSSIAN || - gridtype0 == GRID_LONLAT || - gridtype0 == GRID_CURVILINEAR || - gridtype0 == GRID_GENERIC ) - { - size_t dimlen0 = (size_t)gridAxisInq->axisSize(gridID0); - if ( dimlen == dimlen0 ) - { - double (*inqVal)(int gridID, int index) - = gridAxisInq->axisVal; - if ( IS_EQUAL(inqVal(gridID0, 0), inqVal(gridID, 0)) && - IS_EQUAL(inqVal(gridID0, (int)dimlen-1), inqVal(gridID, (int)dimlen-1)) ) - { - dimID = axisDimIDs[index]; - break; - } - } - } - } - } - - if ( dimID == UNDEFID ) - { - const double *pvals = gridAxisInq->axisValsPtr(gridID); - - /* enough to append _ plus up to 100 decimal and trailing \0 */ - char extendedAxisname[axisnameLen + 4 + 1]; - memcpy(extendedAxisname, axisname, axisnameLen + 1); - checkGridName(extendedAxisname, fileID, vlistID, gridID, ngrids, axisLetter); - size_t extendedAxisnameLen - = axisnameLen + strlen(extendedAxisname + axisnameLen); - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - if ( ndims ) - { - char dimname[CDI_MAX_NAME+3]; - dimname[0] = 0; - - if ( pvals == NULL ) - cdiGridInqString(gridID, dimKey, CDI_MAX_NAME, dimname); - - if ( dimname[0] == 0 ) strcpy(dimname, extendedAxisname); - dimID = checkDimName(fileID, dimlen, dimname); - - if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID); - } - - bool gen_bounds = false; - int grid_is_cyclic = gridIsCircular(gridID); - double *pbounds = NULL; - if ( pvals ) - { - cdf_def_var(fileID, extendedAxisname, xtype, ndims, &dimID, &ncvarid); - - cdfPutGridStdAtts(fileID, ncvarid, gridID, gridAxisInq); - { - char axisStr[2] = { axisLetter, '\0' }; - cdf_put_att_text(fileID, ncvarid, "axis", 1, axisStr); - } - - pbounds = (double *)gridAxisInq->axisBoundsPtr(gridID); - - if ( CDI_cmor_mode && grid_is_cyclic && !pbounds ) - { - gen_bounds = true; - pbounds = (double*) Malloc(2*dimlen*sizeof(double)); - for ( size_t i = 0; i < dimlen-1; ++i ) - { - pbounds[i*2+1] = (pvals[i] + pvals[i+1])/2; - pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2; - } - finishCyclicBounds(pbounds, dimlen, pvals); - } - if ( pbounds ) - { - size_t nvertex = 2; - if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR ) - cdf_def_dim(fileID, bndsName, nvertex, &nvdimID); - } - if ( pbounds && nvdimID != UNDEFID ) - { - char boundsname[extendedAxisnameLen + 1 + sizeof (bndsName)]; - memcpy(boundsname, axisname, extendedAxisnameLen); - boundsname[extendedAxisnameLen] = '_'; - memcpy(boundsname + extendedAxisnameLen + 1, bndsName, sizeof bndsName); - int dimIDs[2] = { dimID, nvdimID }; - cdf_def_var(fileID, boundsname, xtype, 2, dimIDs, &ncbvarid); - cdf_put_att_text(fileID, ncvarid, "bounds", extendedAxisnameLen + sizeof (bndsName), boundsname); - } - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals); - if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds); - if ( gen_bounds ) Free(pbounds); - - if ( ndims == 0 ) ncAxisVarIDs[gridindex] = ncvarid; - } - - axisDimIDs[gridindex] = dimID; -} - -static void -finishCyclicXBounds(double *pbounds, size_t dimlen, const double *pvals) -{ - pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)*0.5; - pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)*0.5; -} - -static -void cdfDefXaxis(stream_t *streamptr, int gridID, int ndims) -{ - cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsX, streamptr->xdimID, - CDI_GRID_XDIMNAME, 'X', finishCyclicXBounds, - streamptr->ncxvarID); -} - -static void -finishCyclicYBounds(double *pbounds, size_t dimlen, const double *pvals) -{ - pbounds[0] = copysign(90.0, pvals[0]); - pbounds[2*dimlen-1] = copysign(90.0, pvals[dimlen-1]); -} - -static -void cdfDefYaxis(stream_t *streamptr, int gridID, int ndims) -{ - cdfDefAxisCommon(streamptr, gridID, ndims, &gridInqsY, streamptr->ydimID, - CDI_GRID_YDIMNAME, 'Y', finishCyclicYBounds, - streamptr->ncyvarID); -} - -static -void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int comptype) -{ -#if defined (HAVE_NETCDF4) - if ( gridsize > 1 && comptype == COMPRESS_ZIP && (filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C) ) - { - nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL); - cdfDefVarDeflate(fileID, ncvarid, 1); - } -#endif -} - -static -void cdfDefCurvilinear(stream_t *streamptr, int gridID) -{ - int xdimID = UNDEFID; - int ydimID = UNDEFID; - int ncxvarid = UNDEFID, ncyvarid = UNDEFID; - int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID; - nc_type xtype = gridInqPrec(gridID) == DATATYPE_FLT32 ? NC_FLOAT : NC_DOUBLE; - - int vlistID = streamptr->vlistID; - int fileID = streamptr->fileID; - - int ngrids = vlistNgrids(vlistID); - - size_t dimlen = (size_t)gridInqSize(gridID); - size_t xdimlen = (size_t)gridInqXsize(gridID); - size_t ydimlen = (size_t)gridInqYsize(gridID); - int gridindex = vlistGridIndex(vlistID, gridID); - - for ( int index = 0; index < ngrids; index++ ) - { - if ( streamptr->xdimID[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == GRID_CURVILINEAR ) - { - size_t dimlen0 = (size_t)gridInqSize(gridID0); - if ( dimlen == dimlen0 ) - if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) && - IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) && - IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) && - IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) ) - { - xdimID = streamptr->xdimID[index]; - ydimID = streamptr->ydimID[index]; - ncxvarid = streamptr->ncxvarID[index]; - ncyvarid = streamptr->ncyvarID[index]; - break; - } - } - } - } - - if ( xdimID == UNDEFID || ydimID == UNDEFID ) - { - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - { - char xdimname[CDI_MAX_NAME+3]; - xdimname[0] = 0; - cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname); - if ( xdimname[0] == 0 ) { xdimname[0] = 'x'; xdimname[1] = 0; } - xdimID = checkDimName(fileID, xdimlen, xdimname); - if ( xdimID == UNDEFID ) cdf_def_dim(fileID, xdimname, xdimlen, &xdimID); - } - { - char ydimname[CDI_MAX_NAME+3]; - ydimname[0] = 0; - cdiGridInqString(gridID, CDI_GRID_YDIMNAME, CDI_MAX_NAME, ydimname); - if ( ydimname[0] == 0 ) { ydimname[0] = 'y'; ydimname[1] = 0; } - ydimID = checkDimName(fileID, ydimlen, ydimname); - if ( ydimID == UNDEFID ) cdf_def_dim(fileID, ydimname, ydimlen, &ydimID); - } - - int nvdimID = UNDEFID; - int dimIDs[3]; - if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) ) - { - char vdimname[CDI_MAX_NAME+3]; - vdimname[0] = 0; - cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname); - if ( vdimname[0] == 0 ) strcpy(vdimname, "nv4"); - size_t nvertex = 4; - nvdimID = checkDimName(fileID, nvertex, vdimname); - if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID); - } - - dimIDs[0] = ydimID; - dimIDs[1] = xdimID; - dimIDs[2] = nvdimID; - - if ( gridInqXvalsPtr(gridID) ) - { - char xaxisname[CDI_MAX_NAME]; - gridInqXname(gridID, xaxisname); - checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X'); - - cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid); - cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); - - cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX); - - /* attribute for Panoply */ - cdf_put_att_text(fileID, ncxvarid, "_CoordinateAxisType", 3, "Lon"); - - if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID ) - { - size_t xaxisnameLen = strlen(xaxisname); - xaxisname[xaxisnameLen] = '_'; - memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName)); - cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid); - cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); - - cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname); - } - } - - if ( gridInqYvalsPtr(gridID) ) - { - char yaxisname[CDI_MAX_NAME]; - gridInqYname(gridID, yaxisname); - checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y'); - - cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid); - cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); - - cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY); - - /* attribute for Panoply */ - cdf_put_att_text(fileID, ncyvarid, "_CoordinateAxisType", 3, "Lat"); - - if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID ) - { - size_t yaxisnameLen = strlen(yaxisname); - yaxisname[yaxisnameLen] = '_'; - memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName)); - cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid); - cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); - - cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname); - } - } - - if ( gridInqAreaPtr(gridID) ) - { - static const char yaxisname_[] = "cell_area"; - static const char units[] = "m2"; - static const char longname[] = "area of grid cell"; - static const char stdname[] = "cell_area"; - - cdf_def_var(fileID, yaxisname_, xtype, 2, dimIDs, &ncavarid); - - cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname); - cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname); - cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units); - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - if ( ncxvarid != UNDEFID ) cdf_put_var_double(fileID, ncxvarid, gridInqXvalsPtr(gridID)); - if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID)); - if ( ncyvarid != UNDEFID ) cdf_put_var_double(fileID, ncyvarid, gridInqYvalsPtr(gridID)); - if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID)); - if ( ncavarid != UNDEFID ) cdf_put_var_double(fileID, ncavarid, gridInqAreaPtr(gridID)); - } - - streamptr->xdimID[gridindex] = xdimID; - streamptr->ydimID[gridindex] = ydimID; - streamptr->ncxvarID[gridindex] = ncxvarid; - streamptr->ncyvarID[gridindex] = ncyvarid; - streamptr->ncavarID[gridindex] = ncavarid; -} - -static -void cdfDefRgrid(stream_t *streamptr, int gridID) -{ - int dimID = UNDEFID; - - int vlistID = streamptr->vlistID; - int ngrids = vlistNgrids(vlistID); - - size_t dimlen = (size_t)gridInqSize(gridID); - - int iz = 0; - for ( int index = 0; index < ngrids; index++ ) - { - if ( streamptr->xdimID[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == GRID_GAUSSIAN_REDUCED ) - { - size_t dimlen0 = (size_t)gridInqSize(gridID0); - - if ( dimlen == dimlen0 ) - { - dimID = streamptr->xdimID[index]; - break; - } - iz++; - } - } - } - - if ( dimID == UNDEFID ) - { - int fileID = streamptr->fileID; - static bool lwarn = true; - if ( lwarn ) - { - Warning("Creating a NetCDF file with data on a gaussian reduced grid."); - Warning("The further processing of the resulting file is unsupported!"); - lwarn = false; - } - - char axisname[7] = "rgridX"; - if ( iz == 0 ) axisname[5] = '\0'; - else sprintf(&axisname[5], "%1d", iz+1); - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - cdf_def_dim(fileID, axisname, dimlen, &dimID); - - cdf_enddef(fileID); - streamptr->ncmode = 2; - } - - int gridindex = vlistGridIndex(vlistID, gridID); - streamptr->xdimID[gridindex] = dimID; -} - -static -void cdfDefGdim(stream_t *streamptr, int gridID) -{ - int iz = 0; - int dimID = UNDEFID; - - int vlistID = streamptr->vlistID; - int ngrids = vlistNgrids(vlistID); - - size_t dimlen = (size_t)gridInqSize(gridID); - - if ( gridInqYsize(gridID) == 0 ) - for ( int index = 0; index < ngrids; index++ ) - { - if ( streamptr->xdimID[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == GRID_GENERIC ) - { - size_t dimlen0 = (size_t)gridInqSize(gridID0); - if ( dimlen == dimlen0 ) - { - dimID = streamptr->xdimID[index]; - break; - } - else - iz++; - } - } - } - - if ( gridInqXsize(gridID) == 0 ) - for ( int index = 0; index < ngrids; index++ ) - { - if ( streamptr->ydimID[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == GRID_GENERIC ) - { - size_t dimlen0 = (size_t)gridInqSize(gridID0); - if ( dimlen == dimlen0 ) - { - dimID = streamptr->ydimID[index]; - break; - } - else - iz++; - } - } - } - - if ( dimID == UNDEFID ) - { - int fileID = streamptr->fileID; - char dimname[CDI_MAX_NAME]; - strcpy(dimname, "gsize"); - - dimID = checkDimName(fileID, dimlen, dimname); - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID); - - cdf_enddef(fileID); - streamptr->ncmode = 2; - } - - int gridindex = vlistGridIndex(vlistID, gridID); - streamptr->xdimID[gridindex] = dimID; -} - -static -void cdfDefGridReference(stream_t *streamptr, int gridID) -{ - int fileID = streamptr->fileID; - int number = gridInqNumber(gridID); - - if ( number > 0 ) - { - cdf_put_att_int(fileID, NC_GLOBAL, "number_of_grid_used", NC_INT, 1, &number); - } - - const char *gridfile = gridInqReferencePtr(gridID); - if ( gridfile && gridfile[0] != 0 ) - cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile); -} - -static -void cdfDefGridUUID(stream_t *streamptr, int gridID) -{ - unsigned char uuidOfHGrid[CDI_UUID_SIZE]; - - gridInqUUID(gridID, uuidOfHGrid); - if ( !cdiUUIDIsNull(uuidOfHGrid) ) - { - char uuidOfHGridStr[37]; - cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr); - if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 ) - { - int fileID = streamptr->fileID; - //if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfHGrid", 36, uuidOfHGridStr); - //if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); - } - } -} - -static -void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID) -{ - unsigned char uuidOfVGrid[CDI_UUID_SIZE]; - zaxisInqUUID(zaxisID, uuidOfVGrid); - - if ( uuidOfVGrid[0] != 0 ) - { - char uuidOfVGridStr[37]; - cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr); - if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 ) - { - int fileID = streamptr->fileID; - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfVGrid", 36, uuidOfVGridStr); - if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); - } - } -} - -static -void cdfDefUnstructured(stream_t *streamptr, int gridID) -{ - int dimID = UNDEFID; - int ncxvarid = UNDEFID, ncyvarid = UNDEFID; - int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID; - int nvdimID = UNDEFID; - nc_type xtype = NC_DOUBLE; - - if ( gridInqPrec(gridID) == DATATYPE_FLT32 ) xtype = NC_FLOAT; - - int vlistID = streamptr->vlistID; - int fileID = streamptr->fileID; - - int ngrids = vlistNgrids(vlistID); - - size_t dimlen = (size_t)gridInqSize(gridID); - int gridindex = vlistGridIndex(vlistID, gridID); - - for ( int index = 0; index < ngrids; index++ ) - { - if ( streamptr->xdimID[index] != UNDEFID ) - { - int gridID0 = vlistGrid(vlistID, index); - int gridtype0 = gridInqType(gridID0); - if ( gridtype0 == GRID_UNSTRUCTURED ) - { - size_t dimlen0 = (size_t)gridInqSize(gridID0); - if ( dimlen == dimlen0 ) - if ( gridInqNvertex(gridID0) == gridInqNvertex(gridID) && - IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) && - IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) && - IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) && - IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) ) - { - dimID = streamptr->xdimID[index]; - ncxvarid = streamptr->ncxvarID[index]; - ncyvarid = streamptr->ncyvarID[index]; - ncavarid = streamptr->ncavarID[index]; - break; - } - } - } - } - - if ( dimID == UNDEFID ) - { - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - { - char xdimname[CDI_MAX_NAME+3]; - xdimname[0] = 0; - cdiGridInqString(gridID, CDI_GRID_XDIMNAME, CDI_MAX_NAME, xdimname); - if ( xdimname[0] == 0 ) strcpy(xdimname, "ncells"); - dimID = checkDimName(fileID, dimlen, xdimname); - if ( dimID == UNDEFID ) cdf_def_dim(fileID, xdimname, dimlen, &dimID); - } - - size_t nvertex = (size_t)gridInqNvertex(gridID); - if ( nvertex > 0 ) - { - char vdimname[CDI_MAX_NAME+3]; - vdimname[0] = 0; - cdiGridInqString(gridID, CDI_GRID_VDIMNAME, CDI_MAX_NAME, vdimname); - if ( vdimname[0] == 0 ) strcpy(vdimname, "vertices"); - nvdimID = checkDimName(fileID, nvertex, vdimname); - if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID); - } - - cdfDefGridReference(streamptr, gridID); - - cdfDefGridUUID(streamptr, gridID); - - if ( gridInqXvalsPtr(gridID) ) - { - char xaxisname[CDI_MAX_NAME]; - gridInqXname(gridID, xaxisname); - checkGridName(xaxisname, fileID, vlistID, gridID, ngrids, 'X'); - cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid); - cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); - - cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX); - - if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID ) - { - int dimIDs[2] = { dimID, nvdimID }; - size_t xaxisnameLen = strlen(xaxisname); - xaxisname[xaxisnameLen] = '_'; - memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName)); - cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid); - cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); - - cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname); - } - } - - if ( gridInqYvalsPtr(gridID) ) - { - char yaxisname[CDI_MAX_NAME]; - gridInqYname(gridID, yaxisname); - checkGridName(yaxisname, fileID, vlistID, gridID, ngrids, 'Y'); - cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid); - cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); - - cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY); - - if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID ) - { - int dimIDs[2] = { dimID, nvdimID }; - size_t yaxisnameLen = strlen(yaxisname); - yaxisname[yaxisnameLen] = '_'; - memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName)); - cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid); - cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); - - cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname); - } - } - - if ( gridInqAreaPtr(gridID) ) - { - static const char yaxisname_[] = "cell_area"; - static const char units[] = "m2"; - static const char longname[] = "area of grid cell"; - static const char stdname[] = "cell_area"; - - cdf_def_var(fileID, yaxisname_, xtype, 1, &dimID, &ncavarid); - - cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname); - cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname); - cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units); - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - if ( ncxvarid != UNDEFID ) cdf_put_var_double(fileID, ncxvarid, gridInqXvalsPtr(gridID)); - if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID)); - if ( ncyvarid != UNDEFID ) cdf_put_var_double(fileID, ncyvarid, gridInqYvalsPtr(gridID)); - if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID)); - if ( ncavarid != UNDEFID ) cdf_put_var_double(fileID, ncavarid, gridInqAreaPtr(gridID)); - } - - streamptr->xdimID[gridindex] = dimID; - streamptr->ncxvarID[gridindex] = ncxvarid; - streamptr->ncyvarID[gridindex] = ncyvarid; - streamptr->ncavarID[gridindex] = ncavarid; -} - -struct attTxtTab2 -{ - const char *attName, *attVal; - size_t valLen; -}; - -static -void cdf_def_vct_echam(stream_t *streamptr, int zaxisID) -{ - int type = zaxisInqType(zaxisID); - - if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF ) - { - int ilev = zaxisInqVctSize(zaxisID)/2; - if ( ilev == 0 ) return; - - int mlev = ilev - 1; - size_t start; - size_t count = 1; - int ncdimid, ncdimid2; - int hyaiid, hybiid, hyamid, hybmid; - double mval; - - if ( streamptr->vct.ilev > 0 ) - { - if ( streamptr->vct.ilev != ilev ) - Error("more than one VCT for each file unsupported!"); - return; - } - - int fileID = streamptr->fileID; - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - cdf_def_dim(fileID, "nhym", (size_t)mlev, &ncdimid); - cdf_def_dim(fileID, "nhyi", (size_t)ilev, &ncdimid2); - - streamptr->vct.mlev = mlev; - streamptr->vct.ilev = ilev; - streamptr->vct.mlevID = ncdimid; - streamptr->vct.ilevID = ncdimid2; - - cdf_def_var(fileID, "hyai", NC_DOUBLE, 1, &ncdimid2, &hyaiid); - cdf_def_var(fileID, "hybi", NC_DOUBLE, 1, &ncdimid2, &hybiid); - cdf_def_var(fileID, "hyam", NC_DOUBLE, 1, &ncdimid, &hyamid); - cdf_def_var(fileID, "hybm", NC_DOUBLE, 1, &ncdimid, &hybmid); - - { - static const char lname_n[] = "long_name", - lname_v_ai[] = "hybrid A coefficient at layer interfaces", - units_n[] = "units", - units_v_ai[] = "Pa", - lname_v_bi[] = "hybrid B coefficient at layer interfaces", - units_v_bi[] = "1", - lname_v_am[] = "hybrid A coefficient at layer midpoints", - units_v_am[] = "Pa", - lname_v_bm[] = "hybrid B coefficient at layer midpoints", - units_v_bm[] = "1"; - static const struct attTxtTab2 tab[] - = { - { lname_n, lname_v_ai, sizeof (lname_v_ai) - 1 }, - { units_n, units_v_ai, sizeof (units_v_ai) - 1 }, - { lname_n, lname_v_bi, sizeof (lname_v_bi) - 1 }, - { units_n, units_v_bi, sizeof (units_v_bi) - 1 }, - { lname_n, lname_v_am, sizeof (lname_v_am) - 1 }, - { units_n, units_v_am, sizeof (units_v_am) - 1 }, - { lname_n, lname_v_bm, sizeof (lname_v_bm) - 1 }, - { units_n, units_v_bm, sizeof (units_v_bm) - 1 }, - }; - enum { tabLen = sizeof (tab) / sizeof (tab[0]) }; - int ids[tabLen] = { hyaiid, hyaiid, hybiid, hybiid, - hyamid, hyamid, hybmid, hybmid }; - for ( size_t i = 0; i < tabLen; ++i ) - cdf_put_att_text(fileID, ids[i], tab[i].attName, tab[i].valLen, tab[i].attVal); - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - const double *vctptr = zaxisInqVctPtr(zaxisID); - - cdf_put_var_double(fileID, hyaiid, vctptr); - cdf_put_var_double(fileID, hybiid, vctptr+ilev); - - for ( int i = 0; i < mlev; i++ ) - { - start = (size_t)i; - mval = (vctptr[i] + vctptr[i+1]) * 0.5; - cdf_put_vara_double(fileID, hyamid, &start, &count, &mval); - mval = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5; - cdf_put_vara_double(fileID, hybmid, &start, &count, &mval); - } - } -} - -static -void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID) -{ - int type = zaxisInqType(zaxisID); - - if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF ) - { - int ilev = zaxisInqVctSize(zaxisID)/2; - if ( ilev == 0 ) return; - - int mlev = ilev - 1; - int hyaiid = 0, hybiid = 0, hyamid, hybmid; - - if ( streamptr->vct.ilev > 0 ) - { - if ( streamptr->vct.ilev != ilev ) - Error("more than one VCT for each file unsupported!"); - return; - } - - int fileID = streamptr->fileID; - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - int dimIDs[2]; - dimIDs[0] = nclevID; - dimIDs[1] = ncbndsID; - - streamptr->vct.mlev = mlev; - streamptr->vct.ilev = ilev; - streamptr->vct.mlevID = nclevID; - streamptr->vct.ilevID = nclevID; - - cdf_def_var(fileID, "ap", NC_DOUBLE, 1, dimIDs, &hyamid); - cdf_def_var(fileID, "b", NC_DOUBLE, 1, dimIDs, &hybmid); - - { - static const char lname[] = "vertical coordinate formula term: ap(k)"; - cdf_put_att_text(fileID, hyamid, "long_name", sizeof (lname) - 1, lname); - } - { - static const char units[] = "Pa"; - cdf_put_att_text(fileID, hyamid, "units", sizeof (units) - 1, units); - } - { - static const char lname[] = "vertical coordinate formula term: b(k)"; - cdf_put_att_text(fileID, hybmid, "long_name", sizeof (lname) - 1, lname); - } - { - static const char units[] = "1"; - cdf_put_att_text(fileID, hybmid, "units", sizeof (units) - 1, units); - } - - if ( ncbndsID != -1 ) - { - cdf_def_var(fileID, "ap_bnds", NC_DOUBLE, 2, dimIDs, &hyaiid); - cdf_def_var(fileID, "b_bnds", NC_DOUBLE, 2, dimIDs, &hybiid); - { - static const char lname[] = "vertical coordinate formula term: ap(k+1/2)"; - cdf_put_att_text(fileID, hyaiid, "long_name", sizeof (lname) - 1, lname); - } - { - static const char units[] = "Pa"; - cdf_put_att_text(fileID, hyaiid, "units", sizeof (units) - 1, units); - } - { - static const char lname[] = "vertical coordinate formula term: b(k+1/2)"; - cdf_put_att_text(fileID, hybiid, "long_name", sizeof (lname) - 1, lname); - } - { - static const char units[] = "1"; - cdf_put_att_text(fileID, hybiid, "units", sizeof (units) - 1, units); - } - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - const double *vctptr = zaxisInqVctPtr(zaxisID); - double tarray[ilev*2]; - - if ( ncbndsID != -1 ) - { - for ( int i = 0; i < mlev; ++i ) - { - tarray[2*i ] = vctptr[i]; - tarray[2*i+1] = vctptr[i+1]; - } - cdf_put_var_double(fileID, hyaiid, tarray); - - for ( int i = 0; i < mlev; ++i ) - { - tarray[2*i ] = vctptr[ilev+i]; - tarray[2*i+1] = vctptr[ilev+i+1]; - } - cdf_put_var_double(fileID, hybiid, tarray); - } - - for ( int i = 0; i < mlev; ++i ) - tarray[i] = (vctptr[i] + vctptr[i+1]) * 0.5; - cdf_put_var_double(fileID, hyamid, tarray); - - for ( int i = 0; i < mlev; ++i ) - tarray[i] = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5; - cdf_put_var_double(fileID, hybmid, tarray); - } -} - -struct attTxtTab { const char *txt; size_t txtLen; }; - -static -void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname) -{ - int fileID = streamptr->fileID; - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - cdf_def_dim(fileID, axisname, dimlen, dimID); - cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID, &ncvarid); - - { - static const char sname[] = "hybrid_sigma_pressure"; - cdf_put_att_text(fileID, ncvarid, "standard_name", sizeof (sname) - 1, sname); - } - { - static const char *attName[] = { - "long_name", - "formula", - "formula_terms" - }; - enum { nAtt = sizeof (attName) / sizeof (attName[0]) }; - static const char lname_m[] = "hybrid level at layer midpoints", - formula_m[] = "hyam hybm (mlev=hyam+hybm*aps)", - fterms_m[] = "ap: hyam b: hybm ps: aps", - lname_i[] = "hybrid level at layer interfaces", - formula_i[] = "hyai hybi (ilev=hyai+hybi*aps)", - fterms_i[] = "ap: hyai b: hybi ps: aps"; - static const struct attTxtTab tab[2][nAtt] = { - { - { lname_i, sizeof (lname_i) - 1 }, - { formula_i, sizeof (formula_i) - 1 }, - { fterms_i, sizeof (fterms_i) - 1 } - }, - { - { lname_m, sizeof (lname_m) - 1 }, - { formula_m, sizeof (formula_m) - 1 }, - { fterms_m, sizeof (fterms_m) - 1 } - } - }; - - size_t tabSelect = type == ZAXIS_HYBRID; - for (size_t i = 0; i < nAtt; ++i) - cdf_put_att_text(fileID, ncvarid, attName[i], - tab[tabSelect][i].txtLen, tab[tabSelect][i].txt); - } - - { - static const char units[] = "level"; - cdf_put_att_text(fileID, ncvarid, "units", sizeof (units) - 1, units); - } - { - static const char direction[] = "down"; - cdf_put_att_text(fileID, ncvarid, "positive", sizeof (direction) - 1, direction); - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID)); - - cdf_def_vct_echam(streamptr, zaxisID); - - if ( *dimID == UNDEFID ) - { - if ( type == ZAXIS_HYBRID ) - streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID; - else - streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID; - } -} - -static -void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname) -{ - char psname[CDI_MAX_NAME]; - psname[0] = 0; - zaxisInqPsName(zaxisID, psname); - if ( psname[0] == 0 ) strcpy(psname, "ps"); - - int fileID = streamptr->fileID; - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - strcpy(axisname, "lev"); - - cdf_def_dim(fileID, axisname, dimlen, dimID); - cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID, &ncvarid); - - { - static const char sname[] = "standard_name", - sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate", - lname[] = "long_name", - lname_v[] = "hybrid sigma pressure coordinate", - formula[] = "formula", - formula_v[] = "p = ap + b*ps", - fterms[] = "formula_terms", - fterms_v[] = "ap: ap b: b ps: ", - units[] = "units", - units_v[] = "1", - axis[] = "axis", - axis_v[] = "Z", - direction[] = "positive", - direction_v[] = "down"; - struct attTxtTab2 tab[] = { - { sname, sname_v, sizeof (sname_v) - 1 }, - { lname, lname_v, sizeof (lname_v) - 1 }, - { formula, formula_v, sizeof (formula_v) - 1 }, - { fterms, fterms_v, sizeof (fterms_v) - 1 }, - { units, units_v, sizeof (units_v) - 1 }, - { axis, axis_v, sizeof (axis_v) - 1 }, - { direction, direction_v, sizeof (direction_v) - 1 }, - }; - enum { nAtt = sizeof (tab) / sizeof (tab[0]) }; - for (size_t i = 0; i < nAtt; ++i) - cdf_put_att_text(fileID, ncvarid, tab[i].attName, tab[i].valLen, tab[i].attVal); - } - - int ncbvarid = UNDEFID; - int nvdimID = UNDEFID; - - double lbounds[dimlen], ubounds[dimlen], levels[dimlen]; - - zaxisInqLevels(zaxisID, levels); - - if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - zaxisInqLbounds(zaxisID, lbounds); - zaxisInqUbounds(zaxisID, ubounds); - } - else - { - for ( size_t i = 0; i < dimlen; ++i ) lbounds[i] = levels[i]; - for ( size_t i = 0; i < dimlen-1; ++i ) ubounds[i] = levels[i+1]; - ubounds[dimlen-1] = levels[dimlen-1] + 1; - } - - //if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - size_t nvertex = 2; - if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR ) - cdf_def_dim(fileID, bndsName, nvertex, &nvdimID); - - if ( nvdimID != UNDEFID ) - { - size_t axisnameLen = strlen(axisname); - axisname[axisnameLen] = '_'; - memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName)); - axisnameLen += sizeof (bndsName); - int dimIDs[2] = { *dimID, nvdimID }; - cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid); - cdf_put_att_text(fileID, ncvarid, "bounds", axisnameLen, axisname); - { - static const char sname[] = "standard_name", - sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate", - formula[] = "formula", - formula_v[] = "p = ap + b*ps"; - struct attTxtTab2 tab[] = { - { sname, sname_v, sizeof (sname_v) - 1 }, - { formula, formula_v, sizeof (formula_v) - 1 }, - }; - enum { nAtt = sizeof (tab) / sizeof (tab[0]) }; - for (size_t i = 0; i < nAtt; ++i) - cdf_put_att_text(fileID, ncbvarid, tab[i].attName, tab[i].valLen, tab[i].attVal); - } - { - char txt[CDI_MAX_NAME]; - size_t len = (size_t)(sprintf(txt, "%s%s", "ap: ap_bnds b: b_bnds ps: ", psname)); - cdf_put_att_text(fileID, ncbvarid, "formula_terms", len, txt); - } - { - static const char units[] = "1"; - cdf_put_att_text(fileID, ncbvarid, "units", sizeof (units) - 1, units); - } - } - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - cdf_put_var_double(fileID, ncvarid, levels); - - if ( ncbvarid != UNDEFID ) - { - double zbounds[2*dimlen]; - for ( size_t i = 0; i < dimlen; ++i ) - { - zbounds[2*i ] = lbounds[i]; - zbounds[2*i+1] = ubounds[i]; - } - cdf_put_var_double(fileID, ncbvarid, zbounds); - } - - cdf_def_vct_cf(streamptr, zaxisID, *dimID, nvdimID); - - if ( *dimID == UNDEFID ) - { - if ( type == ZAXIS_HYBRID ) - streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID; - else - streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID; - } -} - -static -void cdf_def_zaxis_hybrid(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname) -{ - if ( (!CDI_cmor_mode && cdiConvention == CDI_CONVENTION_ECHAM) || type == ZAXIS_HYBRID_HALF ) - cdf_def_zaxis_hybrid_echam(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname); - else - cdf_def_zaxis_hybrid_cf(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname); -} - -static -void cdfDefZaxis(stream_t *streamptr, int zaxisID) -{ - /* char zaxisname0[CDI_MAX_NAME]; */ - char axisname[CDI_MAX_NAME]; - int dimID = UNDEFID; - int dimIDs[2]; - int ncvarid = UNDEFID, ncbvarid = UNDEFID; - int nvdimID = UNDEFID; - int xtype = NC_DOUBLE; - - if ( zaxisInqPrec(zaxisID) == DATATYPE_FLT32 ) xtype = NC_FLOAT; - - int vlistID = streamptr->vlistID; - int fileID = streamptr->fileID; - - int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); - - int nzaxis = vlistNzaxis(vlistID); - - size_t dimlen = (size_t)zaxisInqSize(zaxisID); - int type = zaxisInqType(zaxisID); - - int is_scalar = FALSE; - if ( dimlen == 1 ) - { - is_scalar = zaxisInqScalar(zaxisID); - if ( !is_scalar && CDI_cmor_mode ) - { - is_scalar = TRUE; - zaxisDefScalar(zaxisID); - } - } - - int ndims = 1; - if ( is_scalar ) ndims = 0; - - if ( dimlen == 1 ) - switch (type) - { - case ZAXIS_SURFACE: - case ZAXIS_CLOUD_BASE: - case ZAXIS_CLOUD_TOP: - case ZAXIS_ISOTHERM_ZERO: - case ZAXIS_TOA: - case ZAXIS_SEA_BOTTOM: - case ZAXIS_ATMOSPHERE: - case ZAXIS_MEANSEA: - case ZAXIS_LAKE_BOTTOM: - case ZAXIS_SEDIMENT_BOTTOM: - case ZAXIS_SEDIMENT_BOTTOM_TA: - case ZAXIS_SEDIMENT_BOTTOM_TW: - case ZAXIS_MIX_LAYER: - return; - } - - zaxisInqName(zaxisID, axisname); - - if ( dimID == UNDEFID ) - { - checkZaxisName(axisname, fileID, vlistID, zaxisID, nzaxis); - - char dimname[CDI_MAX_NAME+3]; - dimname[0] = 0; - //cdiZaxisInqString(zaxisID, CDI_ZAXIS_DIMNAME, CDI_MAX_NAME, dimname); - if ( dimname[0] == 0 ) strcpy(dimname, axisname); - - if ( type == ZAXIS_REFERENCE ) cdfDefZaxisUUID(streamptr, zaxisID); - - if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF ) - { - cdf_def_zaxis_hybrid(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, &dimID, axisname); - } - else - { - dimID = checkDimName(fileID, dimlen, dimname); - - if ( streamptr->ncmode == 2 ) cdf_redef(fileID); - - if ( ndims && dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID); - - cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid); - - cdfPutGridStdAtts(fileID, ncvarid, zaxisID, &gridInqsZ); - - { - int positive = zaxisInqPositive(zaxisID); - static const char positive_up[] = "up", - positive_down[] = "down"; - static const struct attTxtTab tab[2] = { - { positive_up, sizeof (positive_up) - 1 }, - { positive_down, sizeof (positive_down) - 1 }, - }; - if ( positive == POSITIVE_UP || positive == POSITIVE_DOWN ) - { - size_t select = positive == POSITIVE_DOWN; - cdf_put_att_text(fileID, ncvarid, "positive", - tab[select].txtLen, tab[select].txt); - } - } - cdf_put_att_text(fileID, ncvarid, "axis", 1, "Z"); - - if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - size_t nvertex = 2; - if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR ) - cdf_def_dim(fileID, bndsName, nvertex, &nvdimID); - - if ( nvdimID != UNDEFID ) - { - size_t axisnameLen = strlen(axisname); - axisname[axisnameLen] = '_'; - memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName)); - dimIDs[0] = dimID; - dimIDs[ndims] = nvdimID; - cdf_def_var(fileID, axisname, (nc_type) xtype, ndims+1, dimIDs, &ncbvarid); - cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname); - } - } - - cdf_enddef(fileID); - streamptr->ncmode = 2; - - cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID)); - - if ( ncbvarid != UNDEFID ) - { - double lbounds[dimlen], ubounds[dimlen], zbounds[2*dimlen]; - zaxisInqLbounds(zaxisID, lbounds); - zaxisInqUbounds(zaxisID, ubounds); - for ( size_t i = 0; i < dimlen; ++i ) - { - zbounds[2*i ] = lbounds[i]; - zbounds[2*i+1] = ubounds[i]; - } - - cdf_put_var_double(fileID, ncbvarid, zbounds); - } - - if ( ndims == 0 ) streamptr->nczvarID[zaxisindex] = ncvarid; - } - } - - if ( dimID != UNDEFID ) - streamptr->zaxisID[zaxisindex] = dimID; -} - -static -void cdfDefPole(stream_t *streamptr, int gridID) -{ - int ncvarid = UNDEFID; - static const char varname[] = "rotated_pole"; - static const char mapname[] = "rotated_latitude_longitude"; - - int fileID = streamptr->fileID; - - double ypole = gridInqYpole(gridID); - double xpole = gridInqXpole(gridID); - double angle = gridInqAngle(gridID); - - cdf_redef(fileID); - - int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); - if ( ncerrcode == NC_NOERR ) - { - cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", sizeof (mapname) - 1, mapname); - cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole); - cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole); - if ( IS_NOT_EQUAL(angle, 0) ) - cdf_put_att_double(fileID, ncvarid, "north_pole_grid_longitude", NC_DOUBLE, 1, &angle); - } - - cdf_enddef(fileID); -} - - -static -void cdfDefMapping(stream_t *streamptr, int gridID) -{ - int ncvarid = UNDEFID; - int fileID = streamptr->fileID; - - if ( gridInqType(gridID) == GRID_SINUSOIDAL ) - { - static const char varname[] = "sinusoidal"; - static const char mapname[] = "sinusoidal"; - - cdf_redef(fileID); - - int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); - if ( ncerrcode == NC_NOERR ) - { - cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname); - /* - cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole); - cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole); - */ - } - - cdf_enddef(fileID); - } - else if ( gridInqType(gridID) == GRID_LAEA ) - { - static const char varname[] = "laea"; - static const char mapname[] = "lambert_azimuthal_equal_area"; - - cdf_redef(fileID); - - int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); - if ( ncerrcode == NC_NOERR ) - { - double a, lon_0, lat_0; - - gridInqLaea(gridID, &a, &lon_0, &lat_0); - - cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname); - cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &a); - cdf_put_att_double(fileID, ncvarid, "longitude_of_projection_origin", NC_DOUBLE, 1, &lon_0); - cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0); - } - - cdf_enddef(fileID); - } - else if ( gridInqType(gridID) == GRID_LCC2 ) - { - static const char varname[] = "Lambert_Conformal"; - static const char mapname[] = "lambert_conformal_conic"; - - cdf_redef(fileID); - - int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); - if ( ncerrcode == NC_NOERR ) - { - double radius, lon_0, lat_0, lat_1, lat_2; - - gridInqLcc2(gridID, &radius, &lon_0, &lat_0, &lat_1, &lat_2); - - cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname); - if ( radius > 0 ) - cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &radius); - cdf_put_att_double(fileID, ncvarid, "longitude_of_central_meridian", NC_DOUBLE, 1, &lon_0); - cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0); - if ( IS_EQUAL(lat_1, lat_2) ) - cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 1, &lat_1); - else - { - double lat_1_2[2]; - lat_1_2[0] = lat_1; - lat_1_2[1] = lat_2; - cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 2, lat_1_2); - } - } - - cdf_enddef(fileID); - } -} - - -static -void cdfDefGrid(stream_t *streamptr, int gridID) -{ - int vlistID = streamptr->vlistID; - int gridindex = vlistGridIndex(vlistID, gridID); - if ( streamptr->xdimID[gridindex] != UNDEFID ) return; - - int gridtype = gridInqType(gridID); - int size = gridInqSize(gridID); - - if ( CDI_Debug ) - Message("gridtype = %d size = %d", gridtype, size); - - if ( gridtype == GRID_GAUSSIAN || - gridtype == GRID_LONLAT || - gridtype == GRID_GENERIC ) - { - if ( gridtype == GRID_GENERIC ) - { - if ( size == 1 && gridInqXsize(gridID) == 0 && gridInqYsize(gridID) == 0 ) - { - /* no grid information */ - } - else - { - int lx = 0, ly = 0; - if ( gridInqXsize(gridID) > 0 /*&& gridInqXvals(gridID, NULL) > 0*/ ) - { - cdfDefXaxis(streamptr, gridID, 1); - lx = 1; - } - - if ( gridInqYsize(gridID) > 0 /*&& gridInqYvals(gridID, NULL) > 0*/ ) - { - cdfDefYaxis(streamptr, gridID, 1); - ly = 1; - } - - if ( lx == 0 && ly == 0 ) cdfDefGdim(streamptr, gridID); - } - } - else - { - int ndims = 1; - if ( gridtype == GRID_LONLAT && size == 1 && gridInqHasDims(gridID) == FALSE ) - ndims = 0; - - if ( gridInqXsize(gridID) > 0 ) cdfDefXaxis(streamptr, gridID, ndims); - if ( gridInqYsize(gridID) > 0 ) cdfDefYaxis(streamptr, gridID, ndims); - } - - if ( gridIsRotated(gridID) ) cdfDefPole(streamptr, gridID); - } - else if ( gridtype == GRID_CURVILINEAR ) - { - cdfDefCurvilinear(streamptr, gridID); - } - else if ( gridtype == GRID_UNSTRUCTURED ) - { - cdfDefUnstructured(streamptr, gridID); - } - else if ( gridtype == GRID_GAUSSIAN_REDUCED ) - { - cdfDefRgrid(streamptr, gridID); - } - else if ( gridtype == GRID_SPECTRAL ) - { - cdfDefComplex(streamptr, gridID); - cdfDefSP(streamptr, gridID); - } - else if ( gridtype == GRID_FOURIER ) - { - cdfDefComplex(streamptr, gridID); - cdfDefFC(streamptr, gridID); - } - else if ( gridtype == GRID_TRAJECTORY ) - { - cdfDefTrajLon(streamptr, gridID); - cdfDefTrajLat(streamptr, gridID); - } - else if ( gridtype == GRID_SINUSOIDAL || gridtype == GRID_LAEA || gridtype == GRID_LCC2 ) - { - cdfDefXaxis(streamptr, gridID, 1); - cdfDefYaxis(streamptr, gridID, 1); - - cdfDefMapping(streamptr, gridID); - } - /* - else if ( gridtype == GRID_LCC ) - { - cdfDefLcc(streamptr, gridID); - } - */ - else - { - Error("Unsupported grid type: %s", gridNamePtr(gridtype)); - } -} - -static -void scale_add(size_t size, double *data, double addoffset, double scalefactor) -{ - int laddoffset; - int lscalefactor; - - laddoffset = IS_NOT_EQUAL(addoffset, 0); - lscalefactor = IS_NOT_EQUAL(scalefactor, 1); - - if ( laddoffset || lscalefactor ) - { - for (size_t i = 0; i < size; ++i ) - { - if ( lscalefactor ) data[i] *= scalefactor; - if ( laddoffset ) data[i] += addoffset; - } - } -} - -static -void cdfCreateRecords(stream_t *streamptr, int tsID) -{ - if ( tsID < 0 || (tsID >= streamptr->ntsteps && tsID > 0) ) return; - - if ( streamptr->tsteps[tsID].nallrecs > 0 ) return; - - int vlistID = streamptr->vlistID; - - tsteps_t* sourceTstep = streamptr->tsteps; - tsteps_t* destTstep = sourceTstep + tsID; - - int nvars = vlistNvars(vlistID); - int nrecs = vlistNrecs(vlistID); - - if ( nrecs <= 0 ) return; - - if ( tsID == 0 ) - { - int nvrecs = nrecs; /* use all records at first timestep */ - - streamptr->nrecs += nrecs; - - destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t)); - destTstep->nrecs = nrecs; - destTstep->nallrecs = nrecs; - destTstep->recordSize = nrecs; - destTstep->curRecID = UNDEFID; - destTstep->recIDs = (int *) Malloc((size_t)nvrecs*sizeof (int));; - for ( int recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID; - - record_t *records = destTstep->records; - - for ( int varID = 0, recID = 0; varID < nvars; varID++ ) - { - int zaxisID = vlistInqVarZaxis(vlistID, varID); - int nlev = zaxisInqSize(zaxisID); - for ( int levelID = 0; levelID < nlev; levelID++ ) - { - recordInitEntry(&records[recID]); - records[recID].varID = (short)varID; - records[recID].levelID = (short)levelID; - recID++; - } - } - } - else if ( tsID == 1 ) - { - int nvrecs = 0; - for ( int varID = 0; varID < nvars; varID++ ) - { - if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT ) - { - int zaxisID = vlistInqVarZaxis(vlistID, varID); - nvrecs += zaxisInqSize(zaxisID); - } - } - - streamptr->nrecs += nvrecs; - - destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t)); - destTstep->nrecs = nvrecs; - destTstep->nallrecs = nrecs; - destTstep->recordSize = nrecs; - destTstep->curRecID = UNDEFID; - - memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t)); - - if ( nvrecs ) - { - destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof (int)); - for ( int recID = 0, vrecID = 0; recID < nrecs; recID++ ) - { - int varID = destTstep->records[recID].varID; - if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT ) - { - destTstep->recIDs[vrecID++] = recID; - } - } - } - } - else - { - if ( streamptr->tsteps[1].records == 0 ) cdfCreateRecords(streamptr, 1); - - int nvrecs = streamptr->tsteps[1].nrecs; - - streamptr->nrecs += nvrecs; - - destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t)); - destTstep->nrecs = nvrecs; - destTstep->nallrecs = nrecs; - destTstep->recordSize = nrecs; - destTstep->curRecID = UNDEFID; - - memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t)); - - destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof(int)); - - memcpy(destTstep->recIDs, streamptr->tsteps[1].recIDs, (size_t)nvrecs*sizeof(int)); - } -} - - -static -int cdfTimeDimID(int fileID, int ndims, int nvars) -{ - for ( int dimid = 0; dimid < ndims; dimid++ ) - { - char dimname[80]; - cdf_inq_dimname(fileID, dimid, dimname); - if ( memcmp(dimname, "time", 4) == 0 ) - return dimid; - } - - - for ( int varid = 0; varid < nvars; varid++ ) - { - int nvdims, nvatts, dimids[9]; - cdf_inq_var(fileID, varid, NULL, NULL, &nvdims, dimids, &nvatts); - if ( nvdims == 1 ) - { - for ( int iatt = 0; iatt < nvatts; iatt++ ) - { - char sbuf[CDI_MAX_NAME]; - cdf_inq_attname(fileID, varid, iatt, sbuf); - if ( strncmp(sbuf, "units", 5) == 0 ) - { - cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf); - strtolower(sbuf); - - if ( isTimeUnits(sbuf) ) - return dimids[0]; - } - } - } - } - - return UNDEFID; -} - -static -void init_ncdims(long ndims, ncdim_t *ncdims) -{ - for ( long ncdimid = 0; ncdimid < ndims; ncdimid++ ) - { - ncdims[ncdimid].ncvarid = UNDEFID; - ncdims[ncdimid].dimtype = UNDEFID; - ncdims[ncdimid].len = 0; - ncdims[ncdimid].name[0] = 0; - } -} - -static -void init_ncvars(long nvars, ncvar_t *ncvars) -{ - for ( long ncvarid = 0; ncvarid < nvars; ++ncvarid ) - { - ncvars[ncvarid].ncid = UNDEFID; - ncvars[ncvarid].ignore = FALSE; - ncvars[ncvarid].isvar = UNDEFID; - ncvars[ncvarid].islon = FALSE; - ncvars[ncvarid].islat = FALSE; - ncvars[ncvarid].islev = FALSE; - ncvars[ncvarid].istime = FALSE; - ncvars[ncvarid].warn = FALSE; - ncvars[ncvarid].tsteptype = TSTEP_CONSTANT; - ncvars[ncvarid].param = UNDEFID; - ncvars[ncvarid].code = UNDEFID; - ncvars[ncvarid].tabnum = 0; - ncvars[ncvarid].calendar = FALSE; - ncvars[ncvarid].climatology = FALSE; - ncvars[ncvarid].bounds = UNDEFID; - ncvars[ncvarid].lformula = FALSE; - ncvars[ncvarid].lformulaterms = FALSE; - ncvars[ncvarid].gridID = UNDEFID; - ncvars[ncvarid].zaxisID = UNDEFID; - ncvars[ncvarid].gridtype = UNDEFID; - ncvars[ncvarid].zaxistype = UNDEFID; - ncvars[ncvarid].xdim = UNDEFID; - ncvars[ncvarid].ydim = UNDEFID; - ncvars[ncvarid].zdim = UNDEFID; - ncvars[ncvarid].xvarid = UNDEFID; - ncvars[ncvarid].yvarid = UNDEFID; - ncvars[ncvarid].zvarid = UNDEFID; - ncvars[ncvarid].tvarid = UNDEFID; - ncvars[ncvarid].psvarid = UNDEFID; - ncvars[ncvarid].p0varid = UNDEFID; - ncvars[ncvarid].ncoordvars = 0; - for ( int i = 0; i < MAX_COORDVARS; ++i ) - ncvars[ncvarid].coordvarids[i] = UNDEFID; - ncvars[ncvarid].nauxvars = 0; - for ( int i = 0; i < MAX_AUXVARS; ++i ) - ncvars[ncvarid].auxvarids[i] = UNDEFID; - ncvars[ncvarid].cellarea = UNDEFID; - ncvars[ncvarid].tableID = UNDEFID; - ncvars[ncvarid].xtype = 0; - ncvars[ncvarid].ndims = 0; - ncvars[ncvarid].gmapid = UNDEFID; - ncvars[ncvarid].vctsize = 0; - ncvars[ncvarid].vct = NULL; - ncvars[ncvarid].truncation = 0; - ncvars[ncvarid].position = 0; - ncvars[ncvarid].positive = 0; - ncvars[ncvarid].chunked = 0; - ncvars[ncvarid].chunktype = UNDEFID; - ncvars[ncvarid].defmissval = 0; - ncvars[ncvarid].deffillval = 0; - ncvars[ncvarid].missval = 0; - ncvars[ncvarid].fillval = 0; - ncvars[ncvarid].addoffset = 0; - ncvars[ncvarid].scalefactor = 1; - ncvars[ncvarid].name[0] = 0; - ncvars[ncvarid].longname[0] = 0; - ncvars[ncvarid].stdname[0] = 0; - ncvars[ncvarid].units[0] = 0; - ncvars[ncvarid].extra[0] = 0; - ncvars[ncvarid].natts = 0; - ncvars[ncvarid].atts = NULL; - ncvars[ncvarid].deflate = 0; - ncvars[ncvarid].lunsigned = 0; - ncvars[ncvarid].lvalidrange = 0; - ncvars[ncvarid].validrange[0] = VALIDMISS; - ncvars[ncvarid].validrange[1] = VALIDMISS; - ncvars[ncvarid].ensdata = NULL; - } -} - -static -void cdfSetVar(ncvar_t *ncvars, int ncvarid, short isvar) -{ - if ( ncvars[ncvarid].isvar != UNDEFID && - ncvars[ncvarid].isvar != isvar && - ncvars[ncvarid].warn == FALSE ) - { - if ( ! ncvars[ncvarid].ignore ) - Warning("Inconsistent variable definition for %s!", ncvars[ncvarid].name); - - ncvars[ncvarid].warn = TRUE; - isvar = FALSE; - } - - ncvars[ncvarid].isvar = isvar; -} - -static -void cdfSetDim(ncvar_t *ncvars, int ncvarid, int dimid, int dimtype) -{ - if ( ncvars[ncvarid].dimtype[dimid] != UNDEFID && - ncvars[ncvarid].dimtype[dimid] != dimtype ) - { - Warning("Inconsistent dimension definition for %s! dimid = %d; type = %d; newtype = %d", - ncvars[ncvarid].name, dimid, ncvars[ncvarid].dimtype[dimid], dimtype); - } - - ncvars[ncvarid].dimtype[dimid] = dimtype; -} - -static -bool isLonAxis(const char *units, const char *stdname) -{ - bool status = false; - char lc_units[16]; - - memcpy(lc_units, units, 15); - lc_units[15] = 0; - strtolower(lc_units); - - if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) && - (memcmp(stdname, "grid_longitude", 14) == 0 || memcmp(stdname, "longitude", 9) == 0)) ) - { - status = true; - } - - if ( status == false && - memcmp(stdname, "grid_latitude", 13) && memcmp(stdname, "latitude", 8) && - memcmp(lc_units, "degree", 6) == 0 ) - { - int ioff = 6; - if ( lc_units[ioff] == 's' ) ioff++; - if ( lc_units[ioff] == '_' ) ioff++; - if ( lc_units[ioff] == 'e' ) status = true; - } - - return status; -} - -static -bool isLatAxis(const char *units, const char *stdname) -{ - bool status = false; - char lc_units[16]; - - memcpy(lc_units, units, 15); - lc_units[15] = 0; - strtolower(lc_units); - - if ( ((memcmp(lc_units, "degree", 6) == 0 || memcmp(lc_units, "radian", 6) == 0) && - (memcmp(stdname, "grid_latitude", 13) == 0 || memcmp(stdname, "latitude", 8) == 0)) ) - { - status = true; - } - - if ( status == false && - memcmp(stdname, "grid_longitude", 14) && memcmp(stdname, "longitude", 9) && - memcmp(lc_units, "degree", 6) == 0 ) - { - int ioff = 6; - if ( lc_units[ioff] == 's' ) ioff++; - if ( lc_units[ioff] == '_' ) ioff++; - if ( lc_units[ioff] == 'n' || lc_units[ioff] == 's' ) status = true; - } - - return status; -} - -static -bool isDBLAxis(/*const char *units,*/ const char *longname) -{ - bool status = false; - - if ( strcmp(longname, "depth below land") == 0 || - strcmp(longname, "depth_below_land") == 0 || - strcmp(longname, "levels below the surface") == 0 ) - { - /* - if ( strcmp(ncvars[ncvarid].units, "cm") == 0 || - strcmp(ncvars[ncvarid].units, "dm") == 0 || - strcmp(ncvars[ncvarid].units, "m") == 0 ) - */ - status = true; - } - - return status; -} - -static -bool unitsIsHeight(const char *units) -{ - bool status = false; - int u0 = units[0]; - - if ( (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0)) || - (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k')) ) - { - status = true; - } - - return status; -} - -static -bool isDepthAxis(const char *stdname, const char *longname) -{ - bool status = false; - - if ( strcmp(stdname, "depth") == 0 ) - status = true; - else - if ( strcmp(longname, "depth_below_sea") == 0 || - strcmp(longname, "depth below sea") == 0 ) - { - status = true; - } - - return status; -} - -static -bool isHeightAxis(const char *stdname, const char *longname) -{ - bool status = false; - - if ( strcmp(stdname, "height") == 0 ) - status = true; - else - if ( strcmp(longname, "height") == 0 || - strcmp(longname, "height above the surface") == 0 ) - { - status = true; - } - - return status; -} - -static -bool unitsIsPressure(const char *units) -{ - bool status = false; - - if ( strncmp(units, "millibar", 8) == 0 || - strncmp(units, "mb", 2) == 0 || - strncmp(units, "hectopas", 8) == 0 || - strncmp(units, "hPa", 3) == 0 || - strncmp(units, "Pa", 2) == 0 ) - { - status = true; - } - - return status; -} - -static -int scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid, int *avarid, int *p0varid) -{ - int status = 0; - *apvarid = -1; - *bvarid = -1; - *psvarid = -1; - *avarid = -1; - *p0varid = -1; - enum { attstringlen = 8192 }; char attstring[attstringlen]; - cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring); - if ( strcmp(attstring, "p = ap + b*ps") == 0 ) - { - status = 1; - int lstop = FALSE; - int dimvarid; - cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring); - char *pstring = attstring; - - for ( int i = 0; i < 3; i++ ) - { - while ( isspace((int) *pstring) ) pstring++; - if ( *pstring == 0 ) break; - char *tagname = pstring; - while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; - if ( *pstring == 0 ) lstop = TRUE; - *pstring++ = 0; - - while ( isspace((int) *pstring) ) pstring++; - if ( *pstring == 0 ) break; - char *varname = pstring; - while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; - if ( *pstring == 0 ) lstop = TRUE; - *pstring++ = 0; - - int status_nc = nc_inq_varid(ncid, varname, &dimvarid); - if ( status_nc == NC_NOERR ) - { - if ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid; - else if ( strcmp(tagname, "b:") == 0 ) *bvarid = dimvarid; - else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid; - } - else if ( strcmp(tagname, "ps:") != 0 ) - { - Warning("%s - %s", nc_strerror(status_nc), varname); - } - - if ( lstop ) break; - } - } - else if ( strcmp(attstring, "xxxp = a*p0 + b*ps") == 0 ) - { - status = 2; - int lstop = FALSE; - int dimvarid; - cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring); - char *pstring = attstring; - - for ( int i = 0; i < 4; i++ ) - { - while ( isspace((int) *pstring) ) pstring++; - if ( *pstring == 0 ) break; - char *tagname = pstring; - while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; - if ( *pstring == 0 ) lstop = TRUE; - *pstring++ = 0; - - while ( isspace((int) *pstring) ) pstring++; - if ( *pstring == 0 ) break; - char *varname = pstring; - while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; - if ( *pstring == 0 ) lstop = TRUE; - *pstring++ = 0; - - int status_nc = nc_inq_varid(ncid, varname, &dimvarid); - if ( status_nc == NC_NOERR ) - { - if ( strcmp(tagname, "a:") == 0 ) *avarid = dimvarid; - else if ( strcmp(tagname, "b:") == 0 ) *bvarid = dimvarid; - else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid; - else if ( strcmp(tagname, "p0:") == 0 ) *p0varid = dimvarid; - } - else if ( strcmp(tagname, "ps:") != 0 ) - { - Warning("%s - %s", nc_strerror(status_nc), varname); - } - - if ( lstop ) break; - } - } - - return status; -} - -static -bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims) -{ - bool status = false; - int ncfvarid = ncvarid; - ncvar_t *ncvar = &ncvars[ncvarid]; - - if ( strcmp(ncvar->stdname, "atmosphere_hybrid_sigma_pressure_coordinate") == 0 ) - { - cdiConvention = CDI_CONVENTION_CF; - - status = true; - ncvar->zaxistype = ZAXIS_HYBRID; - int dimid = ncvar->dimids[0]; - size_t dimlen = ncdims[dimid].len; - - int ret; - int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1, avarid1 = -1, p0varid1 = -1; - if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms ) - ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1, &avarid1, &p0varid1); - if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE; - if ( bvarid1 != -1 ) ncvars[bvarid1].isvar = FALSE; - if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1; - if ( avarid1 != -1 ) ncvars[avarid1].isvar = FALSE; - if ( p0varid1 != -1 ) ncvar->p0varid = p0varid1; - - if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms ) - { - ncfvarid = ncvar->bounds; - int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1, avarid2 = -1, p0varid2 = -1; - ret = 0; - if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms ) - ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2, &avarid2, &p0varid2); - if ( ret == 1 ) avarid2 = apvarid2; - if ( avarid2 != -1 && bvarid2 != -1 ) - { - ncvars[avarid2].isvar = FALSE; - ncvars[bvarid2].isvar = FALSE; - - if ( dimid == ncvars[avarid2].dimids[0] && ncdims[ncvars[avarid2].dimids[1]].len == 2 ) - { - double px = 1; - if ( ret == 2 && p0varid1 == p0varid2 ) - cdf_get_var_double(ncid, p0varid2, &px); - - double abuf[dimlen*2], bbuf[dimlen*2]; - cdf_get_var_double(ncid, avarid2, abuf); - cdf_get_var_double(ncid, bvarid2, bbuf); - /* - for ( int i = 0; i < dimlen; ++i ) - printf("%d %g %g %g %g\n", i, abuf[i*2], abuf[i*2+1], bbuf[i*2], bbuf[i*2+1]); - */ - size_t vctsize = (dimlen+1)*2; - double *vct = (double *) Malloc(vctsize * sizeof(double)); - for ( size_t i = 0; i < dimlen; ++i ) - { - vct[i] = abuf[i*2]; - vct[i+dimlen+1] = bbuf[i*2]; - } - vct[dimlen] = abuf[dimlen*2-1]; - vct[dimlen*2+1] = bbuf[dimlen*2-1]; - - if ( ret == 2 && IS_NOT_EQUAL(px, 1) ) - for ( size_t i = 0; i < dimlen+1; ++i ) vct[i] *= px; - - ncvar->vct = vct; - ncvar->vctsize = vctsize; - } - } - } - } - - return status; -} - - -static -int isGaussGrid(size_t ysize, double yinc, const double *yvals) -{ - int lgauss = FALSE; - double *yv, *yw; - - if ( IS_EQUAL(yinc, 0) && ysize > 2 ) /* check if gaussian */ - { - size_t i; - yv = (double *) Malloc(ysize*sizeof(double)); - yw = (double *) Malloc(ysize*sizeof(double)); - gaussaw(yv, yw, ysize); - Free(yw); - for ( i = 0; i < ysize; i++ ) - yv[i] = asin(yv[i])/M_PI*180.0; - - for ( i = 0; i < ysize; i++ ) - if ( fabs(yv[i] - yvals[i]) > - ((yv[0] - yv[1])/500) ) break; - - if ( i == ysize ) lgauss = TRUE; - - /* check S->N */ - if ( lgauss == FALSE ) - { - for ( i = 0; i < ysize; i++ ) - if ( fabs(yv[i] - yvals[ysize-i-1]) > - ((yv[0] - yv[1])/500) ) break; - - if ( i == ysize ) lgauss = TRUE; - } - - Free(yv); - } - - return (lgauss); -} - -static -void printNCvars(const ncvar_t *ncvars, int nvars, const char *oname) -{ - char axis[7]; - int ncvarid, i; - int ndim; - static const char iaxis[] = {'t', 'z', 'y', 'x'}; - - fprintf(stderr, "%s:\n", oname); - - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - ndim = 0; - if ( ncvars[ncvarid].isvar ) - { - axis[ndim++] = 'v'; - axis[ndim++] = ':'; - for ( i = 0; i < ncvars[ncvarid].ndims; i++ ) - {/* - if ( ncvars[ncvarid].tvarid != -1 ) axis[ndim++] = iaxis[0]; - else if ( ncvars[ncvarid].zvarid != -1 ) axis[ndim++] = iaxis[1]; - else if ( ncvars[ncvarid].yvarid != -1 ) axis[ndim++] = iaxis[2]; - else if ( ncvars[ncvarid].xvarid != -1 ) axis[ndim++] = iaxis[3]; - else - */ - if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) axis[ndim++] = iaxis[0]; - else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) axis[ndim++] = iaxis[1]; - else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) axis[ndim++] = iaxis[2]; - else if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) axis[ndim++] = iaxis[3]; - else axis[ndim++] = '?'; - } - } - else - { - axis[ndim++] = 'c'; - axis[ndim++] = ':'; - if ( ncvars[ncvarid].istime ) axis[ndim++] = iaxis[0]; - else if ( ncvars[ncvarid].islev ) axis[ndim++] = iaxis[1]; - else if ( ncvars[ncvarid].islat ) axis[ndim++] = iaxis[2]; - else if ( ncvars[ncvarid].islon ) axis[ndim++] = iaxis[3]; - else axis[ndim++] = '?'; - } - - axis[ndim++] = 0; - - fprintf(stderr, "%3d %3d %-6s %s\n", ncvarid, ndim-3, axis, ncvars[ncvarid].name); - } -} - -static -void cdfScanVarAttributes(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, - int timedimid, int modelID, int format) -{ - int ncid; - int ncdimid; - int nvdims, nvatts; - int *dimidsp; - int iatt; - nc_type xtype, atttype; - size_t attlen; - char name[CDI_MAX_NAME]; - char attname[CDI_MAX_NAME]; - const int attstringlen = 8192; char attstring[8192]; - - int nchecked_vars = 0; - enum { max_check_vars = 9 }; - char *checked_vars[max_check_vars]; - for ( int i = 0; i < max_check_vars; ++i ) checked_vars[i] = NULL; - - for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - ncid = ncvars[ncvarid].ncid; - dimidsp = ncvars[ncvarid].dimids; - - cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts); - strcpy(ncvars[ncvarid].name, name); - - for ( ncdimid = 0; ncdimid < nvdims; ncdimid++ ) - ncvars[ncvarid].dimtype[ncdimid] = -1; - - ncvars[ncvarid].xtype = xtype; - ncvars[ncvarid].ndims = nvdims; - -#if defined (HAVE_NETCDF4) - if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 ) - { - int shuffle, deflate, deflate_level; - size_t chunks[nvdims]; - int storage_in; - nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflate_level); - if ( deflate > 0 ) ncvars[ncvarid].deflate = 1; - - if ( nc_inq_var_chunking(ncid, ncvarid, &storage_in, chunks) == NC_NOERR ) - { - if ( storage_in == NC_CHUNKED ) - { - ncvars[ncvarid].chunked = 1; - for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i]; - if ( CDI_Debug ) - { - fprintf(stderr, "%s: chunking %d %d %d chunks ", name, storage_in, NC_CONTIGUOUS, NC_CHUNKED); - for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]); - fprintf(stderr, "\n"); - } - { - char *buf = ncvars[ncvarid].extra; - size_t pos = strlen(buf); - static const char prefix[] = "chunks="; - memcpy(buf + pos, prefix, sizeof (prefix)); - pos += sizeof (prefix) - 1; - for ( int i = nvdims-1; i >= 0; --i ) - { - pos += (size_t)(sprintf(buf + pos, "%zu%s", chunks[i], - i > 0 ? "x" : "")); - } - buf[pos] = ' '; buf[pos + 1] = 0; - } - } - } - } -#endif - - if ( nvdims > 0 ) - { - if ( timedimid == dimidsp[0] ) - { - ncvars[ncvarid].tsteptype = TSTEP_INSTANT; - cdfSetDim(ncvars, ncvarid, 0, T_AXIS); - } - else - { - for ( ncdimid = 1; ncdimid < nvdims; ncdimid++ ) - { - if ( timedimid == dimidsp[ncdimid] ) - { - Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name); - ncvars[ncvarid].isvar = FALSE; - } - } - } - } - - for ( iatt = 0; iatt < nvatts; iatt++ ) - { - cdf_inq_attname(ncid, ncvarid, iatt, attname); - cdf_inq_atttype(ncid, ncvarid, attname, &atttype); - cdf_inq_attlen(ncid, ncvarid, attname, &attlen); - - if ( strcmp(attname, "long_name") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].longname); - } - else if ( strcmp(attname, "standard_name") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].stdname); - } - else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units); - } - else if ( strcmp(attname, "calendar") == 0 ) - { - ncvars[ncvarid].calendar = TRUE; - } - else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) ) - { - char paramstr[32]; - int pnum = 0, pcat = 255, pdis = 255; - cdfGetAttText(ncid, ncvarid, attname, sizeof(paramstr), paramstr); - sscanf(paramstr, "%d.%d.%d", &pnum, &pcat, &pdis); - ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis); - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( strcmp(attname, "code") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].code); - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) ) - { - int tablenum; - cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum); - if ( tablenum > 0 ) - { - ncvars[ncvarid].tabnum = tablenum; - ncvars[ncvarid].tableID = tableInq(modelID, tablenum, NULL); - if ( ncvars[ncvarid].tableID == CDI_UNDEFID ) - ncvars[ncvarid].tableID = tableDef(modelID, tablenum, NULL); - } - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - if ( memcmp(attstring, "Triangular", attlen) == 0 ) - ncvars[ncvarid].gridtype = GRID_SPECTRAL; - } - else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - strtolower(attstring); - - if ( strcmp(attstring, "gaussian reduced") == 0 ) - ncvars[ncvarid].gridtype = GRID_GAUSSIAN_REDUCED; - else if ( strcmp(attstring, "gaussian") == 0 ) - ncvars[ncvarid].gridtype = GRID_GAUSSIAN; - else if ( strncmp(attstring, "spectral", 8) == 0 ) - ncvars[ncvarid].gridtype = GRID_SPECTRAL; - else if ( strncmp(attstring, "fourier", 7) == 0 ) - ncvars[ncvarid].gridtype = GRID_FOURIER; - else if ( strcmp(attstring, "trajectory") == 0 ) - ncvars[ncvarid].gridtype = GRID_TRAJECTORY; - else if ( strcmp(attstring, "generic") == 0 ) - ncvars[ncvarid].gridtype = GRID_GENERIC; - else if ( strcmp(attstring, "cell") == 0 ) - ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED; - else if ( strcmp(attstring, "unstructured") == 0 ) - ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED; - else if ( strcmp(attstring, "curvilinear") == 0 ) - ncvars[ncvarid].gridtype = GRID_CURVILINEAR; - else if ( strcmp(attstring, "sinusoidal") == 0 ) - ; - else if ( strcmp(attstring, "laea") == 0 ) - ; - else if ( strcmp(attstring, "lcc2") == 0 ) - ; - else if ( strcmp(attstring, "linear") == 0 ) // ignore grid type linear - ; - else - { - static int warn = TRUE; - if ( warn ) - { - warn = FALSE; - Warning("NetCDF attribute grid_type='%s' unsupported!", attstring); - } - } - - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - strtolower(attstring); - - if ( strcmp(attstring, "toa") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_TOA; - else if ( strcmp(attstring, "cloudbase") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_BASE; - else if ( strcmp(attstring, "cloudtop") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_CLOUD_TOP; - else if ( strcmp(attstring, "isotherm0") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_ISOTHERM_ZERO; - else if ( strcmp(attstring, "seabottom") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_SEA_BOTTOM; - else if ( strcmp(attstring, "lakebottom") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_LAKE_BOTTOM; - else if ( strcmp(attstring, "sedimentbottom") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM; - else if ( strcmp(attstring, "sedimentbottomta") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TA; - else if ( strcmp(attstring, "sedimentbottomtw") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_SEDIMENT_BOTTOM_TW; - else if ( strcmp(attstring, "mixlayer") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_MIX_LAYER; - else if ( strcmp(attstring, "atmosphere") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_ATMOSPHERE; - else - { - static int warn = TRUE; - if ( warn ) - { - warn = FALSE; - Warning("NetCDF attribute level_type='%s' unsupported!", attstring); - } - } - - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation); - } - else if ( strcmp(attname, "truncation") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation); - } - else if ( strcmp(attname, "number_of_grid_in_reference") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].position); - } - else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset); - /* - if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT ) - if ( ncvars[ncvarid].addoffset != 0 ) - Warning("attribute add_offset not supported for atttype %d", atttype); - */ - /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */ - } - else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor); - /* - if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT ) - if ( ncvars[ncvarid].scalefactor != 1 ) - Warning("attribute scale_factor not supported for atttype %d", atttype); - */ - /* (also used for lon/lat) cdfSetVar(ncvars, ncvarid, TRUE); */ - } - else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - int ncboundsid; - int status = nc_inq_varid(ncid, attstring, &ncboundsid); - if ( status == NC_NOERR ) - { - ncvars[ncvarid].climatology = TRUE; - ncvars[ncvarid].bounds = ncboundsid; - cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE); - cdfSetVar(ncvars, ncvarid, FALSE); - } - else - Warning("%s - %s", nc_strerror(status), attstring); - } - else if ( xtypeIsText(atttype) && strcmp(attname, "bounds") == 0 ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - int ncboundsid; - int status = nc_inq_varid(ncid, attstring, &ncboundsid); - if ( status == NC_NOERR ) - { - ncvars[ncvarid].bounds = ncboundsid; - cdfSetVar(ncvars, ncvars[ncvarid].bounds, FALSE); - cdfSetVar(ncvars, ncvarid, FALSE); - } - else - Warning("%s - %s", nc_strerror(status), attstring); - } - else if ( xtypeIsText(atttype) && strcmp(attname, "formula_terms") == 0 ) - { - ncvars[ncvarid].lformulaterms = TRUE; - } - else if ( xtypeIsText(atttype) && strcmp(attname, "formula") == 0 ) - { - ncvars[ncvarid].lformula = TRUE; - } - else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - char *pstring = attstring; - - while ( isspace((int) *pstring) ) pstring++; - char *cell_measures = pstring; - while ( isalnum((int) *pstring) ) pstring++; - *pstring++ = 0; - while ( isspace((int) *pstring) ) pstring++; - char *cell_var = pstring; - while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++; - *pstring++ = 0; - /* - printf("cell_measures >%s<\n", cell_measures); - printf("cell_var >%s<\n", cell_var); - */ - if ( memcmp(cell_measures, "area", 4) == 0 ) - { - int nc_cell_id; - int status = nc_inq_varid(ncid, cell_var, &nc_cell_id); - if ( status == NC_NOERR ) - { - ncvars[ncvarid].cellarea = nc_cell_id; - /* ncvars[nc_cell_id].isvar = UNDEFID; */ - cdfSetVar(ncvars, nc_cell_id, FALSE); - } - else - Warning("%s - %s", nc_strerror(status), cell_var); - } - else - { - Warning("%s has an unexpected contents: %s", attname, cell_measures); - } - cdfSetVar(ncvars, ncvarid, TRUE); - } - /* - else if ( strcmp(attname, "coordinates") == 0 ) - { - char *pstring, *xvarname = NULL, *yvarname = NULL; - - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - pstring = attstring; - - while ( isspace((int) *pstring) ) pstring++; - xvarname = pstring; - while ( isgraph((int) *pstring) ) pstring++; - *pstring++ = 0; - while ( isspace((int) *pstring) ) pstring++; - yvarname = pstring; - while ( isgraph((int) *pstring) ) pstring++; - *pstring++ = 0; - - cdf_inq_varid(ncid, xvarname, &ncvars[ncvarid].xvarid); - cdf_inq_varid(ncid, yvarname, &ncvars[ncvarid].yvarid); - - cdfSetVar(ncvars, ncvars[ncvarid].xvarid, FALSE); - cdfSetVar(ncvars, ncvars[ncvarid].yvarid, FALSE); - cdfSetVar(ncvars, ncvarid, TRUE); - } - */ - else if ( (strcmp(attname, "associate") == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) ) - { - int lstop = FALSE; - int dimvarid; - - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - char *pstring = attstring; - - for ( int i = 0; i < MAX_COORDVARS; i++ ) - { - while ( isspace((int) *pstring) ) pstring++; - if ( *pstring == 0 ) break; - char *varname = pstring; - while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; - if ( *pstring == 0 ) lstop = TRUE; - *pstring++ = 0; - - int status = nc_inq_varid(ncid, varname, &dimvarid); - if ( status == NC_NOERR ) - { - cdfSetVar(ncvars, dimvarid, FALSE); - if ( cdiIgnoreAttCoordinates == FALSE ) - { - ncvars[ncvarid].coordvarids[i] = dimvarid; - ncvars[ncvarid].ncoordvars++; - } - } - else - { - int k; - for ( k = 0; k < nchecked_vars; ++k ) - if ( strcmp(checked_vars[k], varname) == 0 ) break; - - if ( k == nchecked_vars ) - { - if ( nchecked_vars < max_check_vars ) checked_vars[nchecked_vars++] = strdup(varname); - Warning("%s - %s", nc_strerror(status), varname); - } - } - - if ( lstop ) break; - } - - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) ) - { - int lstop = FALSE; - int dimvarid; - - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - char *pstring = attstring; - - for ( int i = 0; i < MAX_AUXVARS; i++ ) - { - while ( isspace((int) *pstring) ) pstring++; - if ( *pstring == 0 ) break; - char *varname = pstring; - while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; - if ( *pstring == 0 ) lstop = TRUE; - *pstring++ = 0; - - int status = nc_inq_varid(ncid, varname, &dimvarid); - if ( status == NC_NOERR ) - { - cdfSetVar(ncvars, dimvarid, FALSE); - // if ( cdiIgnoreAttCoordinates == FALSE ) - { - ncvars[ncvarid].auxvarids[i] = dimvarid; - ncvars[ncvarid].nauxvars++; - } - } - else - Warning("%s - %s", nc_strerror(status), varname); - - if ( lstop ) break; - } - - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - int nc_gmap_id; - int status = nc_inq_varid(ncid, attstring, &nc_gmap_id); - if ( status == NC_NOERR ) - { - ncvars[ncvarid].gmapid = nc_gmap_id; - cdfSetVar(ncvars, ncvars[ncvarid].gmapid, FALSE); - } - else - Warning("%s - %s", nc_strerror(status), attstring); - - cdfSetVar(ncvars, ncvarid, TRUE); - } - else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - strtolower(attstring); - - if ( memcmp(attstring, "down", 4) == 0 ) ncvars[ncvarid].positive = POSITIVE_DOWN; - else if ( memcmp(attstring, "up", 2) == 0 ) ncvars[ncvarid].positive = POSITIVE_UP; - - if ( ncvars[ncvarid].ndims == 1 ) - { - cdfSetVar(ncvars, ncvarid, FALSE); - cdfSetDim(ncvars, ncvarid, 0, Z_AXIS); - ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS; - } - } - else if ( strcmp(attname, "_FillValue") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].fillval); - ncvars[ncvarid].deffillval = TRUE; - /* cdfSetVar(ncvars, ncvarid, TRUE); */ - } - else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval); - ncvars[ncvarid].defmissval = TRUE; - /* cdfSetVar(ncvars, ncvarid, TRUE); */ - } - else if ( strcmp(attname, "valid_range") == 0 && attlen == 2 ) - { - if ( ncvars[ncvarid].lvalidrange == FALSE ) - { - extern int cdiIgnoreValidRange; - int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype); - if ( cdiIgnoreValidRange == FALSE && lignore == FALSE ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange); - ncvars[ncvarid].lvalidrange = TRUE; - if ( ((int)ncvars[ncvarid].validrange[0]) == 0 && ((int)ncvars[ncvarid].validrange[1]) == 255 ) - ncvars[ncvarid].lunsigned = TRUE; - /* cdfSetVar(ncvars, ncvarid, TRUE); */ - } - else if ( lignore ) - { - Warning("Inconsistent data type for attribute %s:valid_range, ignored!", name); - } - } - } - else if ( strcmp(attname, "valid_min") == 0 && attlen == 1 ) - { - if ( ncvars[ncvarid].lvalidrange == FALSE ) - { - extern int cdiIgnoreValidRange; - int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype); - if ( cdiIgnoreValidRange == FALSE && lignore == FALSE ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]); - ncvars[ncvarid].lvalidrange = TRUE; - } - else if ( lignore ) - { - Warning("Inconsistent data type for attribute %s:valid_min, ignored!", name); - } - } - } - else if ( strcmp(attname, "valid_max") == 0 && attlen == 1 ) - { - if ( ncvars[ncvarid].lvalidrange == FALSE ) - { - extern int cdiIgnoreValidRange; - int lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype); - if ( cdiIgnoreValidRange == FALSE && lignore == FALSE ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]); - ncvars[ncvarid].lvalidrange = TRUE; - } - else if ( lignore ) - { - Warning("Inconsistent data type for attribute %s:valid_max, ignored!", name); - } - } - } - else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - strtolower(attstring); - - if ( memcmp(attstring, "true", 4) == 0 ) - { - ncvars[ncvarid].lunsigned = TRUE; - /* - ncvars[ncvarid].lvalidrange = TRUE; - ncvars[ncvarid].validrange[0] = 0; - ncvars[ncvarid].validrange[1] = 255; - */ - } - /* cdfSetVar(ncvars, ncvarid, TRUE); */ - } - else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - strtolower(attstring); - - if ( memcmp(attstring, "ignore", 6) == 0 ) - { - ncvars[ncvarid].ignore = TRUE; - cdfSetVar(ncvars, ncvarid, FALSE); - } - } - else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - attlen = strlen(attstring); - - if ( (int) attlen > nvdims && nvdims > 0 && attlen > 1 ) - { - Warning("Unexpected axis attribute length for %s, ignored!", name); - } - else if ( nvdims == 0 && attlen == 1 ) - { - if ( attstring[0] == 'z' || attstring[0] == 'Z' ) - { - cdfSetVar(ncvars, ncvarid, FALSE); - ncvars[ncvarid].islev = TRUE; - } - } - else - { - strtolower(attstring); - int i; - for ( i = 0; i < (int)attlen; ++i ) - { - if ( attstring[i] != '-' && attstring[i] != 't' && attstring[i] != 'z' && - attstring[i] != 'y' && attstring[i] != 'x' ) - { - Warning("Unexpected character in axis attribute for %s, ignored!", name); - break; - } - } - - if ( i == (int) attlen && (int) attlen == nvdims ) - { - while ( attlen-- ) - { - if ( (int) attstring[attlen] == 't' ) - { - if ( attlen != 0 ) Warning("axis attribute 't' not on first position"); - cdfSetDim(ncvars, ncvarid, (int)attlen, T_AXIS); - } - else if ( (int) attstring[attlen] == 'z' ) - { - ncvars[ncvarid].zdim = dimidsp[attlen]; - cdfSetDim(ncvars, ncvarid, (int)attlen, Z_AXIS); - - if ( ncvars[ncvarid].ndims == 1 ) - { - cdfSetVar(ncvars, ncvarid, FALSE); - ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS; - } - } - else if ( (int) attstring[attlen] == 'y' ) - { - ncvars[ncvarid].ydim = dimidsp[attlen]; - cdfSetDim(ncvars, ncvarid, (int)attlen, Y_AXIS); - - if ( ncvars[ncvarid].ndims == 1 ) - { - cdfSetVar(ncvars, ncvarid, FALSE); - ncdims[ncvars[ncvarid].dimids[0]].dimtype = Y_AXIS; - } - } - else if ( (int) attstring[attlen] == 'x' ) - { - ncvars[ncvarid].xdim = dimidsp[attlen]; - cdfSetDim(ncvars, ncvarid, (int)attlen, X_AXIS); - - if ( ncvars[ncvarid].ndims == 1 ) - { - cdfSetVar(ncvars, ncvarid, FALSE); - ncdims[ncvars[ncvarid].dimids[0]].dimtype = X_AXIS; - } - } - } - } - } - } - else if ( ( strcmp(attname, "realization") == 0 ) || - ( strcmp(attname, "ensemble_members") == 0 ) || - ( strcmp(attname, "forecast_init_type") == 0 ) ) - { - int temp; - - if( ncvars[ncvarid].ensdata == NULL ) - ncvars[ncvarid].ensdata = (ensinfo_t *) Malloc( sizeof( ensinfo_t ) ); - - cdfGetAttInt(ncid, ncvarid, attname, 1, &temp); - - if( strcmp(attname, "realization") == 0 ) - ncvars[ncvarid].ensdata->ens_index = temp; - else if( strcmp(attname, "ensemble_members") == 0 ) - ncvars[ncvarid].ensdata->ens_count = temp; - else if( strcmp(attname, "forecast_init_type") == 0 ) - ncvars[ncvarid].ensdata->forecast_init_type = temp; - - cdfSetVar(ncvars, ncvarid, TRUE); - } - else - { - if ( ncvars[ncvarid].natts == 0 ) - ncvars[ncvarid].atts - = (int *) Malloc((size_t)nvatts * sizeof (int)); - - ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt; - /* - int attrint; - double attrflt; - nc_type attrtype; - cdf_inq_attlen(ncid, ncvarid, attname, &attlen); - cdf_inq_atttype(ncid, ncvarid, attname, &attrtype); - if ( attlen == 1 && (attrtype == NC_INT || attrtype == NC_SHORT) ) - { - cdfGetAttInt(ncid, ncvarid, attname, 1, &attrint); - printf("int: %s.%s = %d\n", ncvars[ncvarid].name, attname, attrint); - } - else if ( attlen == 1 && (attrtype == NC_FLOAT || attrtype == NC_DOUBLE) ) - { - cdfGetAttDouble(ncid, ncvarid, attname, 1, &attrflt); - printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attrflt); - } - else if ( attrtype == NC_CHAR ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - attstring[attlen] = 0; - printf("txt: %s.%s = %s\n", ncvars[ncvarid].name, attname, attstring); - } - else - printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname); - */ - } - } - } - - for ( int i = 0; i < max_check_vars; ++i ) if ( checked_vars[i] ) Free(checked_vars[i]); -} - -static -void setDimType(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) -{ - int ndims; - int ncvarid, ncdimid; - int i; - - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].isvar == TRUE ) - { - int lxdim = 0, lydim = 0, lzdim = 0/* , ltdim = 0 */; - ndims = ncvars[ncvarid].ndims; - for ( i = 0; i < ndims; i++ ) - { - ncdimid = ncvars[ncvarid].dimids[i]; - if ( ncdims[ncdimid].dimtype == X_AXIS ) cdfSetDim(ncvars, ncvarid, i, X_AXIS); - else if ( ncdims[ncdimid].dimtype == Y_AXIS ) cdfSetDim(ncvars, ncvarid, i, Y_AXIS); - else if ( ncdims[ncdimid].dimtype == Z_AXIS ) cdfSetDim(ncvars, ncvarid, i, Z_AXIS); - else if ( ncdims[ncdimid].dimtype == T_AXIS ) cdfSetDim(ncvars, ncvarid, i, T_AXIS); - } - - if ( CDI_Debug ) - { - Message("var %d %s", ncvarid, ncvars[ncvarid].name); - for ( i = 0; i < ndims; i++ ) - printf(" dim%d type=%d ", i, ncvars[ncvarid].dimtype[i]); - printf("\n"); - } - - for ( i = 0; i < ndims; i++ ) - { - if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) lxdim = TRUE; - else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) lydim = TRUE; - else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) lzdim = TRUE; - /* else if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) ltdim = TRUE; */ - } - - if ( lxdim == FALSE && ncvars[ncvarid].xvarid != UNDEFID ) - { - if ( ncvars[ncvars[ncvarid].xvarid].ndims == 0 ) lxdim = TRUE; - } - - if ( lydim == FALSE && ncvars[ncvarid].yvarid != UNDEFID ) - { - if ( ncvars[ncvars[ncvarid].yvarid].ndims == 0 ) lydim = TRUE; - } - - // if ( ndims > 1 ) - for ( i = ndims-1; i >= 0; i-- ) - { - if ( ncvars[ncvarid].dimtype[i] == -1 ) - { - if ( lxdim == FALSE ) - { - cdfSetDim(ncvars, ncvarid, i, X_AXIS); - lxdim = TRUE; - } - else if ( lydim == FALSE && ncvars[ncvarid].gridtype != GRID_UNSTRUCTURED ) - { - cdfSetDim(ncvars, ncvarid, i, Y_AXIS); - lydim = TRUE; - } - else if ( lzdim == FALSE ) - { - cdfSetDim(ncvars, ncvarid, i, Z_AXIS); - lzdim = TRUE; - } - } - } - } - } -} - -/* verify coordinate vars - first scan (dimname == varname) */ -static -void verify_coordinate_vars_1(int ncid, int ndims, ncdim_t *ncdims, ncvar_t *ncvars, int timedimid) -{ - int ncdimid, ncvarid; - - for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) - { - ncvarid = ncdims[ncdimid].ncvarid; - if ( ncvarid != -1 ) - { - if ( ncvars[ncvarid].dimids[0] == timedimid ) - { - ncvars[ncvarid].istime = TRUE; - ncdims[ncdimid].dimtype = T_AXIS; - continue; - } - - if ( isHybridSigmaPressureCoordinate(ncid, ncvarid, ncvars, ncdims) ) continue; - - if ( ncvars[ncvarid].units[0] != 0 ) - { - if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) - { - ncvars[ncvarid].islon = TRUE; - cdfSetVar(ncvars, ncvarid, FALSE); - cdfSetDim(ncvars, ncvarid, 0, X_AXIS); - ncdims[ncdimid].dimtype = X_AXIS; - } - else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) - { - ncvars[ncvarid].islat = TRUE; - cdfSetVar(ncvars, ncvarid, FALSE); - cdfSetDim(ncvars, ncvarid, 0, Y_AXIS); - ncdims[ncdimid].dimtype = Y_AXIS; - } - else if ( unitsIsPressure(ncvars[ncvarid].units) ) - { - ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE; - } - else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 ) - { - if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; - else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; - else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; - else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; - else if ( strcmp(ncvars[ncvarid].units, "level") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_GENERIC; - } - else if ( isDBLAxis(ncvars[ncvarid].longname) ) - { - ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND; - } - else if ( unitsIsHeight(ncvars[ncvarid].units) ) - { - if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) - ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA; - else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) - ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT; - } - } - else - { - if ( (strcmp(ncvars[ncvarid].longname, "generalized_height") == 0 || - strcmp(ncvars[ncvarid].longname, "generalized height") == 0) && - strcmp(ncvars[ncvarid].stdname, "height") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_REFERENCE; - } - - if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 && - ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 ) - { - if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 ) - { - ncvars[ncvarid].islon = TRUE; - cdfSetVar(ncvars, ncvarid, FALSE); - cdfSetDim(ncvars, ncvarid, 0, X_AXIS); - ncdims[ncdimid].dimtype = X_AXIS; - continue; - } - else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 ) - { - ncvars[ncvarid].islat = TRUE; - cdfSetVar(ncvars, ncvarid, FALSE); - cdfSetDim(ncvars, ncvarid, 0, Y_AXIS); - ncdims[ncdimid].dimtype = Y_AXIS; - continue; - } - } - - if ( ncvars[ncvarid].zaxistype != UNDEFID ) - { - ncvars[ncvarid].islev = TRUE; - cdfSetVar(ncvars, ncvarid, FALSE); - cdfSetDim(ncvars, ncvarid, 0, Z_AXIS); - ncdims[ncdimid].dimtype = Z_AXIS; - } - } - } -} - -/* verify coordinate vars - second scan (all other variables) */ -static -void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars) -{ - int ncvarid; - - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].isvar == 0 ) - { - if ( ncvars[ncvarid].units[0] != 0 ) - { - if ( isLonAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) - { - ncvars[ncvarid].islon = TRUE; - continue; - } - else if ( isLatAxis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) - { - ncvars[ncvarid].islat = TRUE; - continue; - } - else if ( unitsIsPressure(ncvars[ncvarid].units) ) - { - ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE; - continue; - } - else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 ) - { - if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; - else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; - else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; - else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; - else if ( strcmp(ncvars[ncvarid].units, "level") == 0 ) - ncvars[ncvarid].zaxistype = ZAXIS_GENERIC; - continue; - } - else if ( isDBLAxis(ncvars[ncvarid].longname) ) - { - ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND; - continue; - } - else if ( unitsIsHeight(ncvars[ncvarid].units) ) - { - if ( isDepthAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) - ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA; - else if ( isHeightAxis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) - ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT; - continue; - } - } - - /* not needed anymore for rotated grids */ - if ( ncvars[ncvarid].islon == FALSE && ncvars[ncvarid].longname[0] != 0 && - ncvars[ncvarid].islat == FALSE && ncvars[ncvarid].longname[1] != 0 ) - { - if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 ) - { - ncvars[ncvarid].islon = TRUE; - continue; - } - else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 ) - { - ncvars[ncvarid].islat = TRUE; - continue; - } - } - } - } -} - -#if defined (PROJECTION_TEST) -static -void copy_numeric_projatts(int gridID, int ncvarID, int ncfileID) -{ - int iatt, nvatts; - size_t attlen; - char attname[CDI_MAX_NAME]; - nc_type xtype; - - cdf_inq_varnatts(ncfileID, ncvarID, &nvatts); - - for ( iatt = 0; iatt < nvatts; iatt++ ) - { - cdf_inq_attname(ncfileID, ncvarID, iatt, attname); - cdf_inq_atttype(ncfileID, ncvarID, attname, &xtype); - cdf_inq_attlen(ncfileID, ncvarID, attname, &attlen); - - // printf("%s %d\n", attname, (int)attlen); - } - -} -#endif - -static -void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar) -{ - if ( ncvar->chunked ) - { - int ndims = ncvar->ndims; - - if ( grid->type == GRID_UNSTRUCTURED ) - { - if ( ncvar->chunks[ndims-1] == grid->size ) - ncvar->chunktype = CHUNK_GRID; - else - ncvar->chunktype = CHUNK_AUTO; - } - else - { - if ( grid->xsize > 1 && grid->ysize > 1 && ndims > 1 && - grid->xsize == ncvar->chunks[ndims-1] && - grid->ysize == ncvar->chunks[ndims-2] ) - ncvar->chunktype = CHUNK_GRID; - else if ( grid->xsize > 1 && grid->xsize == ncvar->chunks[ndims-1] ) - ncvar->chunktype = CHUNK_LINES; - else - ncvar->chunktype = CHUNK_AUTO; - } - } -} - -static struct gridVirtTable cdfLazyGridVtable; -static double *cdfPendingLoad; -#ifdef HAVE_LIBPTHREAD -static pthread_once_t cdfLazyInitialized = PTHREAD_ONCE_INIT; -#else -static bool cdfLazyInitialized; -#endif - -struct cdfLazyGrid -{ - grid_t base; - const struct gridVirtTable *baseVtable; - struct { - int datasetNCId, varNCId; - } cellAreaGet, xBoundsGet, yBoundsGet; - struct xyValGet { - double scalefactor, addoffset; - size_t start[3], count[3], size, dimsize; - int datasetNCId, varNCId; - short ndims; - } xValsGet, yValsGet; -#ifdef HAVE_LIBPTHREAD - pthread_mutex_t loadSerialize; -#endif -}; - -#ifdef HAVE_LIBPTHREAD -#define lock_lazy_load(plGrid) pthread_mutex_lock(&((plGrid)->loadSerialize)) -#define unlock_lazy_load(plGrid) pthread_mutex_unlock(&((plGrid)->loadSerialize)) -#define destroy_lazy_load_lock(plGrid) pthread_mutex_destroy(&((plGrid)->loadSerialize)) -#define init_lazy_load_lock(plGrid) pthread_mutex_init(&((plGrid)->loadSerialize), NULL) -#else -#define lock_lazy_load(plGrid) -#define unlock_lazy_load(plGrid) -#define destroy_lazy_load_lock(plGrid) -#define init_lazy_load_lock(plGrid) -#endif - -static void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid) -{ - lazyGrid->base.extraData = NULL; - if (lazyGrid->base.area == cdfPendingLoad) - lazyGrid->base.area = NULL; - if (lazyGrid->base.xvals == cdfPendingLoad) - lazyGrid->base.xvals = NULL; - if (lazyGrid->base.yvals == cdfPendingLoad) - lazyGrid->base.yvals = NULL; - if (lazyGrid->base.xbounds == cdfPendingLoad) - lazyGrid->base.xbounds = NULL; - if (lazyGrid->base.ybounds == cdfPendingLoad) - lazyGrid->base.ybounds = NULL; - destroy_lazy_load_lock(lazyGrid); -} - -static void cdfLazyGridDelete(grid_t *grid) -{ - struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; - void (*baseDestroy)(grid_t *grid) = cdfGrid->baseVtable->destroy; - cdfLazyGridDestroy(cdfGrid); - baseDestroy(grid); -} - -static void cdfLazyGridDestroyOnce(void) -{ - /* -#ifdef HAVE_MMAP - size_t pgSize = cdiGetPageSize(false); - munmap(cdfPendingLoad, pgSize); -#endif - */ -} - -static void -cdfLazyGridDefArea(grid_t *grid, const double *area) -{ - struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(cdfGrid); - if (grid->area == cdfPendingLoad) - grid->area = NULL; - cdfGrid->cellAreaGet.datasetNCId = -1; - cdfGrid->cellAreaGet.varNCId = -1; - cdfGrid->baseVtable->defArea(grid, area); - unlock_lazy_load(cdfGrid); -} - - -static const double * -cdfLazyGridInqAreaPtr(grid_t *grid) -{ - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(lazyGrid); - if (grid->area == cdfPendingLoad) - { - grid->area = (double *)Malloc((size_t)grid->size * sizeof(double)); - cdf_get_var_double(lazyGrid->cellAreaGet.datasetNCId, - lazyGrid->cellAreaGet.varNCId, grid->area); - } - unlock_lazy_load(lazyGrid); - return lazyGrid->baseVtable->inqAreaPtr(grid); -} - -static void -cdfLazyGridInqArea(grid_t *grid, double *area) -{ - grid->vtable->inqAreaPtr(grid); - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lazyGrid->baseVtable->inqArea(grid, area); -} - - -static void -cdfLazyLoadXYVals(struct xyValGet *valsGet, double **valsp) -{ - double *grid_vals - = (double *)Malloc(valsGet->size * sizeof (double)); - *valsp = grid_vals; - if ( valsGet->ndims == 3 ) - cdf_get_vara_double(valsGet->datasetNCId, valsGet->varNCId, - valsGet->start, valsGet->count, grid_vals); - else - cdf_get_var_double(valsGet->datasetNCId, valsGet->varNCId, grid_vals); - scale_add(valsGet->size, grid_vals, valsGet->addoffset, valsGet->scalefactor); -} - -static const double * -cdfLazyGridInqXValsPtr(grid_t *grid) -{ - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(lazyGrid); - if (grid->xvals == cdfPendingLoad) - cdfLazyLoadXYVals(&lazyGrid->xValsGet, &grid->xvals); - unlock_lazy_load(lazyGrid); - return lazyGrid->baseVtable->inqXValsPtr(grid); -} - -static const double * -cdfLazyGridInqYValsPtr(grid_t *grid) -{ - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(lazyGrid); - if (grid->yvals == cdfPendingLoad) - cdfLazyLoadXYVals(&lazyGrid->yValsGet, &grid->yvals); - unlock_lazy_load(lazyGrid); - return lazyGrid->baseVtable->inqYValsPtr(grid); -} - -static double -cdfLazyGridInqXYVal(grid_t *grid, size_t index, - const struct xyValGet *valsGet, double *vals, - const double *(*inqValsPtr)(grid_t *gridptr)) -{ - size_t size = valsGet->size; - double v; - if ( vals == cdfPendingLoad ) - { - /* prevent full load if only first/last values get inspected */ - if ( index == 0 || index == size - 1 ) - { - size_t indexND[3]; - if ( valsGet->ndims == 3 ) - { - indexND[0] = 0; - indexND[1] = index / valsGet->count[2]; - indexND[2] = index % valsGet->count[2]; - } - else if ( valsGet->ndims == 2) - { - indexND[0] = index / (size_t)grid->xsize; - indexND[1] = index % (size_t)grid->xsize; - } - else - indexND[0] = index; - cdf_get_var1_double(valsGet->datasetNCId, valsGet->varNCId, - indexND, &v); - } - else - { - const double *grid_vals = inqValsPtr(grid); - v = grid_vals[index]; - } - } - else if ( vals ) - v = vals[index]; - else - v = 0.0; - return v; -} - -static void -cdfLazyGridDefXVals(grid_t *grid, const double *vals) -{ - struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(cdfGrid); - if (grid->xvals == cdfPendingLoad) - grid->xvals = NULL; - cdfGrid->xValsGet.datasetNCId = -1; - cdfGrid->xValsGet.varNCId = -1; - cdfGrid->baseVtable->defXVals(grid, vals); - unlock_lazy_load(cdfGrid); -} - -static void -cdfLazyGridDefYVals(grid_t *grid, const double *vals) -{ - struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(cdfGrid); - if (grid->yvals == cdfPendingLoad) - grid->yvals = NULL; - cdfGrid->yValsGet.datasetNCId = -1; - cdfGrid->yValsGet.varNCId = -1; - cdfGrid->baseVtable->defYVals(grid, vals); - unlock_lazy_load(cdfGrid); -} - -static double -cdfLazyGridInqXVal(grid_t *grid, int index) -{ - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(lazyGrid); - double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->xValsGet, - grid->xvals, grid->vtable->inqXValsPtr); - unlock_lazy_load(lazyGrid); - return rv; -} - -static double -cdfLazyGridInqYVal(grid_t *grid, int index) -{ - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(lazyGrid); - double rv = cdfLazyGridInqXYVal(grid, (size_t)index, &lazyGrid->yValsGet, - grid->yvals, grid->vtable->inqYValsPtr); - unlock_lazy_load(lazyGrid); - return rv; -} - -static bool -cdfLazyXYValGetCompare(struct cdfLazyGrid *lazyGridRef, - struct cdfLazyGrid *lazyGridTest) -{ - struct xyValGet *valsGetXRef = &lazyGridRef->xValsGet, - *valsGetYRef = &lazyGridRef->yValsGet, - *valsGetXTest = &lazyGridTest->xValsGet, - *valsGetYTest = &lazyGridTest->yValsGet; - if (valsGetXRef->datasetNCId == -1 - || valsGetXTest->datasetNCId == -1 - || valsGetYRef->datasetNCId == -1 - || valsGetYTest->datasetNCId == -1) - return lazyGridRef->baseVtable->compareXYFull(&lazyGridRef->base, - &lazyGridTest->base); - return valsGetXRef->datasetNCId != valsGetXTest->datasetNCId - || valsGetXRef->varNCId != valsGetXTest->varNCId - || valsGetYRef->datasetNCId != valsGetYTest->datasetNCId - || valsGetYRef->varNCId != valsGetYTest->varNCId; -} - -static bool -cdfLazyCompareXYFull(grid_t *gridRef, grid_t *gridTest) -{ - bool diff; - struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef; - if (gridTest->vtable == &cdfLazyGridVtable) - diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest); - else - diff = lazyGridRef->baseVtable->compareXYFull(gridRef, gridTest); - return diff; -} - -static bool -cdfLazyCompareXYAO(grid_t *gridRef, grid_t *gridTest) -{ - bool diff; - struct cdfLazyGrid *lazyGridRef = (struct cdfLazyGrid *)gridRef; - if (gridTest->vtable == &cdfLazyGridVtable) - diff = cdfLazyXYValGetCompare(lazyGridRef, (struct cdfLazyGrid *)gridTest); - else - diff = lazyGridRef->baseVtable->compareXYAO(gridRef, gridTest); - return diff; -} - - -static const double * -cdfLazyGridInqXBoundsPtr(grid_t *grid) -{ - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(lazyGrid); - if (grid->xbounds == cdfPendingLoad) - { - grid->xbounds = (double *)Malloc((size_t)grid->nvertex - * (size_t)grid->size * sizeof(double)); - cdf_get_var_double(lazyGrid->xBoundsGet.datasetNCId, - lazyGrid->xBoundsGet.varNCId, grid->xbounds); - } - unlock_lazy_load(lazyGrid); - return lazyGrid->baseVtable->inqXBoundsPtr(grid); -} - -static void -cdfLazyGridDefXBounds(grid_t *grid, const double *xbounds) -{ - struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(cdfGrid); - if (grid->xbounds == cdfPendingLoad) - grid->xbounds = NULL; - cdfGrid->xBoundsGet.datasetNCId = -1; - cdfGrid->xBoundsGet.varNCId = -1; - cdfGrid->baseVtable->defXBounds(grid, xbounds); - unlock_lazy_load(cdfGrid); -} - -static void -cdfLazyGridDefYBounds(grid_t *grid, const double *ybounds) -{ - struct cdfLazyGrid *cdfGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(cdfGrid); - if (grid->ybounds == cdfPendingLoad) - grid->ybounds = NULL; - cdfGrid->yBoundsGet.datasetNCId = -1; - cdfGrid->yBoundsGet.varNCId = -1; - cdfGrid->baseVtable->defYBounds(grid, ybounds); - unlock_lazy_load(cdfGrid); -} - -static const double * -cdfLazyGridInqYBoundsPtr(grid_t *grid) -{ - struct cdfLazyGrid *lazyGrid = (struct cdfLazyGrid *)grid; - lock_lazy_load(lazyGrid); - if (grid->ybounds == cdfPendingLoad) - { - grid->ybounds = (double *)Malloc((size_t)grid->nvertex - * (size_t)grid->size * sizeof(double)); - cdf_get_var_double(lazyGrid->yBoundsGet.datasetNCId, - lazyGrid->yBoundsGet.varNCId, grid->ybounds); - } - unlock_lazy_load(lazyGrid); - return lazyGrid->baseVtable->inqYBoundsPtr(grid); -} - -static void -cdfLazyGridCopyScalarFields(grid_t *gridptrOrig, grid_t *gridptrDup) -{ - struct cdfLazyGrid *lazyGridDup = (struct cdfLazyGrid *)gridptrDup, - *lazyGridOrig = (struct cdfLazyGrid *)gridptrOrig; - lazyGridOrig->baseVtable->copyScalarFields(gridptrOrig, &lazyGridDup->base); - lazyGridDup->baseVtable = lazyGridOrig->baseVtable; - lazyGridDup->cellAreaGet = lazyGridOrig->cellAreaGet; - lazyGridDup->xBoundsGet = lazyGridOrig->xBoundsGet; - lazyGridDup->yBoundsGet = lazyGridOrig->yBoundsGet; - lazyGridDup->xValsGet = lazyGridOrig->xValsGet; - lazyGridDup->yValsGet = lazyGridOrig->yValsGet; - init_lazy_load_lock(lazyGridDup); -} - -static void -cdfLazyGridCopyArrayFields(grid_t *gridptrOrig, grid_t *gridptrDup) -{ - size_t nrowlon = (size_t)gridptrOrig->nrowlon; - size_t gridsize = (size_t)gridptrOrig->size; - int gridtype = gridptrOrig->type; - int irregular = gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED; - if ( nrowlon ) - { - gridptrDup->rowlon = (int *)Malloc(nrowlon * sizeof (int)); - memcpy(gridptrDup->rowlon, gridptrOrig->rowlon, nrowlon * sizeof(int)); - } - - if ( gridptrOrig->xvals != NULL && gridptrOrig->xvals != cdfPendingLoad ) - { - size_t size = irregular ? gridsize : (size_t)gridptrOrig->xsize; - - gridptrDup->xvals = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->xvals, gridptrOrig->xvals, size * sizeof (double)); - } - - if ( gridptrOrig->yvals != NULL && gridptrOrig->yvals != cdfPendingLoad ) - { - size_t size = irregular ? gridsize : (size_t)gridptrOrig->ysize; - - gridptrDup->yvals = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->yvals, gridptrOrig->yvals, size * sizeof (double)); - } - - if ( gridptrOrig->xbounds != NULL && gridptrOrig->xbounds != cdfPendingLoad ) - { - size_t size = (irregular ? gridsize : (size_t)gridptrOrig->xsize) - * (size_t)gridptrOrig->nvertex; - - gridptrDup->xbounds = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->xbounds, gridptrOrig->xbounds, size * sizeof (double)); - } - - if ( gridptrOrig->ybounds != NULL && gridptrOrig->ybounds != cdfPendingLoad ) - { - size_t size = (irregular ? gridsize : (size_t)gridptrOrig->ysize) - * (size_t)gridptrOrig->nvertex; - - gridptrDup->ybounds = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->ybounds, gridptrOrig->ybounds, size * sizeof (double)); - } - - { - if ( gridptrOrig->area != NULL && gridptrOrig->area != cdfPendingLoad ) - { - size_t size = gridsize; - - gridptrDup->area = (double *)Malloc(size * sizeof (double)); - memcpy(gridptrDup->area, gridptrOrig->area, size * sizeof (double)); - } - } - - if ( gridptrOrig->mask != NULL ) - { - size_t size = gridsize; - - gridptrDup->mask = (mask_t *)Malloc(size * sizeof(mask_t)); - memcpy(gridptrDup->mask, gridptrOrig->mask, size * sizeof (mask_t)); - } - - if ( gridptrOrig->mask_gme != NULL ) - { - size_t size = gridsize; - - gridptrDup->mask_gme = (mask_t *)Malloc(size * sizeof (mask_t)); - memcpy(gridptrDup->mask_gme, gridptrOrig->mask_gme, size * sizeof(mask_t)); - } -} - -static grid_t * -cdfLazyGridCopy(grid_t *gridptrOrig) -{ - struct cdfLazyGrid *lazyGridDup - = (struct cdfLazyGrid *)Malloc(sizeof (*lazyGridDup)); - gridptrOrig->vtable->copyScalarFields(gridptrOrig, &lazyGridDup->base); - gridptrOrig->vtable->copyArrayFields(gridptrOrig, &lazyGridDup->base); - return &lazyGridDup->base; -} - -static void -cdfLazyGridInitOnce(void) -{ - cdfLazyGridVtable = cdiGridVtable; - cdfLazyGridVtable.destroy = cdfLazyGridDelete; - cdfLazyGridVtable.copy = cdfLazyGridCopy; - cdfLazyGridVtable.copyScalarFields = cdfLazyGridCopyScalarFields; - cdfLazyGridVtable.copyArrayFields = cdfLazyGridCopyArrayFields; - cdfLazyGridVtable.defArea = cdfLazyGridDefArea; - cdfLazyGridVtable.inqAreaPtr = cdfLazyGridInqAreaPtr; - cdfLazyGridVtable.inqArea = cdfLazyGridInqArea; - cdfLazyGridVtable.inqXValsPtr = cdfLazyGridInqXValsPtr; - cdfLazyGridVtable.inqYValsPtr = cdfLazyGridInqYValsPtr; - cdfLazyGridVtable.inqXVal = cdfLazyGridInqXVal; - cdfLazyGridVtable.inqYVal = cdfLazyGridInqYVal; - cdfLazyGridVtable.defXVals = cdfLazyGridDefXVals; - cdfLazyGridVtable.defYVals = cdfLazyGridDefYVals; - cdfLazyGridVtable.compareXYFull = cdfLazyCompareXYFull; - cdfLazyGridVtable.compareXYAO = cdfLazyCompareXYAO; - cdfLazyGridVtable.defXBounds = cdfLazyGridDefXBounds; - cdfLazyGridVtable.defYBounds = cdfLazyGridDefYBounds; - cdfLazyGridVtable.inqXBoundsPtr = cdfLazyGridInqXBoundsPtr; - cdfLazyGridVtable.inqYBoundsPtr = cdfLazyGridInqYBoundsPtr; - /* create inaccessible memory area, if possible, this serves as - * dummy value for pointers to data not yet loaded */ - /* -#ifdef HAVE_MMAP - { - size_t pgSize = cdiGetPageSize(false); - static const char devZero[] = "/dev/zero"; - int fd = open(devZero, O_RDWR); - if (fd == -1) - SysError("Could not open %s to map anonymous memory", devZero); - void *cdfInvalid = mmap(NULL, pgSize, PROT_NONE, MAP_PRIVATE, fd, 0); - if (cdfInvalid == MAP_FAILED) - SysError("Could not mmap anonymous memory"); - cdfPendingLoad = cdfInvalid; - int rc = close(fd); - if (rc == -1) - SysError("Could not close %s file handle %d after mapping anonymous" - " memory", devZero, fd); - } -#else - */ - cdfPendingLoad = (double *)&cdfPendingLoad; - //#endif - atexit(cdfLazyGridDestroyOnce); -#ifndef HAVE_LIBPTHREAD - cdfLazyInitialized = true; -#endif -} - -static void -cdfBaseGridInit(grid_t *grid, int gridtype) -{ - grid_init(grid); - cdiGridTypeInit(grid, gridtype, 0); -} - -static void -cdfLazyGridInit(struct cdfLazyGrid *grid, int gridtype) -{ -#ifdef HAVE_LIBPTHREAD - pthread_once(&cdfLazyInitialized, cdfLazyGridInitOnce); -#else - if (cdfLazyInitialized) ; else cdfLazyGridInitOnce(); -#endif - cdfBaseGridInit(&grid->base, gridtype); - grid->baseVtable = grid->base.vtable; - grid->cellAreaGet.datasetNCId = -1; - grid->cellAreaGet.varNCId = -1; - grid->xValsGet.datasetNCId = -1; - grid->xValsGet.varNCId = -1; - grid->yValsGet.datasetNCId = -1; - grid->yValsGet.varNCId = -1; - grid->xBoundsGet.datasetNCId = -1; - grid->xBoundsGet.varNCId = -1; - grid->yBoundsGet.datasetNCId = -1; - grid->yBoundsGet.varNCId = -1; - grid->base.vtable = &cdfLazyGridVtable; - init_lazy_load_lock(grid); -} - -static void -cdfLazyGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype) -{ - struct cdfLazyGrid *restrict grid = *gridpptr; - if (!grid) - *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (*grid)); - cdfLazyGridInit(grid, gridtype); -} - -static void -cdfBaseGridRenew(struct cdfLazyGrid *restrict *restrict gridpptr, int gridtype) -{ - struct cdfLazyGrid *restrict grid = *gridpptr; - if (!grid) - *gridpptr = grid = (struct cdfLazyGrid *)Malloc(sizeof (grid_t)); - cdfBaseGridInit((grid_t*)grid, gridtype); -} - - -/* define all input grids */ -static -void define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, int timedimid, unsigned char *uuidOfHGrid, char *gridfile, int number_of_grid_used) -{ - int ltwarn = TRUE; - struct cdfLazyGrid *restrict lazyGrid = NULL, *restrict lazyProj = NULL; -#define grid (&lazyGrid->base) -#define proj (&lazyProj->base) - - for ( int ncvarid = 0; ncvarid < nvars; ++ncvarid ) - { - if ( ncvars[ncvarid].isvar && ncvars[ncvarid].gridID == UNDEFID ) - { - int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1}; - int xdimid = -1, ydimid = -1; - int vdimid = -1; - int islon = 0, islat = 0; - int nxdims = 0, nydims = 0; - size_t size = 0; - size_t xsize = 0, ysize = 0; - double yinc = 0; - struct addIffNewRes projAdded = { .Id = CDI_UNDEFID, .isNew = 0 }, - gridAdded = { .Id = CDI_UNDEFID, .isNew = 0 }; - - int ndims = ncvars[ncvarid].ndims; - for ( int i = 0; i < ndims; i++ ) - { - if ( ncvars[ncvarid].dimtype[i] == X_AXIS && nxdims < 2 ) - { - xdimids[nxdims] = ncvars[ncvarid].dimids[i]; - nxdims++; - } - else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS && nydims < 2 ) - { - ydimids[nydims] = ncvars[ncvarid].dimids[i]; - nydims++; - } - } - - if ( nxdims == 2 ) - { - xdimid = xdimids[1]; - ydimid = xdimids[0]; - } - else if ( nydims == 2 ) - { - xdimid = ydimids[1]; - ydimid = ydimids[0]; - } - else - { - xdimid = xdimids[0]; - ydimid = ydimids[0]; - } - - int xvarid = ncvars[ncvarid].xvarid != UNDEFID - ? ncvars[ncvarid].xvarid - : (xdimid != UNDEFID ? ncdims[xdimid].ncvarid : -1); - int yvarid = ncvars[ncvarid].yvarid != UNDEFID - ? ncvars[ncvarid].yvarid - : (ydimid != UNDEFID ? ncdims[ydimid].ncvarid : -1); - - /* - if ( xdimid != UNDEFID ) - xvarid = ncdims[xdimid].ncvarid; - if ( xvarid == UNDEFID && ncvars[ncvarid].xvarid != UNDEFID ) - xvarid = ncvars[ncvarid].xvarid; - - if ( ydimid != UNDEFID ) - yvarid = ncdims[ydimid].ncvarid; - if ( yvarid == UNDEFID && ncvars[ncvarid].yvarid != UNDEFID ) - yvarid = ncvars[ncvarid].yvarid; - */ - - if ( xdimid != UNDEFID ) xsize = ncdims[xdimid].len; - if ( ydimid != UNDEFID ) ysize = ncdims[ydimid].len; - - if ( ydimid == UNDEFID && yvarid != UNDEFID ) - { - if ( ncvars[yvarid].ndims == 1 ) - { - ydimid = ncvars[yvarid].dimids[0]; - ysize = ncdims[ydimid].len; - } - } - - if ( ncvars[ncvarid].gridtype == UNDEFID || ncvars[ncvarid].gridtype == GRID_GENERIC ) - if ( xdimid != UNDEFID && xdimid == ydimid && nydims == 0 ) ncvars[ncvarid].gridtype = GRID_UNSTRUCTURED; - - if (CDI_netcdf_lazy_grid_load) - { - cdfLazyGridRenew(&lazyGrid, ncvars[ncvarid].gridtype); - cdfLazyGridRenew(&lazyProj, GRID_PROJECTION); - } - else - { - cdfBaseGridRenew(&lazyGrid, ncvars[ncvarid].gridtype); - cdfBaseGridRenew(&lazyProj, GRID_PROJECTION); - } - - grid->prec = DATATYPE_FLT64; - grid->trunc = ncvars[ncvarid].truncation; - - if ( ncvars[ncvarid].gridtype == GRID_TRAJECTORY ) - { - if ( ncvars[ncvarid].xvarid == UNDEFID ) - Error("Longitude coordinate undefined for %s!", ncvars[ncvarid].name); - if ( ncvars[ncvarid].yvarid == UNDEFID ) - Error("Latitude coordinate undefined for %s!", ncvars[ncvarid].name); - } - else - { - size_t start[3], count[3]; - int ltgrid = FALSE; - - if ( xvarid != UNDEFID && yvarid != UNDEFID ) - { - if ( ncvars[xvarid].ndims != ncvars[yvarid].ndims ) - { - Warning("Inconsistent grid structure for variable %s!", ncvars[ncvarid].name); - ncvars[ncvarid].xvarid = UNDEFID; - ncvars[ncvarid].yvarid = UNDEFID; - xvarid = UNDEFID; - yvarid = UNDEFID; - } - - if ( ncvars[xvarid].ndims > 2 || ncvars[yvarid].ndims > 2 ) - { - if ( ncvars[xvarid].ndims == 3 && ncvars[xvarid].dimids[0] == timedimid && - ncvars[yvarid].ndims == 3 && ncvars[yvarid].dimids[0] == timedimid ) - { - if ( ltwarn ) - Warning("Time varying grids unsupported, using grid at time step 1!"); - ltgrid = TRUE; - ltwarn = FALSE; - start[0] = start[1] = start[2] = 0; - count[0] = 1; count[1] = ysize; count[2] = xsize; - } - else - { - Warning("Unsupported grid structure for variable %s (grid dims > 2)!", ncvars[ncvarid].name); - ncvars[ncvarid].xvarid = UNDEFID; - ncvars[ncvarid].yvarid = UNDEFID; - xvarid = UNDEFID; - yvarid = UNDEFID; - } - } - } - - if ( xvarid != UNDEFID ) - { - if ( ncvars[xvarid].ndims > 3 || (ncvars[xvarid].ndims == 3 && ltgrid == FALSE) ) - { - Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[xvarid].name, ncvars[xvarid].ndims); - //ncvars[ncvarid].xvarid = UNDEFID; - xvarid = UNDEFID; - } - } - - if ( yvarid != UNDEFID ) - { - if ( ncvars[yvarid].ndims > 3 || (ncvars[yvarid].ndims == 3 && ltgrid == FALSE) ) - { - Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[yvarid].name, ncvars[yvarid].ndims); - //ncvars[ncvarid].yvarid = UNDEFID; - yvarid = UNDEFID; - } - } - - if ( xvarid != UNDEFID ) - { - bool skipvar = true; - islon = ncvars[xvarid].islon; - ndims = ncvars[xvarid].ndims; - if ( ndims == 2 || ndims == 3 ) - { - ncvars[ncvarid].gridtype = GRID_CURVILINEAR; - size = xsize*ysize; - /* Check size of 2 dimensional coordinate variables */ - int dimid = ncvars[xvarid].dimids[ndims-2]; - size_t dimsize1 = ncdims[dimid].len; - dimid = ncvars[xvarid].dimids[ndims-1]; - size_t dimsize2 = ncdims[dimid].len; - skipvar = dimsize1*dimsize2 != size; - } - else if ( ndims == 1 ) - { - size = xsize; - /* Check size of 1 dimensional coordinate variables */ - int dimid = ncvars[xvarid].dimids[0]; - size_t dimsize = ncdims[dimid].len; - skipvar = dimsize != size; - } - else if ( ndims == 0 && xsize == 0 ) - { - size = xsize = 1; - skipvar = false; - } - - if ( skipvar ) - { - Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name); - ncvars[ncvarid].isvar = -1; - continue; - } - - if ( ncvars[xvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32; - if (CDI_netcdf_lazy_grid_load) - { - lazyGrid->xValsGet = (struct xyValGet){ - .scalefactor = ncvars[xvarid].scalefactor, - .addoffset = ncvars[xvarid].addoffset, - .start = { start[0], start[1], start[2] }, - .count = { count[0], count[1], count[2] }, - .size = size, - .datasetNCId = ncvars[xvarid].ncid, - .varNCId = xvarid, - .ndims = (short)ndims, - }; - grid->xvals = cdfPendingLoad; - } - else - { - grid->xvals = (double *) Malloc(size*sizeof(double)); - if ( ltgrid ) - cdf_get_vara_double(ncvars[xvarid].ncid, xvarid, - start, count, grid->xvals); - else - cdf_get_var_double(ncvars[xvarid].ncid, xvarid, - grid->xvals); - scale_add(size, grid->xvals, - ncvars[xvarid].addoffset, - ncvars[xvarid].scalefactor); - } - strcpy(grid->xname, ncvars[xvarid].name); - strcpy(grid->xlongname, ncvars[xvarid].longname); - strcpy(grid->xunits, ncvars[xvarid].units); - /* don't change the name !!! */ - /* - if ( (len = strlen(grid->xname)) > 2 ) - if ( grid->xname[len-2] == '_' && isdigit((int) grid->xname[len-1]) ) - grid->xname[len-2] = 0; - */ - } - - if ( yvarid != UNDEFID ) - { - bool skipvar = true; - islat = ncvars[yvarid].islat; - ndims = ncvars[yvarid].ndims; - if ( ndims == 2 || ndims == 3 ) - { - ncvars[ncvarid].gridtype = GRID_CURVILINEAR; - size = xsize*ysize; - /* Check size of 2 dimensional coordinate variables */ - { - int dimid; - size_t dimsize1, dimsize2; - dimid = ncvars[yvarid].dimids[ndims-2]; - dimsize1 = ncdims[dimid].len; - dimid = ncvars[yvarid].dimids[ndims-1]; - dimsize2 = ncdims[dimid].len; - skipvar = dimsize1*dimsize2 != size; - } - } - else if ( ndims == 1 ) - { - if ( (int) ysize == 0 ) size = xsize; - else size = ysize; - - /* Check size of 1 dimensional coordinate variables */ - { - int dimid; - size_t dimsize; - dimid = ncvars[yvarid].dimids[0]; - dimsize = ncdims[dimid].len; - skipvar = dimsize != size; - } - } - else if ( ndims == 0 && ysize == 0 ) - { - size = ysize = 1; - skipvar = false; - } - - if ( skipvar ) - { - Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name); - ncvars[ncvarid].isvar = -1; - continue; - } - - if ( ncvars[yvarid].xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32; - /* see below for when it's impossible to operate - * without y values */ - if ( !CDI_netcdf_lazy_grid_load - || ((ncvars[ncvarid].gridtype == UNDEFID || - ncvars[ncvarid].gridtype == GRID_GENERIC) - && islat && (islon || xsize == 0)) ) - { - grid->yvals = (double *) Malloc(size*sizeof(double)); - - if ( ltgrid ) - cdf_get_vara_double(ncvars[yvarid].ncid, yvarid, start, count, grid->yvals); - else - cdf_get_var_double(ncvars[yvarid].ncid, yvarid, grid->yvals); - - scale_add(size, grid->yvals, ncvars[yvarid].addoffset, ncvars[yvarid].scalefactor); - - /* don't change the name !!! */ - /* - if ( (len = strlen(grid->yname)) > 2 ) - if ( grid->yname[len-2] == '_' && isdigit((int) grid->yname[len-1]) ) - grid->yname[len-2] = 0; - */ - if ( islon && (int) ysize > 1 ) - { - yinc = fabs(grid->yvals[0] - grid->yvals[1]); - for ( size_t i = 2; i < ysize; i++ ) - if ( (fabs(grid->yvals[i-1] - grid->yvals[i]) - yinc) > (yinc/1000) ) - { - yinc = 0; - break; - } - } - } - else - { - lazyGrid->yValsGet = (struct xyValGet){ - .scalefactor = ncvars[yvarid].scalefactor, - .addoffset = ncvars[yvarid].addoffset, - .start = { start[0], start[1], start[2] }, - .count = { count[0], count[1], count[2] }, - .size = size, - .datasetNCId = ncvars[yvarid].ncid, - .varNCId = yvarid, - .ndims = (short)ndims, - }; - grid->yvals = cdfPendingLoad; - } - strcpy(grid->yname, ncvars[yvarid].name); - strcpy(grid->ylongname, ncvars[yvarid].longname); - strcpy(grid->yunits, ncvars[yvarid].units); - } - - if ( (int) ysize == 0 ) size = xsize; - else if ( (int) xsize == 0 ) size = ysize; - else if ( ncvars[ncvarid].gridtype == GRID_UNSTRUCTURED ) size = xsize; - else size = xsize*ysize; - } - - if ( ncvars[ncvarid].gridtype == UNDEFID || - ncvars[ncvarid].gridtype == GRID_GENERIC ) - { - if ( islat && (islon || xsize == 0) ) - { - if ( isGaussGrid(ysize, yinc, grid->yvals) ) - { - ncvars[ncvarid].gridtype = GRID_GAUSSIAN; - grid->np = (int)(ysize/2); - } - else - ncvars[ncvarid].gridtype = GRID_LONLAT; - } - else if ( islon && !islat && ysize == 0 ) - { - ncvars[ncvarid].gridtype = GRID_LONLAT; - } - else - ncvars[ncvarid].gridtype = GRID_GENERIC; - } - - switch (ncvars[ncvarid].gridtype) - { - case GRID_GENERIC: - case GRID_LONLAT: - case GRID_GAUSSIAN: - case GRID_UNSTRUCTURED: - case GRID_CURVILINEAR: - { - grid->size = (int)size; - grid->xsize = (int)xsize; - grid->ysize = (int)ysize; - if ( xvarid != UNDEFID ) - { - grid->xdef = 1; - if ( ncvars[xvarid].bounds != UNDEFID ) - { - int nbdims = ncvars[ncvars[xvarid].bounds].ndims; - if ( nbdims == 2 || nbdims == 3 ) - { - vdimid = ncvars[ncvars[xvarid].bounds].dimids[nbdims-1]; - size_t nvertex = ncdims[vdimid].len; - grid->nvertex = (int)nvertex; - if (CDI_netcdf_lazy_grid_load) - { - lazyGrid->xBoundsGet.datasetNCId - = ncvars[xvarid].ncid; - lazyGrid->xBoundsGet.varNCId - = ncvars[xvarid].bounds; - grid->xbounds = cdfPendingLoad; - } - else - { - grid->xbounds - = (double *)Malloc(nvertex * size - * sizeof(double)); - cdf_get_var_double(ncvars[xvarid].ncid, - ncvars[xvarid].bounds, - grid->xbounds); - } - } - } - } - if ( yvarid != UNDEFID ) - { - grid->ydef = 1; - if ( ncvars[yvarid].bounds != UNDEFID ) - { - int nbdims = ncvars[ncvars[yvarid].bounds].ndims; - if ( nbdims == 2 || nbdims == 3 ) - { - /* size_t nvertex = ncdims[ncvars[ncvars[yvarid].bounds].dimids[nbdims-1]].len; - if ( nvertex != grid->nvertex ) - Warning("nvertex problem! nvertex x %d, nvertex y %d", - grid->nvertex, (int) nvertex); - */ - if (CDI_netcdf_lazy_grid_load) - { - lazyGrid->yBoundsGet.datasetNCId - = ncvars[yvarid].ncid; - lazyGrid->yBoundsGet.varNCId - = ncvars[yvarid].bounds; - grid->ybounds = cdfPendingLoad; - } - else - { - vdimid = ncvars[ncvars[yvarid].bounds].dimids[nbdims-1]; - size_t nvertex = ncdims[vdimid].len; - /* - if ( nvertex != grid->nvertex ) - Warning("nvertex problem! nvertex x %d, nvertex y %d", - grid->nvertex, (int) nvertex); - */ - grid->ybounds - = (double *)Malloc(nvertex * size - * sizeof(double)); - cdf_get_var_double(ncvars[yvarid].ncid, - ncvars[yvarid].bounds, - grid->ybounds); - } - } - } - } - - if ( ncvars[ncvarid].cellarea != UNDEFID ) - { - if (CDI_netcdf_lazy_grid_load) - { - grid->area = cdfPendingLoad; - lazyGrid->cellAreaGet.datasetNCId - = ncvars[ncvarid].ncid; - lazyGrid->cellAreaGet.varNCId - = ncvars[ncvarid].cellarea; - } - else - { - grid->area = (double *) Malloc(size*sizeof(double)); - cdf_get_var_double(ncvars[ncvarid].ncid, - ncvars[ncvarid].cellarea, - grid->area); - } - } - - break; - } - case GRID_SPECTRAL: - { - grid->size = (int)size; - grid->lcomplex = 1; - break; - } - case GRID_FOURIER: - { - grid->size = (int)size; - break; - } - case GRID_TRAJECTORY: - { - grid->size = 1; - break; - } - } - - if ( grid->type != ncvars[ncvarid].gridtype ) - { - int gridtype = ncvars[ncvarid].gridtype; - grid->type = gridtype; - cdiGridTypeInit(grid, gridtype, grid->size); - } - - if ( grid->size == 0 ) - { - if ( (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == T_AXIS) || - (ncvars[ncvarid].ndims == 1 && ncvars[ncvarid].dimtype[0] == Z_AXIS) || - (ncvars[ncvarid].ndims == 2 && ncvars[ncvarid].dimtype[0] == T_AXIS && ncvars[ncvarid].dimtype[1] == Z_AXIS) ) - { - grid->type = GRID_GENERIC; - grid->size = 1; - grid->xsize = 0; - grid->ysize = 0; - } - else - { - Warning("Variable %s has an unsupported grid, skipped!", ncvars[ncvarid].name); - ncvars[ncvarid].isvar = -1; - continue; - } - } - - if ( number_of_grid_used != UNDEFID && (grid->type == UNDEFID || grid->type == GRID_GENERIC) ) - grid->type = GRID_UNSTRUCTURED; - - if ( number_of_grid_used != UNDEFID && grid->type == GRID_UNSTRUCTURED ) - grid->number = number_of_grid_used; - - if ( ncvars[ncvarid].gmapid >= 0 && ncvars[ncvarid].gridtype != GRID_CURVILINEAR ) - { - int nvatts; - cdf_inq_varnatts(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, &nvatts); - - for ( int iatt = 0; iatt < nvatts; iatt++ ) - { - size_t attlen; - char attname[CDI_MAX_NAME]; - cdf_inq_attname(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, iatt, attname); - cdf_inq_attlen(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, &attlen); - - if ( strcmp(attname, "grid_mapping_name") == 0 ) - { - enum { - attstringlen = 8192, - }; - char attstring[attstringlen]; - - cdfGetAttText(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, attstringlen, attstring); - strtolower(attstring); - - if ( strcmp(attstring, "rotated_latitude_longitude") == 0 ) - grid->isRotated = TRUE; - else if ( strcmp(attstring, "sinusoidal") == 0 ) - grid->type = GRID_SINUSOIDAL; - else if ( strcmp(attstring, "lambert_azimuthal_equal_area") == 0 ) - grid->type = GRID_LAEA; - else if ( strcmp(attstring, "lambert_conformal_conic") == 0 ) - grid->type = GRID_LCC2; - else if ( strcmp(attstring, "lambert_cylindrical_equal_area") == 0 ) - { - proj->type = GRID_PROJECTION; - proj->name = strdup(attstring); - } - } - else if ( strcmp(attname, "earth_radius") == 0 ) - { - double datt; - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt); - grid->laea_a = datt; - grid->lcc2_a = datt; - } - else if ( strcmp(attname, "longitude_of_projection_origin") == 0 ) - { - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->laea_lon_0); - } - else if ( strcmp(attname, "longitude_of_central_meridian") == 0 ) - { - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->lcc2_lon_0); - } - else if ( strcmp(attname, "latitude_of_projection_origin") == 0 ) - { - double datt; - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt); - grid->laea_lat_0 = datt; - grid->lcc2_lat_0 = datt; - } - else if ( strcmp(attname, "standard_parallel") == 0 ) - { - if ( attlen == 1 ) - { - double datt; - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &datt); - grid->lcc2_lat_1 = datt; - grid->lcc2_lat_2 = datt; - } - else - { - double datt2[2]; - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 2, datt2); - grid->lcc2_lat_1 = datt2[0]; - grid->lcc2_lat_2 = datt2[1]; - } - } - else if ( strcmp(attname, "grid_north_pole_latitude") == 0 ) - { - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->ypole); - } - else if ( strcmp(attname, "grid_north_pole_longitude") == 0 ) - { - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->xpole); - } - else if ( strcmp(attname, "north_pole_grid_longitude") == 0 ) - { - cdfGetAttDouble(ncvars[ncvarid].ncid, ncvars[ncvarid].gmapid, attname, 1, &grid->angle); - } - } - } - - if ( grid->type == GRID_UNSTRUCTURED ) - { - int zdimid = UNDEFID; - int xdimidx = -1, ydimidx = -1; - - for ( int i = 0; i < ndims; i++ ) - { - if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) xdimidx = i; - else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) ydimidx = i; - else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) zdimid = ncvars[ncvarid].dimids[i]; - } - - if ( xdimid != UNDEFID && ydimid != UNDEFID && zdimid == UNDEFID ) - { - if ( grid->xsize > grid->ysize && grid->ysize < 1000 ) - { - ncvars[ncvarid].dimtype[ydimidx] = Z_AXIS; - ydimid = UNDEFID; - grid->size = grid->xsize; - grid->ysize = 0; - } - else if ( grid->ysize > grid->xsize && grid->xsize < 1000 ) - { - ncvars[ncvarid].dimtype[xdimidx] = Z_AXIS; - xdimid = ydimid; - ydimid = UNDEFID; - grid->size = grid->ysize; - grid->xsize = grid->ysize; - grid->ysize = 0; - } - } - - if ( grid->size != grid->xsize ) - { - Warning("Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name); - ncvars[ncvarid].isvar = -1; - continue; - } - - if ( ncvars[ncvarid].position > 0 ) grid->position = ncvars[ncvarid].position; - if ( uuidOfHGrid[0] != 0 ) memcpy(grid->uuid, uuidOfHGrid, 16); - } - -#if defined (PROJECTION_TEST) - if ( proj->type == GRID_PROJECTION ) - { - if ( grid->type == GRID_GENERIC ) - { - grid->type = GRID_CURVILINEAR; - } - - if ( grid->type == GRID_CURVILINEAR ) - { - proj->size = grid->size; - proj->xsize = grid->xsize; - proj->ysize = grid->ysize; - } - - // grid->proj = gridGenerate(proj); - } -#endif - - if ( CDI_Debug ) - { - Message("grid: type = %d, size = %d, nx = %d, ny %d", - grid->type, grid->size, grid->xsize, grid->ysize); - Message("proj: type = %d, size = %d, nx = %d, ny %d", - proj->type, proj->size, proj->xsize, proj->ysize); - } - -#if defined (PROJECTION_TEST) - if ( proj->type == GRID_PROJECTION ) - { - projAdded = cdiVlistAddGridIfNew(vlistID, proj, 1); - ncvars[ncvarid].gridID = projAdded.Id; - copy_numeric_projatts(ncvars[ncvarid].gridID, ncvars[ncvarid].gmapid, ncvars[ncvarid].ncid); - } - else -#endif - { - gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 1); - ncvars[ncvarid].gridID = gridAdded.Id; - } - - if ( grid->type == GRID_UNSTRUCTURED ) - { - if ( gridfile[0] != 0 ) gridDefReference(ncvars[ncvarid].gridID, gridfile); - } - - if ( ncvars[ncvarid].chunked ) grid_set_chunktype(grid, &ncvars[ncvarid]); - - int gridindex = vlistGridIndex(vlistID, ncvars[ncvarid].gridID); - streamptr->xdimID[gridindex] = xdimid; - streamptr->ydimID[gridindex] = ydimid; - if ( xdimid == -1 && ydimid == -1 && grid->size == 1 ) - gridDefHasDims(ncvars[ncvarid].gridID, FALSE); - - if ( xdimid != -1 ) - cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_XDIMNAME, (int)(strlen(ncdims[xdimid].name)+1), ncdims[xdimid].name); - if ( ydimid != -1 ) - cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_YDIMNAME, (int)(strlen(ncdims[ydimid].name)+1), ncdims[ydimid].name); - if ( vdimid != -1 ) - cdiGridDefString(ncvars[ncvarid].gridID, CDI_GRID_VDIMNAME, (int)(strlen(ncdims[vdimid].name)+1), ncdims[vdimid].name); - - if ( CDI_Debug ) - Message("gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid, ncvars[ncvarid].name); - - for ( int ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ ) - if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].gridID == UNDEFID ) - { - int xdimid2 = UNDEFID, ydimid2 = UNDEFID, zdimid2 = UNDEFID; - int xdimidx = -1, ydimidx = -1; - int ndims2 = ncvars[ncvarid2].ndims; - - for ( int i = 0; i < ndims2; i++ ) - { - if ( ncvars[ncvarid2].dimtype[i] == X_AXIS ) - { xdimid2 = ncvars[ncvarid2].dimids[i]; xdimidx = i; } - else if ( ncvars[ncvarid2].dimtype[i] == Y_AXIS ) - { ydimid2 = ncvars[ncvarid2].dimids[i]; ydimidx = i; } - else if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS ) - { zdimid2 = ncvars[ncvarid2].dimids[i]; } - } - - if ( ncvars[ncvarid2].gridtype == UNDEFID && grid->type == GRID_UNSTRUCTURED ) - { - if ( xdimid == xdimid2 && ydimid2 != UNDEFID && zdimid2 == UNDEFID ) - { - ncvars[ncvarid2].dimtype[ydimidx] = Z_AXIS; - ydimid2 = UNDEFID; - } - - if ( xdimid == ydimid2 && xdimid2 != UNDEFID && zdimid2 == UNDEFID ) - { - ncvars[ncvarid2].dimtype[xdimidx] = Z_AXIS; - xdimid2 = ydimid2; - ydimid2 = UNDEFID; - } - } - - if ( xdimid == xdimid2 && - (ydimid == ydimid2 || (xdimid == ydimid && ydimid2 == UNDEFID)) ) - { - int same_grid = ncvars[ncvarid].xvarid == ncvars[ncvarid2].xvarid - && ncvars[ncvarid].yvarid == ncvars[ncvarid2].yvarid - && ncvars[ncvarid].position == ncvars[ncvarid2].position; - /* - if ( xvarid != -1 && ncvars[ncvarid2].xvarid != UNDEFID && - xvarid != ncvars[ncvarid2].xvarid ) same_grid = FALSE; - - if ( yvarid != -1 && ncvars[ncvarid2].yvarid != UNDEFID && - yvarid != ncvars[ncvarid2].yvarid ) same_grid = FALSE; - */ - - if ( same_grid ) - { - if ( CDI_Debug ) - Message("Same gridID %d %d %s", ncvars[ncvarid].gridID, ncvarid2, ncvars[ncvarid2].name); - ncvars[ncvarid2].gridID = ncvars[ncvarid].gridID; - ncvars[ncvarid2].chunktype = ncvars[ncvarid].chunktype; - } - } - } - - if (gridAdded.isNew) - lazyGrid = NULL; - if (projAdded.isNew) - lazyProj = NULL; - } - } - if (lazyGrid) - { - if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyGrid); - grid_free(grid); - Free(grid); - } - if (lazyProj) - { - if (CDI_netcdf_lazy_grid_load) cdfLazyGridDestroy(lazyProj); - grid_free(proj); - Free(proj); - } -#undef proj -#undef grid -} - -/* define all input zaxes */ -static -void define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, - size_t vctsize_echam, double *vct_echam, unsigned char *uuidOfVGrid) -{ - int ncvarid, ncvarid2; - int i, ilev; - int zaxisindex; - int nbdims, nvertex, nlevel; - int psvarid = -1; - char *pname, *plongname, *punits; - size_t vctsize = vctsize_echam; - double *vct = vct_echam; - - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].zaxisID == UNDEFID ) - { - int is_scalar = FALSE; - int with_bounds = FALSE; - int zdimid = UNDEFID; - int zvarid = UNDEFID; - int zsize = 1; - double *lbounds = NULL; - double *ubounds = NULL; - - int positive = 0; - int ndims = ncvars[ncvarid].ndims; - - if ( ncvars[ncvarid].zvarid != -1 && ncvars[ncvars[ncvarid].zvarid].ndims == 0 ) - { - zvarid = ncvars[ncvarid].zvarid; - is_scalar = TRUE; - } - else - { - for ( i = 0; i < ndims; i++ ) - { - if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) - zdimid = ncvars[ncvarid].dimids[i]; - } - - if ( zdimid != UNDEFID ) - { - zvarid = ncdims[zdimid].ncvarid; - zsize = (int)ncdims[zdimid].len; - } - } - - if ( CDI_Debug ) Message("nlevs = %d", zsize); - - double *zvar = (double *) Malloc((size_t)zsize * sizeof (double)); - - int zaxisType = UNDEFID; - if ( zvarid != UNDEFID ) zaxisType = ncvars[zvarid].zaxistype; - if ( zaxisType == UNDEFID ) zaxisType = ZAXIS_GENERIC; - - int zprec = DATATYPE_FLT64; - - if ( zvarid != UNDEFID ) - { - positive = ncvars[zvarid].positive; - pname = ncvars[zvarid].name; - plongname = ncvars[zvarid].longname; - punits = ncvars[zvarid].units; - if ( ncvars[zvarid].xtype == NC_FLOAT ) zprec = DATATYPE_FLT32; - /* don't change the name !!! */ - /* - if ( (len = strlen(pname)) > 2 ) - if ( pname[len-2] == '_' && isdigit((int) pname[len-1]) ) - pname[len-2] = 0; - */ - psvarid = -1; - if ( zaxisType == ZAXIS_HYBRID && ncvars[zvarid].vct ) - { - vct = ncvars[zvarid].vct; - vctsize = ncvars[zvarid].vctsize; - - if ( ncvars[zvarid].psvarid != -1 ) psvarid = ncvars[zvarid].psvarid; - } - - cdf_get_var_double(ncvars[zvarid].ncid, zvarid, zvar); - - if ( ncvars[zvarid].bounds != UNDEFID ) - { - nbdims = ncvars[ncvars[zvarid].bounds].ndims; - if ( nbdims == 2 ) - { - nlevel = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len; - nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len; - if ( nlevel == zsize && nvertex == 2 ) - { - with_bounds = TRUE; - lbounds = (double *) Malloc((size_t)nlevel*sizeof(double)); - ubounds = (double *) Malloc((size_t)nlevel*sizeof(double)); - double zbounds[2*nlevel]; - cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds); - for ( i = 0; i < nlevel; ++i ) - { - lbounds[i] = zbounds[i*2]; - ubounds[i] = zbounds[i*2+1]; - } - } - } - } - } - else - { - pname = NULL; - plongname = NULL; - punits = NULL; - - if ( zsize == 1 ) - { - if ( ncvars[ncvarid].zaxistype != UNDEFID ) - zaxisType = ncvars[ncvarid].zaxistype; - else - zaxisType = ZAXIS_SURFACE; - - zvar[0] = 0; - /* - if ( zdimid == UNDEFID ) - zvar[0] = 9999; - else - zvar[0] = 0; - */ - } - else - { - for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1; - } - } - - ncvars[ncvarid].zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, with_bounds, lbounds, ubounds, - (int)vctsize, vct, pname, plongname, punits, zprec, 1, 0); - - if ( uuidOfVGrid[0] != 0 ) - { - // printf("uuidOfVGrid: defined\n"); - zaxisDefUUID(ncvars[ncvarid].zaxisID, uuidOfVGrid); - } - - if ( zaxisType == ZAXIS_HYBRID && psvarid != -1 ) zaxisDefPsName(ncvars[ncvarid].zaxisID, ncvars[psvarid].name); - - if ( positive > 0 ) zaxisDefPositive(ncvars[ncvarid].zaxisID, positive); - if ( is_scalar ) zaxisDefScalar(ncvars[ncvarid].zaxisID); - - if ( zdimid != -1 ) - cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_DIMNAME, (int)(strlen(ncdims[zdimid].name)+1), ncdims[zdimid].name); - /* - if ( vdimid != -1 ) - cdiZaxisDefString(ncvars[ncvarid].zaxisID, CDI_ZAXIS_VDIMNAME, strlen(ncdims[vdimid].name)+1, ncdims[vdimid].name); - */ - Free(zvar); - Free(lbounds); - Free(ubounds); - - zaxisindex = vlistZaxisIndex(vlistID, ncvars[ncvarid].zaxisID); - streamptr->zaxisID[zaxisindex] = zdimid; - - if ( CDI_Debug ) - Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid, ncvars[ncvarid].name); - - for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ ) - if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].zaxisID == UNDEFID /*&& ncvars[ncvarid2].zaxistype == UNDEFID*/ ) - { - int zvarid2 = UNDEFID; - if ( ncvars[ncvarid2].zvarid != UNDEFID && ncvars[ncvars[ncvarid2].zvarid].ndims == 0 ) - zvarid2 = ncvars[ncvarid2].zvarid; - - int zdimid2 = UNDEFID; - ndims = ncvars[ncvarid2].ndims; - for ( i = 0; i < ndims; i++ ) - { - if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS ) - zdimid2 = ncvars[ncvarid2].dimids[i]; - } - - if ( zdimid == zdimid2 /* && zvarid == zvarid2 */) - { - if ( (zdimid != UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) || - (zdimid == UNDEFID && zvarid != UNDEFID && zvarid == zvarid2) || - (zdimid == UNDEFID && zaxisType == ncvars[ncvarid2].zaxistype) || - (zdimid == UNDEFID && zvarid2 == UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) ) - { - if ( CDI_Debug ) - Message("zaxisID %d %d %s", ncvars[ncvarid].zaxisID, ncvarid2, ncvars[ncvarid2].name); - ncvars[ncvarid2].zaxisID = ncvars[ncvarid].zaxisID; - } - } - } - } - } -} - -struct varinfo -{ - int ncvarid; - const char *name; -}; - -static -int cmpvarname(const void *s1, const void *s2) -{ - const struct varinfo *x = (const struct varinfo *)s1, - *y = (const struct varinfo *)s2; - return (strcmp(x->name, y->name)); -} - -/* define all input data variables */ -static -void define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID, int *varids, int nvars, int num_ncvars, ncvar_t *ncvars) -{ - if ( CDI_Debug ) - { - for(int i = 0; i < nvars; i++) Message("varids[%d] = %d", i, varids[i]); - } - if ( streamptr->sortname ) - { - struct varinfo *varInfo - = (struct varinfo *) Malloc((size_t)nvars * sizeof (struct varinfo)); - - for ( int varID = 0; varID < nvars; varID++ ) - { - int ncvarid = varids[varID]; - varInfo[varID].ncvarid = ncvarid; - varInfo[varID].name = ncvars[ncvarid].name; - } - qsort(varInfo, (size_t)nvars, sizeof(varInfo[0]), cmpvarname); - for ( int varID = 0; varID < nvars; varID++ ) - { - varids[varID] = varInfo[varID].ncvarid; - } - Free(varInfo); - if ( CDI_Debug ) - { - for(int i = 0; i < nvars; i++) Message("sorted varids[%d] = %d", i, varids[i]); - } - } - - for ( int varID1 = 0; varID1 < nvars; varID1++ ) - { - int ncvarid = varids[varID1]; - int gridID = ncvars[ncvarid].gridID; - int zaxisID = ncvars[ncvarid].zaxisID; - - stream_new_var(streamptr, gridID, zaxisID, CDI_UNDEFID); - int varID = vlistDefVar(vlistID, gridID, zaxisID, ncvars[ncvarid].tsteptype); - -#if defined (HAVE_NETCDF4) - if ( ncvars[ncvarid].deflate ) - vlistDefVarCompType(vlistID, varID, COMPRESS_ZIP); - - if ( ncvars[ncvarid].chunked && ncvars[ncvarid].chunktype != UNDEFID ) - vlistDefVarChunkType(vlistID, varID, ncvars[ncvarid].chunktype); -#endif - - streamptr->vars[varID1].defmiss = 0; - streamptr->vars[varID1].ncvarid = ncvarid; - - vlistDefVarName(vlistID, varID, ncvars[ncvarid].name); - if ( ncvars[ncvarid].param != UNDEFID ) vlistDefVarParam(vlistID, varID, ncvars[ncvarid].param); - if ( ncvars[ncvarid].code != UNDEFID ) vlistDefVarCode(vlistID, varID, ncvars[ncvarid].code); - if ( ncvars[ncvarid].code != UNDEFID ) - { - int param = cdiEncodeParam(ncvars[ncvarid].code, ncvars[ncvarid].tabnum, 255); - vlistDefVarParam(vlistID, varID, param); - } - if ( ncvars[ncvarid].longname[0] ) vlistDefVarLongname(vlistID, varID, ncvars[ncvarid].longname); - if ( ncvars[ncvarid].stdname[0] ) vlistDefVarStdname(vlistID, varID, ncvars[ncvarid].stdname); - if ( ncvars[ncvarid].units[0] ) vlistDefVarUnits(vlistID, varID, ncvars[ncvarid].units); - - if ( ncvars[ncvarid].lvalidrange ) - vlistDefVarValidrange(vlistID, varID, ncvars[ncvarid].validrange); - - if ( IS_NOT_EQUAL(ncvars[ncvarid].addoffset, 0) ) - vlistDefVarAddoffset(vlistID, varID, ncvars[ncvarid].addoffset); - if ( IS_NOT_EQUAL(ncvars[ncvarid].scalefactor, 1) ) - vlistDefVarScalefactor(vlistID, varID, ncvars[ncvarid].scalefactor); - - vlistDefVarDatatype(vlistID, varID, cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned)); - - vlistDefVarInstitut(vlistID, varID, instID); - vlistDefVarModel(vlistID, varID, modelID); - if ( ncvars[ncvarid].tableID != UNDEFID ) - vlistDefVarTable(vlistID, varID, ncvars[ncvarid].tableID); - - if ( ncvars[ncvarid].deffillval == FALSE && ncvars[ncvarid].defmissval == TRUE ) - { - ncvars[ncvarid].deffillval = TRUE; - ncvars[ncvarid].fillval = ncvars[ncvarid].missval; - } - - if ( ncvars[ncvarid].deffillval == TRUE ) - vlistDefVarMissval(vlistID, varID, ncvars[ncvarid].fillval); - - if ( CDI_Debug ) - Message("varID = %d gridID = %d zaxisID = %d", varID, - vlistInqVarGrid(vlistID, varID), vlistInqVarZaxis(vlistID, varID)); - - int gridindex = vlistGridIndex(vlistID, gridID); - int xdimid = streamptr->xdimID[gridindex]; - int ydimid = streamptr->ydimID[gridindex]; - - int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); - int zdimid = streamptr->zaxisID[zaxisindex]; - - int ndims = ncvars[ncvarid].ndims; - int iodim = 0; - int ixyz = 0; - int ipow10[4] = {1, 10, 100, 1000}; - - if ( ncvars[ncvarid].tsteptype != TSTEP_CONSTANT ) iodim++; - - if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ndims-iodim <= 2 && ydimid == xdimid ) - { - if ( xdimid == ncvars[ncvarid].dimids[ndims-1] ) - { - ixyz = 321; - } - else - { - ixyz = 213; - } - } - else - { - for ( int idim = iodim; idim < ndims; idim++ ) - { - if ( xdimid == ncvars[ncvarid].dimids[idim] ) - ixyz += 1*ipow10[ndims-idim-1]; - else if ( ydimid == ncvars[ncvarid].dimids[idim] ) - ixyz += 2*ipow10[ndims-idim-1]; - else if ( zdimid == ncvars[ncvarid].dimids[idim] ) - ixyz += 3*ipow10[ndims-idim-1]; - } - } - - vlistDefVarXYZ(vlistID, varID, ixyz); - /* - printf("ixyz %d\n", ixyz); - printf("ndims %d\n", ncvars[ncvarid].ndims); - for ( int i = 0; i < ncvars[ncvarid].ndims; ++i ) - printf("dimids: %d %d\n", i, ncvars[ncvarid].dimids[i]); - printf("xdimid, ydimid %d %d\n", xdimid, ydimid); - */ - if ( ncvars[ncvarid].ensdata != NULL ) - { - vlistDefVarEnsemble( vlistID, varID, ncvars[ncvarid].ensdata->ens_index, - ncvars[ncvarid].ensdata->ens_count, - ncvars[ncvarid].ensdata->forecast_init_type ); - Free(ncvars[ncvarid].ensdata); - ncvars[ncvarid].ensdata = NULL; - } - - if ( ncvars[ncvarid].extra[0] != 0 ) - { - vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra); - } - } - - for ( int varID = 0; varID < nvars; varID++ ) - { - int ncvarid = varids[varID]; - int ncid = ncvars[ncvarid].ncid; - - if ( ncvars[ncvarid].natts ) - { - int attnum; - int iatt; - nc_type attrtype; - size_t attlen; - char attname[CDI_MAX_NAME]; - const int attstringlen = 8192; char attstring[8192]; - int nvatts = ncvars[ncvarid].natts; - - for ( iatt = 0; iatt < nvatts; iatt++ ) - { - attnum = ncvars[ncvarid].atts[iatt]; - cdf_inq_attname(ncid, ncvarid, attnum, attname); - cdf_inq_attlen(ncid, ncvarid, attname, &attlen); - cdf_inq_atttype(ncid, ncvarid, attname, &attrtype); - - if ( attrtype == NC_SHORT || attrtype == NC_INT ) - { - int attint[attlen]; - cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint); - if ( attrtype == NC_SHORT ) - vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT16, (int)attlen, attint); - else - vlistDefAttInt(vlistID, varID, attname, DATATYPE_INT32, (int)attlen, attint); - } - else if ( attrtype == NC_FLOAT || attrtype == NC_DOUBLE ) - { - double attflt[attlen]; - cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt); - if ( attrtype == NC_FLOAT ) - vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT32, (int)attlen, attflt); - else - vlistDefAttFlt(vlistID, varID, attname, DATATYPE_FLT64, (int)attlen, attflt); - } - else if ( xtypeIsText(attrtype) ) - { - cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); - vlistDefAttTxt(vlistID, varID, attname, (int)attlen, attstring); - } - else - { - if ( CDI_Debug ) printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname); - } - } - - if (ncvars[ncvarid].vct) Free(ncvars[ncvarid].vct); - if (ncvars[ncvarid].atts) Free(ncvars[ncvarid].atts); - ncvars[ncvarid].vct = NULL; - ncvars[ncvarid].atts = NULL; - } - } - - /* release mem of not freed attributes */ - for ( int ncvarid = 0; ncvarid < num_ncvars; ncvarid++ ) - if ( ncvars[ncvarid].atts ) Free(ncvars[ncvarid].atts); - - if ( varids ) Free(varids); - - for ( int varID = 0; varID < nvars; varID++ ) - { - if ( vlistInqVarCode(vlistID, varID) == -varID-1 ) - { - const char *pname = vlistInqVarNamePtr(vlistID, varID); - size_t len = strlen(pname); - if ( len > 3 && isdigit((int) pname[3]) ) - { - if ( memcmp("var", pname, 3) == 0 ) - { - vlistDefVarCode(vlistID, varID, atoi(pname+3)); - // vlistDestroyVarName(vlistID, varID); - } - } - else if ( len > 4 && isdigit((int) pname[4]) ) - { - if ( memcmp("code", pname, 4) == 0 ) - { - vlistDefVarCode(vlistID, varID, atoi(pname+4)); - // vlistDestroyVarName(vlistID, varID); - } - } - else if ( len > 5 && isdigit((int) pname[5]) ) - { - if ( memcmp("param", pname, 5) == 0 ) - { - int pnum = -1, pcat = 255, pdis = 255; - sscanf(pname+5, "%d.%d.%d", &pnum, &pcat, &pdis); - vlistDefVarParam(vlistID, varID, cdiEncodeParam(pnum, pcat, pdis)); - // vlistDestroyVarName(vlistID, varID); - } - } - } - } - - for ( int varID = 0; varID < nvars; varID++ ) - { - int varInstID = vlistInqVarInstitut(vlistID, varID); - int varModelID = vlistInqVarModel(vlistID, varID); - int varTableID = vlistInqVarTable(vlistID, varID); - int code = vlistInqVarCode(vlistID, varID); - if ( cdiDefaultTableID != UNDEFID ) - { - if ( tableInqParNamePtr(cdiDefaultTableID, code) ) - { - vlistDestroyVarName(vlistID, varID); - vlistDestroyVarLongname(vlistID, varID); - vlistDestroyVarUnits(vlistID, varID); - - if ( varTableID != UNDEFID ) - { - vlistDefVarName(vlistID, varID, tableInqParNamePtr(cdiDefaultTableID, code)); - if ( tableInqParLongnamePtr(cdiDefaultTableID, code) ) - vlistDefVarLongname(vlistID, varID, tableInqParLongnamePtr(cdiDefaultTableID, code)); - if ( tableInqParUnitsPtr(cdiDefaultTableID, code) ) - vlistDefVarUnits(vlistID, varID, tableInqParUnitsPtr(cdiDefaultTableID, code)); - } - else - { - varTableID = cdiDefaultTableID; - } - } - - if ( cdiDefaultModelID != UNDEFID ) varModelID = cdiDefaultModelID; - if ( cdiDefaultInstID != UNDEFID ) varInstID = cdiDefaultInstID; - } - if ( varInstID != UNDEFID ) vlistDefVarInstitut(vlistID, varID, varInstID); - if ( varModelID != UNDEFID ) vlistDefVarModel(vlistID, varID, varModelID); - if ( varTableID != UNDEFID ) vlistDefVarTable(vlistID, varID, varTableID); - } -} - -static -void scan_global_attributes(int fileID, int vlistID, stream_t *streamptr, int ngatts, int *instID, int *modelID, int *ucla_les, unsigned char *uuidOfHGrid, unsigned char *uuidOfVGrid, char *gridfile, int *number_of_grid_used) -{ - nc_type xtype; - size_t attlen; - char attname[CDI_MAX_NAME]; - enum { attstringlen = 65636 }; - char attstring[attstringlen]; - int iatt; - - for ( iatt = 0; iatt < ngatts; iatt++ ) - { - cdf_inq_attname(fileID, NC_GLOBAL, iatt, attname); - cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype); - cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen); - - if ( xtypeIsText(xtype) ) - { - cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen, attstring); - - size_t attstrlen = strlen(attstring); - - if ( attlen > 0 && attstring[0] != 0 ) - { - if ( strcmp(attname, "history") == 0 ) - { - streamptr->historyID = iatt; - } - else if ( strcmp(attname, "institution") == 0 ) - { - *instID = institutInq(0, 0, NULL, attstring); - if ( *instID == UNDEFID ) - *instID = institutDef(0, 0, NULL, attstring); - } - else if ( strcmp(attname, "source") == 0 ) - { - *modelID = modelInq(-1, 0, attstring); - if ( *modelID == UNDEFID ) - *modelID = modelDef(-1, 0, attstring); - } - else if ( strcmp(attname, "Source") == 0 ) - { - if ( strncmp(attstring, "UCLA-LES", 8) == 0 ) - *ucla_les = TRUE; - } - /* - else if ( strcmp(attname, "Conventions") == 0 ) - { - } - */ - else if ( strcmp(attname, "CDI") == 0 ) - { - } - else if ( strcmp(attname, "CDO") == 0 ) - { - } - /* - else if ( strcmp(attname, "forecast_reference_time") == 0 ) - { - memcpy(fcreftime, attstring, attstrlen+1); - } - */ - else if ( strcmp(attname, "grid_file_uri") == 0 ) - { - memcpy(gridfile, attstring, attstrlen+1); - } - else if ( strcmp(attname, "uuidOfHGrid") == 0 && attstrlen == 36 ) - { - attstring[36] = 0; - cdiStr2UUID(attstring, uuidOfHGrid); - // printf("uuid: %d %s\n", attlen, attstring); - } - else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 ) - { - attstring[36] = 0; - cdiStr2UUID(attstring, uuidOfVGrid); - } - else - { - if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 ) - { - memcpy(gridfile, attstring, attstrlen+1); - } - - vlistDefAttTxt(vlistID, CDI_GLOBAL, attname, (int)attstrlen, attstring); - } - } - } - else if ( xtype == NC_SHORT || xtype == NC_INT ) - { - if ( strcmp(attname, "number_of_grid_used") == 0 ) - { - (*number_of_grid_used) = UNDEFID; - cdfGetAttInt(fileID, NC_GLOBAL, attname, 1, number_of_grid_used); - } - else - { - int attint[attlen]; - cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint); - if ( xtype == NC_SHORT ) - vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT16, (int)attlen, attint); - else - vlistDefAttInt(vlistID, CDI_GLOBAL, attname, DATATYPE_INT32, (int)attlen, attint); - } - } - else if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) - { - double attflt[attlen]; - cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt); - if ( xtype == NC_FLOAT ) - vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT32, (int)attlen, attflt); - else - vlistDefAttFlt(vlistID, CDI_GLOBAL, attname, DATATYPE_FLT64, (int)attlen, attflt); - } - } -} - -static -int find_leadtime(int nvars, ncvar_t *ncvars) -{ - int leadtime_id = UNDEFID; - - for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].stdname[0] ) - { - if ( strcmp(ncvars[ncvarid].stdname, "forecast_period") == 0 ) - { - leadtime_id = ncvarid; - break; - } - } - } - - return (leadtime_id); -} - -static -void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, stream_t *streamptr, - int *time_has_units, int *time_has_bounds, int *time_climatology) -{ - int ncvarid; - - if ( timedimid == UNDEFID ) - { - char timeunits[CDI_MAX_NAME]; - - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].ndims == 0 && strcmp(ncvars[ncvarid].name, "time") == 0 ) - { - if ( ncvars[ncvarid].units[0] ) - { - strcpy(timeunits, ncvars[ncvarid].units); - strtolower(timeunits); - - if ( isTimeUnits(timeunits) ) - { - streamptr->basetime.ncvarid = ncvarid; - break; - } - } - } - } - } - else - { - int ltimevar = FALSE; - - if ( ncdims[timedimid].ncvarid != UNDEFID ) - { - streamptr->basetime.ncvarid = ncdims[timedimid].ncvarid; - ltimevar = TRUE; - } - - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - if ( ncvarid != streamptr->basetime.ncvarid && - ncvars[ncvarid].ndims == 1 && - timedimid == ncvars[ncvarid].dimids[0] && - !xtypeIsText(ncvars[ncvarid].xtype) && - isTimeAxisUnits(ncvars[ncvarid].units) ) - { - ncvars[ncvarid].isvar = FALSE; - - if ( !ltimevar ) - { - streamptr->basetime.ncvarid = ncvarid; - ltimevar = TRUE; - if ( CDI_Debug ) - fprintf(stderr, "timevar %s\n", ncvars[ncvarid].name); - } - else - { - Warning("Found more than one time variable, skipped variable %s!", ncvars[ncvarid].name); - } - } - - if ( ltimevar == FALSE ) /* search for WRF time description */ - { - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - if ( ncvarid != streamptr->basetime.ncvarid && - ncvars[ncvarid].ndims == 2 && - timedimid == ncvars[ncvarid].dimids[0] && - xtypeIsText(ncvars[ncvarid].xtype) && - ncdims[ncvars[ncvarid].dimids[1]].len == 19 ) - { - streamptr->basetime.ncvarid = ncvarid; - streamptr->basetime.lwrf = TRUE; - break; - } - } - - /* time varID */ - ncvarid = streamptr->basetime.ncvarid; - - if ( ncvarid == UNDEFID ) - { - Warning("Time variable >%s< not found!", ncdims[timedimid].name); - } - } - - /* time varID */ - ncvarid = streamptr->basetime.ncvarid; - - if ( ncvarid != UNDEFID && streamptr->basetime.lwrf == FALSE ) - { - if ( ncvars[ncvarid].units[0] != 0 ) *time_has_units = TRUE; - - if ( ncvars[ncvarid].bounds != UNDEFID ) - { - int nbdims = ncvars[ncvars[ncvarid].bounds].ndims; - if ( nbdims == 2 ) - { - int len = (int) ncdims[ncvars[ncvars[ncvarid].bounds].dimids[nbdims-1]].len; - if ( len == 2 && timedimid == ncvars[ncvars[ncvarid].bounds].dimids[0] ) - { - *time_has_bounds = TRUE; - streamptr->basetime.ncvarboundsid = ncvars[ncvarid].bounds; - if ( ncvars[ncvarid].climatology ) *time_climatology = TRUE; - } - } - } - } -} - -static -void read_vct_echam(int fileID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims, double **vct, size_t *pvctsize) -{ - /* find ECHAM VCT */ - int nvcth_id = UNDEFID, vcta_id = UNDEFID, vctb_id = UNDEFID; - - for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].ndims == 1 ) - { - size_t len = strlen(ncvars[ncvarid].name); - if ( len == 4 && ncvars[ncvarid].name[0] == 'h' && ncvars[ncvarid].name[1] == 'y' ) - { - if ( ncvars[ncvarid].name[2] == 'a' && ncvars[ncvarid].name[3] == 'i' ) // hyai - { - vcta_id = ncvarid; - nvcth_id = ncvars[ncvarid].dimids[0]; - ncvars[ncvarid].isvar = FALSE; - } - else if ( ncvars[ncvarid].name[2] == 'b' && ncvars[ncvarid].name[3] == 'i' ) //hybi - { - vctb_id = ncvarid; - nvcth_id = ncvars[ncvarid].dimids[0]; - ncvars[ncvarid].isvar = FALSE; - } - else if ( (ncvars[ncvarid].name[2] == 'a' || ncvars[ncvarid].name[2] == 'b') && ncvars[ncvarid].name[3] == 'm' ) - { - ncvars[ncvarid].isvar = FALSE; // hyam or hybm - } - } - } - } - - /* read VCT */ - if ( nvcth_id != UNDEFID && vcta_id != UNDEFID && vctb_id != UNDEFID ) - { - size_t vctsize = ncdims[nvcth_id].len; - vctsize *= 2; - *vct = (double *) Malloc(vctsize*sizeof(double)); - cdf_get_var_double(fileID, vcta_id, *vct); - cdf_get_var_double(fileID, vctb_id, *vct+vctsize/2); - *pvctsize = vctsize; - } -} - - -int cdfInqContents(stream_t *streamptr) -{ - int ndims, nvars, ngatts, unlimdimid; - int ncvarid; - int ncdimid; - size_t ntsteps; - int timedimid = -1; - int *varids; - int nvarids; - int time_has_units = FALSE; - int time_has_bounds = FALSE; - int time_climatology = FALSE; - int leadtime_id = UNDEFID; - int nvars_data; - int instID = UNDEFID; - int modelID = UNDEFID; - int taxisID; - int i; - int calendar = UNDEFID; - ncdim_t *ncdims; - ncvar_t *ncvars = NULL; - int format = 0; - int ucla_les = FALSE; - unsigned char uuidOfHGrid[CDI_UUID_SIZE]; - unsigned char uuidOfVGrid[CDI_UUID_SIZE]; - char gridfile[8912]; - char fcreftime[CDI_MAX_NAME]; - int number_of_grid_used = UNDEFID; - - memset(uuidOfHGrid, 0, CDI_UUID_SIZE); - memset(uuidOfVGrid, 0, CDI_UUID_SIZE); - gridfile[0] = 0; - fcreftime[0] = 0; - - int vlistID = streamptr->vlistID; - int fileID = streamptr->fileID; - - if ( CDI_Debug ) Message("streamID = %d, fileID = %d", streamptr->self, fileID); - -#if defined (HAVE_NETCDF4) - nc_inq_format(fileID, &format); -#endif - - cdf_inq(fileID, &ndims , &nvars, &ngatts, &unlimdimid); - - if ( CDI_Debug ) - Message("root: ndims %d, nvars %d, ngatts %d", ndims, nvars, ngatts); - - if ( ndims == 0 ) - { - Warning("ndims = %d", ndims); - return (CDI_EUFSTRUCT); - } - - /* alloc ncdims */ - ncdims = (ncdim_t *) Malloc((size_t)ndims * sizeof (ncdim_t)); - init_ncdims(ndims, ncdims); - - if ( nvars > 0 ) - { - /* alloc ncvars */ - ncvars = (ncvar_t *) Malloc((size_t)nvars * sizeof (ncvar_t)); - init_ncvars(nvars, ncvars); - - for ( ncvarid = 0; ncvarid < nvars; ++ncvarid ) - ncvars[ncvarid].ncid = fileID; - } - -#if defined (TEST_GROUPS) -#if defined (HAVE_NETCDF4) - if ( format == NC_FORMAT_NETCDF4 ) - { - int ncid; - int numgrps; - int ncids[NC_MAX_VARS]; - char name1[CDI_MAX_NAME]; - int gndims, gnvars, gngatts, gunlimdimid; - nc_inq_grps(fileID, &numgrps, ncids); - for ( int i = 0; i < numgrps; ++i ) - { - ncid = ncids[i]; - nc_inq_grpname (ncid, name1); - cdf_inq(ncid, &gndims , &gnvars, &gngatts, &gunlimdimid); - - if ( CDI_Debug ) - Message("%s: ndims %d, nvars %d, ngatts %d", name1, gndims, gnvars, gngatts); - - if ( gndims == 0 ) - { - } - } - } -#endif -#endif - - if ( nvars == 0 ) - { - Warning("nvars = %d", nvars); - return (CDI_EUFSTRUCT); - } - - /* scan global attributes */ - scan_global_attributes(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, - uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used); - - /* find time dim */ - if ( unlimdimid >= 0 ) - timedimid = unlimdimid; - else - timedimid = cdfTimeDimID(fileID, ndims, nvars); - - streamptr->basetime.ncdimid = timedimid; - - if ( timedimid != UNDEFID ) - cdf_inq_dimlen(fileID, timedimid, &ntsteps); - else - ntsteps = 0; - - if ( CDI_Debug ) Message("Number of timesteps = %d", ntsteps); - if ( CDI_Debug ) Message("Time dimid = %d", streamptr->basetime.ncdimid); - - /* read ncdims */ - for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) - { - cdf_inq_dimlen(fileID, ncdimid, &ncdims[ncdimid].len); - cdf_inq_dimname(fileID, ncdimid, ncdims[ncdimid].name); - if ( timedimid == ncdimid ) - ncdims[ncdimid].dimtype = T_AXIS; - } - - if ( CDI_Debug ) printNCvars(ncvars, nvars, "cdfScanVarAttributes"); - - /* scan attributes of all variables */ - cdfScanVarAttributes(nvars, ncvars, ncdims, timedimid, modelID, format); - - - if ( CDI_Debug ) printNCvars(ncvars, nvars, "find coordinate vars"); - - /* find coordinate vars */ - for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) - { - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].ndims == 1 ) - { - if ( timedimid != UNDEFID && timedimid == ncvars[ncvarid].dimids[0] ) - { - if ( ncvars[ncvarid].isvar != FALSE ) cdfSetVar(ncvars, ncvarid, TRUE); - } - else - { - // if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE); - } - // if ( ncvars[ncvarid].isvar != TRUE ) cdfSetVar(ncvars, ncvarid, FALSE); - - if ( ncdimid == ncvars[ncvarid].dimids[0] && ncdims[ncdimid].ncvarid == UNDEFID ) - if ( strcmp(ncvars[ncvarid].name, ncdims[ncdimid].name) == 0 ) - { - ncdims[ncdimid].ncvarid = ncvarid; - ncvars[ncvarid].isvar = FALSE; - } - } - } - } - - /* find time vars */ - find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &time_has_units, &time_has_bounds, &time_climatology); - - leadtime_id = find_leadtime(nvars, ncvars); - if ( leadtime_id != UNDEFID ) ncvars[leadtime_id].isvar = FALSE; - - /* check ncvars */ - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( timedimid != UNDEFID ) - if ( ncvars[ncvarid].isvar == -1 && - ncvars[ncvarid].ndims > 1 && - timedimid == ncvars[ncvarid].dimids[0] ) - cdfSetVar(ncvars, ncvarid, TRUE); - - if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims == 0 ) - cdfSetVar(ncvars, ncvarid, FALSE); - - //if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims > 1 ) - if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims >= 1 ) - cdfSetVar(ncvars, ncvarid, TRUE); - - if ( ncvars[ncvarid].isvar == -1 ) - { - ncvars[ncvarid].isvar = 0; - Warning("Variable %s has an unknown type, skipped!", ncvars[ncvarid].name); - continue; - } - - if ( ncvars[ncvarid].ndims > 4 ) - { - ncvars[ncvarid].isvar = 0; - Warning("%d dimensional variables are not supported, skipped variable %s!", - ncvars[ncvarid].ndims, ncvars[ncvarid].name); - continue; - } - - if ( ncvars[ncvarid].ndims == 4 && timedimid == UNDEFID ) - { - ncvars[ncvarid].isvar = 0; - Warning("%d dimensional variables without time dimension are not supported, skipped variable %s!", - ncvars[ncvarid].ndims, ncvars[ncvarid].name); - continue; - } - - if ( xtypeIsText(ncvars[ncvarid].xtype) ) - { - ncvars[ncvarid].isvar = 0; - continue; - } - - if ( cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned) == -1 ) - { - ncvars[ncvarid].isvar = 0; - Warning("Variable %s has an unsupported data type, skipped!", ncvars[ncvarid].name); - continue; - } - - if ( timedimid != UNDEFID && ntsteps == 0 && ncvars[ncvarid].ndims > 0 ) - { - if ( timedimid == ncvars[ncvarid].dimids[0] ) - { - ncvars[ncvarid].isvar = 0; - Warning("Number of time steps undefined, skipped variable %s!", ncvars[ncvarid].name); - continue; - } - } - } - - /* verify coordinate vars - first scan (dimname == varname) */ - verify_coordinate_vars_1(fileID, ndims, ncdims, ncvars, timedimid); - - /* verify coordinate vars - second scan (all other variables) */ - verify_coordinate_vars_2(nvars, ncvars); - - if ( CDI_Debug ) printNCvars(ncvars, nvars, "verify_coordinate_vars"); - - if ( ucla_les == TRUE ) - { - for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) - { - ncvarid = ncdims[ncdimid].ncvarid; - if ( ncvarid != -1 ) - { - if ( ncdims[ncdimid].dimtype == UNDEFID && ncvars[ncvarid].units[0] == 'm' ) - { - if ( ncvars[ncvarid].name[0] == 'x' ) ncdims[ncdimid].dimtype = X_AXIS; - else if ( ncvars[ncvarid].name[0] == 'y' ) ncdims[ncdimid].dimtype = Y_AXIS; - else if ( ncvars[ncvarid].name[0] == 'z' ) ncdims[ncdimid].dimtype = Z_AXIS; - } - } - } - } - /* - for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) - { - ncvarid = ncdims[ncdimid].ncvarid; - if ( ncvarid != -1 ) - { - printf("coord var %d %s %s\n", ncvarid, ncvars[ncvarid].name, ncvars[ncvarid].units); - if ( ncdims[ncdimid].dimtype == X_AXIS ) - printf("coord var %d %s is x dim\n", ncvarid, ncvars[ncvarid].name); - if ( ncdims[ncdimid].dimtype == Y_AXIS ) - printf("coord var %d %s is y dim\n", ncvarid, ncvars[ncvarid].name); - if ( ncdims[ncdimid].dimtype == Z_AXIS ) - printf("coord var %d %s is z dim\n", ncvarid, ncvars[ncvarid].name); - if ( ncdims[ncdimid].dimtype == T_AXIS ) - printf("coord var %d %s is t dim\n", ncvarid, ncvars[ncvarid].name); - - if ( ncvars[ncvarid].islon ) - printf("coord var %d %s is lon\n", ncvarid, ncvars[ncvarid].name); - if ( ncvars[ncvarid].islat ) - printf("coord var %d %s is lat\n", ncvarid, ncvars[ncvarid].name); - if ( ncvars[ncvarid].islev ) - printf("coord var %d %s is lev\n", ncvarid, ncvars[ncvarid].name); - } - } - */ - - /* Set coordinate varids (att: associate) */ - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - { - if ( ncvars[ncvarid].isvar == TRUE && ncvars[ncvarid].ncoordvars ) - { - /* ndims = ncvars[ncvarid].ndims; */ - ndims = ncvars[ncvarid].ncoordvars; - for ( i = 0; i < ndims; i++ ) - { - if ( ncvars[ncvars[ncvarid].coordvarids[i]].islon ) - ncvars[ncvarid].xvarid = ncvars[ncvarid].coordvarids[i]; - else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islat ) - ncvars[ncvarid].yvarid = ncvars[ncvarid].coordvarids[i]; - else if ( ncvars[ncvars[ncvarid].coordvarids[i]].islev ) - ncvars[ncvarid].zvarid = ncvars[ncvarid].coordvarids[i]; - } - } - } - - /* set dim type */ - setDimType(nvars, ncvars, ncdims); - - /* read ECHAM VCT if present */ - size_t vctsize = 0; - double *vct = NULL; - read_vct_echam(fileID, nvars, ncvars, ncdims, &vct, &vctsize); - - - if ( CDI_Debug ) printNCvars(ncvars, nvars, "define_all_grids"); - - /* define all grids */ - define_all_grids(streamptr, vlistID, ncdims, nvars, ncvars, timedimid, uuidOfHGrid, gridfile, number_of_grid_used); - - - /* define all zaxes */ - define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid); - if ( vct ) Free(vct); - - - /* select vars */ - varids = (int *) Malloc((size_t)nvars * sizeof (int)); - nvarids = 0; - for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) - if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid; - - nvars_data = nvarids; - - if ( CDI_Debug ) Message("time varid = %d", streamptr->basetime.ncvarid); - if ( CDI_Debug ) Message("ntsteps = %d", ntsteps); - if ( CDI_Debug ) Message("nvars_data = %d", nvars_data); - - - if ( nvars_data == 0 ) - { - streamptr->ntsteps = 0; - return (CDI_EUFSTRUCT); - } - - if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID ) - ntsteps = 1; - - streamptr->ntsteps = (long)ntsteps; - - /* define all data variables */ - define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars); - - - cdiCreateTimesteps(streamptr); - - /* time varID */ - int nctimevarid = streamptr->basetime.ncvarid; - - if ( time_has_units ) - { - taxis_t *taxis = &streamptr->tsteps[0].taxis; - - if ( setBaseTime(ncvars[nctimevarid].units, taxis) == 1 ) - { - nctimevarid = UNDEFID; - streamptr->basetime.ncvarid = UNDEFID; - } - - if ( leadtime_id != UNDEFID && taxis->type == TAXIS_RELATIVE ) - { - streamptr->basetime.leadtimeid = leadtime_id; - taxis->type = TAXIS_FORECAST; - - int timeunit = -1; - if ( ncvars[leadtime_id].units[0] != 0 ) timeunit = scanTimeUnit(ncvars[leadtime_id].units); - if ( timeunit == -1 ) timeunit = taxis->unit; - taxis->fc_unit = timeunit; - - setForecastTime(fcreftime, taxis); - } - } - - if ( time_has_bounds ) - { - streamptr->tsteps[0].taxis.has_bounds = TRUE; - if ( time_climatology ) streamptr->tsteps[0].taxis.climatology = TRUE; - } - - if ( nctimevarid != UNDEFID ) - { - taxis_t *taxis = &streamptr->tsteps[0].taxis; - ptaxisDefName(taxis, ncvars[nctimevarid].name); - if ( ncvars[nctimevarid].longname[0] ) - ptaxisDefLongname(taxis, ncvars[nctimevarid].longname); - } - - if ( nctimevarid != UNDEFID ) - if ( ncvars[nctimevarid].calendar == TRUE ) - { - enum {attstringlen = 8192}; - char attstring[attstringlen]; - - cdfGetAttText(fileID, nctimevarid, "calendar", attstringlen, attstring); - strtolower(attstring); - - if ( memcmp(attstring, "standard", 8) == 0 || - memcmp(attstring, "gregorian", 9) == 0 ) - calendar = CALENDAR_STANDARD; - else if ( memcmp(attstring, "none", 4) == 0 ) - calendar = CALENDAR_NONE; - else if ( memcmp(attstring, "proleptic", 9) == 0 ) - calendar = CALENDAR_PROLEPTIC; - else if ( memcmp(attstring, "360", 3) == 0 ) - calendar = CALENDAR_360DAYS; - else if ( memcmp(attstring, "365", 3) == 0 || - memcmp(attstring, "noleap", 6) == 0 ) - calendar = CALENDAR_365DAYS; - else if ( memcmp(attstring, "366", 3) == 0 || - memcmp(attstring, "all_leap", 8) == 0 ) - calendar = CALENDAR_366DAYS; - else - Warning("calendar >%s< unsupported!", attstring); - } - - if ( streamptr->tsteps[0].taxis.type == TAXIS_FORECAST ) - { - taxisID = taxisCreate(TAXIS_FORECAST); - } - else if ( streamptr->tsteps[0].taxis.type == TAXIS_RELATIVE ) - { - taxisID = taxisCreate(TAXIS_RELATIVE); - } - else - { - taxisID = taxisCreate(TAXIS_ABSOLUTE); - if ( !time_has_units ) - { - taxisDefTunit(taxisID, TUNIT_DAY); - streamptr->tsteps[0].taxis.unit = TUNIT_DAY; - } - } - - - if ( calendar == UNDEFID && streamptr->tsteps[0].taxis.type != TAXIS_ABSOLUTE ) - { - calendar = CALENDAR_STANDARD; - } - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) -#pragma GCC diagnostic push -#pragma GCC diagnostic warning "-Wstrict-overflow" -#endif - if ( calendar != UNDEFID ) - { - taxis_t *taxis = &streamptr->tsteps[0].taxis; - taxis->calendar = calendar; - taxisDefCalendar(taxisID, calendar); - } -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) -#pragma GCC diagnostic pop -#endif - - vlistDefTaxis(vlistID, taxisID); - - streamptr->curTsID = 0; - streamptr->rtsteps = 1; - - (void) cdfInqTimestep(streamptr, 0); - - cdfCreateRecords(streamptr, 0); - - /* free ncdims */ - Free(ncdims); - - /* free ncvars */ - Free(ncvars); - - return (0); -} - -static -void wrf_read_timestep(int fileID, int nctimevarid, int tsID, taxis_t *taxis) -{ - size_t start[2], count[2]; - char stvalue[32]; - start[0] = (size_t) tsID; start[1] = 0; - count[0] = 1; count[1] = 19; - stvalue[0] = 0; - cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue); - stvalue[19] = 0; - { - int year = 1, month = 1, day = 1 , hour = 0, minute = 0, second = 0; - if ( strlen(stvalue) == 19 ) - sscanf(stvalue, "%d-%d-%d_%d:%d:%d", &year, &month, &day, &hour, &minute, &second); - taxis->vdate = cdiEncodeDate(year, month, day); - taxis->vtime = cdiEncodeTime(hour, minute, second); - taxis->type = TAXIS_ABSOLUTE; - } -} - -static -double get_timevalue(int fileID, int nctimevarid, int tsID, timecache_t *tcache) -{ - double timevalue = 0; - size_t index = (size_t) tsID; - - if ( tcache ) - { - if ( tcache->size == 0 || (tsID < tcache->startid || tsID > (tcache->startid+tcache->size-1)) ) - { - int maxvals = MAX_TIMECACHE_SIZE; - tcache->startid = (tsID/MAX_TIMECACHE_SIZE)*MAX_TIMECACHE_SIZE; - if ( (tcache->startid + maxvals) > tcache->maxvals ) maxvals = (tcache->maxvals)%MAX_TIMECACHE_SIZE; - tcache->size = maxvals; - index = (size_t) tcache->startid; - // fprintf(stderr, "fill time cache: %d %d %d %d %d\n", tcache->maxvals, tsID, tcache->startid, tcache->startid+maxvals-1, maxvals); - for ( int ival = 0; ival < maxvals; ++ival ) - { - cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue); - if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; - tcache->cache[ival] = timevalue; - index++; - } - } - - timevalue = tcache->cache[tsID%MAX_TIMECACHE_SIZE]; - } - else - { - cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue); - if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; - } - - return timevalue; -} - - -int cdfInqTimestep(stream_t * streamptr, int tsID) -{ - long nrecs = 0; - double timevalue; - int fileID; - taxis_t *taxis; - - if ( CDI_Debug ) Message("streamID = %d tsID = %d", streamptr->self, tsID); - - if ( tsID < 0 ) Error("unexpected tsID = %d", tsID); - - if ( tsID < streamptr->ntsteps && streamptr->ntsteps > 0 ) - { - cdfCreateRecords(streamptr, tsID); - - taxis = &streamptr->tsteps[tsID].taxis; - if ( tsID > 0 ) - ptaxisCopy(taxis, &streamptr->tsteps[0].taxis); - - timevalue = tsID; - - int nctimevarid = streamptr->basetime.ncvarid; - if ( nctimevarid != UNDEFID ) - { - fileID = streamptr->fileID; - size_t index = (size_t)tsID; - - if ( streamptr->basetime.lwrf ) - { - wrf_read_timestep(fileID, nctimevarid, tsID, taxis); - } - else - { -#if defined (USE_TIMECACHE) - if ( streamptr->basetime.timevar_cache == NULL ) - { - streamptr->basetime.timevar_cache = (timecache_t *) Malloc(MAX_TIMECACHE_SIZE*sizeof(timecache_t)); - streamptr->basetime.timevar_cache->size = 0; - streamptr->basetime.timevar_cache->maxvals = streamptr->ntsteps; - } -#endif - timevalue = get_timevalue(fileID, nctimevarid, tsID, streamptr->basetime.timevar_cache); - cdiDecodeTimeval(timevalue, taxis, &taxis->vdate, &taxis->vtime); - } - - int nctimeboundsid = streamptr->basetime.ncvarboundsid; - if ( nctimeboundsid != UNDEFID ) - { - size_t start[2], count[2]; - start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1; - cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue); - if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; - - cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_lb, &taxis->vtime_lb); - - start[0] = index; count[0] = 1; start[1] = 1; count[1] = 1; - cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue); - if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; - - cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_ub, &taxis->vtime_ub); - } - - int leadtimeid = streamptr->basetime.leadtimeid; - if ( leadtimeid != UNDEFID ) - { - timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL); - cdiSetForecastPeriod(timevalue, taxis); - } - } - } - - streamptr->curTsID = tsID; - nrecs = streamptr->tsteps[tsID].nrecs; - - return ((int) nrecs); -} - - -void cdfDefHistory(stream_t *streamptr, int size, const char *history) -{ - int ncid = streamptr->fileID; - cdf_put_att_text(ncid, NC_GLOBAL, "history", (size_t) size, history); -} - - -int cdfInqHistorySize(stream_t *streamptr) -{ - size_t size = 0; - int ncid = streamptr->fileID; - if ( streamptr->historyID != UNDEFID ) - cdf_inq_attlen(ncid, NC_GLOBAL, "history", &size); - - return ((int) size); -} - - -void cdfInqHistoryString(stream_t *streamptr, char *history) -{ - int ncid = streamptr->fileID; - if ( streamptr->historyID != UNDEFID ) - { - nc_type atttype; - cdf_inq_atttype(ncid, NC_GLOBAL, "history", &atttype); - - if ( atttype == NC_CHAR ) - { - cdf_get_att_text(ncid, NC_GLOBAL, "history", history); - } -#if defined (HAVE_NETCDF4) - else if ( atttype == NC_STRING ) - { - // ToDo - Warning("History attribute with type NC_STRING unsupported!"); - } -#endif - } -} - - -void cdfDefVars(stream_t *streamptr) -{ - int vlistID = streamptr->vlistID; - if ( vlistID == UNDEFID ) - Error("Internal problem! vlist undefined for streamptr %p", streamptr); - - int ngrids = vlistNgrids(vlistID); - int nzaxis = vlistNzaxis(vlistID); - /* - if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr); - */ - if ( ngrids > 0 ) - for ( int index = 0; index < ngrids; index++ ) - { - int gridID = vlistGrid(vlistID, index); - cdfDefGrid(streamptr, gridID); - } - - if ( nzaxis > 0 ) - for ( int index = 0; index < nzaxis; index++ ) - { - int zaxisID = vlistZaxis(vlistID, index); - if ( streamptr->zaxisID[index] == UNDEFID ) cdfDefZaxis(streamptr, zaxisID); - } - - /* define time first!!! - int nvars = vlistNvars(vlistID); - for ( int varID = 0; varID < nvars; varID++ ) - { - int ncvarid = cdfDefVar(streamptr, varID); - } - */ -} -#endif -/* - * Local Variables: - * c-file-style: "Java" - * c-basic-offset: 2 - * indent-tabs-mode: nil - * show-trailing-whitespace: t - * require-trailing-newline: t - * End: - */ diff --git a/src/stream_cdf.h b/src/stream_cdf.h index c0228b853a09ccde16bb4a7cb821f671131f11d1..ad61c1ed6e06c0f7f8e5fed32f810771099bdd57 100644 --- a/src/stream_cdf.h +++ b/src/stream_cdf.h @@ -1,6 +1,8 @@ #ifndef _STREAM_CDF_H #define _STREAM_CDF_H +#include "cdi_int.h" + void cdfDefVars(stream_t *streamptr); void cdfDefTimestep(stream_t *streamptr, int tsID); int cdfInqTimestep(stream_t *streamptr, int tsID); @@ -14,6 +16,8 @@ void cdfDefRecord(stream_t * streamptr); void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1); +void cdfDefineAttributes(int vlistID, int varID, int fileID, int ncvarID); + void cdf_read_record(stream_t *streamptr, int memtype, void *data, int *nmiss); void cdf_write_record(stream_t *streamptr, int memtype, const void *data, int nmiss); @@ -29,6 +33,8 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype, void cdfDefVarDeflate(int ncid, int ncvarid, int deflate_level); void cdfDefTime(stream_t* streamptr); +void cdf_scale_add(size_t size, double *data, double addoffset, double scalefactor); + #endif /* * Local Variables: diff --git a/src/stream_cdf_i.c b/src/stream_cdf_i.c new file mode 100644 index 0000000000000000000000000000000000000000..dd561e9e7d1501e6b5e491b1fc083670678ad481 --- /dev/null +++ b/src/stream_cdf_i.c @@ -0,0 +1,4170 @@ +#if defined (HAVE_CONFIG_H) +#include "config.h" +#endif + +#ifdef HAVE_LIBNETCDF + +//#define TEST_GROUPS 1 + +#include <ctype.h> + +#include "dmemory.h" +#include "gaussgrid.h" +#include "cdi_int.h" +#include "cdi_uuid.h" +#include "stream_cdf.h" +#include "cdf_int.h" +#include "varscan.h" +#include "vlist.h" +#include "cdf_util.h" +#include "cdf_lazy_grid.h" + +#undef UNDEFID +#define UNDEFID CDI_UNDEFID + +#define X_AXIS 1 +#define Y_AXIS 2 +#define Z_AXIS 3 +#define T_AXIS 4 + +#define POSITIVE_UP 1 +#define POSITIVE_DOWN 2 + +typedef struct { + int ncvarid; + int dimtype; + size_t len; + char name[CDI_MAX_NAME]; +} +ncdim_t; +#define MAX_COORDVARS 4 +#define MAX_AUXVARS 4 + +typedef struct { + int ncid; + int isvar; + bool ignore; + bool isx; + bool isy; + bool islon; + bool islat; + bool islev; + bool istime; + bool warn; + bool climatology; + bool lformula; + bool lformulaterms; + int tsteptype; + int param; + int code; + int tabnum; + int bounds; + int gridID; + int zaxisID; + int gridtype; + int zaxistype; + int xdim; + int ydim; + int zdim; + int xvarid; + int yvarid; + int zvarid; + int tvarid; + int psvarid; + int p0varid; + int ncoordvars; + int coordvarids[MAX_COORDVARS]; + int nauxvars; + int auxvarids[MAX_AUXVARS]; + int cellarea; + int calendar; + int tableID; + int truncation; + int position; + bool defmissval; + bool deffillval; + int xtype; + int ndims; + int gmapid; + int positive; + int dimids[8]; + int dimtype[8]; + int chunks[8]; + int chunked; + int chunktype; + int natts; + int deflate; + bool lunsigned; + bool lvalidrange; + int *atts; + size_t vctsize; + double *vct; + double missval; + double fillval; + double addoffset; + double scalefactor; + double validrange[2]; + char name[CDI_MAX_NAME]; + char longname[CDI_MAX_NAME]; + char stdname[CDI_MAX_NAME]; + char units[CDI_MAX_NAME]; + char extra[CDI_MAX_NAME]; + ensinfo_t *ensdata; /* Ensemble information */ +} +ncvar_t; + + +static +void scanTimeString(const char *ptu, int *rdate, int *rtime) +{ + int year = 1, month = 1, day = 1; + int hour = 0, minute = 0, second = 0; + int v1 = 1, v2 = 1, v3 = 1; + + *rdate = 0; + *rtime = 0; + + if ( *ptu ) + { + v1 = atoi(ptu); + if ( v1 < 0 ) ptu++; + while ( isdigit((int) *ptu) ) ptu++; + if ( *ptu ) + { + v2 = atoi(++ptu); + while ( isdigit((int) *ptu) ) ptu++; + if ( *ptu ) + { + v3 = atoi(++ptu); + while ( isdigit((int) *ptu) ) ptu++; + } + } + } + + if ( v3 > 999 && v1 < 32 ) + { year = v3; month = v2; day = v1; } + else + { year = v1; month = v2; day = v3; } + + while ( isspace((int) *ptu) ) ptu++; + + if ( *ptu ) + { + while ( ! isdigit((int) *ptu) ) ptu++; + + hour = atoi(ptu); + while ( isdigit((int) *ptu) ) ptu++; + if ( *ptu == ':' ) + { + ptu++; + minute = atoi(ptu); + while ( isdigit((int) *ptu) ) ptu++; + if ( *ptu == ':' ) + { + ptu++; + second = atoi(ptu); + } + } + } + + *rdate = cdiEncodeDate(year, month, day); + *rtime = cdiEncodeTime(hour, minute, second); +} + +static +int scanTimeUnit(const char *unitstr) +{ + size_t len = strlen(unitstr); + int timeunit = get_timeunit(len, unitstr); + if ( timeunit == -1 ) + Message("Unsupported TIMEUNIT: %s!", unitstr); + + return timeunit; +} + +static +void setForecastTime(const char *timestr, taxis_t *taxis) +{ + (*taxis).fdate = 0; + (*taxis).ftime = 0; + + int len = (int) strlen(timestr); + if ( len == 0 ) return; + + int fdate = 0, ftime = 0; + scanTimeString(timestr, &fdate, &ftime); + + (*taxis).fdate = fdate; + (*taxis).ftime = ftime; +} + +static +int setBaseTime(const char *timeunits, taxis_t *taxis) +{ + int timetype = TAXIS_ABSOLUTE; + int rdate = -1, rtime = -1; + + size_t len = strlen(timeunits); + char *tu = (char *) Malloc((len+1) * sizeof (char)); + memcpy(tu, timeunits, (len+1) * sizeof (char)); + char *ptu = tu; + + for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]); + + int timeunit = get_timeunit(len, ptu); + if ( timeunit == -1 ) + { + Message("Unsupported TIMEUNIT: %s!", timeunits); + return 1; + } + + while ( ! isspace(*ptu) && *ptu != 0 ) ptu++; + if ( *ptu ) + { + while ( isspace(*ptu) ) ptu++; + + if ( memcmp(ptu, "as", 2) == 0 ) + timetype = TAXIS_ABSOLUTE; + else if ( memcmp(ptu, "since", 5) == 0 ) + timetype = TAXIS_RELATIVE; + + while ( ! isspace(*ptu) && *ptu != 0 ) ptu++; + if ( *ptu ) + { + while ( isspace(*ptu) ) ptu++; + + if ( timetype == TAXIS_ABSOLUTE ) + { + if ( memcmp(ptu, "%y%m%d.%f", 9) != 0 && timeunit == TUNIT_DAY ) + { + Message("Unsupported format %s for TIMEUNIT day!", ptu); + timeunit = -1; + } + else if ( memcmp(ptu, "%y%m.%f", 7) != 0 && timeunit == TUNIT_MONTH ) + { + Message("Unsupported format %s for TIMEUNIT month!", ptu); + timeunit = -1; + } + } + else if ( timetype == TAXIS_RELATIVE ) + { + scanTimeString(ptu, &rdate, &rtime); + + (*taxis).rdate = rdate; + (*taxis).rtime = rtime; + + if ( CDI_Debug ) + Message("rdate = %d rtime = %d", rdate, rtime); + } + } + } + + (*taxis).type = timetype; + (*taxis).unit = timeunit; + + Free(tu); + + if ( CDI_Debug ) + Message("timetype = %d unit = %d", timetype, timeunit); + + return 0; +} + +static +void cdfGetAttInt(int fileID, int ncvarid, const char *attname, int attlen, int *attint) +{ + nc_type atttype; + size_t nc_attlen; + + *attint = 0; + + cdf_inq_atttype(fileID, ncvarid, attname, &atttype); + cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen); + + if ( atttype != NC_CHAR ) + { + int *pintatt = (int)nc_attlen > attlen + ? (int *)(Malloc(nc_attlen * sizeof (int))) : attint; + + cdf_get_att_int(fileID, ncvarid, attname, pintatt); + + if ( (int)nc_attlen > attlen ) + { + memcpy(attint, pintatt, (size_t)attlen * sizeof (int)); + Free(pintatt); + } + } +} + +static +void cdfGetAttDouble(int fileID, int ncvarid, char *attname, int attlen, double *attdouble) +{ + nc_type atttype; + size_t nc_attlen; + + *attdouble = 0; + + cdf_inq_atttype(fileID, ncvarid, attname, &atttype); + cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen); + + if ( atttype != NC_CHAR ) + { + double *pdoubleatt = NULL; + + if ( (int)nc_attlen > attlen ) + pdoubleatt = (double *) Malloc(nc_attlen * sizeof (double)); + else + pdoubleatt = attdouble; + + cdf_get_att_double(fileID, ncvarid, attname, pdoubleatt); + + if ( (int)nc_attlen > attlen ) + { + memcpy(attdouble, pdoubleatt, (size_t)attlen * sizeof (double)); + Free(pdoubleatt); + } + } +} + +static +bool cdfCheckAttText(int fileID, int ncvarid, const char *attname) +{ + bool status = false; + nc_type atttype; + + int status_nc = nc_inq_atttype(fileID, ncvarid, attname, &atttype); + + if ( status_nc == NC_NOERR + && (atttype == NC_CHAR +#if defined (HAVE_NETCDF4) + || atttype == NC_STRING +#endif + ) ) + { + status = true; + } + + return status; +} + +static +void cdfGetAttText(int fileID, int ncvarid, const char *attname, int attlen, char *atttext) +{ + nc_type atttype; + size_t nc_attlen; + + cdf_inq_atttype(fileID, ncvarid, attname, &atttype); + cdf_inq_attlen(fileID, ncvarid, attname, &nc_attlen); + + if ( atttype == NC_CHAR ) + { + char attbuf[65636]; + if ( nc_attlen < sizeof(attbuf) ) + { + cdf_get_att_text(fileID, ncvarid, attname, attbuf); + + if ( (int) nc_attlen > (attlen-1) ) nc_attlen = (size_t)(attlen-1); + + attbuf[nc_attlen++] = 0; + memcpy(atttext, attbuf, nc_attlen); + } + else + { + atttext[0] = 0; + } + } +#if defined (HAVE_NETCDF4) + else if ( atttype == NC_STRING ) + { + if ( nc_attlen == 1 ) + { + char *attbuf = NULL; + cdf_get_att_string(fileID, ncvarid, attname, &attbuf); + + size_t ssize = strlen(attbuf) + 1; + + if ( ssize > (size_t)attlen ) ssize = (size_t)attlen; + memcpy(atttext, attbuf, ssize); + atttext[ssize - 1] = 0; + Free(attbuf); + } + else + { + atttext[0] = 0; + } + } +#endif +} + +static +bool xtypeIsText(nc_type xtype) +{ + bool isText = false; + + if ( xtype == NC_CHAR ) isText = true; +#if defined (HAVE_NETCDF4) + else if ( xtype == NC_STRING ) isText = true; +#endif + + return isText; +} + +static +bool xtypeIsFloat(nc_type xtype) +{ + bool isFloat = xtype == NC_FLOAT || xtype == NC_DOUBLE; + + return isFloat; +} + +static +bool xtypeIsInt(nc_type xtype) +{ + bool isInt = xtype == NC_SHORT || xtype == NC_INT + || xtype == NC_BYTE +#if defined (HAVE_NETCDF4) + || xtype == NC_USHORT || xtype == NC_UINT + || xtype == NC_UBYTE +#endif + ; + + return isInt; +} + +static +int cdfInqDatatype(int xtype, bool lunsigned) +{ + int datatype = -1; + +#if defined (HAVE_NETCDF4) + if ( xtype == NC_BYTE && lunsigned ) xtype = NC_UBYTE; +#endif + + if ( xtype == NC_BYTE ) datatype = DATATYPE_INT8; + /* else if ( xtype == NC_CHAR ) datatype = DATATYPE_UINT8; */ + else if ( xtype == NC_SHORT ) datatype = DATATYPE_INT16; + else if ( xtype == NC_INT ) datatype = DATATYPE_INT32; + else if ( xtype == NC_FLOAT ) datatype = DATATYPE_FLT32; + else if ( xtype == NC_DOUBLE ) datatype = DATATYPE_FLT64; +#if defined (HAVE_NETCDF4) + else if ( xtype == NC_UBYTE ) datatype = DATATYPE_UINT8; + else if ( xtype == NC_LONG ) datatype = DATATYPE_INT32; + else if ( xtype == NC_USHORT ) datatype = DATATYPE_UINT16; + else if ( xtype == NC_UINT ) datatype = DATATYPE_UINT32; + else if ( xtype == NC_INT64 ) datatype = DATATYPE_FLT64; + else if ( xtype == NC_UINT64 ) datatype = DATATYPE_FLT64; +#endif + + return datatype; +} + + +/* not used +int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID) +{ + int tsID, recID; + + recID = streamptr->tsteps[0].curRecID++; + printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID); + printf("cdfInqRecord tsID %d\n", streamptr->curTsID); + + if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs ) + { + streamptr->tsteps[0].curRecID = 0; + } + + *varID = streamptr->tsteps[0].records[recID].varID; + *levelID = streamptr->tsteps[0].records[recID].levelID; + + streamptr->record->varID = *varID; + streamptr->record->levelID = *levelID; + + if ( CDI_Debug ) + Message("recID = %d varID = %d levelID = %d", recID, *varID, *levelID); + + return (recID+1); +} +*/ + +void cdf_scale_add(size_t size, double *data, double addoffset, double scalefactor) +{ + int laddoffset = IS_NOT_EQUAL(addoffset, 0); + int lscalefactor = IS_NOT_EQUAL(scalefactor, 1); + + if ( laddoffset || lscalefactor ) + { + for ( size_t i = 0; i < size; ++i ) + { + if ( lscalefactor ) data[i] *= scalefactor; + if ( laddoffset ) data[i] += addoffset; + } + } +} + +static +void cdfCreateRecords(stream_t *streamptr, int tsID) +{ + if ( tsID < 0 || (tsID >= streamptr->ntsteps && tsID > 0) ) return; + + if ( streamptr->tsteps[tsID].nallrecs > 0 ) return; + + int vlistID = streamptr->vlistID; + + tsteps_t* sourceTstep = streamptr->tsteps; + tsteps_t* destTstep = sourceTstep + tsID; + + int nvars = vlistNvars(vlistID); + int nrecs = vlistNrecs(vlistID); + + if ( nrecs <= 0 ) return; + + if ( tsID == 0 ) + { + int nvrecs = nrecs; /* use all records at first timestep */ + + streamptr->nrecs += nrecs; + + destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t)); + destTstep->nrecs = nrecs; + destTstep->nallrecs = nrecs; + destTstep->recordSize = nrecs; + destTstep->curRecID = UNDEFID; + destTstep->recIDs = (int *) Malloc((size_t)nvrecs*sizeof (int));; + for ( int recID = 0; recID < nvrecs; recID++ ) destTstep->recIDs[recID] = recID; + + record_t *records = destTstep->records; + + for ( int varID = 0, recID = 0; varID < nvars; varID++ ) + { + int zaxisID = vlistInqVarZaxis(vlistID, varID); + int nlev = zaxisInqSize(zaxisID); + for ( int levelID = 0; levelID < nlev; levelID++ ) + { + recordInitEntry(&records[recID]); + records[recID].varID = (short)varID; + records[recID].levelID = (short)levelID; + recID++; + } + } + } + else if ( tsID == 1 ) + { + int nvrecs = 0; + for ( int varID = 0; varID < nvars; varID++ ) + { + if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT ) + { + int zaxisID = vlistInqVarZaxis(vlistID, varID); + nvrecs += zaxisInqSize(zaxisID); + } + } + + streamptr->nrecs += nvrecs; + + destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t)); + destTstep->nrecs = nvrecs; + destTstep->nallrecs = nrecs; + destTstep->recordSize = nrecs; + destTstep->curRecID = UNDEFID; + + memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t)); + + if ( nvrecs ) + { + destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof (int)); + for ( int recID = 0, vrecID = 0; recID < nrecs; recID++ ) + { + int varID = destTstep->records[recID].varID; + if ( vlistInqVarTsteptype(vlistID, varID) != TSTEP_CONSTANT ) + { + destTstep->recIDs[vrecID++] = recID; + } + } + } + } + else + { + if ( streamptr->tsteps[1].records == 0 ) cdfCreateRecords(streamptr, 1); + + int nvrecs = streamptr->tsteps[1].nrecs; + + streamptr->nrecs += nvrecs; + + destTstep->records = (record_t *) Malloc((size_t)nrecs*sizeof(record_t)); + destTstep->nrecs = nvrecs; + destTstep->nallrecs = nrecs; + destTstep->recordSize = nrecs; + destTstep->curRecID = UNDEFID; + + memcpy(destTstep->records, sourceTstep->records, (size_t)nrecs*sizeof(record_t)); + + destTstep->recIDs = (int *) Malloc((size_t)nvrecs * sizeof(int)); + + memcpy(destTstep->recIDs, streamptr->tsteps[1].recIDs, (size_t)nvrecs*sizeof(int)); + } +} + +static +int cdf_time_dimid(int fileID, int ndims, int nvars) +{ + char dimname[80]; + for ( int dimid = 0; dimid < ndims; ++dimid ) + { + dimname[0] = 0; + cdf_inq_dimname(fileID, dimid, dimname); + size_t len = strlen(dimname); + if ( len >= 4 && memcmp(dimname, "time", 4) == 0 ) return dimid; + if ( len >= 4 && memcmp(dimname, "Time", 4) == 0 ) return dimid; + } + + for ( int varid = 0; varid < nvars; ++varid ) + { + nc_type xtype; + int nvdims, nvatts, dimids[9]; + cdf_inq_var(fileID, varid, NULL, &xtype, &nvdims, dimids, &nvatts); + if ( nvdims == 1 ) + { + char sbuf[CDI_MAX_NAME]; + for ( int iatt = 0; iatt < nvatts; ++iatt ) + { + sbuf[0] = 0; + cdf_inq_attname(fileID, varid, iatt, sbuf); + if ( strncmp(sbuf, "units", 5) == 0 ) + { + cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf); + str_tolower(sbuf); + + if ( is_time_units(sbuf) ) return dimids[0]; + } + } + } + } + + return UNDEFID; +} + +static +void init_ncdims(long ndims, ncdim_t *ncdims) +{ + for ( long ncdimid = 0; ncdimid < ndims; ncdimid++ ) + { + ncdims[ncdimid].ncvarid = UNDEFID; + ncdims[ncdimid].dimtype = UNDEFID; + ncdims[ncdimid].len = 0; + ncdims[ncdimid].name[0] = 0; + } +} + +static +void init_ncvars(long nvars, ncvar_t *ncvars) +{ + for ( long ncvarid = 0; ncvarid < nvars; ++ncvarid ) + { + ncvars[ncvarid].ncid = UNDEFID; + ncvars[ncvarid].isvar = UNDEFID; + ncvars[ncvarid].ignore = false; + ncvars[ncvarid].isx = false; + ncvars[ncvarid].isy = false; + ncvars[ncvarid].islon = false; + ncvars[ncvarid].islat = false; + ncvars[ncvarid].islev = false; + ncvars[ncvarid].istime = false; + ncvars[ncvarid].warn = false; + ncvars[ncvarid].climatology = false; + ncvars[ncvarid].lformula = false; + ncvars[ncvarid].lformulaterms = false; + ncvars[ncvarid].tsteptype = TSTEP_CONSTANT; + ncvars[ncvarid].param = UNDEFID; + ncvars[ncvarid].code = UNDEFID; + ncvars[ncvarid].tabnum = 0; + ncvars[ncvarid].calendar = FALSE; + ncvars[ncvarid].bounds = UNDEFID; + ncvars[ncvarid].gridID = UNDEFID; + ncvars[ncvarid].zaxisID = UNDEFID; + ncvars[ncvarid].gridtype = UNDEFID; + ncvars[ncvarid].zaxistype = UNDEFID; + ncvars[ncvarid].xdim = UNDEFID; + ncvars[ncvarid].ydim = UNDEFID; + ncvars[ncvarid].zdim = UNDEFID; + ncvars[ncvarid].xvarid = UNDEFID; + ncvars[ncvarid].yvarid = UNDEFID; + ncvars[ncvarid].zvarid = UNDEFID; + ncvars[ncvarid].tvarid = UNDEFID; + ncvars[ncvarid].psvarid = UNDEFID; + ncvars[ncvarid].p0varid = UNDEFID; + ncvars[ncvarid].ncoordvars = 0; + for ( int i = 0; i < MAX_COORDVARS; ++i ) + ncvars[ncvarid].coordvarids[i] = UNDEFID; + ncvars[ncvarid].nauxvars = 0; + for ( int i = 0; i < MAX_AUXVARS; ++i ) + ncvars[ncvarid].auxvarids[i] = UNDEFID; + ncvars[ncvarid].cellarea = UNDEFID; + ncvars[ncvarid].tableID = UNDEFID; + ncvars[ncvarid].xtype = 0; + ncvars[ncvarid].ndims = 0; + ncvars[ncvarid].gmapid = UNDEFID; + ncvars[ncvarid].vctsize = 0; + ncvars[ncvarid].vct = NULL; + ncvars[ncvarid].truncation = 0; + ncvars[ncvarid].position = 0; + ncvars[ncvarid].positive = 0; + ncvars[ncvarid].chunked = 0; + ncvars[ncvarid].chunktype = UNDEFID; + ncvars[ncvarid].defmissval = false; + ncvars[ncvarid].deffillval = false; + ncvars[ncvarid].missval = 0; + ncvars[ncvarid].fillval = 0; + ncvars[ncvarid].addoffset = 0; + ncvars[ncvarid].scalefactor = 1; + ncvars[ncvarid].name[0] = 0; + ncvars[ncvarid].longname[0] = 0; + ncvars[ncvarid].stdname[0] = 0; + ncvars[ncvarid].units[0] = 0; + ncvars[ncvarid].extra[0] = 0; + ncvars[ncvarid].natts = 0; + ncvars[ncvarid].atts = NULL; + ncvars[ncvarid].deflate = 0; + ncvars[ncvarid].lunsigned = false; + ncvars[ncvarid].lvalidrange = false; + ncvars[ncvarid].validrange[0] = VALIDMISS; + ncvars[ncvarid].validrange[1] = VALIDMISS; + ncvars[ncvarid].ensdata = NULL; + } +} + +static +void cdf_set_var(ncvar_t *ncvars, int ncvarid, short isvar) +{ + if ( ncvars[ncvarid].isvar != UNDEFID && + ncvars[ncvarid].isvar != isvar && + ncvars[ncvarid].warn == false ) + { + if ( ! ncvars[ncvarid].ignore ) + Warning("Inconsistent variable definition for %s!", ncvars[ncvarid].name); + + ncvars[ncvarid].warn = true; + isvar = FALSE; + } + + ncvars[ncvarid].isvar = isvar; +} + +static +void cdf_set_dim(ncvar_t *ncvars, int ncvarid, int dimid, int dimtype) +{ + if ( ncvars[ncvarid].dimtype[dimid] != UNDEFID && + ncvars[ncvarid].dimtype[dimid] != dimtype ) + { + Warning("Inconsistent dimension definition for %s! dimid = %d; type = %d; newtype = %d", + ncvars[ncvarid].name, dimid, ncvars[ncvarid].dimtype[dimid], dimtype); + } + + ncvars[ncvarid].dimtype[dimid] = dimtype; +} + +static +int scan_hybrid_formula(int ncid, int ncfvarid, int *apvarid, int *bvarid, int *psvarid, int *avarid, int *p0varid) +{ + int status = 0; + *apvarid = -1; + *bvarid = -1; + *psvarid = -1; + *avarid = -1; + *p0varid = -1; + enum { attstringlen = 8192 }; char attstring[attstringlen]; + cdfGetAttText(ncid, ncfvarid, "formula", attstringlen, attstring); + if ( strcmp(attstring, "p = ap + b*ps") == 0 ) + { + status = 1; + bool lstop = false; + int dimvarid; + cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring); + char *pstring = attstring; + + for ( int i = 0; i < 3; i++ ) + { + while ( isspace((int) *pstring) ) pstring++; + if ( *pstring == 0 ) break; + char *tagname = pstring; + while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; + if ( *pstring == 0 ) lstop = true; + *pstring++ = 0; + + while ( isspace((int) *pstring) ) pstring++; + if ( *pstring == 0 ) break; + char *varname = pstring; + while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; + if ( *pstring == 0 ) lstop = true; + *pstring++ = 0; + + int status_nc = nc_inq_varid(ncid, varname, &dimvarid); + if ( status_nc == NC_NOERR ) + { + if ( strcmp(tagname, "ap:") == 0 ) *apvarid = dimvarid; + else if ( strcmp(tagname, "b:") == 0 ) *bvarid = dimvarid; + else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid; + } + else if ( strcmp(tagname, "ps:") != 0 ) + { + Warning("%s - %s", nc_strerror(status_nc), varname); + } + + if ( lstop ) break; + } + } + else if ( strcmp(attstring, "xxxp = a*p0 + b*ps") == 0 ) + { + status = 2; + bool lstop = false; + int dimvarid; + cdfGetAttText(ncid, ncfvarid, "formula_terms", attstringlen, attstring); + char *pstring = attstring; + + for ( int i = 0; i < 4; i++ ) + { + while ( isspace((int) *pstring) ) pstring++; + if ( *pstring == 0 ) break; + char *tagname = pstring; + while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; + if ( *pstring == 0 ) lstop = true; + *pstring++ = 0; + + while ( isspace((int) *pstring) ) pstring++; + if ( *pstring == 0 ) break; + char *varname = pstring; + while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; + if ( *pstring == 0 ) lstop = true; + *pstring++ = 0; + + int status_nc = nc_inq_varid(ncid, varname, &dimvarid); + if ( status_nc == NC_NOERR ) + { + if ( strcmp(tagname, "a:") == 0 ) *avarid = dimvarid; + else if ( strcmp(tagname, "b:") == 0 ) *bvarid = dimvarid; + else if ( strcmp(tagname, "ps:") == 0 ) *psvarid = dimvarid; + else if ( strcmp(tagname, "p0:") == 0 ) *p0varid = dimvarid; + } + else if ( strcmp(tagname, "ps:") != 0 ) + { + Warning("%s - %s", nc_strerror(status_nc), varname); + } + + if ( lstop ) break; + } + } + + return status; +} + +static +bool isHybridSigmaPressureCoordinate(int ncid, int ncvarid, ncvar_t *ncvars, const ncdim_t *ncdims) +{ + bool status = false; + int ncfvarid = ncvarid; + ncvar_t *ncvar = &ncvars[ncvarid]; + + if ( strcmp(ncvar->stdname, "atmosphere_hybrid_sigma_pressure_coordinate") == 0 ) + { + cdiConvention = CDI_CONVENTION_CF; + + status = true; + ncvar->zaxistype = ZAXIS_HYBRID; + int dimid = ncvar->dimids[0]; + size_t dimlen = ncdims[dimid].len; + + int ret; + int apvarid1 = -1, bvarid1 = -1, psvarid1 = -1, avarid1 = -1, p0varid1 = -1; + if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms ) + ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid1, &bvarid1, &psvarid1, &avarid1, &p0varid1); + if ( apvarid1 != -1 ) ncvars[apvarid1].isvar = FALSE; + if ( bvarid1 != -1 ) ncvars[bvarid1].isvar = FALSE; + if ( psvarid1 != -1 ) ncvar->psvarid = psvarid1; + if ( avarid1 != -1 ) ncvars[avarid1].isvar = FALSE; + if ( p0varid1 != -1 ) ncvar->p0varid = p0varid1; + + if ( ncvar->bounds != UNDEFID && ncvars[ncvar->bounds].lformula && ncvars[ncvar->bounds].lformulaterms ) + { + ncfvarid = ncvar->bounds; + int apvarid2 = -1, bvarid2 = -1, psvarid2 = -1, avarid2 = -1, p0varid2 = -1; + ret = 0; + if ( ncvars[ncfvarid].lformula && ncvars[ncfvarid].lformulaterms ) + ret = scan_hybrid_formula(ncid, ncfvarid, &apvarid2, &bvarid2, &psvarid2, &avarid2, &p0varid2); + if ( ret == 1 ) avarid2 = apvarid2; + if ( avarid2 != -1 && bvarid2 != -1 ) + { + ncvars[avarid2].isvar = FALSE; + ncvars[bvarid2].isvar = FALSE; + + if ( dimid == ncvars[avarid2].dimids[0] && ncdims[ncvars[avarid2].dimids[1]].len == 2 ) + { + double px = 1; + if ( ret == 2 && p0varid1 == p0varid2 ) + cdf_get_var_double(ncid, p0varid2, &px); + + double abuf[dimlen*2], bbuf[dimlen*2]; + cdf_get_var_double(ncid, avarid2, abuf); + cdf_get_var_double(ncid, bvarid2, bbuf); + /* + for ( int i = 0; i < dimlen; ++i ) + printf("%d %g %g %g %g\n", i, abuf[i*2], abuf[i*2+1], bbuf[i*2], bbuf[i*2+1]); + */ + size_t vctsize = (dimlen+1)*2; + double *vct = (double *) Malloc(vctsize * sizeof(double)); + for ( size_t i = 0; i < dimlen; ++i ) + { + vct[i] = abuf[i*2]; + vct[i+dimlen+1] = bbuf[i*2]; + } + vct[dimlen] = abuf[dimlen*2-1]; + vct[dimlen*2+1] = bbuf[dimlen*2-1]; + + if ( ret == 2 && IS_NOT_EQUAL(px, 1) ) + for ( size_t i = 0; i < dimlen+1; ++i ) vct[i] *= px; + + ncvar->vct = vct; + ncvar->vctsize = vctsize; + } + } + } + } + + return status; +} + +static +void cdf_set_cdi_attr(int ncid, int ncvarid, int attnum, int cdiID, int varID) +{ + nc_type atttype; + size_t attlen; + char attname[CDI_MAX_NAME]; + + cdf_inq_attname(ncid, ncvarid, attnum, attname); + cdf_inq_attlen(ncid, ncvarid, attname, &attlen); + cdf_inq_atttype(ncid, ncvarid, attname, &atttype); + + if ( xtypeIsInt(atttype) ) + { + int attint[attlen]; + cdfGetAttInt(ncid, ncvarid, attname, (int)attlen, attint); + int datatype = (atttype == NC_SHORT) ? DATATYPE_INT16 : + (atttype == NC_BYTE) ? DATATYPE_INT8 : +#if defined (HAVE_NETCDF4) + (atttype == NC_UBYTE) ? DATATYPE_UINT8 : + (atttype == NC_USHORT) ? DATATYPE_UINT16 : + (atttype == NC_UINT) ? DATATYPE_UINT32 : +#endif + DATATYPE_INT32; + cdiDefAttInt(cdiID, varID, attname, datatype, (int)attlen, attint); + } + else if ( xtypeIsFloat(atttype) ) + { + double attflt[attlen]; + cdfGetAttDouble(ncid, ncvarid, attname, (int)attlen, attflt); + int datatype = (atttype == NC_FLOAT) ? DATATYPE_FLT32 : DATATYPE_FLT64; + cdiDefAttFlt(cdiID, varID, attname, datatype, (int)attlen, attflt); + } + else if ( xtypeIsText(atttype) ) + { + enum {attstringlen = 8192}; char attstring[attstringlen]; + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + cdiDefAttTxt(cdiID, varID, attname, (int)attlen, attstring); + } +} + +static +void cdf_print_vars(const ncvar_t *ncvars, int nvars, const char *oname) +{ + char axis[7]; + static const char iaxis[] = {'t', 'z', 'y', 'x'}; + + fprintf(stderr, "%s:\n", oname); + + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + int ndim = 0; + if ( ncvars[ncvarid].isvar ) + { + axis[ndim++] = 'v'; + axis[ndim++] = ':'; + for ( int i = 0; i < ncvars[ncvarid].ndims; i++ ) + {/* + if ( ncvars[ncvarid].tvarid != -1 ) axis[ndim++] = iaxis[0]; + else if ( ncvars[ncvarid].zvarid != -1 ) axis[ndim++] = iaxis[1]; + else if ( ncvars[ncvarid].yvarid != -1 ) axis[ndim++] = iaxis[2]; + else if ( ncvars[ncvarid].xvarid != -1 ) axis[ndim++] = iaxis[3]; + else + */ + if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) axis[ndim++] = iaxis[0]; + else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) axis[ndim++] = iaxis[1]; + else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) axis[ndim++] = iaxis[2]; + else if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) axis[ndim++] = iaxis[3]; + else axis[ndim++] = '?'; + } + } + else + { + axis[ndim++] = 'c'; + axis[ndim++] = ':'; + if ( ncvars[ncvarid].istime ) axis[ndim++] = iaxis[0]; + else if ( ncvars[ncvarid].islev ) axis[ndim++] = iaxis[1]; + else if ( ncvars[ncvarid].islat ) axis[ndim++] = iaxis[2]; + else if ( ncvars[ncvarid].isy ) axis[ndim++] = iaxis[2]; + else if ( ncvars[ncvarid].islon ) axis[ndim++] = iaxis[3]; + else if ( ncvars[ncvarid].isx ) axis[ndim++] = iaxis[3]; + else axis[ndim++] = '?'; + } + + axis[ndim++] = 0; + + fprintf(stderr, "%3d %3d %-6s %s\n", ncvarid, ndim-3, axis, ncvars[ncvarid].name); + } +} + +static +void cdf_scan_attr_axis(ncvar_t *ncvars, ncdim_t *ncdims, int ncvarid, const char *attstring, size_t attlen, + int nvdims, int *dimidsp, const char *name) +{ + int i; + for ( i = 0; i < (int)attlen; ++i ) + { + if ( attstring[i] != '-' && attstring[i] != 't' && attstring[i] != 'z' && + attstring[i] != 'y' && attstring[i] != 'x' ) + { + Warning("Unexpected character in axis attribute for %s, ignored!", name); + break; + } + } + + if ( i == (int) attlen && (int) attlen == nvdims ) + { + while ( attlen-- ) + { + if ( (int) attstring[attlen] == 't' ) + { + if ( attlen != 0 ) Warning("axis attribute 't' not on first position"); + cdf_set_dim(ncvars, ncvarid, (int)attlen, T_AXIS); + } + else if ( (int) attstring[attlen] == 'z' ) + { + ncvars[ncvarid].zdim = dimidsp[attlen]; + cdf_set_dim(ncvars, ncvarid, (int)attlen, Z_AXIS); + + if ( ncvars[ncvarid].ndims == 1 ) + { + cdf_set_var(ncvars, ncvarid, FALSE); + ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS; + } + } + else if ( (int) attstring[attlen] == 'y' ) + { + ncvars[ncvarid].ydim = dimidsp[attlen]; + cdf_set_dim(ncvars, ncvarid, (int)attlen, Y_AXIS); + + if ( ncvars[ncvarid].ndims == 1 ) + { + cdf_set_var(ncvars, ncvarid, FALSE); + ncdims[ncvars[ncvarid].dimids[0]].dimtype = Y_AXIS; + } + } + else if ( (int) attstring[attlen] == 'x' ) + { + ncvars[ncvarid].xdim = dimidsp[attlen]; + cdf_set_dim(ncvars, ncvarid, (int)attlen, X_AXIS); + + if ( ncvars[ncvarid].ndims == 1 ) + { + cdf_set_var(ncvars, ncvarid, FALSE); + ncdims[ncvars[ncvarid].dimids[0]].dimtype = X_AXIS; + } + } + } + } +} + +static +void cdf_scan_var_attr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, int modelID, int format) +{ + int ncdimid; + int nvdims, nvatts; + int iatt; + nc_type xtype, atttype; + size_t attlen; + char name[CDI_MAX_NAME]; + char attname[CDI_MAX_NAME]; + const int attstringlen = 8192; char attstring[8192]; + + int nchecked_vars = 0; + enum { max_check_vars = 9 }; + char *checked_vars[max_check_vars]; + for ( int i = 0; i < max_check_vars; ++i ) checked_vars[i] = NULL; + + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + int ncid = ncvars[ncvarid].ncid; + int *dimidsp = ncvars[ncvarid].dimids; + + cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts); + strcpy(ncvars[ncvarid].name, name); + + for ( ncdimid = 0; ncdimid < nvdims; ncdimid++ ) + ncvars[ncvarid].dimtype[ncdimid] = -1; + + ncvars[ncvarid].xtype = xtype; + ncvars[ncvarid].ndims = nvdims; + +#if defined (HAVE_NETCDF4) + if ( format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4 ) + { + int shuffle, deflate, deflate_level; + size_t chunks[nvdims]; + int storage_in; + nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflate_level); + if ( deflate > 0 ) ncvars[ncvarid].deflate = 1; + + if ( nc_inq_var_chunking(ncid, ncvarid, &storage_in, chunks) == NC_NOERR ) + { + if ( storage_in == NC_CHUNKED ) + { + ncvars[ncvarid].chunked = 1; + for ( int i = 0; i < nvdims; ++i ) ncvars[ncvarid].chunks[i] = (int)chunks[i]; + if ( CDI_Debug ) + { + fprintf(stderr, "%s: chunking %d %d %d chunks ", name, storage_in, NC_CONTIGUOUS, NC_CHUNKED); + for ( int i = 0; i < nvdims; ++i ) fprintf(stderr, "%ld ", chunks[i]); + fprintf(stderr, "\n"); + } + { + char *buf = ncvars[ncvarid].extra; + size_t pos = strlen(buf); + static const char prefix[] = "chunks="; + memcpy(buf + pos, prefix, sizeof (prefix)); + pos += sizeof (prefix) - 1; + for ( int i = nvdims-1; i >= 0; --i ) + { + pos += (size_t)(sprintf(buf + pos, "%zu%s", chunks[i], + i > 0 ? "x" : "")); + } + buf[pos] = ' '; buf[pos + 1] = 0; + } + } + } + } +#endif + + if ( nvdims > 0 ) + { + if ( timedimid == dimidsp[0] ) + { + ncvars[ncvarid].tsteptype = TSTEP_INSTANT; + cdf_set_dim(ncvars, ncvarid, 0, T_AXIS); + } + else + { + for ( ncdimid = 1; ncdimid < nvdims; ncdimid++ ) + { + if ( timedimid == dimidsp[ncdimid] ) + { + Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvars[ncvarid].name); + ncvars[ncvarid].isvar = FALSE; + } + } + } + } + + for ( iatt = 0; iatt < nvatts; iatt++ ) + { + cdf_inq_attname(ncid, ncvarid, iatt, attname); + cdf_inq_atttype(ncid, ncvarid, attname, &atttype); + cdf_inq_attlen(ncid, ncvarid, attname, &attlen); + + if ( strcmp(attname, "long_name") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].longname); + } + else if ( strcmp(attname, "standard_name") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].stdname); + } + else if ( strcmp(attname, "units") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, CDI_MAX_NAME, ncvars[ncvarid].units); + } + else if ( strcmp(attname, "calendar") == 0 ) + { + ncvars[ncvarid].calendar = TRUE; + } + else if ( strcmp(attname, "param") == 0 && xtypeIsText(atttype) ) + { + char paramstr[32]; + int pnum = 0, pcat = 255, pdis = 255; + cdfGetAttText(ncid, ncvarid, attname, sizeof(paramstr), paramstr); + sscanf(paramstr, "%d.%d.%d", &pnum, &pcat, &pdis); + ncvars[ncvarid].param = cdiEncodeParam(pnum, pcat, pdis); + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( strcmp(attname, "code") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].code); + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( strcmp(attname, "table") == 0 && !xtypeIsText(atttype) ) + { + int tablenum; + cdfGetAttInt(ncid, ncvarid, attname, 1, &tablenum); + if ( tablenum > 0 ) + { + ncvars[ncvarid].tabnum = tablenum; + ncvars[ncvarid].tableID = tableInq(modelID, tablenum, NULL); + if ( ncvars[ncvarid].tableID == CDI_UNDEFID ) + ncvars[ncvarid].tableID = tableDef(modelID, tablenum, NULL); + } + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( strcmp(attname, "trunc_type") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + if ( memcmp(attstring, "Triangular", attlen) == 0 ) + ncvars[ncvarid].gridtype = GRID_SPECTRAL; + } + else if ( strcmp(attname, "grid_type") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + str_tolower(attstring); + + set_gridtype(attstring, &ncvars[ncvarid].gridtype); + + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( strcmp(attname, "level_type") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + str_tolower(attstring); + + set_zaxistype(attstring, &ncvars[ncvarid].zaxistype); + + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( strcmp(attname, "trunc_count") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation); + } + else if ( strcmp(attname, "truncation") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].truncation); + } + else if ( strcmp(attname, "number_of_grid_in_reference") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttInt(ncid, ncvarid, attname, 1, &ncvars[ncvarid].position); + } + else if ( strcmp(attname, "add_offset") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].addoffset); + /* + if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT ) + if ( ncvars[ncvarid].addoffset != 0 ) + Warning("attribute add_offset not supported for atttype %d", atttype); + */ + /* (also used for lon/lat) cdf_set_var(ncvars, ncvarid, TRUE); */ + } + else if ( strcmp(attname, "scale_factor") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].scalefactor); + /* + if ( atttype != NC_BYTE && atttype != NC_SHORT && atttype != NC_INT ) + if ( ncvars[ncvarid].scalefactor != 1 ) + Warning("attribute scale_factor not supported for atttype %d", atttype); + */ + /* (also used for lon/lat) cdf_set_var(ncvars, ncvarid, TRUE); */ + } + else if ( strcmp(attname, "climatology") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + int ncboundsid; + int status = nc_inq_varid(ncid, attstring, &ncboundsid); + if ( status == NC_NOERR ) + { + ncvars[ncvarid].climatology = true; + ncvars[ncvarid].bounds = ncboundsid; + cdf_set_var(ncvars, ncvars[ncvarid].bounds, FALSE); + cdf_set_var(ncvars, ncvarid, FALSE); + } + else + Warning("%s - %s", nc_strerror(status), attstring); + } + else if ( xtypeIsText(atttype) && strcmp(attname, "bounds") == 0 ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + int ncboundsid; + int status = nc_inq_varid(ncid, attstring, &ncboundsid); + if ( status == NC_NOERR ) + { + ncvars[ncvarid].bounds = ncboundsid; + cdf_set_var(ncvars, ncvars[ncvarid].bounds, FALSE); + cdf_set_var(ncvars, ncvarid, FALSE); + } + else + Warning("%s - %s", nc_strerror(status), attstring); + } + else if ( xtypeIsText(atttype) && strcmp(attname, "formula_terms") == 0 ) + { + ncvars[ncvarid].lformulaterms = true; + } + else if ( xtypeIsText(atttype) && strcmp(attname, "formula") == 0 ) + { + ncvars[ncvarid].lformula = true; + } + else if ( strcmp(attname, "cell_measures") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + char *pstring = attstring; + + while ( isspace((int) *pstring) ) pstring++; + char *cell_measures = pstring; + while ( isalnum((int) *pstring) ) pstring++; + *pstring++ = 0; + while ( isspace((int) *pstring) ) pstring++; + char *cell_var = pstring; + while ( ! isspace((int) *pstring) && *pstring != 0 ) pstring++; + *pstring++ = 0; + /* + printf("cell_measures >%s<\n", cell_measures); + printf("cell_var >%s<\n", cell_var); + */ + if ( memcmp(cell_measures, "area", 4) == 0 ) + { + int nc_cell_id; + int status = nc_inq_varid(ncid, cell_var, &nc_cell_id); + if ( status == NC_NOERR ) + { + ncvars[ncvarid].cellarea = nc_cell_id; + /* ncvars[nc_cell_id].isvar = UNDEFID; */ + cdf_set_var(ncvars, nc_cell_id, FALSE); + } + else + Warning("%s - %s", nc_strerror(status), cell_var); + } + else + { + Warning("%s has an unexpected contents: %s", attname, cell_measures); + } + cdf_set_var(ncvars, ncvarid, TRUE); + } + /* + else if ( strcmp(attname, "coordinates") == 0 ) + { + char *pstring, *xvarname = NULL, *yvarname = NULL; + + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + pstring = attstring; + + while ( isspace((int) *pstring) ) pstring++; + xvarname = pstring; + while ( isgraph((int) *pstring) ) pstring++; + *pstring++ = 0; + while ( isspace((int) *pstring) ) pstring++; + yvarname = pstring; + while ( isgraph((int) *pstring) ) pstring++; + *pstring++ = 0; + + cdf_inq_varid(ncid, xvarname, &ncvars[ncvarid].xvarid); + cdf_inq_varid(ncid, yvarname, &ncvars[ncvarid].yvarid); + + cdf_set_var(ncvars, ncvars[ncvarid].xvarid, FALSE); + cdf_set_var(ncvars, ncvars[ncvarid].yvarid, FALSE); + cdf_set_var(ncvars, ncvarid, TRUE); + } + */ + else if ( (strcmp(attname, "associate") == 0 || strcmp(attname, "coordinates") == 0) && xtypeIsText(atttype) ) + { + bool lstop = false; + + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + char *pstring = attstring; + + for ( int i = 0; i < MAX_COORDVARS; i++ ) + { + while ( isspace((int) *pstring) ) pstring++; + if ( *pstring == 0 ) break; + char *varname = pstring; + while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; + if ( *pstring == 0 ) lstop = true; + *pstring++ = 0; + + int dimvarid; + int status = nc_inq_varid(ncid, varname, &dimvarid); + if ( status == NC_NOERR ) + { + cdf_set_var(ncvars, dimvarid, FALSE); + if ( cdiIgnoreAttCoordinates == false ) + { + ncvars[ncvarid].coordvarids[i] = dimvarid; + ncvars[ncvarid].ncoordvars++; + } + } + else + { + int k; + for ( k = 0; k < nchecked_vars; ++k ) + if ( strcmp(checked_vars[k], varname) == 0 ) break; + + if ( k == nchecked_vars ) + { + if ( nchecked_vars < max_check_vars ) checked_vars[nchecked_vars++] = strdup(varname); + Warning("%s - %s", nc_strerror(status), varname); + } + } + + if ( lstop ) break; + } + + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( (strcmp(attname, "auxiliary_variable") == 0) && xtypeIsText(atttype) ) + { + bool lstop = false; + + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + char *pstring = attstring; + + for ( int i = 0; i < MAX_AUXVARS; i++ ) + { + while ( isspace((int) *pstring) ) pstring++; + if ( *pstring == 0 ) break; + char *varname = pstring; + while ( !isspace((int) *pstring) && *pstring != 0 ) pstring++; + if ( *pstring == 0 ) lstop = true; + *pstring++ = 0; + + int dimvarid; + int status = nc_inq_varid(ncid, varname, &dimvarid); + if ( status == NC_NOERR ) + { + cdf_set_var(ncvars, dimvarid, FALSE); + // if ( cdiIgnoreAttCoordinates == FALSE ) + { + ncvars[ncvarid].auxvarids[i] = dimvarid; + ncvars[ncvarid].nauxvars++; + } + } + else + Warning("%s - %s", nc_strerror(status), varname); + + if ( lstop ) break; + } + + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( strcmp(attname, "grid_mapping") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + int nc_gmap_id; + int status = nc_inq_varid(ncid, attstring, &nc_gmap_id); + if ( status == NC_NOERR ) + { + ncvars[ncvarid].gmapid = nc_gmap_id; + cdf_set_var(ncvars, ncvars[ncvarid].gmapid, FALSE); + } + else + Warning("%s - %s", nc_strerror(status), attstring); + + cdf_set_var(ncvars, ncvarid, TRUE); + } + else if ( strcmp(attname, "positive") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + str_tolower(attstring); + + if ( memcmp(attstring, "down", 4) == 0 ) ncvars[ncvarid].positive = POSITIVE_DOWN; + else if ( memcmp(attstring, "up", 2) == 0 ) ncvars[ncvarid].positive = POSITIVE_UP; + + if ( ncvars[ncvarid].ndims == 1 ) + { + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, Z_AXIS); + ncdims[ncvars[ncvarid].dimids[0]].dimtype = Z_AXIS; + } + } + else if ( strcmp(attname, "_FillValue") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].fillval); + ncvars[ncvarid].deffillval = true; + /* cdf_set_var(ncvars, ncvarid, TRUE); */ + } + else if ( strcmp(attname, "missing_value") == 0 && !xtypeIsText(atttype) ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 1, &ncvars[ncvarid].missval); + ncvars[ncvarid].defmissval = true; + /* cdf_set_var(ncvars, ncvarid, TRUE); */ + } + else if ( strcmp(attname, "valid_range") == 0 && attlen == 2 ) + { + if ( ncvars[ncvarid].lvalidrange == false ) + { + extern int cdiIgnoreValidRange; + bool lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype); + if ( cdiIgnoreValidRange == FALSE && lignore == false ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 2, ncvars[ncvarid].validrange); + ncvars[ncvarid].lvalidrange = true; + if ( ((int)ncvars[ncvarid].validrange[0]) == 0 && ((int)ncvars[ncvarid].validrange[1]) == 255 ) + ncvars[ncvarid].lunsigned = true; + /* cdf_set_var(ncvars, ncvarid, TRUE); */ + } + else if ( lignore ) + { + Warning("Inconsistent data type for attribute %s:valid_range, ignored!", name); + } + } + } + else if ( strcmp(attname, "valid_min") == 0 && attlen == 1 ) + { + if ( ncvars[ncvarid].lvalidrange == false ) + { + extern int cdiIgnoreValidRange; + bool lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype); + if ( cdiIgnoreValidRange == FALSE && lignore == false ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[0]); + ncvars[ncvarid].lvalidrange = true; + } + else if ( lignore ) + { + Warning("Inconsistent data type for attribute %s:valid_min, ignored!", name); + } + } + } + else if ( strcmp(attname, "valid_max") == 0 && attlen == 1 ) + { + if ( ncvars[ncvarid].lvalidrange == false ) + { + extern int cdiIgnoreValidRange; + bool lignore = xtypeIsFloat(atttype) != xtypeIsFloat(xtype); + if ( cdiIgnoreValidRange == FALSE && lignore == false ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 1, &(ncvars[ncvarid].validrange)[1]); + ncvars[ncvarid].lvalidrange = true; + } + else if ( lignore ) + { + Warning("Inconsistent data type for attribute %s:valid_max, ignored!", name); + } + } + } + else if ( strcmp(attname, "_Unsigned") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + str_tolower(attstring); + + if ( memcmp(attstring, "true", 4) == 0 ) + { + ncvars[ncvarid].lunsigned = true; + /* + ncvars[ncvarid].lvalidrange = true; + ncvars[ncvarid].validrange[0] = 0; + ncvars[ncvarid].validrange[1] = 255; + */ + } + /* cdf_set_var(ncvars, ncvarid, TRUE); */ + } + else if ( strcmp(attname, "cdi") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + str_tolower(attstring); + + if ( memcmp(attstring, "ignore", 6) == 0 ) + { + ncvars[ncvarid].ignore = true; + cdf_set_var(ncvars, ncvarid, FALSE); + } + } + else if ( strcmp(attname, "axis") == 0 && xtypeIsText(atttype) ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + attlen = strlen(attstring); + + if ( (int) attlen > nvdims && nvdims > 0 && attlen > 1 ) + { + Warning("Unexpected axis attribute length for %s, ignored!", name); + } + else if ( nvdims == 0 && attlen == 1 ) + { + if ( attstring[0] == 'z' || attstring[0] == 'Z' ) + { + cdf_set_var(ncvars, ncvarid, FALSE); + ncvars[ncvarid].islev = true; + } + } + else + { + str_tolower(attstring); + cdf_scan_attr_axis(ncvars, ncdims, ncvarid, attstring, attlen, nvdims, dimidsp, name); + } + } + else if ( ( strcmp(attname, "realization") == 0 ) || + ( strcmp(attname, "ensemble_members") == 0 ) || + ( strcmp(attname, "forecast_init_type") == 0 ) ) + { + int temp; + + if( ncvars[ncvarid].ensdata == NULL ) + ncvars[ncvarid].ensdata = (ensinfo_t *) Malloc( sizeof( ensinfo_t ) ); + + cdfGetAttInt(ncid, ncvarid, attname, 1, &temp); + + if( strcmp(attname, "realization") == 0 ) + ncvars[ncvarid].ensdata->ens_index = temp; + else if( strcmp(attname, "ensemble_members") == 0 ) + ncvars[ncvarid].ensdata->ens_count = temp; + else if( strcmp(attname, "forecast_init_type") == 0 ) + ncvars[ncvarid].ensdata->forecast_init_type = temp; + + cdf_set_var(ncvars, ncvarid, TRUE); + } + else + { + if ( ncvars[ncvarid].natts == 0 ) + ncvars[ncvarid].atts + = (int *) Malloc((size_t)nvatts * sizeof (int)); + + ncvars[ncvarid].atts[ncvars[ncvarid].natts++] = iatt; + /* + int attrint; + double attrflt; + nc_type atttype; + cdf_inq_attlen(ncid, ncvarid, attname, &attlen); + cdf_inq_atttype(ncid, ncvarid, attname, &atttype); + if ( attlen == 1 && (atttype == NC_INT || atttype == NC_SHORT) ) + { + cdfGetAttInt(ncid, ncvarid, attname, 1, &attrint); + printf("int: %s.%s = %d\n", ncvars[ncvarid].name, attname, attrint); + } + else if ( attlen == 1 && (atttype == NC_FLOAT || atttype == NC_DOUBLE) ) + { + cdfGetAttDouble(ncid, ncvarid, attname, 1, &attrflt); + printf("flt: %s.%s = %g\n", ncvars[ncvarid].name, attname, attrflt); + } + else if ( atttype == NC_CHAR ) + { + cdfGetAttText(ncid, ncvarid, attname, attstringlen, attstring); + attstring[attlen] = 0; + printf("txt: %s.%s = %s\n", ncvars[ncvarid].name, attname, attstring); + } + else + printf("att: %s.%s = unknown\n", ncvars[ncvarid].name, attname); + */ + } + } + } + + for ( int i = 0; i < max_check_vars; ++i ) if ( checked_vars[i] ) Free(checked_vars[i]); +} + +static +void cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) +{ + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + if ( ncvars[ncvarid].isvar == TRUE ) + { + bool lxdim = false, lydim = false, lzdim = false/* , ltdim = false */; + int ndims = ncvars[ncvarid].ndims; + for ( int i = 0; i < ndims; i++ ) + { + int ncdimid = ncvars[ncvarid].dimids[i]; + if ( ncdims[ncdimid].dimtype == X_AXIS ) cdf_set_dim(ncvars, ncvarid, i, X_AXIS); + else if ( ncdims[ncdimid].dimtype == Y_AXIS ) cdf_set_dim(ncvars, ncvarid, i, Y_AXIS); + else if ( ncdims[ncdimid].dimtype == Z_AXIS ) cdf_set_dim(ncvars, ncvarid, i, Z_AXIS); + else if ( ncdims[ncdimid].dimtype == T_AXIS ) cdf_set_dim(ncvars, ncvarid, i, T_AXIS); + } + + if ( CDI_Debug ) + { + Message("var %d %s", ncvarid, ncvars[ncvarid].name); + for ( int i = 0; i < ndims; i++ ) + printf(" dim%d type=%d ", i, ncvars[ncvarid].dimtype[i]); + printf("\n"); + } + + for ( int i = 0; i < ndims; i++ ) + { + if ( ncvars[ncvarid].dimtype[i] == X_AXIS ) lxdim = true; + else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) lydim = true; + else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) lzdim = true; + /* else if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) ltdim = true; */ + } + + if ( !lxdim && ncvars[ncvarid].xvarid != UNDEFID ) + { + if ( ncvars[ncvars[ncvarid].xvarid].ndims == 0 ) lxdim = true; + } + + if ( !lydim && ncvars[ncvarid].yvarid != UNDEFID ) + { + if ( ncvars[ncvars[ncvarid].yvarid].ndims == 0 ) lydim = true; + } + + // if ( ndims > 1 ) + for ( int i = ndims-1; i >= 0; i-- ) + { + if ( ncvars[ncvarid].dimtype[i] == -1 ) + { + if ( !lxdim ) + { + cdf_set_dim(ncvars, ncvarid, i, X_AXIS); + lxdim = true; + } + else if ( !lydim && ncvars[ncvarid].gridtype != GRID_UNSTRUCTURED ) + { + cdf_set_dim(ncvars, ncvarid, i, Y_AXIS); + lydim = true; + } + else if ( !lzdim ) + { + cdf_set_dim(ncvars, ncvarid, i, Z_AXIS); + lzdim = true; + } + } + } + } + } +} + +/* verify coordinate vars - first scan (dimname == varname) */ +static +void verify_coordinate_vars_1(int ncid, int ndims, ncdim_t *ncdims, ncvar_t *ncvars, int timedimid) +{ + for ( int ncdimid = 0; ncdimid < ndims; ncdimid++ ) + { + int ncvarid = ncdims[ncdimid].ncvarid; + if ( ncvarid != -1 ) + { + if ( ncvars[ncvarid].dimids[0] == timedimid ) + { + ncvars[ncvarid].istime = true; + ncdims[ncdimid].dimtype = T_AXIS; + continue; + } + + if ( isHybridSigmaPressureCoordinate(ncid, ncvarid, ncvars, ncdims) ) continue; + + if ( ncvars[ncvarid].units[0] != 0 ) + { + if ( is_lon_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].islon = true; + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, X_AXIS); + ncdims[ncdimid].dimtype = X_AXIS; + } + else if ( is_lat_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].islat = true; + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, Y_AXIS); + ncdims[ncdimid].dimtype = Y_AXIS; + } + else if ( is_x_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].isx = true; + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, X_AXIS); + ncdims[ncdimid].dimtype = X_AXIS; + } + else if ( is_y_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].isy = true; + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, Y_AXIS); + ncdims[ncdimid].dimtype = Y_AXIS; + } + else if ( is_pressure_units(ncvars[ncvarid].units) ) + { + ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE; + } + else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 ) + { + if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; + else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; + else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; + else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; + else if ( strcmp(ncvars[ncvarid].units, "level") == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_GENERIC; + } + else if ( is_DBL_axis(ncvars[ncvarid].longname) ) + { + ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND; + } + else if ( is_height_units(ncvars[ncvarid].units) ) + { + if ( is_depth_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) + ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA; + else if ( is_height_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) + ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT; + } + } + else + { + if ( (strcmp(ncvars[ncvarid].longname, "generalized_height") == 0 || + strcmp(ncvars[ncvarid].longname, "generalized height") == 0) && + strcmp(ncvars[ncvarid].stdname, "height") == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_REFERENCE; + } + + if ( !ncvars[ncvarid].islon && ncvars[ncvarid].longname[0] != 0 && + !ncvars[ncvarid].islat && ncvars[ncvarid].longname[1] != 0 ) + { + if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 ) + { + ncvars[ncvarid].islon = true; + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, X_AXIS); + ncdims[ncdimid].dimtype = X_AXIS; + continue; + } + else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 ) + { + ncvars[ncvarid].islat = true; + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, Y_AXIS); + ncdims[ncdimid].dimtype = Y_AXIS; + continue; + } + } + + if ( ncvars[ncvarid].zaxistype != UNDEFID ) + { + ncvars[ncvarid].islev = true; + cdf_set_var(ncvars, ncvarid, FALSE); + cdf_set_dim(ncvars, ncvarid, 0, Z_AXIS); + ncdims[ncdimid].dimtype = Z_AXIS; + } + } + } +} + +/* verify coordinate vars - second scan (all other variables) */ +static +void verify_coordinate_vars_2(int nvars, ncvar_t *ncvars) +{ + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + if ( ncvars[ncvarid].isvar == 0 ) + { + if ( ncvars[ncvarid].units[0] != 0 ) + { + if ( is_lon_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].islon = true; + continue; + } + else if ( is_lat_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].islat = true; + continue; + } + else if ( is_x_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].isx = true; + continue; + } + else if ( is_y_axis(ncvars[ncvarid].units, ncvars[ncvarid].stdname) ) + { + ncvars[ncvarid].isy = true; + continue; + } + else if ( is_pressure_units(ncvars[ncvarid].units) ) + { + ncvars[ncvarid].zaxistype = ZAXIS_PRESSURE; + continue; + } + else if ( strcmp(ncvars[ncvarid].units, "level") == 0 || strcmp(ncvars[ncvarid].units, "1") == 0 ) + { + if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer midpoints") == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; + else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at midpoints", 25) == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID; + else if ( strcmp(ncvars[ncvarid].longname, "hybrid level at layer interfaces") == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; + else if ( strncmp(ncvars[ncvarid].longname, "hybrid level at interfaces", 26) == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_HYBRID_HALF; + else if ( strcmp(ncvars[ncvarid].units, "level") == 0 ) + ncvars[ncvarid].zaxistype = ZAXIS_GENERIC; + continue; + } + else if ( is_DBL_axis(ncvars[ncvarid].longname) ) + { + ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_LAND; + continue; + } + else if ( is_height_units(ncvars[ncvarid].units) ) + { + if ( is_depth_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) + ncvars[ncvarid].zaxistype = ZAXIS_DEPTH_BELOW_SEA; + else if ( is_height_axis(ncvars[ncvarid].stdname, ncvars[ncvarid].longname) ) + ncvars[ncvarid].zaxistype = ZAXIS_HEIGHT; + continue; + } + } + + /* not needed anymore for rotated grids */ + if ( !ncvars[ncvarid].islon && ncvars[ncvarid].longname[0] != 0 && + !ncvars[ncvarid].islat && ncvars[ncvarid].longname[1] != 0 ) + { + if ( memcmp(ncvars[ncvarid].longname+1, "ongitude", 8) == 0 ) + { + ncvars[ncvarid].islon = true; + continue; + } + else if ( memcmp(ncvars[ncvarid].longname+1, "atitude", 7) == 0 ) + { + ncvars[ncvarid].islat = true; + continue; + } + } + } + } +} + +static +void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar) +{ + if ( ncvar->chunked ) + { + int ndims = ncvar->ndims; + + if ( grid->type == GRID_UNSTRUCTURED ) + { + if ( ncvar->chunks[ndims-1] == grid->size ) + ncvar->chunktype = CDI_CHUNK_GRID; + else + ncvar->chunktype = CDI_CHUNK_AUTO; + } + else + { + if ( grid->x.size > 1 && grid->y.size > 1 && ndims > 1 && + grid->x.size == ncvar->chunks[ndims-1] && + grid->y.size == ncvar->chunks[ndims-2] ) + ncvar->chunktype = CDI_CHUNK_GRID; + else if ( grid->x.size > 1 && grid->x.size == ncvar->chunks[ndims-1] ) + ncvar->chunktype = CDI_CHUNK_LINES; + else + ncvar->chunktype = CDI_CHUNK_AUTO; + } + } +} + +/* define all input grids */ +static +void cdf_load_vals(size_t size, int ndims, int varid, ncvar_t *ncvar, double **gridvals, struct xyValGet *valsGet, + int ntdims, size_t *start, size_t *count) +{ + if ( CDI_netcdf_lazy_grid_load ) + { + *valsGet = (struct xyValGet){ + .scalefactor = ncvar->scalefactor, + .addoffset = ncvar->addoffset, + .start = { start[0], start[1], start[2] }, + .count = { count[0], count[1], count[2] }, + .size = size, + .datasetNCId = ncvar->ncid, + .varNCId = varid, + .ndims = (short)ndims, + }; + *gridvals = cdfPendingLoad; + } + else + { + *gridvals = (double*) Malloc(size*sizeof(double)); + if ( ntdims == 1 ) + cdf_get_vara_double(ncvar->ncid, varid, start, count, *gridvals); + else + cdf_get_var_double(ncvar->ncid, varid, *gridvals); + cdf_scale_add(size, *gridvals, ncvar->addoffset, ncvar->scalefactor); + } +} + +static +void cdf_load_bounds(size_t size, ncvar_t *ncvar, double **gridbounds, struct cdfLazyGridIds *cellBoundsGet) +{ + if ( CDI_netcdf_lazy_grid_load ) + { + cellBoundsGet->datasetNCId = ncvar->ncid; + cellBoundsGet->varNCId = ncvar->bounds; + *gridbounds = cdfPendingLoad; + } + else + { + *gridbounds = (double*) Malloc(size*sizeof(double)); + cdf_get_var_double(ncvar->ncid, ncvar->bounds, *gridbounds); + } +} + +static +void cdf_load_cellarea(size_t size, ncvar_t *ncvar, double **gridarea, struct cdfLazyGridIds *cellAreaGet) +{ + if ( CDI_netcdf_lazy_grid_load ) + { + cellAreaGet->datasetNCId = ncvar->ncid; + cellAreaGet->varNCId = ncvar->cellarea; + *gridarea = cdfPendingLoad; + } + else + { + *gridarea = (double*) Malloc(size*sizeof(double)); + cdf_get_var_double(ncvar->ncid, ncvar->cellarea, *gridarea); + } +} + +static +void cdf_copy_axis_attr(ncvar_t *ncvar, struct gridaxis_t *gridaxis) +{ + strcpy(gridaxis->name, ncvar->name); + strcpy(gridaxis->longname, ncvar->longname); + strcpy(gridaxis->units, ncvar->units); +} + +static +int cdf_get_xydimid(int ndims, int *dimids, int *dimtype, int *xdimid, int *ydimid) +{ + int nxdims = 0, nydims = 0; + int xdimids[2] = {-1,-1}, ydimids[2] = {-1,-1}; + + for ( int i = 0; i < ndims; i++ ) + { + if ( dimtype[i] == X_AXIS && nxdims < 2 ) + { + xdimids[nxdims] = dimids[i]; + nxdims++; + } + else if ( dimtype[i] == Y_AXIS && nydims < 2 ) + { + ydimids[nydims] = dimids[i]; + nydims++; + } + } + + if ( nxdims == 2 ) + { + *xdimid = xdimids[1]; + *ydimid = xdimids[0]; + } + else if ( nydims == 2 ) + { + *xdimid = ydimids[1]; + *ydimid = ydimids[0]; + } + else + { + *xdimid = xdimids[0]; + *ydimid = ydimids[0]; + } + + return nydims; +} + +static +void cdf_check_gridtype(int *gridtype, bool islon, bool islat, size_t xsize, size_t ysize, grid_t *grid) +{ + if ( islat && (islon || xsize == 0) ) + { + double yinc = 0; + if ( islon && (int) ysize > 1 ) + { + yinc = fabs(grid->y.vals[0] - grid->y.vals[1]); + for ( size_t i = 2; i < ysize; i++ ) + if ( (fabs(grid->y.vals[i-1] - grid->y.vals[i]) - yinc) > (yinc/1000) ) + { + yinc = 0; + break; + } + } + if ( ysize < 10000 && isGaussGrid(ysize, yinc, grid->y.vals) ) + { + *gridtype = GRID_GAUSSIAN; + grid->np = (int)(ysize/2); + } + else + *gridtype = GRID_LONLAT; + } + else if ( islon && !islat && ysize == 0 ) + { + *gridtype = GRID_LONLAT; + } + else + *gridtype = GRID_GENERIC; +} + +static +bool cdf_read_xcoord(struct cdfLazyGrid *restrict lazyGrid, ncdim_t *ncdims, ncvar_t *ncvar, int xvarid, ncvar_t *axisvar, + size_t *xsize, size_t ysize, int ntdims, size_t *start, size_t *count, bool *islon) +{ + grid_t *grid = &lazyGrid->base; + bool skipvar = true; + *islon = axisvar->islon; + int ndims = axisvar->ndims; + size_t size = 0; + if ( (ndims - ntdims) == 2 ) + { + ncvar->gridtype = GRID_CURVILINEAR; + size = (*xsize)*ysize; + /* Check size of 2 dimensional coordinate variables */ + int dimid = axisvar->dimids[ndims-2]; + size_t dimsize1 = ncdims[dimid].len; + dimid = axisvar->dimids[ndims-1]; + size_t dimsize2 = ncdims[dimid].len; + skipvar = dimsize1*dimsize2 != size; + } + else if ( (ndims - ntdims) == 1 ) + { + size = *xsize; + /* Check size of 1 dimensional coordinate variables */ + int dimid = axisvar->dimids[ndims-1]; + size_t dimsize = ncdims[dimid].len; + skipvar = dimsize != size; + } + else if ( ndims == 0 && *xsize == 0 ) + { + size = *xsize = 1; + skipvar = false; + } + + if ( skipvar ) + { + Warning("Unsupported array structure, skipped variable %s!", ncvar->name); + ncvar->isvar = -1; + return true; + } + + if ( axisvar->xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32; + + cdf_load_vals(size, ndims, xvarid, axisvar, &grid->x.vals, &lazyGrid->xValsGet, ntdims, start, count); + + cdf_copy_axis_attr(axisvar, &grid->x); + + return false; +} + +static +bool cdf_read_ycoord(struct cdfLazyGrid *restrict lazyGrid, ncdim_t *ncdims, ncvar_t *ncvar, int yvarid, ncvar_t *axisvar, + size_t xsize, size_t *ysize, int ntdims, size_t *start, size_t *count, bool *islat) +{ + grid_t *grid = &lazyGrid->base; + bool skipvar = true; + *islat = axisvar->islat; + int ndims = axisvar->ndims; + size_t size = 0; + if ( (ndims - ntdims) == 2 ) + { + ncvar->gridtype = GRID_CURVILINEAR; + size = xsize*(*ysize); + /* Check size of 2 dimensional coordinate variables */ + int dimid = axisvar->dimids[ndims-2]; + size_t dimsize1 = ncdims[dimid].len; + dimid = axisvar->dimids[ndims-1]; + size_t dimsize2 = ncdims[dimid].len; + skipvar = dimsize1*dimsize2 != size; + } + else if ( (ndims - ntdims) == 1 ) + { + if ( (int) *ysize == 0 ) size = xsize; + else size = *ysize; + + int dimid = axisvar->dimids[ndims-1]; + size_t dimsize = ncdims[dimid].len; + skipvar = dimsize != size; + } + else if ( ndims == 0 && *ysize == 0 ) + { + size = *ysize = 1; + skipvar = false; + } + + if ( skipvar ) + { + Warning("Unsupported array structure, skipped variable %s!", ncvar->name); + ncvar->isvar = -1; + return true; + } + + if ( axisvar->xtype == NC_FLOAT ) grid->prec = DATATYPE_FLT32; + + cdf_load_vals(size, ndims, yvarid, axisvar, &grid->y.vals, &lazyGrid->yValsGet, + ntdims, start, count); + + cdf_copy_axis_attr(axisvar, &grid->y); + + return false; +} + +static +bool cdf_read_coordinates(struct cdfLazyGrid *restrict lazyGrid, ncvar_t *ncvar, ncvar_t *ncvars, ncdim_t *ncdims, + int timedimid, int xvarid, int yvarid, size_t xsize, size_t ysize, int *vdimid) +{ + grid_t *grid = &lazyGrid->base; + size_t size = 0; + + grid->prec = DATATYPE_FLT64; + + if ( ncvar->gridtype == GRID_TRAJECTORY ) + { + if ( ncvar->xvarid == UNDEFID ) Error("Longitude coordinate undefined for %s!", ncvar->name); + if ( ncvar->yvarid == UNDEFID ) Error("Latitude coordinate undefined for %s!", ncvar->name); + } + else + { + static bool ltwarn = true; + size_t start[3], count[3]; + int ntdims = 0; + + if ( xvarid != UNDEFID && yvarid != UNDEFID ) + { + int ndims = ncvars[xvarid].ndims; + if ( ndims != ncvars[yvarid].ndims ) + { + Warning("Inconsistent grid structure for variable %s!", ncvar->name); + ncvar->xvarid = xvarid = UNDEFID; + ncvar->yvarid = yvarid = UNDEFID; + } + if ( ndims > 1 ) + { + if ( ndims <= 3 ) + { + if ( ncvars[xvarid].dimids[0] == timedimid && ncvars[yvarid].dimids[0] == timedimid ) + { + size_t ntsteps = 0; + cdf_inq_dimlen(ncvar->ncid, timedimid, &ntsteps); + if ( ltwarn && ntsteps > 1 ) Warning("Time varying grids unsupported, using grid at time step 1!"); + ltwarn = false; + ntdims = 1; + start[0] = start[1] = start[2] = 0; + count[0] = 1; count[1] = ysize; count[ndims-1] = xsize; + } + } + else + { + Warning("Unsupported grid structure for variable %s (grid dims > 2)!", ncvar->name); + ncvar->xvarid = xvarid = UNDEFID; + ncvar->yvarid = yvarid = UNDEFID; + } + } + } + + if ( xvarid != UNDEFID ) + { + if ( (ncvars[xvarid].ndims - ntdims) > 2 ) + { + Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[xvarid].name, ncvars[xvarid].ndims); + //ncvar->xvarid = UNDEFID; + xvarid = UNDEFID; + } + } + + if ( yvarid != UNDEFID ) + { + if ( (ncvars[yvarid].ndims - ntdims) > 2 ) + { + Warning("Coordinate variable %s has to many dimensions (%d), skipped!", ncvars[yvarid].name, ncvars[yvarid].ndims); + //ncvar->yvarid = UNDEFID; + yvarid = UNDEFID; + } + } + + bool islon = false, islat = false; + + if ( xvarid != UNDEFID ) + if ( cdf_read_xcoord(lazyGrid, ncdims, ncvar, xvarid, &ncvars[xvarid], + &xsize, ysize, ntdims, start, count, &islon) ) + return true; + + if ( yvarid != UNDEFID ) + if ( cdf_read_ycoord(lazyGrid, ncdims, ncvar, yvarid, &ncvars[yvarid], + xsize, &ysize, ntdims, start, count, &islat) ) + return true; + + if ( (int) ysize == 0 ) size = xsize; + else if ( (int) xsize == 0 ) size = ysize; + else if ( ncvar->gridtype == GRID_UNSTRUCTURED ) size = xsize; + else size = xsize*ysize; + + if ( ncvar->gridtype == UNDEFID || ncvar->gridtype == GRID_GENERIC ) + cdf_check_gridtype(&ncvar->gridtype, islon, islat, xsize, ysize, grid); + } + + int gridtype = grid->type; + if ( gridtype != GRID_PROJECTION ) gridtype = ncvar->gridtype; + else if ( gridtype == GRID_PROJECTION && ncvar->gridtype == GRID_LONLAT ) + { + int gmapvarid = ncvar->gmapid; + if ( gmapvarid != UNDEFID && cdfCheckAttText(ncvar->ncid, gmapvarid, "grid_mapping_name") ) + { + char attstring[CDI_MAX_NAME]; + cdfGetAttText(ncvar->ncid, gmapvarid, "grid_mapping_name", CDI_MAX_NAME, attstring); + if ( strcmp(attstring, "latitude_longitude") == 0 ) gridtype = ncvar->gridtype; + } + } + + switch (gridtype) + { + case GRID_GENERIC: + case GRID_LONLAT: + case GRID_GAUSSIAN: + case GRID_UNSTRUCTURED: + case GRID_CURVILINEAR: + case GRID_PROJECTION: + { + grid->size = (int)size; + grid->x.size = (int)xsize; + grid->y.size = (int)ysize; + if ( xvarid != UNDEFID ) + { + grid->x.flag = 1; + int bvarid = ncvars[xvarid].bounds; + if ( bvarid != UNDEFID ) + { + int nbdims = ncvars[bvarid].ndims; + if ( nbdims == 2 || nbdims == 3 ) + { + *vdimid = ncvars[bvarid].dimids[nbdims-1]; + grid->nvertex = (int)ncdims[*vdimid].len; + cdf_load_bounds(grid->size*grid->nvertex, &ncvars[xvarid], &grid->x.bounds, &lazyGrid->xBoundsGet); + } + } + } + if ( yvarid != UNDEFID ) + { + grid->y.flag = 1; + int bvarid = ncvars[yvarid].bounds; + if ( bvarid != UNDEFID ) + { + int nbdims = ncvars[bvarid].ndims; + if ( nbdims == 2 || nbdims == 3 ) + { + if ( *vdimid == UNDEFID ) + { + *vdimid = ncvars[bvarid].dimids[nbdims-1]; + grid->nvertex = (int)ncdims[*vdimid].len; + } + cdf_load_bounds(grid->size*grid->nvertex, &ncvars[yvarid], &grid->y.bounds, &lazyGrid->yBoundsGet); + } + } + } + + if ( ncvar->cellarea != UNDEFID ) + cdf_load_cellarea(size, ncvar, &grid->area, &lazyGrid->cellAreaGet); + + break; + } + case GRID_SPECTRAL: + { + grid->size = (int)size; + grid->lcomplex = 1; + grid->trunc = ncvar->truncation; + break; + } + case GRID_FOURIER: + { + grid->size = (int)size; + grid->trunc = ncvar->truncation; + break; + } + case GRID_TRAJECTORY: + { + grid->size = 1; + break; + } + } + + // if ( grid->type != GRID_PROJECTION && grid->type != ncvar->gridtype ) + if ( grid->type != gridtype ) + { + // int gridtype = ncvar->gridtype; + grid->type = gridtype; + cdiGridTypeInit(grid, gridtype, grid->size); + } + + if ( grid->size == 0 ) + { + int ndims = ncvar->ndims; + int *dimtype = ncvar->dimtype; + if ( (ndims == 1 && dimtype[0] == T_AXIS) || + (ndims == 1 && dimtype[0] == Z_AXIS) || + (ndims == 2 && dimtype[0] == T_AXIS && dimtype[1] == Z_AXIS) ) + { + grid->type = GRID_GENERIC; + grid->size = 1; + grid->x.size = 0; + grid->y.size = 0; + } + else + { + Warning("Variable %s has an unsupported grid, skipped!", ncvar->name); + ncvar->isvar = -1; + return true; + } + } + + return false; +} + +static +bool cdf_set_unstructured_par(ncvar_t *ncvar, grid_t *grid, int xdimid, int ydimid, int number_of_grid_used, unsigned char *uuidOfHGrid) +{ + int ndims = ncvar->ndims; + int *dimtype = ncvar->dimtype; + + int zdimid = UNDEFID; + int xdimidx = UNDEFID, ydimidx = UNDEFID; + + for ( int i = 0; i < ndims; i++ ) + { + if ( dimtype[i] == X_AXIS ) xdimidx = i; + else if ( dimtype[i] == Y_AXIS ) ydimidx = i; + else if ( dimtype[i] == Z_AXIS ) zdimid = ncvar->dimids[i]; + } + + if ( xdimid != UNDEFID && ydimid != UNDEFID && zdimid == UNDEFID ) + { + if ( grid->x.size > grid->y.size && grid->y.size < 1000 ) + { + dimtype[ydimidx] = Z_AXIS; + ydimid = UNDEFID; + grid->size = grid->x.size; + grid->y.size = 0; + } + else if ( grid->y.size > grid->x.size && grid->x.size < 1000 ) + { + dimtype[xdimidx] = Z_AXIS; + xdimid = ydimid; + ydimid = UNDEFID; + grid->size = grid->y.size; + grid->x.size = grid->y.size; + grid->y.size = 0; + } + } + + if ( grid->size != grid->x.size ) + { + Warning("Unsupported array structure, skipped variable %s!", ncvar->name); + ncvar->isvar = -1; + return true; + } + + if ( number_of_grid_used != UNDEFID ) grid->number = number_of_grid_used; + if ( ncvar->position > 0 ) grid->position = ncvar->position; + if ( uuidOfHGrid[0] != 0 ) memcpy(grid->uuid, uuidOfHGrid, 16); + + return false; +} + +static +void cdf_read_mapping_atts(int ncid, int gmapvarid, int projID, const char *varname) +{ + if ( cdfCheckAttText(ncid, gmapvarid, "grid_mapping_name") ) + { + char attstring[CDI_MAX_NAME]; + cdfGetAttText(ncid, gmapvarid, "grid_mapping_name", CDI_MAX_NAME, attstring); + cdiGridDefKeyStr(projID, CDI_KEY_MAPPING, (int)(strlen(attstring)+1), attstring); + } + else + { + Warning("Text attribute %s:grid_mapping_name missing!", varname); + } + + int nvatts; + cdf_inq_varnatts(ncid, gmapvarid, &nvatts); + for ( int attnum = 0; attnum < nvatts; ++attnum ) + cdf_set_cdi_attr(ncid, gmapvarid, attnum, projID, CDI_GLOBAL); +} + +static +void cdf_set_proj_atts(int ncid, int gmapvarid, grid_t *grid) +{ + int nvatts; + cdf_inq_varnatts(ncid, gmapvarid, &nvatts); + + for ( int iatt = 0; iatt < nvatts; iatt++ ) + { + nc_type atttype; + size_t attlen; + char attname[CDI_MAX_NAME]; + cdf_inq_attname(ncid, gmapvarid, iatt, attname); + cdf_inq_attlen(ncid, gmapvarid, attname, &attlen); + cdf_inq_atttype(ncid, gmapvarid, attname, &atttype); + + if ( strcmp(attname, "grid_mapping_name") == 0 ) + { + enum {attstringlen = 8192}; + char attstring[attstringlen]; + cdfGetAttText(ncid, gmapvarid, attname, attstringlen, attstring); + str_tolower(attstring); + + if ( strcmp(attstring, "rotated_latitude_longitude") == 0 ) + grid->isRotated = TRUE; + else if ( strcmp(attstring, "sinusoidal") == 0 ) + grid->type = GRID_SINUSOIDAL; + else if ( strcmp(attstring, "lambert_azimuthal_equal_area") == 0 ) + grid->type = GRID_LAEA; + else if ( strcmp(attstring, "lambert_conformal_conic") == 0 ) + grid->type = GRID_LCC2; + } + else if ( strcmp(attname, "earth_radius") == 0 ) + { + double datt; + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &datt); + grid->laea.a = datt; + grid->lcc2.a = datt; + } + else if ( strcmp(attname, "longitude_of_projection_origin") == 0 ) + { + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->laea.lon_0); + } + else if ( strcmp(attname, "longitude_of_central_meridian") == 0 ) + { + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->lcc2.lon_0); + } + else if ( strcmp(attname, "latitude_of_projection_origin") == 0 ) + { + double datt; + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &datt); + grid->laea.lat_0 = datt; + grid->lcc2.lat_0 = datt; + } + else if ( strcmp(attname, "standard_parallel") == 0 ) + { + if ( attlen == 1 ) + { + double datt; + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &datt); + grid->lcc2.lat_1 = datt; + grid->lcc2.lat_2 = datt; + } + else + { + double datt2[2]; + cdfGetAttDouble(ncid, gmapvarid, attname, 2, datt2); + grid->lcc2.lat_1 = datt2[0]; + grid->lcc2.lat_2 = datt2[1]; + } + } + else if ( strcmp(attname, "grid_north_pole_latitude") == 0 ) + { + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->rll.ypole); + } + else if ( strcmp(attname, "grid_north_pole_longitude") == 0 ) + { + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->rll.xpole); + } + else if ( strcmp(attname, "north_pole_grid_longitude") == 0 ) + { + cdfGetAttDouble(ncid, gmapvarid, attname, 1, &grid->rll.angle); + } + } +} + +static +void cdf_set_grid_to_similar_vars(ncvar_t *ncvar1, ncvar_t *ncvar2, int gridtype, int xdimid, int ydimid) +{ + if ( ncvar2->isvar == TRUE && ncvar2->gridID == UNDEFID ) + { + int xdimid2 = UNDEFID, ydimid2 = UNDEFID, zdimid2 = UNDEFID; + int xdimidx = UNDEFID, ydimidx = UNDEFID; + int ndims2 = ncvar2->ndims; + + for ( int i = 0; i < ndims2; i++ ) + { + int *dimtype2 = ncvar2->dimtype; + int *dimids2 = ncvar2->dimids; + if ( dimtype2[i] == X_AXIS ) { xdimid2 = dimids2[i]; xdimidx = i; } + else if ( dimtype2[i] == Y_AXIS ) { ydimid2 = dimids2[i]; ydimidx = i; } + else if ( dimtype2[i] == Z_AXIS ) { zdimid2 = dimids2[i]; } + } + + if ( ncvar2->gridtype == UNDEFID && gridtype == GRID_UNSTRUCTURED ) + { + if ( xdimid == xdimid2 && ydimid2 != UNDEFID && zdimid2 == UNDEFID ) + { + ncvar2->dimtype[ydimidx] = Z_AXIS; + ydimid2 = UNDEFID; + } + + if ( xdimid == ydimid2 && xdimid2 != UNDEFID && zdimid2 == UNDEFID ) + { + ncvar2->dimtype[xdimidx] = Z_AXIS; + xdimid2 = ydimid2; + ydimid2 = UNDEFID; + } + } + + if ( xdimid == xdimid2 && + (ydimid == ydimid2 || (xdimid == ydimid && ydimid2 == UNDEFID)) ) + { + bool same_grid = ncvar1->xvarid == ncvar2->xvarid + && ncvar1->yvarid == ncvar2->yvarid + && ncvar1->position == ncvar2->position; + /* + if ( xvarid != -1 && ncvar2->xvarid != UNDEFID && + xvarid != ncvar2->xvarid ) same_grid = false; + + if ( yvarid != -1 && ncvar2->yvarid != UNDEFID && + yvarid != ncvar2->yvarid ) same_grid = false; + */ + + if ( same_grid ) + { + if ( CDI_Debug ) Message("Same gridID %d %s", ncvar1->gridID, ncvar2->name); + ncvar2->gridID = ncvar1->gridID; + ncvar2->chunktype = ncvar1->chunktype; + } + } + } +} + +static +void cdf_define_all_grids(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, + int timedimid, unsigned char *uuidOfHGrid, char *gridfile, int number_of_grid_used) +{ +#ifdef TEST_PROJECTION + bool testproj = true; +#else + bool testproj = false; +#endif + + for ( int ncvarid = 0; ncvarid < nvars; ++ncvarid ) + { + ncvar_t *ncvar = &ncvars[ncvarid]; + if ( ncvar->isvar && ncvar->gridID == UNDEFID ) + { + int gmapvarid = ncvar->gmapid; + bool lproj = gmapvarid != UNDEFID; + bool lgrid = !(lproj && ncvar->xvarid == UNDEFID); + int ndims = ncvar->ndims; + int *dimtype = ncvar->dimtype; + int vdimid = UNDEFID; + struct addIfNewRes projAdded = { .Id = CDI_UNDEFID, .isNew = 0 }, + gridAdded = { .Id = CDI_UNDEFID, .isNew = 0 }; + + int xdimid = UNDEFID, ydimid = UNDEFID; + int nydims = cdf_get_xydimid(ndims, ncvar->dimids, dimtype, &xdimid, &ydimid); + + int xaxisid = (xdimid != UNDEFID) ? ncdims[xdimid].ncvarid : UNDEFID; + int yaxisid = (ydimid != UNDEFID) ? ncdims[ydimid].ncvarid : UNDEFID; + int xvarid = (ncvar->xvarid != UNDEFID) ? ncvar->xvarid : xaxisid; + int yvarid = (ncvar->yvarid != UNDEFID) ? ncvar->yvarid : yaxisid; + + size_t xsize = (xdimid != UNDEFID) ? ncdims[xdimid].len : 0; + size_t ysize = (ydimid != UNDEFID) ? ncdims[ydimid].len : 0; + + if ( ydimid == UNDEFID && yvarid != UNDEFID ) + { + if ( ncvars[yvarid].ndims == 1 ) + { + ydimid = ncvars[yvarid].dimids[0]; + ysize = ncdims[ydimid].len; + } + } + + bool lunstructured = xdimid != UNDEFID && xdimid == ydimid && nydims == 0; + if ( (ncvar->gridtype == UNDEFID || ncvar->gridtype == GRID_GENERIC) && lunstructured ) + ncvar->gridtype = GRID_UNSTRUCTURED; + + struct cdfLazyGrid *restrict lazyGrid = NULL, *restrict lazyProj = NULL; + + { +#ifdef TEST_PROJECTION + int gridtype = !lgrid ? GRID_PROJECTION : ncvar->gridtype; +#else + int gridtype = ncvar->gridtype; +#endif + if ( CDI_netcdf_lazy_grid_load ) + { + cdfLazyGridRenew(&lazyGrid, gridtype); + if ( lgrid && lproj ) cdfLazyGridRenew(&lazyProj, GRID_PROJECTION); + } + else + { + cdfBaseGridRenew(&lazyGrid, gridtype); + if ( lgrid && lproj ) cdfBaseGridRenew(&lazyProj, GRID_PROJECTION); + } + } + grid_t *grid = &lazyGrid->base; + grid_t *proj = ( lgrid && lproj ) ? &lazyProj->base : NULL; + + xaxisid = (xdimid != UNDEFID) ? ncdims[xdimid].ncvarid : UNDEFID; + yaxisid = (ydimid != UNDEFID) ? ncdims[ydimid].ncvarid : UNDEFID; + + + if ( cdf_read_coordinates(lazyGrid, ncvar, ncvars, ncdims, + timedimid, xvarid, yvarid, xsize, ysize, &vdimid) ) + continue; + + if ( number_of_grid_used != UNDEFID && (grid->type == UNDEFID || grid->type == GRID_GENERIC) ) + grid->type = GRID_UNSTRUCTURED; + + if ( grid->type == GRID_UNSTRUCTURED ) + if ( cdf_set_unstructured_par(ncvar, grid, xdimid, ydimid, number_of_grid_used, uuidOfHGrid) ) + continue; + + if ( lproj ) + { + int ncid = ncvars[gmapvarid].ncid; + if ( !testproj && ncvar->gridtype != GRID_CURVILINEAR ) + { + cdf_set_proj_atts(ncid, gmapvarid, grid); + } + else if ( testproj ) + { + if ( lgrid ) + { + int dumid; + cdf_read_coordinates(lazyProj, ncvar, ncvars, ncdims, timedimid, + xaxisid, yaxisid, xsize, ysize, &dumid); + } + } + } + + if ( CDI_Debug ) + { + Message("grid: type = %d, size = %d, nx = %d, ny %d", + grid->type, grid->size, grid->x.size, grid->y.size); + if ( proj ) + Message("proj: type = %d, size = %d, nx = %d, ny %d", + proj->type, proj->size, proj->x.size, proj->y.size); + } + + + if ( lgrid && lproj && testproj ) + { + projAdded = cdiVlistAddGridIfNew(vlistID, proj, 2); + grid->proj = projAdded.Id; + } + + gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 1); + ncvar->gridID = gridAdded.Id; + + int gridID = ncvar->gridID; + + if ( lproj && testproj ) + { + int projID = lgrid ? grid->proj : gridID; + int ncid = ncvars[gmapvarid].ncid; + const char *gmapname = ncvars[gmapvarid].name; + cdf_read_mapping_atts(ncid, gmapvarid, projID, gmapname); + cdiGridDefKeyStr(projID, CDI_KEY_MAPNAME, (int)(strlen(gmapname)+1), gmapname); + gridVerifyProj(projID); + } + + if ( grid->type == GRID_UNSTRUCTURED && gridfile[0] != 0 ) + gridDefReference(gridID, gridfile); + + if ( ncvar->chunked ) grid_set_chunktype(grid, ncvar); + + int gridindex = vlistGridIndex(vlistID, gridID); + streamptr->xdimID[gridindex] = xdimid; + streamptr->ydimID[gridindex] = ydimid; + if ( xdimid == UNDEFID && ydimid == UNDEFID && grid->size == 1 ) + gridDefHasDims(gridID, FALSE); + + if ( xdimid != UNDEFID ) cdiGridDefKeyStr(gridID, CDI_KEY_XDIMNAME, (int)(strlen(ncdims[xdimid].name)+1), ncdims[xdimid].name); + if ( ydimid != UNDEFID ) cdiGridDefKeyStr(gridID, CDI_KEY_YDIMNAME, (int)(strlen(ncdims[ydimid].name)+1), ncdims[ydimid].name); + if ( vdimid != UNDEFID ) cdiGridDefKeyStr(gridID, CDI_KEY_VDIMNAME, (int)(strlen(ncdims[vdimid].name)+1), ncdims[vdimid].name); + + if ( CDI_Debug ) Message("gridID %d %d %s", gridID, ncvarid, ncvar->name); + + for ( int ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ ) + cdf_set_grid_to_similar_vars(ncvar, &ncvars[ncvarid2], grid->type, xdimid, ydimid); + + if ( gridAdded.isNew ) lazyGrid = NULL; + if ( projAdded.isNew ) lazyProj = NULL; + + if ( lazyGrid ) + { + if ( CDI_netcdf_lazy_grid_load ) cdfLazyGridDestroy(lazyGrid); + if ( grid ) { grid_free(grid); Free(grid); } + } + + if ( lazyProj ) + { + if ( CDI_netcdf_lazy_grid_load ) cdfLazyGridDestroy(lazyProj); + if ( proj ) { grid_free(proj); Free(proj); } + } + } + } +} + +/* define all input zaxes */ +static +void cdf_define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int nvars, ncvar_t *ncvars, + size_t vctsize_echam, double *vct_echam, unsigned char *uuidOfVGrid) +{ + int ncvarid2; + int i, ilev; + int zaxisindex; + int nbdims, nvertex, nlevel; + int psvarid = -1; + char *pname, *plongname, *punits; + size_t vctsize = vctsize_echam; + double *vct = vct_echam; + + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + ncvar_t *ncvar = &ncvars[ncvarid]; + if ( ncvar->isvar == TRUE && ncvar->zaxisID == UNDEFID ) + { + bool is_scalar = false; + bool with_bounds = false; + int zdimid = UNDEFID; + int zvarid = UNDEFID; + int zsize = 1; + double *lbounds = NULL; + double *ubounds = NULL; + + int positive = 0; + int ndims = ncvar->ndims; + + if ( ncvar->zvarid != -1 && ncvars[ncvar->zvarid].ndims == 0 ) + { + zvarid = ncvar->zvarid; + is_scalar = true; + } + else + { + for ( i = 0; i < ndims; i++ ) + { + if ( ncvar->dimtype[i] == Z_AXIS ) + zdimid = ncvar->dimids[i]; + } + + if ( zdimid != UNDEFID ) + { + zvarid = ncdims[zdimid].ncvarid; + zsize = (int)ncdims[zdimid].len; + } + } + + if ( CDI_Debug ) Message("nlevs = %d", zsize); + + double *zvar = (double *) Malloc((size_t)zsize * sizeof (double)); + + int zaxisType = UNDEFID; + if ( zvarid != UNDEFID ) zaxisType = ncvars[zvarid].zaxistype; + if ( zaxisType == UNDEFID ) zaxisType = ZAXIS_GENERIC; + + int zprec = DATATYPE_FLT64; + + if ( zvarid != UNDEFID ) + { + positive = ncvars[zvarid].positive; + pname = ncvars[zvarid].name; + plongname = ncvars[zvarid].longname; + punits = ncvars[zvarid].units; + if ( ncvars[zvarid].xtype == NC_FLOAT ) zprec = DATATYPE_FLT32; + /* don't change the name !!! */ + /* + if ( (len = strlen(pname)) > 2 ) + if ( pname[len-2] == '_' && isdigit((int) pname[len-1]) ) + pname[len-2] = 0; + */ + psvarid = -1; + if ( zaxisType == ZAXIS_HYBRID && ncvars[zvarid].vct ) + { + vct = ncvars[zvarid].vct; + vctsize = ncvars[zvarid].vctsize; + + if ( ncvars[zvarid].psvarid != -1 ) psvarid = ncvars[zvarid].psvarid; + } + + cdf_get_var_double(ncvars[zvarid].ncid, zvarid, zvar); + + if ( ncvars[zvarid].bounds != UNDEFID ) + { + nbdims = ncvars[ncvars[zvarid].bounds].ndims; + if ( nbdims == 2 ) + { + nlevel = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len; + nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len; + if ( nlevel == zsize && nvertex == 2 ) + { + with_bounds = true; + lbounds = (double *) Malloc((size_t)nlevel*sizeof(double)); + ubounds = (double *) Malloc((size_t)nlevel*sizeof(double)); + double zbounds[2*nlevel]; + cdf_get_var_double(ncvars[zvarid].ncid, ncvars[zvarid].bounds, zbounds); + for ( i = 0; i < nlevel; ++i ) + { + lbounds[i] = zbounds[i*2]; + ubounds[i] = zbounds[i*2+1]; + } + } + } + } + } + else + { + pname = NULL; + plongname = NULL; + punits = NULL; + + if ( zsize == 1 ) + { + if ( ncvar->zaxistype != UNDEFID ) + zaxisType = ncvar->zaxistype; + else + zaxisType = ZAXIS_SURFACE; + + zvar[0] = 0; + /* + if ( zdimid == UNDEFID ) + zvar[0] = 9999; + else + zvar[0] = 0; + */ + } + else + { + for ( ilev = 0; ilev < zsize; ilev++ ) zvar[ilev] = ilev + 1; + } + } + + ncvar->zaxisID = varDefZaxis(vlistID, zaxisType, (int) zsize, zvar, (int)with_bounds, lbounds, ubounds, + (int)vctsize, vct, pname, plongname, punits, zprec, 1, 0); + + if ( uuidOfVGrid[0] != 0 ) + { + // printf("uuidOfVGrid: defined\n"); + zaxisDefUUID(ncvar->zaxisID, uuidOfVGrid); + } + + if ( zaxisType == ZAXIS_HYBRID && psvarid != -1 ) zaxisDefPsName(ncvar->zaxisID, ncvars[psvarid].name); + + if ( positive > 0 ) zaxisDefPositive(ncvar->zaxisID, positive); + if ( is_scalar ) zaxisDefScalar(ncvar->zaxisID); + + if ( zdimid != -1 ) + cdiZaxisDefString(ncvar->zaxisID, CDI_ZAXIS_DIMNAME, (int)(strlen(ncdims[zdimid].name)+1), ncdims[zdimid].name); + /* + if ( vdimid != -1 ) + cdiZaxisDefString(ncvar->zaxisID, CDI_ZAXIS_VDIMNAME, strlen(ncdims[vdimid].name)+1, ncdims[vdimid].name); + */ + Free(zvar); + Free(lbounds); + Free(ubounds); + + zaxisindex = vlistZaxisIndex(vlistID, ncvar->zaxisID); + streamptr->zaxisID[zaxisindex] = zdimid; + + if ( CDI_Debug ) + Message("zaxisID %d %d %s", ncvar->zaxisID, ncvarid, ncvar->name); + + for ( ncvarid2 = ncvarid+1; ncvarid2 < nvars; ncvarid2++ ) + if ( ncvars[ncvarid2].isvar == TRUE && ncvars[ncvarid2].zaxisID == UNDEFID /*&& ncvars[ncvarid2].zaxistype == UNDEFID*/ ) + { + int zvarid2 = UNDEFID; + if ( ncvars[ncvarid2].zvarid != UNDEFID && ncvars[ncvars[ncvarid2].zvarid].ndims == 0 ) + zvarid2 = ncvars[ncvarid2].zvarid; + + int zdimid2 = UNDEFID; + ndims = ncvars[ncvarid2].ndims; + for ( i = 0; i < ndims; i++ ) + { + if ( ncvars[ncvarid2].dimtype[i] == Z_AXIS ) + zdimid2 = ncvars[ncvarid2].dimids[i]; + } + + if ( zdimid == zdimid2 /* && zvarid == zvarid2 */) + { + if ( (zdimid != UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) || + (zdimid == UNDEFID && zvarid != UNDEFID && zvarid == zvarid2) || + (zdimid == UNDEFID && zaxisType == ncvars[ncvarid2].zaxistype) || + (zdimid == UNDEFID && zvarid2 == UNDEFID && ncvars[ncvarid2].zaxistype == UNDEFID) ) + { + if ( CDI_Debug ) + Message("zaxisID %d %d %s", ncvar->zaxisID, ncvarid2, ncvars[ncvarid2].name); + ncvars[ncvarid2].zaxisID = ncvar->zaxisID; + } + } + } + } + } +} + +struct varinfo +{ + int ncvarid; + const char *name; +}; + +static +int cmpvarname(const void *s1, const void *s2) +{ + const struct varinfo *x = (const struct varinfo *)s1, + *y = (const struct varinfo *)s2; + return strcmp(x->name, y->name); +} + +/* define all input data variables */ +static +void cdf_define_all_vars(stream_t *streamptr, int vlistID, int instID, int modelID, int *varids, int nvars, int num_ncvars, ncvar_t *ncvars) +{ + if ( CDI_Debug ) + for ( int i = 0; i < nvars; i++ ) Message("varids[%d] = %d", i, varids[i]); + + if ( streamptr->sortname ) + { + struct varinfo *varInfo + = (struct varinfo *) Malloc((size_t)nvars * sizeof (struct varinfo)); + + for ( int varID = 0; varID < nvars; varID++ ) + { + int ncvarid = varids[varID]; + varInfo[varID].ncvarid = ncvarid; + varInfo[varID].name = ncvars[ncvarid].name; + } + qsort(varInfo, (size_t)nvars, sizeof(varInfo[0]), cmpvarname); + for ( int varID = 0; varID < nvars; varID++ ) + { + varids[varID] = varInfo[varID].ncvarid; + } + Free(varInfo); + if ( CDI_Debug ) + for ( int i = 0; i < nvars; i++ ) Message("sorted varids[%d] = %d", i, varids[i]); + } + + for ( int varID1 = 0; varID1 < nvars; varID1++ ) + { + int ncvarid = varids[varID1]; + int gridID = ncvars[ncvarid].gridID; + int zaxisID = ncvars[ncvarid].zaxisID; + + stream_new_var(streamptr, gridID, zaxisID, CDI_UNDEFID); + int varID = vlistDefVar(vlistID, gridID, zaxisID, ncvars[ncvarid].tsteptype); + +#if defined (HAVE_NETCDF4) + if ( ncvars[ncvarid].deflate ) + vlistDefVarCompType(vlistID, varID, CDI_COMPRESS_ZIP); + + if ( ncvars[ncvarid].chunked && ncvars[ncvarid].chunktype != UNDEFID ) + vlistDefVarChunkType(vlistID, varID, ncvars[ncvarid].chunktype); +#endif + + streamptr->vars[varID1].defmiss = 0; + streamptr->vars[varID1].ncvarid = ncvarid; + + vlistDefVarName(vlistID, varID, ncvars[ncvarid].name); + if ( ncvars[ncvarid].param != UNDEFID ) vlistDefVarParam(vlistID, varID, ncvars[ncvarid].param); + if ( ncvars[ncvarid].code != UNDEFID ) vlistDefVarCode(vlistID, varID, ncvars[ncvarid].code); + if ( ncvars[ncvarid].code != UNDEFID ) + { + int param = cdiEncodeParam(ncvars[ncvarid].code, ncvars[ncvarid].tabnum, 255); + vlistDefVarParam(vlistID, varID, param); + } + if ( ncvars[ncvarid].longname[0] ) vlistDefVarLongname(vlistID, varID, ncvars[ncvarid].longname); + if ( ncvars[ncvarid].stdname[0] ) vlistDefVarStdname(vlistID, varID, ncvars[ncvarid].stdname); + if ( ncvars[ncvarid].units[0] ) vlistDefVarUnits(vlistID, varID, ncvars[ncvarid].units); + + if ( ncvars[ncvarid].lvalidrange ) + vlistDefVarValidrange(vlistID, varID, ncvars[ncvarid].validrange); + + if ( IS_NOT_EQUAL(ncvars[ncvarid].addoffset, 0) ) + vlistDefVarAddoffset(vlistID, varID, ncvars[ncvarid].addoffset); + if ( IS_NOT_EQUAL(ncvars[ncvarid].scalefactor, 1) ) + vlistDefVarScalefactor(vlistID, varID, ncvars[ncvarid].scalefactor); + + vlistDefVarDatatype(vlistID, varID, cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned)); + + vlistDefVarInstitut(vlistID, varID, instID); + vlistDefVarModel(vlistID, varID, modelID); + if ( ncvars[ncvarid].tableID != UNDEFID ) + vlistDefVarTable(vlistID, varID, ncvars[ncvarid].tableID); + + if ( ncvars[ncvarid].deffillval == false && ncvars[ncvarid].defmissval ) + { + ncvars[ncvarid].deffillval = true; + ncvars[ncvarid].fillval = ncvars[ncvarid].missval; + } + + if ( ncvars[ncvarid].deffillval ) + vlistDefVarMissval(vlistID, varID, ncvars[ncvarid].fillval); + + if ( CDI_Debug ) + Message("varID = %d gridID = %d zaxisID = %d", varID, + vlistInqVarGrid(vlistID, varID), vlistInqVarZaxis(vlistID, varID)); + + int gridindex = vlistGridIndex(vlistID, gridID); + int xdimid = streamptr->xdimID[gridindex]; + int ydimid = streamptr->ydimID[gridindex]; + + int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); + int zdimid = streamptr->zaxisID[zaxisindex]; + + int ndims = ncvars[ncvarid].ndims; + int iodim = 0; + int ixyz = 0; + int ipow10[4] = {1, 10, 100, 1000}; + + if ( ncvars[ncvarid].tsteptype != TSTEP_CONSTANT ) iodim++; + + int *dimids = ncvars[ncvarid].dimids; + + if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ndims-iodim <= 2 && ydimid == xdimid ) + { + ixyz = (xdimid == dimids[ndims-1]) ? 321 : 213; + } + else + { + for ( int idim = iodim; idim < ndims; idim++ ) + { + if ( xdimid == dimids[idim] ) ixyz += 1*ipow10[ndims-idim-1]; + else if ( ydimid == dimids[idim] ) ixyz += 2*ipow10[ndims-idim-1]; + else if ( zdimid == dimids[idim] ) ixyz += 3*ipow10[ndims-idim-1]; + } + } + + vlistDefVarXYZ(vlistID, varID, ixyz); + /* + printf("ixyz %d\n", ixyz); + printf("ndims %d\n", ncvars[ncvarid].ndims); + for ( int i = 0; i < ncvars[ncvarid].ndims; ++i ) + printf("dimids: %d %d\n", i, dimids[i]); + printf("xdimid, ydimid %d %d\n", xdimid, ydimid); + */ + if ( ncvars[ncvarid].ensdata != NULL ) + { + vlistDefVarEnsemble( vlistID, varID, ncvars[ncvarid].ensdata->ens_index, + ncvars[ncvarid].ensdata->ens_count, + ncvars[ncvarid].ensdata->forecast_init_type ); + Free(ncvars[ncvarid].ensdata); + ncvars[ncvarid].ensdata = NULL; + } + + if ( ncvars[ncvarid].extra[0] != 0 ) + { + vlistDefVarExtra(vlistID, varID, ncvars[ncvarid].extra); + } + } + + for ( int varID = 0; varID < nvars; varID++ ) + { + int ncvarid = varids[varID]; + int ncid = ncvars[ncvarid].ncid; + + int nvatts = ncvars[ncvarid].natts; + for ( int iatt = 0; iatt < nvatts; ++iatt ) + { + int attnum = ncvars[ncvarid].atts[iatt]; + cdf_set_cdi_attr(ncid, ncvarid, attnum, vlistID, varID); + } + + if ( ncvars[ncvarid].atts ) + { + Free(ncvars[ncvarid].atts); + ncvars[ncvarid].atts = NULL; + } + + if ( ncvars[ncvarid].vct ) + { + Free(ncvars[ncvarid].vct); + ncvars[ncvarid].vct = NULL; + } + } + + /* release mem of not freed attributes */ + for ( int ncvarid = 0; ncvarid < num_ncvars; ncvarid++ ) + if ( ncvars[ncvarid].atts ) Free(ncvars[ncvarid].atts); + + if ( varids ) Free(varids); + + for ( int varID = 0; varID < nvars; varID++ ) + { + if ( vlistInqVarCode(vlistID, varID) == -varID-1 ) + { + const char *pname = vlistInqVarNamePtr(vlistID, varID); + size_t len = strlen(pname); + if ( len > 3 && isdigit((int) pname[3]) ) + { + if ( memcmp("var", pname, 3) == 0 ) + { + vlistDefVarCode(vlistID, varID, atoi(pname+3)); + // vlistDestroyVarName(vlistID, varID); + } + } + else if ( len > 4 && isdigit((int) pname[4]) ) + { + if ( memcmp("code", pname, 4) == 0 ) + { + vlistDefVarCode(vlistID, varID, atoi(pname+4)); + // vlistDestroyVarName(vlistID, varID); + } + } + else if ( len > 5 && isdigit((int) pname[5]) ) + { + if ( memcmp("param", pname, 5) == 0 ) + { + int pnum = -1, pcat = 255, pdis = 255; + sscanf(pname+5, "%d.%d.%d", &pnum, &pcat, &pdis); + vlistDefVarParam(vlistID, varID, cdiEncodeParam(pnum, pcat, pdis)); + // vlistDestroyVarName(vlistID, varID); + } + } + } + } + + for ( int varID = 0; varID < nvars; varID++ ) + { + int varInstID = vlistInqVarInstitut(vlistID, varID); + int varModelID = vlistInqVarModel(vlistID, varID); + int varTableID = vlistInqVarTable(vlistID, varID); + int code = vlistInqVarCode(vlistID, varID); + if ( cdiDefaultTableID != UNDEFID ) + { + if ( tableInqParNamePtr(cdiDefaultTableID, code) ) + { + vlistDestroyVarName(vlistID, varID); + vlistDestroyVarLongname(vlistID, varID); + vlistDestroyVarUnits(vlistID, varID); + + if ( varTableID != UNDEFID ) + { + vlistDefVarName(vlistID, varID, tableInqParNamePtr(cdiDefaultTableID, code)); + if ( tableInqParLongnamePtr(cdiDefaultTableID, code) ) + vlistDefVarLongname(vlistID, varID, tableInqParLongnamePtr(cdiDefaultTableID, code)); + if ( tableInqParUnitsPtr(cdiDefaultTableID, code) ) + vlistDefVarUnits(vlistID, varID, tableInqParUnitsPtr(cdiDefaultTableID, code)); + } + else + { + varTableID = cdiDefaultTableID; + } + } + + if ( cdiDefaultModelID != UNDEFID ) varModelID = cdiDefaultModelID; + if ( cdiDefaultInstID != UNDEFID ) varInstID = cdiDefaultInstID; + } + if ( varInstID != UNDEFID ) vlistDefVarInstitut(vlistID, varID, varInstID); + if ( varModelID != UNDEFID ) vlistDefVarModel(vlistID, varID, varModelID); + if ( varTableID != UNDEFID ) vlistDefVarTable(vlistID, varID, varTableID); + } +} + +static +void cdf_scan_global_attr(int fileID, int vlistID, stream_t *streamptr, int ngatts, int *instID, int *modelID, bool *ucla_les, unsigned char *uuidOfHGrid, unsigned char *uuidOfVGrid, char *gridfile, int *number_of_grid_used) +{ + nc_type xtype; + size_t attlen; + char attname[CDI_MAX_NAME]; + enum { attstringlen = 65636 }; + char attstring[attstringlen]; + + for ( int iatt = 0; iatt < ngatts; iatt++ ) + { + cdf_inq_attname(fileID, NC_GLOBAL, iatt, attname); + cdf_inq_atttype(fileID, NC_GLOBAL, attname, &xtype); + cdf_inq_attlen(fileID, NC_GLOBAL, attname, &attlen); + + if ( xtypeIsText(xtype) ) + { + cdfGetAttText(fileID, NC_GLOBAL, attname, attstringlen, attstring); + + size_t attstrlen = strlen(attstring); + + if ( attlen > 0 && attstring[0] != 0 ) + { + if ( strcmp(attname, "history") == 0 ) + { + streamptr->historyID = iatt; + } + else if ( strcmp(attname, "institution") == 0 ) + { + *instID = institutInq(0, 0, NULL, attstring); + if ( *instID == UNDEFID ) + *instID = institutDef(0, 0, NULL, attstring); + } + else if ( strcmp(attname, "source") == 0 ) + { + *modelID = modelInq(-1, 0, attstring); + if ( *modelID == UNDEFID ) + *modelID = modelDef(-1, 0, attstring); + } + else if ( strcmp(attname, "Source") == 0 ) + { + if ( strncmp(attstring, "UCLA-LES", 8) == 0 ) + *ucla_les = true; + } + /* + else if ( strcmp(attname, "Conventions") == 0 ) + { + } + */ + else if ( strcmp(attname, "CDI") == 0 ) + { + } + else if ( strcmp(attname, "CDO") == 0 ) + { + } + /* + else if ( strcmp(attname, "forecast_reference_time") == 0 ) + { + memcpy(fcreftime, attstring, attstrlen+1); + } + */ + else if ( strcmp(attname, "grid_file_uri") == 0 ) + { + memcpy(gridfile, attstring, attstrlen+1); + } + else if ( strcmp(attname, "uuidOfHGrid") == 0 && attstrlen == 36 ) + { + attstring[36] = 0; + cdiStr2UUID(attstring, uuidOfHGrid); + // printf("uuid: %d %s\n", attlen, attstring); + } + else if ( strcmp(attname, "uuidOfVGrid") == 0 && attstrlen == 36 ) + { + attstring[36] = 0; + cdiStr2UUID(attstring, uuidOfVGrid); + } + else + { + if ( strcmp(attname, "ICON_grid_file_uri") == 0 && gridfile[0] == 0 ) + { + memcpy(gridfile, attstring, attstrlen+1); + } + + cdiDefAttTxt(vlistID, CDI_GLOBAL, attname, (int)attstrlen, attstring); + } + } + } + else if ( xtype == NC_SHORT || xtype == NC_INT ) + { + if ( strcmp(attname, "number_of_grid_used") == 0 ) + { + (*number_of_grid_used) = UNDEFID; + cdfGetAttInt(fileID, NC_GLOBAL, attname, 1, number_of_grid_used); + } + else + { + int attint[attlen]; + cdfGetAttInt(fileID, NC_GLOBAL, attname, (int)attlen, attint); + int datatype = (xtype == NC_SHORT) ? DATATYPE_INT16 : DATATYPE_INT32; + cdiDefAttInt(vlistID, CDI_GLOBAL, attname, datatype, (int)attlen, attint); + } + } + else if ( xtype == NC_FLOAT || xtype == NC_DOUBLE ) + { + double attflt[attlen]; + cdfGetAttDouble(fileID, NC_GLOBAL, attname, (int)attlen, attflt); + int datatype = (xtype == NC_FLOAT) ? DATATYPE_FLT32 : DATATYPE_FLT64; + cdiDefAttFlt(vlistID, CDI_GLOBAL, attname, datatype, (int)attlen, attflt); + } + } +} + +static +int find_leadtime(int nvars, ncvar_t *ncvars) +{ + int leadtime_id = UNDEFID; + + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + if ( ncvars[ncvarid].stdname[0] && strcmp(ncvars[ncvarid].stdname, "forecast_period") == 0 ) + { + leadtime_id = ncvarid; + break; + } + } + + return leadtime_id; +} + +static +void find_time_vars(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimid, stream_t *streamptr, + bool *time_has_units, bool *time_has_bounds, bool *time_climatology) +{ + int ncvarid; + + if ( timedimid == UNDEFID ) + { + char timeunits[CDI_MAX_NAME]; + + for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + if ( ncvars[ncvarid].ndims == 0 && strcmp(ncvars[ncvarid].name, "time") == 0 ) + { + if ( ncvars[ncvarid].units[0] ) + { + strcpy(timeunits, ncvars[ncvarid].units); + str_tolower(timeunits); + + if ( is_time_units(timeunits) ) + { + streamptr->basetime.ncvarid = ncvarid; + break; + } + } + } + } + } + else + { + bool ltimevar = false; + + if ( ncdims[timedimid].ncvarid != UNDEFID ) + { + streamptr->basetime.ncvarid = ncdims[timedimid].ncvarid; + ltimevar = true; + } + + for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) + if ( ncvarid != streamptr->basetime.ncvarid && + ncvars[ncvarid].ndims == 1 && + timedimid == ncvars[ncvarid].dimids[0] && + !xtypeIsText(ncvars[ncvarid].xtype) && + is_timeaxis_units(ncvars[ncvarid].units) ) + { + ncvars[ncvarid].isvar = FALSE; + + if ( !ltimevar ) + { + streamptr->basetime.ncvarid = ncvarid; + ltimevar = true; + if ( CDI_Debug ) + fprintf(stderr, "timevar %s\n", ncvars[ncvarid].name); + } + else + { + Warning("Found more than one time variable, skipped variable %s!", ncvars[ncvarid].name); + } + } + + if ( ltimevar == false ) /* search for WRF time description */ + { + for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) + if ( ncvarid != streamptr->basetime.ncvarid && + ncvars[ncvarid].ndims == 2 && + timedimid == ncvars[ncvarid].dimids[0] && + xtypeIsText(ncvars[ncvarid].xtype) && + ncdims[ncvars[ncvarid].dimids[1]].len == 19 ) + { + streamptr->basetime.ncvarid = ncvarid; + streamptr->basetime.lwrf = true; + break; + } + } + + /* time varID */ + ncvarid = streamptr->basetime.ncvarid; + + if ( ncvarid == UNDEFID ) + { + Warning("Time variable >%s< not found!", ncdims[timedimid].name); + } + } + + /* time varID */ + ncvarid = streamptr->basetime.ncvarid; + + if ( ncvarid != UNDEFID && streamptr->basetime.lwrf == false ) + { + if ( ncvars[ncvarid].units[0] != 0 ) *time_has_units = true; + + if ( ncvars[ncvarid].bounds != UNDEFID ) + { + int nbdims = ncvars[ncvars[ncvarid].bounds].ndims; + if ( nbdims == 2 ) + { + int len = (int) ncdims[ncvars[ncvars[ncvarid].bounds].dimids[nbdims-1]].len; + if ( len == 2 && timedimid == ncvars[ncvars[ncvarid].bounds].dimids[0] ) + { + *time_has_bounds = true; + streamptr->basetime.ncvarboundsid = ncvars[ncvarid].bounds; + if ( ncvars[ncvarid].climatology ) *time_climatology = true; + } + } + } + } +} + +static +void read_vct_echam(int fileID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims, double **vct, size_t *pvctsize) +{ + /* find ECHAM VCT */ + int nvcth_id = UNDEFID, vcta_id = UNDEFID, vctb_id = UNDEFID; + + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + if ( ncvars[ncvarid].ndims == 1 ) + { + size_t len = strlen(ncvars[ncvarid].name); + if ( len == 4 && ncvars[ncvarid].name[0] == 'h' && ncvars[ncvarid].name[1] == 'y' ) + { + if ( ncvars[ncvarid].name[2] == 'a' && ncvars[ncvarid].name[3] == 'i' ) // hyai + { + vcta_id = ncvarid; + nvcth_id = ncvars[ncvarid].dimids[0]; + ncvars[ncvarid].isvar = FALSE; + } + else if ( ncvars[ncvarid].name[2] == 'b' && ncvars[ncvarid].name[3] == 'i' ) //hybi + { + vctb_id = ncvarid; + nvcth_id = ncvars[ncvarid].dimids[0]; + ncvars[ncvarid].isvar = FALSE; + } + else if ( (ncvars[ncvarid].name[2] == 'a' || ncvars[ncvarid].name[2] == 'b') && ncvars[ncvarid].name[3] == 'm' ) + { + ncvars[ncvarid].isvar = FALSE; // hyam or hybm + } + } + } + } + + /* read VCT */ + if ( nvcth_id != UNDEFID && vcta_id != UNDEFID && vctb_id != UNDEFID ) + { + size_t vctsize = ncdims[nvcth_id].len; + vctsize *= 2; + *vct = (double *) Malloc(vctsize*sizeof(double)); + cdf_get_var_double(fileID, vcta_id, *vct); + cdf_get_var_double(fileID, vctb_id, *vct+vctsize/2); + *pvctsize = vctsize; + } +} + +static +void cdf_set_ucla_dimtype(int ndims, ncdim_t *ncdims, ncvar_t *ncvars) +{ + for ( int ncdimid = 0; ncdimid < ndims; ncdimid++ ) + { + int ncvarid = ncdims[ncdimid].ncvarid; + if ( ncvarid != -1 ) + { + if ( ncdims[ncdimid].dimtype == UNDEFID && ncvars[ncvarid].units[0] == 'm' ) + { + if ( ncvars[ncvarid].name[0] == 'x' ) ncdims[ncdimid].dimtype = X_AXIS; + else if ( ncvars[ncvarid].name[0] == 'y' ) ncdims[ncdimid].dimtype = Y_AXIS; + else if ( ncvars[ncvarid].name[0] == 'z' ) ncdims[ncdimid].dimtype = Z_AXIS; + } + } + } +} + +static +int cdf_check_vars(int nvars, ncvar_t *ncvars, int ntsteps, int timedimid) +{ + for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + if ( timedimid != UNDEFID ) + if ( ncvars[ncvarid].isvar == -1 && + ncvars[ncvarid].ndims > 1 && + timedimid == ncvars[ncvarid].dimids[0] ) + cdf_set_var(ncvars, ncvarid, TRUE); + + if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims == 0 ) + cdf_set_var(ncvars, ncvarid, FALSE); + + //if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims > 1 ) + if ( ncvars[ncvarid].isvar == -1 && ncvars[ncvarid].ndims >= 1 ) + cdf_set_var(ncvars, ncvarid, TRUE); + + if ( ncvars[ncvarid].isvar == -1 ) + { + ncvars[ncvarid].isvar = 0; + Warning("Variable %s has an unknown type, skipped!", ncvars[ncvarid].name); + continue; + } + + if ( ncvars[ncvarid].ndims > 4 ) + { + ncvars[ncvarid].isvar = 0; + Warning("%d dimensional variables are not supported, skipped variable %s!", + ncvars[ncvarid].ndims, ncvars[ncvarid].name); + continue; + } + + if ( ncvars[ncvarid].ndims == 4 && timedimid == UNDEFID ) + { + ncvars[ncvarid].isvar = 0; + Warning("%d dimensional variables without time dimension are not supported, skipped variable %s!", + ncvars[ncvarid].ndims, ncvars[ncvarid].name); + continue; + } + + if ( xtypeIsText(ncvars[ncvarid].xtype) ) + { + ncvars[ncvarid].isvar = 0; + continue; + } + + if ( cdfInqDatatype(ncvars[ncvarid].xtype, ncvars[ncvarid].lunsigned) == -1 ) + { + ncvars[ncvarid].isvar = 0; + Warning("Variable %s has an unsupported data type, skipped!", ncvars[ncvarid].name); + continue; + } + + if ( timedimid != UNDEFID && ntsteps == 0 && ncvars[ncvarid].ndims > 0 ) + { + if ( timedimid == ncvars[ncvarid].dimids[0] ) + { + ncvars[ncvarid].isvar = 0; + Warning("Number of time steps undefined, skipped variable %s!", ncvars[ncvarid].name); + continue; + } + } + } + + return timedimid; +} + + +int cdfInqContents(stream_t *streamptr) +{ + int ndims, nvars, ngatts, unlimdimid; + int ncvarid; + int ncdimid; + int timedimid = -1; + int *varids; + int nvarids; + bool time_has_units = false; + bool time_has_bounds = false; + bool time_climatology = false; + int leadtime_id = UNDEFID; + int nvars_data; + int instID = UNDEFID; + int modelID = UNDEFID; + int taxisID; + int calendar = UNDEFID; + int format = 0; + bool ucla_les = false; + char gridfile[8912]; + char fcreftime[CDI_MAX_NAME]; + int number_of_grid_used = UNDEFID; + + unsigned char uuidOfHGrid[CDI_UUID_SIZE]; + unsigned char uuidOfVGrid[CDI_UUID_SIZE]; + memset(uuidOfHGrid, 0, CDI_UUID_SIZE); + memset(uuidOfVGrid, 0, CDI_UUID_SIZE); + gridfile[0] = 0; + fcreftime[0] = 0; + + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + + if ( CDI_Debug ) Message("streamID = %d, fileID = %d", streamptr->self, fileID); + +#if defined (HAVE_NETCDF4) + nc_inq_format(fileID, &format); +#endif + + cdf_inq(fileID, &ndims , &nvars, &ngatts, &unlimdimid); + + if ( CDI_Debug ) + Message("root: ndims %d, nvars %d, ngatts %d", ndims, nvars, ngatts); + + if ( ndims == 0 ) + { + Warning("No dimensions found!"); + return CDI_EUFSTRUCT; + } + + /* alloc ncdims */ + ncdim_t *ncdims = (ncdim_t *) Malloc((size_t)ndims * sizeof (ncdim_t)); + init_ncdims(ndims, ncdims); + +#if defined (TEST_GROUPS) +#if defined (HAVE_NETCDF4) + if ( format == NC_FORMAT_NETCDF4 ) + { + int ncid; + int numgrps; + int ncids[NC_MAX_VARS]; + char name1[CDI_MAX_NAME]; + int gndims, gnvars, gngatts, gunlimdimid; + nc_inq_grps(fileID, &numgrps, ncids); + for ( int i = 0; i < numgrps; ++i ) + { + ncid = ncids[i]; + nc_inq_grpname(ncid, name1); + cdf_inq(ncid, &gndims , &gnvars, &gngatts, &gunlimdimid); + + if ( CDI_Debug ) + Message("%s: ndims %d, nvars %d, ngatts %d", name1, gndims, gnvars, gngatts); + + if ( gndims == 0 ) + { + } + } + } +#endif +#endif + + if ( nvars == 0 ) + { + Warning("No arrays found!"); + return CDI_EUFSTRUCT; + } + + /* alloc ncvars */ + ncvar_t *ncvars = (ncvar_t *) Malloc((size_t)nvars * sizeof (ncvar_t)); + init_ncvars(nvars, ncvars); + + for ( ncvarid = 0; ncvarid < nvars; ++ncvarid ) ncvars[ncvarid].ncid = fileID; + + + /* scan global attributes */ + cdf_scan_global_attr(fileID, vlistID, streamptr, ngatts, &instID, &modelID, &ucla_les, + uuidOfHGrid, uuidOfVGrid, gridfile, &number_of_grid_used); + + /* find time dim */ + if ( unlimdimid >= 0 ) + timedimid = unlimdimid; + else + timedimid = cdf_time_dimid(fileID, ndims, nvars); + + streamptr->basetime.ncdimid = timedimid; + + size_t ntsteps = 0; + if ( timedimid != UNDEFID ) cdf_inq_dimlen(fileID, timedimid, &ntsteps); + + if ( CDI_Debug ) Message("Number of timesteps = %d", ntsteps); + if ( CDI_Debug ) Message("Time dimid = %d", streamptr->basetime.ncdimid); + + /* read ncdims */ + for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) + { + cdf_inq_dimlen(fileID, ncdimid, &ncdims[ncdimid].len); + cdf_inq_dimname(fileID, ncdimid, ncdims[ncdimid].name); + if ( timedimid == ncdimid ) + ncdims[ncdimid].dimtype = T_AXIS; + } + + if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "cdf_scan_var_attr"); + + /* scan attributes of all variables */ + cdf_scan_var_attr(nvars, ncvars, ncdims, timedimid, modelID, format); + + + if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "find coordinate vars"); + + /* find coordinate vars */ + for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) + { + for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + if ( ncvars[ncvarid].ndims == 1 ) + { + if ( timedimid != UNDEFID && timedimid == ncvars[ncvarid].dimids[0] ) + { + if ( ncvars[ncvarid].isvar != FALSE ) cdf_set_var(ncvars, ncvarid, TRUE); + } + else + { + // if ( ncvars[ncvarid].isvar != TRUE ) cdf_set_var(ncvars, ncvarid, FALSE); + } + // if ( ncvars[ncvarid].isvar != TRUE ) cdf_set_var(ncvars, ncvarid, FALSE); + + if ( ncdimid == ncvars[ncvarid].dimids[0] && ncdims[ncdimid].ncvarid == UNDEFID ) + if ( strcmp(ncvars[ncvarid].name, ncdims[ncdimid].name) == 0 ) + { + ncdims[ncdimid].ncvarid = ncvarid; + ncvars[ncvarid].isvar = FALSE; + } + } + } + } + + /* find time vars */ + find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &time_has_units, &time_has_bounds, &time_climatology); + + leadtime_id = find_leadtime(nvars, ncvars); + if ( leadtime_id != UNDEFID ) ncvars[leadtime_id].isvar = FALSE; + + /* check ncvars */ + timedimid = cdf_check_vars(nvars, ncvars, ntsteps, timedimid); + + /* verify coordinate vars - first scan (dimname == varname) */ + verify_coordinate_vars_1(fileID, ndims, ncdims, ncvars, timedimid); + + /* verify coordinate vars - second scan (all other variables) */ + verify_coordinate_vars_2(nvars, ncvars); + + if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "verify_coordinate_vars"); + + if ( ucla_les ) cdf_set_ucla_dimtype(ndims, ncdims, ncvars); + + /* + for ( ncdimid = 0; ncdimid < ndims; ncdimid++ ) + { + ncvarid = ncdims[ncdimid].ncvarid; + if ( ncvarid != -1 ) + { + printf("coord var %d %s %s\n", ncvarid, ncvars[ncvarid].name, ncvars[ncvarid].units); + if ( ncdims[ncdimid].dimtype == X_AXIS ) + printf("coord var %d %s is x dim\n", ncvarid, ncvars[ncvarid].name); + if ( ncdims[ncdimid].dimtype == Y_AXIS ) + printf("coord var %d %s is y dim\n", ncvarid, ncvars[ncvarid].name); + if ( ncdims[ncdimid].dimtype == Z_AXIS ) + printf("coord var %d %s is z dim\n", ncvarid, ncvars[ncvarid].name); + if ( ncdims[ncdimid].dimtype == T_AXIS ) + printf("coord var %d %s is t dim\n", ncvarid, ncvars[ncvarid].name); + + if ( ncvars[ncvarid].islon ) + printf("coord var %d %s is lon\n", ncvarid, ncvars[ncvarid].name); + if ( ncvars[ncvarid].islat ) + printf("coord var %d %s is lat\n", ncvarid, ncvars[ncvarid].name); + if ( ncvars[ncvarid].islev ) + printf("coord var %d %s is lev\n", ncvarid, ncvars[ncvarid].name); + } + } + */ + + /* Set coordinate varids (att: associate) */ + for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) + { + ncvar_t *ncvar = &ncvars[ncvarid]; + if ( ncvar->isvar == TRUE && ncvar->ncoordvars ) + { + int ndims = ncvar->ncoordvars; + for ( int i = 0; i < ndims; i++ ) + { + if ( ncvars[ncvar->coordvarids[i]].islon || + ncvars[ncvar->coordvarids[i]].isx ) ncvar->xvarid = ncvar->coordvarids[i]; + else if ( ncvars[ncvar->coordvarids[i]].islat || + ncvars[ncvar->coordvarids[i]].isy ) ncvar->yvarid = ncvar->coordvarids[i]; + else if ( ncvars[ncvar->coordvarids[i]].islev ) ncvar->zvarid = ncvar->coordvarids[i]; + } + } + } + + /* set dim type */ + cdf_set_dimtype(nvars, ncvars, ncdims); + + /* read ECHAM VCT if present */ + size_t vctsize = 0; + double *vct = NULL; + read_vct_echam(fileID, nvars, ncvars, ncdims, &vct, &vctsize); + + + if ( CDI_Debug ) cdf_print_vars(ncvars, nvars, "cdf_define_all_grids"); + + /* define all grids */ + cdf_define_all_grids(streamptr, vlistID, ncdims, nvars, ncvars, timedimid, uuidOfHGrid, gridfile, number_of_grid_used); + + + /* define all zaxes */ + cdf_define_all_zaxes(streamptr, vlistID, ncdims, nvars, ncvars, vctsize, vct, uuidOfVGrid); + if ( vct ) Free(vct); + + + /* select vars */ + varids = (int *) Malloc((size_t)nvars * sizeof (int)); + nvarids = 0; + for ( ncvarid = 0; ncvarid < nvars; ncvarid++ ) + if ( ncvars[ncvarid].isvar == TRUE ) varids[nvarids++] = ncvarid; + + nvars_data = nvarids; + + if ( CDI_Debug ) Message("time varid = %d", streamptr->basetime.ncvarid); + if ( CDI_Debug ) Message("ntsteps = %d", ntsteps); + if ( CDI_Debug ) Message("nvars_data = %d", nvars_data); + + + if ( nvars_data == 0 ) + { + streamptr->ntsteps = 0; + return CDI_EUFSTRUCT; + } + + if ( ntsteps == 0 && streamptr->basetime.ncdimid == UNDEFID && streamptr->basetime.ncvarid != UNDEFID ) + ntsteps = 1; + + streamptr->ntsteps = (long)ntsteps; + + /* define all data variables */ + cdf_define_all_vars(streamptr, vlistID, instID, modelID, varids, nvars_data, nvars, ncvars); + + + cdiCreateTimesteps(streamptr); + + /* time varID */ + int nctimevarid = streamptr->basetime.ncvarid; + + if ( time_has_units ) + { + taxis_t *taxis = &streamptr->tsteps[0].taxis; + + if ( setBaseTime(ncvars[nctimevarid].units, taxis) == 1 ) + { + nctimevarid = UNDEFID; + streamptr->basetime.ncvarid = UNDEFID; + } + + if ( leadtime_id != UNDEFID && taxis->type == TAXIS_RELATIVE ) + { + streamptr->basetime.leadtimeid = leadtime_id; + taxis->type = TAXIS_FORECAST; + + int timeunit = -1; + if ( ncvars[leadtime_id].units[0] != 0 ) timeunit = scanTimeUnit(ncvars[leadtime_id].units); + if ( timeunit == -1 ) timeunit = taxis->unit; + taxis->fc_unit = timeunit; + + setForecastTime(fcreftime, taxis); + } + } + + if ( time_has_bounds ) + { + streamptr->tsteps[0].taxis.has_bounds = true; + if ( time_climatology ) streamptr->tsteps[0].taxis.climatology = true; + } + + if ( nctimevarid != UNDEFID ) + { + taxis_t *taxis = &streamptr->tsteps[0].taxis; + ptaxisDefName(taxis, ncvars[nctimevarid].name); + if ( ncvars[nctimevarid].longname[0] ) + ptaxisDefLongname(taxis, ncvars[nctimevarid].longname); + } + + if ( nctimevarid != UNDEFID ) + if ( ncvars[nctimevarid].calendar == TRUE ) + { + enum {attstringlen = 8192}; + char attstring[attstringlen]; + + cdfGetAttText(fileID, nctimevarid, "calendar", attstringlen, attstring); + str_tolower(attstring); + set_calendar(attstring, &calendar); + } + + if ( streamptr->tsteps[0].taxis.type == TAXIS_FORECAST ) + { + taxisID = taxisCreate(TAXIS_FORECAST); + } + else if ( streamptr->tsteps[0].taxis.type == TAXIS_RELATIVE ) + { + taxisID = taxisCreate(TAXIS_RELATIVE); + } + else + { + taxisID = taxisCreate(TAXIS_ABSOLUTE); + if ( !time_has_units ) + { + taxisDefTunit(taxisID, TUNIT_DAY); + streamptr->tsteps[0].taxis.unit = TUNIT_DAY; + } + } + + + if ( calendar == UNDEFID && streamptr->tsteps[0].taxis.type != TAXIS_ABSOLUTE ) + { + calendar = CALENDAR_STANDARD; + } + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wstrict-overflow" +#endif + if ( calendar != UNDEFID ) + { + taxis_t *taxis = &streamptr->tsteps[0].taxis; + taxis->calendar = calendar; + taxisDefCalendar(taxisID, calendar); + } +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) +#pragma GCC diagnostic pop +#endif + + vlistDefTaxis(vlistID, taxisID); + + streamptr->curTsID = 0; + streamptr->rtsteps = 1; + + (void) cdfInqTimestep(streamptr, 0); + + cdfCreateRecords(streamptr, 0); + + /* free ncdims */ + Free(ncdims); + + /* free ncvars */ + Free(ncvars); + + return 0; +} + +static +void wrf_read_timestep(int fileID, int nctimevarid, int tsID, taxis_t *taxis) +{ + size_t start[2], count[2]; + char stvalue[32]; + start[0] = (size_t) tsID; start[1] = 0; + count[0] = 1; count[1] = 19; + stvalue[0] = 0; + cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue); + stvalue[19] = 0; + { + int year = 1, month = 1, day = 1 , hour = 0, minute = 0, second = 0; + if ( strlen(stvalue) == 19 ) + sscanf(stvalue, "%d-%d-%d_%d:%d:%d", &year, &month, &day, &hour, &minute, &second); + taxis->vdate = cdiEncodeDate(year, month, day); + taxis->vtime = cdiEncodeTime(hour, minute, second); + taxis->type = TAXIS_ABSOLUTE; + } +} + +static +double get_timevalue(int fileID, int nctimevarid, int tsID, timecache_t *tcache) +{ + double timevalue = 0; + + if ( tcache ) + { + if ( tcache->size == 0 || (tsID < tcache->startid || tsID > (tcache->startid+tcache->size-1)) ) + { + int maxvals = MAX_TIMECACHE_SIZE; + tcache->startid = (tsID/MAX_TIMECACHE_SIZE)*MAX_TIMECACHE_SIZE; + if ( (tcache->startid + maxvals) > tcache->maxvals ) maxvals = (tcache->maxvals)%MAX_TIMECACHE_SIZE; + tcache->size = maxvals; + size_t index = (size_t) tcache->startid; + // fprintf(stderr, "fill time cache: %d %d %d %d %d\n", tcache->maxvals, tsID, tcache->startid, tcache->startid+maxvals-1, maxvals); + for ( int ival = 0; ival < maxvals; ++ival ) + { + cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue); + if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; + tcache->cache[ival] = timevalue; + index++; + } + } + + timevalue = tcache->cache[tsID%MAX_TIMECACHE_SIZE]; + } + else + { + size_t index = (size_t) tsID; + cdf_get_var1_double(fileID, nctimevarid, &index, &timevalue); + if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; + } + + return timevalue; +} + + +int cdfInqTimestep(stream_t * streamptr, int tsID) +{ + if ( CDI_Debug ) Message("streamID = %d tsID = %d", streamptr->self, tsID); + + if ( tsID < 0 ) Error("unexpected tsID = %d", tsID); + + if ( tsID < streamptr->ntsteps && streamptr->ntsteps > 0 ) + { + cdfCreateRecords(streamptr, tsID); + + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; + if ( tsID > 0 ) + ptaxisCopy(taxis, &streamptr->tsteps[0].taxis); + + double timevalue = tsID; + + int nctimevarid = streamptr->basetime.ncvarid; + if ( nctimevarid != UNDEFID ) + { + int fileID = streamptr->fileID; + size_t index = (size_t)tsID; + + if ( streamptr->basetime.lwrf ) + { + wrf_read_timestep(fileID, nctimevarid, tsID, taxis); + } + else + { +#if defined (USE_TIMECACHE) + if ( streamptr->basetime.timevar_cache == NULL ) + { + streamptr->basetime.timevar_cache = (timecache_t *) Malloc(MAX_TIMECACHE_SIZE*sizeof(timecache_t)); + streamptr->basetime.timevar_cache->size = 0; + streamptr->basetime.timevar_cache->maxvals = streamptr->ntsteps; + } +#endif + timevalue = get_timevalue(fileID, nctimevarid, tsID, streamptr->basetime.timevar_cache); + cdiDecodeTimeval(timevalue, taxis, &taxis->vdate, &taxis->vtime); + } + + int nctimeboundsid = streamptr->basetime.ncvarboundsid; + if ( nctimeboundsid != UNDEFID ) + { + size_t start[2], count[2]; + start[0] = index; count[0] = 1; start[1] = 0; count[1] = 1; + cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue); + if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; + + cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_lb, &taxis->vtime_lb); + + start[0] = index; count[0] = 1; start[1] = 1; count[1] = 1; + cdf_get_vara_double(fileID, nctimeboundsid, start, count, &timevalue); + if ( timevalue >= NC_FILL_DOUBLE || timevalue < -NC_FILL_DOUBLE ) timevalue = 0; + + cdiDecodeTimeval(timevalue, taxis, &taxis->vdate_ub, &taxis->vtime_ub); + } + + int leadtimeid = streamptr->basetime.leadtimeid; + if ( leadtimeid != UNDEFID ) + { + timevalue = get_timevalue(fileID, leadtimeid, tsID, NULL); + cdiSetForecastPeriod(timevalue, taxis); + } + } + } + + streamptr->curTsID = tsID; + long nrecs = streamptr->tsteps[tsID].nrecs; + + return (int) nrecs; +} + + +int cdfInqHistorySize(stream_t *streamptr) +{ + size_t size = 0; + int ncid = streamptr->fileID; + if ( streamptr->historyID != UNDEFID ) + cdf_inq_attlen(ncid, NC_GLOBAL, "history", &size); + + return (int) size; +} + + +void cdfInqHistoryString(stream_t *streamptr, char *history) +{ + int ncid = streamptr->fileID; + if ( streamptr->historyID != UNDEFID ) + { + nc_type atttype; + cdf_inq_atttype(ncid, NC_GLOBAL, "history", &atttype); + + if ( atttype == NC_CHAR ) + { + cdf_get_att_text(ncid, NC_GLOBAL, "history", history); + } +#if defined (HAVE_NETCDF4) + else if ( atttype == NC_STRING ) + { + // ToDo + Warning("History attribute with type NC_STRING unsupported!"); + } +#endif + } +} + +#endif +/* + * Local Variables: + * c-file-style: "Java" + * c-basic-offset: 2 + * indent-tabs-mode: nil + * show-trailing-whitespace: t + * require-trailing-newline: t + * End: + */ diff --git a/src/stream_cdf_o.c b/src/stream_cdf_o.c new file mode 100644 index 0000000000000000000000000000000000000000..70ba1e1e24e88a3ca69e9c829034d1c940b575fc --- /dev/null +++ b/src/stream_cdf_o.c @@ -0,0 +1,2201 @@ +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#ifdef HAVE_LIBNETCDF + +#include "dmemory.h" +#include "cdi_int.h" +#include "cdi_uuid.h" +#include "stream_cdf.h" +#include "cdf_int.h" +#include "varscan.h" +#include "vlist.h" +#include "zaxis.h" + + +#undef UNDEFID +#define UNDEFID CDI_UNDEFID + +#define POSITIVE_UP 1 +#define POSITIVE_DOWN 2 + + +static const char bndsName[] = "bnds"; + + +void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1) +{ + int vlistID1 = streamptr1->vlistID; + int tsID = streamptr1->curTsID; + int vrecID = streamptr1->tsteps[tsID].curRecID; + int recID = streamptr1->tsteps[tsID].recIDs[vrecID]; + int ivarID = streamptr1->tsteps[tsID].records[recID].varID; + int gridID = vlistInqVarGrid(vlistID1, ivarID); + int datasize = gridInqSize(gridID); + int datatype = vlistInqVarDatatype(vlistID1, ivarID); + int memtype = datatype != DATATYPE_FLT32 ? MEMTYPE_DOUBLE : MEMTYPE_FLOAT; + + void *data = Malloc((size_t)datasize + * (memtype == MEMTYPE_DOUBLE ? sizeof(double) : sizeof(float))); + + int nmiss; + cdf_read_record(streamptr1, memtype, data, &nmiss); + cdf_write_record(streamptr2, memtype, data, nmiss); + + Free(data); +} + +/* not used +int cdfInqRecord(stream_t *streamptr, int *varID, int *levelID) +{ + int tsID, recID; + + recID = streamptr->tsteps[0].curRecID++; + printf("cdfInqRecord recID %d %d\n", recID, streamptr->tsteps[0].curRecID); + printf("cdfInqRecord tsID %d\n", streamptr->curTsID); + + if ( streamptr->tsteps[0].curRecID >= streamptr->tsteps[0].nrecs ) + { + streamptr->tsteps[0].curRecID = 0; + } + + *varID = streamptr->tsteps[0].records[recID].varID; + *levelID = streamptr->tsteps[0].records[recID].levelID; + + streamptr->record->varID = *varID; + streamptr->record->levelID = *levelID; + + if ( CDI_Debug ) + Message("recID = %d varID = %d levelID = %d", recID, *varID, *levelID); + + return (recID+1); +} +*/ + + +void cdfDefRecord(stream_t *streamptr) +{ + (void)streamptr; +} + +static +void cdfDefTimeValue(stream_t *streamptr, int tsID) +{ + int fileID = streamptr->fileID; + + if ( CDI_Debug ) + Message("streamID = %d, fileID = %d", streamptr->self, fileID); + + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; + + if ( streamptr->ncmode == 1 ) + { + cdf_enddef(fileID); + streamptr->ncmode = 2; + } + + size_t index = (size_t)tsID; + + double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis); + if ( CDI_Debug ) Message("tsID = %d timevalue = %f", tsID, timevalue); + + int ncvarid = streamptr->basetime.ncvarid; + cdf_put_var1_double(fileID, ncvarid, &index, &timevalue); + + if ( taxis->has_bounds ) + { + size_t start[2], count[2]; + + ncvarid = streamptr->basetime.ncvarboundsid; + + timevalue = cdiEncodeTimeval(taxis->vdate_lb, taxis->vtime_lb, &streamptr->tsteps[0].taxis); + start[0] = (size_t)tsID; count[0] = 1; start[1] = 0; count[1] = 1; + cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue); + + timevalue = cdiEncodeTimeval(taxis->vdate_ub, taxis->vtime_ub, &streamptr->tsteps[0].taxis); + start[0] = (size_t)tsID; count[0] = 1; start[1] = 1; count[1] = 1; + cdf_put_vara_double(fileID, ncvarid, start, count, &timevalue); + } + + ncvarid = streamptr->basetime.leadtimeid; + if ( taxis->type == TAXIS_FORECAST && ncvarid != UNDEFID ) + { + timevalue = taxis->fc_period; + cdf_put_var1_double(fileID, ncvarid, &index, &timevalue); + } + + /* +printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue); + */ +} + +static +int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *taxis_name, taxis_t* taxis) +{ + int time_bndsid = -1; + int dims[2]; + + dims[0] = nctimedimid; + + /* fprintf(stderr, "time has bounds\n"); */ + + if ( nc_inq_dimid(fileID, bndsName, &dims[1]) != NC_NOERR ) + cdf_def_dim(fileID, bndsName, 2, &dims[1]); + + const char *bndsAttName, *bndsAttVal; + size_t bndsAttValLen; + char tmpstr[CDI_MAX_NAME]; + if ( taxis->climatology ) + { + static const char climatology_bndsName[] = "climatology_bnds", + climatology_bndsAttName[] = "climatology"; + bndsAttName = climatology_bndsAttName; + bndsAttValLen = sizeof (climatology_bndsName) - 1; + bndsAttVal = climatology_bndsName; + } + else + { + size_t taxisnameLen = strlen(taxis_name); + memcpy(tmpstr, taxis_name, taxisnameLen); + tmpstr[taxisnameLen] = '_'; + memcpy(tmpstr + taxisnameLen + 1, bndsName, sizeof (bndsName)); + size_t tmpstrLen = taxisnameLen + sizeof (bndsName); + static const char generic_bndsAttName[] = "bounds"; + bndsAttName = generic_bndsAttName; + bndsAttValLen = tmpstrLen; + bndsAttVal = tmpstr; + } + cdf_def_var(fileID, bndsAttVal, NC_DOUBLE, 2, dims, &time_bndsid); + cdf_put_att_text(fileID, nctimevarid, bndsAttName, bndsAttValLen, bndsAttVal); + + return time_bndsid; +} + +static +void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis) +{ + unitstr[0] = 0; + + if ( taxis0->type == TAXIS_ABSOLUTE ) + { + if ( taxis0->unit == TUNIT_YEAR ) + sprintf(unitstr, "year as %s", "%Y.%f"); + else if ( taxis0->unit == TUNIT_MONTH ) + sprintf(unitstr, "month as %s", "%Y%m.%f"); + else + sprintf(unitstr, "day as %s", "%Y%m%d.%f"); + } + else + { + int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR; + int rdate = taxis->rdate; + int rtime = taxis->rtime; + if ( rdate == -1 ) + { + rdate = taxis->vdate; + rtime = taxis->vtime; + } + + int year, month, day, hour, minute, second; + cdiDecodeDate(rdate, &year, &month, &day); + cdiDecodeTime(rtime, &hour, &minute, &second); + + if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE; + if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE; + if ( timeunit == TUNIT_3HOURS || + timeunit == TUNIT_6HOURS || + timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR; + + sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d", + tunitNamePtr(timeunit), year, month, day, hour, minute, second); + } +} + +static +void cdfDefForecastTimeUnits(char *unitstr, int timeunit) +{ + unitstr[0] = 0; + + if ( timeunit == -1 ) timeunit = TUNIT_HOUR; + + if ( timeunit == TUNIT_QUARTER ) timeunit = TUNIT_MINUTE; + if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE; + if ( timeunit == TUNIT_3HOURS || + timeunit == TUNIT_6HOURS || + timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR; + + strcpy(unitstr, tunitNamePtr(timeunit)); +} + +static +void cdfDefCalendar(int fileID, int ncvarid, int calendar) +{ + static const struct { int calCode; const char *calStr; } calTab[] = { + { CALENDAR_STANDARD, "standard" }, + { CALENDAR_PROLEPTIC, "proleptic_gregorian" }, + { CALENDAR_NONE, "none" }, + { CALENDAR_360DAYS, "360_day" }, + { CALENDAR_365DAYS, "365_day" }, + { CALENDAR_366DAYS, "366_day" }, + }; + enum { calTabSize = sizeof calTab / sizeof calTab[0] }; + + for (size_t i = 0; i < calTabSize; ++i) + if (calTab[i].calCode == calendar) + { + const char *calstr = calTab[i].calStr; + size_t len = strlen(calstr); + cdf_put_att_text(fileID, ncvarid, "calendar", len, calstr); + break; + } +} + + +void cdfDefTime(stream_t* streamptr) +{ + int time_varid; + int time_dimid; + int time_bndsid = -1; + static const char default_name[] = "time"; + + if ( streamptr->basetime.ncvarid != UNDEFID ) return; + + int fileID = streamptr->fileID; + + if ( streamptr->ncmode == 0 ) streamptr->ncmode = 1; + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + taxis_t *taxis = &streamptr->tsteps[0].taxis; + + const char *taxis_name = (taxis->name && taxis->name[0]) ? taxis->name : default_name ; + + cdf_def_dim(fileID, taxis_name, NC_UNLIMITED, &time_dimid); + streamptr->basetime.ncdimid = time_dimid; + + cdf_def_var(fileID, taxis_name, NC_DOUBLE, 1, &time_dimid, &time_varid); + + streamptr->basetime.ncvarid = time_varid; + + { + static const char timeStr[] = "time"; + cdf_put_att_text(fileID, time_varid, "standard_name", sizeof(timeStr) - 1, timeStr); + } + + if ( taxis->longname && taxis->longname[0] ) + cdf_put_att_text(fileID, time_varid, "long_name", strlen(taxis->longname), taxis->longname); + + if ( taxis->has_bounds ) + { + time_bndsid = cdfDefTimeBounds(fileID, time_varid, time_dimid, taxis_name, taxis); + streamptr->basetime.ncvarboundsid = time_bndsid; + } + + { + char unitstr[CDI_MAX_NAME]; + cdfDefTimeUnits(unitstr, &streamptr->tsteps[0].taxis, taxis); + size_t len = strlen(unitstr); + if ( len ) + { + cdf_put_att_text(fileID, time_varid, "units", len, unitstr); + /* + if ( taxis->has_bounds ) + cdf_put_att_text(fileID, time_bndsid, "units", len, unitstr); + */ + } + } + + if ( taxis->calendar != -1 ) + { + cdfDefCalendar(fileID, time_varid, taxis->calendar); + /* + if ( taxis->has_bounds ) + cdfDefCalendar(fileID, time_bndsid, taxis->calendar); + */ + } + + if ( taxis->type == TAXIS_FORECAST ) + { + int leadtimeid; + + cdf_def_var(fileID, "leadtime", NC_DOUBLE, 1, &time_dimid, &leadtimeid); + + streamptr->basetime.leadtimeid = leadtimeid; + + { + static const char stdname[] = "forecast_period"; + cdf_put_att_text(fileID, leadtimeid, "standard_name", sizeof(stdname) - 1, stdname); + } + + { + static const char lname[] = "Time elapsed since the start of the forecast"; + cdf_put_att_text(fileID, leadtimeid, "long_name", sizeof(lname) - 1, lname); + } + + { + char unitstr[CDI_MAX_NAME]; + cdfDefForecastTimeUnits(unitstr, taxis->fc_unit); + size_t len = strlen(unitstr); + if ( len ) + cdf_put_att_text(fileID, leadtimeid, "units", len, unitstr); + } + } + + cdf_put_att_text(fileID, time_varid, "axis", 1, "T"); + + if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); +} + + +void cdfDefTimestep(stream_t *streamptr, int tsID) +{ + int vlistID = streamptr->vlistID; + + if ( vlistHasTime(vlistID) ) cdfDefTime(streamptr); + + cdfDefTimeValue(streamptr, tsID); +} + +static +void cdfDefComplex(stream_t *streamptr, int gridID, int gridindex) +{ + int dimID = UNDEFID; + int fileID = streamptr->fileID; + ncgrid_t *ncgrid = streamptr->ncgrid; + + for ( int index = 0; index < gridindex; ++index ) + { + if ( ncgrid[index].xdimID != UNDEFID ) + { + int gridID0 = ncgrid[index].gridID; + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == GRID_SPECTRAL || gridtype0 == GRID_FOURIER ) + { + dimID = ncgrid[index].xdimID; + break; + } + } + } + + if ( dimID == UNDEFID ) + { + static const char axisname[] = "nc2"; + size_t dimlen = 2; + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + cdf_def_dim(fileID, axisname, dimlen, &dimID); + cdf_enddef(fileID); + + streamptr->ncmode = 2; + } + + ncgrid[gridindex].gridID = gridID; + ncgrid[gridindex].xdimID = dimID; +} + +static void +cdfDefSPorFC(stream_t *streamptr, int gridID, int gridindex, + char *restrict axisname, int gridRefType) +{ + int index, iz = 0; + int dimID = UNDEFID; + ncgrid_t *ncgrid = streamptr->ncgrid; + + size_t dimlen = (size_t)gridInqSize(gridID)/2; + + for ( index = 0; index < gridindex; index++ ) + { + if ( ncgrid[index].ydimID != UNDEFID ) + { + int gridID0 = ncgrid[index].gridID; + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == gridRefType ) + { + size_t dimlen0 = (size_t)gridInqSize(gridID0)/2; + if ( dimlen == dimlen0 ) + { + dimID = ncgrid[index].ydimID; + break; + } + else + iz++; + } + } + } + + if ( dimID == UNDEFID ) + { + int fileID = streamptr->fileID; + if ( iz == 0 ) axisname[3] = '\0'; + else sprintf(&axisname[3], "%1d", iz+1); + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + cdf_def_dim(fileID, axisname, dimlen, &dimID); + + cdf_enddef(fileID); + streamptr->ncmode = 2; + } + + ncgrid[gridindex].gridID = gridID; + ncgrid[gridindex].ydimID = dimID; +} + +static +void cdfDefSP(stream_t *streamptr, int gridID, int gridindex) +{ + /* + char longname[] = "Spherical harmonic coefficient"; + */ + char axisname[5] = "nspX"; + cdfDefSPorFC(streamptr, gridID, gridindex, axisname, GRID_SPECTRAL); +} + + +static +void cdfDefFC(stream_t *streamptr, int gridID, int gridindex) +{ + char axisname[5] = "nfcX"; + cdfDefSPorFC(streamptr, gridID, gridindex, axisname, GRID_FOURIER); +} + +static const struct cdfDefGridAxisInqs { + int (*axisSize)(int gridID); + void (*axisName)(int gridID, char *dimname); + void (*axisStdname)(int gridID, char *dimstdname); + void (*axisLongname)(int gridID, char *dimlongname); + void (*axisUnits)(int gridID, char *dimunits); + double (*axisVal)(int gridID, int index); + const double *(*axisValsPtr)(int gridID); + const double *(*axisBoundsPtr)(int gridID); +} gridInqsX = { + .axisSize = gridInqXsize, + .axisName = gridInqXname, + .axisStdname = gridInqXstdname, + .axisLongname = gridInqXlongname, + .axisUnits = gridInqXunits, + .axisVal = gridInqXval, + .axisValsPtr = gridInqXvalsPtr, + .axisBoundsPtr = gridInqXboundsPtr, +}, gridInqsY = { + .axisSize = gridInqYsize, + .axisName = gridInqYname, + .axisStdname = gridInqYstdname, + .axisLongname = gridInqYlongname, + .axisUnits = gridInqYunits, + .axisVal = gridInqYval, + .axisValsPtr = gridInqYvalsPtr, + .axisBoundsPtr = gridInqYboundsPtr, +}, gridInqsZ = { + .axisStdname = zaxisInqStdname, + .axisLongname = zaxisInqLongname, + .axisUnits = zaxisInqUnits, +}; + +static void +cdfPutGridStdAtts(int fileID, int ncvarid, + int gridID, const struct cdfDefGridAxisInqs *inqs) +{ + size_t len; + { + char stdname[CDI_MAX_NAME]; + inqs->axisStdname(gridID, stdname); + if ( (len = strlen(stdname)) ) + cdf_put_att_text(fileID, ncvarid, "standard_name", len, stdname); + } + { + char longname[CDI_MAX_NAME]; + inqs->axisLongname(gridID, longname); + if ( (len = strlen(longname)) ) + cdf_put_att_text(fileID, ncvarid, "long_name", len, longname); + } + { + char units[CDI_MAX_NAME]; + inqs->axisUnits(gridID, units); + if ( (len = strlen(units)) ) + cdf_put_att_text(fileID, ncvarid, "units", len, units); + } +} + +static void +cdfDefTrajLatLon(stream_t *streamptr, int gridID, int gridindex, + const struct cdfDefGridAxisInqs *inqs, int dimtype) +{ + nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE; + ncgrid_t *ncgrid = streamptr->ncgrid; + + int dimlen = inqs->axisSize(gridID); + if ( dimlen != 1 ) + Error("%c size isn't 1 for %s grid!", dimtype, gridNamePtr(gridInqType(gridID))); + + int ncvarid = UNDEFID; + if ( dimtype == 'X' ) + ncvarid = ncgrid[gridindex].xdimID; + else + ncvarid = ncgrid[gridindex].ydimID; + + if ( ncvarid == UNDEFID ) + { + int dimNcID = streamptr->basetime.ncvarid; + int fileID = streamptr->fileID; + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + char axisname[CDI_MAX_NAME]; + inqs->axisName(gridID, axisname); + cdf_def_var(fileID, axisname, xtype, 1, &dimNcID, &ncvarid); + cdfPutGridStdAtts(fileID, ncvarid, gridID, inqs); + cdf_enddef(fileID); + streamptr->ncmode = 2; + } + + ncgrid[gridindex].gridID = gridID; + if ( dimtype == 'X' ) + ncgrid[gridindex].xdimID = ncvarid; /* var ID for trajectory !!! */ + else + ncgrid[gridindex].ydimID = ncvarid; /* var ID for trajectory !!! */ +} + +static +void cdfDefTrajLon(stream_t *streamptr, int gridID, int gridindex) +{ + cdfDefTrajLatLon(streamptr, gridID, gridindex, &gridInqsX, 'X'); +} + + +static +void cdfDefTrajLat(stream_t *streamptr, int gridID, int gridindex) +{ + cdfDefTrajLatLon(streamptr, gridID, gridindex, &gridInqsY, 'Y'); +} + +static +int checkDimName(int fileID, size_t dimlen, char *dimname) +{ + /* check whether the dimenion name is already defined with the same length */ + unsigned iz = 0; + int dimid = UNDEFID; + char name[CDI_MAX_NAME]; + + size_t len = strlen(dimname); + memcpy(name, dimname, len + 1); + + do + { + if ( iz ) sprintf(name + len, "_%u", iz+1); + + int dimid0, status = nc_inq_dimid(fileID, name, &dimid0); + if ( status != NC_NOERR ) + break; + size_t dimlen0; + cdf_inq_dimlen(fileID, dimid0, &dimlen0); + if ( dimlen0 == dimlen ) + { + dimid = dimid0; + break; + } + iz++; + } + while ( iz <= 99 ); + + + if ( iz ) sprintf(dimname + len, "_%u", iz+1); + + return dimid; +} + +static +void checkGridName(char *axisname, int fileID) +{ + int ncdimid; + char axisname2[CDI_MAX_NAME]; + + /* check that the name is not already defined */ + unsigned iz = 0; + + size_t axisnameLen = strlen(axisname); + memcpy(axisname2, axisname, axisnameLen + 1); + do + { + if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1); + + int status = nc_inq_varid(fileID, axisname2, &ncdimid); + if ( status != NC_NOERR ) break; + + ++iz; + } + while ( iz <= 99 ); + + if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1); +} + +static +int checkZaxisName(char *axisname, int fileID, int vlistID, int zaxisID, int nzaxis) +{ + char axisname2[CDI_MAX_NAME]; + + /* check that the name is not already defined */ + unsigned iz = 0; + + size_t axisnameLen = strlen(axisname); + memcpy(axisname2, axisname, axisnameLen + 1); + do + { + if ( iz ) sprintf(axisname2 + axisnameLen, "_%u", iz+1); + + int ncdimid, status = nc_inq_varid(fileID, axisname2, &ncdimid); + + if ( status != NC_NOERR ) + { + if ( iz ) + { + /* check that the name does not exist for other zaxes */ + for ( int index = 0; index < nzaxis; index++ ) + { + int zaxisID0 = vlistZaxis(vlistID, index); + if ( zaxisID != zaxisID0 ) + { + const char *axisname0 = zaxisInqNamePtr(zaxisID0); + if ( strcmp(axisname0, axisname2) == 0 ) goto nextSuffix; + } + } + } + break; + } + nextSuffix: + ++iz; + } + while (iz <= 99); + + + if ( iz ) sprintf(axisname + axisnameLen, "_%u", iz+1); + + return (int)iz; +} + +static void +cdfDefAxisCommon(stream_t *streamptr, int gridID, int gridindex, int ndims, + const struct cdfDefGridAxisInqs *gridAxisInq, int dimKey, char axisLetter, + void (*finishCyclicBounds)(double *pbounds, size_t dimlen, const double *pvals)) +{ + int dimID = UNDEFID; + int ncvarid = UNDEFID, ncbvarid = UNDEFID; + int nvdimID = UNDEFID; + int fileID = streamptr->fileID; + size_t dimlen = (size_t)gridAxisInq->axisSize(gridID); + nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE; + ncgrid_t *ncgrid = streamptr->ncgrid; + + for ( int index = 0; index < gridindex; ++index ) + { + int gridID0 = ncgrid[index].gridID; + assert(gridID0 != UNDEFID); + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == GRID_GAUSSIAN || + gridtype0 == GRID_LONLAT || + gridtype0 == GRID_PROJECTION || + gridtype0 == GRID_CURVILINEAR || + gridtype0 == GRID_GENERIC ) + { + size_t dimlen0 = (size_t)gridAxisInq->axisSize(gridID0); + if ( dimlen == dimlen0 ) + { + double (*inqVal)(int gridID, int index) = gridAxisInq->axisVal; + if ( IS_EQUAL(inqVal(gridID0, 0), inqVal(gridID, 0)) && + IS_EQUAL(inqVal(gridID0, (int)dimlen-1), inqVal(gridID, (int)dimlen-1)) ) + { + if ( dimKey == CDI_KEY_XDIMNAME ) + dimID = ncgrid[index].xdimID; + else + dimID = ncgrid[index].ydimID; + break; + } + } + } + } + + if ( dimID == UNDEFID ) + { + const double *pvals = gridAxisInq->axisValsPtr(gridID); + + char axisname[CDI_MAX_NAME]; + gridAxisInq->axisName(gridID, axisname); + if ( axisname[0] == 0 ) Error("axis name undefined!"); + size_t axisnameLen = strlen(axisname); + + /* enough to append _ plus up to 100 decimal and trailing \0 */ + char extendedAxisname[axisnameLen + 4 + 1]; + memcpy(extendedAxisname, axisname, axisnameLen + 1); + checkGridName(extendedAxisname, fileID); + size_t extendedAxisnameLen = axisnameLen + strlen(extendedAxisname + axisnameLen); + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + if ( ndims ) + { + char dimname[CDI_MAX_NAME+3]; dimname[0] = 0; + + if ( pvals == NULL ) + cdiGridInqKeyStr(gridID, dimKey, CDI_MAX_NAME, dimname); + + if ( dimname[0] == 0 ) strcpy(dimname, extendedAxisname); + dimID = checkDimName(fileID, dimlen, dimname); + + if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID); + } + + bool gen_bounds = false; + bool grid_is_cyclic = gridIsCircular(gridID) > 0; + double *pbounds = NULL; + if ( pvals ) + { + cdf_def_var(fileID, extendedAxisname, xtype, ndims, &dimID, &ncvarid); + + cdfPutGridStdAtts(fileID, ncvarid, gridID, gridAxisInq); + { + char axisStr[2] = { axisLetter, '\0' }; + cdf_put_att_text(fileID, ncvarid, "axis", 1, axisStr); + } + + pbounds = (double *)gridAxisInq->axisBoundsPtr(gridID); + + if ( CDI_cmor_mode && grid_is_cyclic && !pbounds ) + { + gen_bounds = true; + pbounds = (double*) Malloc(2*dimlen*sizeof(double)); + for ( size_t i = 0; i < dimlen-1; ++i ) + { + pbounds[i*2+1] = (pvals[i] + pvals[i+1])/2; + pbounds[(i+1)*2] = (pvals[i] + pvals[i+1])/2; + } + finishCyclicBounds(pbounds, dimlen, pvals); + } + if ( pbounds ) + { + size_t nvertex = 2; + if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR ) + cdf_def_dim(fileID, bndsName, nvertex, &nvdimID); + } + if ( pbounds && nvdimID != UNDEFID ) + { + char boundsname[extendedAxisnameLen + 1 + sizeof (bndsName)]; + memcpy(boundsname, axisname, extendedAxisnameLen); + boundsname[extendedAxisnameLen] = '_'; + memcpy(boundsname + extendedAxisnameLen + 1, bndsName, sizeof bndsName); + int dimIDs[2] = { dimID, nvdimID }; + cdf_def_var(fileID, boundsname, xtype, 2, dimIDs, &ncbvarid); + cdf_put_att_text(fileID, ncvarid, "bounds", extendedAxisnameLen + sizeof (bndsName), boundsname); + } + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + if ( ncvarid != UNDEFID ) cdf_put_var_double(fileID, ncvarid, pvals); + if ( ncbvarid != UNDEFID ) cdf_put_var_double(fileID, ncbvarid, pbounds); + if ( gen_bounds ) Free(pbounds); + + if ( ndims == 0 ) + { + if ( dimKey == CDI_KEY_XDIMNAME ) + ncgrid[gridindex].xvarID = ncvarid; + else + ncgrid[gridindex].yvarID = ncvarid; + } + } + + ncgrid[gridindex].gridID = gridID; + if ( dimKey == CDI_KEY_XDIMNAME ) + ncgrid[gridindex].xdimID = dimID; + else + ncgrid[gridindex].ydimID = dimID; +} + +static +void finishCyclicXBounds(double *pbounds, size_t dimlen, const double *pvals) +{ + pbounds[0] = (pvals[0] + pvals[dimlen-1]-360)*0.5; + pbounds[2*dimlen-1] = (pvals[dimlen-1] + pvals[0]+360)*0.5; +} + +static +void cdfDefXaxis(stream_t *streamptr, int gridID, int gridindex, int ndims) +{ + cdfDefAxisCommon(streamptr, gridID, gridindex, ndims, &gridInqsX, + CDI_KEY_XDIMNAME, 'X', finishCyclicXBounds); +} + +static +void finishCyclicYBounds(double *pbounds, size_t dimlen, const double *pvals) +{ + pbounds[0] = copysign(90.0, pvals[0]); + pbounds[2*dimlen-1] = copysign(90.0, pvals[dimlen-1]); +} + +static +void cdfDefYaxis(stream_t *streamptr, int gridID, int gridindex, int ndims) +{ + cdfDefAxisCommon(streamptr, gridID, gridindex, ndims, &gridInqsY, + CDI_KEY_YDIMNAME, 'Y', finishCyclicYBounds); +} + +static +void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int comptype) +{ +#if defined (HAVE_NETCDF4) + if ( gridsize > 1 && comptype == CDI_COMPRESS_ZIP && (filetype == FILETYPE_NC4 || filetype == FILETYPE_NC4C) ) + { + nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL); + cdfDefVarDeflate(fileID, ncvarid, 1); + } +#endif +} + +static +void cdfDefCurvilinear(stream_t *streamptr, int gridID, int gridindex) +{ + int xdimID = UNDEFID; + int ydimID = UNDEFID; + int ncxvarid = UNDEFID, ncyvarid = UNDEFID; + int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID; + nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE; + ncgrid_t *ncgrid = streamptr->ncgrid; + + int fileID = streamptr->fileID; + + size_t dimlen = (size_t)gridInqSize(gridID); + size_t xdimlen = (size_t)gridInqXsize(gridID); + size_t ydimlen = (size_t)gridInqYsize(gridID); + + for ( int index = 0; index < gridindex; index++ ) + { + if ( ncgrid[index].xdimID != UNDEFID ) + { + int gridID0 = ncgrid[index].gridID; + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == GRID_CURVILINEAR ) + { + size_t dimlen0 = (size_t)gridInqSize(gridID0); + if ( dimlen == dimlen0 ) + if ( IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) && + IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) && + IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) && + IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) ) + { + xdimID = ncgrid[index].xdimID; + ydimID = ncgrid[index].ydimID; + ncxvarid = ncgrid[index].xvarID; + ncyvarid = ncgrid[index].yvarID; + break; + } + } + } + } + + if ( xdimID == UNDEFID || ydimID == UNDEFID ) + { + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + { + char xdimname[CDI_MAX_NAME+3]; + xdimname[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_XDIMNAME, CDI_MAX_NAME, xdimname); + if ( xdimname[0] == 0 ) { xdimname[0] = 'x'; xdimname[1] = 0; } + xdimID = checkDimName(fileID, xdimlen, xdimname); + if ( xdimID == UNDEFID ) cdf_def_dim(fileID, xdimname, xdimlen, &xdimID); + } + { + char ydimname[CDI_MAX_NAME+3]; + ydimname[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_YDIMNAME, CDI_MAX_NAME, ydimname); + if ( ydimname[0] == 0 ) { ydimname[0] = 'y'; ydimname[1] = 0; } + ydimID = checkDimName(fileID, ydimlen, ydimname); + if ( ydimID == UNDEFID ) cdf_def_dim(fileID, ydimname, ydimlen, &ydimID); + } + + int nvdimID = UNDEFID; + int dimIDs[3]; + if ( gridInqXboundsPtr(gridID) || gridInqYboundsPtr(gridID) ) + { + char vdimname[CDI_MAX_NAME+3]; + vdimname[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_VDIMNAME, CDI_MAX_NAME, vdimname); + if ( vdimname[0] == 0 ) strcpy(vdimname, "nv4"); + size_t nvertex = 4; + nvdimID = checkDimName(fileID, nvertex, vdimname); + if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID); + } + + dimIDs[0] = ydimID; + dimIDs[1] = xdimID; + dimIDs[2] = nvdimID; + + if ( gridInqXvalsPtr(gridID) ) + { + char xaxisname[CDI_MAX_NAME]; + gridInqXname(gridID, xaxisname); + checkGridName(xaxisname, fileID); + + cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncxvarid); + cdfGridCompress(fileID, ncxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); + + cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX); + + /* attribute for Panoply */ + cdf_put_att_text(fileID, ncxvarid, "_CoordinateAxisType", 3, "Lon"); + + if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID ) + { + size_t xaxisnameLen = strlen(xaxisname); + xaxisname[xaxisnameLen] = '_'; + memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName)); + cdf_def_var(fileID, xaxisname, xtype, 3, dimIDs, &ncbxvarid); + cdfGridCompress(fileID, ncbxvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); + + cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname); + } + } + + if ( gridInqYvalsPtr(gridID) ) + { + char yaxisname[CDI_MAX_NAME]; + gridInqYname(gridID, yaxisname); + checkGridName(yaxisname, fileID); + + cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncyvarid); + cdfGridCompress(fileID, ncyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); + + cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY); + + /* attribute for Panoply */ + cdf_put_att_text(fileID, ncyvarid, "_CoordinateAxisType", 3, "Lat"); + + if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID ) + { + size_t yaxisnameLen = strlen(yaxisname); + yaxisname[yaxisnameLen] = '_'; + memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName)); + cdf_def_var(fileID, yaxisname, xtype, 3, dimIDs, &ncbyvarid); + cdfGridCompress(fileID, ncbyvarid, (int)(xdimlen*ydimlen), streamptr->filetype, streamptr->comptype); + + cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname); + } + } + + if ( gridInqAreaPtr(gridID) ) + { + static const char yaxisname_[] = "cell_area"; + static const char units[] = "m2"; + static const char longname[] = "area of grid cell"; + static const char stdname[] = "cell_area"; + + cdf_def_var(fileID, yaxisname_, xtype, 2, dimIDs, &ncavarid); + + cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname); + cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname); + cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units); + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + if ( ncxvarid != UNDEFID ) cdf_put_var_double(fileID, ncxvarid, gridInqXvalsPtr(gridID)); + if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID)); + if ( ncyvarid != UNDEFID ) cdf_put_var_double(fileID, ncyvarid, gridInqYvalsPtr(gridID)); + if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID)); + if ( ncavarid != UNDEFID ) cdf_put_var_double(fileID, ncavarid, gridInqAreaPtr(gridID)); + } + + ncgrid[gridindex].gridID = gridID; + ncgrid[gridindex].xdimID = xdimID; + ncgrid[gridindex].ydimID = ydimID; + ncgrid[gridindex].xvarID = ncxvarid; + ncgrid[gridindex].yvarID = ncyvarid; + ncgrid[gridindex].avarID = ncavarid; +} + +static +void cdfDefRgrid(stream_t *streamptr, int gridID, int gridindex) +{ + ncgrid_t *ncgrid = streamptr->ncgrid; + int dimID = UNDEFID; + + size_t dimlen = (size_t)gridInqSize(gridID); + + int iz = 0; + for ( int index = 0; index < gridindex; index++ ) + { + if ( ncgrid[index].xdimID != UNDEFID ) + { + int gridID0 = ncgrid[index].gridID; + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == GRID_GAUSSIAN_REDUCED ) + { + size_t dimlen0 = (size_t)gridInqSize(gridID0); + + if ( dimlen == dimlen0 ) + { + dimID = ncgrid[index].xdimID; + break; + } + iz++; + } + } + } + + if ( dimID == UNDEFID ) + { + int fileID = streamptr->fileID; + static bool lwarn = true; + if ( lwarn ) + { + Warning("Creating a NetCDF file with data on a gaussian reduced grid."); + Warning("The further processing of the resulting file is unsupported!"); + lwarn = false; + } + + char axisname[7] = "rgridX"; + if ( iz == 0 ) axisname[5] = '\0'; + else sprintf(&axisname[5], "%1d", iz+1); + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + cdf_def_dim(fileID, axisname, dimlen, &dimID); + + cdf_enddef(fileID); + streamptr->ncmode = 2; + } + + ncgrid[gridindex].gridID = gridID; + ncgrid[gridindex].xdimID = dimID; +} + +static +void cdfDefGdim(stream_t *streamptr, int gridID, int gridindex) +{ + ncgrid_t *ncgrid = streamptr->ncgrid; + int iz = 0; + int dimID = UNDEFID; + + size_t dimlen = (size_t)gridInqSize(gridID); + + if ( gridInqYsize(gridID) == 0 ) + for ( int index = 0; index < gridindex; index++ ) + { + if ( ncgrid[index].xdimID != UNDEFID ) + { + int gridID0 = ncgrid[index].gridID; + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == GRID_GENERIC ) + { + size_t dimlen0 = (size_t)gridInqSize(gridID0); + if ( dimlen == dimlen0 ) + { + dimID = ncgrid[index].xdimID; + break; + } + else + iz++; + } + } + } + + if ( gridInqXsize(gridID) == 0 ) + for ( int index = 0; index < gridindex; index++ ) + { + if ( ncgrid[index].ydimID != UNDEFID ) + { + int gridID0 = ncgrid[index].gridID; + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == GRID_GENERIC ) + { + size_t dimlen0 = (size_t)gridInqSize(gridID0); + if ( dimlen == dimlen0 ) + { + dimID = ncgrid[index].ydimID; + break; + } + else + iz++; + } + } + } + + if ( dimID == UNDEFID ) + { + int fileID = streamptr->fileID; + char dimname[CDI_MAX_NAME]; + strcpy(dimname, "gsize"); + + dimID = checkDimName(fileID, dimlen, dimname); + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + if ( dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID); + + cdf_enddef(fileID); + streamptr->ncmode = 2; + } + + ncgrid[gridindex].gridID = gridID; + ncgrid[gridindex].xdimID = dimID; +} + +static +void cdfDefGridReference(stream_t *streamptr, int gridID) +{ + int fileID = streamptr->fileID; + int number = gridInqNumber(gridID); + + if ( number > 0 ) + { + cdf_put_att_int(fileID, NC_GLOBAL, "number_of_grid_used", NC_INT, 1, &number); + } + + const char *gridfile = gridInqReferencePtr(gridID); + if ( gridfile && gridfile[0] != 0 ) + cdf_put_att_text(fileID, NC_GLOBAL, "grid_file_uri", strlen(gridfile), gridfile); +} + +static +void cdfDefGridUUID(stream_t *streamptr, int gridID) +{ + unsigned char uuidOfHGrid[CDI_UUID_SIZE]; + + gridInqUUID(gridID, uuidOfHGrid); + if ( !cdiUUIDIsNull(uuidOfHGrid) ) + { + char uuidOfHGridStr[37]; + cdiUUID2Str(uuidOfHGrid, uuidOfHGridStr); + if ( uuidOfHGridStr[0] != 0 && strlen(uuidOfHGridStr) == 36 ) + { + int fileID = streamptr->fileID; + //if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfHGrid", 36, uuidOfHGridStr); + //if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); + } + } +} + +static +void cdfDefZaxisUUID(stream_t *streamptr, int zaxisID) +{ + unsigned char uuidOfVGrid[CDI_UUID_SIZE]; + zaxisInqUUID(zaxisID, uuidOfVGrid); + + if ( uuidOfVGrid[0] != 0 ) + { + char uuidOfVGridStr[37]; + cdiUUID2Str(uuidOfVGrid, uuidOfVGridStr); + if ( uuidOfVGridStr[0] != 0 && strlen(uuidOfVGridStr) == 36 ) + { + int fileID = streamptr->fileID; + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + cdf_put_att_text(fileID, NC_GLOBAL, "uuidOfVGrid", 36, uuidOfVGridStr); + if ( streamptr->ncmode == 2 ) cdf_enddef(fileID); + } + } +} + +static +void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex) +{ + int dimID = UNDEFID; + int ncxvarid = UNDEFID, ncyvarid = UNDEFID; + int ncbxvarid = UNDEFID, ncbyvarid = UNDEFID, ncavarid = UNDEFID; + int nvdimID = UNDEFID; + nc_type xtype = (gridInqPrec(gridID) == DATATYPE_FLT32) ? NC_FLOAT : NC_DOUBLE; + ncgrid_t *ncgrid = streamptr->ncgrid; + + int fileID = streamptr->fileID; + + size_t dimlen = (size_t)gridInqSize(gridID); + + for ( int index = 0; index < gridindex; index++ ) + { + if ( ncgrid[index].xdimID != UNDEFID ) + { + int gridID0 = ncgrid[index].gridID; + int gridtype0 = gridInqType(gridID0); + if ( gridtype0 == GRID_UNSTRUCTURED ) + { + size_t dimlen0 = (size_t)gridInqSize(gridID0); + if ( dimlen == dimlen0 ) + if ( gridInqNvertex(gridID0) == gridInqNvertex(gridID) && + IS_EQUAL(gridInqXval(gridID0, 0), gridInqXval(gridID, 0)) && + IS_EQUAL(gridInqXval(gridID0, (int)dimlen-1), gridInqXval(gridID, (int)dimlen-1)) && + IS_EQUAL(gridInqYval(gridID0, 0), gridInqYval(gridID, 0)) && + IS_EQUAL(gridInqYval(gridID0, (int)dimlen-1), gridInqYval(gridID, (int)dimlen-1)) ) + { + dimID = ncgrid[index].xdimID; + ncxvarid = ncgrid[index].xvarID; + ncyvarid = ncgrid[index].yvarID; + ncavarid = ncgrid[index].avarID; + break; + } + } + } + } + + if ( dimID == UNDEFID ) + { + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + { + char xdimname[CDI_MAX_NAME+3]; + xdimname[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_XDIMNAME, CDI_MAX_NAME, xdimname); + if ( xdimname[0] == 0 ) strcpy(xdimname, "ncells"); + dimID = checkDimName(fileID, dimlen, xdimname); + if ( dimID == UNDEFID ) cdf_def_dim(fileID, xdimname, dimlen, &dimID); + } + + size_t nvertex = (size_t)gridInqNvertex(gridID); + if ( nvertex > 0 ) + { + char vdimname[CDI_MAX_NAME+3]; + vdimname[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_VDIMNAME, CDI_MAX_NAME, vdimname); + if ( vdimname[0] == 0 ) strcpy(vdimname, "vertices"); + nvdimID = checkDimName(fileID, nvertex, vdimname); + if ( nvdimID == UNDEFID ) cdf_def_dim(fileID, vdimname, nvertex, &nvdimID); + } + + cdfDefGridReference(streamptr, gridID); + + cdfDefGridUUID(streamptr, gridID); + + if ( gridInqXvalsPtr(gridID) ) + { + char xaxisname[CDI_MAX_NAME]; + gridInqXname(gridID, xaxisname); + checkGridName(xaxisname, fileID); + cdf_def_var(fileID, xaxisname, xtype, 1, &dimID, &ncxvarid); + cdfGridCompress(fileID, ncxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); + + cdfPutGridStdAtts(fileID, ncxvarid, gridID, &gridInqsX); + + if ( gridInqXboundsPtr(gridID) && nvdimID != UNDEFID ) + { + int dimIDs[2] = { dimID, nvdimID }; + size_t xaxisnameLen = strlen(xaxisname); + xaxisname[xaxisnameLen] = '_'; + memcpy(xaxisname + xaxisnameLen + 1, bndsName, sizeof (bndsName)); + cdf_def_var(fileID, xaxisname, xtype, 2, dimIDs, &ncbxvarid); + cdfGridCompress(fileID, ncbxvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); + + cdf_put_att_text(fileID, ncxvarid, "bounds", xaxisnameLen + sizeof (bndsName), xaxisname); + } + } + + if ( gridInqYvalsPtr(gridID) ) + { + char yaxisname[CDI_MAX_NAME]; + gridInqYname(gridID, yaxisname); + checkGridName(yaxisname, fileID); + cdf_def_var(fileID, yaxisname, xtype, 1, &dimID, &ncyvarid); + cdfGridCompress(fileID, ncyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); + + cdfPutGridStdAtts(fileID, ncyvarid, gridID, &gridInqsY); + + if ( gridInqYboundsPtr(gridID) && nvdimID != UNDEFID ) + { + int dimIDs[2] = { dimID, nvdimID }; + size_t yaxisnameLen = strlen(yaxisname); + yaxisname[yaxisnameLen] = '_'; + memcpy(yaxisname + yaxisnameLen + 1, bndsName, sizeof (bndsName)); + cdf_def_var(fileID, yaxisname, xtype, 2, dimIDs, &ncbyvarid); + cdfGridCompress(fileID, ncbyvarid, (int)dimlen, streamptr->filetype, streamptr->comptype); + + cdf_put_att_text(fileID, ncyvarid, "bounds", yaxisnameLen + sizeof (bndsName), yaxisname); + } + } + + if ( gridInqAreaPtr(gridID) ) + { + static const char yaxisname_[] = "cell_area"; + static const char units[] = "m2"; + static const char longname[] = "area of grid cell"; + static const char stdname[] = "cell_area"; + + cdf_def_var(fileID, yaxisname_, xtype, 1, &dimID, &ncavarid); + + cdf_put_att_text(fileID, ncavarid, "standard_name", sizeof (stdname) - 1, stdname); + cdf_put_att_text(fileID, ncavarid, "long_name", sizeof (longname) - 1, longname); + cdf_put_att_text(fileID, ncavarid, "units", sizeof (units) - 1, units); + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + if ( ncxvarid != UNDEFID ) cdf_put_var_double(fileID, ncxvarid, gridInqXvalsPtr(gridID)); + if ( ncbxvarid != UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID)); + if ( ncyvarid != UNDEFID ) cdf_put_var_double(fileID, ncyvarid, gridInqYvalsPtr(gridID)); + if ( ncbyvarid != UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID)); + if ( ncavarid != UNDEFID ) cdf_put_var_double(fileID, ncavarid, gridInqAreaPtr(gridID)); + } + + ncgrid[gridindex].gridID = gridID; + ncgrid[gridindex].xdimID = dimID; + ncgrid[gridindex].xvarID = ncxvarid; + ncgrid[gridindex].yvarID = ncyvarid; + ncgrid[gridindex].avarID = ncavarid; +} + +struct attTxtTab2 +{ + const char *attName, *attVal; + size_t valLen; +}; + +static +void cdf_def_vct_echam(stream_t *streamptr, int zaxisID) +{ + int type = zaxisInqType(zaxisID); + + if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF ) + { + int ilev = zaxisInqVctSize(zaxisID)/2; + if ( ilev == 0 ) return; + + int mlev = ilev - 1; + size_t start; + size_t count = 1; + int ncdimid, ncdimid2; + int hyaiid, hybiid, hyamid, hybmid; + double mval; + + if ( streamptr->vct.ilev > 0 ) + { + if ( streamptr->vct.ilev != ilev ) + Error("more than one VCT for each file unsupported!"); + return; + } + + int fileID = streamptr->fileID; + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + cdf_def_dim(fileID, "nhym", (size_t)mlev, &ncdimid); + cdf_def_dim(fileID, "nhyi", (size_t)ilev, &ncdimid2); + + streamptr->vct.mlev = mlev; + streamptr->vct.ilev = ilev; + streamptr->vct.mlevID = ncdimid; + streamptr->vct.ilevID = ncdimid2; + + cdf_def_var(fileID, "hyai", NC_DOUBLE, 1, &ncdimid2, &hyaiid); + cdf_def_var(fileID, "hybi", NC_DOUBLE, 1, &ncdimid2, &hybiid); + cdf_def_var(fileID, "hyam", NC_DOUBLE, 1, &ncdimid, &hyamid); + cdf_def_var(fileID, "hybm", NC_DOUBLE, 1, &ncdimid, &hybmid); + + { + static const char lname_n[] = "long_name", + lname_v_ai[] = "hybrid A coefficient at layer interfaces", + units_n[] = "units", + units_v_ai[] = "Pa", + lname_v_bi[] = "hybrid B coefficient at layer interfaces", + units_v_bi[] = "1", + lname_v_am[] = "hybrid A coefficient at layer midpoints", + units_v_am[] = "Pa", + lname_v_bm[] = "hybrid B coefficient at layer midpoints", + units_v_bm[] = "1"; + static const struct attTxtTab2 tab[] + = { + { lname_n, lname_v_ai, sizeof (lname_v_ai) - 1 }, + { units_n, units_v_ai, sizeof (units_v_ai) - 1 }, + { lname_n, lname_v_bi, sizeof (lname_v_bi) - 1 }, + { units_n, units_v_bi, sizeof (units_v_bi) - 1 }, + { lname_n, lname_v_am, sizeof (lname_v_am) - 1 }, + { units_n, units_v_am, sizeof (units_v_am) - 1 }, + { lname_n, lname_v_bm, sizeof (lname_v_bm) - 1 }, + { units_n, units_v_bm, sizeof (units_v_bm) - 1 }, + }; + enum { tabLen = sizeof (tab) / sizeof (tab[0]) }; + int ids[tabLen] = { hyaiid, hyaiid, hybiid, hybiid, + hyamid, hyamid, hybmid, hybmid }; + for ( size_t i = 0; i < tabLen; ++i ) + cdf_put_att_text(fileID, ids[i], tab[i].attName, tab[i].valLen, tab[i].attVal); + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + const double *vctptr = zaxisInqVctPtr(zaxisID); + + cdf_put_var_double(fileID, hyaiid, vctptr); + cdf_put_var_double(fileID, hybiid, vctptr+ilev); + + for ( int i = 0; i < mlev; i++ ) + { + start = (size_t)i; + mval = (vctptr[i] + vctptr[i+1]) * 0.5; + cdf_put_vara_double(fileID, hyamid, &start, &count, &mval); + mval = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5; + cdf_put_vara_double(fileID, hybmid, &start, &count, &mval); + } + } +} + +static +void cdf_def_vct_cf(stream_t *streamptr, int zaxisID, int nclevID, int ncbndsID) +{ + int type = zaxisInqType(zaxisID); + + if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF ) + { + int ilev = zaxisInqVctSize(zaxisID)/2; + if ( ilev == 0 ) return; + + int mlev = ilev - 1; + int hyaiid = 0, hybiid = 0, hyamid, hybmid; + + if ( streamptr->vct.ilev > 0 ) + { + if ( streamptr->vct.ilev != ilev ) + Error("more than one VCT for each file unsupported!"); + return; + } + + int fileID = streamptr->fileID; + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + int dimIDs[2]; + dimIDs[0] = nclevID; + dimIDs[1] = ncbndsID; + + streamptr->vct.mlev = mlev; + streamptr->vct.ilev = ilev; + streamptr->vct.mlevID = nclevID; + streamptr->vct.ilevID = nclevID; + + cdf_def_var(fileID, "ap", NC_DOUBLE, 1, dimIDs, &hyamid); + cdf_def_var(fileID, "b", NC_DOUBLE, 1, dimIDs, &hybmid); + + { + static const char lname[] = "vertical coordinate formula term: ap(k)"; + cdf_put_att_text(fileID, hyamid, "long_name", sizeof (lname) - 1, lname); + } + { + static const char units[] = "Pa"; + cdf_put_att_text(fileID, hyamid, "units", sizeof (units) - 1, units); + } + { + static const char lname[] = "vertical coordinate formula term: b(k)"; + cdf_put_att_text(fileID, hybmid, "long_name", sizeof (lname) - 1, lname); + } + { + static const char units[] = "1"; + cdf_put_att_text(fileID, hybmid, "units", sizeof (units) - 1, units); + } + + if ( ncbndsID != -1 ) + { + cdf_def_var(fileID, "ap_bnds", NC_DOUBLE, 2, dimIDs, &hyaiid); + cdf_def_var(fileID, "b_bnds", NC_DOUBLE, 2, dimIDs, &hybiid); + { + static const char lname[] = "vertical coordinate formula term: ap(k+1/2)"; + cdf_put_att_text(fileID, hyaiid, "long_name", sizeof (lname) - 1, lname); + } + { + static const char units[] = "Pa"; + cdf_put_att_text(fileID, hyaiid, "units", sizeof (units) - 1, units); + } + { + static const char lname[] = "vertical coordinate formula term: b(k+1/2)"; + cdf_put_att_text(fileID, hybiid, "long_name", sizeof (lname) - 1, lname); + } + { + static const char units[] = "1"; + cdf_put_att_text(fileID, hybiid, "units", sizeof (units) - 1, units); + } + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + const double *vctptr = zaxisInqVctPtr(zaxisID); + double tarray[ilev*2]; + + if ( ncbndsID != -1 ) + { + for ( int i = 0; i < mlev; ++i ) + { + tarray[2*i ] = vctptr[i]; + tarray[2*i+1] = vctptr[i+1]; + } + cdf_put_var_double(fileID, hyaiid, tarray); + + for ( int i = 0; i < mlev; ++i ) + { + tarray[2*i ] = vctptr[ilev+i]; + tarray[2*i+1] = vctptr[ilev+i+1]; + } + cdf_put_var_double(fileID, hybiid, tarray); + } + + for ( int i = 0; i < mlev; ++i ) + tarray[i] = (vctptr[i] + vctptr[i+1]) * 0.5; + cdf_put_var_double(fileID, hyamid, tarray); + + for ( int i = 0; i < mlev; ++i ) + tarray[i] = (vctptr[ilev+i] + vctptr[ilev+i+1]) * 0.5; + cdf_put_var_double(fileID, hybmid, tarray); + } +} + +struct attTxtTab { const char *txt; size_t txtLen; }; + +static +void cdf_def_zaxis_hybrid_echam(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname) +{ + int fileID = streamptr->fileID; + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + cdf_def_dim(fileID, axisname, dimlen, dimID); + cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID, &ncvarid); + + { + static const char sname[] = "hybrid_sigma_pressure"; + cdf_put_att_text(fileID, ncvarid, "standard_name", sizeof (sname) - 1, sname); + } + { + static const char *attName[] = { + "long_name", + "formula", + "formula_terms" + }; + enum { nAtt = sizeof (attName) / sizeof (attName[0]) }; + static const char lname_m[] = "hybrid level at layer midpoints", + formula_m[] = "hyam hybm (mlev=hyam+hybm*aps)", + fterms_m[] = "ap: hyam b: hybm ps: aps", + lname_i[] = "hybrid level at layer interfaces", + formula_i[] = "hyai hybi (ilev=hyai+hybi*aps)", + fterms_i[] = "ap: hyai b: hybi ps: aps"; + static const struct attTxtTab tab[2][nAtt] = { + { + { lname_i, sizeof (lname_i) - 1 }, + { formula_i, sizeof (formula_i) - 1 }, + { fterms_i, sizeof (fterms_i) - 1 } + }, + { + { lname_m, sizeof (lname_m) - 1 }, + { formula_m, sizeof (formula_m) - 1 }, + { fterms_m, sizeof (fterms_m) - 1 } + } + }; + + size_t tabSelect = type == ZAXIS_HYBRID; + for (size_t i = 0; i < nAtt; ++i) + cdf_put_att_text(fileID, ncvarid, attName[i], + tab[tabSelect][i].txtLen, tab[tabSelect][i].txt); + } + + { + static const char units[] = "level"; + cdf_put_att_text(fileID, ncvarid, "units", sizeof (units) - 1, units); + } + { + static const char direction[] = "down"; + cdf_put_att_text(fileID, ncvarid, "positive", sizeof (direction) - 1, direction); + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID)); + + cdf_def_vct_echam(streamptr, zaxisID); + + if ( *dimID == UNDEFID ) + { + if ( type == ZAXIS_HYBRID ) + streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID; + else + streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID; + } +} + +static +void cdf_def_zaxis_hybrid_cf(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname) +{ + char psname[CDI_MAX_NAME]; + psname[0] = 0; + zaxisInqPsName(zaxisID, psname); + if ( psname[0] == 0 ) strcpy(psname, "ps"); + + int fileID = streamptr->fileID; + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + strcpy(axisname, "lev"); + + cdf_def_dim(fileID, axisname, dimlen, dimID); + cdf_def_var(fileID, axisname, (nc_type) xtype, 1, dimID, &ncvarid); + + { + static const char sname[] = "standard_name", + sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate", + lname[] = "long_name", + lname_v[] = "hybrid sigma pressure coordinate", + formula[] = "formula", + formula_v[] = "p = ap + b*ps", + fterms[] = "formula_terms", + fterms_v[] = "ap: ap b: b ps: ", + units[] = "units", + units_v[] = "1", + axis[] = "axis", + axis_v[] = "Z", + direction[] = "positive", + direction_v[] = "down"; + struct attTxtTab2 tab[] = { + { sname, sname_v, sizeof (sname_v) - 1 }, + { lname, lname_v, sizeof (lname_v) - 1 }, + { formula, formula_v, sizeof (formula_v) - 1 }, + { fterms, fterms_v, sizeof (fterms_v) - 1 }, + { units, units_v, sizeof (units_v) - 1 }, + { axis, axis_v, sizeof (axis_v) - 1 }, + { direction, direction_v, sizeof (direction_v) - 1 }, + }; + enum { nAtt = sizeof (tab) / sizeof (tab[0]) }; + for (size_t i = 0; i < nAtt; ++i) + cdf_put_att_text(fileID, ncvarid, tab[i].attName, tab[i].valLen, tab[i].attVal); + } + + int ncbvarid = UNDEFID; + int nvdimID = UNDEFID; + + double lbounds[dimlen], ubounds[dimlen], levels[dimlen]; + + zaxisInqLevels(zaxisID, levels); + + if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) + { + zaxisInqLbounds(zaxisID, lbounds); + zaxisInqUbounds(zaxisID, ubounds); + } + else + { + for ( size_t i = 0; i < dimlen; ++i ) lbounds[i] = levels[i]; + for ( size_t i = 0; i < dimlen-1; ++i ) ubounds[i] = levels[i+1]; + ubounds[dimlen-1] = levels[dimlen-1] + 1; + } + + //if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) + { + size_t nvertex = 2; + if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR ) + cdf_def_dim(fileID, bndsName, nvertex, &nvdimID); + + if ( nvdimID != UNDEFID ) + { + size_t axisnameLen = strlen(axisname); + axisname[axisnameLen] = '_'; + memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName)); + axisnameLen += sizeof (bndsName); + int dimIDs[2] = { *dimID, nvdimID }; + cdf_def_var(fileID, axisname, (nc_type) xtype, 2, dimIDs, &ncbvarid); + cdf_put_att_text(fileID, ncvarid, "bounds", axisnameLen, axisname); + { + static const char sname[] = "standard_name", + sname_v[] = "atmosphere_hybrid_sigma_pressure_coordinate", + formula[] = "formula", + formula_v[] = "p = ap + b*ps"; + struct attTxtTab2 tab[] = { + { sname, sname_v, sizeof (sname_v) - 1 }, + { formula, formula_v, sizeof (formula_v) - 1 }, + }; + enum { nAtt = sizeof (tab) / sizeof (tab[0]) }; + for (size_t i = 0; i < nAtt; ++i) + cdf_put_att_text(fileID, ncbvarid, tab[i].attName, tab[i].valLen, tab[i].attVal); + } + { + char txt[CDI_MAX_NAME]; + size_t len = (size_t)(sprintf(txt, "%s%s", "ap: ap_bnds b: b_bnds ps: ", psname)); + cdf_put_att_text(fileID, ncbvarid, "formula_terms", len, txt); + } + { + static const char units[] = "1"; + cdf_put_att_text(fileID, ncbvarid, "units", sizeof (units) - 1, units); + } + } + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + cdf_put_var_double(fileID, ncvarid, levels); + + if ( ncbvarid != UNDEFID ) + { + double zbounds[2*dimlen]; + for ( size_t i = 0; i < dimlen; ++i ) + { + zbounds[2*i ] = lbounds[i]; + zbounds[2*i+1] = ubounds[i]; + } + cdf_put_var_double(fileID, ncbvarid, zbounds); + } + + cdf_def_vct_cf(streamptr, zaxisID, *dimID, nvdimID); + + if ( *dimID == UNDEFID ) + { + if ( type == ZAXIS_HYBRID ) + streamptr->zaxisID[zaxisindex] = streamptr->vct.mlevID; + else + streamptr->zaxisID[zaxisindex] = streamptr->vct.ilevID; + } +} + +static +void cdf_def_zaxis_hybrid(stream_t *streamptr, int type, int ncvarid, int zaxisID, int zaxisindex, int xtype, size_t dimlen, int *dimID, char *axisname) +{ + if ( (!CDI_cmor_mode && cdiConvention == CDI_CONVENTION_ECHAM) || type == ZAXIS_HYBRID_HALF ) + cdf_def_zaxis_hybrid_echam(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname); + else + cdf_def_zaxis_hybrid_cf(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, dimID, axisname); +} + +static +void cdfDefZaxis(stream_t *streamptr, int zaxisID) +{ + /* char zaxisname0[CDI_MAX_NAME]; */ + char axisname[CDI_MAX_NAME]; + int dimID = UNDEFID; + int dimIDs[2]; + int ncvarid = UNDEFID, ncbvarid = UNDEFID; + int nvdimID = UNDEFID; + int xtype = NC_DOUBLE; + + if ( zaxisInqPrec(zaxisID) == DATATYPE_FLT32 ) xtype = NC_FLOAT; + + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + + int zaxisindex = vlistZaxisIndex(vlistID, zaxisID); + + int nzaxis = vlistNzaxis(vlistID); + + size_t dimlen = (size_t)zaxisInqSize(zaxisID); + int type = zaxisInqType(zaxisID); + + int is_scalar = FALSE; + if ( dimlen == 1 ) + { + is_scalar = zaxisInqScalar(zaxisID); + if ( !is_scalar && CDI_cmor_mode ) + { + is_scalar = TRUE; + zaxisDefScalar(zaxisID); + } + } + + int ndims = 1; + if ( is_scalar ) ndims = 0; + + if ( dimlen == 1 ) + switch (type) + { + case ZAXIS_SURFACE: + case ZAXIS_CLOUD_BASE: + case ZAXIS_CLOUD_TOP: + case ZAXIS_ISOTHERM_ZERO: + case ZAXIS_TOA: + case ZAXIS_SEA_BOTTOM: + case ZAXIS_ATMOSPHERE: + case ZAXIS_MEANSEA: + case ZAXIS_LAKE_BOTTOM: + case ZAXIS_SEDIMENT_BOTTOM: + case ZAXIS_SEDIMENT_BOTTOM_TA: + case ZAXIS_SEDIMENT_BOTTOM_TW: + case ZAXIS_MIX_LAYER: + return; + } + + zaxisInqName(zaxisID, axisname); + + if ( dimID == UNDEFID ) + { + checkZaxisName(axisname, fileID, vlistID, zaxisID, nzaxis); + + char dimname[CDI_MAX_NAME+3]; + dimname[0] = 0; + //cdiZaxisInqString(zaxisID, CDI_ZAXIS_DIMNAME, CDI_MAX_NAME, dimname); + if ( dimname[0] == 0 ) strcpy(dimname, axisname); + + if ( type == ZAXIS_REFERENCE ) cdfDefZaxisUUID(streamptr, zaxisID); + + if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF ) + { + cdf_def_zaxis_hybrid(streamptr, type, ncvarid, zaxisID, zaxisindex, xtype, dimlen, &dimID, axisname); + } + else + { + dimID = checkDimName(fileID, dimlen, dimname); + + if ( streamptr->ncmode == 2 ) cdf_redef(fileID); + + if ( ndims && dimID == UNDEFID ) cdf_def_dim(fileID, dimname, dimlen, &dimID); + + cdf_def_var(fileID, axisname, (nc_type) xtype, ndims, &dimID, &ncvarid); + + cdfPutGridStdAtts(fileID, ncvarid, zaxisID, &gridInqsZ); + + { + int positive = zaxisInqPositive(zaxisID); + static const char positive_up[] = "up", + positive_down[] = "down"; + static const struct attTxtTab tab[2] = { + { positive_up, sizeof (positive_up) - 1 }, + { positive_down, sizeof (positive_down) - 1 }, + }; + if ( positive == POSITIVE_UP || positive == POSITIVE_DOWN ) + { + size_t select = positive == POSITIVE_DOWN; + cdf_put_att_text(fileID, ncvarid, "positive", + tab[select].txtLen, tab[select].txt); + } + } + cdf_put_att_text(fileID, ncvarid, "axis", 1, "Z"); + + if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) + { + size_t nvertex = 2; + if ( nc_inq_dimid(fileID, bndsName, &nvdimID) != NC_NOERR ) + cdf_def_dim(fileID, bndsName, nvertex, &nvdimID); + + if ( nvdimID != UNDEFID ) + { + size_t axisnameLen = strlen(axisname); + axisname[axisnameLen] = '_'; + memcpy(axisname + axisnameLen + 1, bndsName, sizeof (bndsName)); + dimIDs[0] = dimID; + dimIDs[ndims] = nvdimID; + cdf_def_var(fileID, axisname, (nc_type) xtype, ndims+1, dimIDs, &ncbvarid); + cdf_put_att_text(fileID, ncvarid, "bounds", strlen(axisname), axisname); + } + } + + cdf_enddef(fileID); + streamptr->ncmode = 2; + + cdf_put_var_double(fileID, ncvarid, zaxisInqLevelsPtr(zaxisID)); + + if ( ncbvarid != UNDEFID ) + { + double lbounds[dimlen], ubounds[dimlen], zbounds[2*dimlen]; + zaxisInqLbounds(zaxisID, lbounds); + zaxisInqUbounds(zaxisID, ubounds); + for ( size_t i = 0; i < dimlen; ++i ) + { + zbounds[2*i ] = lbounds[i]; + zbounds[2*i+1] = ubounds[i]; + } + + cdf_put_var_double(fileID, ncbvarid, zbounds); + } + + if ( ndims == 0 ) streamptr->nczvarID[zaxisindex] = ncvarid; + } + } + + if ( dimID != UNDEFID ) + streamptr->zaxisID[zaxisindex] = dimID; +} + +static +void cdfDefPole(stream_t *streamptr, int gridID) +{ + int ncvarid = UNDEFID; + static const char varname[] = "rotated_pole"; + static const char mapname[] = "rotated_latitude_longitude"; + + int fileID = streamptr->fileID; + + double ypole = gridInqYpole(gridID); + double xpole = gridInqXpole(gridID); + double angle = gridInqAngle(gridID); + + cdf_redef(fileID); + + int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); + if ( ncerrcode == NC_NOERR ) + { + cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", sizeof (mapname) - 1, mapname); + cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole); + cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole); + if ( IS_NOT_EQUAL(angle, 0) ) + cdf_put_att_double(fileID, ncvarid, "north_pole_grid_longitude", NC_DOUBLE, 1, &angle); + } + + cdf_enddef(fileID); +} + +static +void cdf_def_mapping(stream_t *streamptr, int gridID) +{ + char mapping[CDI_MAX_NAME]; mapping[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping); + if ( mapping[0] ) + { + char gmapvarname[CDI_MAX_NAME]; gmapvarname[0] = 0; + cdiGridInqKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, gmapvarname); + + int fileID = streamptr->fileID; + cdf_redef(fileID); + + int ncvarid; + int ncerrcode = nc_def_var(fileID, gmapvarname, (nc_type) NC_INT, 0, NULL, &ncvarid); + if ( ncerrcode == NC_NOERR ) + cdfDefineAttributes(gridID, CDI_GLOBAL, fileID, ncvarid); + + cdf_enddef(fileID); + + if ( ncerrcode == NC_NOERR ) + { + int dummy = 1; + cdf_put_var_int(fileID, ncvarid, &dummy); + } + } +} + +static +void cdfDefMapping(stream_t *streamptr, int gridID) +{ + int ncvarid = UNDEFID; + int fileID = streamptr->fileID; + + if ( gridInqType(gridID) == GRID_SINUSOIDAL ) + { + static const char varname[] = "Sinusoidal"; + static const char mapname[] = "sinusoidal"; + + cdf_redef(fileID); + + int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); + if ( ncerrcode == NC_NOERR ) + { + cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname); + /* + cdf_put_att_double(fileID, ncvarid, "grid_north_pole_latitude", NC_DOUBLE, 1, &ypole); + cdf_put_att_double(fileID, ncvarid, "grid_north_pole_longitude", NC_DOUBLE, 1, &xpole); + */ + } + + cdf_enddef(fileID); + } + else if ( gridInqType(gridID) == GRID_LAEA ) + { + static const char varname[] = "Lambert_AEA"; + static const char mapname[] = "lambert_azimuthal_equal_area"; + + cdf_redef(fileID); + + int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); + if ( ncerrcode == NC_NOERR ) + { + double a, lon_0, lat_0; + + gridInqLaea(gridID, &a, &lon_0, &lat_0); + + cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname); + cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &a); + cdf_put_att_double(fileID, ncvarid, "longitude_of_projection_origin", NC_DOUBLE, 1, &lon_0); + cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0); + } + + cdf_enddef(fileID); + } + else if ( gridInqType(gridID) == GRID_LCC2 ) + { + static const char varname[] = "Lambert_CC"; + static const char mapname[] = "lambert_conformal_conic"; + + cdf_redef(fileID); + + int ncerrcode = nc_def_var(fileID, varname, (nc_type) NC_CHAR, 0, NULL, &ncvarid); + if ( ncerrcode == NC_NOERR ) + { + double radius, lon_0, lat_0, lat_1, lat_2; + + gridInqLcc2(gridID, &radius, &lon_0, &lat_0, &lat_1, &lat_2); + + cdf_put_att_text(fileID, ncvarid, "grid_mapping_name", strlen(mapname), mapname); + if ( radius > 0 ) + cdf_put_att_double(fileID, ncvarid, "earth_radius", NC_DOUBLE, 1, &radius); + cdf_put_att_double(fileID, ncvarid, "longitude_of_central_meridian", NC_DOUBLE, 1, &lon_0); + cdf_put_att_double(fileID, ncvarid, "latitude_of_projection_origin", NC_DOUBLE, 1, &lat_0); + if ( IS_EQUAL(lat_1, lat_2) ) + cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 1, &lat_1); + else + { + double lat_1_2[2]; + lat_1_2[0] = lat_1; + lat_1_2[1] = lat_2; + cdf_put_att_double(fileID, ncvarid, "standard_parallel", NC_DOUBLE, 2, lat_1_2); + } + } + + cdf_enddef(fileID); + } +} + +static +void cdfDefGrid(stream_t *streamptr, int gridID, int gridindex) +{ + if ( streamptr->ncgrid[gridindex].xdimID != UNDEFID ) return; + + int gridtype = gridInqType(gridID); + int size = gridInqSize(gridID); + + if ( CDI_Debug ) + Message("gridtype = %d size = %d", gridtype, size); + + if ( gridtype == GRID_GAUSSIAN || + gridtype == GRID_LONLAT || + gridtype == GRID_PROJECTION || + gridtype == GRID_GENERIC ) + { + if ( gridtype == GRID_GENERIC ) + { + if ( size == 1 && gridInqXsize(gridID) == 0 && gridInqYsize(gridID) == 0 ) + { + /* no grid information */ + streamptr->ncgrid[gridindex].gridID = gridID; + } + else + { + bool lx = false, ly = false; + if ( gridInqXsize(gridID) > 0 /*&& gridInqXvals(gridID, NULL) > 0*/ ) + { + cdfDefXaxis(streamptr, gridID, gridindex, 1); + lx = true; + } + + if ( gridInqYsize(gridID) > 0 /*&& gridInqYvals(gridID, NULL) > 0*/ ) + { + cdfDefYaxis(streamptr, gridID, gridindex, 1); + ly = true; + } + + if ( !lx && !ly ) cdfDefGdim(streamptr, gridID, gridindex); + } + } + else + { + int ndims = 1; + if ( gridtype == GRID_LONLAT && size == 1 && gridInqHasDims(gridID) == FALSE ) + ndims = 0; + + if ( gridInqXsize(gridID) > 0 ) cdfDefXaxis(streamptr, gridID, gridindex, ndims); + if ( gridInqYsize(gridID) > 0 ) cdfDefYaxis(streamptr, gridID, gridindex, ndims); + + cdf_def_mapping(streamptr, gridID); + } + + if ( gridIsRotated(gridID) ) cdfDefPole(streamptr, gridID); + } + else if ( gridtype == GRID_CURVILINEAR ) + { + cdfDefCurvilinear(streamptr, gridID, gridindex); + } + else if ( gridtype == GRID_UNSTRUCTURED ) + { + cdfDefUnstructured(streamptr, gridID, gridindex); + } + else if ( gridtype == GRID_GAUSSIAN_REDUCED ) + { + cdfDefRgrid(streamptr, gridID, gridindex); + } + else if ( gridtype == GRID_SPECTRAL ) + { + cdfDefComplex(streamptr, gridID, gridindex); + cdfDefSP(streamptr, gridID, gridindex); + } + else if ( gridtype == GRID_FOURIER ) + { + cdfDefComplex(streamptr, gridID, gridindex); + cdfDefFC(streamptr, gridID, gridindex); + } + else if ( gridtype == GRID_TRAJECTORY ) + { + cdfDefTrajLon(streamptr, gridID, gridindex); + cdfDefTrajLat(streamptr, gridID, gridindex); + } + else if ( gridtype == GRID_SINUSOIDAL || gridtype == GRID_LAEA || gridtype == GRID_LCC2 ) + { + cdfDefXaxis(streamptr, gridID, gridindex, 1); + cdfDefYaxis(streamptr, gridID, gridindex, 1); + + cdfDefMapping(streamptr, gridID); + } + /* + else if ( gridtype == GRID_LCC ) + { + cdfDefLcc(streamptr, gridID); + } + */ + else + { + Error("Unsupported grid type: %s", gridNamePtr(gridtype)); + } +} + + +void cdfDefHistory(stream_t *streamptr, int size, const char *history) +{ + int ncid = streamptr->fileID; + cdf_put_att_text(ncid, NC_GLOBAL, "history", (size_t) size, history); +} + + +void cdfDefVars(stream_t *streamptr) +{ + int index = 0; + int vlistID = streamptr->vlistID; + if ( vlistID == UNDEFID ) + Error("Internal problem! vlist undefined for streamptr %p", streamptr); + + int ngrids = vlistNgrids(vlistID); + streamptr->ncgrid = (ncgrid_t*) Malloc(2*ngrids*sizeof(ncgrid_t)); + for ( index = 0; index < 2*ngrids; ++index ) + { + streamptr->ncgrid[index].gridID = UNDEFID; + streamptr->ncgrid[index].xdimID = UNDEFID; + streamptr->ncgrid[index].ydimID = UNDEFID; + streamptr->ncgrid[index].xvarID = UNDEFID; + streamptr->ncgrid[index].yvarID = UNDEFID; + streamptr->ncgrid[index].avarID = UNDEFID; + } + + for ( index = 0; index < ngrids; ++index ) + { + int gridID = vlistGrid(vlistID, index); + cdfDefGrid(streamptr, gridID, index); + } + index = ngrids-1; + for ( int i = 0; i < ngrids; ++i ) + { + int gridID = vlistGrid(vlistID, i); + int projID = gridInqProj(gridID); + if ( projID != CDI_UNDEFID ) cdfDefGrid(streamptr, projID, ++index); + } + + int nzaxis = vlistNzaxis(vlistID); + for ( int index = 0; index < nzaxis; ++index ) + { + int zaxisID = vlistZaxis(vlistID, index); + if ( streamptr->zaxisID[index] == UNDEFID ) cdfDefZaxis(streamptr, zaxisID); + } +} + +#endif + +/* + * Local Variables: + * c-file-style: "Java" + * c-basic-offset: 2 + * indent-tabs-mode: nil + * show-trailing-whitespace: t + * require-trailing-newline: t + * End: + */ diff --git a/src/stream_cgribex.c b/src/stream_cgribex.c index 474e33117898c8cba62ffbb28037e32b9cb394b8..3214b8309913d1c46ad0f9dead5a846be191187c 100644 --- a/src/stream_cgribex.c +++ b/src/stream_cgribex.c @@ -36,17 +36,21 @@ int cgribexGetGridType(int *isec2) switch (ISEC2_GridType) { - case GRIB1_GTYPE_LATLON: { if ( ISEC2_Reduced ) break; } - case GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_LONLAT; break; } - case GRIB1_GTYPE_LCC: { gridtype = GRID_LCC; break; } + case GRIB1_GTYPE_LATLON: { gridtype = GRID_LONLAT; break; } +#ifdef TEST_PROJECTION + case GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_PROJECTION; break; } +#else + case GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_LONLAT; break; } +#endif + case GRIB1_GTYPE_LCC: { gridtype = GRID_LCC; break; } case GRIB1_GTYPE_GAUSSIAN: { if ( ISEC2_Reduced ) gridtype = GRID_GAUSSIAN_REDUCED; else gridtype = GRID_GAUSSIAN; break; } - case GRIB1_GTYPE_SPECTRAL: { gridtype = GRID_SPECTRAL; break; } - case GRIB1_GTYPE_GME: { gridtype = GRID_GME; break; } + case GRIB1_GTYPE_SPECTRAL: { gridtype = GRID_SPECTRAL; break; } + case GRIB1_GTYPE_GME: { gridtype = GRID_GME; break; } } return gridtype; @@ -55,9 +59,7 @@ int cgribexGetGridType(int *isec2) static bool cgribexGetIsRotated(int *isec2) { - bool isRotated = (ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT) ? true : false; - - return isRotated; + return (ISEC2_GridType == GRIB1_GTYPE_LATLON_ROT); } static @@ -147,6 +149,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4, { bool compyinc = true; int gridtype = cgribexGetGridType(isec2); + int projtype = (gridtype == GRID_PROJECTION && cgribexGetIsRotated(isec2)) ? CDI_PROJ_RLL : CDI_UNDEFID; if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 ) { @@ -161,192 +164,178 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, double *fsec2, int *isec4, grid_init(grid); cdiGridTypeInit(grid, gridtype, 0); - switch (gridtype) + + if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL ) { - case GRID_LONLAT: - case GRID_GAUSSIAN: + if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat ) + Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat); + grid->size = ISEC4_NumValues; + grid->x.size = ISEC2_NumLon; + grid->y.size = ISEC2_NumLat; + if ( gridtype == GRID_GAUSSIAN ) grid->np = ISEC2_NumPar; + grid->x.inc = 0; + grid->y.inc = 0; + grid->x.flag = 0; + /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */ { - if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat ) - Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat); - grid->size = ISEC4_NumValues; - grid->xsize = ISEC2_NumLon; - grid->ysize = ISEC2_NumLat; - if ( gridtype == GRID_GAUSSIAN ) grid->np = ISEC2_NumPar; - grid->xinc = 0; - grid->yinc = 0; - grid->xdef = 0; - /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */ - { - if ( grid->xsize > 1 ) - { - bool recompinc = true; + if ( grid->x.size > 1 ) + { + bool recompinc = true; - if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000; + if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000; - if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 ) + if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 ) + { + if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->x.size-1))) <= 2 ) { - if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->xsize-1))) <= 2 ) - { - recompinc = false; - grid->xinc = ISEC2_LonIncr * 0.001; - } + recompinc = false; + grid->x.inc = ISEC2_LonIncr * 0.001; } + } - /* recompute xinc if necessary */ - if ( recompinc ) grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize-1); - - /* correct xinc if necessary */ - if ( ISEC2_FirstLon == 0 && ISEC2_LastLon > 354000 && ISEC2_LastLon < 360000 ) - { - double xinc = 360. / grid->xsize; + /* recompute xinc if necessary */ + if ( recompinc ) grid->x.inc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->x.size-1); - if ( fabs(grid->xinc-xinc) > 0.0 ) - { - grid->xinc = xinc; - if ( CDI_Debug ) Message("set xinc to %g", grid->xinc); - } - } - } - grid->xfirst = ISEC2_FirstLon * 0.001; - grid->xlast = ISEC2_LastLon * 0.001; - grid->xdef = 2; - } - grid->ydef = 0; - /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */ - { - if ( grid->ysize > 1 && compyinc ) - { - bool recompinc = true; - if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 ) + /* correct xinc if necessary */ + if ( ISEC2_FirstLon == 0 && ISEC2_LastLon > 354000 && ISEC2_LastLon < 360000 ) + { + double xinc = 360. / grid->x.size; + if ( fabs(grid->x.inc-xinc) > 0.0 ) { - if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->ysize-1))) <= 2 ) - { - recompinc = false; - grid->yinc = ISEC2_LatIncr * 0.001; - } + grid->x.inc = xinc; + if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc); } - - /* recompute yinc if necessary */ - if ( recompinc ) grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1); - } - grid->yfirst = ISEC2_FirstLat * 0.001; - grid->ylast = ISEC2_LastLat * 0.001; - grid->ydef = 2; - } - break; - } - case GRID_GAUSSIAN_REDUCED: - { - grid->np = ISEC2_NumPar; - grid->size = ISEC4_NumValues; - grid->rowlon = ISEC2_RowLonPtr; - grid->nrowlon = ISEC2_NumLat; - grid->ysize = ISEC2_NumLat; - grid->xinc = 0; - grid->yinc = 0; - grid->xdef = 0; - /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */ - { - if ( grid->xsize > 1 ) - { - if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000; - - if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 ) - grid->xinc = ISEC2_LonIncr * 0.001; - else - grid->xinc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->xsize - 1); - } - grid->xfirst = ISEC2_FirstLon * 0.001; - grid->xlast = ISEC2_LastLon * 0.001; - grid->xdef = 2; - } - grid->ydef = 0; - /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */ - { - if ( grid->ysize > 1 ) - { - if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 ) - grid->yinc = ISEC2_LatIncr * 0.001; - else - grid->yinc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->ysize - 1); - } - grid->yfirst = ISEC2_FirstLat * 0.001; - grid->ylast = ISEC2_LastLat * 0.001; - grid->ydef = 2; - } - break; + } + } + grid->x.first = ISEC2_FirstLon * 0.001; + grid->x.last = ISEC2_LastLon * 0.001; + grid->x.flag = 2; } - case GRID_LCC: + grid->y.flag = 0; + /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */ { - if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat ) - Error("numberOfPoints (%d) and gridSize (%d) differ!", - ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat); - - grid->size = ISEC4_NumValues; - grid->xsize = ISEC2_NumLon; - grid->ysize = ISEC2_NumLat; - - grid->lcc_xinc = ISEC2_Lambert_dx; - grid->lcc_yinc = ISEC2_Lambert_dy; - grid->lcc_originLon = ISEC2_FirstLon * 0.001; - grid->lcc_originLat = ISEC2_FirstLat * 0.001; - grid->lcc_lonParY = ISEC2_Lambert_Lov * 0.001; - grid->lcc_lat1 = ISEC2_Lambert_LatS1 * 0.001; - grid->lcc_lat2 = ISEC2_Lambert_LatS2 * 0.001; - grid->lcc_projflag = ISEC2_Lambert_ProjFlag; - grid->lcc_scanflag = ISEC2_ScanFlag; - - grid->xdef = 0; - grid->ydef = 0; + if ( grid->y.size > 1 && compyinc ) + { + bool recompinc = true; + if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 ) + { + if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->y.size-1))) <= 2 ) + { + recompinc = false; + grid->y.inc = ISEC2_LatIncr * 0.001; + } + } - break; + /* recompute yinc if necessary */ + if ( recompinc ) grid->y.inc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->y.size - 1); + } + grid->y.first = ISEC2_FirstLat * 0.001; + grid->y.last = ISEC2_LastLat * 0.001; + grid->y.flag = 2; } - case GRID_SPECTRAL: + } + else if ( gridtype == GRID_GAUSSIAN_REDUCED ) + { + grid->np = ISEC2_NumPar; + grid->size = ISEC4_NumValues; + grid->rowlon = ISEC2_RowLonPtr; + grid->nrowlon = ISEC2_NumLat; + grid->y.size = ISEC2_NumLat; + grid->x.inc = 0; + grid->y.inc = 0; + grid->x.flag = 0; + /* if ( ISEC2_FirstLon != 0 || ISEC2_LastLon != 0 ) */ { - grid->size = ISEC4_NumValues; - grid->trunc = ISEC2_PentaJ; - if ( ISEC2_RepMode == 2 ) - grid->lcomplex = 1; - else - grid->lcomplex = 0; + if ( grid->x.size > 1 ) + { + if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000; - break; - } - case GRID_GME: - { - grid->size = ISEC4_NumValues; - grid->nd = ISEC2_GME_ND; - grid->ni = ISEC2_GME_NI; - grid->ni2 = ISEC2_GME_NI2; - grid->ni3 = ISEC2_GME_NI3; - break; - } - case GRID_GENERIC: - { - grid->size = ISEC4_NumValues; - grid->xsize = 0; - grid->ysize = 0; - break; + if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 ) + grid->x.inc = ISEC2_LonIncr * 0.001; + else + grid->x.inc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->x.size - 1); + } + grid->x.first = ISEC2_FirstLon * 0.001; + grid->x.last = ISEC2_LastLon * 0.001; + grid->x.flag = 2; } - default: + grid->y.flag = 0; + /* if ( ISEC2_FirstLat != 0 || ISEC2_LastLat != 0 ) */ { - Error("Unsupported grid type: %s", gridNamePtr(gridtype)); - break; + if ( grid->y.size > 1 ) + { + if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 ) + grid->y.inc = ISEC2_LatIncr * 0.001; + else + grid->y.inc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->y.size - 1); + } + grid->y.first = ISEC2_FirstLat * 0.001; + grid->y.last = ISEC2_LastLat * 0.001; + grid->y.flag = 2; } } + else if ( gridtype == GRID_LCC ) + { + if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat ) + Error("numberOfPoints (%d) and gridSize (%d) differ!", + ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat); + + grid->size = ISEC4_NumValues; + grid->x.size = ISEC2_NumLon; + grid->y.size = ISEC2_NumLat; + + grid->lcc.xinc = ISEC2_Lambert_dx; + grid->lcc.yinc = ISEC2_Lambert_dy; + grid->lcc.originLon = ISEC2_FirstLon * 0.001; + grid->lcc.originLat = ISEC2_FirstLat * 0.001; + grid->lcc.lonParY = ISEC2_Lambert_Lov * 0.001; + grid->lcc.lat1 = ISEC2_Lambert_LatS1 * 0.001; + grid->lcc.lat2 = ISEC2_Lambert_LatS2 * 0.001; + grid->lcc.projflag = ISEC2_Lambert_ProjFlag; + grid->lcc.scanflag = ISEC2_ScanFlag; + + grid->x.flag = 0; + grid->y.flag = 0; + } + else if ( gridtype == GRID_SPECTRAL ) + { + grid->size = ISEC4_NumValues; + grid->trunc = ISEC2_PentaJ; + if ( ISEC2_RepMode == 2 ) + grid->lcomplex = 1; + else + grid->lcomplex = 0; + } + else if ( gridtype == GRID_GME ) + { + grid->size = ISEC4_NumValues; + grid->gme.nd = ISEC2_GME_ND; + grid->gme.ni = ISEC2_GME_NI; + grid->gme.ni2 = ISEC2_GME_NI2; + grid->gme.ni3 = ISEC2_GME_NI3; + } + else if ( gridtype == GRID_GENERIC ) + { + grid->size = ISEC4_NumValues; + grid->x.size = 0; + grid->y.size = 0; + } + else + { + Error("Unsupported grid type: %s", gridNamePtr(gridtype)); + } grid->isRotated = FALSE; if ( cgribexGetIsRotated(isec2) ) { grid->isRotated = TRUE; - grid->ypole = - ISEC2_LatSP*0.001; - grid->xpole = ISEC2_LonSP*0.001 - 180; - grid->angle = - FSEC2_RotAngle; + grid->rll.xpole = ISEC2_LonSP*0.001 - 180; + grid->rll.ypole = - ISEC2_LatSP*0.001; + grid->rll.angle = - FSEC2_RotAngle; } - grid->xvals = NULL; - grid->yvals = NULL; - grid->type = gridtype; + grid->type = gridtype; + grid->projtype = projtype; } static @@ -380,7 +369,7 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d grid_t *gridptr = (grid_t*) Malloc(sizeof(*gridptr)); cgribexGetGrid(streamptr, isec2, fsec2, isec4, gridptr, iret); - struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, gridptr, 0); + struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, gridptr, 0); int gridID = gridAdded.Id; if ( gridAdded.isNew ) { @@ -391,6 +380,13 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d gridptr->rowlon = (int*) Malloc(nrowlon * sizeof(int)); memcpy(gridptr->rowlon, rowlon, nrowlon * sizeof(int)); } + else if ( gridptr->projtype == CDI_PROJ_RLL ) + { + double xpole = ISEC2_LonSP*0.001 - 180; + double ypole = - ISEC2_LatSP*0.001; + double angle = - FSEC2_RotAngle; + gridDefProjParamRLL(gridID, xpole, ypole, angle); + } } else Free(gridptr); @@ -659,10 +655,10 @@ int cgribexScanTimestep1(stream_t * streamptr) rstatus = gribRead(fileID, (unsigned char *)gribbuffer, &readsize); if ( rstatus ) break; - comptype = COMPRESS_NONE; + comptype = CDI_COMPRESS_NONE; if ( gribGetZip(recsize, (unsigned char *)gribbuffer, &unzipsize) > 0 ) { - comptype = COMPRESS_SZIP; + comptype = CDI_COMPRESS_SZIP; unzipsize += 100; /* need 0 to 1 bytes for rounding of bds */ if ( buffersize < (size_t)unzipsize ) { @@ -1616,8 +1612,8 @@ void cgribexDefTime(int *isec1, int vdate, int vtime, int tsteptype, int numavg, static void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridID) { + bool lrotated = false; bool lcurvi = false; - static bool lwarning = true; memset(isec2, 0, 16*sizeof(int)); @@ -1655,6 +1651,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI } else if ( gridtype == GRID_CURVILINEAR ) { + static bool lwarning = true; if ( lwarning && gridInqSize(gridID) > 1 ) { lwarning = false; @@ -1664,6 +1661,12 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI lcurvi = true; } + if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL ) + { + gridtype = GRID_LONLAT; + lrotated = true; + } + ISEC2_Reduced = FALSE; ISEC2_ScanFlag = 0; @@ -1680,7 +1683,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED ) ISEC2_GridType = GRIB1_GTYPE_GAUSSIAN; - else if ( gridtype == GRID_LONLAT && isRotated ) + else if ( gridtype == GRID_LONLAT && (isRotated || lrotated) ) ISEC2_GridType = GRIB1_GTYPE_LATLON_ROT; else ISEC2_GridType = GRIB1_GTYPE_LATLON; @@ -1696,25 +1699,19 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI } else { - if ( nlon == 0 ) - { - nlon = 1; - } + if ( nlon == 0 ) nlon = 1; else { - xfirst = gridInqXval(gridID, 0); + xfirst = gridInqXval(gridID, 0); xlast = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1); xinc = gridInqXinc(gridID); } } - if ( nlat == 0 ) - { - nlat = 1; - } + if ( nlat == 0 ) nlat = 1; else { - yfirst = gridInqYval(gridID, 0); + yfirst = gridInqYval(gridID, 0); ylast = gridInqYval(gridID, (lcurvi ? nlon*nlat : nlat) - 1); yinc = fabs(gridInqYinc(gridID)); } @@ -1756,14 +1753,23 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI ISEC2_ResFlag = ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 ) ? 0 : 128; - if ( isRotated ) - { - ISEC2_LatSP = - (int)lround(gridInqYpole(gridID) * 1000); - ISEC2_LonSP = (int)lround((gridInqXpole(gridID) + 180) * 1000); - double angle = gridInqAngle(gridID); + if ( isRotated || lrotated ) + { + double xpole = 0, ypole = 0, angle = 0; + if ( isRotated ) + { + xpole = gridInqXpole(gridID); + ypole = gridInqYpole(gridID); + angle = gridInqAngle(gridID); + } + else + gridInqProjParamRLL(gridID, &xpole, &ypole, &angle); + + ISEC2_LatSP = - (int)lround(ypole * 1000); + ISEC2_LonSP = (int)lround((xpole + 180) * 1000); if ( fabs(angle) > 0 ) angle = -angle; FSEC2_RotAngle = angle; - } + } /* East -> West */ if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128; @@ -1849,6 +1855,14 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI } } +static +void isec1DefLevel(int *isec1, int leveltype, int level1, int level2) +{ + ISEC1_LevelType = leveltype; + ISEC1_Level1 = level1; + ISEC1_Level2 = level2; +} + static void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int levelID) { @@ -1861,8 +1875,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev if ( zaxistype == ZAXIS_GENERIC && ltype == 0 ) { Message("Changed zaxis type from %s to %s", - zaxisNamePtr(zaxistype), - zaxisNamePtr(ZAXIS_PRESSURE)); + zaxisNamePtr(zaxistype), zaxisNamePtr(ZAXIS_PRESSURE)); zaxistype = ZAXIS_PRESSURE; zaxisChangeType(zaxisID, zaxistype); zaxisDefUnits(zaxisID, "Pa"); @@ -1880,9 +1893,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev case ZAXIS_DEPTH_BELOW_SEA: case ZAXIS_ISENTROPIC: { - ISEC1_LevelType = grib_ltype; - ISEC1_Level1 = (int) (zaxisInqLevel(zaxisID, levelID)); - ISEC1_Level2 = 0; + isec1DefLevel(isec1, grib_ltype, (int) zaxisInqLevel(zaxisID, levelID), 0); break; } case ZAXIS_CLOUD_BASE: @@ -1892,26 +1903,17 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev case ZAXIS_SEA_BOTTOM: case ZAXIS_ATMOSPHERE: { - ISEC1_LevelType = grib_ltype; - ISEC1_Level1 = 0; - ISEC1_Level2 = 0; + isec1DefLevel(isec1, grib_ltype, 0, 0); break; } case ZAXIS_HYBRID: case ZAXIS_HYBRID_HALF: { if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - ISEC1_LevelType = GRIB1_LTYPE_HYBRID_LAYER; - ISEC1_Level1 = (int) (zaxisInqLbound(zaxisID, levelID)); - ISEC1_Level2 = (int) (zaxisInqUbound(zaxisID, levelID)); - } + isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID_LAYER, (int)zaxisInqLbound(zaxisID, levelID), + (int)zaxisInqUbound(zaxisID, levelID)); else - { - ISEC1_LevelType = GRIB1_LTYPE_HYBRID; - ISEC1_Level1 = (int) (zaxisInqLevel(zaxisID, levelID)); - ISEC1_Level2 = 0; - } + isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID, (int) zaxisInqLevel(zaxisID, levelID), 0); int vctsize = zaxisInqVctSize(zaxisID); if ( vctsize > 255 ) @@ -1933,8 +1935,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev case ZAXIS_PRESSURE: { level = zaxisInqLevel(zaxisID, levelID); - if ( level < 0 ) - Warning("Pressure level of %f Pa is below zero!", level); + if ( level < 0 ) Warning("Pressure level of %f Pa is below zero!", level); char units[128]; zaxisInqUnits(zaxisID, units); @@ -1942,16 +1943,11 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev double dum; if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) ) - { - grib_ltype = GRIB1_LTYPE_99; - } + grib_ltype = GRIB1_LTYPE_99; else - { - level = level/100; - } - ISEC1_LevelType = grib_ltype; - ISEC1_Level1 = (int) level; - ISEC1_Level2 = 0; + level = level/100; + + isec1DefLevel(isec1, grib_ltype, (int) level, 0); break; } case ZAXIS_HEIGHT: @@ -1967,26 +1963,16 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev else if ( units[0] == 'k' ) level *= 1000; } - ISEC1_LevelType = grib_ltype; - ISEC1_Level1 = (int) level; - ISEC1_Level2 = 0; - + isec1DefLevel(isec1, grib_ltype, (int) level, 0); break; } case ZAXIS_SIGMA: { if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - ISEC1_LevelType = GRIB1_LTYPE_SIGMA_LAYER; - ISEC1_Level1 = (int) zaxisInqLbound(zaxisID, levelID); - ISEC1_Level2 = (int) zaxisInqUbound(zaxisID, levelID); - } + isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA_LAYER, (int) zaxisInqLbound(zaxisID, levelID), + (int) zaxisInqUbound(zaxisID, levelID)); else - { - ISEC1_LevelType = GRIB1_LTYPE_SIGMA; - ISEC1_Level1 = (int) zaxisInqLevel(zaxisID, levelID); - ISEC1_Level2 = 0; - } + isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA, (int) zaxisInqLevel(zaxisID, levelID), 0); break; } @@ -2002,26 +1988,16 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev else factor = 100; // meter if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH_LAYER; - ISEC1_Level1 = (int) (factor*zaxisInqLbound(zaxisID, levelID)); - ISEC1_Level2 = (int) (factor*zaxisInqUbound(zaxisID, levelID)); - } + isec1DefLevel(isec1, GRIB1_LTYPE_LANDDEPTH_LAYER, (int) (factor*zaxisInqLbound(zaxisID, levelID)), + (int) (factor*zaxisInqUbound(zaxisID, levelID))); else - { - ISEC1_LevelType = GRIB1_LTYPE_LANDDEPTH; - ISEC1_Level1 = (int) (factor*zaxisInqLevel(zaxisID, levelID)); - ISEC1_Level2 = 0; - } + isec1DefLevel(isec1, GRIB1_LTYPE_LANDDEPTH, (int) (factor*zaxisInqLevel(zaxisID, levelID)), 0); break; } case ZAXIS_GENERIC: { - ISEC1_LevelType = ltype; - ISEC1_Level1 = (int) zaxisInqLevel(zaxisID, levelID); - ISEC1_Level2 = 0; - + isec1DefLevel(isec1, ltype, (int) zaxisInqLevel(zaxisID, levelID), 0); break; } default: diff --git a/src/stream_ext.c b/src/stream_ext.c index 048de7007e88ab6a5d1eca7f465a1ba76834707d..54d59f3fc29cc2d8c44a073d954419c3d4feb5c4 100644 --- a/src/stream_ext.c +++ b/src/stream_ext.c @@ -13,18 +13,16 @@ #include "cdi.h" #include "cdi_int.h" #include "stream_ext.h" -#include "stream_fcommon.h" #include "varscan.h" #include "datetime.h" #include "extra.h" #include "vlist.h" +#include "exse.h" #undef UNDEFID #define UNDEFID CDI_UNDEFID -#define SINGLE_PRECISION 4 -#define DOUBLE_PRECISION 8 #if defined (HAVE_LIBEXTRA) @@ -40,17 +38,11 @@ int extInqDatatype(int prec, int number) int datatype; if ( number == 2 ) - { - if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_CPX64; - else datatype = DATATYPE_CPX32; - } + datatype = (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_CPX64 : DATATYPE_CPX32; else - { - if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64; - else datatype = DATATYPE_FLT32; - } + datatype = (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_FLT64 : DATATYPE_FLT32; - return (datatype); + return datatype; } static @@ -61,15 +53,9 @@ void extDefDatatype(int datatype, int *prec, int *number) datatype != DATATYPE_CPX32 && datatype != DATATYPE_CPX64 ) datatype = DATATYPE_FLT32; - if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 ) - *number = 2; - else - *number = 1; + *number = (datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64) ? 2 : 1; - if ( datatype == DATATYPE_FLT64 || datatype == DATATYPE_CPX64 ) - *prec = DOUBLE_PRECISION; - else - *prec = SINGLE_PRECISION; + *prec = (datatype == DATATYPE_FLT64 || datatype == DATATYPE_CPX64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION; } /* not used @@ -90,7 +76,7 @@ int extInqRecord(stream_t *streamptr, int *varID, int *levelID) *levelID = -1; status = extRead(fileID, extp); - if ( status != 0 ) return (0); + if ( status != 0 ) return 0; extInqHeader(extp, header); @@ -105,49 +91,40 @@ int extInqRecord(stream_t *streamptr, int *varID, int *levelID) *levelID = zaxisInqLevelID(zaxisID, (double) ilevel); - return (1); + return 1; } */ void extReadRecord(stream_t *streamptr, double *data, int *nmiss) { - int vlistID, fileID; - int status; - int recID, vrecID, tsID; - off_t recpos; - int header[4]; - int varID, gridID; - int i, size; - double missval; - void *extp = streamptr->record->exsep; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - tsID = streamptr->curTsID; - vrecID = streamptr->tsteps[tsID].curRecID; - recID = streamptr->tsteps[tsID].recIDs[vrecID]; - recpos = streamptr->tsteps[tsID].records[recID].position; - varID = streamptr->tsteps[tsID].records[recID].varID; + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + int tsID = streamptr->curTsID; + int vrecID = streamptr->tsteps[tsID].curRecID; + int recID = streamptr->tsteps[tsID].recIDs[vrecID]; + int varID = streamptr->tsteps[tsID].records[recID].varID; + off_t recpos = streamptr->tsteps[tsID].records[recID].position; fileSetPos(fileID, recpos, SEEK_SET); - status = extRead(fileID, extp); - if ( status != 0 ) - Error("Failed to read EXTRA record"); + void *extp = streamptr->record->exsep; + int status = extRead(fileID, extp); + if ( status != 0 ) Error("Failed to read EXTRA record"); + int header[4]; extInqHeader(extp, header); extInqDataDP(extp, data); - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - size = gridInqSize(gridID); + double missval = vlistInqVarMissval(vlistID, varID); + int gridID = vlistInqVarGrid(vlistID, varID); + int size = gridInqSize(gridID); streamptr->numvals += size; *nmiss = 0; if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL ) { - for ( i = 0; i < size; i++ ) + for ( int i = 0; i < size; i++ ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -156,7 +133,7 @@ void extReadRecord(stream_t *streamptr, double *data, int *nmiss) } else { - for ( i = 0; i < 2*size; i+=2 ) + for ( int i = 0; i < 2*size; i+=2 ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -174,21 +151,18 @@ void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1) void extDefRecord(stream_t *streamptr) { - int gridID; - int header[4]; int pdis, pcat, pnum; - extrec_t *extp = (extrec_t*) streamptr->record->exsep; - - gridID = streamptr->record->gridID; - cdiDecodeParam(streamptr->record->param, &pnum, &pcat, &pdis); + + int header[4]; header[0] = streamptr->record->date; header[1] = pnum; header[2] = streamptr->record->level; + int gridID = streamptr->record->gridID; header[3] = gridInqSize(gridID); + extrec_t *extp = (extrec_t*) streamptr->record->exsep; extDefDatatype(streamptr->record->prec, &extp->prec, &extp->number); - extDefHeader(extp, header); } @@ -219,11 +193,9 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize, grid_t *grid = (grid_t *)Malloc(sizeof (*grid)); grid_init(grid); cdiGridTypeInit(grid, GRID_GENERIC, xysize); - grid->xsize = xysize; - grid->ysize = 0; - grid->xvals = NULL; - grid->yvals = NULL; - struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); + grid->x.size = xysize; + grid->y.size = 0; + struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); int gridID = gridAdded.Id; if (!gridAdded.isNew) Free(grid); /* @@ -243,46 +215,36 @@ void extAddRecord(stream_t *streamptr, int param, int level, int xysize, streamptr->nrecs++; if ( CDI_Debug ) - Message("varID = %d gridID = %d levelID = %d", - varID, gridID, levelID); + Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID); } static void extScanTimestep1(stream_t *streamptr) { int header[4]; - int status; - int fileID; - int rxysize = 0; - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; DateTime datetime0 = { LONG_MIN, LONG_MIN }; - int tsID; int varID; + off_t recpos = 0; long recsize; - off_t recpos; - int nrecords, nrecs, recID; - int taxisID = -1; - taxis_t *taxis; - int vlistID; + int recID; extcompvar_t compVar, compVar0; extrec_t *extp = (extrec_t*) streamptr->record->exsep; streamptr->curTsID = 0; - tsID = tstepsNewEntry(streamptr); - taxis = &streamptr->tsteps[tsID].taxis; + int tsID = tstepsNewEntry(streamptr); + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; if ( tsID != 0 ) Error("Internal problem! tstepsNewEntry returns %d", tsID); - fileID = streamptr->fileID; + int fileID = streamptr->fileID; - nrecs = 0; + int nrecs = 0; while ( TRUE ) { recpos = fileGetPos(fileID); - status = extRead(fileID, extp); + int status = extRead(fileID, extp); if ( status != 0 ) { streamptr->ntsteps = 1; @@ -292,13 +254,13 @@ void extScanTimestep1(stream_t *streamptr) extInqHeader(extp, header); - vdate = header[0]; - vtime = 0; - rcode = header[1]; - rlevel = header[2]; - rxysize = header[3]; + int vdate = header[0]; + int vtime = 0; + int rcode = header[1]; + int rlevel = header[2]; + int rxysize = header[3]; - param = cdiEncodeParam(rcode, 255, 255); + int param = cdiEncodeParam(rcode, 255, 255); if ( nrecs == 0 ) { @@ -334,17 +296,17 @@ void extScanTimestep1(stream_t *streamptr) cdi_generate_vars(streamptr); - taxisID = taxisCreate(TAXIS_ABSOLUTE); + int taxisID = taxisCreate(TAXIS_ABSOLUTE); taxis->type = TAXIS_ABSOLUTE; taxis->vdate = (int)datetime0.date; taxis->vtime = (int)datetime0.time; - vlistID = streamptr->vlistID; + int vlistID = streamptr->vlistID; vlistDefTaxis(vlistID, taxisID); vlist_check_contents(vlistID); - nrecords = streamptr->tsteps[0].nallrecs; + int nrecords = streamptr->tsteps[0].nallrecs; if ( nrecords < streamptr->tsteps[0].recordSize ) { streamptr->tsteps[0].recordSize = nrecords; @@ -384,43 +346,33 @@ static int extScanTimestep2(stream_t *streamptr) { int header[4]; - int status; - int fileID; - // int rxysize = 0; - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; - int tsID; int varID; off_t recpos = 0; - int nrecords, nrecs, recID, rindex; - int nextstep; - taxis_t *taxis; - int vlistID; extcompvar_t compVar, compVar0; void *extp = streamptr->record->exsep; streamptr->curTsID = 1; - fileID = streamptr->fileID; - vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + int vlistID = streamptr->vlistID; - tsID = streamptr->rtsteps; + int tsID = streamptr->rtsteps; if ( tsID != 1 ) Error("Internal problem! unexpected timestep %d", tsID+1); - taxis = &streamptr->tsteps[tsID].taxis; + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET); cdi_create_records(streamptr, tsID); - nrecords = streamptr->tsteps[0].nallrecs; + int nrecords = streamptr->tsteps[0].nallrecs; streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int)); streamptr->tsteps[1].nrecs = 0; - for ( recID = 0; recID < nrecords; recID++ ) + for ( int recID = 0; recID < nrecords; recID++ ) streamptr->tsteps[1].recIDs[recID] = -1; - for ( recID = 0; recID < nrecords; recID++ ) + for ( int recID = 0; recID < nrecords; recID++ ) { varID = streamptr->tsteps[0].records[recID].varID; streamptr->tsteps[tsID].records[recID].position = @@ -429,10 +381,10 @@ int extScanTimestep2(stream_t *streamptr) streamptr->tsteps[0].records[recID].size; } - for ( rindex = 0; rindex <= nrecords; rindex++ ) + for ( int rindex = 0; rindex <= nrecords; rindex++ ) { recpos = fileGetPos(fileID); - status = extRead(fileID, extp); + int status = extRead(fileID, extp); if ( status != 0 ) { streamptr->ntsteps = 2; @@ -442,13 +394,13 @@ int extScanTimestep2(stream_t *streamptr) extInqHeader(extp, header); - vdate = header[0]; - vtime = 0; - rcode = header[1]; - rlevel = header[2]; + int vdate = header[0]; + int vtime = 0; + int rcode = header[1]; + int rlevel = header[2]; // rxysize = header[3]; - param = cdiEncodeParam(rcode, 255, 255); + int param = cdiEncodeParam(rcode, 255, 255); if ( rindex == 0 ) { @@ -459,7 +411,8 @@ int extScanTimestep2(stream_t *streamptr) compVar.param = param; compVar.level = rlevel; - nextstep = FALSE; + bool nextstep = false; + int recID; for ( recID = 0; recID < nrecords; recID++ ) { compVar0.param = streamptr->tsteps[tsID].records[recID].param; @@ -469,7 +422,7 @@ int extScanTimestep2(stream_t *streamptr) { if ( streamptr->tsteps[tsID].records[recID].used ) { - nextstep = TRUE; + nextstep = true; } else { @@ -482,7 +435,7 @@ int extScanTimestep2(stream_t *streamptr) if ( recID == nrecords ) { Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1); - return (CDI_EUFSTRUCT); + return CDI_EUFSTRUCT; } if ( nextstep ) break; @@ -501,14 +454,14 @@ int extScanTimestep2(stream_t *streamptr) tsID, recID, streamptr->tsteps[tsID].records[recID].param, param, streamptr->tsteps[tsID].records[recID].ilevel, rlevel); - return (CDI_EUFSTRUCT); + return CDI_EUFSTRUCT; } streamptr->tsteps[1].records[recID].position = recpos; } - nrecs = 0; - for ( recID = 0; recID < nrecords; recID++ ) + int nrecs = 0; + for ( int recID = 0; recID < nrecords; recID++ ) { if ( ! streamptr->tsteps[tsID].records[recID].used ) { @@ -534,40 +487,32 @@ int extScanTimestep2(stream_t *streamptr) streamptr->tsteps[tsID].position = recpos; } - return (0); + return 0; } int extInqContents(stream_t *streamptr) { - int fileID; - int status = 0; - - fileID = streamptr->fileID; - streamptr->curTsID = 0; extScanTimestep1(streamptr); + int status = 0; if ( streamptr->ntsteps == -1 ) status = extScanTimestep2(streamptr); + int fileID = streamptr->fileID; fileSetPos(fileID, 0, SEEK_SET); - return (status); + return status; } static long extScanTimestep(stream_t *streamptr) { int header[4]; - int status; - int fileID; - // int rxysize = 0; - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; off_t recpos = 0; int recID; - int rindex, nrecs = 0; + int nrecs = 0; extcompvar_t compVar, compVar0; void *extp = streamptr->record->exsep; /* @@ -594,14 +539,14 @@ long extScanTimestep(stream_t *streamptr) for ( recID = 0; recID < nrecs; recID++ ) streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID]; - fileID = streamptr->fileID; + int fileID = streamptr->fileID; fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET); - for ( rindex = 0; rindex <= nrecs; rindex++ ) + for ( int rindex = 0; rindex <= nrecs; rindex++ ) { recpos = fileGetPos(fileID); - status = extRead(fileID, extp); + int status = extRead(fileID, extp); if ( status != 0 ) { streamptr->ntsteps = streamptr->rtsteps + 1; @@ -611,13 +556,13 @@ long extScanTimestep(stream_t *streamptr) extInqHeader(extp, header); - vdate = header[0]; - vtime = 0; - rcode = header[1]; - rlevel = header[2]; + int vdate = header[0]; + int vtime = 0; + int rcode = header[1]; + int rlevel = header[2]; // rxysize = header[3]; - param = cdiEncodeParam(rcode, 255, 255); + int param = cdiEncodeParam(rcode, 255, 255); // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error if ( rindex == nrecs ) continue; @@ -673,131 +618,54 @@ long extScanTimestep(stream_t *streamptr) streamptr->ntsteps = tsID; } - return (streamptr->ntsteps); + return streamptr->ntsteps; } int extInqTimestep(stream_t *streamptr, int tsID) { - int nrecs; - long ntsteps; - if ( tsID == 0 && streamptr->rtsteps == 0 ) Error("Call to cdiInqContents missing!"); if ( CDI_Debug ) Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps); - ntsteps = UNDEFID; + long ntsteps = UNDEFID; while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID ) ntsteps = extScanTimestep(streamptr); - if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID ) - { - nrecs = 0; - } - else + int nrecs = 0; + if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID) ) { streamptr->curTsID = tsID; nrecs = streamptr->tsteps[tsID].nrecs; } - return (nrecs); -} - - -void extReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss) -{ - int vlistID, fileID; - int levID, nlevs, gridID, gridsize; - off_t recpos, currentfilepos; - int header[4]; - int tsid; - int recID; - int i; - double missval; - void *extp = streamptr->record->exsep; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - /* NOTE: tiles are not supported here! */ - nlevs = streamptr->vars[varID].recordTable[0].nlevs; - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - tsid = streamptr->curTsID; - - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize); - - currentfilepos = fileGetPos(fileID); - - for (levID = 0; levID < nlevs; levID++) - { - /* NOTE: tiles are not supported here! */ - recID = streamptr->vars[varID].recordTable[0].recordID[levID]; - recpos = streamptr->tsteps[tsid].records[recID].position; - fileSetPos(fileID, recpos, SEEK_SET); - extRead(fileID, extp); - extInqHeader(extp, header); - extInqDataDP(extp, &data[levID*gridsize]); - } - fileSetPos(fileID, currentfilepos, SEEK_SET); - - *nmiss = 0; - if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL ) - { - for ( i = 0; i < nlevs*gridsize; i++ ) - if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) - { - data[i] = missval; - (*nmiss)++; - } - } - else - { - for ( i = 0; i < 2*nlevs*gridsize; i+=2 ) - if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) - { - data[i] = missval; - (*nmiss)++; - } - } + return nrecs; } void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss) { - int vlistID, fileID; - int nlevs, gridID, gridsize; - off_t recpos, currentfilepos; - int header[4]; - int tsid; - int recID; - int i; - double missval; + if ( CDI_Debug ) Message("streamID = %d varID = %d levID = %d", streamptr->self, varID, levID); + void *extp = streamptr->record->exsep; - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; /* NOTE: tiles are not supported here! */ - nlevs = streamptr->vars[varID].recordTable[0].nlevs; - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - tsid = streamptr->curTsID; + double missval = vlistInqVarMissval(vlistID, varID); + int gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID)); + int tsid = streamptr->curTsID; - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", - nlevs, gridID, gridsize); - - currentfilepos = fileGetPos(fileID); + off_t currentfilepos = fileGetPos(fileID); /* NOTE: tiles are not supported here! */ - recID = streamptr->vars[varID].recordTable[0].recordID[levID]; - recpos = streamptr->tsteps[tsid].records[recID].position; + int recID = streamptr->vars[varID].recordTable[0].recordID[levID]; + off_t recpos = streamptr->tsteps[tsid].records[recID].position; fileSetPos(fileID, recpos, SEEK_SET); extRead(fileID, extp); + int header[4]; extInqHeader(extp, header); extInqDataDP(extp, data); @@ -806,7 +674,7 @@ void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, *nmiss = 0; if ( vlistInqVarNumber(vlistID, varID) == CDI_REAL ) { - for ( i = 0; i < gridsize; i++ ) + for ( int i = 0; i < gridsize; i++ ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -815,7 +683,7 @@ void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, } else { - for ( i = 0; i < 2*gridsize; i+=2 ) + for ( int i = 0; i < 2*gridsize; i+=2 ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -825,88 +693,59 @@ void extReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, } -void extWriteVarDP(stream_t *streamptr, int varID, const double *data) +void extReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss) { - int fileID; - int levID, nlevs, gridID, gridsize; - int zaxisID; - double level; - int header[4]; - int tsID; - int vlistID; - int pdis, pcat, pnum; - extrec_t *extp = (extrec_t*) streamptr->record->exsep; - if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID); - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - tsID = streamptr->curTsID; - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - zaxisID = vlistInqVarZaxis(vlistID, varID); - nlevs = zaxisInqSize(zaxisID); - - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize); - - cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis); - - header[0] = streamptr->tsteps[tsID].taxis.vdate; - header[1] = pnum; - header[3] = gridInqSize(gridID); - - extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number); - - for ( levID = 0; levID < nlevs; levID++ ) - { - level = zaxisInqLevel(zaxisID, levID); + int vlistID = streamptr->vlistID; + size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID)); + size_t nlevs = (size_t) streamptr->vars[varID].recordTable[0].nlevs; - header[2] = (int) level; - extDefHeader(extp, header); - extDefDataDP(extp, &data[levID*gridsize]); - extWrite(fileID, extp); - } + for ( size_t levID = 0; levID < nlevs; levID++) + extReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss); } void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data) { - int fileID; - int gridID; - int zaxisID; - double level; - int header[4]; - int tsID; - int vlistID; - int pdis, pcat, pnum; - extrec_t *extp = (extrec_t*) streamptr->record->exsep; + if ( CDI_Debug ) Message("streamID = %d varID = %d levID = %d", streamptr->self, varID, levID); - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - tsID = streamptr->curTsID; - gridID = vlistInqVarGrid(vlistID, varID); - zaxisID = vlistInqVarZaxis(vlistID, varID); - level = zaxisInqLevel(zaxisID, levID); - - if ( CDI_Debug ) - Message("gridID = %d zaxisID = %d", gridID, zaxisID); + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + int tsID = streamptr->curTsID; + int pdis, pcat, pnum; cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis); + int header[4]; header[0] = streamptr->tsteps[tsID].taxis.vdate; header[1] = pnum; - header[2] = (int) level; - header[3] = gridInqSize(gridID); + header[2] = (int) zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID); + header[3] = gridInqSize(vlistInqVarGrid(vlistID, varID)); + extrec_t *extp = (extrec_t*) streamptr->record->exsep; extDefDatatype(vlistInqVarDatatype(vlistID, varID), &extp->prec, &extp->number); - extDefHeader(extp, header); + extDefDataDP(extp, data); extWrite(fileID, extp); } + +void extWriteVarDP(stream_t *streamptr, int varID, const double *data) +{ + if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID); + + int vlistID = streamptr->vlistID; + size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID)); + size_t nlevs = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID)); + + for ( size_t levID = 0; levID < nlevs; levID++ ) + extWriteVarSliceDP(streamptr, varID, levID, &data[levID*gridsize]); +} + #endif /* HAVE_LIBEXTRA */ + /* * Local Variables: * c-file-style: "Java" diff --git a/src/stream_fcommon.c b/src/stream_fcommon.c deleted file mode 100644 index 482a031675146499babeb217d472bd68927deb24..0000000000000000000000000000000000000000 --- a/src/stream_fcommon.c +++ /dev/null @@ -1,42 +0,0 @@ -#include <stdlib.h> - -#include "cdi_int.h" -#include "dmemory.h" -#include "file.h" -#include "stream_fcommon.h" - - -void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name) -{ - int fileID1 = streamptr1->fileID; - int fileID2 = streamptr2->fileID; - - int tsID = streamptr1->curTsID; - int vrecID = streamptr1->tsteps[tsID].curRecID; - int recID = streamptr1->tsteps[tsID].recIDs[vrecID]; - off_t recpos = streamptr1->tsteps[tsID].records[recID].position; - size_t recsize = streamptr1->tsteps[tsID].records[recID].size; - - if (fileSetPos(fileID1, recpos, SEEK_SET) != 0) - Error("Cannot seek input file for %s record copy!", container_name); - - char *buffer = (char *) Malloc(recsize); - - if (fileRead(fileID1, buffer, recsize) != recsize) - Error("Failed to read record from %s file for copying!", container_name); - - if (fileWrite(fileID2, buffer, recsize) != recsize) - Error("Failed to write record to %s file when copying!", container_name); - - Free(buffer); -} - -/* - * Local Variables: - * c-file-style: "Java" - * c-basic-offset: 2 - * indent-tabs-mode: nil - * show-trailing-whitespace: t - * require-trailing-newline: t - * End: - */ diff --git a/src/stream_fcommon.h b/src/stream_fcommon.h deleted file mode 100644 index f021f8644625f27a9fa9258929132089452634b9..0000000000000000000000000000000000000000 --- a/src/stream_fcommon.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef STREAM_FCOMMON_H -#define STREAM_FCOMMON_H - -#ifndef _CDI_INT_H -#include "cdi_int.h" -#endif - -void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, - const char *container_name); - -#endif -/* - * Local Variables: - * c-file-style: "Java" - * c-basic-offset: 2 - * indent-tabs-mode: nil - * show-trailing-whitespace: t - * require-trailing-newline: t - * End: - */ diff --git a/src/stream_gribapi.c b/src/stream_gribapi.c index 8189a769583a2fd37adee4b8fa12a1dfd3fe8e9c..0fc59acdef91b8589364e1e06d2c5e8b5376de27 100644 --- a/src/stream_gribapi.c +++ b/src/stream_gribapi.c @@ -459,12 +459,24 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh, // I. e. kick the fixed size array and allocate enough space, whatever that may be. strncpy(record->varname, varname, sizeof(record->varname)); - grid_t *grid = (grid_t *)Malloc(sizeof (*grid)); + grid_t *grid = (grid_t *)Malloc(sizeof(*grid)); gribapiGetGrid(gh, grid); - struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); + struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); int gridID = gridAdded.Id; - if (!gridAdded.isNew) Free(grid); + if ( !gridAdded.isNew ) Free(grid); + else if ( grid->projtype == CDI_PROJ_RLL ) + { + double xpole = 0, ypole = 0, angle = 0; + grib_get_double(gh, "latitudeOfSouthernPoleInDegrees", &ypole); + grib_get_double(gh, "longitudeOfSouthernPoleInDegrees", &xpole); + grib_get_double(gh, "angleOfRotation", &angle); + xpole = xpole - 180; + if ( fabs(ypole) > 0 ) ypole = -ypole; // change from south to north pole + if ( fabs(angle) > 0 ) angle = -angle; + + gridDefProjParamRLL(gridID, xpole, ypole, angle); + } int zaxistype = gribapiGetZaxisType(gribEditionNumber(gh), leveltype1); @@ -693,8 +705,8 @@ grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, vo if ( grib_get_string(gh, "packingType", typeOfPacking, &len) == 0 ) { // fprintf(stderr, "packingType %d %s\n", len, typeOfPacking); - if ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) *outCompressionType = COMPRESS_JPEG; - else if ( strncmp(typeOfPacking, "grid_ccsds", len) == 0 ) *outCompressionType = COMPRESS_SZIP; + if ( strncmp(typeOfPacking, "grid_jpeg", len) == 0 ) *outCompressionType = CDI_COMPRESS_JPEG; + else if ( strncmp(typeOfPacking, "grid_ccsds", len) == 0 ) *outCompressionType = CDI_COMPRESS_SZIP; else if ( strncmp(typeOfPacking, "grid_ieee", len) == 0 ) lieee = true; } } @@ -702,12 +714,12 @@ grib_handle *gribapiGetDiskRepresentation(size_t recsize, size_t *buffersize, vo { if( gribGetZip((long)recsize, *gribbuffer, outUnzipsize) > 0 ) { - *outCompressionType = COMPRESS_SZIP; + *outCompressionType = CDI_COMPRESS_SZIP; ensureBufferSize((size_t)*outUnzipsize + 100, buffersize, gribbuffer); } else { - *outCompressionType = COMPRESS_NONE; + *outCompressionType = CDI_COMPRESS_NONE; } } @@ -1663,7 +1675,7 @@ void gribapiDefStepUnits(int editionNumber, grib_handle *gh, int timeunit, int p else if ( grib2ProDefTempHasStatisticalDef(proDefTempNum) ) { GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitForTimeRange", unitsOfTime), 0); - // GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0); + GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0); } else { @@ -1842,13 +1854,13 @@ getGribApiCompTypeMsg(grib_handle *gh, int comptype, int gridsize) const char *mesg; size_t len; - if ( comptype == COMPRESS_JPEG && gridsize > 1 ) + if ( comptype == CDI_COMPRESS_JPEG && gridsize > 1 ) { static const char mesg_grid_jpeg[] = "grid_jpeg"; len = sizeof (mesg_grid_jpeg) - 1; mesg = mesg_grid_jpeg; } - else if ( comptype == COMPRESS_SZIP && gridsize > 1 ) + else if ( comptype == CDI_COMPRESS_SZIP && gridsize > 1 ) { static const char mesg_grid_ccsds[] = "grid_ccsds"; len = sizeof (mesg_grid_ccsds) - 1; @@ -1869,6 +1881,8 @@ static void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype, bool lieee, int datatype, int nmiss, int gcinit) { UNUSED(nmiss); + bool lrotated = false; + bool lcurvi = false; int gridtype = gridInqType(gridID); int gridsize = gridInqSize(gridID); @@ -1904,13 +1918,20 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype } else if ( gridtype == GRID_CURVILINEAR ) { - static bool lwarn = true; - if ( lwarn && gridsize > 1 ) + static bool lwarning = true; + if ( lwarning && gridsize > 1 ) { - lwarn = false; + lwarning = false; Warning("Curvilinear grids are unsupported in GRIB format! Created wrong Grid Description Section!"); } gridtype = GRID_LONLAT; + lcurvi = true; + } + + if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL ) + { + gridtype = GRID_LONLAT; + lrotated = true; } if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN ) @@ -1940,43 +1961,39 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype double yfirst = 0, ylast = 0, yinc = 0; double latIncr; - { - const char *mesg; - size_t len; - if ( gridtype == GRID_GAUSSIAN ) - { - static const char mesg_gaussian[] = "regular_gg"; - len = sizeof (mesg_gaussian) - 1; - mesg = mesg_gaussian; - } - else if ( gridtype == GRID_GAUSSIAN_REDUCED ) - { - static const char mesg_gaussian_reduced[] = "reduced_gg"; - len = sizeof (mesg_gaussian_reduced) - 1; - mesg = mesg_gaussian_reduced; - } - else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) ) - { - static const char mesg_rot_lonlat[] = "rotated_ll"; - len = sizeof (mesg_rot_lonlat) - 1; - mesg = mesg_rot_lonlat; - } - else - { - static const char mesg_regular_ll[] = "regular_ll"; - len = sizeof (mesg_regular_ll) - 1; - mesg = mesg_regular_ll; - } - GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0); - } + const char *mesg; + size_t len; + if ( gridtype == GRID_GAUSSIAN ) + { + static const char mesg_gaussian[] = "regular_gg"; + len = sizeof(mesg_gaussian) - 1; + mesg = mesg_gaussian; + } + else if ( gridtype == GRID_GAUSSIAN_REDUCED ) + { + static const char mesg_gaussian_reduced[] = "reduced_gg"; + len = sizeof(mesg_gaussian_reduced) - 1; + mesg = mesg_gaussian_reduced; + } + else if ( gridtype == GRID_LONLAT && (gridIsRotated(gridID) || lrotated) ) + { + static const char mesg_rot_lonlat[] = "rotated_ll"; + len = sizeof(mesg_rot_lonlat) - 1; + mesg = mesg_rot_lonlat; + } + else + { + static const char mesg_regular_ll[] = "regular_ll"; + len = sizeof(mesg_regular_ll) - 1; + mesg = mesg_regular_ll; + } + GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0); long nlon = gridInqXsize(gridID); long nlat = gridInqYsize(gridID); if ( gridtype == GRID_GAUSSIAN_REDUCED ) { - //GRIB_CHECK(my_grib_set_long(gh, "numberOfValues", gridsize), 0); - nlon = 0; int *rowlon = (int *) Malloc((size_t)nlat*sizeof(int)); @@ -1995,26 +2012,20 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype } else { - if ( nlon == 0 ) - { - nlon = 1; - } + if ( nlon == 0 ) nlon = 1; else { - xfirst = gridInqXval(gridID, 0); - xlast = gridInqXval(gridID, nlon-1); + xfirst = gridInqXval(gridID, 0); + xlast = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1); xinc = gridInqXinc(gridID); } } - if ( nlat == 0 ) - { - nlat = 1; - } + if ( nlat == 0 ) nlat = 1; else { - yfirst = gridInqYval(gridID, 0); - ylast = gridInqYval(gridID, nlat-1); + yfirst = gridInqYval(gridID, 0); + ylast = gridInqYval(gridID, (lcurvi ? nlon*nlat : nlat) - 1); yinc = gridInqYinc(gridID); } @@ -2032,10 +2043,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype if ( yfirst < ylast ) jscan = 1; GRIB_CHECK(my_grib_set_long(gh, "jScansPositively", jscan), 0); } - /* - if ( fabs(xinc*1000 - ISEC2_LonIncr) > FLT_EPSILON ) - ISEC2_LonIncr = 0; - */ + if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED ) { int np = gridInqNP(gridID); @@ -2047,67 +2055,46 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype latIncr = yinc; if ( latIncr < 0 ) latIncr = -latIncr; GRIB_CHECK(my_grib_set_double(gh, "jDirectionIncrementInDegrees", latIncr), 0); - /* - if ( fabs(yinc*1000 - ISEC2_LatIncr) > FLT_EPSILON ) - ISEC2_LatIncr = 0; - */ } - /* - if ( ISEC2_NumLon > 1 && ISEC2_NumLat == 1 ) - if ( ISEC2_LonIncr != 0 && ISEC2_LatIncr == 0 ) ISEC2_LatIncr = ISEC2_LonIncr; - if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 ) - if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr; - - if ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 ) - ISEC2_ResFlag = 0; - else - ISEC2_ResFlag = 128; - */ - if ( gridIsRotated(gridID) ) + if ( gridIsRotated(gridID) || lrotated ) { - double xpole = gridInqXpole(gridID); - double ypole = gridInqYpole(gridID); - double angle = gridInqAngle(gridID); - /* change from north to south pole */ - if ( fabs(ypole) > 0 ) ypole = -ypole; - xpole = xpole + 180; - if ( fabs(angle) > 0 ) angle = -angle; - GRIB_CHECK(my_grib_set_double(gh, "latitudeOfSouthernPoleInDegrees", ypole), 0); - GRIB_CHECK(my_grib_set_double(gh, "longitudeOfSouthernPoleInDegrees", xpole), 0); - GRIB_CHECK(my_grib_set_double(gh, "angleOfRotation", angle), 0); - } - - /* East -> West */ - //if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128; + double xpole = 0, ypole = 0, angle = 0; + if ( gridIsRotated(gridID) ) + { + xpole = gridInqXpole(gridID); + ypole = gridInqYpole(gridID); + angle = gridInqAngle(gridID); + } + else + gridInqProjParamRLL(gridID, &xpole, &ypole, &angle); - /* South -> North */ - //if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64; + xpole = xpole + 180; + if ( fabs(ypole) > 0 ) ypole = -ypole; // change from north to south pole + if ( fabs(angle) > 0 ) angle = -angle; + GRIB_CHECK(my_grib_set_double(gh, "latitudeOfSouthernPoleInDegrees", ypole), 0); + GRIB_CHECK(my_grib_set_double(gh, "longitudeOfSouthernPoleInDegrees", xpole), 0); + GRIB_CHECK(my_grib_set_double(gh, "angleOfRotation", angle), 0); + } if ( editionNumber != 2 ) { lieee = false; comptype = 0; } - { - const char *mesg; - size_t len; - if ( lieee ) - { - static const char mesg_grid_ieee[] = "grid_ieee"; - len = sizeof (mesg_grid_ieee) - 1; - mesg = mesg_grid_ieee; - } - else - { - struct gribApiMsg gaMsg - = getGribApiCompTypeMsg(gh, comptype, gridsize); - len = gaMsg.msgLen; - mesg = gaMsg.msg; - } - GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0); - if ( lieee ) - GRIB_CHECK(my_grib_set_long(gh, "precision", - datatype == DATATYPE_FLT64 ? 2 : 1), 0); - - } + if ( lieee ) + { + static const char mesg_grid_ieee[] = "grid_ieee"; + len = sizeof (mesg_grid_ieee) - 1; + mesg = mesg_grid_ieee; + } + else + { + struct gribApiMsg gaMsg = getGribApiCompTypeMsg(gh, comptype, gridsize); + len = gaMsg.msgLen; + mesg = gaMsg.msg; + } + GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0); + if ( lieee ) + GRIB_CHECK(my_grib_set_long(gh, "precision", + datatype == DATATYPE_FLT64 ? 2 : 1), 0); break; } @@ -2202,7 +2189,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridsize), 0); GRIB_CHECK(my_grib_set_long(gh, "totalNumberOfGridPoints", gridsize), 0); - if ( comptype == COMPRESS_SZIP ) + if ( comptype == CDI_COMPRESS_SZIP ) { static const char mesg[] = "grid_ccsds"; size_t len = sizeof (mesg) -1; @@ -2238,7 +2225,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype Warning("Can't write UUID!"); } - if ( comptype == COMPRESS_SZIP ) + if ( comptype == CDI_COMPRESS_SZIP ) { static const char mesg[] = "grid_ccsds"; size_t len = sizeof (mesg) -1; @@ -2614,7 +2601,7 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI long editionNumber = 2; char name[256]; char stdname[256]; - gribContainer_t *gc = (gribContainer_t *) gribContainer; + // extern unsigned char _grib_template_GRIB2[]; int param = vlistInqVarParam(vlistID, varID); @@ -2628,8 +2615,11 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI #if defined(GRIBAPIENCODETEST) grib_handle *gh = (grib_handle *) gribHandleNew(editionNumber); #else + gribContainer_t *gc = (gribContainer_t *) gribContainer; + assert(gc != NULL); grib_handle *gh = (struct grib_handle *)gc->gribHandle; #endif + GRIB_CHECK(grib_get_long(gh, "editionNumber", &editionNumber), 0); if ( editionNumber == 2 ) diff --git a/src/stream_ieg.c b/src/stream_ieg.c index 20c08f97ccf306ea72b27861d46d4e65c071105c..4696222924ac4e15735d83dde3364fa6e398bf43 100644 --- a/src/stream_ieg.c +++ b/src/stream_ieg.c @@ -19,16 +19,14 @@ #include "varscan.h" #include "datetime.h" #include "ieg.h" -#include "stream_fcommon.h" #include "stream_ieg.h" #include "vlist.h" +#include "exse.h" #undef UNDEFID #define UNDEFID CDI_UNDEFID -#define SINGLE_PRECISION 4 -#define DOUBLE_PRECISION 8 #if defined (HAVE_LIBIEG) @@ -36,34 +34,25 @@ typedef struct { int param; int level; -} IEGCOMPVAR; +} iegcompvar_t; -static int iegInqDatatype(int prec) +static +int iegInqDatatype(int prec) { - int datatype; - - if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64; - else datatype = DATATYPE_FLT32; - - return (datatype); + return (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_FLT64 : DATATYPE_FLT32; } - -static int iegDefDatatype(int datatype) +static +int iegDefDatatype(int datatype) { - int prec; - if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 ) Error("CDI/IEG library does not support complex numbers!"); if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 ) datatype = DATATYPE_FLT32; - if ( datatype == DATATYPE_FLT64 ) prec = DOUBLE_PRECISION; - else prec = SINGLE_PRECISION; - - return (prec); + return (datatype == DATATYPE_FLT64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION; } /* not used @@ -83,7 +72,7 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID) *levelID = -1; status = iegRead(fileID, iegp); - if ( status != 0 ) return (0); + if ( status != 0 ) return 0; icode = IEG_P_Parameter(iegp->ipdb); if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER ) @@ -99,45 +88,37 @@ int iegInqRecord(stream_t *streamptr, int *varID, int *levelID) *levelID = zaxisInqLevelID(zaxisID, (double) ilevel); - return (1); + return 1; } */ void iegReadRecord(stream_t *streamptr, double *data, int *nmiss) { - int vlistID, fileID; - int status; - int recID, vrecID, tsID; - off_t recpos; - int varID, gridID; - int i, size; - double missval; - void *iegp = streamptr->record->exsep; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - tsID = streamptr->curTsID; - vrecID = streamptr->tsteps[tsID].curRecID; - recID = streamptr->tsteps[tsID].recIDs[vrecID]; - recpos = streamptr->tsteps[tsID].records[recID].position; - varID = streamptr->tsteps[tsID].records[recID].varID; + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + int tsID = streamptr->curTsID; + int vrecID = streamptr->tsteps[tsID].curRecID; + int recID = streamptr->tsteps[tsID].recIDs[vrecID]; + int varID = streamptr->tsteps[tsID].records[recID].varID; + off_t recpos = streamptr->tsteps[tsID].records[recID].position; fileSetPos(fileID, recpos, SEEK_SET); - status = iegRead(fileID, iegp); + void *iegp = streamptr->record->exsep; + int status = iegRead(fileID, iegp); if ( status != 0 ) Error("Could not read IEG record!"); iegInqDataDP(iegp, data); - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - size = gridInqSize(gridID); + double missval = vlistInqVarMissval(vlistID, varID); + int gridID = vlistInqVarGrid(vlistID, varID); + int size = gridInqSize(gridID); streamptr->numvals += size; *nmiss = 0; - for ( i = 0; i < size; i++ ) + for ( int i = 0; i < size; i++ ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -197,19 +178,18 @@ int iegGetZaxisType(int iegleveltype) } } - return (leveltype); + return leveltype; } static void iegDefTime(int *pdb, int date, int time, int taxisID) { - int year, month, day, hour, minute, second; int timetype = -1; - if ( taxisID != -1 ) timetype = taxisInqType(taxisID); if ( timetype == TAXIS_ABSOLUTE || timetype == TAXIS_RELATIVE ) { + int year, month, day, hour, minute, second; cdiDecodeDate(date, &year, &month, &day); cdiDecodeTime(time, &hour, &minute, &second); @@ -260,21 +240,25 @@ calc_resfac(double xfirst, double xlast, double xinc, double yfirst, double ylas } } - return (resfac); + return resfac; } static void iegDefGrid(int *gdb, int gridID) { + int projID = gridInqProj(gridID); + if ( projID != CDI_UNDEFID && gridInqProjType(projID) == CDI_PROJ_RLL ) gridID = projID; + int gridtype = gridInqType(gridID); - if ( gridtype == GRID_GENERIC ) - { - int xsize, ysize; + int projtype = CDI_UNDEFID; + if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL ) projtype = CDI_PROJ_RLL; - xsize = gridInqXsize(gridID); - ysize = gridInqYsize(gridID); + int xsize = gridInqXsize(gridID); + int ysize = gridInqYsize(gridID); + if ( gridtype == GRID_GENERIC ) + { if ( (ysize == 32 || ysize == 48 || ysize == 64 || ysize == 96 || ysize == 160) && (xsize == 2*ysize || xsize == 1) ) @@ -298,39 +282,32 @@ void iegDefGrid(int *gdb, int gridID) gridtype = GRID_LONLAT; } - if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN ) + bool lrotated = ((gridtype == GRID_LONLAT && gridIsRotated(gridID)) || projtype == CDI_PROJ_RLL); + + if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL ) { double xfirst = 0, xlast = 0, xinc = 0; double yfirst = 0, ylast = 0, yinc = 0; - int nlon = gridInqXsize(gridID), - nlat = gridInqYsize(gridID); - - if ( nlon == 0 ) - { - nlon = 1; - } + if ( xsize == 0 ) xsize = 1; else { - xfirst = gridInqXval(gridID, 0); - xlast = gridInqXval(gridID, nlon-1); + xfirst = gridInqXval(gridID, 0); + xlast = gridInqXval(gridID, xsize-1); xinc = gridInqXinc(gridID); } - if ( nlat == 0 ) - { - nlat = 1; - } + if ( ysize == 0 ) ysize = 1; else { - yfirst = gridInqYval(gridID, 0); - ylast = gridInqYval(gridID, nlat-1); + yfirst = gridInqYval(gridID, 0); + ylast = gridInqYval(gridID, ysize-1); yinc = gridInqYinc(gridID); } if ( gridtype == GRID_GAUSSIAN ) IEG_G_GridType(gdb) = 4; - else if ( gridtype == GRID_LONLAT && gridIsRotated(gridID) ) + else if ( lrotated ) IEG_G_GridType(gdb) = 10; else IEG_G_GridType(gdb) = 0; @@ -341,8 +318,8 @@ void iegDefGrid(int *gdb, int gridID) IEG_G_ResFac(gdb) = iresfac; - IEG_G_NumLon(gdb) = nlon; - IEG_G_NumLat(gdb) = nlat; + IEG_G_NumLon(gdb) = xsize; + IEG_G_NumLat(gdb) = ysize; IEG_G_FirstLat(gdb) = (int)lround(yfirst*resfac); IEG_G_LastLat(gdb) = (int)lround(ylast*resfac); IEG_G_FirstLon(gdb) = (int)lround(xfirst*resfac); @@ -352,7 +329,7 @@ void iegDefGrid(int *gdb, int gridID) IEG_G_LonIncr(gdb) = 0; if ( gridtype == GRID_GAUSSIAN ) - IEG_G_LatIncr(gdb) = nlat/2; + IEG_G_LatIncr(gdb) = ysize/2; else { IEG_G_LatIncr(gdb) = (int)lround(yinc*resfac); @@ -368,15 +345,22 @@ void iegDefGrid(int *gdb, int gridID) if ( IEG_G_NumLon(gdb) == 1 && IEG_G_NumLat(gdb) > 1 ) if ( IEG_G_LonIncr(gdb) == 0 && IEG_G_LatIncr(gdb) != 0 ) IEG_G_LonIncr(gdb) = IEG_G_LatIncr(gdb); - if ( IEG_G_LatIncr(gdb) == 0 || IEG_G_LonIncr(gdb) == 0 ) - IEG_G_ResFlag(gdb) = 0; - else - IEG_G_ResFlag(gdb) = 128; + IEG_G_ResFlag(gdb) = (IEG_G_LatIncr(gdb) == 0 || IEG_G_LonIncr(gdb) == 0) ? 0 : 128; - if ( gridIsRotated(gridID) ) + if ( lrotated ) { - IEG_G_LatSP(gdb) = - (int)lround(gridInqYpole(gridID) * resfac); - IEG_G_LonSP(gdb) = (int)lround((gridInqXpole(gridID) + 180) * resfac); + double xpole = 0, ypole = 0, angle = 0; + if ( projtype == CDI_PROJ_RLL ) + gridInqProjParamRLL(gridID, &xpole, &ypole, &angle); + else + { + xpole = gridInqXpole(gridID); + ypole = gridInqYpole(gridID); + angle = gridInqAngle(gridID); + } + + IEG_G_LatSP(gdb) = - (int)lround(ypole * resfac); + IEG_G_LonSP(gdb) = (int)lround((xpole + 180) * resfac); IEG_G_Size(gdb) = 42; } else @@ -392,20 +376,26 @@ void iegDefGrid(int *gdb, int gridID) IEG_G_ScanFlag(gdb) = 64; } +static +void pdbDefLevel(int *pdb, int leveltype, int level1, int level2) +{ + IEG_P_LevelType(pdb) = leveltype; + IEG_P_Level1(pdb) = level1; + IEG_P_Level2(pdb) = level2; +} + static void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID) { double level; - int ilevel, leveltype; - static int vct_warning = 1; + int ilevel; - leveltype = zaxisInqType(zaxisID); + int leveltype = zaxisInqType(zaxisID); if ( leveltype == ZAXIS_GENERIC ) { Message("Changed zaxis type from %s to %s", - zaxisNamePtr(leveltype), - zaxisNamePtr(ZAXIS_PRESSURE)); + zaxisNamePtr(leveltype), zaxisNamePtr(ZAXIS_PRESSURE)); leveltype = ZAXIS_PRESSURE; zaxisChangeType(zaxisID, leveltype); zaxisDefUnits(zaxisID, "Pa"); @@ -417,36 +407,26 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID) { case ZAXIS_SURFACE: { - IEG_P_LevelType(pdb) = IEG_LTYPE_SURFACE; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = (int)(zaxisInqLevel(zaxisID, levelID)); + pdbDefLevel(pdb, IEG_LTYPE_SURFACE, 0, (int)zaxisInqLevel(zaxisID, levelID)); break; } case ZAXIS_HYBRID: { - int vctsize; - if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID_LAYER; - IEG_P_Level1(pdb) = (int)(zaxisInqLbound(zaxisID, levelID)); - IEG_P_Level2(pdb) = (int)(zaxisInqUbound(zaxisID, levelID)); - } + pdbDefLevel(pdb, IEG_LTYPE_HYBRID_LAYER, (int)zaxisInqLbound(zaxisID, levelID), + (int)zaxisInqUbound(zaxisID, levelID)); else - { - IEG_P_LevelType(pdb) = IEG_LTYPE_HYBRID; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = (int)(zaxisInqLevel(zaxisID, levelID)); - } + pdbDefLevel(pdb, IEG_LTYPE_HYBRID, 0, (int)zaxisInqLevel(zaxisID, levelID)); - vctsize = zaxisInqVctSize(zaxisID); + int vctsize = zaxisInqVctSize(zaxisID); if ( vctsize > 100 ) { + static bool vct_warning = true; /* IEG_G_NumVCP(gdb) = 0; */ if ( vct_warning ) { Warning("VCT size of %d is too large (maximum is 100). Set to 0!", vctsize); - vct_warning = 0; + vct_warning = false; } } else @@ -463,8 +443,7 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID) char units[128]; level = zaxisInqLevel(zaxisID, levelID); - if ( level < 0 ) - Warning("pressure level of %f Pa is below 0.", level); + if ( level < 0 ) Warning("pressure level of %f Pa is below 0.", level); zaxisInqUnits(zaxisID, units); if ( memcmp(units, "hPa", 3) == 0 || memcmp(units, "mb",2 ) == 0 ) @@ -472,81 +451,43 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID) ilevel = (int) level; if ( level < 32768 && (level < 100 || modf(level/100, &dum) > 0) ) - { - IEG_P_LevelType(pdb) = IEG_LTYPE_99; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = ilevel; - } + pdbDefLevel(pdb, IEG_LTYPE_99, 0, ilevel); else - { - IEG_P_LevelType(pdb) = IEG_LTYPE_ISOBARIC; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = ilevel/100; - } - break; + pdbDefLevel(pdb, IEG_LTYPE_ISOBARIC, 0, ilevel/100); + + break; } case ZAXIS_HEIGHT: { level = zaxisInqLevel(zaxisID, levelID); - - ilevel = (int) level; - IEG_P_LevelType(pdb) = IEG_LTYPE_HEIGHT; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = ilevel; - + pdbDefLevel(pdb, IEG_LTYPE_HEIGHT, 0, (int)level); break; } case ZAXIS_ALTITUDE: { level = zaxisInqLevel(zaxisID, levelID); - - ilevel = (int) level; - IEG_P_LevelType(pdb) = IEG_LTYPE_ALTITUDE; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = ilevel; - + pdbDefLevel(pdb, IEG_LTYPE_ALTITUDE, 0, (int)level); break; } case ZAXIS_DEPTH_BELOW_LAND: { if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) ) - { - IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH_LAYER; - IEG_P_Level1(pdb) = (int)(zaxisInqLbound(zaxisID, levelID)); - IEG_P_Level2(pdb) = (int)(zaxisInqUbound(zaxisID, levelID)); - } + pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH_LAYER, (int)zaxisInqLbound(zaxisID, levelID), (int)zaxisInqUbound(zaxisID, levelID)); else - { - level = zaxisInqLevel(zaxisID, levelID); - - ilevel = (int) level; - IEG_P_LevelType(pdb) = IEG_LTYPE_LANDDEPTH; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = ilevel; - } + pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH, 0, (int)zaxisInqLevel(zaxisID, levelID)); break; } case ZAXIS_DEPTH_BELOW_SEA: { level = zaxisInqLevel(zaxisID, levelID); - - ilevel = (int) level; - IEG_P_LevelType(pdb) = IEG_LTYPE_SEADEPTH; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = ilevel; - + pdbDefLevel(pdb, IEG_LTYPE_SEADEPTH, 0, (int)level); break; } case ZAXIS_ISENTROPIC: { level = zaxisInqLevel(zaxisID, levelID); - - ilevel = (int) level; - IEG_P_LevelType(pdb) = 113; - IEG_P_Level1(pdb) = 0; - IEG_P_Level2(pdb) = ilevel; - + pdbDefLevel(pdb, 113, 0, (int)level); break; } default: @@ -566,68 +507,55 @@ void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1) void iegDefRecord(stream_t *streamptr) { - int vlistID; - int gridID; - int date, time; - int datatype; - int i; - int param, pdis, pcat, pnum; - int varID, levelID, tsID, zaxisID; - int byteorder; - iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; + Record *record = streamptr->record; + iegrec_t *iegp = (iegrec_t*) record->exsep; - vlistID = streamptr->vlistID; - byteorder = streamptr->byteorder; + int vlistID = streamptr->vlistID; + int byteorder = streamptr->byteorder; - varID = streamptr->record->varID; - levelID = streamptr->record->levelID; - tsID = streamptr->curTsID; + int varID = record->varID; + int levelID = record->levelID; + int tsID = streamptr->curTsID; - gridID = vlistInqVarGrid(vlistID, varID); - zaxisID = vlistInqVarZaxis(vlistID, varID); + int gridID = vlistInqVarGrid(vlistID, varID); + int zaxisID = vlistInqVarZaxis(vlistID, varID); iegInitMem(iegp); - for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1; + for ( int i = 0; i < 37; i++ ) iegp->ipdb[i] = -1; iegp->byteswap = getByteswap(byteorder); - param = vlistInqVarParam(vlistID, varID); + int param = vlistInqVarParam(vlistID, varID); + int pdis, pcat, pnum; cdiDecodeParam(param, &pnum, &pcat, &pdis); IEG_P_Parameter(iegp->ipdb) = pnum; if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat; - date = streamptr->tsteps[tsID].taxis.vdate; - time = streamptr->tsteps[tsID].taxis.vtime; + int date = streamptr->tsteps[tsID].taxis.vdate; + int time = streamptr->tsteps[tsID].taxis.vtime; iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID)); iegDefGrid(iegp->igdb, gridID); iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levelID); - datatype = streamptr->record->prec; - - iegp->dprec = iegDefDatatype(datatype); + iegp->dprec = iegDefDatatype(record->prec); } void iegWriteRecord(stream_t *streamptr, const double *data) { - int fileID; - int i, gridsize, gridID; - double refval; - iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; - - fileID = streamptr->fileID; - gridID = streamptr->record->gridID; + Record *record = streamptr->record; + iegrec_t *iegp = (iegrec_t*) record->exsep; - gridsize = gridInqSize(gridID); + int fileID = streamptr->fileID; + int gridsize = gridInqSize(record->gridID); - refval = data[0]; - for ( i = 1; i < gridsize; i++ ) + double refval = data[0]; + for ( int i = 1; i < gridsize; i++ ) if ( data[i] < refval ) refval = data[i]; iegp->refval = refval; iegDefDataDP(iegp, data); - iegWrite(fileID, iegp); } @@ -635,7 +563,6 @@ static void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vct, size_t recsize, off_t position, int prec) { - int levelID = 0; int vlistID = streamptr->vlistID; int tsID = streamptr->curTsID; int recID = recordNewEntry(streamptr, tsID); @@ -661,18 +588,25 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc record->ilevel2 = level2; record->ltype = IEG_P_LevelType(pdb); - int gridtype = - ( IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10 ) ? GRID_LONLAT : - ( IEG_G_GridType(gdb) == 4 ) ? GRID_GAUSSIAN : GRID_GENERIC; +#ifdef TEST_PROJECTION + int gridtype = (IEG_G_GridType(gdb) == 0) ? GRID_LONLAT : + (IEG_G_GridType(gdb) == 10) ? GRID_PROJECTION : + (IEG_G_GridType(gdb) == 4) ? GRID_GAUSSIAN : GRID_GENERIC; +#else + int gridtype = (IEG_G_GridType(gdb) == 0 || IEG_G_GridType(gdb) == 10) ? GRID_LONLAT : + (IEG_G_GridType(gdb) == 4) ? GRID_GAUSSIAN : GRID_GENERIC; +#endif grid_t *grid = (grid_t *)Malloc(sizeof (*grid)); grid_init(grid); cdiGridTypeInit(grid, gridtype, IEG_G_NumLon(gdb)*IEG_G_NumLat(gdb)); - grid->xsize = IEG_G_NumLon(gdb); - grid->ysize = IEG_G_NumLat(gdb); - grid->xinc = 0; - grid->yinc = 0; - grid->xdef = 0; + int xsize = IEG_G_NumLon(gdb); + int ysize = IEG_G_NumLat(gdb); + grid->x.size = xsize; + grid->y.size = ysize; + grid->x.inc = 0; + grid->y.inc = 0; + grid->x.flag = 0; int iresfac = IEG_G_ResFac(gdb); if ( iresfac == 0 ) iresfac = 1000; @@ -680,78 +614,74 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc /* if ( IEG_G_FirstLon != 0 || IEG_G_LastLon != 0 ) */ { - if ( grid->xsize > 1 ) + if ( xsize > 1 ) { if ( IEG_G_ResFlag(gdb) && IEG_G_LonIncr(gdb) > 0 ) - grid->xinc = IEG_G_LonIncr(gdb) * resfac; + grid->x.inc = IEG_G_LonIncr(gdb) * resfac; else - grid->xinc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (grid->xsize - 1); + grid->x.inc = (IEG_G_LastLon(gdb) - IEG_G_FirstLon(gdb)) * resfac / (xsize - 1); /* correct xinc if necessary */ if ( IEG_G_FirstLon(gdb) == 0 && IEG_G_LastLon(gdb) > 354000 ) { - double xinc = 360. / grid->xsize; - /* FIXME: why not use grid->xinc != xinc as condition? */ - if ( fabs(grid->xinc-xinc) > 0.0 ) + double xinc = 360. / xsize; + /* FIXME: why not use grid->x.inc != xinc as condition? */ + if ( fabs(grid->x.inc-xinc) > 0.0 ) { - grid->xinc = xinc; - if ( CDI_Debug ) Message("set xinc to %g", grid->xinc); + grid->x.inc = xinc; + if ( CDI_Debug ) Message("set xinc to %g", grid->x.inc); } } } - grid->xfirst = IEG_G_FirstLon(gdb) * resfac; - grid->xlast = IEG_G_LastLon(gdb) * resfac; - grid->xdef = 2; + grid->x.first = IEG_G_FirstLon(gdb) * resfac; + grid->x.last = IEG_G_LastLon(gdb) * resfac; + grid->x.flag = 2; } - grid->ydef = 0; + grid->y.flag = 0; /* if ( IEG_G_FirstLat != 0 || IEG_G_LastLat != 0 ) */ { - if ( grid->ysize > 1 ) + if ( ysize > 1 ) { if ( IEG_G_ResFlag(gdb) && IEG_G_LatIncr(gdb) > 0 ) - grid->yinc = IEG_G_LatIncr(gdb) * resfac; + grid->y.inc = IEG_G_LatIncr(gdb) * resfac; else - grid->yinc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (grid->ysize - 1); + grid->y.inc = (IEG_G_LastLat(gdb) - IEG_G_FirstLat(gdb)) * resfac / (ysize - 1); } - grid->yfirst = IEG_G_FirstLat(gdb) * resfac; - grid->ylast = IEG_G_LastLat(gdb) * resfac; - grid->ydef = 2; + grid->y.first = IEG_G_FirstLat(gdb) * resfac; + grid->y.last = IEG_G_LastLat(gdb) * resfac; + grid->y.flag = 2; } - /* - grid->xfirst= IEG_G_FirstLon(gdb) * resfac; - grid->xlast = IEG_G_LastLon(gdb) * resfac; - grid->xinc = IEG_G_LonIncr(gdb) * resfac; - grid->xdef = 2; - grid->yfirst= IEG_G_FirstLat(gdb) * resfac; - grid->ylast = IEG_G_LastLat(gdb) * resfac; - grid->yinc = IEG_G_LatIncr(gdb) * resfac; - grid->ydef = 2; - */ - grid->xvals = NULL; - grid->yvals = NULL; grid->isRotated = FALSE; + double xpole = 0, ypole = 0; if ( IEG_G_GridType(gdb) == 10 ) { - grid->isRotated = TRUE; - grid->ypole = - IEG_G_LatSP(gdb) * resfac; - grid->xpole = IEG_G_LonSP(gdb) * resfac - 180; - grid->angle = 0; + xpole = IEG_G_LonSP(gdb) * resfac - 180; + ypole = - IEG_G_LatSP(gdb) * resfac; + if ( gridtype == GRID_LONLAT ) + { + grid->isRotated = TRUE; + grid->rll.xpole = xpole; + grid->rll.ypole = ypole; + grid->rll.angle = 0; + } + else + grid->projtype = CDI_PROJ_RLL; } - struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); + struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); int gridID = gridAdded.Id; - if (!gridAdded.isNew) Free(grid); + if ( !gridAdded.isNew ) Free(grid); + else if ( gridtype == GRID_PROJECTION ) gridDefProjParamRLL(gridID, xpole, ypole, 0); int leveltype = iegGetZaxisType(IEG_P_LevelType(pdb)); - if ( leveltype == ZAXIS_HYBRID ) { double tmpvct[100]; size_t vctsize = (size_t)IEG_G_NumVCP(gdb); - for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i]; - for (size_t i = 0; i < vctsize/2; i++ ) tmpvct[i+vctsize/2] = vct[i+50]; + for ( size_t i = 0; i < vctsize/2; i++ ) tmpvct[i] = vct[i]; + for ( size_t i = 0; i < vctsize/2; i++ ) tmpvct[i+vctsize/2] = vct[i+50]; varDefVCT(vctsize, tmpvct); } @@ -761,6 +691,7 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc int datatype = iegInqDatatype(prec); int varID; + int levelID = 0; varAddRecord(recID, param, gridID, leveltype, lbounds, level1, level2, 0, 0, datatype, &varID, &levelID, TSTEP_INSTANT, 0, 0, -1, NULL, NULL, NULL, NULL, NULL, NULL); @@ -772,8 +703,7 @@ void iegAddRecord(stream_t *streamptr, int param, int *pdb, int *gdb, double *vc streamptr->nrecs++; if ( CDI_Debug ) - Message("varID = %d gridID = %d levelID = %d", - varID, gridID, levelID); + Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID); } #if 0 @@ -783,9 +713,8 @@ void iegCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int { int varID = 0; int levelID = 0; - record_t *record; - record = &streamptr->tsteps[tsID].records[recID]; + record_t *record = &streamptr->tsteps[tsID].records[recID]; if ( param != (*record).param || level != (*record).ilevel ) Error("inconsistent timestep"); @@ -805,17 +734,15 @@ void iegCmpRecord(stream_t *streamptr, int tsID, int recID, off_t position, int } #endif -static void iegDateTime(int *pdb, int *date, int *time) +static +void iegDateTime(int *pdb, int *date, int *time) { - int ryear, rmonth, rday, rhour, rminute; - - ryear = IEG_P_Year(pdb); - - rmonth = IEG_P_Month(pdb); - rday = IEG_P_Day(pdb); + int ryear = IEG_P_Year(pdb); + int rmonth = IEG_P_Month(pdb); + int rday = IEG_P_Day(pdb); - rhour = IEG_P_Hour(pdb); - rminute = IEG_P_Minute(pdb); + int rhour = IEG_P_Hour(pdb); + int rminute = IEG_P_Minute(pdb); if ( rminute == -1 ) rminute = 0; @@ -826,51 +753,39 @@ static void iegDateTime(int *pdb, int *date, int *time) static void iegScanTimestep1(stream_t *streamptr) { - int prec = 0; - int status; - int fileID; - int tabnum; - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; DateTime datetime0 = { LONG_MIN, LONG_MIN }; - int tsID; - int varID; - size_t recsize; off_t recpos; - int nrecords, nrecs, recID; - int taxisID = -1; - taxis_t *taxis; - int vlistID; - IEGCOMPVAR compVar, compVar0; + iegcompvar_t compVar, compVar0; iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; streamptr->curTsID = 0; - tsID = tstepsNewEntry(streamptr); - taxis = &streamptr->tsteps[tsID].taxis; + int tsID = tstepsNewEntry(streamptr); + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; if ( tsID != 0 ) Error("Internal problem! tstepsNewEntry returns %d", tsID); - fileID = streamptr->fileID; + int fileID = streamptr->fileID; - nrecs = 0; + int nrecs = 0; while ( TRUE ) { recpos = fileGetPos(fileID); - status = iegRead(fileID, iegp); + int status = iegRead(fileID, iegp); if ( status != 0 ) { streamptr->ntsteps = 1; break; } - recsize = (size_t)(fileGetPos(fileID) - recpos); + size_t recsize = (size_t)(fileGetPos(fileID) - recpos); - prec = iegp->dprec; - rcode = IEG_P_Parameter(iegp->ipdb); - tabnum = IEG_P_CodeTable(iegp->ipdb); - param = cdiEncodeParam(rcode, tabnum, 255); + int prec = iegp->dprec; + int rcode = IEG_P_Parameter(iegp->ipdb); + int tabnum = IEG_P_CodeTable(iegp->ipdb); + int param = cdiEncodeParam(rcode, tabnum, 255); + int rlevel = 0; if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER ) rlevel = IEG_P_Level1(iegp->ipdb); else @@ -878,6 +793,7 @@ void iegScanTimestep1(stream_t *streamptr) if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100; + int vdate = 0, vtime = 0; iegDateTime(iegp->ipdb, &vdate, &vtime); if ( nrecs == 0 ) @@ -889,12 +805,13 @@ void iegScanTimestep1(stream_t *streamptr) { compVar.param = param; compVar.level = rlevel; + int recID = 0; for ( recID = 0; recID < nrecs; recID++ ) { compVar0.param = streamptr->tsteps[0].records[recID].param; compVar0.level = streamptr->tsteps[0].records[recID].ilevel; - if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 ) break; + if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) == 0 ) break; } if ( recID < nrecs ) break; DateTime datetime = { .date = vdate, .time = vtime}; @@ -914,17 +831,17 @@ void iegScanTimestep1(stream_t *streamptr) cdi_generate_vars(streamptr); - taxisID = taxisCreate(TAXIS_ABSOLUTE); + int taxisID = taxisCreate(TAXIS_ABSOLUTE); taxis->type = TAXIS_ABSOLUTE; taxis->vdate = (int)datetime0.date; taxis->vtime = (int)datetime0.time; - vlistID = streamptr->vlistID; + int vlistID = streamptr->vlistID; vlistDefTaxis(vlistID, taxisID); vlist_check_contents(vlistID); - nrecords = streamptr->tsteps[0].nallrecs; + int nrecords = streamptr->tsteps[0].nallrecs; if ( nrecords < streamptr->tsteps[0].recordSize ) { streamptr->tsteps[0].recordSize = nrecords; @@ -935,7 +852,7 @@ void iegScanTimestep1(stream_t *streamptr) streamptr->tsteps[0].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int)); streamptr->tsteps[0].nrecs = nrecords; - for ( recID = 0; recID < nrecords; recID++ ) + for ( int recID = 0; recID < nrecords; recID++ ) streamptr->tsteps[0].recIDs[recID] = recID; if ( streamptr->ntsteps == -1 ) @@ -953,7 +870,7 @@ void iegScanTimestep1(stream_t *streamptr) if ( taxis->vdate == 0 && taxis->vtime == 0 ) { streamptr->ntsteps = 0; - for ( varID = 0; varID < streamptr->nvars; varID++ ) + for ( int varID = 0; varID < streamptr->nvars; varID++ ) { vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT); } @@ -964,67 +881,55 @@ void iegScanTimestep1(stream_t *streamptr) static int iegScanTimestep2(stream_t *streamptr) { - int status; - int fileID; - int tabnum; - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; - int tsID; - int varID; - size_t recsize; off_t recpos = 0; - int nrecords, nrecs, recID, rindex; - int nextstep; - taxis_t *taxis; - int vlistID; - IEGCOMPVAR compVar, compVar0; + iegcompvar_t compVar, compVar0; iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; streamptr->curTsID = 1; - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; - tsID = streamptr->rtsteps; + int tsID = streamptr->rtsteps; if ( tsID != 1 ) Error("Internal problem! unexpected timestep %d", tsID+1); - taxis = &streamptr->tsteps[tsID].taxis; + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET); cdi_create_records(streamptr, tsID); - nrecords = streamptr->tsteps[0].nallrecs; + int nrecords = streamptr->tsteps[0].nallrecs; streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof(int)); streamptr->tsteps[1].nrecs = 0; - for ( recID = 0; recID < nrecords; recID++ ) + for ( int recID = 0; recID < nrecords; recID++ ) streamptr->tsteps[1].recIDs[recID] = -1; - for ( recID = 0; recID < nrecords; recID++ ) + for ( int recID = 0; recID < nrecords; recID++ ) { - varID = streamptr->tsteps[0].records[recID].varID; streamptr->tsteps[tsID].records[recID].position = streamptr->tsteps[0].records[recID].position; streamptr->tsteps[tsID].records[recID].size = streamptr->tsteps[0].records[recID].size; } - for ( rindex = 0; rindex <= nrecords; rindex++ ) + for ( int rindex = 0; rindex <= nrecords; rindex++ ) { recpos = fileGetPos(fileID); - status = iegRead(fileID, iegp); + int status = iegRead(fileID, iegp); if ( status != 0 ) { streamptr->ntsteps = 2; break; } - recsize = (size_t)(fileGetPos(fileID) - recpos); + size_t recsize = (size_t)(fileGetPos(fileID) - recpos); - rcode = IEG_P_Parameter(iegp->ipdb); - tabnum = IEG_P_CodeTable(iegp->ipdb); - param = cdiEncodeParam(rcode, tabnum, 255); + int rcode = IEG_P_Parameter(iegp->ipdb); + int tabnum = IEG_P_CodeTable(iegp->ipdb); + int param = cdiEncodeParam(rcode, tabnum, 255); + int rlevel = 0; if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER ) rlevel = IEG_P_Level1(iegp->ipdb); else @@ -1032,6 +937,7 @@ int iegScanTimestep2(stream_t *streamptr) if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100; + int vdate = 0, vtime = 0; iegDateTime(iegp->ipdb, &vdate, &vtime); if ( rindex == 0 ) @@ -1043,17 +949,18 @@ int iegScanTimestep2(stream_t *streamptr) compVar.param = param; compVar.level = rlevel; - nextstep = FALSE; + bool nextstep = false; + int recID = 0; for ( recID = 0; recID < nrecords; recID++ ) { compVar0.param = streamptr->tsteps[tsID].records[recID].param; compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel; - if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) == 0 ) + if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) == 0 ) { if ( streamptr->tsteps[tsID].records[recID].used ) { - nextstep = TRUE; + nextstep = true; } else { @@ -1068,7 +975,7 @@ int iegScanTimestep2(stream_t *streamptr) char paramstr[32]; cdiParamToString(param, paramstr, sizeof(paramstr)); Warning("param %s level %d not defined at timestep 1", paramstr, rlevel); - return (CDI_EUFSTRUCT); + return CDI_EUFSTRUCT; } if ( nextstep ) break; @@ -1081,24 +988,24 @@ int iegScanTimestep2(stream_t *streamptr) compVar0.param = streamptr->tsteps[tsID].records[recID].param; compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel; - if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 ) + if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) != 0 ) { Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d", tsID, recID, streamptr->tsteps[tsID].records[recID].param, param, streamptr->tsteps[tsID].records[recID].ilevel, rlevel); - return (CDI_EUFSTRUCT); + return CDI_EUFSTRUCT; } streamptr->tsteps[1].records[recID].position = recpos; } - nrecs = 0; - for ( recID = 0; recID < nrecords; recID++ ) + int nrecs = 0; + for ( int recID = 0; recID < nrecords; recID++ ) { if ( ! streamptr->tsteps[tsID].records[recID].used ) { - varID = streamptr->tsteps[tsID].records[recID].varID; + int varID = streamptr->tsteps[tsID].records[recID].varID; vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT); } else @@ -1120,43 +1027,31 @@ int iegScanTimestep2(stream_t *streamptr) streamptr->tsteps[tsID].position = recpos; } - return (0); + return 0; } int iegInqContents(stream_t *streamptr) { - int fileID; - int status = 0; - - fileID = streamptr->fileID; + int fileID = streamptr->fileID; streamptr->curTsID = 0; iegScanTimestep1(streamptr); + int status = 0; if ( streamptr->ntsteps == -1 ) status = iegScanTimestep2(streamptr); fileSetPos(fileID, 0, SEEK_SET); - return (status); + return status; } static long iegScanTimestep(stream_t *streamptr) { - int status; - int fileID; - int tsID; - int tabnum; - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; - size_t recsize = 0; off_t recpos = 0; - int recID; - taxis_t *taxis; - int rindex, nrecs = 0; - IEGCOMPVAR compVar, compVar0; + iegcompvar_t compVar, compVar0; iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; if ( CDI_Debug ) @@ -1170,9 +1065,10 @@ long iegScanTimestep(stream_t *streamptr) if ( streamptr->rtsteps == 0 ) Error("Internal problem! Missing contents."); - tsID = streamptr->rtsteps; - taxis = &streamptr->tsteps[tsID].taxis; + int tsID = streamptr->rtsteps; + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; + int nrecs = 0; if ( streamptr->tsteps[tsID].recordSize == 0 ) { cdi_create_records(streamptr, tsID); @@ -1182,28 +1078,29 @@ long iegScanTimestep(stream_t *streamptr) streamptr->tsteps[tsID].nrecs = nrecs; streamptr->tsteps[tsID].recIDs = (int *) Malloc((size_t)nrecs * sizeof (int)); - for ( recID = 0; recID < nrecs; recID++ ) + for ( int recID = 0; recID < nrecs; recID++ ) streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID]; - fileID = streamptr->fileID; + int fileID = streamptr->fileID; fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET); - for ( rindex = 0; rindex <= nrecs; rindex++ ) + for ( int rindex = 0; rindex <= nrecs; rindex++ ) { recpos = fileGetPos(fileID); - status = iegRead(fileID, iegp); + int status = iegRead(fileID, iegp); if ( status != 0 ) { streamptr->ntsteps = streamptr->rtsteps + 1; break; } - recsize = (size_t)(fileGetPos(fileID) - recpos); + size_t recsize = (size_t)(fileGetPos(fileID) - recpos); - rcode = IEG_P_Parameter(iegp->ipdb); - tabnum = IEG_P_CodeTable(iegp->ipdb); - param = cdiEncodeParam(rcode, tabnum, 255); + int rcode = IEG_P_Parameter(iegp->ipdb); + int tabnum = IEG_P_CodeTable(iegp->ipdb); + int param = cdiEncodeParam(rcode, tabnum, 255); + int rlevel = 0; if ( IEG_P_LevelType(iegp->ipdb) == IEG_LTYPE_HYBRID_LAYER ) rlevel = IEG_P_Level1(iegp->ipdb); else @@ -1211,11 +1108,12 @@ long iegScanTimestep(stream_t *streamptr) if ( IEG_P_LevelType(iegp->ipdb) == 100 ) rlevel *= 100; + int vdate = 0, vtime = 0; iegDateTime(iegp->ipdb, &vdate, &vtime); // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error if ( rindex == nrecs ) continue; - recID = streamptr->tsteps[tsID].recIDs[rindex]; + int recID = streamptr->tsteps[tsID].recIDs[rindex]; if ( rindex == 0 ) { @@ -1229,7 +1127,7 @@ long iegScanTimestep(stream_t *streamptr) compVar0.param = streamptr->tsteps[tsID].records[recID].param; compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel; - if ( memcmp(&compVar0, &compVar, sizeof(IEGCOMPVAR)) != 0 ) + if ( memcmp(&compVar0, &compVar, sizeof(iegcompvar_t)) != 0 ) { Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d", tsID, recID, @@ -1249,7 +1147,7 @@ long iegScanTimestep(stream_t *streamptr) if ( streamptr->ntsteps != streamptr->rtsteps ) { - tsID = tstepsNewEntry(streamptr); + int tsID = tstepsNewEntry(streamptr); if ( tsID != streamptr->rtsteps ) Error("Internal error. tsID = %d", tsID); @@ -1267,14 +1165,12 @@ long iegScanTimestep(stream_t *streamptr) streamptr->ntsteps = tsID; } - return (streamptr->ntsteps); + return streamptr->ntsteps; } int iegInqTimestep(stream_t *streamptr, int tsID) { - int nrecs; - if ( tsID == 0 && streamptr->rtsteps == 0 ) Error("Call to cdiInqContents missing!"); @@ -1285,95 +1181,35 @@ int iegInqTimestep(stream_t *streamptr, int tsID) while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID ) ntsteps = iegScanTimestep(streamptr); - if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID ) - { - nrecs = 0; - } - else + int nrecs = 0; + if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID) ) { streamptr->curTsID = tsID; nrecs = streamptr->tsteps[tsID].nrecs; } - return (nrecs); -} - - -void iegReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss) -{ - int vlistID, fileID; - int levID, nlevs, gridID, gridsize; - off_t recpos, currentfilepos; - int tsid; - int recID; - int i; - double missval; - void *iegp = streamptr->record->exsep; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - /* NOTE: tiles are not supported here! */ - nlevs = streamptr->vars[varID].recordTable[0].nlevs; - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - tsid = streamptr->curTsID; - - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize); - - currentfilepos = fileGetPos(fileID); - - for (levID = 0; levID < nlevs; levID++) - { - /* NOTE: tiles are not supported here! */ - recID = streamptr->vars[varID].recordTable[0].recordID[levID]; - recpos = streamptr->tsteps[tsid].records[recID].position; - fileSetPos(fileID, recpos, SEEK_SET); - iegRead(fileID, iegp); - iegInqDataDP(iegp, &data[levID*gridsize]); - } - fileSetPos(fileID, currentfilepos, SEEK_SET); - - *nmiss = 0; - for ( i = 0; i < nlevs*gridsize; i++ ) - if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) - { - data[i] = missval; - (*nmiss)++; - } + return nrecs; } void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss) { - int vlistID, fileID; - int nlevs, gridID, gridsize; - off_t recpos, currentfilepos; - int tsid; - int recID; - int i; - double missval; + if ( CDI_Debug ) Message("streamID = %d varID = %d levID = %d", streamptr->self, varID, levID); + void *iegp = streamptr->record->exsep; - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; /* NOTE: tiles are not supported here! */ - nlevs = streamptr->vars[varID].recordTable[0].nlevs; - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - tsid = streamptr->curTsID; - - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", - nlevs, gridID, gridsize); + double missval = vlistInqVarMissval(vlistID, varID); + int gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID)); + int tsid = streamptr->curTsID; - currentfilepos = fileGetPos(fileID); + off_t currentfilepos = fileGetPos(fileID); /* NOTE: tiles are not supported here! */ - recID = streamptr->vars[varID].recordTable[0].recordID[levID]; - recpos = streamptr->tsteps[tsid].records[recID].position; + int recID = streamptr->vars[varID].recordTable[0].recordID[levID]; + off_t recpos = streamptr->tsteps[tsid].records[recID].position; fileSetPos(fileID, recpos, SEEK_SET); iegRead(fileID, iegp); iegInqDataDP(iegp, data); @@ -1381,7 +1217,7 @@ void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, fileSetPos(fileID, currentfilepos, SEEK_SET); *nmiss = 0; - for ( i = 0; i < gridsize; i++ ) + for ( int i = 0; i < gridsize; i++ ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -1390,101 +1226,70 @@ void iegReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, } -void iegWriteVarDP(stream_t *streamptr, int varID, const double *data) +void iegReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss) { - int fileID; - int levID, nlevs, gridID, gridsize; - int zaxisID; - int datatype; - int tsID; - int vlistID; - int i; - int date, time; - int param, pdis, pcat, pnum; - double refval; - iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; + if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID); - if ( CDI_Debug ) - Message("streamID = %d varID = %d", streamptr->self, varID); + int vlistID = streamptr->vlistID; + size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID)); + size_t nlevs = (size_t) streamptr->vars[varID].recordTable[0].nlevs; - iegInitMem(iegp); - for ( i = 0; i < 37; i++ ) iegp->ipdb[i] = -1; + for ( size_t levID = 0; levID < nlevs; levID++) + iegReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss); +} - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - tsID = streamptr->curTsID; - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - zaxisID = vlistInqVarZaxis(vlistID, varID); - nlevs = zaxisInqSize(zaxisID); - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize); +void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data) +{ + if ( CDI_Debug ) Message("streamID = %d varID = %d levID = %d", streamptr->self, varID, levID); + + iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; + iegInitMem(iegp); + for ( int i = 0; i < 37; i++ ) iegp->ipdb[i] = -1; - param = vlistInqVarParam(vlistID, varID); + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + int tsID = streamptr->curTsID; + int gridID = vlistInqVarGrid(vlistID, varID); + int zaxisID = vlistInqVarZaxis(vlistID, varID); + + int param = vlistInqVarParam(vlistID, varID); + int pdis, pcat, pnum; cdiDecodeParam(param, &pnum, &pcat, &pdis); IEG_P_Parameter(iegp->ipdb) = pnum; if ( pdis == 255 ) IEG_P_CodeTable(iegp->ipdb) = pcat; - date = streamptr->tsteps[tsID].taxis.vdate; - time = streamptr->tsteps[tsID].taxis.vtime; + int date = streamptr->tsteps[tsID].taxis.vdate; + int time = streamptr->tsteps[tsID].taxis.vtime; iegDefTime(iegp->ipdb, date, time, vlistInqTaxis(vlistID)); iegDefGrid(iegp->igdb, gridID); + iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levID); - datatype = vlistInqVarDatatype(vlistID, varID); - - iegp->dprec = iegDefDatatype(datatype); + iegp->dprec = iegDefDatatype(vlistInqVarDatatype(vlistID, varID)); - for ( levID = 0; levID < nlevs; levID++ ) - { - iegDefLevel(iegp->ipdb, iegp->igdb, iegp->vct, zaxisID, levID); + int gridsize = gridInqSize(gridID); - refval = data[0]; - for ( i = 1; i < gridsize; i++ ) - if ( data[levID*gridsize+i] < refval ) refval = data[levID*gridsize+i]; + double refval = data[0]; + for ( int i = 1; i < gridsize; i++ ) + if ( data[i] < refval ) refval = data[i]; - iegp->refval = refval; + iegp->refval = refval; - iegDefDataDP(iegp, &data[levID*gridsize]); - iegWrite(fileID, iegp); - } + iegDefDataDP(iegp, data); + iegWrite(fileID, iegp); } -void iegWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data) +void iegWriteVarDP(stream_t *streamptr, int varID, const double *data) { - int fileID; - int gridID; - int zaxisID; - /* double level; */ - int datatype; - /* int tsID; */ - int vlistID; - /* int param, date, time, datasize; */ - iegrec_t *iegp = (iegrec_t*) streamptr->record->exsep; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - /* tsID = streamptr->curTsID; */ - gridID = vlistInqVarGrid(vlistID, varID); - zaxisID = vlistInqVarZaxis(vlistID, varID); - (void)levID; - /* level = zaxisInqLevel(zaxisID, levID); */ - - if ( CDI_Debug ) - Message("gridID = %d zaxisID = %d", gridID, zaxisID); + if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID); - /* param = vlistInqVarParam(vlistID, varID); */ - /* date = streamptr->tsteps[tsID].taxis.vdate; */ - /* time = streamptr->tsteps[tsID].taxis.vtime; */ - /* datasize = gridInqSize(gridID); */ - - datatype = vlistInqVarDatatype(vlistID, varID); - - iegp->dprec = iegDefDatatype(datatype); + int vlistID = streamptr->vlistID; + size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID)); + size_t nlevs = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID)); - iegDefDataDP(iegp, data); - iegWrite(fileID, iegp); + for ( size_t levID = 0; levID < nlevs; levID++ ) + iegWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]); } #endif /* HAVE_LIBIEG */ diff --git a/src/stream_record.c b/src/stream_record.c index ea43cd1d605c6f3e6dbd5a130bc7bb8c65e31a78..23b1f4060145d17a5ea6ecdbc6c6056f9245d3fe 100644 --- a/src/stream_record.c +++ b/src/stream_record.c @@ -86,18 +86,19 @@ int recordNewEntry(stream_t *streamptr, int tsID) static void cdiInitRecord(stream_t *streamptr) { - streamptr->record = (Record *) Malloc(sizeof(Record)); - - streamptr->record->param = 0; - streamptr->record->level = 0; - streamptr->record->date = 0; - streamptr->record->time = 0; - streamptr->record->gridID = 0; - streamptr->record->buffer = NULL; - streamptr->record->buffersize = 0; - streamptr->record->position = 0; - streamptr->record->varID = 0; - streamptr->record->levelID = CDI_UNDEFID; + Record *record = (Record *) Malloc(sizeof(Record)); + streamptr->record = record; + + record->param = 0; + record->level = 0; + record->date = 0; + record->time = 0; + record->gridID = 0; + record->buffer = NULL; + record->buffersize = 0; + record->position = 0; + record->varID = 0; + record->levelID = CDI_UNDEFID; } @@ -170,14 +171,15 @@ void streamDefRecord(int streamID, int varID, int levelID) int param = vlistInqVarParam(vlistID, varID); int level = (int)(zaxisInqLevel(zaxisID, levelID)); - streamptr->record->varID = varID; - streamptr->record->levelID = levelID; - streamptr->record->param = param; - streamptr->record->level = level; - streamptr->record->date = streamptr->tsteps[tsID].taxis.vdate; - streamptr->record->time = streamptr->tsteps[tsID].taxis.vtime; - streamptr->record->gridID = gridID; - streamptr->record->prec = vlistInqVarDatatype(vlistID, varID); + Record *record = streamptr->record; + record->varID = varID; + record->levelID = levelID; + record->param = param; + record->level = level; + record->date = streamptr->tsteps[tsID].taxis.vdate; + record->time = streamptr->tsteps[tsID].taxis.vtime; + record->gridID = gridID; + record->prec = vlistInqVarDatatype(vlistID, varID); switch (streamptr->filetype) { @@ -295,7 +297,6 @@ void streamCopyRecord(int streamID2, int streamID1) void cdi_create_records(stream_t *streamptr, int tsID) { unsigned nrecords, maxrecords; - record_t *records; tsteps_t *sourceTstep = streamptr->tsteps; tsteps_t *destTstep = sourceTstep + tsID; @@ -339,10 +340,8 @@ void cdi_create_records(stream_t *streamptr, int tsID) } // printf("tsID, nrecords %d %d\n", tsID, nrecords); - if ( maxrecords > 0 ) - records = (record_t *) Malloc(maxrecords*sizeof(record_t)); - else - records = NULL; + record_t *records = NULL; + if ( maxrecords > 0 ) records = (record_t *) Malloc(maxrecords*sizeof(record_t)); destTstep->records = records; destTstep->recordSize = (int)maxrecords; @@ -373,6 +372,33 @@ void cdi_create_records(stream_t *streamptr, int tsID) } } } + +#include "file.h" + +void streamFCopyRecord(stream_t *streamptr2, stream_t *streamptr1, const char *container_name) +{ + int fileID1 = streamptr1->fileID; + int fileID2 = streamptr2->fileID; + + int tsID = streamptr1->curTsID; + int vrecID = streamptr1->tsteps[tsID].curRecID; + int recID = streamptr1->tsteps[tsID].recIDs[vrecID]; + off_t recpos = streamptr1->tsteps[tsID].records[recID].position; + size_t recsize = streamptr1->tsteps[tsID].records[recID].size; + + if (fileSetPos(fileID1, recpos, SEEK_SET) != 0) + Error("Cannot seek input file for %s record copy!", container_name); + + char *buffer = (char *) Malloc(recsize); + + if (fileRead(fileID1, buffer, recsize) != recsize) + Error("Failed to read record from %s file for copying!", container_name); + + if (fileWrite(fileID2, buffer, recsize) != recsize) + Error("Failed to write record to %s file when copying!", container_name); + + Free(buffer); +} /* * Local Variables: * c-file-style: "Java" diff --git a/src/stream_srv.c b/src/stream_srv.c index 52752b0df7b9766c11664817fc49fec52fcd165d..8d05996f261f15b61add82b78e93ea47d6f20e23 100644 --- a/src/stream_srv.c +++ b/src/stream_srv.c @@ -16,16 +16,14 @@ #include "varscan.h" #include "datetime.h" #include "service.h" -#include "stream_fcommon.h" #include "stream_srv.h" #include "vlist.h" +#include "exse.h" #undef UNDEFID #define UNDEFID CDI_UNDEFID -#define SINGLE_PRECISION 4 -#define DOUBLE_PRECISION 8 #if defined (HAVE_LIBSERVICE) @@ -33,34 +31,25 @@ typedef struct { int param; int level; -} SRVCOMPVAR; +} srvcompvar_t; -static int srvInqDatatype(int prec) +static +int srvInqDatatype(int prec) { - int datatype; - - if ( prec == DOUBLE_PRECISION ) datatype = DATATYPE_FLT64; - else datatype = DATATYPE_FLT32; - - return (datatype); + return (prec == EXSE_DOUBLE_PRECISION) ? DATATYPE_FLT64 : DATATYPE_FLT32; } - -static int srvDefDatatype(int datatype) +static +int srvDefDatatype(int datatype) { - int prec; - if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 ) Error("CDI/SERVICE library does not support complex numbers!"); if ( datatype != DATATYPE_FLT32 && datatype != DATATYPE_FLT64 ) datatype = DATATYPE_FLT32; - if ( datatype == DATATYPE_FLT64 ) prec = DOUBLE_PRECISION; - else prec = SINGLE_PRECISION; - - return (prec); + return (datatype == DATATYPE_FLT64) ? EXSE_DOUBLE_PRECISION : EXSE_SINGLE_PRECISION; } /* not used @@ -96,19 +85,12 @@ int srvInqRecord(stream_t *streamptr, int *varID, int *levelID) *levelID = zaxisInqLevelID(zaxisID, (double) ilevel); - return (1); + return 1; } */ void srvReadRecord(stream_t *streamptr, double *data, int *nmiss) { - int status; - int header[8]; - int gridID; - int i, size; - double missval; - void *srvp = streamptr->record->exsep; - int vlistID = streamptr->vlistID; int fileID = streamptr->fileID; int tsID = streamptr->curTsID; @@ -119,21 +101,23 @@ void srvReadRecord(stream_t *streamptr, double *data, int *nmiss) fileSetPos(fileID, recpos, SEEK_SET); - status = srvRead(fileID, srvp); + void *srvp = streamptr->record->exsep; + int status = srvRead(fileID, srvp); if ( status != 0 ) Error("Failed to read record from SRV file"); + int header[8]; srvInqHeader(srvp, header); srvInqDataDP(srvp, data); - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - size = gridInqSize(gridID); + double missval = vlistInqVarMissval(vlistID, varID); + int gridID = vlistInqVarGrid(vlistID, varID); + int size = gridInqSize(gridID); streamptr->numvals += size; *nmiss = 0; - for ( i = 0; i < size; i++ ) + for ( int i = 0; i < size; i++ ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -150,20 +134,21 @@ void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1) void srvDefRecord(stream_t *streamptr) { - int header[8]; - Record *restrict record = streamptr->record; - srvrec_t *restrict srvp = (srvrec_t*) record->exsep; - int gridID = record->gridID; + Record *record = streamptr->record; + srvrec_t *srvp = (srvrec_t*) record->exsep; int pdis, pcat, pnum; cdiDecodeParam(record->param, &pnum, &pcat, &pdis); + + int header[8]; header[0] = pnum; header[1] = record->level; header[2] = record->date; header[3] = record->time; + int gridID = record->gridID; int xsize = gridInqXsize(gridID), - ysize = gridInqYsize(gridID); + ysize = gridInqYsize(gridID); if ( xsize == 0 || ysize == 0 ) { xsize = gridInqSize(gridID); @@ -179,7 +164,6 @@ void srvDefRecord(stream_t *streamptr) header[7] = 0; int datatype = record->prec; - srvp->dprec = srvDefDatatype(datatype); srvDefHeader(srvp, header); @@ -209,14 +193,12 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys record->param = param; record->ilevel = level; - grid_t *grid = (grid_t *)Malloc(sizeof (*grid)); + grid_t *grid = (grid_t*) Malloc(sizeof(*grid)); grid_init(grid); cdiGridTypeInit(grid, GRID_GENERIC, xsize*ysize); - grid->xsize = xsize; - grid->ysize = ysize; - grid->xvals = NULL; - grid->yvals = NULL; - struct addIffNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); + grid->x.size = xsize; + grid->y.size = ysize; + struct addIfNewRes gridAdded = cdiVlistAddGridIfNew(vlistID, grid, 0); int gridID = gridAdded.Id; if (!gridAdded.isNew) Free(grid); /* @@ -241,8 +223,7 @@ void srv_add_record(stream_t *streamptr, int param, int level, int xsize, int ys streamptr->nrecs++; if ( CDI_Debug ) - Message("varID = %d gridID = %d levelID = %d", - varID, gridID, levelID); + Message("varID = %d gridID = %d levelID = %d", varID, gridID, levelID); } static @@ -262,7 +243,6 @@ void srvScanTimestep1(stream_t *streamptr) taxis = &streamptr->tsteps[tsID].taxis; } - int fileID = streamptr->fileID; int nrecs = 0; @@ -368,54 +348,43 @@ static int srvScanTimestep2(stream_t *streamptr) { int header[8]; - int status; - int fileID; - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; - int tsID; - int varID; off_t recpos = 0; - int nrecords, nrecs, recID, rindex; - int nextstep; - taxis_t *taxis; - int vlistID; - SRVCOMPVAR compVar, compVar0; + srvcompvar_t compVar, compVar0; void *srvp = streamptr->record->exsep; streamptr->curTsID = 1; - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; - tsID = streamptr->rtsteps; + int tsID = streamptr->rtsteps; if ( tsID != 1 ) Error("Internal problem! unexpected timestep %d", tsID+1); - taxis = &streamptr->tsteps[tsID].taxis; + taxis_t *taxis = &streamptr->tsteps[tsID].taxis; fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET); cdi_create_records(streamptr, tsID); - nrecords = streamptr->tsteps[0].nallrecs; + int nrecords = streamptr->tsteps[0].nallrecs; streamptr->tsteps[1].recIDs = (int *) Malloc((size_t)nrecords * sizeof (int)); streamptr->tsteps[1].nrecs = 0; - for ( recID = 0; recID < nrecords; recID++ ) + for ( int recID = 0; recID < nrecords; recID++ ) streamptr->tsteps[1].recIDs[recID] = -1; - for ( recID = 0; recID < nrecords; recID++ ) + for ( int recID = 0; recID < nrecords; recID++ ) { - varID = streamptr->tsteps[0].records[recID].varID; streamptr->tsteps[tsID].records[recID].position = streamptr->tsteps[0].records[recID].position; streamptr->tsteps[tsID].records[recID].size = streamptr->tsteps[0].records[recID].size; } - for ( rindex = 0; rindex <= nrecords; rindex++ ) + for ( int rindex = 0; rindex <= nrecords; rindex++ ) { recpos = fileGetPos(fileID); - status = srvRead(fileID, srvp); + int status = srvRead(fileID, srvp); if ( status != 0 ) { streamptr->ntsteps = 2; @@ -425,12 +394,12 @@ int srvScanTimestep2(stream_t *streamptr) srvInqHeader(srvp, header); - rcode = header[0]; - rlevel = header[1]; - vdate = header[2]; - vtime = header[3]; + int rcode = header[0]; + int rlevel = header[1]; + int vdate = header[2]; + int vtime = header[3]; - param = cdiEncodeParam(rcode, 255, 255); + int param = cdiEncodeParam(rcode, 255, 255); if ( rindex == 0 ) { @@ -441,17 +410,18 @@ int srvScanTimestep2(stream_t *streamptr) compVar.param = param; compVar.level = rlevel; - nextstep = FALSE; + bool nextstep = false; + int recID; for ( recID = 0; recID < nrecords; recID++ ) { compVar0.param = streamptr->tsteps[tsID].records[recID].param; compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel; - if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) == 0 ) + if ( memcmp(&compVar0, &compVar, sizeof(srvcompvar_t)) == 0 ) { if ( streamptr->tsteps[tsID].records[recID].used ) { - nextstep = TRUE; + nextstep = true; } else { @@ -464,7 +434,7 @@ int srvScanTimestep2(stream_t *streamptr) if ( recID == nrecords ) { Warning("Code %d level %d not found at timestep %d", rcode, rlevel, tsID+1); - return (CDI_EUFSTRUCT); + return CDI_EUFSTRUCT; } if ( nextstep ) break; @@ -477,24 +447,24 @@ int srvScanTimestep2(stream_t *streamptr) compVar0.param = streamptr->tsteps[tsID].records[recID].param; compVar0.level = streamptr->tsteps[tsID].records[recID].ilevel; - if ( memcmp(&compVar0, &compVar, sizeof(SRVCOMPVAR)) != 0 ) + if ( memcmp(&compVar0, &compVar, sizeof(srvcompvar_t)) != 0 ) { Message("tsID = %d recID = %d param = %3d new %3d level = %3d new %3d", tsID, recID, streamptr->tsteps[tsID].records[recID].param, param, streamptr->tsteps[tsID].records[recID].ilevel, rlevel); - return (CDI_EUFSTRUCT); + return CDI_EUFSTRUCT; } streamptr->tsteps[1].records[recID].position = recpos; } - nrecs = 0; - for ( recID = 0; recID < nrecords; recID++ ) + int nrecs = 0; + for ( int recID = 0; recID < nrecords; recID++ ) { if ( ! streamptr->tsteps[tsID].records[recID].used ) { - varID = streamptr->tsteps[tsID].records[recID].varID; + int varID = streamptr->tsteps[tsID].records[recID].varID; vlistDefVarTsteptype(vlistID, varID, TSTEP_CONSTANT); } else @@ -516,40 +486,33 @@ int srvScanTimestep2(stream_t *streamptr) streamptr->tsteps[tsID].position = recpos; } - return (0); + return 0; } int srvInqContents(stream_t *streamptr) { - int fileID; - int status = 0; - - fileID = streamptr->fileID; - streamptr->curTsID = 0; srvScanTimestep1(streamptr); + int status = 0; if ( streamptr->ntsteps == -1 ) status = srvScanTimestep2(streamptr); + int fileID = streamptr->fileID; fileSetPos(fileID, 0, SEEK_SET); - return (status); + return status; } static long srvScanTimestep(stream_t *streamptr) { int header[8]; - int status; - int fileID; /* int rxsize = 0, rysize = 0; */ - int param = 0; - int rcode = 0, rlevel = 0, vdate = 0, vtime = 0; off_t recpos = 0; int recID; - int rindex, nrecs = 0; + int nrecs = 0; void *srvp = streamptr->record->exsep; /* if ( CDI_Debug ) @@ -575,14 +538,14 @@ long srvScanTimestep(stream_t *streamptr) for ( recID = 0; recID < nrecs; recID++ ) streamptr->tsteps[tsID].recIDs[recID] = streamptr->tsteps[1].recIDs[recID]; - fileID = streamptr->fileID; + int fileID = streamptr->fileID; fileSetPos(fileID, streamptr->tsteps[tsID].position, SEEK_SET); - for ( rindex = 0; rindex <= nrecs; rindex++ ) + for ( int rindex = 0; rindex <= nrecs; rindex++ ) { recpos = fileGetPos(fileID); - status = srvRead(fileID, srvp); + int status = srvRead(fileID, srvp); if ( status != 0 ) { streamptr->ntsteps = streamptr->rtsteps + 1; @@ -592,14 +555,14 @@ long srvScanTimestep(stream_t *streamptr) srvInqHeader(srvp, header); - rcode = header[0]; - rlevel = header[1]; - vdate = header[2]; - vtime = header[3]; + int rcode = header[0]; + int rlevel = header[1]; + int vdate = header[2]; + int vtime = header[3]; /* rxsize = header[4]; */ /* rysize = header[5]; */ - param = cdiEncodeParam(rcode, 255, 255); + int param = cdiEncodeParam(rcode, 255, 255); // if ( rindex == nrecs ) break; gcc-4.5 internal compiler error if ( rindex == nrecs ) continue; @@ -651,128 +614,61 @@ long srvScanTimestep(stream_t *streamptr) streamptr->ntsteps = tsID; } - return (streamptr->ntsteps); + return streamptr->ntsteps; } int srvInqTimestep(stream_t *streamptr, int tsID) { - long ntsteps; - int nrecs; - if ( tsID == 0 && streamptr->rtsteps == 0 ) Error("Call to cdiInqContents missing!"); if ( CDI_Debug ) Message("tsID = %d rtsteps = %d", tsID, streamptr->rtsteps); - ntsteps = UNDEFID; + long ntsteps = UNDEFID; while ( ( tsID + 1 ) > streamptr->rtsteps && ntsteps == UNDEFID ) ntsteps = srvScanTimestep(streamptr); - if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID ) - { - nrecs = 0; - } - else + int nrecs = 0; + if ( !(tsID >= streamptr->ntsteps && streamptr->ntsteps != UNDEFID) ) { streamptr->curTsID = tsID; nrecs = streamptr->tsteps[tsID].nrecs; } - return (nrecs); -} - - -void srvReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss) -{ - int vlistID, fileID; - int levID, nlevs, gridID, gridsize; - off_t recpos, currentfilepos; - int header[8]; - int tsid; - int recID; - int i; - double missval; - void *srvp = streamptr->record->exsep; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - /* NOTE: tiles are not supported here! */ - nlevs = streamptr->vars[varID].recordTable[0].nlevs; - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - tsid = streamptr->curTsID; - - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize); - - currentfilepos = fileGetPos(fileID); - - for (levID = 0; levID < nlevs; levID++) - { - /* NOTE: tiles are not supported here! */ - recID = streamptr->vars[varID].recordTable[0].recordID[levID]; - recpos = streamptr->tsteps[tsid].records[recID].position; - fileSetPos(fileID, recpos, SEEK_SET); - if (srvRead(fileID, srvp) < 0) - abort(); - srvInqHeader(srvp, header); - srvInqDataDP(srvp, &data[levID*gridsize]); - } - fileSetPos(fileID, currentfilepos, SEEK_SET); - - *nmiss = 0; - for ( i = 0; i < nlevs*gridsize; i++ ) - if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) - { - data[i] = missval; - (*nmiss)++; - } + return nrecs; } void srvReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, int *nmiss) { - int vlistID, fileID; - int nlevs, gridID, gridsize; - off_t recpos, currentfilepos; - int header[8]; - int tsid; - int recID; - int i; - double missval; + if ( CDI_Debug ) Message("streamID = %d varID = %d levID = %d", streamptr->self, varID, levID); + void *srvp = streamptr->record->exsep; - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; /* NOTE: tiles are not supported here! */ - nlevs = streamptr->vars[varID].recordTable[0].nlevs; - missval = vlistInqVarMissval(vlistID, varID); - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - tsid = streamptr->curTsID; + double missval = vlistInqVarMissval(vlistID, varID); + int gridsize = gridInqSize(vlistInqVarGrid(vlistID, varID)); + int tsid = streamptr->curTsID; - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", - nlevs, gridID, gridsize); - - currentfilepos = fileGetPos(fileID); + off_t currentfilepos = fileGetPos(fileID); /* NOTE: tiles are not supported here! */ - recID = streamptr->vars[varID].recordTable[0].recordID[levID]; - recpos = streamptr->tsteps[tsid].records[recID].position; + int recID = streamptr->vars[varID].recordTable[0].recordID[levID]; + off_t recpos = streamptr->tsteps[tsid].records[recID].position; fileSetPos(fileID, recpos, SEEK_SET); - if (srvRead(fileID, srvp) < 0) - abort(); + if ( srvRead(fileID, srvp) < 0 ) abort(); + int header[8]; srvInqHeader(srvp, header); srvInqDataDP(srvp, data); fileSetPos(fileID, currentfilepos, SEEK_SET); *nmiss = 0; - for ( i = 0; i < gridsize; i++ ) + for ( int i = 0; i < gridsize; i++ ) if ( DBL_IS_EQUAL(data[i], missval) || DBL_IS_EQUAL(data[i], (float)missval) ) { data[i] = missval; @@ -781,105 +677,39 @@ void srvReadVarSliceDP(stream_t *streamptr, int varID, int levID, double *data, } -void srvWriteVarDP(stream_t *streamptr, int varID, const double *data) +void srvReadVarDP(stream_t *streamptr, int varID, double *data, int *nmiss) { - int fileID; - int levID, nlevs, gridID, gridsize; - int zaxisID; - double level; - int header[8]; - int xsize, ysize; - int datatype; - int tsID; - int vlistID; - int pdis, pcat, pnum; - srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep; - - if ( CDI_Debug ) - Message("streamID = %d varID = %d", streamptr->self, varID); - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - tsID = streamptr->curTsID; - gridID = vlistInqVarGrid(vlistID, varID); - gridsize = gridInqSize(gridID); - zaxisID = vlistInqVarZaxis(vlistID, varID); - nlevs = zaxisInqSize(zaxisID); - - if ( CDI_Debug ) - Message("nlevs = %d gridID = %d gridsize = %d", nlevs, gridID, gridsize); - - cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis); - - header[0] = pnum; - header[2] = streamptr->tsteps[tsID].taxis.vdate; - header[3] = streamptr->tsteps[tsID].taxis.vtime; + if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID); - xsize = gridInqXsize(gridID); - ysize = gridInqYsize(gridID); - if ( xsize == 0 || ysize == 0 ) - { - xsize = gridInqSize(gridID); - ysize = 1; - } - if ( gridInqType(gridID) == GRID_UNSTRUCTURED ) ysize = 1; - if ( gridInqSize(gridID) != xsize*ysize ) - Error("Internal problem with gridsize!"); - - header[4] = xsize; - header[5] = ysize; - header[6] = 0; - header[7] = 0; - - datatype = vlistInqVarDatatype(vlistID, varID); - - srvp->dprec = srvDefDatatype(datatype); - - for ( levID = 0; levID < nlevs; levID++ ) - { - level = zaxisInqLevel(zaxisID, levID); + int vlistID = streamptr->vlistID; + size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID)); + size_t nlevs = (size_t) streamptr->vars[varID].recordTable[0].nlevs; - header[1] = (int) level; - srvDefHeader(srvp, header); - srvDefDataDP(srvp, &data[levID*gridsize]); - srvWrite(fileID, srvp); - } + for ( size_t levID = 0; levID < nlevs; levID++) + srvReadVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize], nmiss); } void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double *data) { - int fileID; - int gridID; - int zaxisID; - double level; - int header[8]; - int xsize, ysize; - int datatype; - int tsID; - int vlistID; - int pdis, pcat, pnum; - srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - tsID = streamptr->curTsID; - gridID = vlistInqVarGrid(vlistID, varID); - zaxisID = vlistInqVarZaxis(vlistID, varID); - level = zaxisInqLevel(zaxisID, levID); + if ( CDI_Debug ) Message("streamID = %d varID = %d levID = %d", streamptr->self, varID, levID); - if ( CDI_Debug ) - Message("gridID = %d zaxisID = %d", gridID, zaxisID); + int vlistID = streamptr->vlistID; + int fileID = streamptr->fileID; + int tsID = streamptr->curTsID; + int gridID = vlistInqVarGrid(vlistID, varID); + int pdis, pcat, pnum; cdiDecodeParam(vlistInqVarParam(vlistID, varID), &pnum, &pcat, &pdis); + int header[8]; header[0] = pnum; - header[1] = (int) level; + header[1] = (int) zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID); header[2] = streamptr->tsteps[tsID].taxis.vdate; header[3] = streamptr->tsteps[tsID].taxis.vtime; - xsize = gridInqXsize(gridID); - ysize = gridInqYsize(gridID); + int xsize = gridInqXsize(gridID); + int ysize = gridInqYsize(gridID); if ( xsize == 0 || ysize == 0 ) { xsize = gridInqSize(gridID); @@ -894,8 +724,9 @@ void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double header[6] = 0; header[7] = 0; - datatype = vlistInqVarDatatype(vlistID, varID); + int datatype = vlistInqVarDatatype(vlistID, varID); + srvrec_t *srvp = (srvrec_t*) streamptr->record->exsep; srvp->dprec = srvDefDatatype(datatype); srvDefHeader(srvp, header); @@ -903,7 +734,21 @@ void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double srvWrite(fileID, srvp); } + +void srvWriteVarDP(stream_t *streamptr, int varID, const double *data) +{ + if ( CDI_Debug ) Message("streamID = %d varID = %d", streamptr->self, varID); + + int vlistID = streamptr->vlistID; + size_t gridsize = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID)); + size_t nlevs = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID)); + + for ( size_t levID = 0; levID < nlevs; levID++ ) + srvWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]); +} + #endif /* HAVE_LIBSERVICE */ + /* * Local Variables: * c-file-style: "Java" diff --git a/src/taxis.c b/src/taxis.c index a0db8d524df3a7ff27d62327eaaf9b873b2d3808..111358562e1ce094c6e5c341a270759a6698e2a9 100644 --- a/src/taxis.c +++ b/src/taxis.c @@ -112,7 +112,7 @@ const char *tunitNamePtr(int unitID) else name = Timeunits[0]; - return (name); + return name; } #if 0 @@ -150,7 +150,7 @@ static void taxisDefaultValue(taxis_t* taxisptr) { taxisptr->self = CDI_UNDEFID; - taxisptr->used = FALSE; + taxisptr->used = false; taxisptr->type = DefaultTimeType; taxisptr->vdate = 0; taxisptr->vtime = 0; @@ -161,8 +161,8 @@ void taxisDefaultValue(taxis_t* taxisptr) taxisptr->calendar = cdiDefaultCalendar; taxisptr->unit = DefaultTimeUnit; taxisptr->numavg = 0; - taxisptr->climatology = FALSE; - taxisptr->has_bounds = FALSE; + taxisptr->climatology = false; + taxisptr->has_bounds = false; taxisptr->vdate_lb = 0; taxisptr->vtime_lb = 0; taxisptr->vdate_ub = 0; @@ -187,20 +187,19 @@ taxisNewEntry(cdiResH resH) reshReplace(resH, taxisptr, &taxisOps); } - return (taxisptr); + return taxisptr; } static void taxisInit (void) { - static int taxisInitialized = 0; - char *env; + static bool taxisInitialized = false; if ( taxisInitialized ) return; - taxisInitialized = 1; + taxisInitialized = true; - env = getenv("TAXIS_DEBUG"); + char *env = getenv("TAXIS_DEBUG"); if ( env ) TAXIS_Debug = atoi(env); } @@ -248,8 +247,7 @@ taxisDefRtime(taxisID, 120000); */ int taxisCreate(int taxistype) { - if ( CDI_Debug ) - Message("taxistype: %d", taxistype); + if ( CDI_Debug ) Message("taxistype: %d", taxistype); taxisInit (); @@ -258,10 +256,9 @@ int taxisCreate(int taxistype) int taxisID = taxisptr->self; - if ( CDI_Debug ) - Message("taxisID: %d", taxisID); + if ( CDI_Debug ) Message("taxisID: %d", taxisID); - return (taxisID); + return taxisID; } void taxisDestroyKernel(taxis_t *taxisptr) @@ -303,11 +300,11 @@ int taxisDuplicate(int taxisID1) int taxisID2 = taxisptr2->self; - if ( CDI_Debug ) - Message("taxisID2: %d", taxisID2); + if ( CDI_Debug ) Message("taxisID2: %d", taxisID2); ptaxisCopy(taxisptr2, taxisptr1); - return (taxisID2); + + return taxisID2; } @@ -555,7 +552,7 @@ int taxisInqType(int taxisID) { taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps); - return (taxisptr->type); + return taxisptr->type; } @@ -563,7 +560,7 @@ int taxisHasBounds(int taxisID) { taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps); - return (taxisptr->has_bounds); + return taxisptr->has_bounds; } @@ -571,9 +568,9 @@ void taxisDeleteBounds(int taxisID) { taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps ); - if (taxisptr->has_bounds != FALSE) + if ( taxisptr->has_bounds ) { - taxisptr->has_bounds = FALSE; + taxisptr->has_bounds = false; reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE); } } @@ -630,7 +627,7 @@ int taxisInqVdate(int taxisID) { taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps); - return (taxisptr->vdate); + return taxisptr->vdate; } @@ -647,13 +644,13 @@ void taxisDefVdateBounds(int taxisID, int vdate_lb, int vdate_ub) { taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps ); - if (taxisptr->vdate_lb != vdate_lb - || taxisptr->vdate_ub != vdate_ub - || taxisptr->has_bounds != TRUE) + if ( taxisptr->vdate_lb != vdate_lb + || taxisptr->vdate_ub != vdate_ub + || taxisptr->has_bounds == false ) { taxisptr->vdate_lb = vdate_lb; taxisptr->vdate_ub = vdate_ub; - taxisptr->has_bounds = TRUE; + taxisptr->has_bounds = true; reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE); } } @@ -678,7 +675,7 @@ int taxisInqVtime(int taxisID) { taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps); - return (taxisptr->vtime); + return taxisptr->vtime; } @@ -695,13 +692,13 @@ void taxisDefVtimeBounds(int taxisID, int vtime_lb, int vtime_ub) { taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps ); - if (taxisptr->vtime_lb != vtime_lb - || taxisptr->vtime_ub != vtime_ub - || taxisptr->has_bounds != TRUE) + if ( taxisptr->vtime_lb != vtime_lb + || taxisptr->vtime_ub != vtime_ub + || taxisptr->has_bounds == false ) { taxisptr->vtime_lb = vtime_lb; taxisptr->vtime_ub = vtime_ub; - taxisptr->has_bounds = TRUE; + taxisptr->has_bounds = true; reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE); } } @@ -733,7 +730,7 @@ int taxisInqRdate(int taxisID) reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE); } - return (taxisptr->rdate); + return taxisptr->rdate; } /* @@ -763,7 +760,7 @@ int taxisInqRtime(int taxisID) reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE); } - return (taxisptr->rtime); + return taxisptr->rtime; } /* @@ -792,7 +789,7 @@ int taxisInqFdate(int taxisID) taxisptr->ftime = taxisptr->vtime; } - return (taxisptr->fdate); + return taxisptr->fdate; } /* @@ -821,7 +818,7 @@ int taxisInqFtime(int taxisID) taxisptr->ftime = taxisptr->vtime; } - return (taxisptr->ftime); + return taxisptr->ftime; } /* @@ -847,7 +844,7 @@ int taxisInqCalendar(int taxisID) { taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps ); - return (taxisptr->calendar); + return taxisptr->calendar; } @@ -855,7 +852,7 @@ int taxisInqTunit(int taxisID) { taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps ); - return (taxisptr->unit); + return taxisptr->unit; } @@ -879,7 +876,7 @@ int taxisInqNumavg(int taxisID) { taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps ); - return (taxisptr->numavg); + return taxisptr->numavg; } @@ -887,7 +884,7 @@ taxis_t *taxisPtr(int taxisID) { taxis_t *taxisptr = (taxis_t *)reshGetVal(taxisID, &taxisOps); - return (taxisptr); + return taxisptr; } void @@ -918,8 +915,6 @@ ptaxisDefLongname(taxis_t *taxisptr, const char *longname) static void cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs) { - static int lwarn = TRUE; - *days = 0; *secs = 0; @@ -964,10 +959,11 @@ cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs) } else { + static bool lwarn = true; if ( lwarn ) { Warning("timeunit %s unsupported!", tunitNamePtr(timeunit)); - lwarn = FALSE; + lwarn = false; } } } @@ -975,8 +971,6 @@ cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs) static void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue) { - static int lwarn = TRUE; - if ( timeunit == TUNIT_SECOND ) { *timevalue = days*86400. + secs; @@ -1000,10 +994,11 @@ void cdiEncodeTimevalue(int days, int secs, int timeunit, double *timevalue) } else { + static bool lwarn = true; if ( lwarn ) { Warning("timeunit %s unsupported!", tunitNamePtr(timeunit)); - lwarn = FALSE; + lwarn = false; } } } @@ -1087,7 +1082,7 @@ double vtime2timeval(int vdate, int vtime, taxis_t *taxis) rtime = (*taxis).vtime; } - if ( rdate == 0 && rtime == 0 && vdate == 0 && vtime == 0 ) return(value); + if ( rdate == 0 && rtime == 0 && vdate == 0 && vtime == 0 ) return value; cdiDecodeDate(rdate, &ryear, &rmonth, &day); cdiDecodeTime(rtime, &hour, &minute, &second); @@ -1140,7 +1135,7 @@ double vtime2timeval(int vdate, int vtime, taxis_t *taxis) value /= 30; } - return (value); + return value; } @@ -1172,7 +1167,6 @@ splitTimevalue(double timevalue, int timeunit, int *date, int *time) int vdate = 0, vtime = 0; int hour, minute, second; int year, month, day; - static int lwarn = TRUE; if ( timeunit == TUNIT_SECOND ) { @@ -1212,10 +1206,11 @@ splitTimevalue(double timevalue, int timeunit, int *date, int *time) } else { + static bool lwarn = true; if ( lwarn ) { Warning("timeunit %s unsupported!", tunitNamePtr(timeunit)); - lwarn = FALSE; + lwarn = false; } } @@ -1236,9 +1231,10 @@ splitTimevalue(double timevalue, int timeunit, int *date, int *time) vdate = cdiEncodeDate(year, month, day); vtime = cdiEncodeTime(hour, minute, second); + static bool lwarn = true; if ( lwarn ) { - lwarn = FALSE; + lwarn = false; Warning("Reset wrong date/time to %4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d!", year, month, day, hour, minute, second); } @@ -1355,7 +1351,7 @@ double cdiEncodeTimeval(int date, int time, taxis_t *taxis) else timevalue = vtime2timeval(date, time, taxis); - return (timevalue); + return timevalue; } @@ -1435,13 +1431,13 @@ taxisPrintKernel(taxis_t * taxisptr, FILE * fp) "fc_unit = %d\n" "fc_period = %g\n" "\n", taxisptr->self, taxisptr->self, - taxisptr->used, taxisptr->type, + (int)taxisptr->used, taxisptr->type, taxisptr->vdate, taxisptr->vtime, taxisptr->rdate, taxisptr->rtime, taxisptr->fdate, taxisptr->ftime, taxisptr->calendar, taxisptr->unit, - taxisptr->numavg, taxisptr->climatology, - taxisptr->has_bounds, + taxisptr->numavg, (int)taxisptr->climatology, + (int) taxisptr->has_bounds, vdate_lb, vtime_lb, vdate_ub, vtime_ub, taxisptr->fc_unit, taxisptr->fc_period ); } diff --git a/src/taxis.h b/src/taxis.h index 78cf402d688d6b154f31d2f764fe20ad3246e975..122071e162a7103ff3e26a2fa17d103ab935cff1 100644 --- a/src/taxis.h +++ b/src/taxis.h @@ -1,6 +1,8 @@ #ifndef _TAXIS_H #define _TAXIS_H +#include <stdbool.h> + #ifndef RESOURCE_HANDLE_H #include "resource_handle.h" #endif @@ -9,7 +11,7 @@ typedef struct { /* Date format YYYYMMDD */ /* Time format hhmmss */ int self; - short used; + bool used; short has_bounds; int type; // time type int vdate; // verification date @@ -21,7 +23,7 @@ typedef struct { int calendar; int unit; // time unit int numavg; - int climatology; + bool climatology; int vdate_lb; // lower bounds of vdate int vtime_lb; // lower bounds of vtime int vdate_ub; // upper bounds of vdate diff --git a/src/util.c b/src/util.c index cef54cf8356bcec52f95075f96a14b590b059276..42c62a9c28747cc9ffb1a465517efd7b1e12dd70 100644 --- a/src/util.c +++ b/src/util.c @@ -30,6 +30,7 @@ void cdiPrintDatatypes(void) "+-------------+-------+\n" "| char | %3d |\n" "+-------------+-------+\n" + "| bool | %3d |\n" "| short | %3d |\n" "| int | %3d |\n" "| long | %3d |\n" @@ -48,7 +49,7 @@ void cdiPrintDatatypes(void) "| FLT64 | %-9s |\n" "+-------------+-----------+\n" "\n byte ordering is %s\n\n", - (int) sizeof(void *), (int) sizeof(char), + (int) sizeof(void *), (int) sizeof(char), (int) sizeof(bool), (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(long long), (int) sizeof(size_t), (int) sizeof(off_t), (int) sizeof(float), (int) sizeof(double), (int) sizeof(long double), diff --git a/src/varscan.c b/src/varscan.c index d89fa3297dc0e2edd083cf3f8661c7d0d4454022..c9898ace450f59154de332d1c42d5be79bad1ff4 100644 --- a/src/varscan.c +++ b/src/varscan.c @@ -122,7 +122,7 @@ paramInitEntry(unsigned varID, int param) vartable[varID].tableID = UNDEFID; vartable[varID].typeOfGeneratingProcess = UNDEFID; vartable[varID].productDefinitionTemplate = UNDEFID; - vartable[varID].comptype = COMPRESS_NONE; + vartable[varID].comptype = CDI_COMPRESS_NONE; vartable[varID].complevel = 1; vartable[varID].lmissval = 0; vartable[varID].missval = 0; @@ -1054,7 +1054,7 @@ void varDefMissval(int varID, double missval) void varDefCompType(int varID, int comptype) { - if ( vartable[varID].comptype == COMPRESS_NONE ) + if ( vartable[varID].comptype == CDI_COMPRESS_NONE ) vartable[varID].comptype = comptype; } diff --git a/src/vlist.c b/src/vlist.c index f941413990d66391de32e1df6ecc91d8f566cbc6..7db10e1192db9441c6045fb02133784ce00956ed 100644 --- a/src/vlist.c +++ b/src/vlist.c @@ -12,7 +12,7 @@ #include "namespace.h" #include "resource_handle.h" #include "vlist_var.h" -#include "vlist_att.h" +#include "cdi_att.h" #include "resource_unpack.h" #include "serialize.h" @@ -47,8 +47,7 @@ static int vlistIsInitialized = 0; static int vlist_compare(vlist_t *a, vlist_t *b) { - int diff; - diff = (a->nvars != b->nvars) | (a->ngrids != b->ngrids) + int diff = (a->nvars != b->nvars) | (a->ngrids != b->ngrids) | (a->nzaxis != b->nzaxis) | (a->instID != b->instID) | (a->modelID != b->modelID) | (a->tableID != b->tableID) | (a->ntsteps != b->ntsteps) | (a->atts.nelems != b->atts.nelems); @@ -57,7 +56,7 @@ vlist_compare(vlist_t *a, vlist_t *b) diff |= vlistVarCompare(a, varID, b, varID); size_t natts = a->atts.nelems; for (size_t attID = 0; attID < natts; ++attID) - diff |= vlist_att_compare(a, CDI_GLOBAL, b, CDI_GLOBAL, (int)attID); + diff |= cdi_att_compare(a, CDI_GLOBAL, b, CDI_GLOBAL, (int)attID); return diff; } @@ -77,8 +76,8 @@ const resOps vlistOps = { (valCompareFunc)vlist_compare, (valDestroyFunc)vlist_delete, - (valPrintFunc)vlistPrintKernel - , vlistGetSizeP, + (valPrintFunc)vlistPrintKernel, + vlistGetSizeP, vlistPackP, vlistTxCode }; @@ -87,7 +86,7 @@ resOps vlistOps = { vlist_t *vlist_to_pointer(int vlistID) { VLIST_INIT(); - return (vlist_t*) reshGetVal(vlistID, &vlistOps ); + return (vlist_t*) reshGetVal(vlistID, &vlistOps); } static @@ -109,7 +108,7 @@ void vlist_init_entry(vlist_t *vlistptr) vlistptr->atts.nalloc = MAX_ATTRIBUTES; vlistptr->atts.nelems = 0; vlistptr->nsubtypes = 0; - for (int i=0; i<MAX_SUBTYPES_PS; i++) + for ( int i = 0; i < MAX_SUBTYPES_PS; i++ ) vlistptr->subtypeIDs[i] = CDI_UNDEFID; } @@ -125,15 +124,13 @@ vlist_t *vlist_new_entry(cdiResH resH) vlistptr->self = resH; reshReplace(resH, vlistptr, &vlistOps); } - return (vlistptr); + return vlistptr; } static void vlist_delete_entry(vlist_t *vlistptr) { - int idx; - - idx = vlistptr->self; + int idx = vlistptr->self; reshRemove(idx, &vlistOps ); @@ -146,9 +143,7 @@ void vlist_delete_entry(vlist_t *vlistptr) static void vlist_initialize(void) { - char *env; - - env = getenv("VLIST_DEBUG"); + char *env = getenv("VLIST_DEBUG"); if ( env ) VLIST_Debug = atoi(env); #ifndef HAVE_LIBPTHREAD vlistIsInitialized = TRUE; @@ -210,7 +205,7 @@ int vlistCreate(void) vlist_t *vlistptr = vlist_new_entry(CDI_UNDEFID); if ( CDI_Debug ) Message("create vlistID = %d", vlistptr->self); - return (vlistptr->self); + return vlistptr->self; } static void @@ -219,7 +214,7 @@ vlist_delete(vlist_t *vlistptr) int vlistID = vlistptr->self; if ( CDI_Debug ) Message("call to vlist_delete, vlistID = %d", vlistID); - vlistDelAtts(vlistID, CDI_GLOBAL); + cdiDelAtts(vlistID, CDI_GLOBAL); int nvars = vlistptr->nvars; var_t *vars = vlistptr->vars; @@ -245,7 +240,7 @@ vlist_delete(vlist_t *vlistptr) vlistptr->vars[varID].opt_grib_kvpair_size = 0; vlistptr->vars[varID].opt_grib_kvpair = NULL; - vlistDelAtts(vlistID, varID); + cdiDelAtts(vlistID, varID); } if ( vars ) Free(vars); @@ -348,7 +343,7 @@ void vlistCopy(int vlistID2, int vlistID1) var_t *vars2 = vlistptr2->vars; vlist_copy(vlistptr2, vlistptr1); - vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL); + cdiCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL); if ( vars1 ) { @@ -365,7 +360,7 @@ void vlistCopy(int vlistID2, int vlistID1) var_copy_entries(&vars2[varID], &vars1[varID]); vlistptr2->vars[varID].atts.nelems = 0; - vlistCopyVarAtts(vlistID1, varID, vlistID2, varID); + cdiCopyVarAtts(vlistID1, varID, vlistID2, varID); if ( vars1[varID].levinfo ) { @@ -399,22 +394,21 @@ int vlistDuplicate(int vlistID) int vlistIDnew = vlistCreate(); vlistCopy(vlistIDnew, vlistID); - return (vlistIDnew); + return vlistIDnew; } void vlistClearFlag(int vlistID) { - int varID, levID; vlist_t *vlistptr = vlist_to_pointer(vlistID); - for ( varID = 0; varID < vlistptr->nvars; varID++ ) + for ( int varID = 0; varID < vlistptr->nvars; varID++ ) { vlistptr->vars[varID].flag = FALSE; if ( vlistptr->vars[varID].levinfo ) { int nlevs = zaxisInqSize(vlistptr->vars[varID].zaxisID); - for ( levID = 0; levID < nlevs; levID++ ) + for ( int levID = 0; levID < nlevs; levID++ ) vlistptr->vars[varID].levinfo[levID].flag = FALSE; } } @@ -506,7 +500,7 @@ int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, const double * vlistptr->nzaxis++; } - return (zaxisID); + return zaxisID; } /* @@ -532,7 +526,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1) vlist_copy(vlistptr2, vlistptr1); - vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL); + cdiCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL); if ( vlistptr1->vars ) { @@ -574,7 +568,7 @@ void vlistCopyFlag(int vlistID2, int vlistID1) var_copy_entries(&vars2[varID2], &vars1[varID]); vlistptr2->vars[varID2].atts.nelems = 0; - vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2); + cdiCopyVarAtts(vlistID1, varID, vlistID2, varID2); int nlevs = zaxisInqSize(vars1[varID].zaxisID); int nlevs2 = 0; @@ -738,7 +732,7 @@ void vlistCat(int vlistID2, int vlistID1) } vars2[varID2].atts.nelems = 0; - vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2); + cdiCopyVarAtts(vlistID1, varID, vlistID2, varID2); vlistAdd2GridIDs(vlistptr2, vars1[varID].gridID); vlistAdd2ZaxisIDs(vlistptr2, vars1[varID].zaxisID); @@ -896,28 +890,28 @@ The function @func{vlistNvars} returns the number of variables in the variable l int vlistNvars(int vlistID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->nvars); + return vlistptr->nvars; } int vlistNrecs(int vlistID) { - int nrecs = 0; vlist_t *vlistptr = vlist_to_pointer(vlistID); + int nrecs = 0; for ( int varID = 0; varID < vlistptr->nvars; varID++ ) nrecs += zaxisInqSize(vlistptr->vars[varID].zaxisID); - return (nrecs); + return nrecs; } int vlistNumber(int vlistID) { - int number, number2, datatype; + int number, number2; vlist_t *vlistptr = vlist_to_pointer(vlistID); - datatype = vlistptr->vars[0].datatype; + int datatype = vlistptr->vars[0].datatype; if ( datatype== DATATYPE_CPX32 || datatype == DATATYPE_CPX64 ) number = CDI_COMP; else @@ -938,7 +932,7 @@ int vlistNumber(int vlistID) } } - return (number); + return number; } /* @@ -961,7 +955,7 @@ int vlistNgrids(int vlistID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->ngrids); + return vlistptr->ngrids; } /* @@ -984,7 +978,7 @@ int vlistNzaxis(int vlistID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->nzaxis); + return vlistptr->nzaxis; } @@ -992,7 +986,7 @@ int vlistNsubtypes(int vlistID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->nsubtypes); + return vlistptr->nsubtypes; } @@ -1000,7 +994,7 @@ void vlistDefNtsteps(int vlistID, int nts) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - if (vlistptr->ntsteps != nts) + if ( vlistptr->ntsteps != nts ) { vlistptr->ntsteps = nts; reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE); @@ -1122,7 +1116,7 @@ void vlistDefTaxis(int vlistID, int taxisID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - if (vlistptr->taxisID != taxisID) + if ( vlistptr->taxisID != taxisID ) { //FIXME: This code seems to leak a taxis_t object if `vlistptr->taxisID` was valid before the call to vlistDefTaxis. vlistptr->taxisID = taxisID; @@ -1150,7 +1144,7 @@ int vlistInqTaxis(int vlistID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->taxisID); + return vlistptr->taxisID; } @@ -1158,7 +1152,7 @@ void vlistDefTable(int vlistID, int tableID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - if (vlistptr->tableID != tableID) + if ( vlistptr->tableID != tableID ) { vlistptr->tableID = tableID; reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE); @@ -1170,7 +1164,7 @@ int vlistInqTable(int vlistID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->tableID); + return vlistptr->tableID; } @@ -1178,7 +1172,7 @@ void vlistDefInstitut(int vlistID, int instID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - if (vlistptr->instID != instID) + if ( vlistptr->instID != instID ) { vlistptr->instID = instID; reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE); @@ -1205,7 +1199,7 @@ int vlistInqInstitut(int vlistID) vlistDefInstitut(vlistID, instID); } - return (instID); + return instID; } @@ -1213,7 +1207,7 @@ void vlistDefModel(int vlistID, int modelID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - if (vlistptr->modelID != modelID) + if ( vlistptr->modelID != modelID ) { vlistptr->modelID = modelID; reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE); @@ -1241,7 +1235,7 @@ int vlistInqModel(int vlistID) vlistDefModel(vlistID, modelID); } - return (modelID); + return modelID; } @@ -1257,7 +1251,7 @@ int vlistGridsizeMax(int vlistID) if ( gridsize > gridsizemax ) gridsizemax = gridsize; } - return (gridsizemax); + return gridsizemax; } @@ -1269,7 +1263,7 @@ int vlistGrid(int vlistID, int index) if ( index < vlistptr->ngrids && index >= 0 ) gridID = vlistptr->gridIDs[index]; - return (gridID); + return gridID; } @@ -1283,7 +1277,7 @@ int vlistGridIndex(int vlistID, int gridID) if ( index == vlistptr->ngrids ) index = -1; - return (index); + return index; } @@ -1337,7 +1331,7 @@ int vlistZaxis(int vlistID, int index) if ( index < vlistptr->nzaxis && index >= 0 ) zaxisID = vlistptr->zaxisIDs[index]; - return (zaxisID); + return zaxisID; } @@ -1351,7 +1345,7 @@ int vlistZaxisIndex(int vlistID, int zaxisID) if ( index == vlistptr->nzaxis ) index = -1; - return (index); + return index; } @@ -1455,15 +1449,14 @@ int vlistHasTime(int vlistID) break; } - return (hastime); + return hastime; } enum { vlist_nints=6, }; -static int -vlistTxCode ( void ) +static int vlistTxCode ( void ) { return VLIST; } @@ -1476,7 +1469,7 @@ int vlistGetSizeP ( void * vlistptr, void *context) vlist_t *p = (vlist_t*) vlistptr; txsize = serializeGetSize(vlist_nints, DATATYPE_INT, context); txsize += serializeGetSize(1, DATATYPE_LONG, context); - txsize += vlistAttsGetSize(p, CDI_GLOBAL, context); + txsize += cdiAttsGetSize(p, CDI_GLOBAL, context); for ( varID = 0; varID < p->nvars; varID++ ) txsize += vlistVarGetPackSize(p, varID, context); return txsize; @@ -1498,7 +1491,7 @@ void vlistPackP ( void * vlistptr, void * buf, int size, int *position, serializePack(tempbuf, vlist_nints, DATATYPE_INT, buf, size, position, context); serializePack(&p->ntsteps, 1, DATATYPE_LONG, buf, size, position, context); - vlistAttsPack(p, CDI_GLOBAL, buf, size, position, context); + cdiAttsPack(p, CDI_GLOBAL, buf, size, position, context); for ( varID = 0; varID < p->nvars; varID++ ) { vlistVarPack(p, varID, (char *)buf, size, position, context); @@ -1522,7 +1515,7 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace, p->instID = namespaceAdaptKey(tempbuf[4], originNamespace); p->modelID = namespaceAdaptKey(tempbuf[5], originNamespace); serializeUnpack(buf, size, position, &p->ntsteps, 1, DATATYPE_LONG, context); - vlistAttsUnpack(targetID, CDI_GLOBAL, buf, size, position, context); + cdiAttsUnpack(targetID, CDI_GLOBAL, buf, size, position, context); for (int varID = 0; varID < nvars; varID++ ) vlistVarUnpack(targetID, buf, size, position, originNamespace, context); reshSetStatus(targetID, &vlistOps, @@ -1532,11 +1525,10 @@ void vlistUnpack(char * buf, int size, int *position, int originNamespace, void vlist_check_contents(int vlistID) { - int index, nzaxis, zaxisID; + int zaxisID; + int nzaxis = vlistNzaxis(vlistID); - nzaxis = vlistNzaxis(vlistID); - - for ( index = 0; index < nzaxis; index++ ) + for ( int index = 0; index < nzaxis; index++ ) { zaxisID = vlistZaxis(vlistID, index); if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC ) diff --git a/src/vlist.h b/src/vlist.h index 0179579653421d4468d407ebe9874d5b58492169..be254df7690440a7d2e25d467be99d264bdf5546 100644 --- a/src/vlist.h +++ b/src/vlist.h @@ -17,30 +17,7 @@ #define VALIDMISS 1.e+303 -/* - * CDI attribute - */ -typedef struct { - size_t xsz; /* amount of space at xvalue */ - size_t namesz; /* size of name */ - char *name; /* attribute name */ - int indtype; /* internal data type of xvalue (INT, FLT or TXT) */ - int exdtype; /* external data type */ - /* indtype exdtype */ - /* TXT TXT */ - /* INT INT16, INT32 */ - /* FLT FLT32, FLT64 */ - size_t nelems; /* number of elements */ - void *xvalue; /* the actual data */ -} cdi_att_t; - - -typedef struct { - size_t nalloc; /* number allocated >= nelems */ - size_t nelems; /* length of the array */ - cdi_att_t value[MAX_ATTRIBUTES]; -} cdi_atts_t; - +#include "cdi_att.h" typedef struct { @@ -117,9 +94,9 @@ var_t; typedef struct { //set when a vlist is passed to streamDefVlist() to safeguard against modifications of the wrong vlist object - bool immutable; + bool immutable; //set if this vlist has been created by CDI itself, and must not be destroyed by the user, consequently - bool internal; + bool internal; int self; int nvars; /* number of variables */ int ngrids; @@ -154,8 +131,8 @@ void vlistDefVarTsteptype(int vlistID, int varID, int tsteptype); int vlistInqVarMissvalUsed(int vlistID, int varID); int vlistHasTime(int vlistID); -int vlistDelAtts(int vlistID, int varID); -int vlistCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2); +int cdiDelAtts(int vlistID, int varID); +int cdiCopyVarAtts(int vlistID1, int varID_1, int vlistID2, int varID_2); void vlistUnpack(char * buffer, int bufferSize, int * pos, int originNamespace, void *context, int force_id); @@ -168,7 +145,7 @@ int vlistInqVarValidrange(int vlistID, int varID, double *validrange); void vlistInqVarDimorder(int vlistID, int varID, int (*outDimorder)[3]); -int vlist_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum); +int cdi_att_compare(vlist_t *a, int varIDA, vlist_t *b, int varIDB, int attnum); void resize_opt_grib_entries(var_t *var, int nentries); diff --git a/src/vlist_att.h b/src/vlist_att.h deleted file mode 100644 index c42b36438b56ad453aea959feb26494ffcf86175..0000000000000000000000000000000000000000 --- a/src/vlist_att.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef VLIST_ATT_H -#define VLIST_ATT_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -int -vlistAttsGetSize(vlist_t *p, int varID, void *context); - -void -vlistAttsPack(vlist_t *p, int varID, - void * buf, int size, int *position, void *context); - -void -vlistAttsUnpack(int vlistID, int varID, - void * buf, int size, int *position, void *context); - - -#endif - -/* - * Local Variables: - * c-file-style: "Java" - * c-basic-offset: 2 - * indent-tabs-mode: nil - * show-trailing-whitespace: t - * require-trailing-newline: t - * End: - */ diff --git a/src/vlist_var.c b/src/vlist_var.c index 12b63f0138a98ca2b74745275aaa9dd841acd756..a38cc5a0be6110f9a4405c608506970cbabe4b79 100644 --- a/src/vlist_var.c +++ b/src/vlist_var.c @@ -10,7 +10,7 @@ #include "vlist.h" #include "vlist_var.h" #include "resource_handle.h" -#include "vlist_att.h" +#include "cdi_att.h" #include "namespace.h" #include "serialize.h" #include "error.h" @@ -54,7 +54,7 @@ void vlistvarInitEntry(int vlistID, int varID) vlistptr->vars[varID].units = NULL; vlistptr->vars[varID].extra = NULL; vlistptr->vars[varID].levinfo = NULL; - vlistptr->vars[varID].comptype = COMPRESS_NONE; + vlistptr->vars[varID].comptype = CDI_COMPRESS_NONE; vlistptr->vars[varID].complevel = 1; vlistptr->vars[varID].atts.nalloc = MAX_ATTRIBUTES; vlistptr->vars[varID].atts.nelems = 0; @@ -114,7 +114,7 @@ int vlistvarNewEntry(int vlistID) vlistptr->vars[varID].isUsed = TRUE; - return (varID); + return varID; } void vlistCheckVarID(const char *caller, int vlistID, int varID) @@ -134,12 +134,12 @@ void vlistCheckVarID(const char *caller, int vlistID, int varID) int vlistDefVarTiles(int vlistID, int gridID, int zaxisID, int tsteptype, int tilesetID) { - vlist_t *vlistptr = vlist_to_pointer(vlistID); if ( CDI_Debug ) Message("gridID = %d zaxisID = %d tsteptype = %d", gridID, zaxisID, tsteptype); int varID = vlistvarNewEntry(vlistID); + vlist_t *vlistptr = vlist_to_pointer(vlistID); vlistptr->nvars++; vlistptr->vars[varID].gridID = gridID; vlistptr->vars[varID].zaxisID = zaxisID; @@ -158,7 +158,8 @@ int vlistDefVarTiles(int vlistID, int gridID, int zaxisID, int tsteptype, int ti vlistptr->vars[varID].param = cdiEncodeParam(-(varID + 1), 255, 255); reshSetStatus(vlistID, &vlistOps, RESH_DESYNC_IN_USE); - return (varID); + + return varID; } /* @@ -317,7 +318,7 @@ int vlistInqVarGrid(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].gridID); + return vlistptr->vars[varID].gridID; } /* @@ -343,7 +344,7 @@ int vlistInqVarZaxis(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].zaxisID); + return vlistptr->vars[varID].zaxisID; } @@ -364,7 +365,8 @@ int vlistInqVarSubtype(int vlistID, int varID) vlist_t *vlistptr = vlist_to_pointer(vlistID); vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].subtypeID); + + return vlistptr->vars[varID].subtypeID; } @@ -391,7 +393,7 @@ int vlistInqVarParam(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].param); + return vlistptr->vars[varID].param; } /* @@ -428,7 +430,7 @@ int vlistInqVarCode(int vlistID, int varID) tableInqParCode(vlistptr->vars[varID].tableID, vlistptr->vars[varID].name, &code); } - return (code); + return code; } @@ -438,7 +440,7 @@ const char *vlistInqVarNamePtr(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].name); + return vlistptr->vars[varID].name; } @@ -448,7 +450,7 @@ const char *vlistInqVarLongnamePtr(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].longname); + return vlistptr->vars[varID].longname; } @@ -458,7 +460,7 @@ const char *vlistInqVarStdnamePtr(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].stdname); + return vlistptr->vars[varID].stdname; } @@ -468,7 +470,7 @@ const char *vlistInqVarUnitsPtr(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].units); + return vlistptr->vars[varID].units; } /* @@ -715,10 +717,10 @@ int vlistInqVarID(int vlistID, int code) int param = vlistptr->vars[varID].param; int pdis, pcat, pnum; cdiDecodeParam(param, &pnum, &pcat, &pdis); - if ( pnum == code ) return (varID); + if ( pnum == code ) return varID; } - return (CDI_UNDEFID); + return CDI_UNDEFID; } @@ -726,8 +728,7 @@ int vlistInqVarSize(int vlistID, int varID) { vlistCheckVarID(__func__, vlistID, varID); - int zaxisID, gridID; - int tsteptype; + int zaxisID, gridID, tsteptype; vlistInqVar(vlistID, varID, &gridID, &zaxisID, &tsteptype); int nlevs = zaxisInqSize(zaxisID); @@ -736,7 +737,7 @@ int vlistInqVarSize(int vlistID, int varID) int size = gridsize*nlevs; - return (size); + return size; } /* @@ -765,7 +766,7 @@ int vlistInqVarDatatype(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].datatype); + return vlistptr->vars[varID].datatype; } @@ -780,7 +781,7 @@ int vlistInqVarNumber(int vlistID, int varID) vlistptr->vars[varID].datatype == DATATYPE_CPX64 ) number = CDI_COMP; - return (number); + return number; } /* @@ -840,7 +841,7 @@ void vlistDefVarInstitut(int vlistID, int varID, int instID) int vlistInqVarInstitut(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].instID); + return vlistptr->vars[varID].instID; } @@ -858,7 +859,7 @@ void vlistDefVarModel(int vlistID, int varID, int modelID) int vlistInqVarModel(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].modelID); + return vlistptr->vars[varID].modelID; } @@ -884,7 +885,7 @@ void vlistDefVarTable(int vlistID, int varID, int tableID) int vlistInqVarTable(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].tableID); + return vlistptr->vars[varID].tableID; } /* @@ -1046,7 +1047,7 @@ double vlistInqVarMissval(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].missval); + return vlistptr->vars[varID].missval; } /* @@ -1156,7 +1157,7 @@ int vlistInqVarValidrange(int vlistID, int varID, double *validrange) validrange[1] = vlistptr->vars[varID].validrange[1]; } - return (vlistptr->vars[varID].lvalidrange); + return vlistptr->vars[varID].lvalidrange; } @@ -1179,7 +1180,7 @@ double vlistInqVarScalefactor(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].scalefactor); + return vlistptr->vars[varID].scalefactor; } @@ -1189,7 +1190,7 @@ double vlistInqVarAddoffset(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].addoffset); + return vlistptr->vars[varID].addoffset; } @@ -1254,7 +1255,7 @@ The valid CDI timestep types are @func{TSTEP_CONSTANT}, @func{TSTEP_INSTANT}, int vlistInqVarTsteptype(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].tsteptype); + return vlistptr->vars[varID].tsteptype; } @@ -1272,7 +1273,7 @@ void vlistDefVarTimave(int vlistID, int varID, int timave) int vlistInqVarTimave(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].timave); + return vlistptr->vars[varID].timave; } @@ -1290,7 +1291,7 @@ void vlistDefVarTimaccu(int vlistID, int varID, int timaccu) int vlistInqVarTimaccu(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].timaccu); + return vlistptr->vars[varID].timaccu; } @@ -1308,7 +1309,7 @@ void vlistDefVarTypeOfGeneratingProcess(int vlistID, int varID, int typeOfGenera int vlistInqVarTypeOfGeneratingProcess(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].typeOfGeneratingProcess); + return vlistptr->vars[varID].typeOfGeneratingProcess; } @@ -1327,8 +1328,7 @@ void vlistDefVarProductDefinitionTemplate(int vlistID, int varID, int productDef int vlistInqVarProductDefinitionTemplate(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - - return (vlistptr->vars[varID].productDefinitionTemplate); + return vlistptr->vars[varID].productDefinitionTemplate; } @@ -1386,7 +1386,7 @@ void vlistDestroyVarUnits(int vlistID, int varID) int vlistInqVarMissvalUsed(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].missvalused); + return vlistptr->vars[varID].missvalused; } @@ -1425,7 +1425,7 @@ int vlistInqFlag(int vlistID, int varID, int levID) vlist_t *vlistptr = vlist_to_pointer(vlistID); if (vlistptr->vars[varID].levinfo) - return (vlistptr->vars[varID].levinfo[levID].flag); + return vlistptr->vars[varID].levinfo[levID].flag; else { levinfo_t li = DEFAULT_LEVINFO(levID); @@ -1450,7 +1450,7 @@ int vlistFindVar(int vlistID, int fvarID) Message("varID not found for fvarID %d in vlistID %d!", fvarID, vlistID); } - return (varID); + return varID; } @@ -1477,14 +1477,14 @@ int vlistFindLevel(int vlistID, int fvarID, int flevelID) } } - return (levelID); + return levelID; } int vlistMergedVar(int vlistID, int varID) { vlist_t *vlistptr = vlist_to_pointer(vlistID); - return (vlistptr->vars[varID].mvarID); + return vlistptr->vars[varID].mvarID; } @@ -1523,7 +1523,7 @@ int vlistInqIndex(int vlistID, int varID, int levelID) vlist_t *vlistptr = vlist_to_pointer(vlistID); if (vlistptr->vars[varID].levinfo) - return (vlistptr->vars[varID].levinfo[levelID].index); + return vlistptr->vars[varID].levinfo[levelID].index; else { levinfo_t li = DEFAULT_LEVINFO(levelID); @@ -1612,7 +1612,7 @@ int vlistInqVarCompType(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].comptype); + return vlistptr->vars[varID].comptype; } @@ -1636,7 +1636,7 @@ int vlistInqVarCompLevel(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].complevel); + return vlistptr->vars[varID].complevel; } @@ -1660,7 +1660,7 @@ int vlistInqVarChunkType(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].chunktype); + return vlistptr->vars[varID].chunktype; } static @@ -1737,7 +1737,7 @@ int vlistInqVarXYZ(int vlistID, int varID) vlistCheckVarID(__func__, vlistID, varID); - return (vlistptr->vars[varID].xyz); + return vlistptr->vars[varID].xyz; } /* Ensemble Info Routines */ @@ -1774,7 +1774,7 @@ int vlistInqVarEnsemble( int vlistID, int varID, int *ensID, int *ensCount, int status = 1; } - return (status); + return status; } @@ -2064,7 +2064,7 @@ int vlistVarCompare(vlist_t *a, int varIDA, vlist_t *b, int varIDB) if (natts != b->vars[varIDB].atts.nelems) return 1; for (size_t attID = 0; attID < natts; ++attID) - diff |= vlist_att_compare(a, varIDA, b, varIDB, (int)attID); + diff |= cdi_att_compare(a, varIDA, b, varIDB, (int)attID); if ((diff |= ((pva->ensdata == NULL) ^ (pvb->ensdata == NULL)))) return 1; if (pva->ensdata) @@ -2096,7 +2096,7 @@ int vlistVarGetPackSize(vlist_t *p, int varID, void *context) varsize += serializeGetSize((int)strlen(var->extra), DATATYPE_TXT, context); varsize += serializeGetSize(4 * zaxisInqSize(var->zaxisID), DATATYPE_INT, context); - varsize += vlistAttsGetSize(p, varID, context); + varsize += cdiAttsGetSize(p, varID, context); return varsize; } @@ -2164,7 +2164,7 @@ void vlistVarPack(vlist_t *p, int varID, char * buf, int size, int *position, serializePack(levbuf, nlevs * 4, DATATYPE_INT, buf, size, position, context); } - vlistAttsPack(p, varID, buf, size, position, context); + cdiAttsPack(p, varID, buf, size, position, context); } static inline int @@ -2273,7 +2273,7 @@ void vlistVarUnpack(int vlistID, char * buf, int size, int *position, vlistDefFlag(vlistID, newvar, flagSetLev, levbuf[flagSetLev][0]); } vlistDefVarIOrank(vlistID, newvar, tempbuf[19]); - vlistAttsUnpack(vlistID, newvar, buf, size, position, context); + cdiAttsUnpack(vlistID, newvar, buf, size, position, context); } diff --git a/tests/Makefile.in b/tests/Makefile.in index 632acad8d7edb5f0ae2cd046e44a1d53e27bfd2b..1e41e342b627643057655f43938bced46eb9958e 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -390,11 +390,9 @@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -JASPER_LIBS = @JASPER_LIBS@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_LIBS = @LIBPNG_LIBS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -418,7 +416,6 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ -OPENJPEG_LIBS = @OPENJPEG_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ @@ -500,7 +497,6 @@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ -openjpeg_LIBS = @openjpeg_LIBS@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ diff --git a/tests/test_cdf_read.c b/tests/test_cdf_read.c index a870617d74d8b06331c95592300449250b1a6c6d..31f9567f13e0367fdf125f4b74c21c0b66e86b79 100644 --- a/tests/test_cdf_read.c +++ b/tests/test_cdf_read.c @@ -81,11 +81,11 @@ printAtts(int vlistID) int nAtts, attType, attLen; char attName[CDI_MAX_NAME + 1]; int varID = (int)varIdx - 1; - vlistInqNatts(vlistID, varID, &nAtts); + cdiInqNatts(vlistID, varID, &nAtts); for (size_t attIdx = 0; attIdx < (size_t)nAtts; attIdx++ ) { - int rc = vlistInqAtt(vlistID, varID, (int)attIdx, - attName, &attType, &attLen); + int rc = cdiInqAtt(vlistID, varID, (int)attIdx, + attName, &attType, &attLen); { const char *varDesc = varIdx > 0 ? (sprintf((char *)buf, "%s%d", varDescPrefix, @@ -126,14 +126,14 @@ printAtts(int vlistID) switch (attType) { case DATATYPE_TXT: - rc = vlistInqAttTxt(vlistID, (int)varID, attName, - attLen, (char *)buf); + rc = cdiInqAttTxt(vlistID, (int)varID, attName, + attLen, (char *)buf); if (rc == CDI_NOERR) printf("\"%.*s\"", attLen, (char *)buf); break; case DATATYPE_FLT: - rc = vlistInqAttFlt(vlistID, (int)varID, attName, - attLen + 1, (double *)buf); + rc = cdiInqAttFlt(vlistID, (int)varID, attName, + attLen + 1, (double *)buf); if (rc == CDI_NOERR && attLen) { const double *restrict dp = (const double*)buf; @@ -143,8 +143,8 @@ printAtts(int vlistID) } break; case DATATYPE_INT: - rc = vlistInqAttInt(vlistID, (int)varID, attName, - attLen + 1, (int *)buf); + rc = cdiInqAttInt(vlistID, (int)varID, attName, + attLen + 1, (int *)buf); if (rc == CDI_NOERR && attLen) { const int *restrict ip = (const int *)buf; diff --git a/tests/test_cdf_write.c b/tests/test_cdf_write.c index 43e01b3f5b0185002bcf47c99edc123824b5c151..def2f4f97ead6904e115b35b02d7846b813799ea 100644 --- a/tests/test_cdf_write.c +++ b/tests/test_cdf_write.c @@ -82,8 +82,8 @@ int main(int argc, const char **argv) vlistDefVarMissval(vlistID, varID, missValue); { static const char creatorText[] = "CDI test_cdf_write"; - vlistDefAttTxt(vlistID, varID, "CDI Text Attribute test, created by", - sizeof (creatorText) - 1, creatorText); + cdiDefAttTxt(vlistID, varID, "CDI Text Attribute test, created by", + sizeof (creatorText) - 1, creatorText); } int taxisID = taxisCreate(TAXIS_ABSOLUTE); diff --git a/tests/test_resource_copy.c b/tests/test_resource_copy.c index 9d09677055cc4b3b95dceca56e183c003fb42eb8..dcb9a07183c6da60e9e59c8dac0f70c59258c724 100644 --- a/tests/test_resource_copy.c +++ b/tests/test_resource_copy.c @@ -164,11 +164,10 @@ static struct idPair defineVlist ( int gridID, int zaxisID, int taxisID ) vlistDefVarName(vlistID, varID1, "varname1"); { int globfac[] = { 23, 42 }; - vlistDefAttInt(vlistID, varID1, "seer's globule factors", DATATYPE_INT16, - 2, globfac); + cdiDefAttInt(vlistID, varID1, "seer's globule factors", DATATYPE_INT16, 2, globfac); } vlistDefVarName(vlistID, varID2, "varname2"); - vlistDefAttTxt(vlistID, varID2, "txt demo", 6, "banana"); + cdiDefAttTxt(vlistID, varID2, "txt demo", 6, "banana"); vlistDefTaxis(vlistID, taxisID); int vlistID2 = vlistCreate(); vlistDefVar(vlistID2, gridID, zaxisID, TIME_VARIABLE);