diff --git a/ChangeLog b/ChangeLog index 7d1c5ab2ea063744967e811242bab9cc6c880070..60d0a39cd565c2e01a08634b16d6a5fcfd979c00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,19 @@ -2024-11-?? Uwe Schulzweida +2024-11-28 Uwe Schulzweida * using CGRIBEX library version 2.3.1 * Version 2.5.0 released +2024-11-23 Uwe Schulzweida + + * NetCDF: improved HealPIX support + +2024-11-04 Uwe Schulzweida + + * reset chunktype if z and t are chunked + 2024-10-24 Uwe Schulzweida + * lock access to NCZARR in CDI_Threadsafe mode * Renamed interface functions streamXXXRecord to streamXXXField 2024-10-22 Uwe Schulzweida diff --git a/NEWS b/NEWS index 358f410f56ea015f82b75fc039c596b33b527c0c..d21b4942d545009488a8b484d6f3d109096da300 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,26 @@ CDI NEWS -------- +Version 2.5.0 (28 Nov 2024): + + Changes: + * NetCDF: improved HealPIX support + * reset chunktype if z and t are chunked + * lock access to NCZARR in CDI_Threadsafe mode + +Version 2.4.4 (19 Sep 2024): + + Fixed bugs: + * absolute timeaxis failed with timeunits seconds [Bug #11916] + +Version 2.4.2 (21 Jun 2024): + + Changes: + * NetCDF4: improved calculation of input chunk cache size + * NetCDF4: switched off output chunk cache + Fixed bugs: + * cdiInqContents: missing lock of non thread-safe netCDF4/HDF5 calls (bug fix) + Version 2.4.1 (21 May 2024): Changes: diff --git a/src/stream.c b/src/stream.c index 8ebd6be67f58a15144661505f6d1f7bed42bda93..8da402e54315b32ad325dd10d22a20672be9b5e9 100644 --- a/src/stream.c +++ b/src/stream.c @@ -671,10 +671,17 @@ streamOpenID(const char *filename, char filemode, int filetype, int resH) #ifndef HAVE_NC4HDF5_THREADSAFE if (CDI_Threadsafe) { -#ifndef HAVE_LIBPTHREAD - Error("CDI threadsafe failed, pthread support not compiled in!"); +#ifdef HAVE_LIBPTHREAD + if (filetype == CDI_FILETYPE_NC4 || filetype == CDI_FILETYPE_NC4C || filetype == CDI_FILETYPE_NCZARR) + streamptr->lockIO = true; +#else + static bool lwarn = true; + if (lwarn) + { + lwarn = false; + Warning("CDI threadsafe failed, pthread support not compiled in!"); + } #endif - if (filetype == CDI_FILETYPE_NC4 || filetype == CDI_FILETYPE_NC4C) streamptr->lockIO = true; } #endif diff --git a/src/stream_cdf_i.c b/src/stream_cdf_i.c index a58121a27b819e4e3933634768aaa35dd9a98fc3..9b7565a012bdd95b2b93a32f63d07e6db6648768 100644 --- a/src/stream_cdf_i.c +++ b/src/stream_cdf_i.c @@ -55,6 +55,7 @@ typedef struct int ncid; int varStatus; bool ignoreVar; + bool isHealPIX; bool isCubeSphere; bool isCharAxis; bool isXaxis; @@ -544,8 +545,8 @@ cdf_time_dimid(int fileID, int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvar if (dimid0 != CDI_UNDEFID && check_dimids[dimid0] == false) { - check_dimids[dimid0] = true; if (ncdims[dimid0].ncvarid != CDI_UNDEFID && ncdims[dimid0].ncvarid != varid) continue; + check_dimids[dimid0] = true; char sbuf[CDI_MAX_NAME]; for (int iatt = 0; iatt < ncvar->nattsNC; ++iatt) @@ -588,6 +589,7 @@ init_ncvars(int nvars, ncvar_t *ncvars, int ncid) ncvar->ncid = ncid; ncvar->varStatus = UndefVar; ncvar->ignoreVar = false; + ncvar->isHealPIX = false; ncvar->isCubeSphere = false; ncvar->isCharAxis = false; ncvar->isXaxis = false; @@ -1486,6 +1488,14 @@ scan_vars_attr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int model { ncvar->gmapid = nc_gmap_id; cdf_set_var(&ncvars[ncvar->gmapid], CoordVar); + int nc_gmap_varid = ncvars[ncvar->gmapid].ncid; + if (cdfCheckAttText(nc_gmap_varid, nc_gmap_id, "grid_mapping_name")) + { + char gridMappingName[CDI_MAX_NAME]; + cdfGetAttText(nc_gmap_varid, nc_gmap_id, "grid_mapping_name", CDI_MAX_NAME, gridMappingName); + // if (str_is_equal(gridMappingName, "healpix")) ncvars[ncvar->gmapid].isHealPIX = true; + if (str_is_equal(gridMappingName, "healpix")) ncvar->isHealPIX = true; + } } else Warning("%s - %s", nc_strerror(status), attstring); @@ -1702,6 +1712,31 @@ verify_vars_attr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) } } +static void +find_dimtypes(ncvar_t *ncvars, ncvar_t *ncvar, bool *plxdim, bool *plydim, bool *plzdim, int *plcdim) +{ + bool lxdim = false, lydim = false, lzdim = false /*, ltdim = false */; + int lcdim = 0; + int ndims = ncvar->ndims; + for (int i = 0; i < ndims; i++) + { + int dimtype = ncvar->dimtypes[i]; + lxdim |= (dimtype == X_AXIS); + lydim |= (dimtype == Y_AXIS); + lzdim |= (dimtype == Z_AXIS); + if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++; + // ltdim |= (dimtype == T_AXIS); + } + + if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true; + if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true; + + *plxdim = lxdim; + *plydim = lydim; + *plzdim = lzdim; + *plcdim = lcdim; +} + static void cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) { @@ -1733,22 +1768,10 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) if (ncvar->varStatus == DataVar) { bool lxdim = false, lydim = false, lzdim = false /* , ltdim = false */; - int lcdim = 0; - int ndims = ncvar->ndims; - for (int i = 0; i < ndims; i++) - { - int dimtype = ncvar->dimtypes[i]; - lxdim |= (dimtype == X_AXIS); - lydim |= (dimtype == Y_AXIS); - lzdim |= (dimtype == Z_AXIS); - if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++; - // ltdim |= (dimtype == T_AXIS); - } - + int lcdim; + find_dimtypes(ncvars, ncvar, &lxdim, &lydim, &lzdim, &lcdim); int allcdims = lcdim; - - if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true; - if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true; + int ndims = ncvar->ndims; if (lxdim && (lydim || ncvar->gridtype == GRID_UNSTRUCTURED)) for (int i = ndims - 1; i >= 0; i--) @@ -1796,21 +1819,9 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) { bool lxdim = false, lydim = false, lzdim = false /*, ltdim = false */; int lcdim = 0; - int ndims = ncvar->ndims; - for (int i = 0; i < ndims; i++) - { - int dimtype = ncvar->dimtypes[i]; - lxdim |= (dimtype == X_AXIS); - lydim |= (dimtype == Y_AXIS); - lzdim |= (dimtype == Z_AXIS); - if (ncvar->cvarids[i] != CDI_UNDEFID) lcdim++; - // ltdim |= (dimtype == T_AXIS); - } - + find_dimtypes(ncvars, ncvar, &lxdim, &lydim, &lzdim, &lcdim); int allcdims = lcdim; - - if (!lxdim && ncvar->xvarid != CDI_UNDEFID && ncvars[ncvar->xvarid].ndims == 0) lxdim = true; - if (!lydim && ncvar->yvarid != CDI_UNDEFID && ncvars[ncvar->yvarid].ndims == 0) lydim = true; + int ndims = ncvar->ndims; // if ( ndims > 1 ) for (int i = ndims - 1; i >= 0; i--) @@ -1829,7 +1840,7 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) dimtype = X_AXIS; lxdim = true; } - else if (!lydim && ncvar->gridtype != GRID_UNSTRUCTURED) + else if (!lydim && ncvar->gridtype != GRID_UNSTRUCTURED && ncvar->isHealPIX == false) // else if ( !lydim && ! (ncvars[ncvar->xvarid].dimids[0] == ncvars[ncvar->yvarid].dimids[0] && // ncvars[ncvar->xvarid].ndims == 1 && ncvars[ncvar->yvarid].ndims == 1)) { @@ -2075,19 +2086,21 @@ grid_set_chunktype(grid_t *grid, ncvar_t *ncvar) if (ncvar->isChunked) { int ndims = ncvar->ndims; + size_t chunkSizeAllDims = 1; + for (int i = 0; i < ndims; ++i) chunkSizeAllDims *= ncvar->chunks[i]; + size_t dimN = ncvar->chunks[ndims - 1]; if (grid->type == GRID_UNSTRUCTURED) { - size_t chunkSize = ncvar->chunks[ndims - 1]; + size_t chunkSize = (chunkSizeAllDims == dimN) ? dimN : 0; ncvar->chunkType = (chunkSize == grid->size) ? CDI_CHUNK_GRID : CDI_CHUNK_AUTO; if (ncvar->chunkType == CDI_CHUNK_AUTO && chunkSize > 1) ncvar->chunkSize = (int) chunkSize; } 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]) + if (grid->x.size > 1 && grid->y.size > 1 && ndims > 1 && grid->x.size == dimN && 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]) + else if (grid->x.size > 1 && grid->x.size == dimN && chunkSizeAllDims == dimN) ncvar->chunkType = CDI_CHUNK_LINES; else ncvar->chunkType = CDI_CHUNK_AUTO; @@ -4270,7 +4283,7 @@ cdfVerifyVars(int nvars, ncvar_t *ncvars } static CdiDateTime -wrf_read_timestep(int fileID, int nctimevarid, int tsID) +wrf_read_timestep(int fileID, int nctimevarid, size_t tsID) { enum { @@ -4278,7 +4291,7 @@ wrf_read_timestep(int fileID, int nctimevarid, int tsID) dateTimeSepPos = 19, dateTimeStrSize = 128, }; - size_t start[2] = { (size_t) tsID, 0 }, count[2] = { 1, dateTimeSepPos }; + size_t start[2] = { tsID, 0 }, count[2] = { 1, dateTimeSepPos }; char stvalue[dateTimeStrSize]; stvalue[0] = 0; cdf_get_vara_text(fileID, nctimevarid, start, count, stvalue); @@ -4324,7 +4337,7 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0) int fileID = streamptr->fileID; int nctimevarid = streamptr->basetime.ncvarid; int nctimeboundsid = streamptr->basetime.ncvarboundsid; - bool hasTimesteps = (nctimevarid != CDI_UNDEFID && streamptr->basetime.hasUnits); + bool hasTimesteps = (nctimevarid != CDI_UNDEFID /*&& streamptr->basetime.hasUnits*/); int *ncStepIndices = (int *) Malloc(numTimesteps * sizeof(int)); for (size_t tsID = 0; tsID < numTimesteps; ++tsID) ncStepIndices[tsID] = (int) tsID; @@ -4337,10 +4350,9 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0) if (streamptr->basetime.isWRF) { - for (size_t tsID = 0; tsID < numTimesteps; ++tsID) - vDateTimeList[tsID] = wrf_read_timestep(fileID, nctimevarid, (int) tsID); + for (size_t tsID = 0; tsID < numTimesteps; ++tsID) vDateTimeList[tsID] = wrf_read_timestep(fileID, nctimevarid, tsID); } - else + else if (streamptr->basetime.hasUnits) { double *timevarBuffer = (double *) Malloc(numTimesteps * sizeof(double)); cdf_get_var_double(fileID, nctimevarid, timevarBuffer); @@ -4348,6 +4360,10 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0) vDateTimeList[tsID] = cdi_decode_timeval(get_timevalue(fileID, nctimevarid, tsID, timevarBuffer), taxis0); if (timevarBuffer) Free(timevarBuffer); } + else + { + hasTimesteps = false; + } } // process query information if available @@ -4383,6 +4399,7 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0) } if (ncStepIndices) Free(ncStepIndices); + if (vDateTimeList) Free(vDateTimeList); if (hasTimesteps) { @@ -4421,8 +4438,6 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0) } } } - - if (vDateTimeList) Free(vDateTimeList); } } @@ -4503,7 +4518,7 @@ find_coordinates_vars(int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvars) // set time dependent data vars static void -find_varying_data_vars(int timedimid, int nvars, ncvar_t *ncvars) +find_varying_data_vars1d(int timedimid, int nvars, ncvar_t *ncvars) { for (int ncvarid = 0; ncvarid < nvars; ncvarid++) { @@ -4637,9 +4652,9 @@ cdfInqContents(stream_t *streamptr) if (CDI_Convert_Cubesphere) check_cube_sphere(vlistID, nvars, ncvars, ncdims); - if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find_varying_data_vars"); + if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find_varying_data_vars1d"); - find_varying_data_vars(timedimid, nvars, ncvars); + find_varying_data_vars1d(timedimid, nvars, ncvars); // find time vars bool timeHasUnits = false;