diff --git a/.ci/bb/breeze-mpim/test.all.clang b/.ci/bb/breeze-mpim/test.all.clang index 4396928c68c250a4e4ffec8438115620d321142d..6ca92e801cebe97dc9a3d07c0bdb1a3319c0bda5 100755 --- a/.ci/bb/breeze-mpim/test.all.clang +++ b/.ci/bb/breeze-mpim/test.all.clang @@ -9,15 +9,6 @@ top_srcdir=$(cd "${script_dir}/../../.."; pwd) . "${script_dir}/init.sh" init_clang -# Check the formatting. Note that git-clang-format might keep redundant blank -# lines. Therefore, we use clang-format: -find src app interfaces tests examples \ - \( -name '*.h' -o -name '*.hpp' -o -name '*.c' -o -name '*.cpp' \) -a \ - ! -path 'interfaces/python/cdi_wrapper.cpp' -a \ - ! -path 'interfaces/ruby/cdi_wrapper.cpp' -a \ - ! -path 'src/cdilib.c' \ - | xargs -n 1 -P 8 clang-format --Werror --dry-run --verbose - enable_maintainer_mode='no' if test ! -f "${top_srcdir}/configure"; then "${top_srcdir}/autogen.sh" @@ -41,9 +32,9 @@ FCFLAGS='-g -O2 -no-pie' \ MPI_LAUNCH="${MPI_LAUNCH}" \ PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig" -make -j8 +make -make -j8 check || { cat tests/test-suite.log; exit 1; } +make check || { cat tests/test-suite.log; exit 1; } check_all_tests_passed tests/test-suite.log diff --git a/.ci/bb/breeze-mpim/test.all.nag b/.ci/bb/breeze-mpim/test.all.nag index 68b2618a265fde6e05ad92cbe541814c297926c1..93c4c7939a0cd09b5e73a819384a6c40afa46d9f 100755 --- a/.ci/bb/breeze-mpim/test.all.nag +++ b/.ci/bb/breeze-mpim/test.all.nag @@ -16,7 +16,7 @@ test -f "${top_srcdir}/configure" || "${top_srcdir}/autogen.sh" # Use GCC from the path when compiling/linking Fortran code: export FCFLAGS="-g -O2 -Wc=$(which gcc)" -make -j8 distcheck DISTCHECK_CONFIGURE_FLAGS=" \ +make distcheck DISTCHECK_CONFIGURE_FLAGS=" \ --disable-maintainer-mode \ --enable-cf-interface \ --enable-iso-c-interface \ @@ -30,7 +30,10 @@ FC='${MPIFC}' \ FCFLAGS='${FCFLAGS}' \ MPI_LAUNCH='${MPI_LAUNCH}' \ PKG_CONFIG_PATH='${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig' \ -" | tee >(sed -n '/^Testsuite summary for cdi/,/^# ERROR:/p' > tests/test-suite.log) +" | tee >( + sed 's/'$'\033''\[\([0-9]\{1,2\}\(;[0-9]\{1,2\}\)\?\)\?[mK]//g' | + sed -n '/^Testsuite summary for cdi/,/^# ERROR:/p' > tests/test-suite.log +) check_all_tests_passed tests/test-suite.log diff --git a/.ci/bb/breeze-mpim/test.all.nv b/.ci/bb/breeze-mpim/test.all.nv index 4025ba7b5c2e8294d342e52efc9af9b294c1c34b..20c0f73671af09674fd00b922bfbddbd81442888 100755 --- a/.ci/bb/breeze-mpim/test.all.nv +++ b/.ci/bb/breeze-mpim/test.all.nv @@ -34,7 +34,7 @@ FC="${MPIFC}" \ MPI_LAUNCH="${MPI_LAUNCH}" \ PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig" -make -j8 +make # Check that an executable is not overlinked to libscalesppmcore.so: tested_file='examples/pio/collectData.parallel' @@ -55,7 +55,7 @@ if test -n "${invalid_needed}"; then exit 1 fi -make -j8 check || { cat tests/test-suite.log; exit 1; } +make check || { cat tests/test-suite.log; exit 1; } check_all_tests_passed tests/test-suite.log diff --git a/.ci/bb/breeze-mpim/test.ru-py.gcc b/.ci/bb/breeze-mpim/test.ru-py.gcc index f514da1f6ca178cd888ce0a6194b04fcbf5c4bbb..c8a933cd2bd42913f61fa3611726b7d3b56d93ef 100755 --- a/.ci/bb/breeze-mpim/test.ru-py.gcc +++ b/.ci/bb/breeze-mpim/test.ru-py.gcc @@ -29,16 +29,16 @@ fi CC="${CC}" \ CXX="${CXX}" -make -j8 +make -make -j8 check || { cat interfaces/test-suite.log tests/test-suite.log; exit 1; } +make check || { cat interfaces/test-suite.log tests/test-suite.log; exit 1; } check_all_tests_passed interfaces/test-suite.log check_no_git_untracked # Check the installation: -make -j8 install +make install export RUBYLIB="$(find "${install_dir}" -name 'Cdi.so' -printf '%h'):${RUBYLIB-}" ruby ./interfaces/ruby/test.rb ./interfaces/testdata/mulval.grb ruby ./interfaces/ruby/test.rb ./interfaces/testdata/mulval.nc @@ -47,7 +47,7 @@ python ./interfaces/python/test.py ./interfaces/testdata/mulval.grb python ./interfaces/python/test.py ./interfaces/testdata/mulval.nc # Check the uninstallation: -make -j8 uninstall +make uninstall remaining_files=$(find "${install_dir}" -type f) || { echo "ERROR: failed to get the list of files in the installation prefix '${install_dir}'" >&2 exit 1 diff --git a/.ci/bb/daint-cscs/init.sh b/.ci/bb/daint-cscs/init.sh deleted file mode 100644 index 489b2dafdd7c269a073d1c1691a20ace4564d37b..0000000000000000000000000000000000000000 --- a/.ci/bb/daint-cscs/init.sh +++ /dev/null @@ -1,81 +0,0 @@ -# Initialize utility functions: -. "$(cd "$(dirname "${BASH_SOURCE}")"; pwd)/../common_utils.sh" - -# -# Initializes the environment. -# -init_env () -{ - AUTOMAKE_ROOT='/project/d56/libcdi-ci-sw/gcc-11.2.0-haswell/automake-1.16.3-46gthis' - export PATH="${AUTOMAKE_ROOT}/bin:${PATH-}" - # Tell the custom installation of Automake where the libtool macros are: - export ACLOCAL_PATH="/usr/share/aclocal:${ACLOCAL_PATH-}" -} - -# -# Sets variables for tests with Cray. -# -init_cray () -{ - init_env - switch_for_module craype PrgEnv-cray cce/12.0.3 cray-mpich - - # Build and test against NetCDF that does not support MPI parallel invocations - # (parallel NetCDF4 tests are known to fail in this case when run from the - # user home directory on Daint): - switch_for_module cray-netcdf - - # Uncomment the following line to test against MPI-capable NetCDF: - # switch_for_module cray-netcdf-hdf5parallel cray-hdf5-parallel - - CC=cc - CXX=CC - FC=ftn - MPI_LAUNCH="$(which srun) -p cscsci -C gpu -A d56 -t 05:00" - - ECCODES_ROOT='/project/d56/libcdi-ci-sw/cce-12.0.3-haswell/eccodes-2.24.2-o2a4fw3' - PPM_ROOT='/project/d56/libcdi-ci-sw/cce-12.0.3-haswell/scales-ppm-1.0.8-44zlrlu' - YAXT_ROOT='/project/d56/libcdi-ci-sw/cce-12.0.3-haswell/yaxt-0.9.2.1-enz3pcz' - - # The installations of ecCodes, PPM and YAXT do not provide '*.la' files, - # which would trigger the RPATH injection: - export LD_LIBRARY_PATH="${ECCODES_ROOT}/lib64:${PPM_ROOT}/lib:${YAXT_ROOT}/lib:${LD_LIBRARY_PATH-}" -} - -# -# Sets variables for tests with PGI. -# -init_pgi () -{ - init_env - # We use deprecated versions (the most recent compatible with PGI though) of - # the Cray packages and have to make sure that the default versions are - # unloaded (otherwise, we get various warnings and errors): - module unload cray-mpich cray-netcdf cray-netcdf-hdf5parallel cray-hdf5 cray-hdf5-parallel - switch_for_module craype PrgEnv-pgi/6.0.8 pgi/20.1.1 cray-mpich/7.7.15 - - # Build and test against NetCDF that does not support MPI parallel invocations - # (parallel NetCDF4 tests are known to fail in this case when run from the - # user home directory on Daint): - switch_for_module cray-netcdf/4.7.4.0 cray-hdf5/1.12.0.0 - - # Uncomment the following line to test against MPI-capable NetCDF: - # switch_for_module cray-netcdf-hdf5parallel/4.7.4.0 cray-hdf5-parallel/1.12.0.0 - - CC=cc - CXX=CC - FC=ftn - MPI_LAUNCH="$(which srun) -p cscsci -C gpu -A d56 -t 05:00" - - ECCODES_ROOT='/project/d56/libcdi-ci-sw/pgi-20.1.1-haswell/eccodes-2.24.2-hwtl5nr' - PPM_ROOT='/project/d56/libcdi-ci-sw/pgi-20.1.1-haswell/scales-ppm-1.0.8-z2nxqya' - YAXT_ROOT='/project/d56/libcdi-ci-sw/pgi-20.1.1-haswell/yaxt-0.9.2.1-3orop7g' - - # The deprecated versions of the Cray packages are not in the default linker - # search path: - export LD_LIBRARY_PATH="${MPICH_DIR}/lib:${NETCDF_DIR}/lib:${HDF5_DIR}/lib:${LD_LIBRARY_PATH-}" - - # The installations of ecCodes, PPM and YAXT do not provide '*.la' files, - # which would trigger the RPATH injection: - export LD_LIBRARY_PATH="${ECCODES_ROOT}/lib64:${PPM_ROOT}/lib:${YAXT_ROOT}/lib:${LD_LIBRARY_PATH}" -} diff --git a/.ci/bb/daint-cscs/test.all.cray b/.ci/bb/daint-cscs/test.all.cray deleted file mode 100755 index 35921729d6a67d9cf0a23d77ff270aae9c9a7b0c..0000000000000000000000000000000000000000 --- a/.ci/bb/daint-cscs/test.all.cray +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -set -eu -set -o pipefail - -script_dir=$(cd "$(dirname "$0")"; pwd) -top_srcdir=$(cd "${script_dir}/../../.."; pwd) - -. "${script_dir}/init.sh" -init_cray - -# Save time for the person running this script manually: -if test "x${PE_NETCDF_MODULE_NAME}" = 'xcray-netcdf'; then - case $top_srcdir in - "${HOME}/"*) - echo "ERROR: parallel NetCDF4 tests are known to fail when CDI is built in the user home directory and linked against NetCDF that does not support MPI parallel invocations" >&2 - exit 1 - esac -fi - -enable_maintainer_mode='no' -if test ! -f "${top_srcdir}/configure"; then - "${top_srcdir}/autogen.sh" - # If there is no configure script, there are, most probably, no Fortran - # interface files, which are generated in the maintainer mode only: - enable_maintainer_mode='yes' -fi - -# The configure script does not check the 'lib64' subdirectory, therefore we -# run it with '--with-eccodes' and the following flags. Note that fixing this -# in the configure script might be tricky: the 'lib64' subdirectory should be -# checked first but if it does not exist or does not contain the library, we -# might end up linking to a library from the linker's default search path -# (e.g. /usr/lib) instead of the one from "$with_eccodes/lib" because -# "-L${with_eccodes}/lib64" would be ignored in that case: -CPPFLAGS="-I${ECCODES_ROOT}/include" -LDFLAGS="-L${ECCODES_ROOT}/lib64" - -"${top_srcdir}/configure" \ ---enable-cf-interface \ ---enable-iso-c-interface \ ---enable-maintainer-mode="${enable_maintainer_mode}" \ ---enable-mpi \ ---enable-option-checking=fatal \ ---enable-ppm-dist-array \ ---with-concurrent-mpi-checks \ ---with-eccodes \ ---with-netcdf \ -CC="${CC}" \ -CPPFLAGS="${CPPFLAGS}" \ -FC="${FC}" \ -LDFLAGS="${LDFLAGS}" \ -MPI_LAUNCH="${MPI_LAUNCH}" \ -PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig:${PKG_CONFIG_PATH}" - -make -j8 - -# Run with '-j' to submit as many MPI jobs as possible -# (see '--with-concurrent-mpi-checks'): -make -j check || { cat tests/test-suite.log; exit 1; } - -check_all_tests_passed tests/test-suite.log - -check_no_git_untracked diff --git a/.ci/bb/daint-cscs/test.all.pgi b/.ci/bb/daint-cscs/test.all.pgi deleted file mode 100755 index fde1e97b07b1a79a3bbe413a5e171df7b5696b69..0000000000000000000000000000000000000000 --- a/.ci/bb/daint-cscs/test.all.pgi +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -set -eu -set -o pipefail - -script_dir=$(cd "$(dirname "$0")"; pwd) -top_srcdir=$(cd "${script_dir}/../../.."; pwd) - -. "${script_dir}/init.sh" -init_pgi - -# Save time for the person running this script manually: -if test "x${PE_NETCDF_MODULE_NAME}" = 'xcray-netcdf'; then - case $top_srcdir in - "${HOME}/"*) - echo "ERROR: parallel NetCDF4 tests are known to fail when CDI is built in the user home directory and linked against NetCDF that does not support MPI parallel invocations" >&2 - exit 1 - esac -fi - -enable_maintainer_mode='no' -if test ! -f "${top_srcdir}/configure"; then - "${top_srcdir}/autogen.sh" - # If there is no configure script, there are, most probably, no Fortran - # interface files, which are generated in the maintainer mode only: - enable_maintainer_mode='yes' -fi - -# The configure script does not check the 'lib64' subdirectory, therefore we -# run it with '--with-eccodes' and the following flags. Note that fixing this -# in the configure script might be tricky: the 'lib64' subdirectory should be -# checked first but if it does not exist or does not contain the library, we -# might end up linking to a library from the linker's default search path -# (e.g. /usr/lib) instead of the one from "$with_eccodes/lib" because -# "-L${with_eccodes}/lib64" would be ignored in that case: -CPPFLAGS="-I${ECCODES_ROOT}/include" -LDFLAGS="-L${ECCODES_ROOT}/lib64" - -"${top_srcdir}/configure" \ ---enable-cf-interface \ ---enable-iso-c-interface \ ---enable-maintainer-mode="${enable_maintainer_mode}" \ ---enable-mpi \ ---enable-option-checking=fatal \ ---enable-ppm-dist-array \ ---with-concurrent-mpi-checks \ ---with-eccodes \ ---with-netcdf \ -CC="${CC}" \ -CPPFLAGS="${CPPFLAGS}" \ -FC="${FC}" \ -LDFLAGS="${LDFLAGS}" \ -MPI_LAUNCH="${MPI_LAUNCH}" \ -PKG_CONFIG_PATH="${YAXT_ROOT}/lib/pkgconfig:${PPM_ROOT}/lib/pkgconfig:${PKG_CONFIG_PATH}" \ -PTHREAD_LIBS='-lpthread' - -make -j8 - -# Run with '-j' to submit as many MPI jobs as possible -# (see '--with-concurrent-mpi-checks'): -make -j check || { cat tests/test-suite.log; exit 1; } - -check_all_tests_passed tests/test-suite.log - -check_no_git_untracked diff --git a/.ci/bb/levante-dkrz/init.sh b/.ci/bb/levante-dkrz/init.sh index 5cd38af4d2e0b2dd647acea3c409982019efc731..ac1d83807eaaf5a1b38d0aec5836a70bbb0e5d23 100644 --- a/.ci/bb/levante-dkrz/init.sh +++ b/.ci/bb/levante-dkrz/init.sh @@ -6,7 +6,7 @@ # init_env () { - switch_for_module ruby/3.0.2-gcc-11.2.0 + switch_for_module git ruby/3.0.2-gcc-11.2.0 } # diff --git a/.ci/bb/run_all.sh b/.ci/bb/run_all.sh index bba02cd2629b4f76830910b0153bba47acea8712..f5398d01ca77666941e0cdddcbbad5758a0b87a1 100755 --- a/.ci/bb/run_all.sh +++ b/.ci/bb/run_all.sh @@ -16,8 +16,6 @@ case $(uname -s) in test_environment='breeze-mpim' ;; levante*.lvt.dkrz.de\ *) test_environment='levante-dkrz' ;; - daint*.login.cscs.ch\ *) - test_environment='daint-cscs' ;; esac esac diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..f64790a7ae6ee4f621c48537c24bc70a0866f7b7 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,119 @@ +workflow: + auto_cancel: + on_new_commit: none + on_job_failure: none + rules: + - if: $CI_COMMIT_BRANCH == "master" + - if: $CI_COMMIT_BRANCH == "develop" + - if: $CI_COMMIT_BRANCH =~ /^cdi-.*-release$/ + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + auto_cancel: + on_new_commit: interruptible + on_job_failure: all + - if: $CI_PIPELINE_SOURCE == "web" + +stages: + - basic + - levante + - breeze + +.colorized: + variables: + DEFAULT: '\033[0m' + RED: '\033[0;31m' + +style: + stage: basic + extends: .colorized + variables: + GIT_DEPTH: 1 + STYLE_PATCH: ${CI_PROJECT_DIR}/style.patch + before_script: + - apk add black clang-extra-tools git py3-flake8 py3-isort py3-pip python3 + script: + - >- + clang-format --style=file -i + $(find src app interfaces tests examples + \( -name '*.h' -o -name '*.hpp' -o -name '*.c' -o -name '*.cpp' \) -a + ! -path 'interfaces/python/cdi_wrapper.cpp' -a + ! -path 'interfaces/ruby/cdi_wrapper.cpp' -a + ! -path 'src/cdilib.c') + - | + # Test if patching is necessary + test ! -s ${STYLE_PATCH} || { + printf "${RED}The source code does not meet the style recuirements. \ + Please, apply the patch (see artifacts).${DEFAULT}\n" + + printf "${RED}Note that the result of the formatting might depend on \ + the versions of the formatting tools. In this project, whatever \ + formatting this CI job produces is the correct one. If it expects \ + you to re-format parts of the source code that you did not modify, \ + do so in a separate commit, which must not be squashed, and list the \ + commit in the '.git-blame-ignore-revs' file.${DEFAULT}\n" + + exit 1 + } + artifacts: + paths: + - ${STYLE_PATCH} + expire_in: 60min + expose_as: 'Style Patch' + when: on_failure + tags: + - alpine + interruptible: true + +.common: + needs: [] + variables: + GIT_DEPTH: 1 + TASK_COUNT: 8 + MAKEFLAGS: --jobs=${TASK_COUNT} + AM_COLOR_TESTS: always + interruptible: true + +include: + - project: "anw_dienste/ci-templates" + file: ".slurm-ci.yml" + +.common-levante: + stage: levante + extends: + - .default + - .common + variables: + PARTITION: shared + TASK_COUNT: 8 + TIME_LIMIT: "15:00" + SCHEDULER_PARAMETERS: >- + --account=ka1125 + --partition=${PARTITION} + --ntasks=${TASK_COUNT} + --time=${TIME_LIMIT} + --nodes=1 + before_script: + - module purge + script: + - "${CI_PROJECT_DIR}/.ci/bb/levante-dkrz/${CI_JOB_NAME}" + +.common-breeze: + stage: breeze + extends: .common + before_script: + - module purge + script: + - "${CI_PROJECT_DIR}/.ci/bb/breeze-mpim/${CI_JOB_NAME}" + tags: + - mpim, breeze1-3 + +test.all.gcc: + extends: .common-levante + +test.all.intel-classic: + extends: .common-levante + +test.icon-pio.intel-classic: + extends: .common-levante + +test.icon.gcc: + extends: .common-levante diff --git a/CMakeLists.txt b/CMakeLists.txt index 71c43b56eb83dde30767073a4375a64f8d883746..20739bda0487b03968b1c27166b5a89765b5b0cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,29 +1,38 @@ -# cmake options: -# -# -DCMAKE_INSTALL_PREFIX=/path/to/install +cmake_minimum_required( VERSION 3.30 FATAL_ERROR ) -cmake_minimum_required( VERSION 3.12 FATAL_ERROR ) - -project( cdi VERSION 2.4.0 LANGUAGES C ) +project(libcdi VERSION 2.4.0 LANGUAGES C ) set(CMAKE_C_STANDARD 11) +include(CheckIncludeFile) + configure_file ( "${PROJECT_SOURCE_DIR}/cmake/cdi_config.h.in" - "${PROJECT_BINARY_DIR}/config.h" + "${PROJECT_SOURCE_DIR}/src/config.h" ) -include_directories("${PROJECT_BINARY_DIR}") - -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - -find_package(NetCDF) +find_package(hdf5 REQUIRED) +if(hdf5_FOUND) + message(STATUS "HDF5 shaed found") +else() + message(FATAL_ERROR "HDF shared not found") +endif() + +#NetCDF +find_package(netCDF COMPONENTS C REQUIRED) +set(netcdf_flag HAVE_LIBNETCDF) +set(netcdf_flag ${HAVE_LIBNETCDF}) +check_include_files("netcdf.h" ${netcdf_flag} C) +if (${netCDF_FOUND}) + message(STATUS "added compile definition HAVE_LIBNETCDF=${netCDF_FOUND}") + add_compile_definitions(HAVE_LIBNETCDF=${netCDF_FOUND}) +else() + message(WARNING "netcdf not found, compiling without netcdf") +endif () -set(HAVE_NETCDF ${netCDF_FOUND} ) -if (netCDF_FOUND) - set(HAVE_NETCDF 1) -endif () +#adding subdirectories +## lib and general files +add_subdirectory(src) +## cdi executable +add_subdirectory(app) -add_subdirectory( src ) -add_subdirectory( app ) -#target_link_libraries(cdi PRIVATE NetCDF) diff --git a/ChangeLog b/ChangeLog index be3386e10bbc5c5522d4bd83dfa96b02761d81d6..60d0a39cd565c2e01a08634b16d6a5fcfd979c00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +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 + + * NetCDF: search for time dimension only if it is undefined + +2024-10-21 Uwe Schulzweida + + * NetCDF: use positive attribute only for variables with undefined status + +2024-09-19 Uwe Schulzweida + + * Version 2.4.4 released + +2024-09-18 Uwe Schulzweida + + * absolute timeaxis failed with timeunits seconds [Bug #11916] + 2024-08-14 Uwe Schulzweida * Version 2.4.3 released 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/app/CMakeLists.txt b/app/CMakeLists.txt index 22bca89f702b3c330d8e9cfdf9f2ff7d493f6f4c..ce87f49683bff30ea6f52c4f06e33dc4d1bf135e 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -7,6 +7,6 @@ target_include_directories(cdi PUBLIC $<INSTALL_INTERFACE:include ) -target_link_libraries(cdi PUBLIC cdilib) +target_link_libraries(cdi PUBLIC cdilib netCDF::netcdf ${HDF5_LIBS} pthread) target_compile_definitions(cdi PUBLIC HAVE_CONFIG_H) diff --git a/app/cdi.c b/app/cdi.c index 0ff261e87665efcae74d8f730043966ef66ee978..819d74e3c1cd69eedde49f4a3eb764ab1483e6b1 100644 --- a/app/cdi.c +++ b/app/cdi.c @@ -175,8 +175,8 @@ usage(void) fprintf(stderr, " -E Use ecCodes to decode/encode GRIB1 messages\n"); fprintf(stderr, " -f <format> Format of the output file. (grb, grb2, nc, nc2, nc4, nc4c, nc5, nczarr, srv, ext or ieg)\n"); fprintf(stderr, " -i <num> Number of worker to decode/decompress GRIB records\n"); - fprintf(stderr, " -m Move records\n"); - fprintf(stderr, " -r Use CDI record API\n"); + fprintf(stderr, " -m Move fields\n"); + fprintf(stderr, " -r Use CDI field API\n"); fprintf(stderr, " -s give short information if ofile is missing\n"); fprintf(stderr, " -T Pre scan hole GRIB file to get the number of timesteps\n"); fprintf(stderr, " -t <table> Parameter table name/file\n"); @@ -765,7 +765,7 @@ main(int argc, char *argv[]) char *wTable = NULL; bool preScan = false; int Move = 0; - int Record = 0; + int Field = 0; int Variable = 0; int Debug = 0; int Vardis = 0; @@ -816,7 +816,7 @@ main(int argc, char *argv[]) case 'N': queryNames[numQueryNames++] = strdup(optarg); break; case 'n': Info = 0; NoInfo = 1; break; case 'R': cdiDefGlobal("REGULARGRID", 1); break; - case 'r': Record = 1; break; + case 'r': Field = 1; break; case 'X': Variable = 1; break; case 'S': queryStepidx[numQueryStepidx++] = atoi(optarg); break; case 's': Shortinfo = 1; break; @@ -976,12 +976,12 @@ main(int argc, char *argv[]) CdiDateTime vdatetime = taxisInqVdatetime(taxisID1); - if (Record) + if (Field) { for (recID = 0; recID < nrecs; recID++) { - streamInqRecord(streamID1, &varID, &levelID); - streamReadRecord(streamID1, data, &nmiss); + streamInqField(streamID1, &varID, &levelID); + streamReadField(streamID1, data, &nmiss); int number = vlistInqVarNumber(vlistID1, varID); int gridID = vlistInqVarGrid(vlistID1, varID); @@ -1006,11 +1006,11 @@ main(int argc, char *argv[]) if (fname2) { - streamDefRecord(streamID2, varID, levelID); + streamDefField(streamID2, varID, levelID); if (Move) - streamCopyRecord(streamID2, streamID1); + streamCopyField(streamID2, streamID1); else - streamWriteRecord(streamID2, data, nmiss); + streamWriteField(streamID2, data, nmiss); } } } diff --git a/configure.ac b/configure.ac index d5384fae6f61b49e8ffb6bbc6f04465e55d9a557..caa057f45a4237c314588e343f073fcbedc14504 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ AC_PREREQ([2.69]) LT_PREREQ([2.4.6]) -AC_INIT([cdi],[2.4.3],[https://mpimet.mpg.de/cdi]) +AC_INIT([cdi],[2.5.0],[https://mpimet.mpg.de/cdi]) AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version]) AC_CONFIG_AUX_DIR([config]) diff --git a/doc/tex/cdi_cman.tex b/doc/tex/cdi_cman.tex index d33aa7943e9840dc49d90f1803982a6c8cbc88d6..f1c152aec41847d25995bff78846c6dbdfd9af6a 100644 --- a/doc/tex/cdi_cman.tex +++ b/doc/tex/cdi_cman.tex @@ -136,7 +136,7 @@ \end{picture} \begin{flushright} -{\large\bfseries Climate Data Interface \\ Version 2.4.0 \\ February 2024} +{\large\bfseries Climate Data Interface \\ Version 2.5.0 \\ November 2024} \end{flushright} \vfill diff --git a/doc/tex/cdi_fman.tex b/doc/tex/cdi_fman.tex index ef3d9edbc92473b690ff9cb4b1a40cfd6379cae0..3058229d9750e4f693bd20398e06ead7608011b3 100644 --- a/doc/tex/cdi_fman.tex +++ b/doc/tex/cdi_fman.tex @@ -133,7 +133,7 @@ \end{picture} \begin{flushright} -{\large\bfseries Climate Data Interface \\ Version 2.4.0 \\ February 2024} +{\large\bfseries Climate Data Interface \\ Version 2.5.0 \\ November 2024} \end{flushright} \vfill diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d2dc7e693e16780f4b8e4fdcca1d2725de8e272..1f88fe09b84956160e7b52fb11ea0605f0b274a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -142,5 +142,7 @@ add_library(cdilib ${cdi_src_files} # INSTALL_HEADERS_LIST cdi.h ) +find_package(HDF5 REQUIRED COMPONENTS C REQUIRED) +target_link_libraries(cdilib PUBLIC netCDF::netcdf ${HDF5_LIBS}) target_compile_definitions(cdilib PUBLIC HAVE_CONFIG_H) diff --git a/src/cdf.c b/src/cdf.c index f0faf003410481bb7a27d569d47e79217dcaf933..78e7fff9ff3579a3718212be6e11917fdf186367 100644 --- a/src/cdf.c +++ b/src/cdf.c @@ -199,6 +199,8 @@ cdf4Open(const char *filename, const char *mode, int *filetype) static void cdfCloseFile(int fileID) { + + if (CDF_Debug) Message( "Closing cdf file: %d", fileID); cdf_close(fileID); } diff --git a/src/cdf_read.c b/src/cdf_read.c index a5d1f836a2e7c16b850c211e410bec1e82083ffd..05622e06081bc7bfa5e099e941303d242be8c217 100644 --- a/src/cdf_read.c +++ b/src/cdf_read.c @@ -944,7 +944,7 @@ cdf_read_next_record(stream_t *streamptr, int recID, int memtype, void *data, si } void -cdf_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) +cdf_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) { int tsID = streamptr->curTsID; int vrecID = streamptr->tsteps[tsID].curRecID; diff --git a/src/cdf_records.c b/src/cdf_records.c index 5e179588cd65309681121926d45e78bb858e58b1..1ad97c2a7d8aa5f25b0fcf4306e68117ffabaa81 100644 --- a/src/cdf_records.c +++ b/src/cdf_records.c @@ -82,19 +82,19 @@ cdf_create_records(stream_t *streamptr, size_t tsID) tsteps_t *sourceTstep = streamptr->tsteps; tsteps_t *destTstep = sourceTstep + tsID; - int numRecs = vlistNumRecords(vlistID); - if (numRecs <= 0) return; + int numFields = vlistNumFields(vlistID); + if (numFields <= 0) return; if (tsID == 0) { - int numRecsAvail = numRecs; // use all records at first timestep + int numRecsAvail = numFields; // use all records at first timestep - streamptr->nrecs += numRecs; + streamptr->nrecs += numFields; - cdf_init_timestep(destTstep, numRecs, numRecsAvail); + cdf_init_timestep(destTstep, numFields, numRecsAvail); destTstep->recIDs = (int *) Malloc((size_t) numRecsAvail * sizeof(int)); - cdf_init_records_step0(numRecs, destTstep->recIDs, destTstep->records, vlistID); + cdf_init_records_step0(numFields, destTstep->recIDs, destTstep->records, vlistID); } else if (tsID == 1) { @@ -102,14 +102,14 @@ cdf_create_records(stream_t *streamptr, size_t tsID) streamptr->nrecs += numRecsAvail; - cdf_init_timestep(destTstep, numRecs, numRecsAvail); + cdf_init_timestep(destTstep, numFields, numRecsAvail); - memcpy(destTstep->records, sourceTstep->records, (size_t) numRecs * sizeof(record_t)); + memcpy(destTstep->records, sourceTstep->records, (size_t) numFields * sizeof(record_t)); if (numRecsAvail) { destTstep->recIDs = (int *) Malloc((size_t) numRecsAvail * sizeof(int)); - cdf_init_records_step1(numRecs, destTstep->recIDs, destTstep->records, vlistID); + cdf_init_records_step1(numFields, destTstep->recIDs, destTstep->records, vlistID); } } else @@ -120,9 +120,9 @@ cdf_create_records(stream_t *streamptr, size_t tsID) streamptr->nrecs += numRecsAvail; - cdf_init_timestep(destTstep, numRecs, numRecsAvail); + cdf_init_timestep(destTstep, numFields, numRecsAvail); - memcpy(destTstep->records, sourceTstep->records, (size_t) numRecs * sizeof(record_t)); + memcpy(destTstep->records, sourceTstep->records, (size_t) numFields * sizeof(record_t)); if (numRecsAvail) { diff --git a/src/cdf_write.c b/src/cdf_write.c index 521802dc209a9059abcfe7ba78acfe8ff578359a..eb556afcac38904a2ddbc11224283458fb6d6c16 100644 --- a/src/cdf_write.c +++ b/src/cdf_write.c @@ -1638,7 +1638,7 @@ cdf_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtype, co } void -cdf_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals) +cdf_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals) { int varID = streamptr->record->varID; int levelID = streamptr->record->levelID; diff --git a/src/cdi.h b/src/cdi.h index bbe58c112e726faf6a39d6dde07007bf93629e34..624905c5dda1551c5803546224f815d35db79c47 100644 --- a/src/cdi.h +++ b/src/cdi.h @@ -353,6 +353,10 @@ int cdiEncodeTime(int hour, int minute, int second); int cdiGetFiletype(const char *uri, int *byteorder); int cdiGetProtocol(const char *uri, const char **filename); +int streamOpenReadNCMem(int ncid); +int streamOpenWriteNCMem(int ncid); +void streamCloseNCMem(int ncid); + // streamOpenRead: Open a dataset for reading int streamOpenRead(const char *path); @@ -443,15 +447,15 @@ void streamWriteVarChunk(int streamID, int varID, const int rect[][2], const void streamWriteVarChunkF(int streamID, int varID, const int rect[][2], const float data[], SizeType numMissVals); -// STREAM record I/O routines (sequential access) +// STREAM field I/O routines (sequential access) -void streamDefRecord(int streamID, int varID, int levelID); -void streamInqRecord(int streamID, int *varID, int *levelID); -void streamWriteRecord(int streamID, const double data[], SizeType numMissVals); -void streamWriteRecordF(int streamID, const float data[], SizeType numMissVals); -void streamReadRecord(int streamID, double data[], SizeType *numMissVals); -void streamReadRecordF(int streamID, float data[], SizeType *numMissVals); -void streamCopyRecord(int streamIDdest, int streamIDsrc); +void streamDefField(int streamID, int varID, int levelID); +void streamInqField(int streamID, int *varID, int *levelID); +void streamWriteField(int streamID, const double data[], SizeType numMissVals); +void streamWriteFieldF(int streamID, const float data[], SizeType numMissVals); +void streamReadField(int streamID, double data[], SizeType *numMissVals); +void streamReadFieldF(int streamID, float data[], SizeType *numMissVals); +void streamCopyField(int streamIDdest, int streamIDsrc); void streamInqGRIBinfo(int streamID, int *intnum, float *fltnum, off_t *bignum); @@ -565,7 +569,7 @@ int vlistZaxis(int vlistID, int index); int vlistZaxisIndex(int vlistID, int zaxisID); void vlistChangeZaxisIndex(int vlistID, int index, int zaxisID); void vlistChangeZaxis(int vlistID, int zaxisID1, int zaxisID2); -int vlistNumRecords(int vlistID); +int vlistNumFields(int vlistID); int vlistSubtype(int vlistID, int index); int vlistSubtypeIndex(int vlistID, int subtypeID); diff --git a/src/cdi_int.h b/src/cdi_int.h index fd31cd2d5fc03b5ba4aeac6ca1b1cfd084c3140e..847b95d36ee2e02b362cba2e4253ae8c82086fc3 100644 --- a/src/cdi_int.h +++ b/src/cdi_int.h @@ -55,7 +55,7 @@ bool strStartsWith(const char *vstr, const char *cstr); static inline bool str_is_equal(const char *x, const char *y) { - return (*x == *y) && strcmp(x, y) == 0; + return (*x == *y) && (strcmp(x, y) == 0); } #ifndef M_PI diff --git a/src/cgribex.h b/src/cgribex.h index afb23c6150602b56bbd7519ceaeb657663528a27..892511532a44384d54fc69fad679b0cf445ee47c 100644 --- a/src/cgribex.h +++ b/src/cgribex.h @@ -31,29 +31,29 @@ #define GRIB1_LTYPE_LANDDEPTH 111 #define GRIB1_LTYPE_LANDDEPTH_LAYER 112 #define GRIB1_LTYPE_ISENTROPIC 113 -#define GRIB1_LTYPE_SEADEPTH 160 // Depth Below Sea Level -#define GRIB1_LTYPE_LAKE_BOTTOM 162 // Lake or River Bottom -#define GRIB1_LTYPE_SEDIMENT_BOTTOM 163 // Bottom Of Sediment Layer -#define GRIB1_LTYPE_SEDIMENT_BOTTOM_TA 164 // Bottom Of Thermally Active Sediment Layer -#define GRIB1_LTYPE_SEDIMENT_BOTTOM_TW 165 // Bottom Of Sediment Layer Penetrated By Thermal Wave -#define GRIB1_LTYPE_MIX_LAYER 166 // Mixing Layer +#define GRIB1_LTYPE_SEADEPTH 160 // Depth Below Sea Level +#define GRIB1_LTYPE_LAKE_BOTTOM 162 // Lake or River Bottom +#define GRIB1_LTYPE_SEDIMENT_BOTTOM 163 // Bottom Of Sediment Layer +#define GRIB1_LTYPE_SEDIMENT_BOTTOM_TA 164 // Bottom Of Thermally Active Sediment Layer +#define GRIB1_LTYPE_SEDIMENT_BOTTOM_TW 165 // Bottom Of Sediment Layer Penetrated By Thermal Wave +#define GRIB1_LTYPE_MIX_LAYER 166 // Mixing Layer // GRIB1 Data representation type (Grid Type) [Table 6] -#define GRIB1_GTYPE_LATLON 0 // latitude/longitude -#define GRIB1_GTYPE_LATLON_ROT 10 // rotated latitude/longitude -#define GRIB1_GTYPE_LATLON_STR 20 // stretched latitude/longitude -#define GRIB1_GTYPE_LATLON_ROTSTR 30 // rotated and stretched latitude/longitude -#define GRIB1_GTYPE_GAUSSIAN 4 // gaussian grid -#define GRIB1_GTYPE_GAUSSIAN_ROT 14 // rotated gaussian grid -#define GRIB1_GTYPE_GAUSSIAN_STR 24 // stretched gaussian grid -#define GRIB1_GTYPE_GAUSSIAN_ROTSTR 34 // rotated and stretched gaussian grid -#define GRIB1_GTYPE_LCC 3 // Lambert conformal -#define GRIB1_GTYPE_SPECTRAL 50 // spherical harmonics -#define GRIB1_GTYPE_GME 192 // hexagonal GME grid +#define GRIB1_GTYPE_LATLON 0 // latitude/longitude +#define GRIB1_GTYPE_LATLON_ROT 10 // rotated latitude/longitude +#define GRIB1_GTYPE_LATLON_STR 20 // stretched latitude/longitude +#define GRIB1_GTYPE_LATLON_ROTSTR 30 // rotated and stretched latitude/longitude +#define GRIB1_GTYPE_GAUSSIAN 4 // gaussian grid +#define GRIB1_GTYPE_GAUSSIAN_ROT 14 // rotated gaussian grid +#define GRIB1_GTYPE_GAUSSIAN_STR 24 // stretched gaussian grid +#define GRIB1_GTYPE_GAUSSIAN_ROTSTR 34 // rotated and stretched gaussian grid +#define GRIB1_GTYPE_LCC 3 // Lambert conformal +#define GRIB1_GTYPE_SPECTRAL 50 // spherical harmonics +#define GRIB1_GTYPE_GME 192 // hexagonal GME grid // Macros for the indicator section ( Section 0 ) -#define ISEC0_GRIB_Len (isec0[ 0]) // Number of octets in the GRIB message -#define ISEC0_GRIB_Version (isec0[ 1]) // GRIB edition number +#define ISEC0_GRIB_Len (isec0[ 0]) // Number of octets in the GRIB message +#define ISEC0_GRIB_Version (isec0[ 1]) // GRIB edition number // Macros for the product definition section ( Section 1 ) @@ -67,108 +67,108 @@ #define ISEC1_TABLE4_30MINUTES 14 -#define ISEC1_CodeTable (isec1[ 0]) // Version number of code table -#define ISEC1_CenterID (isec1[ 1]) // Identification of centre -#define ISEC1_ModelID (isec1[ 2]) // Identification of model -#define ISEC1_GridDefinition (isec1[ 3]) // Grid definition -#define ISEC1_Sec2Or3Flag (isec1[ 4]) // Section 2 or 3 included -#define ISEC1_Parameter (isec1[ 5]) // Parameter indicator -#define ISEC1_LevelType (isec1[ 6]) // Type of level indicator -#define ISEC1_Level1 (isec1[ 7]) // Level 1 -#define ISEC1_Level2 (isec1[ 8]) // Level 2 -#define ISEC1_Year (isec1[ 9]) // Year of century (YY) -#define ISEC1_Month (isec1[10]) // Month (MM) -#define ISEC1_Day (isec1[11]) // Day (DD) -#define ISEC1_Hour (isec1[12]) // Hour (HH) -#define ISEC1_Minute (isec1[13]) // Minute (MM) -#define ISEC1_TimeUnit (isec1[14]) // Time unit indicator -#define ISEC1_TimePeriod1 (isec1[15]) // P1 Time period -#define ISEC1_TimePeriod2 (isec1[16]) // P2 Time period -#define ISEC1_TimeRange (isec1[17]) // Time range indicator -#define ISEC1_AvgNum (isec1[18]) // Number of products included in an average -#define ISEC1_AvgMiss (isec1[19]) // Number of products missing from an average -#define ISEC1_Century (isec1[20]) // Century -#define ISEC1_SubCenterID (isec1[21]) // Subcenter identifier -#define ISEC1_DecScaleFactor (isec1[22]) // Decimal scale factor -#define ISEC1_LocalFLag (isec1[23]) // Flag field to indicate local use in isec1 +#define ISEC1_CodeTable (isec1[ 0]) // Version number of code table +#define ISEC1_CenterID (isec1[ 1]) // Identification of centre +#define ISEC1_ModelID (isec1[ 2]) // Identification of model +#define ISEC1_GridDefinition (isec1[ 3]) // Grid definition +#define ISEC1_Sec2Or3Flag (isec1[ 4]) // Section 2 or 3 included +#define ISEC1_Parameter (isec1[ 5]) // Parameter indicator +#define ISEC1_LevelType (isec1[ 6]) // Type of level indicator +#define ISEC1_Level1 (isec1[ 7]) // Level 1 +#define ISEC1_Level2 (isec1[ 8]) // Level 2 +#define ISEC1_Year (isec1[ 9]) // Year of century (YY) +#define ISEC1_Month (isec1[10]) // Month (MM) +#define ISEC1_Day (isec1[11]) // Day (DD) +#define ISEC1_Hour (isec1[12]) // Hour (HH) +#define ISEC1_Minute (isec1[13]) // Minute (MM) +#define ISEC1_TimeUnit (isec1[14]) // Time unit indicator +#define ISEC1_TimePeriod1 (isec1[15]) // P1 Time period +#define ISEC1_TimePeriod2 (isec1[16]) // P2 Time period +#define ISEC1_TimeRange (isec1[17]) // Time range indicator +#define ISEC1_AvgNum (isec1[18]) // Number of products included in an average +#define ISEC1_AvgMiss (isec1[19]) // Number of products missing from an average +#define ISEC1_Century (isec1[20]) // Century +#define ISEC1_SubCenterID (isec1[21]) // Subcenter identifier +#define ISEC1_DecScaleFactor (isec1[22]) // Decimal scale factor +#define ISEC1_LocalFLag (isec1[23]) // Flag field to indicate local use in isec1 #define ISEC1_ECMWF_LocalExtension (isec1[36]) #define ISEC1_ECMWF_Class (isec1[37]) // Macros for the grid definition section ( Section 2 ) -#define ISEC2_GridType (isec2[ 0]) // Data representation type +#define ISEC2_GridType (isec2[ 0]) // Data representation type // Triangular grids -#define ISEC2_GME_NI2 (isec2[ 1]) // Number of factor 2 in factorisation of Ni -#define ISEC2_GME_NI3 (isec2[ 2]) // Number of factor 3 in factorisation of Ni -#define ISEC2_GME_ND (isec2[ 3]) // Nubmer of diamonds -#define ISEC2_GME_NI (isec2[ 4]) // Number of tri. subdiv. of the icosahedron -#define ISEC2_GME_AFlag (isec2[ 5]) // Flag for orientation of diamonds (Table A) -#define ISEC2_GME_LatPP (isec2[ 6]) // Latitude of pole point -#define ISEC2_GME_LonPP (isec2[ 7]) // Longitude of pole point -#define ISEC2_GME_LonMPL (isec2[ 8]) // Longitude of the first diamond -#define ISEC2_GME_BFlag (isec2[ 9]) // Flag for storage sequence (Table B) +#define ISEC2_GME_NI2 (isec2[ 1]) // Number of factor 2 in factorisation of Ni +#define ISEC2_GME_NI3 (isec2[ 2]) // Number of factor 3 in factorisation of Ni +#define ISEC2_GME_ND (isec2[ 3]) // Nubmer of diamonds +#define ISEC2_GME_NI (isec2[ 4]) // Number of tri. subdiv. of the icosahedron +#define ISEC2_GME_AFlag (isec2[ 5]) // Flag for orientation of diamonds (Table A) +#define ISEC2_GME_LatPP (isec2[ 6]) // Latitude of pole point +#define ISEC2_GME_LonPP (isec2[ 7]) // Longitude of pole point +#define ISEC2_GME_LonMPL (isec2[ 8]) // Longitude of the first diamond +#define ISEC2_GME_BFlag (isec2[ 9]) // Flag for storage sequence (Table B) // Spherical harmonic coeficients -#define ISEC2_PentaJ (isec2[ 1]) // J pentagonal resolution parameter -#define ISEC2_PentaK (isec2[ 2]) // K pentagonal resolution parameter -#define ISEC2_PentaM (isec2[ 3]) // M pentagonal resolution parameter -#define ISEC2_RepType (isec2[ 4]) // Representation type -#define ISEC2_RepMode (isec2[ 5]) // Representation mode +#define ISEC2_PentaJ (isec2[ 1]) // J pentagonal resolution parameter +#define ISEC2_PentaK (isec2[ 2]) // K pentagonal resolution parameter +#define ISEC2_PentaM (isec2[ 3]) // M pentagonal resolution parameter +#define ISEC2_RepType (isec2[ 4]) // Representation type +#define ISEC2_RepMode (isec2[ 5]) // Representation mode // Gaussian grids -#define ISEC2_NumLon (isec2[ 1]) // Number of points along a parallel (Ni) -#define ISEC2_NumLat (isec2[ 2]) // Number of points along a meridian (Nj) -#define ISEC2_FirstLat (isec2[ 3]) // Latitude of the first grid point -#define ISEC2_FirstLon (isec2[ 4]) // Longitude of the first grid point -#define ISEC2_ResFlag (isec2[ 5]) // Resolution flag: 128 regular grid -#define ISEC2_LastLat (isec2[ 6]) // Latitude of the last grid point -#define ISEC2_LastLon (isec2[ 7]) // Longitude of the last grid point -#define ISEC2_LonIncr (isec2[ 8]) // i direction increment -#define ISEC2_LatIncr (isec2[ 9]) // j direction increment +#define ISEC2_NumLon (isec2[ 1]) // Number of points along a parallel (Ni) +#define ISEC2_NumLat (isec2[ 2]) // Number of points along a meridian (Nj) +#define ISEC2_FirstLat (isec2[ 3]) // Latitude of the first grid point +#define ISEC2_FirstLon (isec2[ 4]) // Longitude of the first grid point +#define ISEC2_ResFlag (isec2[ 5]) // Resolution flag: 128 regular grid +#define ISEC2_LastLat (isec2[ 6]) // Latitude of the last grid point +#define ISEC2_LastLon (isec2[ 7]) // Longitude of the last grid point +#define ISEC2_LonIncr (isec2[ 8]) // i direction increment +#define ISEC2_LatIncr (isec2[ 9]) // j direction increment #define ISEC2_NumPar (isec2[ 9]) // Number of parallels between a pole and the E. -#define ISEC2_ScanFlag (isec2[10]) // Scanning mode flags -#define ISEC2_NumVCP (isec2[11]) // Number of vertical coordinate parameters +#define ISEC2_ScanFlag (isec2[10]) // Scanning mode flags +#define ISEC2_NumVCP (isec2[11]) // Number of vertical coordinate parameters // Lambert -#define ISEC2_Lambert_Lov (isec2[ 6]) // Orientation of the grid -#define ISEC2_Lambert_dx (isec2[ 8]) // X-direction grid length -#define ISEC2_Lambert_dy (isec2[ 9]) // Y-direction grid length -#define ISEC2_Lambert_ProjFlag (isec2[12]) // Projection centre flag -#define ISEC2_Lambert_LatS1 (isec2[13]) // First lat at which the secant cone cuts the sphere -#define ISEC2_Lambert_LatS2 (isec2[14]) // Second lat at which the secant cone cuts the sphere -#define ISEC2_Lambert_LatSP (isec2[19]) // Latitude of the southern pole -#define ISEC2_Lambert_LonSP (isec2[20]) // Longitude of the southern pole +#define ISEC2_Lambert_Lov (isec2[ 6]) // Orientation of the grid +#define ISEC2_Lambert_dx (isec2[ 8]) // X-direction grid length +#define ISEC2_Lambert_dy (isec2[ 9]) // Y-direction grid length +#define ISEC2_Lambert_ProjFlag (isec2[12]) // Projection centre flag +#define ISEC2_Lambert_LatS1 (isec2[13]) // First lat at which the secant cone cuts the sphere +#define ISEC2_Lambert_LatS2 (isec2[14]) // Second lat at which the secant cone cuts the sphere +#define ISEC2_Lambert_LatSP (isec2[19]) // Latitude of the southern pole +#define ISEC2_Lambert_LonSP (isec2[20]) // Longitude of the southern pole -#define ISEC2_Reduced (isec2[16]) // 0: regular, 1: reduced grid +#define ISEC2_Reduced (isec2[16]) // 0: regular, 1: reduced grid #define ISEC2_ReducedPointsPtr (&isec2[22]) -#define ISEC2_ReducedPoints(i) (isec2[22+i]) // Number of points along each parallel +#define ISEC2_ReducedPoints(i) (isec2[22+i]) // Number of points along each parallel -#define ISEC2_LatSP (isec2[12]) // Latitude of the southern pole of rotation -#define ISEC2_LonSP (isec2[13]) // Longitude of the southern pole of rotation +#define ISEC2_LatSP (isec2[12]) // Latitude of the southern pole of rotation +#define ISEC2_LonSP (isec2[13]) // Longitude of the southern pole of rotation -#define FSEC2_RotAngle (fsec2[ 0]) // Angle of rotation -#define FSEC2_StrFact (fsec2[ 1]) // Stretching factor +#define FSEC2_RotAngle (fsec2[ 0]) // Angle of rotation +#define FSEC2_StrFact (fsec2[ 1]) // Stretching factor // Macros for the bit map section ( Section 3 ) -#define ISEC3_PredefBitmap (isec3[ 0]) // Predefined bitmap -#define ISEC3_MissVal (isec3[ 1]) // Missing data value for integers -#define FSEC3_MissVal (fsec3[ 1]) // Missing data value for floats +#define ISEC3_PredefBitmap (isec3[ 0]) // Predefined bitmap +#define ISEC3_MissVal (isec3[ 1]) // Missing data value for integers +#define FSEC3_MissVal (fsec3[ 1]) // Missing data value for floats // Macros for the binary data section ( Section 4 ) -#define ISEC4_NumValues (isec4[ 0]) // Number of data values for encode/decode -#define ISEC4_NumBits (isec4[ 1]) // Number of bits used for each encoded value -#define ISEC4_NumNonMissValues (isec4[20]) // Number of non-missing values +#define ISEC4_NumValues (isec4[ 0]) // Number of data values for encode/decode +#define ISEC4_NumBits (isec4[ 1]) // Number of bits used for each encoded value +#define ISEC4_NumNonMissValues (isec4[20]) // Number of non-missing values #ifdef __cplusplus @@ -247,6 +247,9 @@ int grib_info_for_grads(off_t recpos, long recsize, unsigned char *gribbuffer, double calculate_pfactor_float(const float* spectralField, long fieldTruncation, long subsetTruncation); double calculate_pfactor_double(const double* spectralField, long fieldTruncation, long subsetTruncation); +int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp, unsigned char **gdsp, unsigned char **bmsp, + unsigned char **bdsp, long *gribrecsize); + #ifdef __cplusplus } #endif diff --git a/src/cgribexlib.c b/src/cgribexlib.c index a19337c13e190a9af685feea5cd8497e3b124761..d1786fdb3f92f03a25b3281075ebed8795cd8f77 100644 --- a/src/cgribexlib.c +++ b/src/cgribexlib.c @@ -1,7 +1,7 @@ -// Automatically generated by m214003 at 2024-06-08, do not edit +// Automatically generated by m214003 at 2024-10-30, do not edit -// CGRIBEXLIB_VERSION="2.3.0" +// CGRIBEXLIB_VERSION="2.3.1" #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined(__clang__) #pragma GCC diagnostic push @@ -1219,8 +1219,13 @@ xlc_r -g -O3 -qhot -q64 -qarch=auto -qtune=auto -qreport -DTEST_ENCODE encode_ar #define GRIBPACK unsigned char #ifndef HOST_ENDIANNESS +#ifdef __cplusplus +static const uint32_t HOST_ENDIANNESS_temp[1] = { UINT32_C(0x00030201) }; +#define HOST_ENDIANNESS (((const unsigned char *) HOST_ENDIANNESS_temp)[0]) +#else #define HOST_ENDIANNESS (((const unsigned char *) &(const uint32_t[1]){ UINT32_C(0x00030201) })[0]) #endif +#endif #define IS_BIGENDIAN() (HOST_ENDIANNESS == 0) #define Error(x, y) @@ -1948,16 +1953,16 @@ decfp2(int kexp, int kmant) /* Section 2 . Convert other values. */ /* ----------------------------------------------------------------- */ - /* Sign of value. */ + // Sign of value. int iexp = kexp; int isign = (iexp < 128) * 2 - 1; iexp -= iexp < 128 ? 0 : 128; - /* Decode value. */ + // Decode value. - /* pval = isign * pow(2.0, -24.0) * kmant * pow(16.0, (double)(iexp - 64)); */ + // double pval = isign * pow(2.0, -24.0) * kmant * pow(16.0, (double)(iexp - 64)); iexp -= 64; @@ -1968,7 +1973,7 @@ decfp2(int kexp, int kmant) /* ----------------------------------------------------------------- */ return pval; -} /* decfp2 */ +} #include <stdarg.h> #include <stdint.h> @@ -2319,11 +2324,7 @@ gribPrintSec1(int *isec0, int *isec1) int ibit, ierr, iout, iyear; int jiloop; float value; - char hversion[9]; - /* - char hfirst[121], hsecond[121], hthird[121], hfourth[121]; - */ grsdef(); @@ -2347,22 +2348,6 @@ gribPrintSec1(int *isec0, int *isec1) fprintf(grprsm, " Flag (Code Table 1) %8.8d\n", iout); fprintf(grprsm, " Parameter identifier (Code Table 2). %9d\n", isec1[5]); - /* - IERR = CHKTAB2(ISEC1,HFIRST,HSECOND,HTHIRD,HFOURTH) - IF( IERR .EQ. 0 ) THEN - DO JLOOP = 121, 1, -1 - IF( HSECOND(JLOOP:JLOOP).NE.' ' ) THEN - IOFFSET = JLOOP - GOTO 110 - ENDIF - ENDDO - GOTO 120 - 110 CONTINUE - WRITE(*,'(2H ",A,1H")') HSECOND(1:IOFFSET) - 120 CONTINUE - ENDIF - */ - if (isec1[5] != 127) { fprintf(grprsm, " Type of level (Code Table 3). %9d\n", isec1[6]); @@ -2379,7 +2364,6 @@ gribPrintSec1(int *isec0, int *isec1) if (iyear != 255) { int date, time; - /* iyear = ((isec1[20]-1)*100 + isec1[9]); */ gribDateTime(isec1, &date, &time); iyear = date / 10000; fprintf(grprsm, " Year of reference time of data. %9d (%4d)\n", isec1[9], iyear); @@ -2408,10 +2392,10 @@ gribPrintSec1(int *isec0, int *isec1) else fprintf(grprsm, " Century of reference time of data. %9d\n", isec1[20]); - /* Print sub-centre */ + // Print sub-centre fprintf(grprsm, " Sub-centre identifier. %9d\n", ISEC1_SubCenterID); - /* Decimal scale factor */ + // Decimal scale factor fprintf(grprsm, " Units decimal scaling factor. %9d\n", isec1[22]); /* @@ -2473,7 +2457,7 @@ gribPrintSec1(int *isec0, int *isec1) fprintf(grprsm, " Class. %9d\n", isec1[37]); fprintf(grprsm, " Type. %9d\n", isec1[38]); fprintf(grprsm, " Stream. %9d\n", isec1[39]); - sprintf(hversion, "%4s", (char *) &isec1[40]); + snprintf(hversion, sizeof(hversion), "%4s", (char *) &isec1[40]); hversion[4] = 0; fprintf(grprsm, " Version number or Experiment identifier. %4s\n", hversion); /* @@ -2792,14 +2776,11 @@ gribPrintSec1(int *isec0, int *isec1) fprintf(grprsm, " Type %9d\n", isec1[42]); fprintf(grprsm, " Stream %9d\n", isec1[43]); /* - sprintf(hversion, "%8d", isec1[44]); + snprintf(hversion, sizeof(hversion), "%8d", isec1[44]); fprintf(grprsm, " Version number/experiment identifier: %4s\n", &hversion[4]); */ iyear = isec1[45]; - if (iyear > 50) - iyear = iyear + 1900; - else - iyear = iyear + 2000; + iyear = iyear + ((iyear > 50) ? 1900 : 2000); fprintf(grprsm, " Year %9d\n", iyear); fprintf(grprsm, " Month %9d\n", isec1[46]); @@ -3020,11 +3001,7 @@ printQuasi(int *isec2) fprintf(grprsm, " Number of points along a parallel varies.\n"); int ntos = (fmod((double) isec2[10], 128.) < 64); - - if (ntos) - fprintf(grprsm, " Number of points. Parallel. (North to South)\n"); - else - fprintf(grprsm, " Number of points. Parallel. (South to North)\n"); + fprintf(grprsm, " Number of points. Parallel. %s\n", ntos ? "(North to South)" : "(South to North)"); // Display number of points for each latitude int latcnt = isec2[2]; @@ -3034,7 +3011,7 @@ printQuasi(int *isec2) for (int j = 0; j < latcnt; ++j) { nextlat = nextlat + 1; - sprintf(yout, "%4d", nextlat); + snprintf(yout, sizeof(yout), "%4d", nextlat); // Finished? if (nextlat > latcnt) break; @@ -3055,7 +3032,7 @@ printQuasi(int *isec2) if (nextlat < latcnt) goto LABEL110; } // Display neighbouring latitudes with same number of points as 'nn to mm'. - if (nrepeat >= 1) sprintf(yout + 4, "to %5d", nextlat); + if (nrepeat >= 1) snprintf(yout + 4, sizeof(yout) - 4, "to %5d", nextlat); fprintf(grprsm, " %5d %-12s\n", isec2[nextlat + 21], yout); memset(yout, ' ', (size_t) 11); } @@ -3718,10 +3695,9 @@ gribCheckSeek(int fileID, long *offset, int *version) int gribFileSeek(int fileID, long *offset) { - /* position file pointer after GRIB */ + // position file pointer after GRIB const long GRIB = 0x47524942; long code = 0; - int ch; int retry = 4096 * 4096; *offset = 0; @@ -3730,7 +3706,7 @@ gribFileSeek(int fileID, long *offset) while (retry--) { - ch = filePtrGetc(fileptr); + int ch = filePtrGetc(fileptr); if (ch == EOF) return -1; code = ((code << 8) + ch) & 0xFFFFFFFF; @@ -3892,10 +3868,7 @@ gribGetSize(int fileID) return 0; } - if (ierr == -1) - return 0; - else if (ierr == 1) - return 0; + if (ierr == -1) return 0; size_t recSize = gribReadSize(fileID); @@ -3914,6 +3887,7 @@ gribRead(int fileID, void *buffer, size_t *buffersize) if (ierr > 0) { Warning("GRIB record not found!"); + *buffersize = 0; return -2; } @@ -3922,11 +3896,6 @@ gribRead(int fileID, void *buffer, size_t *buffersize) *buffersize = 0; return -1; } - else if (ierr == 1) - { - *buffersize = 0; - return -2; - } size_t recSize = gribReadSize(fileID); size_t readSize = recSize; @@ -4060,9 +4029,7 @@ C ---------------------------------------------------------------- /* Common area variables have not been set. Set them. */ - /* - Set GRIB calendar. - */ + // Set GRIB calendar. if (CGRIBEX_grib_calendar == -1) { CGRIBEX_grib_calendar = CALENDAR_PROLEPTIC; @@ -4084,18 +4051,14 @@ C ---------------------------------------------------------------- CGRIBEX_grib_calendar = CALENDAR_NONE; } } - /* - Set GRIBEX compatibility mode. - */ + // Set GRIBEX compatibility mode. envString = getenv("GRIB_GRIBEX_MODE_ON"); if (envString != NULL) { if (atoi(envString) == 1) CGRIBEX_Const = 0; } - /* - See if output stream needs changing - */ + // See if output stream needs changing grprsm = stdout; env_stream = getenv("GRPRS_STREAM"); if (env_stream) @@ -4113,7 +4076,7 @@ C ---------------------------------------------------------------- else { char filename[] = "unit.00"; - sprintf(filename, "%2.2d", unit); + snprintf(filename, sizeof(filename), "%2.2d", unit); grprsm = fopen(filename, "w"); if (!grprsm) SysError("GRPRS_STREAM = %d", unit); } @@ -4127,9 +4090,7 @@ C ---------------------------------------------------------------- } } } - /* - Mark common area values set by user. - */ + // Mark common area values set by user. lfirst = false; } @@ -5191,7 +5152,7 @@ grib2PrintALL(int nrec, long offset, long recpos, long recsize, unsigned char *g printf("level %d %d %d %d %d %d %d\n", level1type, level1sf, level1, level1*level1sf, level2sf, level2, level2*level2sf); */ char paramstr[16]; - sprintf(paramstr, "%d.%d.%d", paramnum, paramcat, dis); + snprintf(paramstr, sizeof(paramstr), "%d.%d.%d", paramnum, paramcat, dis); fprintf(stdout, "%5d :%4ld %8ld %6ld :%2d %3ld %3ld %3ld %3ld %4ld %6ld %6ld : %-9s %7d : %5d %5d %6.4g\n", nrec, offset, recpos, recsize, GRIB_EDITION(is), ids_len, lus_len, gds_len, pds_len, drs_len, bms_len, bds_len, paramstr, level1, level1type, gridtype, cr); @@ -12614,7 +12575,7 @@ encode_dummy(void) (void) encode_array_unrolled_double(0, 0, 0, NULL, NULL, 0, 0, NULL); (void) encode_array_unrolled_float(0, 0, 0, NULL, NULL, 0, 0, NULL); } -static const char grb_libvers[] = "2.3.0"; +static const char grb_libvers[] = "2.3.1"; const char * cgribexLibraryVersion(void) { diff --git a/src/grb_read.c b/src/grb_read.c index 628f43b8b317cc16be5163e45aa1210c5b6e96d3..9c82461945d496e7b14a77979cd8bda2addf1717 100644 --- a/src/grb_read.c +++ b/src/grb_read.c @@ -309,7 +309,7 @@ grb_read_next_record(stream_t *streamptr, int recID, int memType, void *data, si } void -grb_read_record(stream_t *streamptr, int memType, void *data, size_t *numMissVals) +grb_read_field(stream_t *streamptr, int memType, void *data, size_t *numMissVals) { int tsID = streamptr->curTsID; int vrecID = streamptr->tsteps[tsID].curRecID; diff --git a/src/grb_write.c b/src/grb_write.c index f9c9ec8d02b344815bcca5ad83fb80f10e5dbfe0..9ece9e4c10669e5875cc02efa512ac4047b1c8d8 100644 --- a/src/grb_write.c +++ b/src/grb_write.c @@ -216,7 +216,7 @@ fillup_gribbuffer(size_t nbytes, unsigned char *gribbuffer) } void -grbCopyRecord(stream_t *streamptr2, stream_t *streamptr1) +grbCopyField(stream_t *streamptr2, stream_t *streamptr1) { int filetype = streamptr1->filetype; int fileID1 = streamptr1->fileID; @@ -488,7 +488,7 @@ grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, siz } void -grb_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals) +grb_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals) { int varID = streamptr->record->varID; int levelID = streamptr->record->levelID; diff --git a/src/stream.c b/src/stream.c index 8ebd6be67f58a15144661505f6d1f7bed42bda93..81fee3cae624cb8f00ecfc238bb57ca3c65d0dcb 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 @@ -706,6 +713,42 @@ streamOpenID(const char *filename, char filemode, int filetype, int resH) return streamID; } +int +streamOpenNCMem(int ncidp, char mode) +{ + cdiInitialize(); + stream_t *streamptr = stream_new_entry(CDI_UNDEFID); + int streamID = CDI_ESYSTEM; + +#ifdef HAVE_NETCDF4 + streamID = streamptr->self; + if (streamID < 0) return CDI_ELIMIT; + + size_t max_file_path_length = 128; + size_t actual_length = 0; + char *filename = (char *) malloc(sizeof(char) * max_file_path_length); + + nc_inq_path(ncidp, &actual_length, filename); + + streamptr->filename = strdup(filename); + streamptr->filemode = mode; + streamptr->filetype = CDI_FILETYPE_NC4; + streamptr->fileID = ncidp; + + if (mode == 'r') + { + int status = stream_create_vlist(streamptr, NULL); + if (status < 0) + { + streamID = status; + if (streamptr->record) Free(streamptr->record); + reshRemove(streamptr->self, &streamOps); + } + } +#endif + + return streamID; +} static int streamOpen(const char *filename, const char *filemode, int filetype) { @@ -753,7 +796,7 @@ streamOpenA(const char *filename, const char *filemode, int filetype) if (str_is_equal(filemode, "r")) cdiVlistMakeImmutable(streamptr->vlistID); { - void (*streamCloseDelegate)(stream_t * streamptr, int recordBufIsToBeDeleted) + void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted) = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func; streamCloseDelegate(streamptr, 0); @@ -1222,14 +1265,10 @@ deallocate_sleveltable_t(sleveltable_t *entry) } static void -streamDestroy(stream_t *streamptr) +streamDestroyViaDelegate(stream_t *streamptr, void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted)) { - xassert(streamptr); - int vlistID = streamptr->vlistID; - - void (*streamCloseDelegate)(stream_t * streamptr, int recordBufIsToBeDeleted) - = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func; + xassert(streamptr); if (streamptr->filetype != CDI_FILETYPE_UNDEF) streamCloseDelegate(streamptr, 1); if (streamptr->record) @@ -1285,6 +1324,7 @@ streamDestroy(stream_t *streamptr) } #endif + int vlistID = streamptr->vlistID; if (vlistID != -1) { int taxisID = (streamptr->filemode != 'w') ? vlistInqTaxis(vlistID) : -1; @@ -1299,6 +1339,16 @@ streamDestroy(stream_t *streamptr) Free(streamptr); } + +static void +streamDestroy(stream_t *streamptr) +{ + void (*streamCloseDelegate)(stream_t *streamptr, int recordBufIsToBeDeleted) + = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_CLOSE_BACKEND).func; + + streamDestroyViaDelegate(streamptr, streamCloseDelegate); +} + static void streamDestroyP(void *streamptr) { @@ -1390,7 +1440,7 @@ streamSync(int streamID) { stream_t *streamptr = stream_to_pointer(streamID); - void (*myStreamSync_)(stream_t * streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_STREAM_SYNC).func; + void (*myStreamSync_)(stream_t *streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_STREAM_SYNC).func; myStreamSync_(streamptr); } @@ -1424,7 +1474,7 @@ cdiStreamDefTimestep_(stream_t *streamptr, int tsID) /* usually points to cdfDefTimestep in serial mode but * to cdiPioCdfDefTimestep on servers and to a null-op on * clients in client/server mode */ - void (*myCdfDefTimestep)(stream_t * streamptr, int tsID, size_t) + void (*myCdfDefTimestep)(stream_t *streamptr, int tsID, size_t) = (void (*)(stream_t *, int, size_t)) namespaceSwitchGet(NSSWITCH_CDF_DEF_TIMESTEP).func; myCdfDefTimestep(streamptr, tsID, 1); } @@ -1462,7 +1512,7 @@ streamDefTimestep(int streamID, int tsID) if (streamptr->lockIO) CDI_IO_LOCK(); - int (*myStreamDefTimestep_)(stream_t * streamptr, int tsID) + int (*myStreamDefTimestep_)(stream_t *streamptr, int tsID) = (int (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_DEF_TIMESTEP_).func; int status = myStreamDefTimestep_(streamptr, tsID); @@ -1763,7 +1813,7 @@ streamTxCode(void *s) void cdiStreamSetupVlist(stream_t *s, int vlistID) { - void (*myStreamSetupVlist)(stream_t * s, int vlistID) + void (*myStreamSetupVlist)(stream_t *s, int vlistID) = (void (*)(stream_t *, int)) namespaceSwitchGet(NSSWITCH_STREAM_SETUP_VLIST).func; myStreamSetupVlist(s, vlistID); } @@ -1821,7 +1871,7 @@ cdiStreamSetupVlist_(stream_t *streamptr, int vlistID) /* calls cdfDefCoordinateVars in serial mode but * cdiPioClientStreamNOP (i.e. nothing) on client ranks * and cdiPioServerCdfDefVars on server ranks in parallel mode*/ - void (*myCdfDefVars)(stream_t * streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func; + void (*myCdfDefVars)(stream_t *streamptr) = (void (*)(stream_t *)) namespaceSwitchGet(NSSWITCH_CDF_STREAM_SETUP).func; myCdfDefVars(streamptr); } break; @@ -1989,6 +2039,64 @@ streamUnpack(char *unpackBuffer, int unpackBufferSize, int *unpackBufferPos, int return retval; } + +/* * + * This function does not really close the memio, + * this has to be done outside cdi to access the memory buffer*/ +void +freePtrAfterNCMem(stream_t *streamptr, int recordBufIsToBeDeleted) +{ + int fileID = streamptr->fileID; + + if (fileID == CDI_UNDEFID) + { + Warning("File %s not open!", streamptr->filename); + return; + } + + if (streamptr->ntsteps == 0 && streamptr->tsteps != NULL) + { + if (streamptr->tsteps[0].records) + { + Free(streamptr->tsteps[0].records); + streamptr->tsteps[0].records = NULL; + } + if (streamptr->tsteps[0].recIDs) + { + Free(streamptr->tsteps[0].recIDs); + streamptr->tsteps[0].recIDs = NULL; + } + } +} + + +void +streamCloseNCMem(int streamID) +{ + stream_t *streamptr = stream_to_pointer(streamID); + + bool lockIO = streamptr->lockIO; + if (lockIO) CDI_IO_LOCK(); + + if (CDI_Debug) Message("streamID = %d filename = %s", streamID, streamptr->filename); + streamDestroyViaDelegate(streamptr,freePtrAfterNCMem); + reshRemove(streamID, &streamOps); + if (CDI_Debug) Message("Removed stream %d from stream list", streamID); + + if (lockIO) CDI_IO_UNLOCK(); +} + +int +streamOpenReadNCMem(int ncidp) +{ + return streamOpenNCMem(ncidp, 'r'); +} +int +streamOpenWriteNCMem(int ncidp) +{ + return streamOpenNCMem(ncidp, 'w'); +} + /* * Local Variables: * c-file-style: "Java" diff --git a/src/stream_cdf.h b/src/stream_cdf.h index 0e0991c1d81507db6385c16a57a2048bf30fb6c5..d4b379742b09f9983910c0310f8c0220e3eac2e8 100644 --- a/src/stream_cdf.h +++ b/src/stream_cdf.h @@ -30,14 +30,14 @@ int cdfInqTimestep(stream_t *streamptr, int tsID); int cdfInqContents(stream_t *streamptr); void cdfEndDef(stream_t *streamptr); -void cdfDefRecord(stream_t *streamptr); +void cdfDefField(stream_t *streamptr); void cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1); void cdfDefineAttributes(int filetype, int vlistID, int varID, int fileID, int ncvarID); -void cdf_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); -void cdf_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals); +void cdf_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); +void cdf_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals); void cdf_read_var(stream_t *streamptr, int varID, int memtype, void *data, size_t *numMissVals); void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data, size_t numMissVals); diff --git a/src/stream_cdf_i.c b/src/stream_cdf_i.c index 7d9e9e9f25166d3ee1b6b16d7ae8d2cf10a58421..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; @@ -114,6 +115,7 @@ typedef struct size_t gridSize; size_t xSize; size_t ySize; + int nattsNC; int natts; int *atts; size_t vctsize; @@ -189,15 +191,6 @@ scan_time_units(const char *unitstr) return timeunit; } -static void -set_forecast_time(const char *timestr, taxis_t *taxis) -{ - if (strlen(timestr) != 0) - taxis->fDateTime = scan_time_string(timestr); - else - cdiDateTime_init(&(taxis->fDateTime)); -} - static int set_base_time(const char *timeUnitsStr, taxis_t *taxis) { @@ -525,43 +518,46 @@ cdf_scale_add(size_t size, double *data, double addoffset, double scalefactor) } static int -cdf_time_dimid(int fileID, int ndims, int nvars, ncdim_t *ncdims) +cdf_time_dimid(int fileID, int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvars) { char dimname[CDI_MAX_NAME]; - for (int dimid = 0; dimid < ndims; ++dimid) { - dimname[0] = 0; - cdf_inq_dimname(fileID, ncdims[dimid].dimid, dimname); - if ((dimname[0] == 'T' || dimname[0] == 't') && dimname[1] == 'i' && dimname[2] == 'm' && dimname[3] == 'e') return dimid; + strcpy(dimname, ncdims[dimid].name); + if (str_is_equal("time", str_to_lower(dimname))) return dimid; } + bool check_dimids[MAX_DIMS_CDF]; + for (int i = 0; i < MAX_DIMS_CDF; ++i) check_dimids[i] = false; + 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); - for (int i = 0; i < nvdims; ++i) - for (int dimid = 0; dimid < ndims; ++dimid) - if (ncdims[dimid].dimid == dimids[i]) - { - dimids[i] = dimid; - break; - } - - if (nvdims == 1) + ncvar_t *ncvar = &ncvars[varid]; + if (ncvars[varid].ndims == 1) { - char sbuf[CDI_MAX_NAME]; - for (int iatt = 0; iatt < nvatts; ++iatt) + int dimid0 = CDI_UNDEFID; + for (int gdimid = 0; gdimid < ndims; ++gdimid) + if (ncdims[gdimid].dimid == ncvar->dimids[0]) + { + dimid0 = gdimid; + break; + } + + if (dimid0 != CDI_UNDEFID && check_dimids[dimid0] == false) { - sbuf[0] = 0; - cdf_inq_attname(fileID, varid, iatt, sbuf); - if (strStartsWith(sbuf, "units")) - { - cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf); - str_to_lower(sbuf); + if (ncdims[dimid0].ncvarid != CDI_UNDEFID && ncdims[dimid0].ncvarid != varid) continue; + check_dimids[dimid0] = true; - if (is_time_units(sbuf)) return dimids[0]; + char sbuf[CDI_MAX_NAME]; + for (int iatt = 0; iatt < ncvar->nattsNC; ++iatt) + { + sbuf[0] = 0; + cdf_inq_attname(fileID, varid, iatt, sbuf); + if (str_is_equal(sbuf, "units")) + { + cdfGetAttText(fileID, varid, "units", sizeof(sbuf), sbuf); + if (is_time_units(str_to_lower(sbuf))) return dimid0; + } } } } @@ -573,9 +569,9 @@ cdf_time_dimid(int fileID, int ndims, int nvars, ncdim_t *ncdims) static void init_ncdims(int ndims, ncdim_t *ncdims) { - for (int ncdimid = 0; ncdimid < ndims; ncdimid++) + for (int gdimid = 0; gdimid < ndims; gdimid++) { - ncdim_t *ncdim = &ncdims[ncdimid]; + ncdim_t *ncdim = &ncdims[gdimid]; ncdim->dimid = CDI_UNDEFID; ncdim->ncvarid = CDI_UNDEFID; ncdim->dimtype = CDI_UNDEFID; @@ -587,12 +583,13 @@ init_ncdims(int ndims, ncdim_t *ncdims) static void init_ncvars(int nvars, ncvar_t *ncvars, int ncid) { - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) + for (int varid = 0; varid < nvars; varid++) { - ncvar_t *ncvar = &ncvars[ncvarid]; + ncvar_t *ncvar = &ncvars[varid]; ncvar->ncid = ncid; ncvar->varStatus = UndefVar; ncvar->ignoreVar = false; + ncvar->isHealPIX = false; ncvar->isCubeSphere = false; ncvar->isCharAxis = false; ncvar->isXaxis = false; @@ -652,6 +649,7 @@ init_ncvars(int nvars, ncvar_t *ncvars, int ncid) ncvar->gridSize = 0; ncvar->xSize = 0; ncvar->ySize = 0; + ncvar->nattsNC = 0; ncvar->natts = 0; ncvar->atts = NULL; ncvar->vctsize = 0; @@ -924,13 +922,13 @@ cdf_print_vars(const ncvar_t *ncvars, int nvars, const char *oname) fprintf(stderr, "%s:\n", oname); - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) + for (int varid = 0; varid < nvars; varid++) { - const ncvar_t *ncvar = &ncvars[ncvarid]; + const ncvar_t *ncvar = &ncvars[varid]; int ndim = 0; - if (ncvar->varStatus == DataVar) + if (ncvar->varStatus == DataVar || ncvar->varStatus == UndefVar) { - axis[ndim++] = 'v'; + axis[ndim++] = (ncvar->varStatus == DataVar) ? 'v' : 'u'; axis[ndim++] = ':'; for (int i = 0; i < ncvar->ndims; i++) { @@ -957,7 +955,7 @@ cdf_print_vars(const ncvar_t *ncvars, int nvars, const char *oname) axis[ndim++] = 0; - fprintf(stderr, "%3d %3d %-6s %s\n", ncvarid, ndim-3, axis, ncvar->name); + fprintf(stderr, "%3d %3d %-6s %s\n", varid, ndim-3, axis, ncvar->name); } // clang-format on } @@ -1079,109 +1077,178 @@ is_valid_coordinate(ncvar_t *ncvar) return status; } -#if defined __GNUC__ || (__GNUC__ == 4 && __GNUC_MINOR__ == 9) -#pragma GCC diagnostic push -#pragma GCC diagnostic warning "-Wstrict-overflow" -#endif - static void -cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timedimid, int modelID, int format) +read_coordinates_vars(int ncid, char *attstring, ncvar_t *ncvar, ncvar_t *ncvars, int *nchecked_vars, char *checked_vars[], + int max_check_vars) { - int nvdims, nvatts; - nc_type xtype, atttype; - size_t attlen; - char name[CDI_MAX_NAME]; - char attname[CDI_MAX_NAME]; - 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++) + bool lstop = false; + for (int i = 0; i < MAX_COORDVARS && !lstop; i++) { - ncvar_t *ncvar = &ncvars[ncvarid]; - int ncid = ncvar->ncid; - int *dimidsp = ncvar->dimids; + while (isspace((int) *attstring)) attstring++; + if (*attstring == 0) break; + char *varname = attstring; + while (!isspace((int) *attstring) && *attstring != 0) attstring++; + if (*attstring == 0) lstop = true; + if (*(attstring - 1) == ',') *(attstring - 1) = 0; + *attstring++ = 0; - cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts); - for (int i = 0; i < nvdims; ++i) - for (int dimid = 0; dimid < ndims; ++dimid) - if (ncdims[dimid].dimid == dimidsp[i]) + int dimvarid; + int status = nc_inq_varid(ncid, varname, &dimvarid); + if (status == NC_NOERR) + { + if (is_valid_coordinate(&ncvars[dimvarid])) { - dimidsp[i] = dimid; - break; + cdf_set_var(&ncvars[dimvarid], CoordVar); + if (!CDI_Ignore_Att_Coordinates) + { + ncvar->coordvarids[i] = dimvarid; + ncvar->ncoordvars++; + } } - strcpy(ncvar->name, name); + } + else + { + if (!CDI_Ignore_Att_Coordinates) ncvar->ncoordvars++; - for (int ncdimid = 0; ncdimid < nvdims; ncdimid++) ncvar->dimtypes[ncdimid] = -1; + int k; + for (k = 0; k < *nchecked_vars; ++k) + if (str_is_equal(checked_vars[k], varname)) break; - ncvar->xtype = xtype; - ncvar->ndims = nvdims; + if (k == *nchecked_vars) + { + if (*nchecked_vars < max_check_vars) checked_vars[*nchecked_vars++] = strdup(varname); + Warning("%s - >%s<", nc_strerror(status), varname); + } + } + } +} -#ifdef HAVE_NETCDF4 - if (format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4) +static void +read_auxiliary_vars(int ncid, char *attstring, ncvar_t *ncvar, ncvar_t *ncvars) +{ + bool lstop = false; + for (int i = 0; i < MAX_AUXVARS && !lstop; i++) + { + while (isspace((int) *attstring)) attstring++; + if (*attstring == 0) break; + char *varname = attstring; + while (!isspace((int) *attstring) && *attstring != 0) attstring++; + if (*attstring == 0) lstop = true; + *attstring++ = 0; + + int dimvarid; + int status = nc_inq_varid(ncid, varname, &dimvarid); + if (status == NC_NOERR) { - int shuffle = 0, deflate = 0, deflateLevel = 0; - nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflateLevel); - if (deflate > 0) ncvar->hasDeflate = true; + cdf_set_var(&ncvars[dimvarid], CoordVar); + // if ( !CDI_Ignore_Att_Coordinates ) + { + ncvar->auxvarids[i] = dimvarid; + ncvar->nauxvars++; + } + } + else + Warning("%s - %s", nc_strerror(status), varname); + } +} + +static void +set_vars_chunks(int ncid, int ncvarid, int nvdims, ncvar_t *ncvar) +{ + int shuffle = 0, deflate = 0, deflateLevel = 0; + nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflateLevel); + if (deflate > 0) ncvar->hasDeflate = true; #ifdef HAVE_NC_DEF_VAR_SZIP - int options_mask = 0, pixels_per_block = 0; - nc_inq_var_szip(ncid, ncvarid, &options_mask, &pixels_per_block); - if (options_mask && pixels_per_block) ncvar->hasSzip = true; + int options_mask = 0, pixels_per_block = 0; + nc_inq_var_szip(ncid, ncvarid, &options_mask, &pixels_per_block); + if (options_mask && pixels_per_block) ncvar->hasSzip = true; #endif - ncvar->hasFilter = cdf_get_var_filter(ncid, ncvarid, ncvar->filterSpec, CDI_MAX_NAME); - // if (ncvar->hasFilter) printf("filterSpec: %s=%s\n", ncvar->name, ncvar->filterSpec); + ncvar->hasFilter = cdf_get_var_filter(ncid, ncvarid, ncvar->filterSpec, CDI_MAX_NAME); + // if (ncvar->hasFilter) printf("filterSpec: %s=%s\n", ncvar->name, ncvar->filterSpec); - size_t chunks[nvdims]; - int storageIn; - if (nc_inq_var_chunking(ncid, ncvarid, &storageIn, chunks) == NC_NOERR) + size_t chunks[nvdims]; + int storageIn; + if (nc_inq_var_chunking(ncid, ncvarid, &storageIn, chunks) == NC_NOERR) + { + if (storageIn == NC_CHUNKED) + { + ncvar->isChunked = true; + for (int i = 0; i < nvdims; ++i) ncvar->chunks[i] = chunks[i]; + if (CDI_Debug) { - if (storageIn == NC_CHUNKED) - { - ncvar->isChunked = true; - for (int i = 0; i < nvdims; ++i) ncvar->chunks[i] = chunks[i]; - if (CDI_Debug) - { - fprintf(stderr, "%s: chunking %d %d %d chunks ", name, storageIn, NC_CONTIGUOUS, NC_CHUNKED); - for (int i = 0; i < nvdims; ++i) fprintf(stderr, "%zu ", chunks[i]); - fprintf(stderr, "\n"); - } - - set_extra_attr(ncvar->extra, nvdims, chunks); - } + fprintf(stderr, "%s: chunking %d %d %d chunks ", ncvar->name, storageIn, NC_CONTIGUOUS, NC_CHUNKED); + for (int i = 0; i < nvdims; ++i) fprintf(stderr, "%zu ", chunks[i]); + fprintf(stderr, "\n"); } - size_t size; - size_t nelems; - float preemption; - if (nc_get_var_chunk_cache(ncid, ncvarid, &size, &nelems, &preemption) == NC_NOERR) + set_extra_attr(ncvar->extra, nvdims, chunks); + } + } + + size_t size; + size_t nelems; + float preemption; + if (nc_get_var_chunk_cache(ncid, ncvarid, &size, &nelems, &preemption) == NC_NOERR) + { + ncvar->chunkCacheSize = size; + ncvar->chunkCacheNelems = nelems; + ncvar->chunkCachePreemption = preemption; + if (CDI_Debug) fprintf(stderr, "%s: chunkCacheSize=%zu nelems=%zu preemption=%g\n", ncvar->name, size, nelems, preemption); + } +} + +#if defined __GNUC__ || (__GNUC__ == 4 && __GNUC_MINOR__ == 9) +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wstrict-overflow" +#endif + +static void +read_vars_info(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int format) +{ + for (int varid = 0; varid < nvars; varid++) + { + ncvar_t *ncvar = &ncvars[varid]; + cdf_inq_var(ncvar->ncid, varid, ncvar->name, &ncvar->xtype, &ncvar->ndims, ncvar->dimids, &ncvar->nattsNC); + + for (int vdimid = 0; vdimid < ncvar->ndims; ++vdimid) + for (int gdimid = 0; gdimid < ndims; ++gdimid) + if (ncdims[gdimid].dimid == ncvar->dimids[vdimid]) { - ncvar->chunkCacheSize = size; - ncvar->chunkCacheNelems = nelems; - ncvar->chunkCachePreemption = preemption; - if (CDI_Debug) fprintf(stderr, "%s: chunkCacheSize=%zu nelems=%zu preemption=%g\n", name, size, nelems, preemption); + ncvar->dimids[vdimid] = gdimid; + break; } + + for (int vdimid = 0; vdimid < ncvar->ndims; vdimid++) ncvar->dimtypes[vdimid] = -1; + +#ifdef HAVE_NETCDF4 + if (format == NC_FORMAT_NETCDF4_CLASSIC || format == NC_FORMAT_NETCDF4) + { + set_vars_chunks(ncvar->ncid, varid, ncvar->ndims, ncvar); } #endif + } +} - if (nvdims > 0) +static void +set_vars_timetype(int nvars, ncvar_t *ncvars, int timedimid) +{ + for (int varid = 0; varid < nvars; varid++) + { + ncvar_t *ncvar = &ncvars[varid]; + if (ncvar->ndims > 0) { - if (timedimid == dimidsp[0]) + if (timedimid == ncvar->dimids[0]) { ncvar->timetype = TIME_VARYING; cdf_set_dim(ncvar, 0, T_AXIS); } else { - for (int ncdimid = 1; ncdimid < nvdims; ncdimid++) + int nvdims = ncvar->ndims; + for (int vdimid = 1; vdimid < nvdims; vdimid++) { - if (timedimid == dimidsp[ncdimid]) + if (timedimid == ncvar->dimids[vdimid]) { Warning("Time must be the first dimension! Unsupported array structure, skipped variable %s!", ncvar->name); ncvar->varStatus = CoordVar; @@ -1190,14 +1257,30 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed } } } +} + +static void +scan_vars_attr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int modelID) +{ + 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; + + char attname[CDI_MAX_NAME]; + char attstring[8192]; for (int ncvarid = 0; ncvarid < nvars; ncvarid++) { ncvar_t *ncvar = &ncvars[ncvarid]; int ncid = ncvar->ncid; - int *dimidsp = ncvar->dimids; - - cdf_inq_var(ncid, ncvarid, name, &xtype, &nvdims, dimidsp, &nvatts); + const char *name = ncvar->name; + int nvdims = ncvar->ndims; + nc_type xtype = ncvar->xtype; + int nvatts = ncvar->nattsNC; if (ncvar->natts == 0 && nvatts > 0) ncvar->atts = (int *) Malloc((size_t) nvatts * sizeof(int)); @@ -1205,6 +1288,8 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed { int nc_cell_id = CDI_UNDEFID; + nc_type atttype; + size_t attlen; cdf_inq_attname(ncid, ncvarid, iatt, attname); cdf_inq_atttype(ncid, ncvarid, attname, &atttype); cdf_inq_attlen(ncid, ncvarid, attname, &attlen); @@ -1387,82 +1472,12 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed } else if (isText && (str_is_equal(attname, "associate") || str_is_equal(attname, "coordinates"))) { - bool lstop = false; - char *pstring = attstring; - - for (int i = 0; i < MAX_COORDVARS && !lstop; 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; - if (*(pstring - 1) == ',') *(pstring - 1) = 0; - *pstring++ = 0; - - int dimvarid; - int status = nc_inq_varid(ncid, varname, &dimvarid); - if (status == NC_NOERR) - { - if (is_valid_coordinate(&ncvars[dimvarid])) - { - cdf_set_var(&ncvars[dimvarid], CoordVar); - if (!CDI_Ignore_Att_Coordinates) - { - ncvar->coordvarids[i] = dimvarid; - ncvar->ncoordvars++; - } - } - } - else - { - if (!CDI_Ignore_Att_Coordinates) ncvar->ncoordvars++; - - int k; - for (k = 0; k < nchecked_vars; ++k) - if (str_is_equal(checked_vars[k], varname)) break; - - if (k == nchecked_vars) - { - if (nchecked_vars < max_check_vars) checked_vars[nchecked_vars++] = strdup(varname); - Warning("%s - >%s<", nc_strerror(status), varname); - } - } - } - + read_coordinates_vars(ncid, attstring, ncvar, ncvars, &nchecked_vars, checked_vars, max_check_vars); cdf_set_var(ncvar, DataVar); } else if (isText && str_is_equal(attname, "auxiliary_variable")) { - bool lstop = false; - 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], CoordVar); - // if ( !CDI_Ignore_Att_Coordinates ) - { - ncvar->auxvarids[i] = dimvarid; - ncvar->nauxvars++; - } - } - else - Warning("%s - %s", nc_strerror(status), varname); - - if (lstop) break; - } - + read_auxiliary_vars(ncid, attstring, ncvar, ncvars); cdf_set_var(ncvar, DataVar); } else if (isText && str_is_equal(attname, "grid_mapping")) @@ -1473,6 +1488,14 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed { 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); @@ -1482,22 +1505,26 @@ cdfScanVarAttr(int nvars, ncvar_t *ncvars, int ndims, ncdim_t *ncdims, int timed else if (isText && str_is_equal(attname, "positive")) { str_to_lower(attstring); - if (str_is_equal(attstring, "down")) ncvar->positive = POSITIVE_DOWN; else if (str_is_equal(attstring, "up")) ncvar->positive = POSITIVE_UP; - if (ncvar->ndims == 1) - { - cdf_set_var(ncvar, CoordVar); - cdf_set_dim(ncvar, 0, Z_AXIS); - ncdims[ncvar->dimids[0]].dimtype = Z_AXIS; - } - else if (ncvar->ndims == 0) + int dimid0 = ncvar->dimids[0]; + if (ncvar->varStatus == UndefVar + && (nvdims == 0 || (nvdims == 1 && ncvar->dimtypes[0] == CDI_UNDEFID && ncdims[dimid0].ncvarid == CDI_UNDEFID))) { - cdf_set_var(ncvar, CoordVar); - ncvar->isZaxis = true; + if (nvdims == 1) + { + cdf_set_var(ncvar, CoordVar); + cdf_set_dim(ncvar, 0, Z_AXIS); + if (dimid0 < ndims) ncdims[dimid0].dimtype = Z_AXIS; + } + else if (nvdims == 0) + { + cdf_set_var(ncvar, CoordVar); + ncvar->isZaxis = true; + } } else { @@ -1638,7 +1665,7 @@ cdf_set_chunk_info(stream_t *streamptr, int nvars, ncvar_t *ncvars) } static void -cdfVerifyVarAttr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) +verify_vars_attr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) { nc_type atttype; size_t attlen; @@ -1685,12 +1712,37 @@ cdfVerifyVarAttr(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) { - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) + for (int varid = 0; varid < nvars; varid++) { - ncvar_t *ncvar = &ncvars[ncvarid]; + ncvar_t *ncvar = &ncvars[varid]; if (ncvar->varStatus == DataVar) { int ndims = ncvar->ndims; @@ -1703,35 +1755,23 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) if (CDI_Debug) { - Message("var %d %s", ncvarid, ncvar->name); + Message("var %d %s", varid, ncvar->name); for (int i = 0; i < ndims; i++) printf(" dim%d type=%d ", i, ncvar->dimtypes[i]); printf("\n"); } } } - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) + for (int varid = 0; varid < nvars; varid++) { - ncvar_t *ncvar = &ncvars[ncvarid]; + ncvar_t *ncvar = &ncvars[varid]; 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--) @@ -1754,9 +1794,9 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) } } - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) + for (int varid = 0; varid < nvars; varid++) { - ncvar_t *ncvar = &ncvars[ncvarid]; + ncvar_t *ncvar = &ncvars[varid]; int ndims = ncvar->ndims; for (int i = 0; i < ndims; i++) { @@ -1772,28 +1812,16 @@ cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims) } } - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) + for (int varid = 0; varid < nvars; varid++) { - ncvar_t *ncvar = &ncvars[ncvarid]; + ncvar_t *ncvar = &ncvars[varid]; 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); - } - + 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--) @@ -1812,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)) { @@ -2058,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; @@ -3739,7 +3769,7 @@ cdf_copy_attflt(int fileID, int vlistID, nc_type xtype, size_t attlen, char *att if (attlen > 8) Free(pattflt); } -static bool +static void check_cube_sphere(int vlistID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims) { bool isGeosData = false; @@ -3821,7 +3851,7 @@ check_cube_sphere(int vlistID, int nvars, ncvar_t *ncvars, ncdim_t *ncdims) } } - return isGeosData; + if (CDI_Debug) Message("isGeosData %d", isGeosData); } static void @@ -3885,12 +3915,6 @@ cdf_scan_global_attr(int fileID, int vlistID, int ngatts, int *instID, int *mode else if (str_is_equal(attname, "CDO")) { } - /* - else if ( str_is_equal(attname, "forecast_reference_time") ) - { - memcpy(fcreftime, attstring, attstrlen+1); - } - */ else if (str_is_equal(attname, "grid_file_uri")) { memcpy(gridInfo->gridfile, attstring, attstrlen + 1); @@ -4259,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 { @@ -4267,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); @@ -4313,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; @@ -4326,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); @@ -4337,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 @@ -4372,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) { @@ -4410,8 +4438,6 @@ cdf_read_timesteps(size_t numTimesteps, stream_t *streamptr, taxis_t *taxis0) } } } - - if (vDateTimeList) Free(vDateTimeList); } } @@ -4424,82 +4450,155 @@ stream_set_ncdims(stream_t *streamptr, int ndims, ncdim_t *ncdims) for (int i = 0; i < n; i++) streamptr->ncDimLen[i] = ncdims[i].len; } +static void +set_ncdim_ids(int fileID, int ndims, ncdim_t *ncdims) +{ + if (ndims) + { + int gdimid = 0; + for (int i = 0; i < NC_MAX_DIMS; ++i) + { + if (nc_inq_dimlen(fileID, i, NULL) == NC_NOERR) + { + ncdims[gdimid++].dimid = i; + if (gdimid == ndims) break; + } + } + } +} + +static void +read_ncdims(int fileID, int ndims, ncdim_t *ncdims) +{ + for (int gdimid = 0; gdimid < ndims; gdimid++) + { + cdf_inq_dimlen(fileID, ncdims[gdimid].dimid, &ncdims[gdimid].len); + cdf_inq_dimname(fileID, ncdims[gdimid].dimid, ncdims[gdimid].name); + } +} + +static void +check_ncgroups(int fileID) +{ + int numgrps = 0; + int ncids[NC_MAX_VARS]; + char gname[CDI_MAX_NAME]; + nc_inq_grps(fileID, &numgrps, ncids); + for (int i = 0; i < numgrps; ++i) + { + int ncid = ncids[i]; + nc_inq_grpname(ncid, gname); + int gndims, gnvars, gngatts, gunlimdimid; + cdf_inq(ncid, &gndims, &gnvars, &gngatts, &gunlimdimid); + + if (CDI_Debug) Message("%s: ndims %d, nvars %d, ngatts %d", gname, gndims, gnvars, gngatts); + } + if (numgrps) Warning("NetCDF4 groups not supported! Found %d root group%s.", numgrps, (numgrps > 1) ? "s" : ""); +} + +static void +find_coordinates_vars(int ndims, ncdim_t *ncdims, int nvars, ncvar_t *ncvars) +{ + for (int gdimid = 0; gdimid < ndims; gdimid++) + { + for (int varid = 0; varid < nvars; varid++) + { + ncvar_t *ncvar = &ncvars[varid]; + if (ncvar->ndims == 1 && gdimid == ncvar->dimids[0] && ncdims[gdimid].ncvarid == CDI_UNDEFID) + { + if (str_is_equal(ncvar->name, ncdims[gdimid].name)) + { + ncdims[gdimid].ncvarid = varid; + ncvar->varStatus = CoordVar; + } + } + } + } +} + +// set time dependent data vars +static void +find_varying_data_vars1d(int timedimid, int nvars, ncvar_t *ncvars) +{ + for (int ncvarid = 0; ncvarid < nvars; ncvarid++) + { + ncvar_t *ncvar = &ncvars[ncvarid]; + if (ncvar->ndims == 1) + { + if (timedimid != CDI_UNDEFID && timedimid == ncvar->dimids[0]) + { + if (ncvar->varStatus != CoordVar) cdf_set_var(ncvar, DataVar); + } + else + { + // if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar); + } + // if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar); + } + } +} + +static void +set_coordinates_varids(int nvars, ncvar_t *ncvars) +{ + for (int varid = 0; varid < nvars; varid++) + { + ncvar_t *ncvar = &ncvars[varid]; + if (ncvar->varStatus == DataVar && ncvar->ncoordvars) + { + for (int i = 0; i < ncvar->ncoordvars; i++) + { + int ncvaridc = ncvar->coordvarids[i]; + if (ncvaridc != CDI_UNDEFID) + { + ncvar_t *ncvarc = &ncvars[ncvaridc]; + // clang-format off + if (ncvarc->isLon || ncvarc->isXaxis) ncvar->xvarid = ncvaridc; + else if (ncvarc->isLat || ncvarc->isYaxis) ncvar->yvarid = ncvaridc; + else if (ncvarc->isZaxis) ncvar->zvarid = ncvaridc; + else if (ncvarc->isTaxis) ncvar->tvarid = ncvaridc; + else if (ncvarc->isCharAxis) ncvar->cvarids[i] = ncvaridc; + else if (ncvarc->printWarning) + { + Warning("Coordinates variable %s can't be assigned!", ncvarc->name); + ncvarc->printWarning = false; + } + // clang-format on + } + } + } + } +} + int cdfInqContents(stream_t *streamptr) { - bool timeHasUnits = false; - bool timeHasBounds = false; - bool timeClimatology = false; - int leadtime_id = CDI_UNDEFID; - int format = 0; - char fcreftime[CDI_MAX_NAME]; GridInfo gridInfo; gridInfo.gridfile[0] = 0; memset(gridInfo.uuid, 0, CDI_UUID_SIZE); gridInfo.number_of_grid_used = CDI_UNDEFID; gridInfo.timedimid = CDI_UNDEFID; - fcreftime[0] = 0; - int vlistID = streamptr->vlistID; int fileID = streamptr->fileID; if (CDI_Debug) Message("streamID = %d, fileID = %d", streamptr->self, fileID); -#ifdef HAVE_NETCDF4 - nc_inq_format(fileID, &format); -#endif - int ndims = 0, nvars = 0, ngatts = 0, unlimdimid = 0; 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 = ndims ? (ncdim_t *) Malloc((size_t) ndims * sizeof(ncdim_t)) : NULL; init_ncdims(ndims, ncdims); + set_ncdim_ids(fileID, ndims, ncdims); + read_ncdims(fileID, ndims, ncdims); - if (ndims) - { - int ncdimid = 0; - for (int dimid = 0; dimid < NC_MAX_DIMS; ++dimid) - { - if (nc_inq_dimlen(fileID, dimid, NULL) == NC_NOERR) - { - ncdims[ncdimid++].dimid = dimid; - if (ncdimid == ndims) break; - } - } - } - + int format = 0; #ifdef HAVE_NETCDF4 - if (format == NC_FORMAT_NETCDF4) - { - int numgrps = 0; - int ncids[NC_MAX_VARS]; - char gname[CDI_MAX_NAME]; - nc_inq_grps(fileID, &numgrps, ncids); - for (int i = 0; i < numgrps; ++i) - { - int ncid = ncids[i]; - nc_inq_grpname(ncid, gname); - int gndims, gnvars, gngatts, gunlimdimid; - cdf_inq(ncid, &gndims, &gnvars, &gngatts, &gunlimdimid); - - if (CDI_Debug) Message("%s: ndims %d, nvars %d, ngatts %d", gname, gndims, gnvars, gngatts); - - if (gndims == 0) - { - } - } - if (numgrps) Warning("NetCDF4 groups not supported! Found %d root group%s.", numgrps, (numgrps > 1) ? "s" : ""); - } + nc_inq_format(fileID, &format); + if (format == NC_FORMAT_NETCDF4) check_ncgroups(fileID); #endif if (nvars == 0) @@ -4512,6 +4611,9 @@ cdfInqContents(stream_t *streamptr) ncvar_t *ncvars = (ncvar_t *) Malloc((size_t) nvars * sizeof(ncvar_t)); init_ncvars(nvars, ncvars, fileID); + read_vars_info(nvars, ncvars, ndims, ncdims, format); + find_coordinates_vars(ndims, ncdims, nvars, ncvars); + // scan global attributes int instID = CDI_UNDEFID; int modelID = CDI_UNDEFID; @@ -4520,12 +4622,10 @@ cdfInqContents(stream_t *streamptr) cdf_scan_global_attr(fileID, vlistID, ngatts, &instID, &modelID, &ucla_les, uuidOfVGrid, &gridInfo); // find time dim - int timedimid = (unlimdimid >= 0) ? unlimdimid : cdf_time_dimid(fileID, ndims, nvars, ncdims); - + int timedimid = (unlimdimid >= 0) ? unlimdimid : cdf_time_dimid(fileID, ndims, ncdims, nvars, ncvars); streamptr->basetime.ncdimid = timedimid; - size_t ntsteps = 0; - if (timedimid != CDI_UNDEFID) cdf_inq_dimlen(fileID, ncdims[timedimid].dimid, &ntsteps); + size_t ntsteps = (timedimid == CDI_UNDEFID) ? 0 : ncdims[timedimid].len; if (ntsteps > INT_MAX) { Warning("Size limit exceeded for time dimension (limit=%d)!", INT_MAX); @@ -4535,63 +4635,34 @@ cdfInqContents(stream_t *streamptr) if (CDI_Debug) Message("Number of timesteps = %zu", ntsteps); if (CDI_Debug) Message("Time dimid = %d", streamptr->basetime.ncdimid); - // read ncdims - for (int ncdimid = 0; ncdimid < ndims; ncdimid++) + // set T_AXIS dimtype + for (int gdimid = 0; gdimid < ndims; gdimid++) { - cdf_inq_dimlen(fileID, ncdims[ncdimid].dimid, &ncdims[ncdimid].len); - cdf_inq_dimname(fileID, ncdims[ncdimid].dimid, ncdims[ncdimid].name); - if (timedimid == ncdimid) ncdims[ncdimid].dimtype = T_AXIS; + if (timedimid == gdimid) ncdims[gdimid].dimtype = T_AXIS; } stream_set_ncdims(streamptr, ndims, ncdims); - if (CDI_Debug) cdf_print_vars(ncvars, nvars, "cdfScanVarAttr"); + if (CDI_Debug) cdf_print_vars(ncvars, nvars, "scan_vars_attr"); // scan attributes of all variables - cdfScanVarAttr(nvars, ncvars, ndims, ncdims, timedimid, modelID, format); + set_vars_timetype(nvars, ncvars, timedimid); + scan_vars_attr(nvars, ncvars, ndims, ncdims, modelID); + verify_vars_attr(nvars, ncvars, ncdims); - cdfVerifyVarAttr(nvars, ncvars, ncdims); + if (CDI_Convert_Cubesphere) check_cube_sphere(vlistID, nvars, ncvars, ncdims); - if (CDI_Convert_Cubesphere) - { - bool isGeosData = check_cube_sphere(vlistID, nvars, ncvars, ncdims); - if (CDI_Debug) Message("isGeosData %d", isGeosData); - } + if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find_varying_data_vars1d"); - if (CDI_Debug) cdf_print_vars(ncvars, nvars, "find coordinates vars"); - - // find coordinates vars - for (int ncdimid = 0; ncdimid < ndims; ncdimid++) - { - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) - { - ncvar_t *ncvar = &ncvars[ncvarid]; - if (ncvar->ndims == 1) - { - if (timedimid != CDI_UNDEFID && timedimid == ncvar->dimids[0]) - { - if (ncvar->varStatus != CoordVar) cdf_set_var(ncvar, DataVar); - } - else - { - // if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar); - } - // if ( ncvar->varStatus != DataVar ) cdf_set_var(ncvar, CoordVar); - - if (ncdimid == ncvar->dimids[0] && ncdims[ncdimid].ncvarid == CDI_UNDEFID) - if (str_is_equal(ncvar->name, ncdims[ncdimid].name)) - { - ncdims[ncdimid].ncvarid = ncvarid; - ncvar->varStatus = CoordVar; - } - } - } - } + find_varying_data_vars1d(timedimid, nvars, ncvars); // find time vars + bool timeHasUnits = false; + bool timeHasBounds = false; + bool timeClimatology = false; find_time_vars(nvars, ncvars, ncdims, timedimid, streamptr, &timeHasUnits, &timeHasBounds, &timeClimatology); - leadtime_id = find_leadtime(nvars, ncvars, timedimid); + int leadtime_id = find_leadtime(nvars, ncvars, timedimid); if (leadtime_id != CDI_UNDEFID) ncvars[leadtime_id].varStatus = CoordVar; // check ncvars @@ -4627,36 +4698,8 @@ cdfInqContents(stream_t *streamptr) } */ - // Set coordinates varids (att: associate) - for (int ncvarid = 0; ncvarid < nvars; ncvarid++) - { - ncvar_t *ncvar = &ncvars[ncvarid]; - if (ncvar->varStatus == DataVar && ncvar->ncoordvars) - { - for (int i = 0; i < ncvar->ncoordvars; i++) - { - int ncvaridc = ncvar->coordvarids[i]; - if (ncvaridc != CDI_UNDEFID) - { - ncvar_t *ncvarc = &ncvars[ncvaridc]; - // clang-format off - if (ncvarc->isLon || ncvarc->isXaxis) ncvar->xvarid = ncvaridc; - else if (ncvarc->isLat || ncvarc->isYaxis) ncvar->yvarid = ncvaridc; - else if (ncvarc->isZaxis) ncvar->zvarid = ncvaridc; - else if (ncvarc->isTaxis) ncvar->tvarid = ncvaridc; - else if (ncvarc->isCharAxis) ncvar->cvarids[i] = ncvaridc; - else if (ncvarc->printWarning) - { - Warning("Coordinates variable %s can't be assigned!", ncvarc->name); - ncvarc->printWarning = false; - } - // clang-format on - } - } - } - } + set_coordinates_varids(nvars, ncvars); - // set dim type cdf_set_dimtype(nvars, ncvars, ncdims); // read ECHAM VCT if present @@ -4737,12 +4780,9 @@ cdfInqContents(stream_t *streamptr) streamptr->basetime.leadtimeid = leadtime_id; taxis0.type = TAXIS_FORECAST; - int timeunit = -1; - if (ncvars[leadtime_id].units[0] != 0) timeunit = scan_time_units(ncvars[leadtime_id].units); + int timeunit = (ncvars[leadtime_id].units[0] != 0) ? scan_time_units(ncvars[leadtime_id].units) : -1; if (timeunit == -1) timeunit = taxis0.unit; taxis0.fc_unit = timeunit; - - set_forecast_time(fcreftime, &taxis0); } } diff --git a/src/stream_cdf_o.c b/src/stream_cdf_o.c index cd07f30a2ee6fd274b897e31f13807d947e0f8b6..987fb0514748e8247f2af414fa2003f1264e9217 100644 --- a/src/stream_cdf_o.c +++ b/src/stream_cdf_o.c @@ -33,14 +33,14 @@ cdfCopyRecord(stream_t *streamptr2, stream_t *streamptr1) void *data = Malloc(datasize * ((memtype == MEMTYPE_DOUBLE) ? sizeof(double) : sizeof(float))); size_t numMissVals; - cdf_read_record(streamptr1, memtype, data, &numMissVals); - cdf_write_record(streamptr2, memtype, data, numMissVals); + cdf_read_field(streamptr1, memtype, data, &numMissVals); + cdf_write_field(streamptr2, memtype, data, numMissVals); Free(data); } void -cdfDefRecord(stream_t *streamptr) +cdfDefField(stream_t *streamptr) { (void) streamptr; } diff --git a/src/stream_cdf_time.c b/src/stream_cdf_time.c index 62d8a29a998dce7b3e5354307134a6c28b5040a4..dc594c44d4d14dd8080fc484636b7cdff7f8ecfb 100644 --- a/src/stream_cdf_time.c +++ b/src/stream_cdf_time.c @@ -203,11 +203,9 @@ cdfDefTime(stream_t *streamptr) } else { - /* define bogus value since at this time, streamDefTimestep has - * not been called yet - * but since taxis->units is not set, it clearly will not - * exceed the size of unitstr_, i.e. when defining the units - * attribute to this value, a later redefinition will not + /* define bogus value since at this time, streamDefTimestep has not been called yet + * but since taxis->units is not set, it clearly will not exceed the size of unitstr_, + * i.e. when defining the units attribute to this value, a later redefinition will not * cause a recreation of on-disk data */ for (size_t i = 0; i < CDF_MAX_TIME_UNIT_STR; ++i) unitsStr_[i] = 'a'; diff --git a/src/stream_cgribex.c b/src/stream_cgribex.c index c625dc10d9b62169b875586a2cf909c6bd0166d8..a2c73b7f0c104ce5fc2657e94d659287bcd380b2 100644 --- a/src/stream_cgribex.c +++ b/src/stream_cgribex.c @@ -82,16 +82,6 @@ cgribexDelete(void *cgribex) } } -#ifdef __cplusplus -extern "C" -{ -#endif - int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp, unsigned char **gdsp, unsigned char **bmsp, - unsigned char **bdsp, long *gribrecsize); -#ifdef __cplusplus -} -#endif - static size_t cgribexSection2Length(void *gribbuffer, size_t gribbuffersize) { @@ -201,10 +191,10 @@ cgribexGetTimeUnit(int *isec1) case ISEC1_TABLE4_DAY: timeunit = TUNIT_DAY; break; default: if (lprint) - { - Warning("GRIB time unit %d unsupported!", ISEC1_TimeUnit); - lprint = false; - } + { + Warning("GRIB time unit %d unsupported!", ISEC1_TimeUnit); + lprint = false; + } break; } // clang-format on @@ -237,10 +227,10 @@ cgribexGetTsteptype(int timerange) case 10: tsteptype = TSTEP_INSTANT3; break; default: if (lprint) - { - Warning("Time range indicator %d unsupported, set to 0!", timerange); - lprint = false; - } + { + Warning("Time range indicator %d unsupported, set to 0!", timerange); + lprint = false; + } break; } // clang-format on @@ -758,6 +748,8 @@ cgribexSkipRecords(int fileID) size_t recsize = gribGetSize(fileID); if (recsize == 0) Error("Skipping of %d records failed!", CDI_Skip_Records); + grib_check_recsize(0, recsize); + off_t recpos = fileGetPos(fileID); fileSetPos(fileID, recpos, SEEK_CUR); } @@ -818,6 +810,7 @@ cgribexScanTimestep1(stream_t *streamptr) break; } + grib_check_recsize(1, recsize); ensureBufferSize(recsize, &buffersize, &gribbuffer); size_t readsize = recsize; @@ -984,6 +977,7 @@ cgribexScanTimestep2(stream_t *streamptr) break; } + grib_check_recsize(1, recsize); ensureBufferSize(recsize, &buffersize, &gribbuffer); size_t readsize = recsize; @@ -1172,6 +1166,7 @@ cgribexScanTimestep(stream_t *streamptr) break; } + grib_check_recsize(1, recsize); ensureBufferSize(recsize, &buffersize, &gribbuffer); size_t readsize = recsize; diff --git a/src/stream_ext.c b/src/stream_ext.c index 8f4e7ee86e3972ec99471cea938bae0e2e25c938..616ef92dc08043afedb8b2f06dc9aec377039ef0 100644 --- a/src/stream_ext.c +++ b/src/stream_ext.c @@ -38,43 +38,6 @@ extDefDatatype(int datatype, int *prec, int *number) *prec = (datatype == CDI_DATATYPE_FLT64 || datatype == CDI_DATATYPE_CPX64) ? EXSE_PREC_FP64 : EXSE_PREC_FP32; } -/* not used -int extInqRecord(stream_t *streamptr, int *varID, int *levelID) -{ - int status; - int fileID; - int icode, ilevel; - int zaxisID = -1; - int header[4]; - int vlistID; - void *extp = streamptr->record->objectp; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - - *varID = -1; - *levelID = -1; - - status = extRead(fileID, extp); - if ( status != 0 ) return 0; - - extInqHeader(extp, header); - - icode = header[1]; - ilevel = header[2]; - - *varID = vlistInqVarID(vlistID, icode); - - if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode); - - zaxisID = vlistInqVarZaxis(vlistID, *varID); - - *levelID = zaxisInqLevelID(zaxisID, (double) ilevel); - - return 1; -} -*/ - static void ext_read_recordSP(stream_t *streamptr, float *data, size_t *numMissVals) { @@ -140,7 +103,7 @@ ext_read_recordDP(stream_t *streamptr, double *data, size_t *numMissVals) } void -ext_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) +ext_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) { if (memtype == MEMTYPE_DOUBLE) ext_read_recordDP(streamptr, (double *) data, numMissVals); @@ -149,13 +112,13 @@ ext_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVal } void -extCopyRecord(stream_t *streamptr2, stream_t *streamptr1) +extCopyField(stream_t *streamptr2, stream_t *streamptr1) { streamFCopyRecord(streamptr2, streamptr1, "EXTRA"); } void -extDefRecord(stream_t *streamptr) +extDefField(stream_t *streamptr) { Record *record = streamptr->record; @@ -192,7 +155,7 @@ ext_write_recordDP(stream_t *streamptr, const double *data) } void -ext_write_record(stream_t *streamptr, int memtype, const void *data) +ext_write_field(stream_t *streamptr, int memtype, const void *data) { if (memtype == MEMTYPE_DOUBLE) ext_write_recordDP(streamptr, (const double *) data); diff --git a/src/stream_ext.h b/src/stream_ext.h index 3f6d3516066c1b0bf4c1c9bf9b5ed09fafd7d17d..1a0b331a56eb83d7de9c9af8755398a83eb48c76 100644 --- a/src/stream_ext.h +++ b/src/stream_ext.h @@ -8,11 +8,10 @@ int extInqContents(stream_t *streamptr); int extInqTimestep(stream_t *streamptr, int tsID); -int extInqRecord(stream_t *streamptr, int *varID, int *levelID); -void extDefRecord(stream_t *streamptr); -void extCopyRecord(stream_t *streamptr2, stream_t *streamptr1); -void ext_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); -void ext_write_record(stream_t *streamptr, int memtype, const void *data); +void extDefField(stream_t *streamptr); +void extCopyField(stream_t *streamptr2, stream_t *streamptr1); +void ext_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); +void ext_write_field(stream_t *streamptr, int memtype, const void *data); void extReadVarDP(stream_t *streamptr, int varID, double *data, size_t *numMissVals); void extWriteVarDP(stream_t *streamptr, int varID, const double *data); diff --git a/src/stream_grb.c b/src/stream_grb.c index a6985f86ba2c0273b7d81a4329f1ed21728fcea5..9441a53e3876091937dc1881c924dd5b05afde71 100644 --- a/src/stream_grb.c +++ b/src/stream_grb.c @@ -250,19 +250,8 @@ grbBitsPerValue(int datatype) return bitsPerValue; } -/* -int grbInqRecord(stream_t * streamptr, int *varID, int *levelID) -{ - int status; - - status = cgribexInqRecord(streamptr, varID, levelID); - - return (status); -} -*/ - void -grbDefRecord(stream_t *streamptr) +grbDefField(stream_t *streamptr) { UNUSED(streamptr); } diff --git a/src/stream_grb.h b/src/stream_grb.h index e187d4f963e17b84f37b92782ecc156502491f96..123a9a77f74c64f57f031b923058d0707387d8de 100644 --- a/src/stream_grb.h +++ b/src/stream_grb.h @@ -8,6 +8,12 @@ bool zaxis_units_is_Pa(int zaxisID); void ensureBufferSize(size_t requiredSize, size_t *curSize, void **buffer); int grbDecompress(size_t recsize, size_t *buffersize, void **gribbuffer); +static inline void +grib_check_recsize(int version, size_t recsize) +{ + if (recsize > 0xFFFFFFFF) Error("GRIB%d record size=%zu limit exceeded (max=%zu)", version, recsize, 0xFFFFFFFF); +} + static inline bool gribbyte_get_bit(int number, int bit) { @@ -31,11 +37,10 @@ long grbInqContents(stream_t *streamptr); int fdbInqTimestep(stream_t *streamptr, int tsID); int grbInqTimestep(stream_t *streamptr, int tsID); -int grbInqRecord(stream_t *streamptr, int *varID, int *levelID); -void grbDefRecord(stream_t *streamptr); -void grb_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); -void grb_write_record(stream_t *streamptr, int memtype, const void *data, size_t numMissVals); -void grbCopyRecord(stream_t *streamptr2, stream_t *streamptr1); +void grbDefField(stream_t *streamptr); +void grb_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); +void grb_write_field(stream_t *streamptr, int memtype, const void *data, size_t numMissVals); +void grbCopyField(stream_t *streamptr2, stream_t *streamptr1); void grb_read_var(stream_t *streamptr, int varID, int memtype, void *data, size_t *numMissVals); void grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, size_t numMissVals); diff --git a/src/stream_gribapi.c b/src/stream_gribapi.c index 399988356fca6e65a395d3383290169c4d8bbe5d..30c14eba1bfd748fa5a7910663f93bc2ba17ec2d 100644 --- a/src/stream_gribapi.c +++ b/src/stream_gribapi.c @@ -1258,6 +1258,7 @@ gribapiScanTimestep1(stream_t *streamptr) break; } + grib_check_recsize(2, recsize); ensureBufferSize(recsize, &buffersize, &gribbuffer); size_t readsize = recsize; @@ -1419,6 +1420,7 @@ gribapiScanTimestep2(stream_t *streamptr) break; } + grib_check_recsize(2, recsize); ensureBufferSize(recsize, &buffersize, &gribbuffer); size_t readsize = recsize; @@ -1594,6 +1596,7 @@ gribapiScanTimestep(stream_t *streamptr) break; } + grib_check_recsize(2, recsize); ensureBufferSize(recsize, &buffersize, &gribbuffer); size_t readsize = recsize; diff --git a/src/stream_ieg.c b/src/stream_ieg.c index a913e69e787aad1d403bf731172ca797fde70652..4194ed0373cba5a384ee4cbfc4515d54dbee1aa6 100644 --- a/src/stream_ieg.c +++ b/src/stream_ieg.c @@ -90,7 +90,7 @@ ieg_read_recordDP(stream_t *streamptr, double *data, size_t *numMissVals) } void -ieg_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) +ieg_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) { if (memtype == MEMTYPE_DOUBLE) ieg_read_recordDP(streamptr, (double *) data, numMissVals); @@ -418,13 +418,13 @@ iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID) } void -iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1) +iegCopyField(stream_t *streamptr2, stream_t *streamptr1) { streamFCopyRecord(streamptr2, streamptr1, "IEG"); } void -iegDefRecord(stream_t *streamptr) +iegDefField(stream_t *streamptr) { Record *record = streamptr->record; @@ -507,7 +507,7 @@ ieg_write_recordDP(stream_t *streamptr, const double *data) } void -ieg_write_record(stream_t *streamptr, int memtype, const void *data) +ieg_write_field(stream_t *streamptr, int memtype, const void *data) { if (memtype == MEMTYPE_DOUBLE) ieg_write_recordDP(streamptr, (const double *) data); diff --git a/src/stream_ieg.h b/src/stream_ieg.h index a099cdaf4b96dbb58248c015a23926a2685d5d80..85e841411cb4066f04e1bc7ee740457dda2bd181 100644 --- a/src/stream_ieg.h +++ b/src/stream_ieg.h @@ -8,11 +8,10 @@ int iegInqContents(stream_t *streamptr); int iegInqTimestep(stream_t *streamptr, int tsID); -int iegInqRecord(stream_t *streamptr, int *varID, int *levelID); -void iegDefRecord(stream_t *streamptr); -void iegCopyRecord(stream_t *streamptr2, stream_t *streamptr1); -void ieg_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); -void ieg_write_record(stream_t *streamptr, int memtype, const void *data); +void iegDefField(stream_t *streamptr); +void iegCopyField(stream_t *streamptr2, stream_t *streamptr1); +void ieg_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); +void ieg_write_field(stream_t *streamptr, int memtype, const void *data); void iegReadVarDP(stream_t *streamptr, int varID, double *data, size_t *numMissVals); void iegWriteVarDP(stream_t *streamptr, int varID, const double *data); diff --git a/src/stream_read.c b/src/stream_read.c index 059547401207df92a4b16d4d59d9eecc7b5e81ef..c5655dd332ba5042628bcfb04c5e416865c50a82 100644 --- a/src/stream_read.c +++ b/src/stream_read.c @@ -237,19 +237,19 @@ stream_read_record(int streamID, int memtype, void *data, size_t *numMissVals) switch (cdiBaseFiletype(streamptr->filetype)) { #ifdef HAVE_LIBGRIB - case CDI_FILETYPE_GRIB: grb_read_record(streamptr, memtype, data, numMissVals); break; + case CDI_FILETYPE_GRIB: grb_read_field(streamptr, memtype, data, numMissVals); break; #endif #ifdef HAVE_LIBSERVICE - case CDI_FILETYPE_SRV: srv_read_record(streamptr, memtype, data, numMissVals); break; + case CDI_FILETYPE_SRV: srv_read_field(streamptr, memtype, data, numMissVals); break; #endif #ifdef HAVE_LIBEXTRA - case CDI_FILETYPE_EXT: ext_read_record(streamptr, memtype, data, numMissVals); break; + case CDI_FILETYPE_EXT: ext_read_field(streamptr, memtype, data, numMissVals); break; #endif #ifdef HAVE_LIBIEG - case CDI_FILETYPE_IEG: ieg_read_record(streamptr, memtype, data, numMissVals); break; + case CDI_FILETYPE_IEG: ieg_read_field(streamptr, memtype, data, numMissVals); break; #endif #ifdef HAVE_LIBNETCDF - case CDI_FILETYPE_NETCDF: cdf_read_record(streamptr, memtype, data, numMissVals); break; + case CDI_FILETYPE_NETCDF: cdf_read_field(streamptr, memtype, data, numMissVals); break; #endif default: Error("%s support not compiled in!", strfiletype(streamptr->filetype)); } @@ -258,7 +258,7 @@ stream_read_record(int streamID, int memtype, void *data, size_t *numMissVals) } void -streamReadRecord(int streamID, double *data, SizeType *numMissVals) +streamReadField(int streamID, double *data, SizeType *numMissVals) { size_t numMiss = 0; stream_read_record(streamID, MEMTYPE_DOUBLE, (void *) data, &numMiss); @@ -266,7 +266,7 @@ streamReadRecord(int streamID, double *data, SizeType *numMissVals) } void -streamReadRecordF(int streamID, float *data, SizeType *numMissVals) +streamReadFieldF(int streamID, float *data, SizeType *numMissVals) { size_t numMiss = 0; stream_read_record(streamID, MEMTYPE_FLOAT, (void *) data, &numMiss); diff --git a/src/stream_record.c b/src/stream_record.c index a8c6b3ec9818da91aba3d70563e335345c8d2aa1..114b0df4065a60eb624c4f4eff57a749c80807cf 100644 --- a/src/stream_record.c +++ b/src/stream_record.c @@ -97,7 +97,7 @@ cdiInitRecord(stream_t *streamptr) } void -streamInqRecord(int streamID, int *varID, int *levelID) +streamInqField(int streamID, int *varID, int *levelID) { check_parg(varID); check_parg(levelID); @@ -146,7 +146,7 @@ The function streamDefRecord defines the meta-data of the next record. @EndFunction */ void -streamDefRecord(int streamID, int varID, int levelID) +streamDefField(int streamID, int varID, int levelID) { stream_t *streamptr = stream_to_pointer(streamID); @@ -178,21 +178,21 @@ streamDefRecord(int streamID, int varID, int levelID) switch (cdiBaseFiletype(streamptr->filetype)) { #ifdef HAVE_LIBGRIB - case CDI_FILETYPE_GRIB: grbDefRecord(streamptr); break; + case CDI_FILETYPE_GRIB: grbDefField(streamptr); break; #endif #ifdef HAVE_LIBSERVICE - case CDI_FILETYPE_SRV: srvDefRecord(streamptr); break; + case CDI_FILETYPE_SRV: srvDefField(streamptr); break; #endif #ifdef HAVE_LIBEXTRA - case CDI_FILETYPE_EXT: extDefRecord(streamptr); break; + case CDI_FILETYPE_EXT: extDefField(streamptr); break; #endif #ifdef HAVE_LIBIEG - case CDI_FILETYPE_IEG: iegDefRecord(streamptr); break; + case CDI_FILETYPE_IEG: iegDefField(streamptr); break; #endif #ifdef HAVE_LIBNETCDF case CDI_FILETYPE_NETCDF: if (streamptr->accessmode == 0) cdfEndDef(streamptr); - cdfDefRecord(streamptr); + cdfDefField(streamptr); break; #endif default: Error("%s support not compiled in!", strfiletype(streamptr->filetype)); break; @@ -200,7 +200,7 @@ streamDefRecord(int streamID, int varID, int levelID) } void -streamCopyRecord(int streamID2, int streamID1) +streamCopyField(int streamID2, int streamID1) { stream_t *streamptr1 = stream_to_pointer(streamID1), *streamptr2 = stream_to_pointer(streamID2); int filetype1 = streamptr1->filetype, filetype2 = streamptr2->filetype, filetype = CDI_FILETYPE_UNDEF; @@ -213,16 +213,16 @@ streamCopyRecord(int streamID2, int streamID1) switch (cdiBaseFiletype(filetype)) { #ifdef HAVE_LIBGRIB - case CDI_FILETYPE_GRIB: grbCopyRecord(streamptr2, streamptr1); break; + case CDI_FILETYPE_GRIB: grbCopyField(streamptr2, streamptr1); break; #endif #ifdef HAVE_LIBSERVICE - case CDI_FILETYPE_SRV: srvCopyRecord(streamptr2, streamptr1); break; + case CDI_FILETYPE_SRV: srvCopyField(streamptr2, streamptr1); break; #endif #ifdef HAVE_LIBEXTRA - case CDI_FILETYPE_EXT: extCopyRecord(streamptr2, streamptr1); break; + case CDI_FILETYPE_EXT: extCopyField(streamptr2, streamptr1); break; #endif #ifdef HAVE_LIBIEG - case CDI_FILETYPE_IEG: iegCopyRecord(streamptr2, streamptr1); break; + case CDI_FILETYPE_IEG: iegCopyField(streamptr2, streamptr1); break; #endif #ifdef HAVE_LIBNETCDF case CDI_FILETYPE_NETCDF: cdfCopyRecord(streamptr2, streamptr1); break; diff --git a/src/stream_srv.c b/src/stream_srv.c index b38d669198c4ac8966cf1d004fee6415080a5ee9..fa1beba762d18c1133569a7ef733b72232458318 100644 --- a/src/stream_srv.c +++ b/src/stream_srv.c @@ -34,43 +34,6 @@ srvDefDatatype(int datatype) return (datatype == CDI_DATATYPE_FLT64) ? EXSE_PREC_FP64 : EXSE_PREC_FP32; } -/* not used -int srvInqRecord(stream_t *streamptr, int *varID, int *levelID) -{ - int status; - int fileID; - int icode, ilevel; - int zaxisID = -1; - int header[8]; - int vlistID; - void *srvp = streamptr->record->objectp; - - vlistID = streamptr->vlistID; - fileID = streamptr->fileID; - - *varID = -1; - *levelID = -1; - - status = srvRead(fileID, srvp); - if ( status != 0 ) return (0); - - srvInqHeader(srvp, header); - - icode = header[0]; - ilevel = header[1]; - - *varID = vlistInqVarID(vlistID, icode); - - if ( *varID == CDI_UNDEFID ) Error("Code %d undefined", icode); - - zaxisID = vlistInqVarZaxis(vlistID, *varID); - - *levelID = zaxisInqLevelID(zaxisID, (double) ilevel); - - return 1; -} -*/ - static void srv_read_recordSP(stream_t *streamptr, float *data, size_t *numMissVals) { @@ -130,7 +93,7 @@ srv_read_recordDP(stream_t *streamptr, double *data, size_t *numMissVals) } void -srv_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) +srv_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals) { if (memtype == MEMTYPE_DOUBLE) srv_read_recordDP(streamptr, (double *) data, numMissVals); @@ -139,13 +102,13 @@ srv_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVal } void -srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1) +srvCopyField(stream_t *streamptr2, stream_t *streamptr1) { streamFCopyRecord(streamptr2, streamptr1, "SRV"); } void -srvDefRecord(stream_t *streamptr) +srvDefField(stream_t *streamptr) { Record *record = streamptr->record; @@ -198,7 +161,7 @@ srv_write_recordDP(stream_t *streamptr, const double *data) } void -srv_write_record(stream_t *streamptr, int memtype, const void *data) +srv_write_field(stream_t *streamptr, int memtype, const void *data) { if (memtype == MEMTYPE_DOUBLE) srv_write_recordDP(streamptr, (const double *) data); diff --git a/src/stream_srv.h b/src/stream_srv.h index adeaf679200828310ac9245e697cac6e25f75b7b..8e13653b13061c77b13ec394c32440467b01a678 100644 --- a/src/stream_srv.h +++ b/src/stream_srv.h @@ -8,11 +8,10 @@ int srvInqContents(stream_t *streamptr); int srvInqTimestep(stream_t *streamptr, int tsID); -int srvInqRecord(stream_t *streamptr, int *varID, int *levelID); -void srvDefRecord(stream_t *streamptr); -void srvCopyRecord(stream_t *streamptr2, stream_t *streamptr1); -void srv_read_record(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); -void srv_write_record(stream_t *streamptr, int memtype, const void *data); +void srvDefField(stream_t *streamptr); +void srvCopyField(stream_t *streamptr2, stream_t *streamptr1); +void srv_read_field(stream_t *streamptr, int memtype, void *data, size_t *numMissVals); +void srv_write_field(stream_t *streamptr, int memtype, const void *data); void srvReadVarDP(stream_t *streamptr, int varID, double *data, size_t *numMissVals); void srvWriteVarDP(stream_t *streamptr, int varID, const double *data); diff --git a/src/stream_write.c b/src/stream_write.c index 4383cb782b7d3883762bc4ecf426782d071cc3fa..11f781e5abdcdea85783d3637d36152b55af8816 100644 --- a/src/stream_write.c +++ b/src/stream_write.c @@ -286,19 +286,19 @@ stream_write_record(int streamID, int memtype, const void *data, SizeType numMis switch (cdiBaseFiletype(streamptr->filetype)) { #ifdef HAVE_LIBGRIB - case CDI_FILETYPE_GRIB: grb_write_record(streamptr, memtype, data, (size_t) numMissVals); break; + case CDI_FILETYPE_GRIB: grb_write_field(streamptr, memtype, data, (size_t) numMissVals); break; #endif #ifdef HAVE_LIBSERVICE - case CDI_FILETYPE_SRV: srv_write_record(streamptr, memtype, data); break; + case CDI_FILETYPE_SRV: srv_write_field(streamptr, memtype, data); break; #endif #ifdef HAVE_LIBEXTRA - case CDI_FILETYPE_EXT: ext_write_record(streamptr, memtype, data); break; + case CDI_FILETYPE_EXT: ext_write_field(streamptr, memtype, data); break; #endif #ifdef HAVE_LIBIEG - case CDI_FILETYPE_IEG: ieg_write_record(streamptr, memtype, data); break; + case CDI_FILETYPE_IEG: ieg_write_field(streamptr, memtype, data); break; #endif #ifdef HAVE_LIBNETCDF - case CDI_FILETYPE_NETCDF: cdf_write_record(streamptr, memtype, data, (size_t) numMissVals); break; + case CDI_FILETYPE_NETCDF: cdf_write_field(streamptr, memtype, data, (size_t) numMissVals); break; #endif default: Error("%s support not compiled in!", strfiletype(streamptr->filetype)); } @@ -322,13 +322,13 @@ The values are converted to the external data type of the variable, if necessary @EndFunction */ void -streamWriteRecord(int streamID, const double *data, SizeType numMissVals) +streamWriteField(int streamID, const double *data, SizeType numMissVals) { stream_write_record(streamID, MEMTYPE_DOUBLE, (const void *) data, numMissVals); } void -streamWriteRecordF(int streamID, const float *data, SizeType numMissVals) +streamWriteFieldF(int streamID, const float *data, SizeType numMissVals) { stream_write_record(streamID, MEMTYPE_FLOAT, (const void *) data, numMissVals); } diff --git a/src/taxis.c b/src/taxis.c index a22ffb4e27cb83a6ebc188fd7f2d9ce5bccc1737..5acf45b5715e6dba9f64f41f1473927f3a56ddfd 100644 --- a/src/taxis.c +++ b/src/taxis.c @@ -1289,6 +1289,7 @@ cdi_decode_timeval(double timevalue, const taxis_t *taxis) return (taxis->type == TAXIS_ABSOLUTE) ? split_timevalue(timevalue, taxis->unit) : rtimeval2datetime(timevalue, taxis); } +/* static int64_t datetime2seconds(CdiDateTime datetime) { @@ -1305,7 +1306,7 @@ datetime2seconds(CdiDateTime datetime) return seconds; } - +*/ double cdi_encode_timeval(CdiDateTime datetime, taxis_t *taxis) { @@ -1322,10 +1323,12 @@ cdi_encode_timeval(CdiDateTime datetime, taxis_t *taxis) int64_t xdate = cdiDate_get(datetime.date); timeValue = (double) xdate / 100 + copysign((double) (datetime.date.day != 0) * 0.5, (double) xdate); } + /* else if (taxis->unit == TUNIT_SECOND) { timeValue = (double) datetime2seconds(datetime); } + */ else { int hour, minute, second, ms; diff --git a/src/vlist.c b/src/vlist.c index 9a4c817ce0cdbf94acc5f92d8dfbfc98a8fcc848..be99645856a386166af6443eb295fb48b9dd6be2 100644 --- a/src/vlist.c +++ b/src/vlist.c @@ -948,7 +948,7 @@ vlistNvars(int vlistID) } int -vlistNumRecords(int vlistID) +vlistNumFields(int vlistID) { vlist_t *vlistptr = vlist_to_pointer(vlistID);