diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..b4dd7447 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,70 @@ +name: build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CPPFLAGS: "-I/home/runner/hdf5/include -I/home/runner/netcdf-c/include" + LDFLAGS: "-L/home/runner/hdf5/lib -L/home/runner/netcdf-c/lib" + + steps: + - uses: actions/checkout@v2 + - name: Installs + run: | + sudo apt-get install doxygen graphviz wget gfortran libjpeg-dev libz-dev + - name: cache-hdf5 + id: cache-hdf5 + uses: actions/cache@v2 + with: + path: ~/hdf5 + key: hdf5-${{ runner.os }}-1.10.7 + + - name: build-hdf5 + if: steps.cache-hdf5.outputs.cache-hit != 'true' + run: | + set -x + wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.7/src/hdf5-1.10.7.tar.gz &> /dev/null + tar -xzf hdf5-1.10.7.tar.gz + pushd hdf5-1.10.7 + ./configure --prefix=/home/runner/hdf5 --disable-tools --disable-fortran --disable-cxx + make + sudo make install + popd + - name: build-netcdf-c + run: | + set -x + git clone -b ejh_quantize_2 https://github.com/edwardhartnett/netcdf-c.git + pushd netcdf-c + autoreconf -i + ./configure --prefix=/home/runner/netcdf-c --disable-dap --disable-utilities + make -j + sudo make install + popd + # - name: cmake build + # run: | + # set -x + # gcc --version + # export LD_LIBRARY_PATH="/home/runner/netcdf-c/lib:/home/runner/hdf5/lib:$LD_LIBRARY_PATH" + # mkdir build + # cd build + # cmake -Wno-dev -DNetCDF_C_LIBRARY=/home/runner/netcdf-c/lib/libnetcdf.so -DNetCDF_C_INCLUDE_DIR=/home/runner/netcdf-c/include .. || (cat CMakeFiles/CMakeOutput.log && cat CMakeFiles/CMakeError.log) + # make VERBOSE=1 + # make tests VERBOSE=1 +# ctest -VV + - name: autotools build + run: | + set -x + gcc --version + autoreconf -i + ./configure + make -j check + + diff --git a/.gitignore b/.gitignore index e138aa34..e29baa8f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ CTestConfig.cmake -build* \#.\# *.*~ html diff --git a/docs/netcdf-f90-sec6-variables.md b/docs/netcdf-f90-sec6-variables.md index cc1f39d6..b8f224a1 100644 --- a/docs/netcdf-f90-sec6-variables.md +++ b/docs/netcdf-f90-sec6-variables.md @@ -127,7 +127,8 @@ in a netCDF-4/HDF5 file. integer, optional, intent(in) :: deflate_level logical, optional, intent(in) :: shuffle, fletcher32 integer, optional, intent(in) :: endianness - integer, optional, intent(in) :: cache_size, cache_nelems, cache_preemption + integer, optional, intent(in) :: cache_size, cache_nelems, cache_preemption + integer, optional, intent(in) :: quantize_mode, nsd integer :: nf90_def_var @@ -250,7 +251,19 @@ in a netCDF-4/HDF5 file. while a value of 100 means fully read chunks are always preempted before other chunks. +`quantize_mode` +: Set to nf90_noquantize (0) for no quantization (the default), or + nf90_quantize_bitgroom (1) for bitgroom quantization. Quantization + allows users to specify a number of significant digits (NSD) in + nf90_float and nf90_double variables. Bits beyond those needed to + maintain the NSD are set to zero or one (alternating). This causes + the data to compress better when compression is applied. + +`nsd` + +: If quantize_mode is set to nf90_quantize_bitgroom, then this is the + number of significant digits to be maintained in the data. ## Return Codes @@ -723,6 +736,7 @@ netCDF-4/HDF5 file. integer, optional, intent(out) :: deflate_level logical, optional, intent(out) :: shuffle, fletcher32 integer, optional, intent(out) :: endianness + integer, optional, intent(in) :: quantize_mode, nsd integer :: nf90_inquire_variable @@ -798,6 +812,22 @@ netCDF-4/HDF5 file. big-endian format, and NF90\_ENDIAN\_NATIVE if the endianness is not set, and the variable is not created yet. +`quantize_mode` + +: Will be set to nf90_noquantize (0) for no quantization, or + nf90_quantize_bitgroom (1) for bitgroom quantization. Quantization + allows users to specify a number of significant digits (NSD) in + nf90_float and nf90_double variables. Bits beyond those needed to + maintain the NSD are set to zero or one (alternating). This causes + the data to compress better when compression is applied. + +`nsd` + +: If quantize_mode is set to nf90_quantize_bitgroom, then this will be + set to the number of significant digits to be maintained in the + data. + + These functions return the value NF90\_NOERR if no errors occurred. Otherwise, the returned status indicates an error. Possible causes of errors include: diff --git a/fortran/module_netcdf4_nc_interfaces.f90 b/fortran/module_netcdf4_nc_interfaces.f90 index 122b0e79..c80c0f69 100755 --- a/fortran/module_netcdf4_nc_interfaces.f90 +++ b/fortran/module_netcdf4_nc_interfaces.f90 @@ -724,6 +724,19 @@ Function nc_inq_var_szip(ncid, varid, options_mask, pixels_per_block) BIND(C) End Function nc_inq_var_szip End Interface +!------------------------------- nc_inq_var_quantize ------------------------------ +Interface + Function nc_inq_var_quantize(ncid, varid, quantize_mode, nsd) BIND(C) + + USE ISO_C_BINDING, ONLY: C_INT + + Integer(C_INT), VALUE :: ncid, varid + Integer(C_INT), Intent(INOUT) :: quantize_mode, nsd + + Integer(C_INT) :: nc_inq_var_quantize + + End Function nc_inq_var_quantize +End Interface !------------------------------- nc_def_var_fletcher32 ------------------------ Interface Function nc_def_var_fletcher32(ncid, varid, fletcher32) BIND(C) diff --git a/fortran/module_netcdf4_nf_interfaces.F90 b/fortran/module_netcdf4_nf_interfaces.F90 index 2090ce1b..dbb92d86 100755 --- a/fortran/module_netcdf4_nf_interfaces.F90 +++ b/fortran/module_netcdf4_nf_interfaces.F90 @@ -544,6 +544,28 @@ Function nf_inq_var_szip(ncid, varid, options_mask, pixels_per_block) RESULT(sta End Function nf_inq_var_szip End Interface +!-------------------------------- nf_def_var_quantize -------------------------- +Interface + Function nf_def_var_quantize( ncid, varid, quantize_mode, nsd) & + RESULT (status) + + Integer, Intent(IN) :: ncid, varid, quantize_mode, nsd + Integer :: status + + End Function nf_def_var_quantize +End Interface +!-------------------------------- nf_inq_var_quantize ----------------------------- +Interface + Function nf_inq_var_quantize(ncid, varid, quantize_mode, nsd) RESULT(status) + + Implicit NONE + + Integer, Intent(IN) :: ncid, varid + Integer, Intent(INOUT) :: quantize_mode, nsd + Integer :: status + + End Function nf_inq_var_quantize +End Interface !-------------------------------- nf_def_var_fletcher32 ------------------------ Interface Function nf_def_var_fletcher32( ncid, varid, fletcher32) RESULT(status) diff --git a/fortran/module_netcdf_nc_data.F90 b/fortran/module_netcdf_nc_data.F90 index 4508fe4e..b112ddd8 100755 --- a/fortran/module_netcdf_nc_data.F90 +++ b/fortran/module_netcdf_nc_data.F90 @@ -405,6 +405,10 @@ Module netcdf_nc_data Integer(C_INT), Parameter :: NC_ECANTEXTEND = -130 Integer(C_INT), Parameter :: NC_EMPI = -131 +! Quantize feature + Integer(C_INT), Parameter :: NC_NOQUANTIZE = 0 + Integer(C_INT), Parameter :: NC_QUANTIZE_BITGROOM = 1 + #endif !------------------------------------------------------------------------------ diff --git a/fortran/module_netcdf_nc_interfaces.f90 b/fortran/module_netcdf_nc_interfaces.f90 index 9d78fb65..eec92b5d 100755 --- a/fortran/module_netcdf_nc_interfaces.f90 +++ b/fortran/module_netcdf_nc_interfaces.f90 @@ -2540,6 +2540,19 @@ Function nc_def_var_szip(ncid, varid, options_mask, pixels_per_block) BIND(C) End Function nc_def_var_szip End Interface +!---------------------------------- nc_def_var_quantize --------------------------------- +Interface + Function nc_def_var_quantize(ncid, varid, quantize_mode, nsd) BIND(C) + + USE ISO_C_BINDING, ONLY: C_CHAR, C_INT + + Integer(C_INT), VALUE :: ncid, varid, quantize_mode, nsd + + Integer(C_INT) :: nc_def_var_quantize + + End Function nc_def_var_quantize +End Interface + !---------------------------- Start of module procedures --------------------- CONTAINS diff --git a/fortran/module_netcdf_nf_data.F90 b/fortran/module_netcdf_nf_data.F90 index c554a614..e5c070db 100755 --- a/fortran/module_netcdf_nf_data.F90 +++ b/fortran/module_netcdf_nf_data.F90 @@ -161,7 +161,11 @@ Module netcdf_nf_data ! Error handling codes Integer, Parameter :: NF_FATAL = NC_FATAL - Integer, Parameter :: NF_VERBOSE = NC_VERBOSE + Integer, Parameter :: NF_VERBOSE = NC_VERBOSE + + ! Quantize feature + Integer, Parameter :: NF_NOQUANTIZE = NC_NOQUANTIZE + Integer, Parameter :: NF_QUANTIZE_BITGROOM = NC_QUANTIZE_BITGROOM #ifdef ENABLE_CDF5 ! new format types diff --git a/fortran/netcdf4.inc b/fortran/netcdf4.inc index c2a11f70..47796e36 100755 --- a/fortran/netcdf4.inc +++ b/fortran/netcdf4.inc @@ -94,6 +94,12 @@ integer nf_collective parameter (nf_collective = 1) +! For NF_DEF_VAR_QUANTIZE. + integer nf_noquantize + parameter (nf_noquantize = 0) + integer nf_quantize_bitgroom + parameter (nf_quantize_bitgroom = 1) + ! New error codes. integer nf_ehdferr ! Error at HDF5 layer. parameter (nf_ehdferr = -101) @@ -211,6 +217,12 @@ integer nf_inq_var_szip external nf_inq_var_szip + integer nf_def_var_quantize + external nf_def_var_quantize + + integer nf_inq_var_quantize + external nf_inq_var_quantize + integer nf_def_var_fletcher32 external nf_def_var_fletcher32 diff --git a/fortran/netcdf4_externals.f90 b/fortran/netcdf4_externals.f90 index 4b0690a4..ca735f7c 100644 --- a/fortran/netcdf4_externals.f90 +++ b/fortran/netcdf4_externals.f90 @@ -28,4 +28,4 @@ nf_get_var_int64, nf_get_chunk_cache, nf_set_chunk_cache, & nf_inq_var_szip, nf_def_var_szip, nf_free_vlens, nf_free_string, & nf_set_var_chunk_cache, nf_get_var_chunk_cache, nf_rename_grp, & - nf_def_var_filter, nf_inq_var_filter + nf_def_var_filter, nf_inq_var_filter, nf_inq_var_quantize, nf_def_var_quantize diff --git a/fortran/netcdf4_func.f90 b/fortran/netcdf4_func.f90 index a8315faa..0b7da068 100644 --- a/fortran/netcdf4_func.f90 +++ b/fortran/netcdf4_func.f90 @@ -531,6 +531,16 @@ function nf90_def_var_szip(ncid, varid, options_mask, pixels_per_block) nf90_def_var_szip = nf_def_var_szip(ncid, varid, options_mask, pixels_per_block) end function nf90_def_var_szip ! ----------- + function nf90_def_var_quantize(ncid, varid, quantize_mode, nsd) + integer, intent(in) :: ncid + integer, intent(in) :: varid + integer, intent(in) :: quantize_mode + integer, intent(in) :: nsd + integer :: nf90_def_var_quantize + + nf90_def_var_quantize = nf_def_var_quantize(ncid, varid, quantize_mode, nsd) + end function nf90_def_var_quantize + ! ----------- function nf90_def_var_fletcher32(ncid, varid, fletcher32) integer, intent(in) :: ncid integer, intent(in) :: varid @@ -571,6 +581,16 @@ function nf90_inq_var_szip(ncid, varid, options_mask, pixels_per_block) nf90_inq_var_szip = nf_inq_var_szip(ncid, varid, options_mask, pixels_per_block) end function nf90_inq_var_szip ! ----------- + function nf90_inq_var_quantize(ncid, varid, quantize_mode, nsd) + integer, intent(in) :: ncid + integer, intent(in) :: varid + integer, intent(out) :: quantize_mode + integer, intent(out) :: nsd + integer :: nf90_inq_var_quantize + + nf90_inq_var_quantize = nf_inq_var_quantize(ncid, varid, quantize_mode, nsd) + end function nf90_inq_var_quantize + ! ----------- function nf90_inq_var_fletcher32(ncid, varid, fletcher32) integer, intent(in) :: ncid integer, intent(in) :: varid diff --git a/fortran/netcdf4_variables.f90 b/fortran/netcdf4_variables.f90 index 399d6275..b7b1e4b4 100644 --- a/fortran/netcdf4_variables.f90 +++ b/fortran/netcdf4_variables.f90 @@ -19,7 +19,7 @@ end function nf90_def_var_Scalar ! ----- function nf90_def_var_oneDim(ncid, name, xtype, dimids, varid, contiguous, & chunksizes, deflate_level, shuffle, fletcher32, endianness, & - cache_size, cache_nelems, cache_preemption) + cache_size, cache_nelems, cache_preemption, quantize_mode, nsd) integer, intent( in) :: ncid character (len = *), intent( in) :: name integer, intent(in) :: xtype @@ -31,6 +31,7 @@ function nf90_def_var_oneDim(ncid, name, xtype, dimids, varid, contiguous, & logical, optional, intent(in) :: shuffle, fletcher32 integer, optional, intent(in) :: endianness integer, optional, intent(in) :: cache_size, cache_nelems, cache_preemption + integer, optional, intent(in) :: quantize_mode, nsd integer :: nf90_def_var_oneDim integer, dimension(1) :: dimidsA, chunksizes1 @@ -123,11 +124,23 @@ function nf90_def_var_oneDim(ncid, name, xtype, dimids, varid, contiguous, & if (nf90_def_var_oneDim .ne. nf90_noerr) return endif + ! Set quantize if the user wants to. + if (present(quantize_mode)) then + if (.not. present(nsd)) then + nf90_def_var_oneDim = nf90_einval + return + endif + nf90_def_var_oneDim = nf_def_var_quantize(ncid, varid, quantize_mode, nsd) + if (nf90_def_var_oneDim .ne. nf90_noerr) return + + endif + + end function nf90_def_var_oneDim ! ----- function nf90_def_var_ManyDims(ncid, name, xtype, dimids, varid, contiguous, & chunksizes, deflate_level, shuffle, fletcher32, endianness, cache_size, & - cache_nelems, cache_preemption) + cache_nelems, cache_preemption, quantize_mode, nsd) integer, intent(in) :: ncid character (len = *), intent(in) :: name integer, intent( in) :: xtype @@ -139,6 +152,7 @@ function nf90_def_var_ManyDims(ncid, name, xtype, dimids, varid, contiguous, & logical, optional, intent(in) :: shuffle, fletcher32 integer, optional, intent(in) :: endianness integer, optional, intent(in) :: cache_size, cache_nelems, cache_preemption + integer, optional, intent(in) :: quantize_mode, nsd integer :: nf90_def_var_ManyDims ! Local variables. @@ -239,6 +253,16 @@ function nf90_def_var_ManyDims(ncid, name, xtype, dimids, varid, contiguous, & if (nf90_def_var_ManyDims .ne. nf90_noerr) return endif + ! Set quantize if the user wants to. + if (present(quantize_mode)) then + if (.not. present(nsd)) then + nf90_def_var_ManyDims = nf90_einval + return + endif + nf90_def_var_ManyDims = nf_def_var_quantize(ncid, varid, quantize_mode, nsd) + if (nf90_def_var_ManyDims .ne. nf90_noerr) return + endif + end function nf90_def_var_ManyDims ! ----- function nf90_inq_varid(ncid, name, varid) @@ -264,7 +288,7 @@ end function nf90_set_var_chunk_cache ! ----- function nf90_inquire_variable(ncid, varid, name, xtype, ndims, dimids, nAtts, & contiguous, chunksizes, deflate_level, shuffle, fletcher32, endianness, & - cache_size, cache_nelems, cache_preemption) + cache_size, cache_nelems, cache_preemption, quantize_mode, nsd) integer, intent(in) :: ncid, varid character (len = *), optional, intent(out) :: name integer, optional, intent(out) :: xtype, ndims @@ -276,6 +300,7 @@ function nf90_inquire_variable(ncid, varid, name, xtype, ndims, dimids, nAtts, & logical, optional, intent(out) :: shuffle, fletcher32 integer, optional, intent(out) :: endianness integer, optional, intent(out) :: cache_size, cache_nelems, cache_preemption + integer, optional, intent(out) :: quantize_mode, nsd integer :: nf90_inquire_variable ! Local variables @@ -348,6 +373,13 @@ function nf90_inquire_variable(ncid, varid, name, xtype, ndims, dimids, nAtts, & if (present(cache_nelems)) cache_nelems = nelems1 if (present(cache_preemption)) cache_preemption = preemption1 endif + + ! And the quantization... + if (present(quantize_mode)) then + nf90_inquire_variable = nf_inq_var_quantize(ncid, varid, quantize_mode, nsd) + if (nf90_inquire_variable .ne. nf90_noerr) return + endif + end function nf90_inquire_variable ! ----- function nf90_rename_var(ncid, varid, newname) diff --git a/fortran/netcdf4_visibility.f90 b/fortran/netcdf4_visibility.f90 index 5fb23b11..34b6989e 100644 --- a/fortran/netcdf4_visibility.f90 +++ b/fortran/netcdf4_visibility.f90 @@ -23,4 +23,5 @@ nf90_def_var_endian, nf90_inq_var_endian, nf90_inq_user_type, & nf90_put_att_any, nf90_get_att_any, nf90_get_var_any, nf90_put_var_any, & nf90_rename_grp, nf90_def_var_filter, nf90_inq_var_filter, & - nf90_def_var_szip, nf90_inq_var_szip + nf90_def_var_szip, nf90_inq_var_szip, nf90_def_var_quantize, nf90_inq_var_quantize + diff --git a/fortran/netcdf_constants.f90 b/fortran/netcdf_constants.f90 index 786e379f..47913d90 100644 --- a/fortran/netcdf_constants.f90 +++ b/fortran/netcdf_constants.f90 @@ -241,7 +241,9 @@ nf90_noshuffle = 0, & nf90_shuffle = 1, & nf90_szip_ec_option_mask = 4, & - nf90_szip_nn_option_mask = 32 + nf90_szip_nn_option_mask = 32, & + nf90_noquantize = 0, & + nf90_quantize_bitgroom = 1 ! This is the position of NC_NETCDF4 in cmode, counting from the ! right, starting (uncharacteristically for fortran) at 0. It's needed diff --git a/fortran/nf_nc4.f90 b/fortran/nf_nc4.f90 index 08890ecf..2ba42120 100755 --- a/fortran/nf_nc4.f90 +++ b/fortran/nf_nc4.f90 @@ -1569,6 +1569,55 @@ Function nf_inq_var_szip(ncid, varid, options_mask, pixels_per_block) RESULT(sta End Function nf_inq_var_szip +!-------------------------------- nf_def_var_quantize -------------------------- + Function nf_def_var_quantize(ncid, varid, quantize_mode, nsd) & + RESULT (status) +! define variable deflation + USE netcdf4_nc_interfaces + Implicit NONE + Integer, Intent(IN) :: ncid, varid, quantize_mode, nsd + Integer :: status + Integer(C_INT) :: cncid, cvarid, cquantize_mode, cnsd, cstatus + + cncid = ncid + cvarid = varid-1 + cquantize_mode = quantize_mode + cnsd = nsd + + cstatus = nc_def_var_quantize(cncid, cvarid, cquantize_mode, cnsd) + status = cstatus + + End Function nf_def_var_quantize +!-------------------------------- nf_inq_var_quantize ----------------------------- + Function nf_inq_var_quantize(ncid, varid, quantize_mode, nsd) RESULT(status) + +! get quantize variables + + USE netcdf4_nc_interfaces + + Implicit NONE + + Integer, Intent(IN) :: ncid, varid + Integer, Intent(INOUT) :: quantize_mode, nsd + + Integer :: status + + Integer(C_INT) :: cncid, cvarid, cquantize_mode, cnsd, cstatus + + cncid = ncid + cvarid = varid-1 + + cstatus = nc_inq_var_quantize(cncid, cvarid, cquantize_mode, cnsd) + + If (cstatus == NC_NOERR) Then + quantize_mode = cquantize_mode + nsd = cnsd + EndIf + + status = cstatus + + End Function nf_inq_var_quantize + !-------------------------------- nf_def_var_fletcher32 ----------------------- Function nf_def_var_fletcher32( ncid, varid, fletcher32) RESULT(status) diff --git a/nf03_test4/CMakeLists.txt b/nf03_test4/CMakeLists.txt index 9c876cbb..cbd3832c 100644 --- a/nf03_test4/CMakeLists.txt +++ b/nf03_test4/CMakeLists.txt @@ -14,7 +14,7 @@ FILE(COPY ${COPY_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/) if (USE_NETCDF4) # Add these netCDF-4 test programs. SET(nc4_check_PROGRAMS f90tst_vars f90tst_vars_vlen f90tst_grps - f90tst_fill f90tst_fill2 f90tst_vars3 f90tst_vars4 f90tst_vars2 + f90tst_fill f90tst_fill2 f90tst_vars3 f90tst_vars4 f90tst_vars5 f90tst_vars2 f90tst_path f90tst_rengrps f90tst_nc4 f90tst_types f90tst_types2) SET(check_PROGRAMS ${check_PROGRAMS} ${nc4_check_PROGRAMS}) SET(TESTS ${TESTS} ${nc4_check_PROGRAMS}) @@ -27,6 +27,7 @@ if (USE_NETCDF4) SET(f90tst_vars2_SOURCES f90tst_vars2.f90) SET(f90tst_vars3_SOURCES f90tst_vars3.f90) SET(f90tst_vars4_SOURCES f90tst_vars4.f90) + SET(f90tst_vars5_SOURCES f90tst_vars5.f90) SET(f90tst_path_SOURCES f90tst_path.f90) SET(f90tst_rengrps_SOURCES f90tst_rengrps.f90) SET(f90tst_nc4_SOURCES f90tst_nc4.f90) diff --git a/nf03_test4/Makefile.am b/nf03_test4/Makefile.am index cb7579c0..0a47f540 100644 --- a/nf03_test4/Makefile.am +++ b/nf03_test4/Makefile.am @@ -14,8 +14,8 @@ LDADD = ${top_builddir}/fortran/libnetcdff.la # tst_f90_nc4 NC4_F90_TESTS = f90tst_vars f90tst_vars_vlen f90tst_grps f90tst_fill \ -f90tst_fill2 f90tst_vars2 f90tst_vars3 f90tst_vars4 f90tst_path \ -f90tst_rengrps f90tst_nc4 f90tst_types f90tst_types2 +f90tst_fill2 f90tst_vars2 f90tst_vars3 f90tst_vars4 f90tst_vars5 \ +f90tst_path f90tst_rengrps f90tst_nc4 f90tst_types f90tst_types2 check_PROGRAMS = $(NC4_F90_TESTS) TESTS = $(NC4_F90_TESTS) @@ -27,6 +27,7 @@ f90tst_fill2_SOURCES = f90tst_fill2.f90 f90tst_vars2_SOURCES = f90tst_vars2.f90 f90tst_vars3_SOURCES = f90tst_vars3.f90 f90tst_vars4_SOURCES = f90tst_vars4.f90 +f90tst_vars5_SOURCES = f90tst_vars5.f90 f90tst_path_SOURCES = f90tst_path.f90 f90tst_rengrps_SOURCES = f90tst_rengrps.f90 f90tst_nc4_SOURCES = f90tst_nc4.f90 diff --git a/nf03_test4/f90tst_vars5.f90 b/nf03_test4/f90tst_vars5.f90 new file mode 100644 index 00000000..05114427 --- /dev/null +++ b/nf03_test4/f90tst_vars5.f90 @@ -0,0 +1,171 @@ +! This is part of the netCDF package. Copyright 2006-2019 +! University Corporation for Atmospheric Research/Unidata. See +! COPYRIGHT file for conditions of use. + +! This program tests netCDF-4 variable functions from fortran. + +! $Id: f90tst_vars2.f90,v 1.7 2010/01/25 21:01:07 ed Exp $ + +program f90tst_vars5 + use typeSizes + use netcdf + implicit none + + ! This is the name of the data file we will create. + character (len = *), parameter :: FILE_NAME = "f90tst_vars5.nc" + + ! We are writing 2D data, a 6 x 12 grid. + integer, parameter :: NDIM1 = 1 + integer, parameter :: DIM_LEN_5 = 5 + integer start(NDIM1), count(NDIM1) + real real_data(DIM_LEN_5) + real*8 double_data(DIM_LEN_5) + + ! We need these ids and other gunk for netcdf. + integer :: ncid, varid1, varid2, varid3, varid4, varid5, dimids(NDIM1) + integer :: chunksizes(NDIM1), chunksizes_in(NDIM1) + integer :: x_dimid, y_dimid + integer :: nvars, ngatts, ndims, unlimdimid, file_format + integer :: x, y + integer, parameter :: DEFLATE_LEVEL = 4 + integer (kind = EightByteInt), parameter :: TOE_SAN_VALUE = 2147483648_EightByteInt + character (len = *), parameter :: VAR1_NAME = "Chon-Ji" + character (len = *), parameter :: VAR2_NAME = "Tan-Gun" + character (len = *), parameter :: VAR3_NAME = "Toe-San" + character (len = *), parameter :: VAR4_NAME = "Won-Hyo" + character (len = *), parameter :: VAR5_NAME = "Yul-Guk" + integer, parameter :: CACHE_SIZE = 8, CACHE_NELEMS = 571 + integer, parameter :: CACHE_PREEMPTION = 66 + + ! Information read back from the file to check correctness. + integer :: varid1_in, varid2_in, varid3_in, varid4_in, varid5_in + integer :: xtype_in, ndims_in, natts_in, dimids_in(NDIM1) + character (len = nf90_max_name) :: name_in + integer :: endianness_in, deflate_level_in + logical :: shuffle_in, fletcher32_in, contiguous_in + integer (kind = EightByteInt) :: toe_san_in + integer :: cache_size_in, cache_nelems_in, cache_preemption_in + integer :: quantize_mode_in, nsd_in + real real_data_in(DIM_LEN_5) + real*8 double_data_in(DIM_LEN_5) + real real_data_expected(DIM_LEN_5) + real*8 double_data_expected(DIM_LEN_5) + real diff + real, parameter :: EPSILON = .01 + + print *, '' + print *,'*** Testing use of quantize feature on netCDF-4 vars from Fortran 90.' + + ! Create some pretend data. + real_data(1) = 1.11111111 + real_data(2) = 1.0 + real_data(3) = 9.99999999 + real_data(4) = 12345.67 + real_data(5) = .1234567 + double_data(1) = 1.1111111 + double_data(2) = 1.0 + double_data(3) = 9.999999999 + double_data(4) = 1234567890.12345 + double_data(5) = 1234567890 + + ! Create the netCDF file. + call check(nf90_create(FILE_NAME, nf90_netcdf4, ncid, cache_nelems = CACHE_NELEMS, & + cache_size = CACHE_SIZE)) + + ! Define the dimension. + call check(nf90_def_dim(ncid, "x", DIM_LEN_5, x_dimid)) + dimids = (/ x_dimid /) + + ! Define some variables. + call check(nf90_def_var(ncid, VAR1_NAME, NF90_FLOAT, dimids, varid1& + &, deflate_level = DEFLATE_LEVEL, quantize_mode =& + & nf90_quantize_bitgroom, nsd = 3)) + call check(nf90_def_var(ncid, VAR2_NAME, NF90_DOUBLE, dimids,& + & varid2, contiguous = .TRUE., quantize_mode =& + & nf90_quantize_bitgroom, nsd = 3)) + + ! Write the pretend data to the file. + call check(nf90_put_var(ncid, varid1, real_data)) + call check(nf90_put_var(ncid, varid2, double_data)) + + ! Close the file. + call check(nf90_close(ncid)) + + ! What we expect to get back. + real_data_expected(1) = 1.11084 + real_data_expected(2) = 1.000488 + real_data_expected(3) = 10 + real_data_expected(4) = 12348 + real_data_expected(5) = 0.1234436 + double_data_expected(1) = 1.11083984375 + double_data_expected(2) = 1.00048828125 + double_data_expected(3) = 10 + double_data_expected(4) = 1234698240 + double_data_expected(5) = 1234173952 + + ! Reopen the file. + call check(nf90_open(FILE_NAME, nf90_nowrite, ncid)) + + ! Check some stuff out. + call check(nf90_inquire(ncid, ndims, nvars, ngatts, unlimdimid, file_format)) + if (ndims /= 1 .or. nvars /= 2 .or. ngatts /= 0 .or. unlimdimid /= -1 .or. & + file_format /= nf90_format_netcdf4) stop 2 + + ! Get varids. + call check(nf90_inq_varid(ncid, VAR1_NAME, varid1_in)) + call check(nf90_inq_varid(ncid, VAR2_NAME, varid2_in)) + + ! Check variable 1. + call check(nf90_inquire_variable(ncid, varid1_in, name_in, xtype_in, ndims_in, dimids_in, & + natts_in, chunksizes = chunksizes_in, endianness = endianness_in, fletcher32 = fletcher32_in, & + deflate_level = deflate_level_in, shuffle = shuffle_in, cache_size = cache_size_in, & + cache_nelems = cache_nelems_in, cache_preemption = cache_preemption_in, & + quantize_mode = quantize_mode_in, nsd = nsd_in)) + if (name_in .ne. VAR1_NAME .or. xtype_in .ne. NF90_FLOAT .or. ndims_in .ne. NDIM1 .or. & + natts_in .ne. 1 .or. dimids_in(1) .ne. dimids(1)) stop 3 + if (quantize_mode_in .ne. nf90_quantize_bitgroom .or. nsd_in .ne. 3) stop 3 + + ! Check variable 2. + call check(nf90_inquire_variable(ncid, varid2_in, name_in, xtype_in, ndims_in, dimids_in, & + natts_in, contiguous = contiguous_in, endianness = endianness_in, fletcher32 = fletcher32_in, & + deflate_level = deflate_level_in, shuffle = shuffle_in, & + quantize_mode = quantize_mode_in, nsd = nsd_in)) + if (name_in .ne. VAR2_NAME .or. xtype_in .ne. NF90_DOUBLE .or. ndims_in .ne. NDIM1 .or. & + natts_in .ne. 1 .or. dimids_in(1) .ne. dimids(1)) stop 6 + if (deflate_level_in .ne. 0 .or. .not. contiguous_in .or. fletcher32_in .or. shuffle_in) stop 7 + if (quantize_mode_in .ne. nf90_quantize_bitgroom .or. nsd_in .ne. 3) stop 3 + + ! Check the data. + call check(nf90_get_var(ncid, varid1_in, real_data_in)) + call check(nf90_get_var(ncid, varid2_in, double_data_in)) + + ! Check the data. + do x = 1, DIM_LEN_5 + diff = abs(real_data_in(x) - real_data_expected(x)) + if (diff .gt. EPSILON) stop 23 + diff = abs(double_data_in(x) - double_data_expected(x)) + ! print *, double_data_in(x), double_data_expected(x) + ! print *, 'x = ', x, ' diff = ', diff + if (diff .gt. EPSILON) stop 24 + end do + + ! Close the file. + call check(nf90_close(ncid)) + + print *,'*** SUCCESS!' + +contains +! This subroutine handles errors by printing an error message and +! exiting with a non-zero status. + subroutine check(errcode) + use netcdf + implicit none + integer, intent(in) :: errcode + + if(errcode /= nf90_noerr) then + print *, 'Error: ', trim(nf90_strerror(errcode)) + stop 2 + endif + end subroutine check +end program f90tst_vars5 + diff --git a/nf03_test4/run_f90_par_test.sh b/nf03_test4/run_f90_par_test.sh index b7033b9c..d8e91f03 100755 --- a/nf03_test4/run_f90_par_test.sh +++ b/nf03_test4/run_f90_par_test.sh @@ -6,12 +6,12 @@ set -e echo "Testing netCDF parallel I/O through the F90 API." -mpirun -n 4 ./f90tst_parallel -mpirun -n 4 ./f90tst_parallel2 -mpirun -n 4 ./f90tst_parallel3 -mpirun -n 8 ./f90tst_nc4_par -mpirun -n 4 ./f90tst_parallel_fill -mpirun -n 4 ./f90tst_parallel_compressed +mpiexec -n 4 ./f90tst_parallel +mpiexec -n 4 ./f90tst_parallel2 +mpiexec -n 4 ./f90tst_parallel3 +mpiexec -n 8 ./f90tst_nc4_par +mpiexec -n 4 ./f90tst_parallel_fill +mpiexec -n 4 ./f90tst_parallel_compressed echo "SUCCESS!!!" exit 0 diff --git a/nf_test4/CMakeLists.txt b/nf_test4/CMakeLists.txt index 9a404609..260c6190 100644 --- a/nf_test4/CMakeLists.txt +++ b/nf_test4/CMakeLists.txt @@ -8,7 +8,7 @@ SET(CMAKE_INCLUDE_CURRENT_DIR ON) if (USE_NETCDF4) # Add these netCDF-4 test programs. SET(nc4_check_PROGRAMS ftst_groups ftst_vars ftst_vars2 ftst_vars3 - ftst_vars4 ftst_vars5 ftst_vars6 ftst_types ftst_types2 + ftst_vars4 ftst_vars5 ftst_vars6 ftst_vars7 ftst_types ftst_types2 ftst_types3 ftst_path ftst_rengrps f03tst_open_mem ftst_var_compact) SET(check_PROGRAMS ${check_PROGRAMS} ${nc4_check_PROGRAMS}) SET(TESTS ${TESTS} ${nc4_check_PROGRAMS}) @@ -20,6 +20,7 @@ if (USE_NETCDF4) SET(ftst_vars4_SOURCES ftst_vars4.F) SET(ftst_vars5_SOURCES ftst_vars5.F) SET(ftst_vars6_SOURCES ftst_vars6.F) + SET(ftst_vars7_SOURCES ftst_vars7.F) SET(ftst_types_SOURCES ftst_types.F) SET(ftst_types2_SOURCES ftst_types2.F) SET(ftst_types3_SOURCES ftst_types3.F) diff --git a/nf_test4/Makefile.am b/nf_test4/Makefile.am index b6d18624..82aad914 100644 --- a/nf_test4/Makefile.am +++ b/nf_test4/Makefile.am @@ -13,8 +13,8 @@ LDADD = ${top_builddir}/fortran/libnetcdff.la # These programs test the F77 netCDF-4 API using include netcdf.inc. NF77_TESTS = ftst_groups ftst_vars ftst_vars2 ftst_vars3 ftst_vars4 \ -ftst_vars5 ftst_vars6 ftst_types ftst_types2 ftst_types3 ftst_path \ -ftst_rengrps f03tst_open_mem ftst_var_compact +ftst_vars5 ftst_vars6 ftst_vars7 ftst_types ftst_types2 ftst_types3 \ +ftst_path ftst_rengrps f03tst_open_mem ftst_var_compact # Compile and run the F77 API tests. check_PROGRAMS = $(NF77_TESTS) @@ -28,6 +28,7 @@ ftst_vars3_SOURCES = ftst_vars3.F ftst_vars4_SOURCES = ftst_vars4.F ftst_vars5_SOURCES = ftst_vars5.F ftst_vars6_SOURCES = ftst_vars6.F +ftst_vars7_SOURCES = ftst_vars7.F ftst_types_SOURCES = ftst_types.F ftst_types2_SOURCES = ftst_types2.F ftst_types3_SOURCES = ftst_types3.F @@ -73,12 +74,12 @@ if USE_SED # These test fortran codes will be created using sed. F03_TEST_CODES = f03tst_groups.F f03tst_vars.F f03tst_vars2.F \ f03tst_vars3.F f03tst_vars4.F f03tst_vars5.F f03tst_vars6.F \ -f03tst_types.F f03tst_types2.F f03tst_types3.F +f03tst_vars7.F f03tst_types.F f03tst_types2.F f03tst_types3.F # The fortran codes will compile into these tests. F03_TESTS = f03tst_groups f03tst_vars f03tst_vars2 f03tst_vars3 \ -f03tst_vars4 f03tst_vars5 f03tst_vars6 f03tst_types f03tst_types2 \ -f03tst_types3 +f03tst_vars4 f03tst_vars5 f03tst_vars6 f03tst_vars7 f03tst_types \ +f03tst_types2 f03tst_types3 # This is a netCDF-4 V2 F77 test program. if BUILD_V2 @@ -118,6 +119,7 @@ f03tst_vars3_SOURCES = f03tst_vars3.F f03tst_vars4_SOURCES = f03tst_vars4.F f03tst_vars5_SOURCES = f03tst_vars5.F f03tst_vars6_SOURCES = f03tst_vars6.F +f03tst_vars7_SOURCES = f03tst_vars7.F f03tst_types_SOURCES = f03tst_types.F f03tst_types2_SOURCES = f03tst_types2.F f03tst_types3_SOURCES = f03tst_types3.F @@ -158,6 +160,11 @@ f03tst_vars6.F: ftst_vars6.F $(SED) "s|include 'netcdf.inc'|implicit none|" $@.tmp > $@.tmp2 $(SED) "s|ftst_vars6.nc|f03tst_vars6.nc|" $@.tmp2 > $@ +f03tst_vars7.F: ftst_vars7.F + $(SED) "s|implicit none|USE netcdf4_f03|" $< > $@.tmp + $(SED) "s|include 'netcdf.inc'|implicit none|" $@.tmp > $@.tmp2 + $(SED) "s|ftst_vars7.nc|f03tst_vars7.nc|" $@.tmp2 > $@ + f03tst_types.F: ftst_types.F $(SED) "s|implicit none|USE netcdf4_f03|" $< > $@.tmp $(SED) "s|include 'netcdf.inc'|implicit none|" $@.tmp > $@.tmp2 diff --git a/nf_test4/ftst_vars7.F b/nf_test4/ftst_vars7.F new file mode 100644 index 00000000..23c6473f --- /dev/null +++ b/nf_test4/ftst_vars7.F @@ -0,0 +1,213 @@ +C This is part of the netCDF package. +C Copyright 2008 University Corporation for Atmospheric Research/Unidata. +C See COPYRIGHT file for conditions of use. + +C This program tests netCDF-4 variable functions from fortran, +C checking the quantize feature. + +C Ed Hartnett, 9/3/21 + + program ftst_vars7 + implicit none + include 'netcdf.inc' + +C This is the name of the data file we will create. + character*(*) FILE_NAME + parameter (FILE_NAME='ftst_vars7.nc') + integer NDIM1 + parameter (NDIM1 = 1) + integer DIM_LEN_5 + parameter (DIM_LEN_5 = 5) + integer NVARS + parameter (NVARS = 2) + integer check_file + integer NSD_3 + parameter (NSD_3 = 3) + + integer ncid, varid(NVARS), dimids(NDIM1) + character*(10) var_name(NVARS) + integer var_type(NVARS) + character*(4) dim_name + parameter (dim_name = 'dim1') + integer start(NDIM1), count(NDIM1) + real real_data(DIM_LEN_5) + real*8 double_data(DIM_LEN_5) + +C Loop index and error handling. + integer x, retval + + print *, '' + print *,'*** Testing quantize feature.' + +C Set up var names. + var_name(1) = 'var__float' + var_type(1) = NF_FLOAT + var_name(2) = 'var_double' + var_type(2) = NF_DOUBLE + +C Set up data. +C float real_data[DIM_LEN_5] = {1.11111111, 1.0, 9.99999999, 12345.67, .1234567}; +C double double_data[DIM_LEN_5] = {1.1111111, 1.0, 9.999999999, 1234567890.12345, 123456789012345.0}; + real_data(1) = 1.11111111 + real_data(2) = 1.0 + real_data(3) = 9.99999999 + real_data(4) = 12345.67 + real_data(5) = .1234567 + double_data(1) = 1.1111111 + double_data(2) = 1.0 + double_data(3) = 9.999999999 + double_data(4) = 1234567890.12345 + double_data(5) = 1234567890 + +C Create the netCDF file. + retval = nf_create(FILE_NAME, NF_NETCDF4, ncid) + if (retval .ne. nf_noerr) stop 1 + +C Create a dimension. + retval = nf_def_dim(ncid, dim_name, DIM_LEN_5, dimids(1)) + if (retval .ne. nf_noerr) stop 2 + +C Create some variables. + do x = 1, NVARS + retval = nf_def_var(ncid, var_name(x), var_type(x), NDIM1, + $ dimids, varid(x)) + if (retval .ne. nf_noerr) stop 3 + +C Turn on quantize. + retval = nf_def_var_quantize(ncid, varid(x), + $ NF_QUANTIZE_BITGROOM, NSD_3) + if (retval .ne. nf_noerr) stop 3 + end do + +C Write some data (which automatically calls nf_enddef). + start(1) = 1 + count(1) = DIM_LEN_5 + retval = nf_put_vara_real(ncid, varid(1), start, count, + $ real_data) + if (retval .ne. 0) stop 200 + retval = nf_put_vara_double(ncid, varid(2), start, count, + $ double_data) + if (retval .ne. 0) stop 200 + +C Check it out. + retval = check_file(ncid, var_name, var_type, dim_name) + if (retval .ne. 0) stop 2 + +C Close the file. + retval = nf_close(ncid) + if (retval .ne. nf_noerr) stop 4 + +C Reopen the file. + retval = nf_open(FILE_NAME, NF_NOWRITE, ncid) + if (retval .ne. nf_noerr) stop 5 + +C Check it out. + retval = check_file(ncid, var_name, var_type, dim_name) + if (retval .ne. 0) stop 6 + +C Close the file. + retval = nf_close(ncid) + if (retval .ne. nf_noerr) stop 7 + + print *,'*** SUCCESS!' + end + +C This function check the file to make sure everything is OK. + integer function check_file(ncid, var_name, var_type, dim_name) + implicit none + include 'netcdf.inc' + +C I need these in both here and the main program. + integer NDIM1 + parameter (NDIM1 = 1) + integer DIM_LEN_5 + parameter (DIM_LEN_5 = 5) + integer NVARS + parameter (NVARS = 2) + integer NSD_3 + parameter (NSD_3 = 3) + real EPSILON + parameter (EPSILON = .01) + +C Parameters + integer ncid + character*(10) var_name(NVARS) + integer var_type(NVARS) + character*(4) dim_name + +C Values that are read in, to check the file. + integer ndims_in, nvars_in, ngatts_in, unlimdimid_in + integer xtype_in, dimids_in(NDIM1), natts_in + integer varid_in(NVARS), dimid_in, quantize_mode_in, nsd_in + character*(10) var_name_in + real real_data_in(DIM_LEN_5) + real*8 double_data_in(DIM_LEN_5) + real real_data_expected(DIM_LEN_5) + real*8 double_data_expected(DIM_LEN_5) + real diff + real*8 diff8 + + integer x, retval + +C What we expect to get back. + real_data_expected(1) = 1.11084 + real_data_expected(2) = 1.000488 + real_data_expected(3) = 10 + real_data_expected(4) = 12348 + real_data_expected(5) = 0.1234436 + double_data_expected(1) = 1.11083984375 + double_data_expected(2) = 1.00048828125 + double_data_expected(3) = 10 + double_data_expected(4) = 1234698240 + double_data_expected(5) = 1234173952 + +C Check it out. + retval = nf_inq(ncid, ndims_in, nvars_in, ngatts_in, + $ unlimdimid_in) + if (retval .ne. nf_noerr) stop 11 + if (ndims_in .ne. 1 .or. nvars_in .ne. NVARS .or. ngatts_in .ne. 0 + $ .or. unlimdimid_in .ne. -1) stop 12 + +C Get the varids and the dimid. + do x = 1, NVARS + retval = nf_inq_varid(ncid, var_name(x), varid_in(x)) + if (retval .ne. nf_noerr) stop 13 + if (varid_in(x) .ne. x) stop 14 + end do + retval = nf_inq_dimid(ncid, dim_name, dimid_in) + if (retval .ne. nf_noerr) stop 15 + if (dimid_in .ne. 1) stop 16 + +C These things are the same for all variables, except natts_in is +C different for quantize vars after the file is written, there is an +C extra attribute. + do x = 1, NVARS + retval = nf_inq_var(ncid, varid_in(x), var_name_in, xtype_in, + $ ndims_in, dimids_in, natts_in) + if (retval .ne. nf_noerr) stop 17 + if (ndims_in .ne. 1 .or. xtype_in .ne. var_type(x) .or. + $ dimids_in(1).ne. dimid_in) stop 18 + retval = nf_inq_var_quantize(ncid, varid_in(x), + $ quantize_mode_in, nsd_in) + if (quantize_mode_in .ne. nf_quantize_bitgroom) stop 20 + if (nsd_in .ne. NSD_3) stop 20 + end do + +C Get the data. + retval = nf_get_var_real(ncid, varid_in(1), real_data_in) + if (retval .ne. nf_noerr) stop 1 + retval = nf_get_var_double(ncid, varid_in(2), double_data_in) + if (retval .ne. nf_noerr) stop 1 + +C Check the data. + do x = 1, DIM_LEN_5 + diff = abs(real_data_in(x) - real_data_expected(x)) + if (diff .gt. EPSILON) stop 23 + diff = abs(double_data_in(x) - double_data_expected(x)) +c$$$ print *, double_data_in(x), double_data_expected(x) +c$$$ print *, 'x = ', x, ' diff = ', diff + if (diff .gt. EPSILON) stop 24 + end do + + check_file = 0 + end