diff --git a/.github/workflows/a3.yml b/.github/workflows/a3.yml new file mode 100644 index 00000000000..53121bb8acb --- /dev/null +++ b/.github/workflows/a3.yml @@ -0,0 +1,147 @@ +name: netcdf-4.7.4_pnetcdf-12.1_ncint_openmpi_4.0.4 + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CPPFLAGS: "-I/home/runner/openmpi/include -I/home/runner/hdf5/include -I/home/runner/netcdf-c/include -I/home/runner/netcdf-fortran/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/openmpi/lib -L/home/runner/hdf5/lib -L/home/runner/netcdf-c/lib -L/home/runner/netcdf-fortran/lib -L/home/runner/pnetcdf/lib" + + steps: + - uses: actions/checkout@v2 + - name: Installs + run: | + sudo apt-get install doxygen graphviz wget gfortran libjpeg-dev libz-dev + - name: cache-openmpi + id: cache-openmpi + uses: actions/cache@v2 + with: + path: ~/openmpi + key: openmpi-${{ runner.os }}-4.0.4 + + - name: build-openmpi + if: steps.cache-openmpi.outputs.cache-hit != 'true' + run: | + wget https://download.open-mpi.org/release/open-mpi/v4.0/openmpi-4.0.4.tar.gz &> /dev/null + tar -xzf openmpi-4.0.4.tar.gz + pushd openmpi-4.0.4 + ./configure --prefix=/home/runner/openmpi + make + sudo make install + popd + - name: cache-hdf5 + id: cache-hdf5 + uses: actions/cache@v2 + with: + path: ~/hdf5 + key: hdf5-${{ runner.os }}-1.10.6-openmpi-4.0.4 + + - name: build-hdf5 + if: steps.cache-hdf5.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.6/src/hdf5-1.10.6.tar.gz &> /dev/null + tar -xzf hdf5-1.10.6.tar.gz + pushd hdf5-1.10.6 + ./configure --prefix=/home/runner/hdf5 --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + make + sudo make install + popd + - name: cache-netcdf-c + id: cache-netcdf-c + uses: actions/cache@v2 + with: + path: ~/netcdf-c + key: netcdf-c-${{ runner.os }}-4.7.4-openmpi-4.0.4 + + - name: build-netcdf-c + if: steps.cache-netcdf-c.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://www.unidata.ucar.edu/downloads/netcdf/ftp/netcdf-c-4.7.4.tar.gz &> /dev/null + tar -xzf netcdf-c-4.7.4.tar.gz + pushd netcdf-c-4.7.4 + ./configure --prefix=/home/runner/netcdf-c --disable-dap --disable-utilities + make -j + sudo make install + popd + - name: cache-netcdf-fortran + id: cache-netcdf-fortran + uses: actions/cache@v2 + with: + path: ~/netcdf-fortran + key: netcdf-fortran-${{ runner.os }}-4.5.3-openmpi-4.0.4 + + - name: build-netcdf-fortran + if: steps.cache-netcdf-fortran.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://github.com/Unidata/netcdf-fortran/archive/v4.5.3.tar.gz &> /dev/null + tar -xzf v4.5.3.tar.gz + pushd netcdf-fortran-4.5.3 + ./configure --prefix=/home/runner/netcdf-fortran + make -j + sudo make install + popd + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v2 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-1.12.1-openmpi-4.0.4 + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz &> /dev/null + tar -xzf pnetcdf-1.12.1.tar.gz + pushd pnetcdf-1.12.1 + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + - name: autotools build + run: | + set -x + echo 'export PATH=/home/runner/openmpi/bin:$PATH' > .bashrc + source .bashrc + export PATH="/home/runner/openmpi/bin:$PATH" + export CC=/home/runner/openmpi/bin/mpicc + autoreconf -i + ./configure --with-mpiexec='mpiexec --oversubscribe' + cat config.h + make check + - name: cmake build + run: | + set -x + echo 'export PATH=/home/runner/openmpi/bin:$PATH' > .bashrc + source .bashrc + export CC=mpicc + mkdir build + cd build + export LD_LIBRARY_PATH="/home/runner/netcdf-c/lib:/home/runner/pnetcdf/lib:/home/runner/hdf5/lib:/home/runner/openmpi/lib:$LD_LIBRARY_PATH" + cmake -Wno-dev -DWITH_MPIEXEC='/home/runner/openmpi/bin/mpiexec;--oversubscribe' -DNetCDF_C_LIBRARY=/home/runner/netcdf-c/lib/libnetcdf.so -DNetCDF_C_INCLUDE_DIR=/home/runner/netcdf-c/include -DPnetCDF_PATH='/home/runner/pnetcdf' -DPIO_ENABLE_FORTRAN=Off -DPIO_HDF5_LOGGING=On -DPIO_USE_MALLOC=On -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off .. || (cat CMakeFiles/CMakeOutput.log && cat CMakeFiles/CMakeError.log) + cat config.h + make VERBOSE=1 + make tests VERBOSE=1 + ctest -VV + + + diff --git a/.github/workflows/a4.yml b/.github/workflows/a4.yml new file mode 100644 index 00000000000..3c625b33de4 --- /dev/null +++ b/.github/workflows/a4.yml @@ -0,0 +1,147 @@ +name: netcdf-4.7.4_pnetcdf-12.1_ncint_mpich-3.3 + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CPPFLAGS: "-I/home/runner/mpich/include -I/home/runner/hdf5/include -I/home/runner/netcdf-c/include -I/home/runner/netcdf-fortran/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/mpich/lib -L/home/runner/hdf5/lib -L/home/runner/netcdf-c/lib -L/home/runner/netcdf-fortran/lib -L/home/runner/pnetcdf/lib" + + steps: + - uses: actions/checkout@v2 + - name: Installs + run: | + sudo apt-get install doxygen graphviz wget gfortran libjpeg-dev libz-dev + - name: cache-mpich + id: cache-mpich + uses: actions/cache@v2 + with: + path: ~/mpich + key: mpich-${{ runner.os }}-3.3.2 + + - name: build-mpich + if: steps.cache-mpich.outputs.cache-hit != 'true' + run: | + wget http://www.mpich.org/static/downloads/3.3.2/mpich-3.3.2.tar.gz &> /dev/null + tar -xzf mpich-3.3.2.tar.gz + pushd mpich-3.3.2 + ./configure --prefix=/home/runner/mpich + make + sudo make install + popd + - name: cache-hdf5 + id: cache-hdf5 + uses: actions/cache@v2 + with: + path: ~/hdf5 + key: hdf5-${{ runner.os }}-1.10.6-mpich-3.3.2 + + - name: build-hdf5 + if: steps.cache-hdf5.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.6/src/hdf5-1.10.6.tar.gz &> /dev/null + tar -xzf hdf5-1.10.6.tar.gz + pushd hdf5-1.10.6 + ./configure --prefix=/home/runner/hdf5 --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + make + sudo make install + popd + - name: cache-netcdf-c + id: cache-netcdf-c + uses: actions/cache@v2 + with: + path: ~/netcdf-c + key: netcdf-c-${{ runner.os }}-4.7.4-mpich-3.3.2 + + - name: build-netcdf-c + if: steps.cache-netcdf-c.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://www.unidata.ucar.edu/downloads/netcdf/ftp/netcdf-c-4.7.4.tar.gz &> /dev/null + tar -xzf netcdf-c-4.7.4.tar.gz + pushd netcdf-c-4.7.4 + ./configure --prefix=/home/runner/netcdf-c --disable-dap --disable-utilities + make -j + sudo make install + popd + - name: cache-netcdf-fortran + id: cache-netcdf-fortran + uses: actions/cache@v2 + with: + path: ~/netcdf-fortran + key: netcdf-fortran-${{ runner.os }}-4.5.3-mpich-3.3.2 + + - name: build-netcdf-fortran + if: steps.cache-netcdf-fortran.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://github.com/Unidata/netcdf-fortran/archive/v4.5.3.tar.gz &> /dev/null + tar -xzf v4.5.3.tar.gz + pushd netcdf-fortran-4.5.3 + ./configure --prefix=/home/runner/netcdf-fortran + make -j + sudo make install + popd + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v2 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-1.12.1-mpich-3.3.2 + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + export PATH="/home/runner/mpich/bin:$PATH" + export CC=/home/runner/mpich/bin/mpicc + wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz &> /dev/null + tar -xzf pnetcdf-1.12.1.tar.gz + pushd pnetcdf-1.12.1 + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + - name: cmake build + run: | + set -x + gcc --version + echo 'export PATH=/home/runner/mpich/bin:$PATH' > .bashrc + source .bashrc + export CC=/home/runner/mpich/bin/mpicc + export FC=/home/runner/mpich/bin/mpifort + export LD_LIBRARY_PATH="/home/runner/netcdf-c/lib:/home/runner/mpich/lib:/home/runner/hdf5/lib:/home/runner/netcdf-fortran/lib:/home/runner/pnetcdf/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 -DPnetCDF_PATH='/home/runner/pnetcdf' -DPIO_ENABLE_FORTRAN=Off -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off .. || (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 + echo 'export PATH=/home/runner/mpich/bin:$PATH' > .bashrc + source .bashrc + export CC=/home/runner/mpich/bin/mpicc + export FC=/home/runner/mpich/bin/mpifort + autoreconf -i + ./configure --enable-fortran + make -j check + + diff --git a/.github/workflows/autotools.yml b/.github/workflows/autotools.yml index 20802f1e253..052487e8b8d 100644 --- a/.github/workflows/autotools.yml +++ b/.github/workflows/autotools.yml @@ -1,4 +1,4 @@ -name: autotools +name: autotools_ubuntu_latest on: push: @@ -14,24 +14,35 @@ jobs: env: CC: mpicc FC: mpifort - CPPFLAGS: "-I/usr/include -I/usr/local/include" -# CFLAGS: "-std=c99 -fsanitize=address -fno-omit-frame-pointer -Werror" -# FFLAGS: "-fsanitize=address -fno-omit-frame-pointer" -# FCFLAGS: "-fsanitize=address -fno-omit-frame-pointer -Werror" + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" steps: - uses: actions/checkout@v2 - name: Installs run: | + set -x + sudo gem install apt-spy2 + sudo apt-spy2 check + sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v2 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-1.11.0 - - name: pnetcdf build + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' run: | - wget https://parallel-netcdf.github.io/Release/pnetcdf-1.11.0.tar.gz + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-1.11.0.tar.gz &> /dev/null tar -xzvf pnetcdf-1.11.0.tar.gz - ls -l pushd pnetcdf-1.11.0 - ./configure --prefix=/usr --enable-shared + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx make sudo make install popd @@ -39,6 +50,6 @@ jobs: - name: autoreconf run: autoreconf -i - name: configure - run: ./configure - - name: make distcheck - run: make distcheck + run: ./configure --enable-fortran --enable-docs + - name: make check + run: make -j check diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index fa04163683c..bf1671b94f9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -14,31 +14,47 @@ jobs: env: CC: mpicc FC: mpifort - CPPFLAGS: "-I/usr/include -I/usr/local/include" + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" + LD_LIBRARY_PATH: "/home/runner/pnetcdf/lib" steps: - uses: actions/checkout@v2 - name: Installs run: | - sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev + set -x + sudo gem install apt-spy2 + sudo apt-spy2 check + sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update + sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev - - name: pnetcdf build + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v2 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-1.12.1 + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' run: | - wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz &> /dev/null tar -xzvf pnetcdf-1.12.1.tar.gz - ls -l pushd pnetcdf-1.12.1 - ./configure --prefix=/usr --enable-shared --disable-cxx + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx make sudo make install popd - name: cmake build run: | - find /usr -name libnetcdf.so + set -x mkdir build cd build - cmake -Wno-dev -DNetCDF_C_LIBRARY=/usr/lib/x86_64-linux-gnu/libnetcdf.so -DNetCDF_C_INCLUDE_DIR=/usr/include -DCMAKE_PREFIX_PATH=/usr -DPIO_HDF5_LOGGING=On -DPIO_USE_MALLOC=On -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off .. + cmake -Wno-dev -DNetCDF_C_LIBRARY=/usr/lib/x86_64-linux-gnu/libnetcdf.so -DNetCDF_C_INCLUDE_DIR=/usr/include -DPnetCDF_PATH='/home/runner/pnetcdf' -DPIO_ENABLE_FORTRAN=Off -DPIO_HDF5_LOGGING=On -DPIO_USE_MALLOC=On -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off .. make VERBOSE=1 make tests VERBOSE=1 ctest -VV diff --git a/.github/workflows/cmake_ncint.yml b/.github/workflows/cmake_ncint.yml new file mode 100644 index 00000000000..53a67a59c26 --- /dev/null +++ b/.github/workflows/cmake_ncint.yml @@ -0,0 +1,60 @@ + name: cmake_ncint + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + env: + CC: mpicc + FC: mpifort + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" + LD_LIBRARY_PATH: "/home/runner/pnetcdf/lib" + + steps: + - uses: actions/checkout@v2 + - name: Installs + run: | + set -x + sudo gem install apt-spy2 + sudo apt-spy2 check + sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update + sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev + + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v2 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-1.12.1 + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' + run: | + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz &> /dev/null + tar -xzvf pnetcdf-1.12.1.tar.gz + pushd pnetcdf-1.12.1 + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx + make + sudo make install + popd + + - name: cmake build + run: | + set -x + mkdir build + cd build + cmake -Wno-dev -DPIO_ENABLE_NETCDF_INTEGRATION=On -DNetCDF_C_LIBRARY=/usr/lib/x86_64-linux-gnu/libnetcdf.so -DNetCDF_C_INCLUDE_DIR=/usr/include -DPnetCDF_PATH='/home/runner/pnetcdf' -DPIO_HDF5_LOGGING=On -DPIO_USE_MALLOC=On -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off .. + make VERBOSE=1 + make tests VERBOSE=1 + ctest -VV diff --git a/.github/workflows/strict_autotools.yml b/.github/workflows/strict_autotools.yml index 0f8f51de1a4..b47c4b1ba5f 100644 --- a/.github/workflows/strict_autotools.yml +++ b/.github/workflows/strict_autotools.yml @@ -1,4 +1,4 @@ -name: strict_autotools +name: strict_autotools_ubuntu_latest on: push: @@ -14,34 +14,49 @@ jobs: env: CC: mpicc FC: mpifort - CPPFLAGS: "-I/usr/include -I/usr/local/include" + CPPFLAGS: "-I/usr/include -I/usr/local/include -I/home/runner/pnetcdf/include" + LDFLAGS: "-L/home/runner/pnetcdf/lib" steps: - uses: actions/checkout@v2 - name: Installs run: | + set -x + sudo gem install apt-spy2 + sudo apt-spy2 check + sudo apt-spy2 fix --commit + # after selecting a specific mirror, we need to run 'apt-get update' + sudo apt-get update sudo apt-get install netcdf-bin libnetcdf-dev doxygen graphviz wget gfortran libjpeg-dev libz-dev openmpi-bin libopenmpi-dev - - name: pnetcdf build + - name: cache-pnetcdf + id: cache-pnetcdf + uses: actions/cache@v2 + with: + path: ~/pnetcdf + key: pnetcdf-${{ runner.os }}-1.12.1 + + - name: build-pnetcdf + if: steps.cache-pnetcdf.outputs.cache-hit != 'true' run: | - wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz + set -x + wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz &> /dev/null tar -xzvf pnetcdf-1.12.1.tar.gz - ls -l pushd pnetcdf-1.12.1 - ./configure --prefix=/usr --enable-shared --disable-cxx + ./configure --prefix=/home/runner/pnetcdf --enable-shared --disable-cxx make sudo make install popd - name: autoreconf run: autoreconf -i - - name: configure - run: | - export CFLAGS="-std=c99 -fsanitize=address -fno-omit-frame-pointer -Werror" - export FFLAGS="-fsanitize=address -fno-omit-frame-pointer -Werror" - export FCFLAGS="-fsanitize=address -fno-omit-frame-pointer -Werror" - ./configure - - name: make -j distcheck + - name: build run: | + set -x + export CFLAGS="-std=c99 -Wall" + export FFLAGS="-Wall" + export FCFLAGS="-Wall" export DISTCHECK_CONFIGURE_FLAGS="--enable-fortran" + ./configure make -j distcheck + diff --git a/.travis.yml b/.travis.yml index 2504a0268d0..931bf1b492b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,11 +23,10 @@ before_script: - export CC=mpicc - export FC=mpif90 - export CPPFLAGS='-I/usr/include' - - wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz - - tar -xzvf pnetcdf-1.12.1.tar.gz - - ls -l + - wget https://parallel-netcdf.github.io/Release/pnetcdf-1.12.1.tar.gz &> /dev/null + - tar -xzf pnetcdf-1.12.1.tar.gz - pushd pnetcdf-1.12.1 - - ./configure --prefix=/usr --enable-shared + - ./configure --prefix=/usr --enable-shared --disable-cxx - make - sudo make install - popd @@ -40,10 +39,11 @@ env: - LDFLAGS='-L/usr/lib' script: + - nc-config --all - autoreconf -i - - export CFLAGS='-std=c99 -fsanitize=address -fno-omit-frame-pointer -Werror' - - export FFLAGS='-fsanitize=address -fno-omit-frame-pointer' - - export FCFLAGS='-fsanitize=address -fno-omit-frame-pointer -Werror' + - export CFLAGS='-g -std=c99 -fsanitize=address -fno-omit-frame-pointer -Werror' + - export FFLAGS='-g -fsanitize=address -fno-omit-frame-pointer' + - export FCFLAGS='-g -fsanitize=address -fno-omit-frame-pointer -Werror' - export DISTCHECK_CONFIGURE_FLAGS='--enable-fortran' - ./configure --enable-fortran --enable-developer-docs - make -j distcheck @@ -54,4 +54,4 @@ script: - cmake -DPIO_HDF5_LOGGING=On -DPIO_USE_MALLOC=On -DPIO_ENABLE_LOGGING=On -DPIO_ENABLE_TIMING=Off .. - make VERBOSE=1 - make tests VERBOSE=1 - - ctest -VV \ No newline at end of file + - ctest -VV diff --git a/CMakeLists.txt b/CMakeLists.txt index 92a016c4c60..cd6af59be0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,9 @@ +# This is part of the PIO library. + +# This is the CMake build file for the main directory. + +# Jim Edwards + cmake_minimum_required (VERSION 2.8.12) project (PIO C Fortran) #cmake_policy(VERSION 3.5.2) @@ -5,7 +11,7 @@ project (PIO C Fortran) # The project version number. set(VERSION_MAJOR 2 CACHE STRING "Project major version number.") set(VERSION_MINOR 5 CACHE STRING "Project minor version number.") -set(VERSION_PATCH 1 CACHE STRING "Project patch version number.") +set(VERSION_PATCH 2 CACHE STRING "Project patch version number.") mark_as_advanced(VERSION_MAJOR VERSION_MINOR VERSION_PATCH) # Create version info in autotools parlance for pio_meta.h. @@ -16,20 +22,23 @@ set(PIO_VERSION_PATCH ${VERSION_PATCH}) # This is needed for the libpio.settings file. SET(PACKAGE_VERSION ${PIO_VERSION_MAJOR}.${PIO_VERSION_MINOR}.${PIO_VERSION_PATCH}) +# This provides cmake_print_variables() function for debugging. +include(CMakePrintHelpers) + # Determine the configure date. IF(DEFINED ENV{SOURCE_DATE_EPOCH}) - EXECUTE_PROCESS( - COMMAND "date" "-u" "-d" "@$ENV{SOURCE_DATE_EPOCH}" - OUTPUT_VARIABLE CONFIG_DATE - ) + EXECUTE_PROCESS( + COMMAND "date" "-u" "-d" "@$ENV{SOURCE_DATE_EPOCH}" + OUTPUT_VARIABLE CONFIG_DATE + ) ELSE() - EXECUTE_PROCESS( - COMMAND date - OUTPUT_VARIABLE CONFIG_DATE - ) + EXECUTE_PROCESS( + COMMAND date + OUTPUT_VARIABLE CONFIG_DATE + ) ENDIF() IF(CONFIG_DATE) - string(STRIP ${CONFIG_DATE} CONFIG_DATE) + string(STRIP ${CONFIG_DATE} CONFIG_DATE) ENDIF() # A function used to create autotools-style 'yes/no' definitions. @@ -77,11 +86,11 @@ option (PIO_ENABLE_LOGGING "Enable debug logging (large output possible)" OFF) option (PIO_ENABLE_DOC "Enable building PIO documentation" ON) option (PIO_ENABLE_COVERAGE "Enable code coverage" OFF) option (PIO_ENABLE_EXAMPLES "Enable PIO examples" ON) +option (PIO_ENABLE_NETCDF_INTEGRATION "Enable netCDF integration" OFF) option (PIO_INTERNAL_DOC "Enable PIO developer documentation" OFF) option (PIO_TEST_BIG_ENDIAN "Enable test to see if machine is big endian" ON) option (PIO_USE_MPIIO "Enable support for MPI-IO auto detect" ON) option (PIO_USE_MPISERIAL "Enable mpi-serial support (instead of MPI)" OFF) -option (PIO_USE_MALLOC "Use native malloc (instead of bget package)" ON) option (PIO_USE_PNETCDF_VARD "Use pnetcdf put_vard " OFF) option (WITH_PNETCDF "Require the use of PnetCDF" ON) @@ -93,17 +102,22 @@ else() endif() # Set a variable that appears in the config.h.in file. -if(PIO_USE_MALLOC) - set(USE_MALLOC 1) -else() - set(USE_MALLOC 0) -endif() +set(USE_MALLOC 1) # Set a variable that appears in the config.h.in file. if(PIO_ENABLE_LOGGING) set(ENABLE_LOGGING 1) + set(HAS_LOGGING "yes") else() set(ENABLE_LOGGING 0) + set(HAS_LOGGING "no") +endif() + +# Set a variable that appears in the config.h.in file. +if(PIO_ENABLE_NETCDF_INTEGRATION) + set(NETCDF_INTEGRATION 1) +else() + set(NETCDF_INTEGRATION 0) endif() if(PIO_USE_MPISERIAL) @@ -205,13 +219,6 @@ endif () set (CMAKE_Fortran_COMPILER_DIRECTIVE "CPR${CMAKE_Fortran_COMPILER_NAME}" CACHE STRING "Fortran compiler name preprocessor directive") -# configure a header file to pass some of the CMake settings -# to the source code -configure_file ( - "${PROJECT_SOURCE_DIR}/cmake_config.h.in" - "${PROJECT_BINARY_DIR}/config.h" - ) - #============================================================================== # SET CODE COVERAGE COMPILER FLAGS #============================================================================== @@ -230,6 +237,23 @@ if (PIO_ENABLE_COVERAGE) endif () endif () +# Include this so we can check values in netcdf_meta.h. +INCLUDE(CheckCSourceCompiles) +INCLUDE(FindNetCDF) +message("Fortran Library build is ${PIO_ENABLE_FORTRAN}") +if (PIO_ENABLE_FORTRAN) + find_package (NetCDF REQUIRED COMPONENTS C Fortran) + find_package (PnetCDF COMPONENTS C Fortran) +else() + find_package (NetCDF REQUIRED COMPONENTS C) + find_package (PnetCDF COMPONENTS C) +endif() + +# Did we find pnetCDF? If so, set _PNETCDF in config.h. +if (PnetCDF_C_FOUND) + set(_PNETCDF 1) +endif () + #============================================================================== # INCLUDE SOURCE DIRECTORIES #============================================================================== @@ -264,11 +288,6 @@ if (PIO_ENABLE_DOC) add_subdirectory (doc) endif () -# Include this so we can check values in netcdf_meta.h. -INCLUDE(CheckCSourceCompiles) -INCLUDE(FindNetCDF) -find_package (NetCDF REQUIRED) -find_package (PnetCDF) SET(STATUS_PNETCDF PnetCDF_C_FOUND) @@ -295,6 +314,11 @@ CHECK_C_SOURCE_COMPILES(" #endif int main() {return 0;}" HAVE_NETCDF_PAR) +# Set this synonym for HAVE_NETCDF_PAR. It is defined in config.h. +if (HAVE_NETCDF_PAR) + set(_NETCDF4 1) +endif () + ### # Check to see if szip write capability is present in netcdf-c. ### @@ -315,6 +339,52 @@ CHECK_C_SOURCE_COMPILES(" choke me #endif int main() {return 0;}" HDF5_HAS_PAR_FILTERS) +if(HDF5_HAS_PAR_FILTERS) + set(HAVE_PAR_FILTERS 1) +else() + set(HAVE_PAR_FILTERS 0) +endif() + +### +# Check to see if this is netcdf-c-4.7.2, which won't work. +### +CHECK_C_SOURCE_COMPILES(" +#include +#if NC_VERSION_MAJOR == 4 && NC_VERSION_MINOR == 7 && NC_VERSION_PATCH == 2 +#else + choke me +#endif +int main() {return 0;}" HAVE_472) +if (HAVE_472) + message (FATAL_ERROR "PIO cannot build with netcdf-c-4.7.2, please upgrade your netCDF library") +endif () + +### +# Check to see if dispatch table version 2 is supported for netcdf integration. +### +CHECK_C_SOURCE_COMPILES(" +#include +#if NC_DISPATCH_VERSION != 2 + choke me +#endif +int main() {return 0;}" HAVE_DISPATCH2) + +if (NETCDF_INTEGRATION) + if (NOT HAVE_DISPATCH2) + message (FATAL_ERROR "Need newer version of netcdf-c for netcdf integration feature, please upgrade your netCDF library") + endif () + set(HAVE_NETCDF_INTEGRATION 1) +else () + set(HAVE_NETCDF_INTEGRATION 0) +endif () + +# Configure testing with MPIEXEC. +if (NOT WITH_MPIEXEC) + set(WITH_MPIEXEC mpiexec) +endif() +#set(MPIEXEC "${WITH_MPIEXEC}" CACHE INTERNAL "") +set(MPIEXEC "${WITH_MPIEXEC}") +set_property(GLOBAL PROPERTY WITH_MPIEXEC "${WITH_MPIEXEC}") ##### # Configure and print the libpio.settings file. @@ -363,6 +433,8 @@ is_enabled(HAVE_H5Z_SZIP HAS_SZLIB) is_enabled(HDF5_HAS_PAR_FILTERS HAS_PAR_FILTERS) is_enabled(HAVE_NETCDF4 HAS_NETCDF4) is_enabled(HAVE_NETCDF_PAR HAS_NETCDF4_PAR) +is_enabled(HAVE_NETCDF_INTEGRATION HAS_NETCDF_INTEGRATION) +is_enabled(PIO_ENABLE_FORTRAN HAS_PIO_FORTRAN) # Generate file from template. CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/libpio.settings.in" @@ -387,7 +459,11 @@ INSTALL(FILES "${PIO_BINARY_DIR}/libpio.settings" ##### configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/src/clib/pio_meta.h.in - ${CMAKE_CURRENT_SOURCE_DIR}/src/clib/pio_meta.h @ONLY) + ${CMAKE_CURRENT_BINARY_DIR}/src/clib/pio_meta.h @ONLY) -FILE(COPY ${CMAKE_CURRENT_SOURCE_DIR}/src/clib/pio_meta.h - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/src/clib/) +# configure a header file to pass some of the CMake settings +# to the source code +configure_file ( + "${PROJECT_SOURCE_DIR}/cmake_config.h.in" + "${PROJECT_BINARY_DIR}/config.h" + ) diff --git a/Makefile.am b/Makefile.am index faa7feb3f4e..8d6fc16db28 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,5 +14,5 @@ endif SUBDIRS = src tests examples ${DOC} scripts cmake # Add these files to the distribution. -EXTRA_DIST = CMakeLists.txt set_flags.am COPYRIGHT cmake_config.h.in \ +EXTRA_DIST = CMakeLists.txt COPYRIGHT cmake_config.h.in \ libpio.settings.in diff --git a/cmake/LibMPI.cmake b/cmake/LibMPI.cmake index f1116724831..2fa9f52af50 100644 --- a/cmake/LibMPI.cmake +++ b/cmake/LibMPI.cmake @@ -1,3 +1,8 @@ +# This is part of the PIO library. + +# THis file contains CMake code related to MPI. + +# Jim Edwards include (CMakeParseArguments) # Find Valgrind to perform memory leak check @@ -90,6 +95,11 @@ function (add_mpi_test TESTNAME) # Get the platform name platform_name (PLATFORM) + get_property(WITH_MPIEXEC GLOBAL PROPERTY WITH_MPIEXEC) + if (WITH_MPIEXEC) + set(MPIEXEC "${WITH_MPIEXEC}") + endif () + # Default ("unknown" platform) execution if (PLATFORM STREQUAL "unknown") diff --git a/cmake_config.h.in b/cmake_config.h.in index cfd26d77601..7561db067df 100644 --- a/cmake_config.h.in +++ b/cmake_config.h.in @@ -5,8 +5,6 @@ */ #ifndef _PIO_CONFIG_ #define _PIO_CONFIG_ -/* Set to avoid warning in intel19 compiler wrt strnlen */ -#define _GNU_SOURCE /** The major part of the version number. */ #define PIO_VERSION_MAJOR @VERSION_MAJOR@ @@ -32,4 +30,23 @@ #define USE_VARD @USE_VARD@ +/* Does netCDF support netCDF/HDF5 files? */ +#cmakedefine HAVE_NETCDF4 + +/* Does netCDF support parallel I/O for netCDF/HDF5 files? */ +#cmakedefine HAVE_NETCDF_PAR + +/* Does PIO support netCDF/HDF5 files? (Will be same as + * HAVE_NETCDF_PAR). */ +#cmakedefine _NETCDF4 + +/* Does netCDF and HDF5 support parallel I/O filters? */ +#cmakedefine HAVE_PAR_FILTERS + +/* Was PIO built with netCDF integration? */ +#cmakedefine NETCDF_INTEGRATION + +/* Does PIO support using pnetcdf for I/O? */ +#cmakedefine _PNETCDF + #endif /* _PIO_CONFIG_ */ diff --git a/configure.ac b/configure.ac index 0ccc1ee2150..4c9eefa0937 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ ## Ed Hartnett 8/16/17 # Initialize autoconf and automake. -AC_INIT(pio, 2.5.1-development) +AC_INIT(pio, 2.5.2) AC_CONFIG_SRCDIR(src/clib/pio_darray.c) AM_INIT_AUTOMAKE([foreign serial-tests]) @@ -10,7 +10,7 @@ AM_INIT_AUTOMAKE([foreign serial-tests]) # AC_DEFINE_UNQUOTED for config.h. AC_SUBST([PIO_VERSION_MAJOR]) PIO_VERSION_MAJOR=2 AC_SUBST([PIO_VERSION_MINOR]) PIO_VERSION_MINOR=5 -AC_SUBST([PIO_VERSION_PATCH]) PIO_VERSION_PATCH=1 +AC_SUBST([PIO_VERSION_PATCH]) PIO_VERSION_PATCH=2 AC_DEFINE_UNQUOTED([PIO_VERSION_MAJOR], [$PIO_VERSION_MAJOR], [PIO major version]) AC_DEFINE_UNQUOTED([PIO_VERSION_MINOR], [$PIO_VERSION_MINOR], [PIO minor version]) AC_DEFINE_UNQUOTED([PIO_VERSION_PATCH], [$PIO_VERSION_PATCH], [PIO patch version]) @@ -18,7 +18,7 @@ AC_DEFINE_UNQUOTED([PIO_VERSION_PATCH], [$PIO_VERSION_PATCH], [PIO patch version # Once more for the documentation. AC_SUBST([VERSION_MAJOR], [2]) AC_SUBST([VERSION_MINOR], [5]) -AC_SUBST([VERSION_PATCH], [1]) +AC_SUBST([VERSION_PATCH], [2]) # The m4 directory holds macros for autoconf. AC_CONFIG_MACRO_DIR([m4]) @@ -117,6 +117,7 @@ test "x$enable_timing" = xyes || enable_timing=no AC_MSG_RESULT([$enable_timing]) if test "x$enable_timing" = xyes; then AC_DEFINE([TIMING], 1, [If true, use GPTL timing library.]) + AC_DEFINE([HAVE_MPI], [1], [required by GPTL timing library]) fi AM_CONDITIONAL(USE_GPTL, [test "x$enable_timing" = xyes]) @@ -201,12 +202,22 @@ if test "x$enable_developer_docs" = xyes; then fi AM_CONDITIONAL(BUILD_DOCS, [test "x$enable_docs" = xyes]) +# Did the user specify an MPI launcher other than mpiexec? +AC_MSG_CHECKING([whether a user specified program to run mpi programs]) +AC_ARG_WITH([mpiexec], + [AS_HELP_STRING([--with-mpiexec=], + [Specify command to launch MPI parallel tests.])], + [WITH_MPIEXEC=$with_mpiexec], [WITH_MPIEXEC=mpiexec]) +AC_MSG_RESULT([$WITH_MPIEXEC]) +AC_SUBST([WITH_MPIEXEC], [$WITH_MPIEXEC]) + # Is doxygen installed? AC_CHECK_PROGS([DOXYGEN], [doxygen]) if test -z "$DOXYGEN" -a "x$enable_docs" = xyes; then AC_MSG_ERROR([Doxygen not found but --enable-docs used.]) fi +AC_MSG_NOTICE([processing doxyfile]) # If building docs, process Doxyfile.in into Doxyfile. if test "x$enable_docs" = xyes; then AC_SUBST([CMAKE_CURRENT_SOURCE_DIR], ["."]) @@ -223,26 +234,17 @@ if test "x$enable_docs" = xyes; then AC_CONFIG_FILES([doc/Doxyfile]) fi -# NetCDF (at least classic) is required for PIO to build. -AC_DEFINE([_NETCDF], [1], [netCDF classic library available]) - -# ???? -AC_DEFINE([CPRGNU], [1], [defined by CMake build]) - -# We must have MPI to build PIO. -AC_DEFINE([HAVE_MPI], [1], [defined by CMake build]) - -# ??? -AC_DEFINE([INCLUDE_CMAKE_FCI], [1], [defined by CMake build]) - -# All builds are on LINUX. -AC_DEFINE([LINUX], [1], [defined by CMake build]) +AC_MSG_NOTICE([finding libraries]) -# Define to solve intel compiler warning. -AC_DEFINE([_GNU_SOURCE], [1], [solve strnlen declared implicitly warning on intel compiler]) +# Ensure we have MPI. +AC_CHECK_FUNCS([MPI_Init]) +if test "x$ac_cv_func_MPI_Init" != "xyes"; then + AC_MSG_ERROR([Can't link to MPI library. MPI is required.]) +fi # Check for netCDF library. AC_CHECK_LIB([netcdf], [nc_create], [], [AC_MSG_ERROR([Can't find or link to the netcdf library.])]) +AC_CHECK_HEADERS([netcdf.h netcdf_meta.h]) # Check for pnetcdf library. AC_CHECK_LIB([pnetcdf], [ncmpi_create], [], []) @@ -253,8 +255,6 @@ fi # If we have parallel-netcdf, then set these as well. if test x$ac_cv_lib_pnetcdf_ncmpi_create = xyes; then AC_DEFINE([_PNETCDF], [1], [parallel-netcdf library available]) - AC_DEFINE([USE_PNETCDF_VARN], [1], [defined by CMake build]) - AC_DEFINE([USE_PNETCDF_VARN_ON_READ], [1], [defined by CMake build]) fi # Do we have netCDF-4? @@ -286,7 +286,8 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], AC_MSG_CHECKING([whether netCDF provides szip write capability]) AC_MSG_RESULT([${have_szip_write}]) -# Do we have parallel filter support? +# Do we have parallel filter support? Parallel filters are required +# for iotype NETCDF4P to use compression. AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], [[#if !NC_HAS_PAR_FILTERS # error @@ -294,6 +295,35 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], ])], [have_par_filters=yes], [have_par_filters=no]) AC_MSG_CHECKING([whether netCDF provides parallel filter support]) AC_MSG_RESULT([${have_par_filters}]) +if test "x$have_par_filters" = xyes ; then + AC_DEFINE([HAVE_PAR_FILTERS], [1], [if true, netcdf-c supports filters with parallel I/O]) +fi + +# Is this version 4.7.2, which does not work? +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if NC_VERSION_MAJOR == 4 && NC_VERSION_MINOR == 7 && NC_VERSION_PATCH == 2 +#else +# error +#endif] +])], [have_472=yes], [have_472=no]) +AC_MSG_CHECKING([whether this is netcdf-c-4.7.2]) +AC_MSG_RESULT([${have_472}]) +if test "x$have_472" = xyes; then + AC_MSG_ERROR([PIO cannot build with netcdf-c-4.7.2, please upgrade your netCDF version.]) +fi + +# Do we have the correct dispatch table version in netcdf-c for netcdf +# integration? +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include "netcdf_meta.h"], +[[#if NC_DISPATCH_VERSION != 2 +# error +#endif] +])], [have_dispatch2=yes], [have_dispatch2=no]) +AC_MSG_CHECKING([whether netcdf-c supports version 2 of dispatch table for netcdf integration]) +AC_MSG_RESULT([${have_dispatch2}]) +if test "x$enable_netcdf_integration" = xyes -a "x$have_dispatch2" = xno; then + AC_MSG_ERROR([NetCDF integration cannot be used with this version of netcdf-c, please upgrade your netCDF version.]) +fi # Set some build settings for when netcdf-4 is supported. if test x$have_netcdf_par = xyes; then @@ -309,9 +339,6 @@ else AC_MSG_ERROR([Unable to find type MPI_Offset in mpi.h]) fi -#AC_CHECK_SIZEOF([MPI_Offset], [], [[#include ]]) -#AC_DEFINE([SIZEOF_MPI_OFFSET], [8], [netCDF classic library available]) - # If we want the timing library, we must find it. if test "x$enable_timing" = xyes; then AC_CHECK_HEADERS([gptl.h]) @@ -373,6 +400,17 @@ AM_CONDITIONAL(NETCDF_INTEGRATION, [test "x$enable_netcdf_integration" = xyes]) AC_CONFIG_FILES([tests/general/pio_tutil.F90:tests/general/util/pio_tutil.F90]) +# The user may have changed the MPIEXEC for these test scripts. +AC_CONFIG_FILES([tests/cunit/run_tests.sh], [chmod ugo+x tests/cunit/run_tests.sh]) +AC_CONFIG_FILES([tests/ncint/run_tests.sh], [chmod ugo+x tests/ncint/run_tests.sh]) +AC_CONFIG_FILES([tests/ncint/run_perf.sh], [chmod ugo+x tests/ncint/run_perf.sh]) +AC_CONFIG_FILES([tests/fncint/run_tests.sh], [chmod ugo+x tests/fncint/run_tests.sh]) +AC_CONFIG_FILES([tests/general/run_tests.sh], [chmod ugo+x tests/general/run_tests.sh]) +AC_CONFIG_FILES([tests/performance/run_tests.sh], [chmod ugo+x tests/performance/run_tests.sh]) +AC_CONFIG_FILES([tests/unit/run_tests.sh], [chmod ugo+x tests/unit/run_tests.sh]) +AC_CONFIG_FILES([examples/c/run_tests.sh], [chmod ugo+x examples/c/run_tests.sh]) +AC_CONFIG_FILES([examples/f03/run_tests.sh], [chmod ugo+x examples/f03/run_tests.sh]) + # Args: # 1. netcdf_meta.h variable # 2. conditional variable that is yes or no. @@ -396,6 +434,7 @@ AX_SET_META([PIO_HAS_PNETCDF],[$enable_pnetcdf],[yes]) AX_SET_META([PIO_HAS_PAR_FILTERS], [$have_par_filters],[yes]) AX_SET_META([PIO_HAS_NETCDF4], [$have_netcdf4],[yes]) AX_SET_META([PIO_HAS_NETCDF4_PAR], [$have_netcdf_par],[yes]) +AX_SET_META([PIO_HAS_NETCDF_INTEGRATION], [$enable_netcdf_integration],[yes]) # Create output variables from various shell variables, for use in # generating libpio.settings. @@ -413,6 +452,8 @@ AC_SUBST(HAS_SZIP_WRITE, [$have_szip_write]) AC_SUBST([HAS_PAR_FILTERS], [$have_par_filters]) AC_SUBST([HAS_NETCDF4], [$have_netcdf4]) AC_SUBST([HAS_NETCDF4_PAR], [$have_netcdf_par]) +AC_SUBST([HAS_NETCDF_INTEGRATION], [$enable_netcdf_integration]) +AC_SUBST([HAS_PIO_FORTRAN], [$enable_fortran]) # Create the build summary file. AC_CONFIG_FILES([libpio.settings diff --git a/ctest/runcdash-nwscla-gnu.sh b/ctest/runcdash-nwscla-gnu.sh index cdc9eb9916d..ba6b60a5d8a 100755 --- a/ctest/runcdash-nwscla-gnu.sh +++ b/ctest/runcdash-nwscla-gnu.sh @@ -9,12 +9,12 @@ fi module reset module unload netcdf -module swap intel gnu/8.1.0 -module swap mpt openmpi/3.1.0 -module load git/2.10.2 -module load cmake/3.12.1 -module load netcdf/4.6.1 -module load pnetcdf/1.10.0 +module swap intel gnu/10.1.0 +module swap mpt openmpi/4.0.3 +module load git +module load cmake +module load netcdf-mpi/4.7.3 +module load pnetcdf/1.12.1 export CC=mpicc export FC=mpif90 diff --git a/ctest/runcdash-nwscla-intel.sh b/ctest/runcdash-nwscla-intel.sh index 9393086ed8d..e85d5760c0d 100755 --- a/ctest/runcdash-nwscla-intel.sh +++ b/ctest/runcdash-nwscla-intel.sh @@ -11,11 +11,11 @@ source /etc/profile.d/modules.sh module reset module unload netcdf -module swap intel intel/19.0.2 -module switch mpt mpt/2.19 -module load cmake/3.7.2 -module load netcdf-mpi/4.6.1 -module load pnetcdf/1.11.0 +module swap intel intel/19.1.1 +module switch mpt mpt/2.22 +module load cmake/3.18.2 +module load netcdf-mpi/4.7.3 +module load pnetcdf/1.12.1 echo "MODULE LIST..." module list diff --git a/ctest/runcdash-nwscla-pgi.sh b/ctest/runcdash-nwscla-pgi.sh index 08538185f44..8d9c0cde8be 100755 --- a/ctest/runcdash-nwscla-pgi.sh +++ b/ctest/runcdash-nwscla-pgi.sh @@ -2,25 +2,25 @@ # Get/Generate the Dashboard Model if [ $# -eq 0 ]; then - model=Experimental + model=Experimental else - model=$1 + model=$1 fi module reset module unload netcdf -module swap intel pgi/17.9 -module swap mpt mpt/2.19 -module load git/2.10.2 -module load cmake/3.12.1 -module load netcdf-mpi/4.6.1 -module load pnetcdf/1.11.0 +module swap intel pgi/20.4 +module swap mpt mpt/2.22 +module load git/2.22.0 +module load cmake/3.18.2 +module load netcdf-mpi/4.7.3 +module load pnetcdf/1.12.1 export CC=mpicc export FC=mpif90 export MPI_TYPE_DEPTH=24 export PIO_DASHBOARD_ROOT=/glade/u/home/jedwards/sandboxes/dashboard -export PIO_COMPILER_ID=PGI-`$CC --version | head -n 2 | tail -n 1 | cut -d' ' -f2` +export PIO_COMPILER_ID=PGI-`$CC --version | head -n 2 | tail -n 1 | cut -d' ' -f4` if [ ! -d "$PIO_DASHBOARD_ROOT" ]; then mkdir "$PIO_DASHBOARD_ROOT" diff --git a/examples/basic/gdecomp_mod.F90 b/examples/basic/gdecomp_mod.F90 index e4f1921452e..b5b41407ad3 100644 --- a/examples/basic/gdecomp_mod.F90 +++ b/examples/basic/gdecomp_mod.F90 @@ -300,9 +300,7 @@ end subroutine gdecomp_print !================================================================== subroutine gdecomp_DOF(gdecomp,my_task,DOF,start,count,write_decomp,test) -#ifdef _NETCDF use netcdf ! _EXTERNAL -#endif implicit none @@ -712,7 +710,6 @@ subroutine gdecomp_DOF(gdecomp,my_task,DOF,start,count,write_decomp,test) ! --- write out arrays --- -#ifdef _NETCDF if (wdecomp) then write(6,*) ' ' write(6,*) trim(subname),' writing decomp info to file ',trim(ncname) @@ -738,7 +735,6 @@ subroutine gdecomp_DOF(gdecomp,my_task,DOF,start,count,write_decomp,test) rcode = nf90_put_var(ncid,varid(2),tskid) rcode = nf90_close(ncid) endif -#endif endif ! testonly diff --git a/examples/basic/testpio.F90 b/examples/basic/testpio.F90 index 2a6e62e427a..d93d4e27521 100644 --- a/examples/basic/testpio.F90 +++ b/examples/basic/testpio.F90 @@ -770,11 +770,7 @@ program testpio ! print *, __FILE__,__LINE__,'>',fname_r8,'<' ! print *, __FILE__,__LINE__,'>',fname_i4,'<' ! print *, __FILE__,__LINE__,'>',fname_r4,'<' -#if defined(_NETCDF) || defined(_PNETCDF) mode = pio_64bit_offset -#else - mode = 0 -#endif if(writePhase) then if(TestCombo) then diff --git a/examples/c/Makefile.am b/examples/c/Makefile.am index 64398761f13..82d1889ed63 100644 --- a/examples/c/Makefile.am +++ b/examples/c/Makefile.am @@ -16,7 +16,9 @@ TESTS = run_tests.sh endif # RUN_TESTS # Distribute the test script. -EXTRA_DIST = run_tests.sh CMakeLists.txt example2.c +EXTRA_DIST = run_tests.sh.in CMakeLists.txt example2.c # Clean up files produced during testing. CLEANFILES = *.nc *.log *.clog2 *.slog2 + +DISTCLEANFILES = run_tests.sh diff --git a/examples/c/run_tests.sh b/examples/c/run_tests.sh.in similarity index 87% rename from examples/c/run_tests.sh rename to examples/c/run_tests.sh.in index 0d369bbb53d..7651c835624 100755 --- a/examples/c/run_tests.sh +++ b/examples/c/run_tests.sh.in @@ -19,7 +19,7 @@ for EXAMPLE in $PIO_EXAMPLES do success1=false echo "running ${EXAMPLE}" - mpiexec -n 4 ./${EXAMPLE} && success1=true + @WITH_MPIEXEC@ -n 4 ./${EXAMPLE} && success1=true if test $success1 = false; then break fi @@ -29,7 +29,7 @@ for EXAMPLE in $PIO_EXAMPLES_16 do success2=false echo "running ${EXAMPLE}" - mpiexec -n 16 ./${EXAMPLE} && success2=true + @WITH_MPIEXEC@ -n 16 ./${EXAMPLE} && success2=true if test $success2 = false; then break fi diff --git a/examples/f03/CMakeLists.txt b/examples/f03/CMakeLists.txt index a299c7cde8c..1073fda1a94 100644 --- a/examples/f03/CMakeLists.txt +++ b/examples/f03/CMakeLists.txt @@ -15,6 +15,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0") if(${PIO_BUILD_TIMING}) SET(TIMING_LINK_LIB timing) endif() -SET(SRC examplePio.f90) +SET(SRC examplePio.F90) ADD_EXECUTABLE(examplePio_f90 ${SRC}) TARGET_LINK_LIBRARIES(examplePio_f90 piof pioc ${TIMING_LINK_LIB}) diff --git a/examples/f03/Makefile.am b/examples/f03/Makefile.am index 9a8781d20ad..fc8698a53a9 100644 --- a/examples/f03/Makefile.am +++ b/examples/f03/Makefile.am @@ -3,8 +3,8 @@ # Ed Hartnett 7/17/19 -# Put together AM_CPPFLAGS and AM_LDFLAGS. -include $(top_srcdir)/set_flags.am +# Find the pio.mod file. +AM_CPPFLAGS = -I$(top_srcdir)/src/flib AM_FCFLAGS = -I$(top_srcdir)/src/flib @@ -14,7 +14,7 @@ ${top_builddir}/src/clib/libpioc.la # Build the test for make check. check_PROGRAMS = examplePio -examplePio_SOURCES = examplePio.f90 +examplePio_SOURCES = examplePio.F90 if RUN_TESTS # Tests will run from a bash script. @@ -22,7 +22,9 @@ TESTS = run_tests.sh endif # RUN_TESTS # Distribute the test script. -EXTRA_DIST = CMakeLists.txt run_tests.sh +EXTRA_DIST = CMakeLists.txt run_tests.sh.in # Clean up files produced during testing. CLEANFILES = *.nc *.log *.mod + +DISTCLEANFILES = run_tests.sh diff --git a/examples/f03/examplePio.f90 b/examples/f03/examplePio.F90 similarity index 99% rename from examples/f03/examplePio.f90 rename to examples/f03/examplePio.F90 index d2baddf2096..88804b7acab 100644 --- a/examples/f03/examplePio.f90 +++ b/examples/f03/examplePio.F90 @@ -1,3 +1,4 @@ +#include "config.h" !> @file !! A simple Fortran example for the ParallelIO Library. module pioExample diff --git a/examples/f03/run_tests.sh b/examples/f03/run_tests.sh.in similarity index 91% rename from examples/f03/run_tests.sh rename to examples/f03/run_tests.sh.in index d7e4d59f480..4bdb7df0964 100755 --- a/examples/f03/run_tests.sh +++ b/examples/f03/run_tests.sh.in @@ -18,7 +18,7 @@ for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi diff --git a/libpio.settings.in b/libpio.settings.in index 44785afd6a5..c3e09045851 100644 --- a/libpio.settings.in +++ b/libpio.settings.in @@ -22,7 +22,7 @@ Extra libraries: @LIBS@ Fortran Compiler: @FC_VERSION@ FFLAGS: @FFLAGS@ FCFLAGS: @FCFLAGS@ -FPPFLAGS: @FPPFLAGS@ +More Fortran Flags: @FPPFLAGS@ # Features -------- @@ -31,4 +31,8 @@ SZIP Write Support: @HAS_SZIP_WRITE@ Parallel Filters: @HAS_PAR_FILTERS@ NetCDF/HDF5 Support: @HAS_NETCDF4@ NetCDF/HDF5 Par I/O: @HAS_NETCDF4_PAR@ +NetCDF Integration: @HAS_NETCDF_INTEGRATION@ +PIO Logging: @HAS_LOGGING@ +MPIEXEC: @WITH_MPIEXEC@ +Fortran: @HAS_PIO_FORTRAN@ diff --git a/set_flags.am b/set_flags.am deleted file mode 100644 index 08efa30db22..00000000000 --- a/set_flags.am +++ /dev/null @@ -1,18 +0,0 @@ -# This is part of the PIO package. -# -# Assemble the CPPFLAGS and for PIO Fortran tests. -# -# Ed Hartnett 3/26/19 - -# Set the CPPFLAGS. -AM_CPPFLAGS = -I$(top_srcdir)/src/flib -D_NETCDF - -# Is the user building with pnetcdf? -if BUILD_PNETCDF -AM_CPPFLAGS += -D_PNETCDF -endif - -# Is the user building with netCDF-4 parallel I/O? -if BUILD_NETCDF4 -AM_CPPFLAGS += -D_NETCDF4 -endif diff --git a/src/clib/CMakeLists.txt b/src/clib/CMakeLists.txt index d81ec2edbc4..8e3e63e6767 100644 --- a/src/clib/CMakeLists.txt +++ b/src/clib/CMakeLists.txt @@ -6,10 +6,15 @@ project (PIOC C) # DEFINE THE TARGET #============================================================================== -add_library (pioc topology.c pio_file.c pioc_support.c pio_lists.c - pioc.c pioc_sc.c pio_spmd.c pio_rearrange.c pio_nc4.c bget.c +set (src topology.c pio_file.c pioc_support.c pio_lists.c + pioc.c pioc_sc.c pio_spmd.c pio_rearrange.c pio_nc4.c pio_nc.c pio_put_nc.c pio_get_nc.c pio_getput_int.c pio_msg.c pio_darray.c pio_darray_int.c pio_get_vard.c pio_put_vard.c pio_error.c) +if (NETCDF_INTEGRATION) + set (src ${src} ../ncint/nc_get_vard.c ../ncint/ncintdispatch.c ../ncint/ncint_pio.c ../ncint/nc_put_vard.c) +endif () + +add_library (pioc ${src}) # set up include-directories include_directories( @@ -21,6 +26,10 @@ include_directories( target_include_directories (pioc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +# Include the ncint source directory +target_include_directories (pioc + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../ncint) + # System and compiler CPP directives target_compile_definitions (pioc PUBLIC ${CMAKE_SYSTEM_DIRECTIVE}) @@ -66,7 +75,6 @@ endif () #===== GPTL ===== if (PIO_ENABLE_TIMING) - find_package (GPTL COMPONENTS C QUIET) if (GPTL_C_FOUND) message (STATUS "Found GPTL C: ${GPTL_C_LIBRARIES}") target_include_directories (pioc @@ -83,53 +91,27 @@ if (PIO_ENABLE_TIMING) endif () #===== NetCDF-C ===== -find_package (NetCDF "4.3.3" COMPONENTS C) if (NetCDF_C_FOUND) target_include_directories (pioc PUBLIC ${NetCDF_C_INCLUDE_DIRS}) - target_compile_definitions (pioc - PUBLIC _NETCDF) target_link_libraries (pioc PUBLIC ${NetCDF_C_LIBRARIES}) - if (${NetCDF_C_HAS_PARALLEL}) - target_compile_definitions (pioc - PUBLIC _NETCDF4) - endif () if (${NetCDF_C_LOGGING_ENABLED}) - target_compile_definitions (pioc - PUBLIC NETCDF_C_LOGGING_ENABLED) # netcdf.h needs this to be defined to use netCDF logging. target_compile_definitions (pioc PUBLIC LOGGING) endif() -else () - target_compile_definitions (pioc - PUBLIC _NONETCDF) endif () #===== PnetCDF-C ===== -if (WITH_PNETCDF) - find_package (PnetCDF "1.7.0" COMPONENTS C) -endif () if (PnetCDF_C_FOUND) target_include_directories (pioc PUBLIC ${PnetCDF_C_INCLUDE_DIRS}) - target_compile_definitions (pioc - PUBLIC _PNETCDF) target_link_libraries (pioc PUBLIC ${PnetCDF_C_LIBRARIES}) # Check library for varn functions set (CMAKE_REQUIRED_LIBRARIES ${PnetCDF_C_LIBRARY}) - check_function_exists (ncmpi_get_varn PnetCDF_C_HAS_VARN) - if (PnetCDF_C_HAS_VARN) - target_compile_definitions(pioc - PUBLIC USE_PNETCDF_VARN - PUBLIC USE_PNETCDF_VARN_ON_READ) - endif() -else () - target_compile_definitions (pioc - PUBLIC _NOPNETCDF) endif () #===== Add EXTRAs ===== diff --git a/src/clib/Makefile.am b/src/clib/Makefile.am index bfcabe342ae..37a92bc4610 100644 --- a/src/clib/Makefile.am +++ b/src/clib/Makefile.am @@ -13,16 +13,16 @@ endif # BUILD_NCINT # These linker flags specify libtool version info. # See http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning # for information regarding incrementing `-version-info`. -libpioc_la_LDFLAGS = -version-info 4:1:3 +libpioc_la_LDFLAGS = -version-info 5:0:0 # The library header file will be installed in include dir. include_HEADERS = pio.h uthash.h pio_meta.h # The library soure files. -libpioc_la_SOURCES = bget.c pioc_sc.c pio_darray.c pio_file.c \ +libpioc_la_SOURCES = pioc_sc.c pio_darray.c pio_file.c \ pio_getput_int.c pio_msg.c pio_nc.c pio_rearrange.c pioc.c \ pioc_support.c pio_darray_int.c pio_get_nc.c pio_lists.c pio_nc4.c \ pio_put_nc.c pio_spmd.c pio_get_vard.c pio_put_vard.c pio_error.c \ -pio_internal.h bget.h uthash.h pio_error.h +pio_internal.h uthash.h pio_error.h EXTRA_DIST = CMakeLists.txt topology.c pio_meta.h.in diff --git a/src/clib/bget.c b/src/clib/bget.c deleted file mode 100644 index d6e8b7bbbbb..00000000000 --- a/src/clib/bget.c +++ /dev/null @@ -1,1677 +0,0 @@ -/* - - B G E T - - Buffer allocator - - Designed and implemented in April of 1972 by John Walker, based on the - Case Algol OPRO$ algorithm implemented in 1966. - - Reimplemented in 1975 by John Walker for the Interdata 70. - Reimplemented in 1977 by John Walker for the Marinchip 9900. - Reimplemented in 1982 by Duff Kurland for the Intel 8080. - - Portable C version implemented in September of 1990 by an older, wiser - instance of the original implementor. - - Souped up and/or weighed down slightly shortly thereafter by Greg - Lutz. - - AMIX edition, including the new compaction call-back option, prepared - by John Walker in July of 1992. - - Bug in built-in test program fixed, ANSI compiler warnings eradicated, - buffer pool validator implemented, and guaranteed repeatable test - added by John Walker in October of 1995. - - This program is in the public domain. - - 1. This is the book of the generations of Adam. In the day that God - created man, in the likeness of God made he him; - 2. Male and female created he them; and blessed them, and called - their name Adam, in the day when they were created. - 3. And Adam lived an hundred and thirty years, and begat a son in - his own likeness, and after his image; and called his name Seth: - 4. And the days of Adam after he had begotten Seth were eight - hundred years: and he begat sons and daughters: - 5. And all the days that Adam lived were nine hundred and thirty - years: and he died. - 6. And Seth lived an hundred and five years, and begat Enos: - 7. And Seth lived after he begat Enos eight hundred and seven years, - and begat sons and daughters: - 8. And all the days of Seth were nine hundred and twelve years: and - he died. - 9. And Enos lived ninety years, and begat Cainan: - 10. And Enos lived after he begat Cainan eight hundred and fifteen - years, and begat sons and daughters: - 11. And all the days of Enos were nine hundred and five years: and - he died. - 12. And Cainan lived seventy years and begat Mahalaleel: - 13. And Cainan lived after he begat Mahalaleel eight hundred and - forty years, and begat sons and daughters: - 14. And all the days of Cainan were nine hundred and ten years: and - he died. - 15. And Mahalaleel lived sixty and five years, and begat Jared: - 16. And Mahalaleel lived after he begat Jared eight hundred and - thirty years, and begat sons and daughters: - 17. And all the days of Mahalaleel were eight hundred ninety and - five years: and he died. - 18. And Jared lived an hundred sixty and two years, and he begat - Enoch: - 19. And Jared lived after he begat Enoch eight hundred years, and - begat sons and daughters: - 20. And all the days of Jared were nine hundred sixty and two years: - and he died. - 21. And Enoch lived sixty and five years, and begat Methuselah: - 22. And Enoch walked with God after he begat Methuselah three - hundred years, and begat sons and daughters: - 23. And all the days of Enoch were three hundred sixty and five - years: - 24. And Enoch walked with God: and he was not; for God took him. - 25. And Methuselah lived an hundred eighty and seven years, and - begat Lamech. - 26. And Methuselah lived after he begat Lamech seven hundred eighty - and two years, and begat sons and daughters: - 27. And all the days of Methuselah were nine hundred sixty and nine - years: and he died. - 28. And Lamech lived an hundred eighty and two years, and begat a - son: - 29. And he called his name Noah, saying, This same shall comfort us - concerning our work and toil of our hands, because of the ground - which the LORD hath cursed. - 30. And Lamech lived after he begat Noah five hundred ninety and - five years, and begat sons and daughters: - 31. And all the days of Lamech were seven hundred seventy and seven - years: and he died. - 32. And Noah was five hundred years old: and Noah begat Shem, Ham, - and Japheth. - - And buffers begat buffers, and links begat links, and buffer pools - begat links to chains of buffer pools containing buffers, and lo the - buffers and links and pools of buffers and pools of links to chains of - pools of buffers were fruitful and they multiplied and the Operating - System looked down upon them and said that it was Good. - - - INTRODUCTION - ============ - - BGET is a comprehensive memory allocation package which is easily - configured to the needs of an application. BGET is efficient in - both the time needed to allocate and release buffers and in the - memory overhead required for buffer pool management. It - automatically consolidates contiguous space to minimise - fragmentation. BGET is configured by compile-time definitions, - Major options include: - - * A built-in test program to exercise BGET and - demonstrate how the various functions are used. - - * Allocation by either the "first fit" or "best fit" - method. - - * Wiping buffers at release time to catch code which - references previously released storage. - - * Built-in routines to dump individual buffers or the - entire buffer pool. - - * Retrieval of allocation and pool size statistics. - - * Quantisation of buffer sizes to a power of two to - satisfy hardware alignment constraints. - - * Automatic pool compaction, growth, and shrinkage by - means of call-backs to user defined functions. - - Applications of BGET can range from storage management in - ROM-based embedded programs to providing the framework upon which - a multitasking system incorporating garbage collection is - constructed. BGET incorporates extensive internal consistency - checking using the mechanism; all these checks can be - turned off by compiling with NDEBUG defined, yielding a version of - BGET with minimal size and maximum speed. - - The basic algorithm underlying BGET has withstood the test of - time; more than 25 years have passed since the first - implementation of this code. And yet, it is substantially more - efficient than the native allocation schemes of many operating - systems: the Macintosh and Microsoft Windows to name two, on which - programs have obtained substantial speed-ups by layering BGET as - an application level memory manager atop the underlying system's. - - BGET has been implemented on the largest mainframes and the lowest - of microprocessors. It has served as the core for multitasking - operating systems, multi-thread applications, embedded software in - data network switching processors, and a host of C programs. And - while it has accreted flexibility and additional options over the - years, it remains fast, memory efficient, portable, and easy to - integrate into your program. - - - BGET IMPLEMENTATION ASSUMPTIONS - =============================== - - BGET is written in as portable a dialect of C as possible. The - only fundamental assumption about the underlying hardware - architecture is that memory is allocated is a linear array which - can be addressed as a vector of C "char" objects. On segmented - address space architectures, this generally means that BGET should - be used to allocate storage within a single segment (although some - compilers simulate linear address spaces on segmented - architectures). On segmented architectures, then, BGET buffer - pools may not be larger than a segment, but since BGET allows any - number of separate buffer pools, there is no limit on the total - storage which can be managed, only on the largest individual - object which can be allocated. Machines with a linear address - architecture, such as the VAX, 680x0, Sparc, MIPS, or the Intel - 80386 and above in native mode, may use BGET without restriction. - - - GETTING STARTED WITH BGET - ========================= - - Although BGET can be configured in a multitude of fashions, there - are three basic ways of working with BGET. The functions - mentioned below are documented in the following section. Please - excuse the forward references which are made in the interest of - providing a roadmap to guide you to the BGET functions you're - likely to need. - - Embedded Applications - --------------------- - - Embedded applications typically have a fixed area of memory - dedicated to buffer allocation (often in a separate RAM address - space distinct from the ROM that contains the executable code). - To use BGET in such an environment, simply call bpool() with the - start address and length of the buffer pool area in RAM, then - allocate buffers with bget() and release them with brel(). - Embedded applications with very limited RAM but abundant CPU speed - may benefit by configuring BGET for BestFit allocation (which is - usually not worth it in other environments). - - Malloc() Emulation - ------------------ - - If the C library malloc() function is too slow, not present in - your development environment (for example, an a native Windows or - Macintosh program), or otherwise unsuitable, you can replace it - with BGET. Initially define a buffer pool of an appropriate size - with bpool()--usually obtained by making a call to the operating - system's low-level memory allocator. Then allocate buffers with - bget(), bgetz(), and bgetr() (the last two permit the allocation - of buffers initialised to zero and [inefficient] re-allocation of - existing buffers for compatibility with C library functions). - Release buffers by calling brel(). If a buffer allocation request - fails, obtain more storage from the underlying operating system, - add it to the buffer pool by another call to bpool(), and continue - execution. - - Automatic Storage Management - ---------------------------- - - You can use BGET as your application's native memory manager and - implement automatic storage pool expansion, contraction, and - optionally application-specific memory compaction by compiling - BGET with the BECtl variable defined, then calling bectl() and - supplying functions for storage compaction, acquisition, and - release, as well as a standard pool expansion increment. All of - these functions are optional (although it doesn't make much sense - to provide a release function without an acquisition function, - does it?). Once the call-back functions have been defined with - bectl(), you simply use bget() and brel() to allocate and release - storage as before. You can supply an initial buffer pool with - bpool() or rely on automatic allocation to acquire the entire - pool. When a call on bget() cannot be satisfied, BGET first - checks if a compaction function has been supplied. If so, it is - called (with the space required to satisfy the allocation request - and a sequence number to allow the compaction routine to be called - successively without looping). If the compaction function is able - to free any storage (it needn't know whether the storage it freed - was adequate) it should return a nonzero value, whereupon BGET - will retry the allocation request and, if it fails again, call the - compaction function again with the next-higher sequence number. - - If the compaction function returns zero, indicating failure to - free space, or no compaction function is defined, BGET next tests - whether a non-NULL allocation function was supplied to bectl(). - If so, that function is called with an argument indicating how - many bytes of additional space are required. This will be the - standard pool expansion increment supplied in the call to bectl() - unless the original bget() call requested a buffer larger than - this; buffers larger than the standard pool block can be managed - "off the books" by BGET in this mode. If the allocation function - succeeds in obtaining the storage, it returns a pointer to the new - block and BGET expands the buffer pool; if it fails, the - allocation request fails and returns NULL to the caller. If a - non-NULL release function is supplied, expansion blocks which - become totally empty are released to the global free pool by - passing their addresses to the release function. - - Equipped with appropriate allocation, release, and compaction - functions, BGET can be used as part of very sophisticated memory - management strategies, including garbage collection. (Note, - however, that BGET is *not* a garbage collector by itself, and - that developing such a system requires much additional logic and - careful design of the application's memory allocation strategy.) - - - BGET FUNCTION DESCRIPTIONS - ========================== - - Functions implemented in this file (some are enabled by certain of - the optional settings below): - - void bpool(void *buffer, bufsize len); - - Create a buffer pool of bytes, using the storage starting at - . You can call bpool() subsequently to contribute - additional storage to the overall buffer pool. - - void *bget(bufsize size); - - Allocate a buffer of bytes. The address of the buffer is - returned, or NULL if insufficient memory was available to allocate - the buffer. - - void *bgetz(bufsize size); - - Allocate a buffer of bytes and clear it to all zeroes. The - address of the buffer is returned, or NULL if insufficient memory - was available to allocate the buffer. - - void *bgetr(void *buffer, bufsize newsize); - - Reallocate a buffer previously allocated by bget(), changing its - size to and preserving all existing data. NULL is - returned if insufficient memory is available to reallocate the - buffer, in which case the original buffer remains intact. - - void brel(void *buf); - - Return the buffer , previously allocated by bget(), to the - free space pool. - - void bectl(int (*compact)(bufsize sizereq, int sequence), - void *(*acquire)(bufsize size), - void (*release)(void *buf), - bufsize pool_incr); - - Expansion control: specify functions through which the package may - compact storage (or take other appropriate action) when an - allocation request fails, and optionally automatically acquire - storage for expansion blocks when necessary, and release such - blocks when they become empty. If is non-NULL, whenever - a buffer allocation request fails, the function will be - called with arguments specifying the number of bytes (total buffer - size, including header overhead) required to satisfy the - allocation request, and a sequence number indicating the number of - consecutive calls on attempting to satisfy this - allocation request. The sequence number is 1 for the first call - on for a given allocation request, and increments on - subsequent calls, permitting the function to take - increasingly dire measures in an attempt to free up storage. If - the function returns a nonzero value, the allocation - attempt is re-tried. If returns 0 (as it must if it - isn't able to release any space or add storage to the buffer - pool), the allocation request fails, which can trigger automatic - pool expansion if the argument is non-NULL. At the time - the function is called, the state of the buffer - allocator is identical to that at the moment the allocation - request was made; consequently, the function may call - brel(), bpool(), bstats(), and/or directly manipulate the buffer - pool in any manner which would be valid were the application in - control. This does not, however, relieve the function - of the need to ensure that whatever actions it takes do not change - things underneath the application that made the allocation - request. For example, a function that released a buffer - in the process of being reallocated with bgetr() would lead to - disaster. Implementing a safe and effective mechanism - requires careful design of an application's memory architecture, - and cannot generally be easily retrofitted into existing code. - - If is non-NULL, that function will be called whenever an - allocation request fails. If the function succeeds in - allocating the requested space and returns a pointer to the new - area, allocation will proceed using the expanded buffer pool. If - cannot obtain the requested space, it should return NULL - and the entire allocation process will fail. - specifies the normal expansion block size. Providing an - function will cause subsequent bget() requests for buffers too - large to be managed in the linked-block scheme (in other words, - larger than minus the buffer overhead) to be satisfied - directly by calls to the function. Automatic release of - empty pool blocks will occur only if all pool blocks in the system - are the size given by . - - void bstats(bufsize *curalloc, bufsize *totfree, - bufsize *maxfree, long *nget, long *nrel); - - The amount of space currently allocated is stored into the - variable pointed to by . The total free space (sum of - all free blocks in the pool) is stored into the variable pointed - to by , and the size of the largest single block in the - free space pool is stored into the variable pointed to by - . The variables pointed to by and are - filled, respectively, with the number of successful (non-NULL - return) bget() calls and the number of brel() calls. - - void bstatse(bufsize *pool_incr, long *npool, - long *npget, long *nprel, - long *ndget, long *ndrel); - - Extended statistics: The expansion block size will be stored into - the variable pointed to by , or the negative thereof if - automatic expansion block releases are disabled. The number of - currently active pool blocks will be stored into the variable - pointed to by . The variables pointed to by and - will be filled with, respectively, the number of expansion - block acquisitions and releases which have occurred. The - variables pointed to by and will be filled with - the number of bget() and brel() calls, respectively, managed - through blocks directly allocated by the acquisition and release - functions. - - void bufdump(void *buf); - - The buffer pointed to by is dumped on standard output. - - void bpoold(void *pool, int dumpalloc, int dumpfree); - - All buffers in the buffer pool , previously initialised by a - call on bpool(), are listed in ascending memory address order. If - is nonzero, the contents of allocated buffers are - dumped; if is nonzero, the contents of free blocks are - dumped. - - int bpoolv(void *pool); - - The named buffer pool, previously initialised by a call on - bpool(), is validated for bad pointers, overwritten data, etc. If - compiled with NDEBUG not defined, any error generates an assertion - failure. Otherwise 1 is returned if the pool is valid, 0 if an - error is found. - - - BGET CONFIGURATION - ================== -*/ -#include -#include -#include -#if PIO_USE_MALLOC -#include -#endif - -#define TestProg 20000 /* Generate built-in test program - if defined. The value specifies - how many buffer allocation attempts - the test program should make. */ -#undef TestProg - -#define SizeQuant 4 /* Buffer allocation size quantum: - all buffers allocated are a - multiple of this size. This - MUST be a power of two. */ - -#define BufDump 1 /* Define this symbol to enable the - bpoold() function which dumps the - buffers in a buffer pool. */ - -#define BufValid 1 /* Define this symbol to enable the - bpoolv() function for validating - a buffer pool. */ - -#define DumpData 1 /* Define this symbol to enable the - bufdump() function which allows - dumping the contents of an allocated - or free buffer. */ - -#define BufStats 1 /* Define this symbol to enable the - bstats() function which calculates - the total free space in the buffer - pool, the largest available - buffer, and the total space - currently allocated. */ - -#define FreeWipe 1 /* Wipe free buffers to a guaranteed - pattern of garbage to trip up - miscreants who attempt to use - pointers into released buffers. */ - -//#define BestFit 1 -#undef BestFit -/* Use a best fit algorithm when - searching for space for an - allocation request. This uses - memory more efficiently, but - allocation will be much slower. */ - -#define BECtl 1 /* Define this symbol to enable the - bectl() function for automatic - pool space control. */ - -#include - -#ifdef lint -#define NDEBUG /* Exits in asserts confuse lint */ -/* LINTLIBRARY */ /* Don't complain about def, no ref */ -extern char *sprintf(); /* Sun includes don't define sprintf */ -#endif - -#include -#include - -#ifdef BufDump /* BufDump implies DumpData */ -#ifndef DumpData -#define DumpData 1 -#endif -#endif - -#ifdef DumpData -#include -#endif - -/* Declare the interface, including the requested buffer size type, - bufsize. */ - -#include "bget.h" - -#define MemSize size_t /* Type for size arguments to memxxx() - functions such as memcmp(). */ - -/* Queue links */ - -struct qlinks { - struct bfhead *flink; /* Forward link */ - struct bfhead *blink; /* Backward link */ -}; - -/* Header in allocated and free buffers */ - -struct bhead { - bufsize prevfree; /* Relative link back to previous - free buffer in memory or 0 if - previous buffer is allocated. */ - bufsize bsize; /* Buffer size: positive if free, - negative if allocated. */ -}; -#define BH(p) ((struct bhead *) (p)) - -/* Header in directly allocated buffers (by acqfcn) */ - -struct bdhead { - bufsize tsize; /* Total size, including overhead */ - struct bhead bh; /* Common header */ -}; -#define BDH(p) ((struct bdhead *) (p)) - -/* Header in free buffers */ - -struct bfhead { - struct bhead bh; /* Common allocated/free header */ - struct qlinks ql; /* Links on free list */ -}; -#define BFH(p) ((struct bfhead *) (p)) - -static struct bfhead freelist = { /* List of free buffers */ - {0, 0}, - {&freelist, &freelist} -}; - - -#ifdef BufStats -static bufsize totalloc = 0; /* Total space currently allocated */ -static long numget = 0, numrel = 0; /* Number of bget() and brel() calls */ -#ifdef BECtl -static long numpblk = 0; /* Number of pool blocks */ -static long numpget = 0, numprel = 0; /* Number of block gets and rels */ -static long numdget = 0, numdrel = 0; /* Number of direct gets and rels */ -#endif /* BECtl */ -#endif /* BufStats */ - -#ifdef BECtl - -/* Automatic expansion block management functions */ - -static int (*compfcn) _((bufsize sizereq, int sequence)) = NULL; -static void *(*acqfcn) _((bufsize size)) = NULL; -static void (*relfcn) _((void *buf)) = NULL; - -static bufsize exp_incr = 0; /* Expansion block size */ -static bufsize pool_len = 0; /* 0: no bpool calls have been made - -1: not all pool blocks are - the same size - >0: (common) block size for all - bpool calls made so far - */ -#endif - -/* Minimum allocation quantum: */ - -#define QLSize (sizeof(struct qlinks)) -#define SizeQ ((SizeQuant > QLSize) ? SizeQuant : QLSize) - -#define V (void) /* To denote unwanted returned values */ - -/* End sentinel: value placed in bsize field of dummy block delimiting - end of pool block. The most negative number which will fit in a - bufsize, defined in a way that the compiler will accept. */ - -#define ESent ((bufsize) (-(((1L << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2)) - -/* added for PIO so that a bpool can be freed and another allocated */ -void bpoolrelease() -{ - PLOG((2, "bpoolrelease")); - freelist.bh.prevfree=0; - freelist.bh.bsize=0; - freelist.ql.flink=&freelist; - freelist.ql.blink=&freelist; - PLOG((2, "bpoolrelease")); - -#ifdef BufStats - totalloc = 0; /* Total space currently allocated */ - numget = 0; - numrel = 0; /* Number of bget() and brel() calls */ -#ifdef BECtl - numpblk = 0; /* Number of pool blocks */ - numpget = 0; - numprel = 0; /* Number of block gets and rels */ - numdget = 0; - numdrel = 0; /* Number of direct gets and rels */ -#endif /* BECtl */ -#endif /* BufStats */ - PLOG((2, "bpoolrelease")); - -#ifdef BECtl -/* Automatic expansion block management functions */ - compfcn = NULL; - acqfcn = NULL; - relfcn = NULL; - exp_incr = 0; - pool_len = 0; -#endif - PLOG((2, "bpoolrelease")); - -} - - - -/* BGET -- Allocate a buffer. */ - -void *bget(requested_size) -bufsize requested_size; -{ - bufsize size = requested_size; - struct bfhead *b; -#ifdef BestFit - struct bfhead *best; -#endif - void *buf; -#ifdef BECtl - int compactseq = 0; -#endif - -#if PIO_USE_MALLOC - // if(requested_size>maxsize){ - // maxsize=requested_size; - // printf("%s %d %d\n",__FILE__,__LINE__,maxsize); - // } - buf = malloc(requested_size); - // printf("bget allocate %ld %x\n",requested_size,buf); - return(buf); -#endif - - - if(size<=0) - print_trace(NULL); - - assert(size > 0); - - if (size < SizeQ) { /* Need at least room for the */ - size = SizeQ; /* queue links. */ - } -#ifdef SizeQuant -#if SizeQuant > 1 - size = (size + (SizeQuant - 1)) & (~(SizeQuant - 1)); -#endif -#endif - - size += sizeof(struct bhead); /* Add overhead in allocated buffer - to size required. */ - -#ifdef BECtl - /* If a compact function was provided in the call to bectl(), wrap - a loop around the allocation process to allow compaction to - intervene in case we don't find a suitable buffer in the chain. */ - - while (1) { -#endif - b = freelist.ql.flink; -#ifdef BestFit - best = &freelist; -#endif - - - /* Scan the free list searching for the first buffer big enough - to hold the requested size buffer. */ - -#ifdef BestFit - while (b != &freelist) { - // printf("%s %d %X %X %X %ld \n",__FILE__,__LINE__,b,&freelist,best,b->bh.bsize); - if (b->bh.bsize >= size) { - if ((best == &freelist) || (b->bh.bsize < best->bh.bsize)) { - best = b; - } - } - b = b->ql.flink; /* Link to next buffer */ - } - b = best; -#endif /* BestFit */ - - while (b != &freelist) { - if ((bufsize) b->bh.bsize >= size) { - - /* Buffer is big enough to satisfy the request. Allocate it - to the caller. We must decide whether the buffer is large - enough to split into the part given to the caller and a - free buffer that remains on the free list, or whether the - entire buffer should be removed from the free list and - given to the caller in its entirety. We only split the - buffer if enough room remains for a header plus the minimum - quantum of allocation. */ - - if ((b->bh.bsize - size) > (SizeQ + (sizeof(struct bhead)))) { - struct bhead *ba, *bn; - - ba = BH(((char *) b) + (b->bh.bsize - size)); - bn = BH(((char *) ba) + size); - assert(bn->prevfree == b->bh.bsize); - /* Subtract size from length of free block. */ - b->bh.bsize -= size; - /* Link allocated buffer to the previous free buffer. */ - ba->prevfree = b->bh.bsize; - /* Plug negative size into user buffer. */ - ba->bsize = -(bufsize) size; - /* Mark buffer after this one not preceded by free block. */ - bn->prevfree = 0; - -#ifdef BufStats - totalloc += size; - numget++; /* Increment number of bget() calls */ -#endif - buf = (void *) ((((char *) ba) + sizeof(struct bhead))); - return buf; - } else { - struct bhead *ba; - - ba = BH(((char *) b) + b->bh.bsize); - assert(ba->prevfree == b->bh.bsize); - - /* The buffer isn't big enough to split. Give the whole - shebang to the caller and remove it from the free list. */ - - assert(b->ql.blink->ql.flink == b); - assert(b->ql.flink->ql.blink == b); - b->ql.blink->ql.flink = b->ql.flink; - b->ql.flink->ql.blink = b->ql.blink; - -#ifdef BufStats - totalloc += b->bh.bsize; - numget++; /* Increment number of bget() calls */ -#endif - /* Negate size to mark buffer allocated. */ - b->bh.bsize = -(b->bh.bsize); - - /* Zero the back pointer in the next buffer in memory - to indicate that this buffer is allocated. */ - ba->prevfree = 0; - - /* Give user buffer starting at queue links. */ - buf = (void *) &(b->ql); - return buf; - } - } - b = b->ql.flink; /* Link to next buffer */ - } -#ifdef BECtl - - /* We failed to find a buffer. If there's a compact function - defined, notify it of the size requested. If it returns - TRUE, try the allocation again. */ - - if ((compfcn == NULL) || (!(*compfcn)(size, ++compactseq))) { - break; - } - } - - /* No buffer available with requested size free. */ - - /* Don't give up yet -- look in the reserve supply. */ - - if (acqfcn != NULL) { - if (size > exp_incr - sizeof(struct bhead)) { - - /* Request is too large to fit in a single expansion - block. Try to satisy it by a direct buffer acquisition. */ - - struct bdhead *bdh; - - size += sizeof(struct bdhead) - sizeof(struct bhead); - if ((bdh = BDH((*acqfcn)((bufsize) size))) != NULL) { - - /* Mark the buffer special by setting the size field - of its header to zero. */ - bdh->bh.bsize = 0; - bdh->bh.prevfree = 0; - bdh->tsize = size; -#ifdef BufStats - totalloc += size; - numget++; /* Increment number of bget() calls */ - numdget++; /* Direct bget() call count */ -#endif - buf = (void *) (bdh + 1); - - /*only let this happen once */ - printf("%s %d memory request exceeds block size %ld %ld\n",__FILE__,__LINE__, - size,exp_incr); - exp_incr = size+sizeof(struct bhead); - - return buf; - } - - } else { - - /* Try to obtain a new expansion block */ - - void *newpool; - - if ((newpool = (*acqfcn)((bufsize) exp_incr)) != NULL) { - bpool(newpool, exp_incr); - buf = bget(requested_size); /* This can't, I say, can't - get into a loop. */ - // printf("%s %d new memory block of size %d\n",__FILE__,__LINE__,exp_incr); - return buf; - } - } - } - - /* Still no buffer available */ - -#endif /* BECtl */ - - return NULL; -} - -/* BGETZ -- Allocate a buffer and clear its contents to zero. We clear - the entire contents of the buffer to zero, not just the - region requested by the caller. */ - -void *bgetz(size) -bufsize size; -{ - char *buf = (char *) bget(size); - - if (buf != NULL) { - struct bhead *b; - bufsize rsize; - - b = BH(buf - sizeof(struct bhead)); - rsize = -(b->bsize); - if (rsize == 0) { - struct bdhead *bd; - - bd = BDH(buf - sizeof(struct bdhead)); - rsize = bd->tsize - sizeof(struct bdhead); - } else { - rsize -= sizeof(struct bhead); - } - assert(rsize >= size); - V memset(buf, 0, (MemSize) rsize); - } - return ((void *) buf); -} - -/* BGETR -- Reallocate a buffer. This is a minimal implementation, - simply in terms of brel() and bget(). It could be - enhanced to allow the buffer to grow into adjacent free - blocks and to avoid moving data unnecessarily. */ - -void *bgetr(buf, size) -void *buf; -bufsize size; -{ - void *nbuf; - bufsize osize; /* Old size of buffer */ - struct bhead *b; - -#if PIO_USE_MALLOC - return(realloc(buf, size)); -#endif - if ((nbuf = bget(size)) == NULL) { /* Acquire new buffer */ - return NULL; - } - if (buf == NULL) { - return nbuf; - } - b = BH(((char *) buf) - sizeof(struct bhead)); - osize = -b->bsize; -#ifdef BECtl - if (osize == 0) { - /* Buffer acquired directly through acqfcn. */ - struct bdhead *bd; - - bd = BDH(((char *) buf) - sizeof(struct bdhead)); - osize = bd->tsize - sizeof(struct bdhead); - } else -#endif - osize -= sizeof(struct bhead); - assert(osize > 0); - V memcpy((char *) nbuf, (char *) buf, /* Copy the data */ - (MemSize) ((size < osize) ? size : osize)); - brel(buf); - return nbuf; -} - -/* BREL -- Release a buffer. */ - -void brel(buf) -void *buf; -{ - struct bfhead *b, *bn; - -#if PIO_USE_MALLOC - // printf("bget free %d %x\n",__LINE__,buf); - free(buf); - return; -#endif - - - if(buf==NULL) return; /* allow for null buffer */ - - b = BFH(((char *) buf) - sizeof(struct bhead)); -#ifdef BufStats - numrel++; /* Increment number of brel() calls */ -#endif - assert(buf != NULL); - -#ifdef BECtl - if (b->bh.bsize == 0) { /* Directly-acquired buffer? */ - struct bdhead *bdh; - - bdh = BDH(((char *) buf) - sizeof(struct bdhead)); - assert(b->bh.prevfree == 0); -#ifdef BufStats - totalloc -= bdh->tsize; - assert(totalloc >= 0); - numdrel++; /* Number of direct releases */ -#endif /* BufStats */ -#ifdef FreeWipe - V memset((char *) buf, 0x55, - (MemSize) (bdh->tsize - sizeof(struct bdhead))); -#endif /* FreeWipe */ - assert(relfcn != NULL); - (*relfcn)((void *) bdh); /* Release it directly. */ - return; - } -#endif /* BECtl */ - - /* Buffer size must be negative, indicating that the buffer is - allocated. */ - - if (b->bh.bsize >= 0) { - bn = NULL; - } - assert(b->bh.bsize < 0); - - /* Back pointer in next buffer must be zero, indicating the - same thing: */ - - assert(BH((char *) b - b->bh.bsize)->prevfree == 0); - -#ifdef BufStats - totalloc += b->bh.bsize; - assert(totalloc >= 0); -#endif - - /* If the back link is nonzero, the previous buffer is free. */ - - if (b->bh.prevfree != 0) { - - /* The previous buffer is free. Consolidate this buffer with it - by adding the length of this buffer to the previous free - buffer. Note that we subtract the size in the buffer being - released, since it's negative to indicate that the buffer is - allocated. */ - - register bufsize size = b->bh.bsize; - - /* Make the previous buffer the one we're working on. */ - assert(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree); - b = BFH(((char *) b) - b->bh.prevfree); - b->bh.bsize -= size; - } else { - - /* The previous buffer isn't allocated. Insert this buffer - on the free list as an isolated free block. */ - - assert(freelist.ql.blink->ql.flink == &freelist); - assert(freelist.ql.flink->ql.blink == &freelist); - b->ql.flink = &freelist; - b->ql.blink = freelist.ql.blink; - freelist.ql.blink = b; - b->ql.blink->ql.flink = b; - b->bh.bsize = -b->bh.bsize; - } - - /* Now we look at the next buffer in memory, located by advancing from - the start of this buffer by its size, to see if that buffer is - free. If it is, we combine this buffer with the next one in - memory, dechaining the second buffer from the free list. */ - - bn = BFH(((char *) b) + b->bh.bsize); - if (bn->bh.bsize > 0) { - - /* The buffer is free. Remove it from the free list and add - its size to that of our buffer. */ - - assert(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize); - assert(bn->ql.blink->ql.flink == bn); - assert(bn->ql.flink->ql.blink == bn); - bn->ql.blink->ql.flink = bn->ql.flink; - bn->ql.flink->ql.blink = bn->ql.blink; - b->bh.bsize += bn->bh.bsize; - - /* Finally, advance to the buffer that follows the newly - consolidated free block. We must set its backpointer to the - head of the consolidated free block. We know the next block - must be an allocated block because the process of recombination - guarantees that two free blocks will never be contiguous in - memory. */ - - bn = BFH(((char *) b) + b->bh.bsize); - } -#ifdef FreeWipe - V memset(((char *) b) + sizeof(struct bfhead), 0x55, - (MemSize) (b->bh.bsize - sizeof(struct bfhead))); -#endif - assert(bn->bh.bsize < 0); - - /* The next buffer is allocated. Set the backpointer in it to point - to this buffer; the previous free buffer in memory. */ - - bn->bh.prevfree = b->bh.bsize; - -#ifdef BECtl - - /* If a block-release function is defined, and this free buffer - constitutes the entire block, release it. Note that pool_len - is defined in such a way that the test will fail unless all - pool blocks are the same size. */ - - if (relfcn != NULL && - ((bufsize) b->bh.bsize) == (pool_len - sizeof(struct bhead))) { - - assert(b->bh.prevfree == 0); - assert(BH((char *) b + b->bh.bsize)->bsize == ESent); - assert(BH((char *) b + b->bh.bsize)->prevfree == b->bh.bsize); - /* Unlink the buffer from the free list */ - b->ql.blink->ql.flink = b->ql.flink; - b->ql.flink->ql.blink = b->ql.blink; - // printf("%s %d calling direct release for %x\n",__FILE__,__LINE__,b); - (*relfcn)(b); - // printf("%s %d completed direct release \n",__FILE__,__LINE__); -#ifdef BufStats - numprel++; /* Nr of expansion block releases */ - numpblk--; /* Total number of blocks */ - assert(numpblk == numpget - numprel); -#endif /* BufStats */ - } -#endif /* BECtl */ -} - -#ifdef BECtl - -/* BECTL -- Establish automatic pool expansion control */ - -void bectl(compact, acquire, release, pool_incr) - int (*compact) _((bufsize sizereq, int sequence)); -void *(*acquire) _((bufsize size)); -void (*release) _((void *buf)); -bufsize pool_incr; -{ - compfcn = compact; - acqfcn = acquire; - relfcn = release; - exp_incr = pool_incr; -} -#endif - -/* BPOOL -- Add a region of memory to the buffer pool. */ - -void bpool(buf, len) -void *buf; -bufsize len; -{ - struct bfhead *b = BFH(buf); - struct bhead *bn; - -#ifdef SizeQuant - len &= ~(SizeQuant - 1); -#endif -#ifdef BECtl - if (pool_len == 0) { - pool_len = len; - } else if (len != pool_len) { - pool_len = -1; - } -#ifdef BufStats - numpget++; /* Number of block acquisitions */ - numpblk++; /* Number of blocks total */ - assert(numpblk == numpget - numprel); -#endif /* BufStats */ -#endif /* BECtl */ - - /* Since the block is initially occupied by a single free buffer, - it had better not be (much) larger than the largest buffer - whose size we can store in bhead.bsize. */ - - assert(len - sizeof(struct bhead) <= -((bufsize) ESent + 1)); - - /* Clear the backpointer at the start of the block to indicate that - there is no free block prior to this one. That blocks - recombination when the first block in memory is released. */ - - b->bh.prevfree = 0; - - /* Chain the new block to the free list. */ - - assert(freelist.ql.blink->ql.flink == &freelist); - assert(freelist.ql.flink->ql.blink == &freelist); - b->ql.flink = &freelist; - b->ql.blink = freelist.ql.blink; - freelist.ql.blink = b; - b->ql.blink->ql.flink = b; - - /* Create a dummy allocated buffer at the end of the pool. This dummy - buffer is seen when a buffer at the end of the pool is released and - blocks recombination of the last buffer with the dummy buffer at - the end. The length in the dummy buffer is set to the largest - negative number to denote the end of the pool for diagnostic - routines (this specific value is not counted on by the actual - allocation and release functions). */ - - len -= sizeof(struct bhead); - b->bh.bsize = (bufsize) len; -#ifdef FreeWipe - V memset(((char *) b) + sizeof(struct bfhead), 0x55, - (MemSize) (len - sizeof(struct bfhead))); -#endif - bn = BH(((char *) b) + len); - bn->prevfree = (bufsize) len; - /* Definition of ESent assumes two's complement! */ - assert((~0) == -1); - bn->bsize = ESent; -} - -#ifdef BufStats - -void bfreespace(bufsize *totfree, bufsize *maxfree) -{ - struct bfhead *b = freelist.ql.flink; - *totfree = 0; - *maxfree = -1; - while (b != &freelist) { - assert(b->bh.bsize > 0); - *totfree += b->bh.bsize; - if (b->bh.bsize > *maxfree) { - *maxfree = b->bh.bsize; - } - b = b->ql.flink; /* Link to next buffer */ - } -} - -/* BSTATS -- Return buffer allocation free space statistics. */ - -void bstats(curalloc, totfree, maxfree, nget, nrel) - bufsize *curalloc, *totfree, *maxfree; -long *nget, *nrel; -{ - *nget = numget; - *nrel = numrel; - *curalloc = totalloc; - bfreespace(totfree, maxfree); -} - -#ifdef BECtl - -/* BSTATSE -- Return extended statistics */ - -void bstatse(pool_incr, npool, npget, nprel, ndget, ndrel) -bufsize *pool_incr; -long *npool, *npget, *nprel, *ndget, *ndrel; -{ - *pool_incr = (pool_len < 0) ? -exp_incr : exp_incr; - *npool = numpblk; - *npget = numpget; - *nprel = numprel; - *ndget = numdget; - *ndrel = numdrel; -} -#endif /* BECtl */ -#endif /* BufStats */ - -#ifdef DumpData - -/* BUFDUMP -- Dump the data in a buffer. This is called with the user - data pointer, and backs up to the buffer header. It will - dump either a free block or an allocated one. */ - -void bufdump(buf) -void *buf; -{ - struct bfhead *b; - unsigned char *bdump; - bufsize bdlen; - - b = BFH(((char *) buf) - sizeof(struct bhead)); - assert(b->bh.bsize != 0); - if (b->bh.bsize < 0) { - bdump = (unsigned char *) buf; - bdlen = (-b->bh.bsize) - sizeof(struct bhead); - } else { - bdump = (unsigned char *) (((char *) b) + sizeof(struct bfhead)); - bdlen = b->bh.bsize - sizeof(struct bfhead); - } - - while (bdlen > 0) { - int i, dupes = 0; - bufsize l = bdlen; - char bhex[50], bascii[20]; - - if (l > 16) { - l = 16; - } - - for (i = 0; i < l; i++) { - V sprintf(bhex + i * 3, "%02X ", bdump[i]); - bascii[i] = isprint(bdump[i]) ? bdump[i] : ' '; - } - bascii[i] = 0; - V printf("%-48s %s\n", bhex, bascii); - bdump += l; - bdlen -= l; - while ((bdlen > 16) && (memcmp((char *) (bdump - 16), - (char *) bdump, 16) == 0)) { - dupes++; - bdump += 16; - bdlen -= 16; - } - if (dupes > 1) { - V printf( - " (%d lines [%d bytes] identical to above line skipped)\n", - dupes, dupes * 16); - } else if (dupes == 1) { - bdump -= 16; - bdlen += 16; - } - } -} -#endif - -#ifdef BufDump - -/* BPOOLD -- Dump a buffer pool. The buffer headers are always listed. - If DUMPALLOC is nonzero, the contents of allocated buffers - are dumped. If DUMPFREE is nonzero, free blocks are - dumped as well. If FreeWipe checking is enabled, free - blocks which have been clobbered will always be dumped. */ - -void bpoold(buf, dumpalloc, dumpfree) -void *buf; -int dumpalloc, dumpfree; -{ - struct bfhead *b = BFH(buf); - - while (b->bh.bsize != ESent) { - bufsize bs = b->bh.bsize; - - if (bs < 0) { - bs = -bs; - V printf("Allocated buffer: size %6ld bytes.\n", (long) bs); - if (dumpalloc) { - bufdump((void *) (((char *) b) + sizeof(struct bhead))); - } - } else { - char *lerr = ""; - - assert(bs > 0); - if ((b->ql.blink->ql.flink != b) || - (b->ql.flink->ql.blink != b)) { - lerr = " (Bad free list links)"; - } - V printf("Free block: size %6ld bytes.%s\n", - (long) bs, lerr); -#ifdef FreeWipe - lerr = ((char *) b) + sizeof(struct bfhead); - if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) || - (memcmp(lerr, lerr + 1, - (MemSize) (bs - (sizeof(struct bfhead) + 1))) != 0))) { - V printf( - "(Contents of above free block have been overstored.)\n"); - bufdump((void *) (((char *) b) + sizeof(struct bhead))); - } else -#endif - if (dumpfree) { - bufdump((void *) (((char *) b) + sizeof(struct bhead))); - } - } - b = BFH(((char *) b) + bs); - } -} -#endif /* BufDump */ - -#ifdef BufValid - -/* BPOOLV -- Validate a buffer pool. If NDEBUG isn't defined, - any error generates an assertion failure. */ - -int bpoolv(buf) -void *buf; -{ - struct bfhead *b = BFH(buf); - - while (b->bh.bsize != ESent) { - bufsize bs = b->bh.bsize; - - if (bs < 0) { - bs = -bs; - } else { - char *lerr = ""; - - assert(bs > 0); - if (bs <= 0) { - return 0; - } - if ((b->ql.blink->ql.flink != b) || - (b->ql.flink->ql.blink != b)) { - V printf("Free block: size %6ld bytes. (Bad free list links)\n", - (long) bs); - assert(0); - return 0; - } -#ifdef FreeWipe - lerr = ((char *) b) + sizeof(struct bfhead); - if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) || - (memcmp(lerr, lerr + 1, - (MemSize) (bs - (sizeof(struct bfhead) + 1))) != 0))) { - V printf( - "(Contents of above free block have been overstored.)\n"); - bufdump((void *) (((char *) b) + sizeof(struct bhead))); - assert(0); - return 0; - } -#endif - } - b = BFH(((char *) b) + bs); - } - return 1; -} -#endif /* BufValid */ - -/***********************\ - * * - * Built-in test program * - * * - \***********************/ - -#ifdef TestProg - -#define Repeatable 1 /* Repeatable pseudorandom sequence */ - /* If Repeatable is not defined, a - time-seeded pseudorandom sequence - is generated, exercising BGET with - a different pattern of calls on each - run. */ -#define OUR_RAND /* Use our own built-in version of - rand() to guarantee the test is - 100% repeatable. */ - -#ifdef BECtl -#define PoolSize 300000 /* Test buffer pool size */ -#else -#define PoolSize 50000 /* Test buffer pool size */ -#endif -#define ExpIncr 32768 /* Test expansion block size */ -#define CompactTries 10 /* Maximum tries at compacting */ - -#define dumpAlloc 0 /* Dump allocated buffers ? */ -#define dumpFree 0 /* Dump free buffers ? */ - -#ifndef Repeatable -extern long time(); -#endif - -extern char *malloc(); -extern int free _((char *)); - -static char *bchain = NULL; /* Our private buffer chain */ -static char *bp = NULL; /* Our initial buffer pool */ - -#include - -#ifdef OUR_RAND - -static unsigned long int next = 1; - -/* Return next random integer */ - -int rand() -{ - next = next * 1103515245L + 12345; - return (unsigned int) (next / 65536L) % 32768L; -} - -/* Set seed for random generator */ - -void srand(seed) -unsigned int seed; -{ - next = seed; -} -#endif - -/* STATS -- Edit statistics returned by bstats() or bstatse(). */ - -static void stats(when) -char *when; -{ - bufsize cural, totfree, maxfree; - long nget, nfree; -#ifdef BECtl - bufsize pincr; - long totblocks, npget, nprel, ndget, ndrel; -#endif - - bstats(&cural, &totfree, &maxfree, &nget, &nfree); - V printf( - "%s: %ld gets, %ld releases. %ld in use, %ld free, largest = %ld\n", - when, nget, nfree, (long) cural, (long) totfree, (long) maxfree); -#ifdef BECtl - bstatse(&pincr, &totblocks, &npget, &nprel, &ndget, &ndrel); - V printf( - " Blocks: size = %ld, %ld (%ld bytes) in use, %ld gets, %ld frees\n", - (long)pincr, totblocks, pincr * totblocks, npget, nprel); - V printf(" %ld direct gets, %ld direct frees\n", ndget, ndrel); -#endif /* BECtl */ -} - -#ifdef BECtl -static int protect = 0; /* Disable compaction during bgetr() */ - -/* BCOMPACT -- Compaction call-back function. */ - -static int bcompact(bsize, seq) -bufsize bsize; -int seq; -{ -#ifdef CompactTries - char *bc = bchain; - int i = rand() & 0x3; - -#ifdef COMPACTRACE - V printf("Compaction requested. %ld bytes needed, sequence %d.\n", - (long) bsize, seq); -#endif - - if (protect || (seq > CompactTries)) { -#ifdef COMPACTRACE - V printf("Compaction gave up.\n"); -#endif - return 0; - } - - /* Based on a random cast, release a random buffer in the list - of allocated buffers. */ - - while (i > 0 && bc != NULL) { - bc = *((char **) bc); - i--; - } - if (bc != NULL) { - char *fb; - - fb = *((char **) bc); - if (fb != NULL) { - *((char **) bc) = *((char **) fb); - brel((void *) fb); - return 1; - } - } - -#ifdef COMPACTRACE - V printf("Compaction bailed out.\n"); -#endif -#endif /* CompactTries */ - return 0; -} - -/* BEXPAND -- Expand pool call-back function. */ - -static void *bexpand(size) -bufsize size; -{ - void *np = NULL; - bufsize cural, totfree, maxfree; - long nget, nfree; - - /* Don't expand beyond the total allocated size given by PoolSize. */ - - bstats(&cural, &totfree, &maxfree, &nget, &nfree); - - if (cural < PoolSize) { - np = (void *) malloc((unsigned) size); - } -#ifdef EXPTRACE - V printf("Expand pool by %ld -- %s.\n", (long) size, - np == NULL ? "failed" : "succeeded"); -#endif - return np; -} - -/* BSHRINK -- Shrink buffer pool call-back function. */ - -static void bshrink(buf) -void *buf; -{ - if (((char *) buf) == bp) { -#ifdef EXPTRACE - V printf("Initial pool released.\n"); -#endif - bp = NULL; - } -#ifdef EXPTRACE - V printf("Shrink pool.\n"); -#endif - free((char *) buf); -} - -#endif /* BECtl */ - -/* Restrict buffer requests to those large enough to contain our pointer and - small enough for the CPU architecture. */ - -static bufsize blimit(bs) -bufsize bs; -{ - if (bs < sizeof(char *)) { - bs = sizeof(char *); - } - - /* This is written out in this ugly fashion because the - cool expression in sizeof(int) that auto-configured - to any length int befuddled some compilers. */ - - if (sizeof(int) == 2) { - if (bs > 32767) { - bs = 32767; - } - } else { - if (bs > 200000) { - bs = 200000; - } - } - return bs; -} - -int main() -{ - int i; - double x; - - /* Seed the random number generator. If Repeatable is defined, we - always use the same seed. Otherwise, we seed from the clock to - shake things up from run to run. */ - -#ifdef Repeatable - V srand(1234); -#else - V srand((int) time((long *) NULL)); -#endif - - /* Compute x such that pow(x, p) ranges between 1 and 4*ExpIncr as - p ranges from 0 to ExpIncr-1, with a concentration in the lower - numbers. */ - - x = 4.0 * ExpIncr; - x = log(x); - x = exp(log(4.0 * ExpIncr) / (ExpIncr - 1.0)); - -#ifdef BECtl - bectl(bcompact, bexpand, bshrink, (bufsize) ExpIncr); - bp = malloc(ExpIncr); - assert(bp != NULL); - bpool((void *) bp, (bufsize) ExpIncr); -#else - bp = malloc(PoolSize); - assert(bp != NULL); - bpool((void *) bp, (bufsize) PoolSize); -#endif - - stats("Create pool"); - V bpoolv((void *) bp); - bpoold((void *) bp, dumpAlloc, dumpFree); - - for (i = 0; i < TestProg; i++) { - char *cb; - bufsize bs = pow(x, (double) (rand() & (ExpIncr - 1))); - - assert(bs <= (((bufsize) 4) * ExpIncr)); - bs = blimit(bs); - if (rand() & 0x400) { - cb = (char *) bgetz(bs); - } else { - cb = (char *) bget(bs); - } - if (cb == NULL) { -#ifdef EasyOut - break; -#else - char *bc = bchain; - - if (bc != NULL) { - char *fb; - - fb = *((char **) bc); - if (fb != NULL) { - *((char **) bc) = *((char **) fb); - brel((void *) fb); - } - continue; - } -#endif - } - *((char **) cb) = (char *) bchain; - bchain = cb; - - /* Based on a random cast, release a random buffer in the list - of allocated buffers. */ - - if ((rand() & 0x10) == 0) { - char *bc = bchain; - int i = rand() & 0x3; - - while (i > 0 && bc != NULL) { - bc = *((char **) bc); - i--; - } - if (bc != NULL) { - char *fb; - - fb = *((char **) bc); - if (fb != NULL) { - *((char **) bc) = *((char **) fb); - brel((void *) fb); - } - } - } - - /* Based on a random cast, reallocate a random buffer in the list - to a random size */ - - if ((rand() & 0x20) == 0) { - char *bc = bchain; - int i = rand() & 0x3; - - while (i > 0 && bc != NULL) { - bc = *((char **) bc); - i--; - } - if (bc != NULL) { - char *fb; - - fb = *((char **) bc); - if (fb != NULL) { - char *newb; - - bs = pow(x, (double) (rand() & (ExpIncr - 1))); - bs = blimit(bs); -#ifdef BECtl - protect = 1; /* Protect against compaction */ -#endif - newb = (char *) bgetr((void *) fb, bs); -#ifdef BECtl - protect = 0; -#endif - if (newb != NULL) { - *((char **) bc) = newb; - } - } - } - } - } - stats("\nAfter allocation"); - if (bp != NULL) { - V bpoolv((void *) bp); - bpoold((void *) bp, dumpAlloc, dumpFree); - } - - while (bchain != NULL) { - char *buf = bchain; - - bchain = *((char **) buf); - brel((void *) buf); - } - stats("\nAfter release"); -#ifndef BECtl - if (bp != NULL) { - V bpoolv((void *) bp); - bpoold((void *) bp, dumpAlloc, dumpFree); - } -#endif - - return 0; -} -#endif diff --git a/src/clib/bget.h b/src/clib/bget.h deleted file mode 100644 index 2b5be7dcdc0..00000000000 --- a/src/clib/bget.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - - Interface definitions for bget.c, the memory management package. - -*/ -#ifndef _BGET_H_ -#define _BGET_H_ - -/* in PIO we use DEBUG bget uses NDEBUG */ -//#ifndef DEBUG -//#undef NDEBUG -//#endif - -#ifndef _ -#ifdef PROTOTYPES -#define _(x) x /* If compiler knows prototypes */ -#else -#define _(x) () /* It it doesn't */ -#endif /* PROTOTYPES */ -#endif - -typedef long bufsize; -void bpool _((void *buffer, bufsize len)); -void *bget _((bufsize size)); -void *bgetz _((bufsize size)); -void *bgetr _((void *buffer, bufsize newsize)); -void brel _((void *buf)); -void bectl _((int (*compact)(bufsize sizereq, int sequence), - void *(*acquire)(bufsize size), - void (*release)(void *buf), bufsize pool_incr)); -void bstats _((bufsize *curalloc, bufsize *totfree, bufsize *maxfree, - long *nget, long *nrel)); -void bstatse _((bufsize *pool_incr, long *npool, long *npget, - long *nprel, long *ndget, long *ndrel)); -void bufdump _((void *buf)); -void bpoold _((void *pool, int dumpalloc, int dumpfree)); -int bpoolv _((void *pool)); -void bpoolrelease _(); -void bfreespace _((bufsize *maxfree, bufsize *totfree)); - -#endif diff --git a/src/clib/pio_darray.c b/src/clib/pio_darray.c index 82d57b38514..4ecabb2fcce 100644 --- a/src/clib/pio_darray.c +++ b/src/clib/pio_darray.c @@ -274,7 +274,7 @@ PIOc_write_darray_multi(int ncid, const int *varids, int ioid, int nvars, if (rlen > 0) { /* Allocate memory for the buffer for all vars/records. */ - if (!(file->iobuf = bget(iodesc->mpitype_size * (size_t)rlen))) + if (!(file->iobuf = malloc(iodesc->mpitype_size * (size_t)rlen))) return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); PLOG((3, "allocated %lld bytes for variable buffer", (size_t)rlen * iodesc->mpitype_size)); @@ -294,7 +294,7 @@ PIOc_write_darray_multi(int ncid, const int *varids, int ioid, int nvars, /* this assures that iobuf is allocated on all iotasks thus assuring that the flush_output_buffer call above is called collectively (from all iotasks) */ - if (!(file->iobuf = bget(1))) + if (!(file->iobuf = malloc(1))) return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); PLOG((3, "allocated token for variable buffer")); } @@ -341,7 +341,7 @@ PIOc_write_darray_multi(int ncid, const int *varids, int ioid, int nvars, if (file->iobuf) { PLOG((3,"freeing variable buffer in pio_darray")); - brel(file->iobuf); + free(file->iobuf); file->iobuf = NULL; } } @@ -365,9 +365,9 @@ PIOc_write_darray_multi(int ncid, const int *varids, int ioid, int nvars, /* Get a buffer. */ if (ios->io_rank == 0) - vdesc0->fillbuf = bget(iodesc->maxholegridsize * iodesc->mpitype_size * nvars); + vdesc0->fillbuf = malloc(iodesc->maxholegridsize * iodesc->mpitype_size * nvars); else if (iodesc->holegridsize > 0) - vdesc0->fillbuf = bget(iodesc->holegridsize * iodesc->mpitype_size * nvars); + vdesc0->fillbuf = malloc(iodesc->holegridsize * iodesc->mpitype_size * nvars); /* copying the fill value into the data buffer for the box * rearranger. This will be overwritten with data where @@ -403,7 +403,7 @@ PIOc_write_darray_multi(int ncid, const int *varids, int ioid, int nvars, /* Free resources. */ if (vdesc0->fillbuf) { - brel(vdesc0->fillbuf); + free(vdesc0->fillbuf); vdesc0->fillbuf = NULL; } } @@ -645,12 +645,7 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra void *bufptr; /* A data buffer. */ wmulti_buffer *wmb; /* The write multi buffer for one or more vars. */ int needsflush = 0; /* True if we need to flush buffer. */ -#if PIO_USE_MALLOC void *realloc_data = NULL; -#else - bufsize totfree; /* Amount of free space in the buffer. */ - bufsize maxfree; /* Max amount of free space in buffer. */ -#endif int hashid; int mpierr = MPI_SUCCESS; /* Return code from MPI functions. */ int ierr = PIO_NOERR; /* Return code. */ @@ -718,7 +713,7 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra if (!wmb) { /* Allocate a buffer. */ - if (!(wmb = bget((bufsize)sizeof(wmulti_buffer)))) + if (!(wmb = malloc(sizeof(wmulti_buffer)))) return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); /* Set pointer to newly allocated buffer and initialize.*/ @@ -735,7 +730,7 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra } PLOG((2, "wmb->num_arrays = %d arraylen = %d iodesc->mpitype_size = %d\n", wmb->num_arrays, arraylen, iodesc->mpitype_size)); -#if PIO_USE_MALLOC + /* Try realloc first and call flush if realloc fails. */ if (arraylen > 0) { @@ -753,15 +748,7 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra PLOG((2, "realloc attempted to get %ld bytes for data, needsflush %d", data_size, needsflush)); } -#else - /* Find out how much free, contiguous space is available. */ - bfreespace(&totfree, &maxfree); - - /* maxfree is the available memory. If that is < 10% greater than - * the size of the current request needsflush is true. */ - if (needsflush == 0) - needsflush = (maxfree <= 1.1 * (1 + wmb->num_arrays) * arraylen * iodesc->mpitype_size); -#endif + /* the limit of data_size < INT_MAX is due to a bug in ROMIO which limits the size of contiguous data to INT_MAX, a fix has been proposed in https://github.com/pmodels/mpich/pull/2888 */ @@ -779,16 +766,6 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra /* Flush data if needed. */ if (needsflush > 0) { -#if !PIO_USE_MALLOC -#ifdef PIO_ENABLE_LOGGING - /* Collect a debug report about buffer. */ - cn_buffer_report(ios, true); - PLOG((2, "maxfree = %ld wmb->num_arrays = %d (1 + wmb->num_arrays) *" - " arraylen * iodesc->mpitype_size = %ld totfree = %ld\n", maxfree, wmb->num_arrays, - (1 + wmb->num_arrays) * arraylen * iodesc->mpitype_size, totfree)); -#endif /* PIO_ENABLE_LOGGING */ -#endif /* !PIO_USE_MALLOC */ - /* If needsflush == 2 flush to disk otherwise just flush to io * node. This will cause PIOc_write_darray_multi() to be * called. */ @@ -796,7 +773,6 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra return pio_err(ios, file, ierr, __FILE__, __LINE__); } -#if PIO_USE_MALLOC /* Try realloc again if there is a flush. */ if (arraylen > 0 && needsflush > 0) { @@ -804,26 +780,17 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); PLOG((2, "after a flush, realloc got %ld bytes for data", (1 + wmb->num_arrays) * arraylen * iodesc->mpitype_size)); } -#else - /* Get memory for data. */ - if (arraylen > 0) - { - if (!(wmb->data = bgetr(wmb->data, (1 + wmb->num_arrays) * arraylen * iodesc->mpitype_size))) - return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); - PLOG((2, "got %ld bytes for data", (1 + wmb->num_arrays) * arraylen * iodesc->mpitype_size)); - } -#endif /* vid is an array of variable ids in the wmb list, grow the list * and add the new entry. */ - if (!(wmb->vid = bgetr(wmb->vid, sizeof(int) * (1 + wmb->num_arrays)))) + if (!(wmb->vid = realloc(wmb->vid, sizeof(int) * (1 + wmb->num_arrays)))) return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); /* wmb->frame is the record number, we assume that the variables * in the wmb list may not all have the same unlimited dimension * value although they usually do. */ if (vdesc->record >= 0) - if (!(wmb->frame = bgetr(wmb->frame, sizeof(int) * (1 + wmb->num_arrays)))) + if (!(wmb->frame = realloc(wmb->frame, sizeof(int) * (1 + wmb->num_arrays)))) return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); /* If we need a fill value, get it. If we are using the subset @@ -832,7 +799,7 @@ PIOc_write_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, void *arra if (iodesc->needsfill) { /* Get memory to hold fill value. */ - if (!(wmb->fillvalue = bgetr(wmb->fillvalue, iodesc->mpitype_size * (1 + wmb->num_arrays)))) + if (!(wmb->fillvalue = realloc(wmb->fillvalue, iodesc->mpitype_size * (1 + wmb->num_arrays)))) return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); memcpy((char *)wmb->fillvalue + iodesc->mpitype_size * wmb->num_arrays, @@ -901,6 +868,8 @@ PIOc_read_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, size_t rlen = 0; /* the length of data in iobuf. */ void *tmparray; /* unsorted copy of array buf if required */ int mpierr = MPI_SUCCESS, mpierr2; /* Return code from MPI function calls. */ + void *fillvalue = NULL; + int pio_type; int ierr; /* Return code. */ #ifdef USE_MPE @@ -961,7 +930,7 @@ PIOc_read_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, /* Allocate a buffer for one record. */ if (ios->ioproc && rlen > 0) - if (!(iobuf = bget(iodesc->mpitype_size * rlen))) + if (!(iobuf = malloc(iodesc->mpitype_size * rlen))) return pio_err(ios, file, PIO_ENOMEM, __FILE__, __LINE__); /* Call the correct darray read function based on iotype. */ @@ -988,23 +957,34 @@ PIOc_read_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, { if (!(tmparray = malloc(iodesc->piotype_size * iodesc->maplen))) return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); - if(iodesc->piotype_size == 1){ - for (int m = 0; m < iodesc->maplen; m++) - ((signed char *)array)[m] = -1; - }else if(iodesc->piotype_size == 2){ - for (int m = 0; m < iodesc->maplen; m++) - ((short *)array)[m] = -1; - }else if(iodesc->piotype_size == 4){ - for (int m = 0; m < iodesc->maplen; m++) - ((int *)array)[m] = -1; - }else if(iodesc->piotype_size == 8){ - for (int m = 0; m < iodesc->maplen; m++) - ((double *)array)[m] = -1; - } } else tmparray = array; + /* prefill the output array with 0 then overwrite from iobuf */ + /* switch(iodesc->piotype) + { + case PIO_SHORT: + for(int i=0; imaplen; i++) + ((short *) array)[i] = (short) 0; + break; + case PIO_INT: + for(int i=0; imaplen; i++) + ((int *) array)[i] = (int) 0; + break; + case PIO_FLOAT: + for(int i=0; imaplen; i++) + ((float *) array)[i] = (float) 0; + break; + case PIO_DOUBLE: + for(int i=0; imaplen; i++) + ((double *) array)[i] = (double) 0; + break; + default: + return PIO_EBADTYPE; + } + */ + /* Rearrange the data. */ if ((ierr = rearrange_io2comp(ios, iodesc, iobuf, tmparray))) return pio_err(ios, file, ierr, __FILE__, __LINE__); @@ -1018,7 +998,7 @@ PIOc_read_darray(int ncid, int varid, int ioid, PIO_Offset arraylen, /* Free the buffer. */ if (rlen > 0) - brel(iobuf); + free(iobuf); #ifdef USE_MPE pio_stop_mpe_log(DARRAY_READ, __func__); diff --git a/src/clib/pio_darray_int.c b/src/clib/pio_darray_int.c index 4a959ba6b6b..a7f4899ac88 100644 --- a/src/clib/pio_darray_int.c +++ b/src/clib/pio_darray_int.c @@ -23,7 +23,7 @@ extern PIO_Offset pio_buffer_size_limit; /** Initial size of compute buffer. */ -bufsize pio_cnbuffer_limit = 33554432; +long pio_cnbuffer_limit = 33554432; /** Global buffer pool pointer. */ extern void *CN_bpool; @@ -46,40 +46,6 @@ bpool_free(void *p) } } -/** - * Initialize the compute buffer to size pio_cnbuffer_limit. - * - * This routine initializes the compute buffer pool if the bget memory - * management is used. If malloc is used (that is, PIO_USE_MALLOC is - * non zero), this function does nothing. - * - * @param ios pointer to the iosystem descriptor which will use the - * new buffer. - * @returns 0 for success, error code otherwise. - * @author Jim Edwards - */ -int -compute_buffer_init(iosystem_desc_t *ios) -{ -#if !PIO_USE_MALLOC - - if (!CN_bpool) - { - if (!(CN_bpool = malloc(pio_cnbuffer_limit))) - return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); - - bpool(CN_bpool, pio_cnbuffer_limit); - if (!CN_bpool) - return pio_err(ios, NULL, PIO_ENOMEM, __FILE__, __LINE__); - - bectl(NULL, malloc, bpool_free, pio_cnbuffer_limit); - } -#endif - PLOG((2, "compute_buffer_init complete")); - - return PIO_NOERR; -} - #if USE_VARD /** * Get the length of dimension 0. @@ -1339,8 +1305,8 @@ pio_read_darray_nc(file_desc_t *file, io_desc_t *iodesc, int vid, void *iobuf) if (tmp_bufsize > 0) { - startlist[rrlen] = bget(fndims * sizeof(PIO_Offset)); - countlist[rrlen] = bget(fndims * sizeof(PIO_Offset)); + startlist[rrlen] = malloc(fndims * sizeof(PIO_Offset)); + countlist[rrlen] = malloc(fndims * sizeof(PIO_Offset)); for (int j = 0; j < fndims; j++) { @@ -1380,8 +1346,8 @@ pio_read_darray_nc(file_desc_t *file, io_desc_t *iodesc, int vid, void *iobuf) /* Release the start and count arrays. */ for (int i = 0; i < rrlen; i++) { - brel(startlist[i]); - brel(countlist[i]); + free(startlist[i]); + free(countlist[i]); } } } @@ -1825,7 +1791,7 @@ flush_output_buffer(file_desc_t *file, bool force, PIO_Offset addsize) if (file->iobuf) { PLOG((3,"freeing variable buffer in flush_output_buffer")); - brel(file->iobuf); + free(file->iobuf); file->iobuf = NULL; } @@ -1835,7 +1801,7 @@ flush_output_buffer(file_desc_t *file, bool force, PIO_Offset addsize) return pio_err(NULL, file, ierr, __FILE__, __LINE__); if (vdesc->fillbuf) { - brel(vdesc->fillbuf); + free(vdesc->fillbuf); vdesc->fillbuf = NULL; } } @@ -1845,82 +1811,6 @@ flush_output_buffer(file_desc_t *file, bool force, PIO_Offset addsize) return ierr; } -/** - * Print out info about the buffer for debug purposes. This should - * only be called when logging is enabled. - * - * @param ios pointer to the IO system structure - * @param collective true if collective report is desired - * @ingroup PIO_write_darray_c - * @author Jim Edwards - */ -void -cn_buffer_report(iosystem_desc_t *ios, bool collective) -{ - int mpierr; /* Return code from MPI functions. */ - - PLOG((2, "cn_buffer_report ios->iossysid = %d collective = %d CN_bpool = %d", - ios->iosysid, collective, CN_bpool)); - if (CN_bpool) - { - long bget_stats[5]; - long bget_mins[5]; - long bget_maxs[5]; - - bstats(bget_stats, bget_stats+1,bget_stats+2,bget_stats+3,bget_stats+4); - if (collective) - { - PLOG((3, "cn_buffer_report calling MPI_Reduce ios->comp_comm = %d", ios->comp_comm)); - if ((mpierr = MPI_Reduce(bget_stats, bget_maxs, 5, MPI_LONG, MPI_MAX, 0, ios->comp_comm))) - check_mpi(NULL, NULL, mpierr, __FILE__, __LINE__); - PLOG((3, "cn_buffer_report calling MPI_Reduce")); - if ((mpierr = MPI_Reduce(bget_stats, bget_mins, 5, MPI_LONG, MPI_MIN, 0, ios->comp_comm))) - check_mpi(NULL, NULL, mpierr, __FILE__, __LINE__); - if (ios->compmaster == MPI_ROOT) - { - PLOG((1, "Currently allocated buffer space %ld %ld", bget_mins[0], bget_maxs[0])); - PLOG((1, "Currently available buffer space %ld %ld", bget_mins[1], bget_maxs[1])); - PLOG((1, "Current largest free block %ld %ld", bget_mins[2], bget_maxs[2])); - PLOG((1, "Number of successful bget calls %ld %ld", bget_mins[3], bget_maxs[3])); - PLOG((1, "Number of successful brel calls %ld %ld", bget_mins[4], bget_maxs[4])); - } - } - else - { - PLOG((1, "Currently allocated buffer space %ld", bget_stats[0])); - PLOG((1, "Currently available buffer space %ld", bget_stats[1])); - PLOG((1, "Current largest free block %ld", bget_stats[2])); - PLOG((1, "Number of successful bget calls %ld", bget_stats[3])); - PLOG((1, "Number of successful brel calls %ld", bget_stats[4])); - } - } -} - -/** - * Free the buffer pool. If malloc is used (that is, PIO_USE_MALLOC is - * non zero), this function does nothing. - * - * @param ios pointer to the IO system structure. - * @ingroup PIO_write_darray_c - * @author Jim Edwards - */ -void -free_cn_buffer_pool(iosystem_desc_t *ios) -{ -#if !PIO_USE_MALLOC - PLOG((2, "free_cn_buffer_pool CN_bpool = %d", CN_bpool)); - /* Note: it is possible that CN_bpool has been freed and set to NULL by bpool_free() */ - if (CN_bpool) - { - cn_buffer_report(ios, false); - bpoolrelease(CN_bpool); - PLOG((2, "free_cn_buffer_pool done!")); - free(CN_bpool); - CN_bpool = NULL; - } -#endif /* !PIO_USE_MALLOC */ -} - /** * Flush the buffer. * @@ -1958,21 +1848,21 @@ flush_buffer(int ncid, wmulti_buffer *wmb, bool flushtodisk) wmb->num_arrays = 0; /* Release the list of variable IDs. */ - brel(wmb->vid); + free(wmb->vid); wmb->vid = NULL; /* Release the data memory. */ - brel(wmb->data); + free(wmb->data); wmb->data = NULL; /* If there is a fill value, release it. */ if (wmb->fillvalue) - brel(wmb->fillvalue); + free(wmb->fillvalue); wmb->fillvalue = NULL; /* Release the record number. */ if (wmb->frame) - brel(wmb->frame); + free(wmb->frame); wmb->frame = NULL; if (ret) diff --git a/src/clib/pio_file.c b/src/clib/pio_file.c index 2db64895539..1edf4f42ec6 100644 --- a/src/clib/pio_file.c +++ b/src/clib/pio_file.c @@ -419,7 +419,7 @@ PIOc_sync(int ncid) if (wmb->num_arrays > 0) flush_buffer(ncid, wmb, true); HASH_DEL(file->buffer, wmb); - brel(wmb); + free(wmb); } file->buffer = NULL; diff --git a/src/clib/pio_internal.h b/src/clib/pio_internal.h index 5a365090ee5..800bfb136f5 100644 --- a/src/clib/pio_internal.h +++ b/src/clib/pio_internal.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -329,15 +328,6 @@ extern "C" { /* Print a trace statement, for debugging. */ void print_trace (FILE *fp); - /* Print diagonstic info to stdout. */ - void cn_buffer_report(iosystem_desc_t *ios, bool collective); - - /* Initialize the compute buffer. */ - int compute_buffer_init(iosystem_desc_t *ios); - - /* Free the buffer pool. */ - void free_cn_buffer_pool(iosystem_desc_t *ios); - /* Flush PIO's data buffer. */ int flush_buffer(int ncid, wmulti_buffer *wmb, bool flushtodisk); diff --git a/src/clib/pio_meta.h.in b/src/clib/pio_meta.h.in index 0b364df626c..a735a890026 100644 --- a/src/clib/pio_meta.h.in +++ b/src/clib/pio_meta.h.in @@ -28,5 +28,7 @@ #define PIO_HAS_PAR_FILTERS @PIO_HAS_PAR_FILTERS@ /*!< NetCDF supports parallel I/O with filters. */ #define PIO_HAS_NETCDF4 @PIO_HAS_NETCDF4@ /*!< NetCDF-4 supported. */ #define PIO_HAS_NETCDF4_PAR @PIO_HAS_NETCDF4_PAR@ /*!< NetCDF-4 parallel I/O supported. */ +#define PIO_HAS_NETCDF_INTEGRATION @PIO_HAS_NETCDF_INTEGRATION@ /*!< NetCDF integration supported. */ +#define PIO_HAS_LOGGING @PIO_HAS_LOGGING@ /*!< PIO logging turned on. */ #endif diff --git a/src/clib/pio_nc.c b/src/clib/pio_nc.c index 7c49d5880f9..684e203e2bc 100644 --- a/src/clib/pio_nc.c +++ b/src/clib/pio_nc.c @@ -2277,12 +2277,6 @@ PIOc_def_var(int ncid, const char *name, nc_type xtype, int ndims, PLOG((3, "defined var ierr %d file->iotype %d", ierr, file->iotype)); #ifdef _NETCDF4 - /* For netCDF-4 serial files, turn on compression for this - * variable, unless this file was opened through the netCDF - * integration feature (or is a scalar). */ - if (!ierr && file->iotype == PIO_IOTYPE_NETCDF4C && !file->ncint_file && ndims) - ierr = nc_def_var_deflate(file->fh, varid, 0, 1, 1); - /* For netCDF-4 parallel files, set parallel access to collective. */ if (!ierr && file->iotype == PIO_IOTYPE_NETCDF4P) ierr = nc_var_par_access(file->fh, varid, NC_COLLECTIVE); diff --git a/src/clib/pio_nc4.c b/src/clib/pio_nc4.c index ef18118fe00..becaf1cdf8b 100644 --- a/src/clib/pio_nc4.c +++ b/src/clib/pio_nc4.c @@ -21,8 +21,7 @@ * * @param ncid the ncid of the open file. * @param varid the ID of the variable. - * @param shuffle non-zero to turn on shuffle filter (can be good for - * integer data). + * @param shuffle non-zero to turn on shuffle filter. * @param deflate non-zero to turn on zlib compression for this * variable. * @param deflate_level 1 to 9, with 1 being faster and 9 being more @@ -84,11 +83,8 @@ PIOc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, if (ios->ioproc) { #ifdef _NETCDF4 - if (file->iotype == PIO_IOTYPE_NETCDF4P) - ierr = NC_EINVAL; - else - if (file->do_io) - ierr = nc_def_var_deflate(file->fh, varid, shuffle, deflate, deflate_level); + if (file->do_io) + ierr = nc_def_var_deflate(file->fh, varid, shuffle, deflate, deflate_level); #endif } diff --git a/src/clib/pio_rearrange.c b/src/clib/pio_rearrange.c index 95536d0bc05..f78b3fce8df 100644 --- a/src/clib/pio_rearrange.c +++ b/src/clib/pio_rearrange.c @@ -798,8 +798,8 @@ compute_counts(iosystem_desc_t *ios, io_desc_t *iodesc, recv_counts, recv_displs, sr_types, ios->union_comm, &iodesc->rearr_opts.comp2io))) return pio_err(ios, NULL, ierr, __FILE__, __LINE__); - - free(s2rindex); + if(s2rindex) + free(s2rindex); return PIO_NOERR; } diff --git a/src/clib/pioc.c b/src/clib/pioc.c index 0f6e693b1d4..99402dce88d 100644 --- a/src/clib/pioc.c +++ b/src/clib/pioc.c @@ -732,8 +732,8 @@ PIOc_InitDecomp(int iosysid, int pio_type, int ndims, const int *gdimlen, int ma iodesc->rearranger, iodesc->maxregions, iodesc->needsfill, iodesc->llen, iodesc->maxiobuflen)); if (iodesc->rindex) - for (int j = 0; j < iodesc->llen; j++) - PLOG((3, "rindex[%d] = %lld", j, iodesc->rindex[j])); + for (int j = 0; j < iodesc->llen; j++) + PLOG((3, "rindex[%d] = %lld", j, iodesc->rindex[j])); #endif /* PIO_ENABLE_LOGGING */ /* This function only does something if pre-processor macro @@ -913,7 +913,6 @@ PIOc_InitDecomp_bc(int iosysid, int pio_type, int ndims, const int *gdimlen, *
  • On IO tasks, create an IO communicator (ios->io_comm). *
  • Assign an iosystemid, and put this iosystem_desc_t into the * list of open iosystems. - *
  • Initialize the bget buffer, unless PIO_USE_MALLOC was used. * * * When complete, there are three MPI communicators (ios->comp_comm, @@ -1076,10 +1075,6 @@ PIOc_Init_Intracomm(MPI_Comm comp_comm, int num_iotasks, int stride, int base, /* Add this ios struct to the list in the PIO library. */ *iosysidp = pio_add_to_iosystem_list(ios); - /* Allocate buffer space for compute nodes. */ - if ((ret = compute_buffer_init(ios))) - return ret; - #ifdef USE_MPE pio_stop_mpe_log(INIT, __func__); #endif /* USE_MPE */ @@ -1243,13 +1238,6 @@ PIOc_free_iosystem(int iosysid) return pio_err(ios, NULL, ierr, __FILE__, __LINE__); PLOG((2, "%d iosystems are still open.", niosysid)); - /* Only free the buffer pool if this is the last open iosysid. */ - if (niosysid == 1) - { - free_cn_buffer_pool(ios); - PLOG((2, "Freed buffer pool.")); - } - /* Free the MPI communicators. my_comm is just a copy (but not an * MPI copy), so does not have to have an MPI_Comm_free() * call. comp_comm and io_comm are MPI duplicates of the comms diff --git a/src/clib/pioc_support.c b/src/clib/pioc_support.c index 6e1849075b8..8a681136d86 100644 --- a/src/clib/pioc_support.c +++ b/src/clib/pioc_support.c @@ -164,14 +164,6 @@ PIOc_set_log_level(int level) /* Set the log level. */ pio_log_level = level; -#if NETCDF_C_LOGGING_ENABLED - int ret; - - /* If netcdf logging is available turn it on starting at level = 4. */ - if (level > NC_LEVEL_DIFF) - if ((ret = nc_set_log_level(level - NC_LEVEL_DIFF))) - return pio_err(NULL, NULL, ret, __FILE__, __LINE__); -#endif /* NETCDF_C_LOGGING_ENABLED */ #endif /* PIO_ENABLE_LOGGING */ return PIO_NOERR; diff --git a/src/flib/CMakeLists.txt b/src/flib/CMakeLists.txt index 1e357c81e5d..99a9ba7cf75 100644 --- a/src/flib/CMakeLists.txt +++ b/src/flib/CMakeLists.txt @@ -31,6 +31,11 @@ set (PIO_Fortran_MODS ${CMAKE_CURRENT_BINARY_DIR}/pio.mod ${CMAKE_CURRENT_BINARY_DIR}/pionfatt_mod.mod ${CMAKE_CURRENT_BINARY_DIR}/pionfput_mod.mod) +if (NETCDF_INTEGRATION) + set (PIO_Fortran_SRCS ${PIO_Fortran_SRCS} ncint_mod.F90) + set (PIO_Fortran_MODS ${PIO_Fortran_MODS} ${CMAKE_CURRENT_BINARY_DIR}/ncint_mod.mod) +endif () + add_library (piof ${PIO_Fortran_SRCS} ${PIO_GenF90_SRCS}) if (NOT PIO_ENABLE_FORTRAN) set_target_properties(piof PROPERTIES EXCLUDE_FROM_ALL TRUE) @@ -137,7 +142,6 @@ endforeach () #===== MPI ===== if (PIO_USE_MPISERIAL) - find_package (MPISERIAL COMPONENTS Fortran REQUIRED) if (MPISERIAL_Fortran_FOUND) target_compile_definitions (piof PRIVATE _MPISERIAL) @@ -149,8 +153,6 @@ if (PIO_USE_MPISERIAL) set (WITH_PNETCDF FALSE) set (MPI_Fortran_INCLUDE_PATH ${MPISERIAL_Fortran_INCLUDE_DIRS}) endif () -else () - find_package (MPI REQUIRED) endif () # Check MPI I/O capabilities @@ -179,9 +181,6 @@ endif () find_path(MPIMOD_PATH NAMES mpi.mod MPI.mod HINTS ${MPI_Fortran_INCLUDE_PATH}) -if (PIO_ENABLE_TIMING) - find_package (GPTL COMPONENTS Fortran_Perf QUIET) -endif () check_macro (MPI_HAS_Fortran_MOD NAME TryMPIMod.f90 @@ -214,46 +213,22 @@ if (PIO_ENABLE_TIMING) endif () #===== NetCDF-Fortran ===== -find_package (NetCDF "4.3.3" COMPONENTS Fortran) if (NetCDF_Fortran_FOUND) target_include_directories (piof PUBLIC ${NetCDF_Fortran_INCLUDE_DIRS}) - target_compile_definitions (piof - PUBLIC _NETCDF) target_link_libraries (piof PUBLIC ${NetCDF_Fortran_LIBRARIES}) - if (EXISTS ${NetCDF_Fortran_INCLUDE_DIR}/netcdf_par.h) - target_compile_definitions (piof - PUBLIC _NETCDF4) - endif () -else () - target_compile_definitions (piof - PUBLIC _NONETCDF) endif () #===== PnetCDF ===== -if (WITH_PNETCDF) - find_package (PnetCDF "1.6" COMPONENTS Fortran REQUIRED) -endif () if (PnetCDF_Fortran_FOUND) target_include_directories (piof PUBLIC ${PnetCDF_Fortran_INCLUDE_DIRS}) - target_compile_definitions (piof - PUBLIC _PNETCDF) target_link_libraries (piof PUBLIC ${PnetCDF_Fortran_LIBRARIES}) # Check library for varn functions set (CMAKE_REQUIRED_LIBRARIES ${PnetCDF_Fortran_LIBRARY}) - check_function_exists (ncmpi_get_varn PnetCDF_Fortran_HAS_VARN) - if (PnetCDF_Fortran_HAS_VARN) - target_compile_definitions(piof - PUBLIC USE_PNETCDF_VARN - PUBLIC USE_PNETCDF_VARN_ON_READ) - endif() -else () - target_compile_definitions (piof - PUBLIC _NOPNETCDF) endif () #===== Add EXTRAs ===== diff --git a/src/flib/Makefile.am b/src/flib/Makefile.am index 93d816e9358..38e0cbfbcd2 100644 --- a/src/flib/Makefile.am +++ b/src/flib/Makefile.am @@ -7,12 +7,10 @@ # The library we are building. lib_LTLIBRARIES = libpiof.la -AM_CPPFLAGS = -D_NETCDF -D_NETCDF4 -D_PNETCDF - # These linker flags specify libtool version info. # See http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning # for information regarding incrementing `-version-info`. -libpiof_la_LDFLAGS = -version-info 3:1:2 +libpiof_la_LDFLAGS = -version-info 4:0:0 # The library soure files. libpiof_la_LIBADD = libpio_nf.la libpio_kinds.la libpio_support.la \ @@ -59,17 +57,17 @@ pionfput_mod.F90: pionfput_mod.F90.in ${top_srcdir}/scripts/genf90.pl $< > $@ # Each mod file depends on the .o file. -pio_kinds.mod: pio_kinds.$(OBJEXT) -pio_types.mod: pio_types.$(OBJEXT) -pio_support.mod: pio_support.$(OBJEXT) -pio_nf.mod: pio_nf.$(OBJEXT) -piodarray.mod: piodarray.F90 piodarray.$(OBJEXT) -pionfatt_mod.mod: pionfatt_mod.F90 pionfatt_mod.$(OBJEXT) -pionfget_mod.mod: pionfget_mod.F90 pionfget_mod.$(OBJEXT) -pionfput_mod.mod: pionfput_mod.F90 pionfput_mod.$(OBJEXT) -piolib_mod.mod: piolib_mod.$(OBJEXT) -ncint_mod.mod: ncint_mod.$(OBJEXT) -pio.mod: pio.$(OBJEXT) +pio_kinds.mod: pio_kinds.lo +pio_types.mod: pio_types.lo +pio_support.mod: pio_support.lo +pio_nf.mod: pio_nf.lo +piodarray.mod: piodarray.F90 piodarray.lo +pionfatt_mod.mod: pionfatt_mod.F90 pionfatt_mod.lo +pionfget_mod.mod: pionfget_mod.F90 pionfget_mod.lo +pionfput_mod.mod: pionfput_mod.F90 pionfput_mod.lo +piolib_mod.mod: piolib_mod.lo +ncint_mod.mod: ncint_mod.lo +pio.mod: pio.lo # Some mod files depend on other mod files. DEPEND_FILES = pio_kinds.mod piolib_mod.mod pio_types.mod piodarray.mod \ @@ -77,7 +75,7 @@ pio_nf.mod pionfatt_mod.mod pionfget_mod.mod pionfput_mod.mod pio_support.mod if NETCDF_INTEGRATION DEPEND_FILES += ncint_mod.mod endif -pio.$(OBJEXT): $(DEPEND_FILES) +pio.lo: $(DEPEND_FILES) # Mod files are built and then installed as headers. MODFILES = pio_kinds.mod pio_types.mod pio_support.mod pio_nf.mod \ @@ -97,15 +95,15 @@ if BUILD_DOCS BUILT_SOURCES += piodarray.f90 piolib_mod.f90 pionfatt_mod.f90 pionfget_mod.f90 \ pionfput_mod.f90 pionfatt_mod_2.f90 pionfget_mod_2.f90 piodarray.f90: piodarray.F90 - $(CC) -E $< > $@ + $(CC) -I../.. $(AM_CPPFLAGS) -E $< > $@ piolib_mod.f90: piolib_mod.F90 $(CC) -I../.. $(AM_CPPFLAGS) -E $< > $@ pionfatt_mod.f90: pionfatt_mod.F90 - $(CC) -E $< > $@ + $(CC) -I../.. $(AM_CPPFLAGS) -E $< > $@ pionfget_mod.f90: pionfget_mod.F90 - $(CC) -E $< > $@ + $(CC) -I../.. $(AM_CPPFLAGS) -E $< > $@ pionfput_mod.f90: pionfput_mod.F90 - $(CC) -E $< > $@ + $(CC) -I../.. $(AM_CPPFLAGS) -E $< > $@ # Unfortunately the genf90.pl script which generates these fortran # files has no way of handling doxygen documentation. So use sed to diff --git a/src/flib/pio.F90 b/src/flib/pio.F90 index a14a8af9912..da1fc9faf18 100644 --- a/src/flib/pio.F90 +++ b/src/flib/pio.F90 @@ -39,9 +39,7 @@ module pio pio_iotype_pnetcdf,pio_iotype_netcdf, & pio_global, pio_char, pio_write, pio_nowrite, pio_clobber, pio_noclobber, & pio_max_name, pio_max_var_dims, pio_rearr_subset, pio_rearr_box, & -#if defined(_NETCDF) || defined(_PNETCDF) pio_nofill, pio_unlimited, pio_fill_int, pio_fill_double, pio_fill_float, & -#endif pio_64bit_offset, pio_64bit_data, & pio_internal_error, pio_bcast_error, pio_return_error, pio_default @@ -78,7 +76,8 @@ module pio PIO_strerror use pionfatt_mod, only : PIO_put_att => put_att, & - PIO_get_att => get_att + PIO_get_att => get_att, & + PIO_inq_var_fill => inq_var_fill use pionfput_mod, only : PIO_put_var => put_var use pionfget_mod, only : PIO_get_var => get_var use pio_support, only: pio_writedof diff --git a/src/flib/pio_kinds.F90 b/src/flib/pio_kinds.F90 index c5074c1f850..f9de9a185aa 100644 --- a/src/flib/pio_kinds.F90 +++ b/src/flib/pio_kinds.F90 @@ -4,6 +4,7 @@ !! types like integer, character, logical, real4 and real8. !! !< +#include "config.h" module pio_kinds ! uses mpi if available diff --git a/src/flib/pio_nf.F90 b/src/flib/pio_nf.F90 index b40b7b71356..35630b64aa6 100644 --- a/src/flib/pio_nf.F90 +++ b/src/flib/pio_nf.F90 @@ -1,3 +1,4 @@ +#include "config.h" !> !! @file !! Code to implement the classic netCDF Fortran API in PIO. @@ -7,13 +8,35 @@ !> @defgroup PIO_inquire_dimension Learn About Dimension !! Learn dimension name, ID, or length in Fortran. !! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! pio_inq_dimlen() | inq_dimlen_desc(), inq_dimlen_id(), inq_dimlen_desc_long(), inq_dimlen_id_long() +!! pio_inq_ndims() | inq_ndims_id() +!! pio_inq_dimid() | inq_dimid_desc(), inq_dimid_id() +!! pio_inq_dimname() | inq_dimname_desc(), inq_dimname_id() +!! !! @defgroup PIO_inquire Learn About a File !! Learn the number of variables, dimensions, global attributes, and !! the unlimited dimension ID in Fortran. !! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! pio_inquire() | inquire_desc(), inquire_id() +!! !! @defgroup PIO_enddef Define Mode !! End or re-enter define mode in Fortran. !! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! pio_enddef() | enddef_desc(), enddef_id() +!! pio_redef() | redef_desc(), redef_id() +!! !! @defgroup PIO_set_log_level Debug Logging !! Set debugging log level in Fortran. !! @@ -23,15 +46,50 @@ !! @defgroup PIO_def_dim Define a Dimension !! Define a new dimension, with name and length in Fortran. !! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! pio_def_dim() | def_dim_desc(), def_dim_id(), def_dim_int_desc(), def_dim_int_id() +!! !! @defgroup PIO_inquire_variable Learn About a Variable !! Learn variable name, ID, type, dimensions, compression, chunking in !! Fortran. !! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! pio_inquire_variable() | inquire_variable_desc(), inquire_variable_vid(), inquire_variable_id() +!! pio_inq_varid() | inq_varid_desc(), inq_varid_vid(), inq_varid_id() +!! pio_inq_vartype() | inq_varname_desc(), inq_varname_vid(), inq_varname_id() +!! pio_inq_varndims() | inq_varndims_desc(), inq_varndims_vid(), inq_varndims_id() +!! pio_inq_vardimid() | inq_vardimid_desc(), inq_vardimid_vid(), inq_vardimid_id() +!! pio_inq_varnatts() | inq_varnatts_desc(), inq_varnatts_vid(), inq_varnatts_id() +!! pio_inq_var_deflate() | inq_var_deflate_desc(), inq_var_deflate_vid(), inq_var_deflate_id() +!! pio_inq_var_chunking() | inq_var_chunking_desc(), inq_var_chunking_vid(), inq_var_chunking_id() +!! !! @defgroup PIO_inq_att Learn About an Attribute !! Learn attribute name, number, type, size in Fortran. !! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! pio_inq_attname() | inq_attname_desc(), inq_attname_vid(), inq_attname_id() +!! pio_inq_att() | inq_att_desc(), inq_att_vid(), inq_att_id() +!! pio_inq_attlen() | inq_attlen_desc(), inq_attlen_vid(), inq_attlen_id() +!! !! @defgroup PIO_def_var Define a Variable !! Define a new variable in Fortran. +!! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! pio_def_var() | def_var_0d_desc(), def_var_md_desc(), def_var_0d_id(), def_var_md_id() +!! pio_def_var_deflate() | def_var_deflate_desc(), def_var_deflate_id() +!! pio_def_var_chunking() | def_var_chunking_desc() !< module pio_nf @@ -60,6 +118,7 @@ module pio_nf pio_inq_vardimid , & pio_inq_varnatts , & pio_inq_var_deflate , & + pio_inq_var_chunking , & pio_inquire_variable , & pio_inquire_dimension , & pio_inq_dimname , & @@ -74,7 +133,8 @@ module pio_nf pio_get_var_chunk_cache , & pio_redef , & pio_set_log_level , & - pio_strerror + pio_strerror , & + pio_set_fill ! pio_copy_att to be done interface pio_def_var @@ -91,7 +151,7 @@ module pio_nf end interface pio_def_var_deflate interface pio_def_var_chunking module procedure & - def_var_chunking + def_var_chunking_desc end interface pio_def_var_chunking interface pio_inq_attname module procedure & @@ -155,6 +215,12 @@ module pio_nf inq_var_deflate_vid , & inq_var_deflate_id end interface pio_inq_var_deflate + interface pio_inq_var_chunking + module procedure & + inq_var_chunking_desc , & + inq_var_chunking_vid , & + inq_var_chunking_id + end interface pio_inq_var_chunking interface pio_inquire_dimension module procedure & inquire_dimension_desc , & @@ -198,6 +264,13 @@ module pio_nf inq_dimname_id end interface pio_inq_dimname + interface PIO_set_fill + module procedure & + set_fill_id ,& + set_fill_desc + end interface PIO_set_fill + + interface pio_inq_nvars module procedure & inq_nvars_id @@ -286,6 +359,55 @@ integer function inq_dimid_desc(File ,name,dimid) result(ie ierr = inq_dimid_id(file%fh ,name,dimid) end function inq_dimid_desc + !> + !! @public + !! @ingroup PIO_set_fill + !! Set the netcdf fill mode + !! + !! @param ncid A netcdf file ID returned by \ref + !! PIO_openfile or \ref PIO_createfile. + !! @param fillmode Desired fill mode for the dataset, either PIO_NOFILL or PIO_FILL. + !! @param old_mode Returned current fill mode of the dataset before this call, either PIO_NOFILL or PIO_FILL. + !! @retval ierr @copydoc error_return + !! @author Jim Edwards + !< + integer function set_fill_id(ncid ,fillmode, old_mode) result(ierr) + integer , intent(in) :: ncid + integer , intent(in) :: fillmode + integer , intent(out) :: old_mode + interface + integer(C_INT) function PIOc_set_fill(ncid ,fillmode, old_mode) & + bind(C ,name="PIOc_set_fill") + use iso_c_binding + integer(c_int) ,value :: ncid + integer(c_int) :: fillmode + integer(c_int) :: old_mode + end function PIOc_set_fill + end interface + + ierr = PIOc_set_fill(ncid, fillmode, old_mode) + + end function set_fill_id + + !> + !! @public + !! @ingroup PIO_set_fill + !! Set the netcdf fill mode + !! + !! @param File @copydoc file_desc_t + !! @param fillmode Desired fill mode for the dataset, either PIO_NOFILL or PIO_FILL. + !! @param old_mode Returned current fill mode of the dataset before this call, either PIO_NOFILL or PIO_FILL. + !! @retval ierr @copydoc error_return + !! @author Jim Edwards + !< + integer function set_fill_desc(File, fillmode, old_mode) result(ierr) + type(File_desc_t) ,intent(in) :: File + integer ,intent(in) :: fillmode + integer ,intent(out):: old_mode + ierr = set_fill_id(file%fh ,fillmode, old_mode) + end function set_fill_desc + + !> !! @public !! @ingroup PIO_inquire_dimension @@ -1241,6 +1363,77 @@ end function PIOc_inq_var_deflate ierr = PIOc_inq_var_deflate(ncid, varid-1, shuffle, deflate, deflate_level) end function inq_var_deflate_id + !> + !! @public + !! @ingroup PIO_inquire_variable + !! Gets metadata information for netcdf file. + !! + !! @param File @copydoc file_desc_t + !! @param vardesc @copydoc var_desc_t + !! @param storage 0 for chunked, 1 for contiguous + !! @param chunksizes Array of chunk sizes. + !! @retval ierr @copydoc error_return + !! @author Ed Hartnett + !< + integer function inq_var_chunking_desc(File, vardesc, storage, chunksizes) result(ierr) + + type (File_desc_t), intent(in) :: File + type (Var_desc_t), intent(in) :: vardesc + integer, intent(out) :: storage + integer (kind=PIO_OFFSET_KIND), intent(out) :: chunksizes(*) + + ierr = pio_inq_var_chunking(File%fh, vardesc%varid, storage, chunksizes) + end function inq_var_chunking_desc + + !> + !! @public + !! @ingroup PIO_inquire_variable + !! Gets metadata information for netcdf file. + !! @author Ed Hartnett + !< + integer function inq_var_chunking_vid(File, varid, storage, chunksizes) result(ierr) + + type (File_desc_t), intent(in) :: File + integer, intent(in) :: varid + integer, intent(out) :: storage + integer (kind=PIO_OFFSET_KIND), intent(out) :: chunksizes(*) + + ierr = pio_inq_var_chunking(File%fh, varid, storage, chunksizes) + end function inq_var_chunking_vid + + !> + !! @public + !! @ingroup PIO_inquire_variable + !! Gets metadata information for netcdf file. + !! @author Ed Hartnett + !< + integer function inq_var_chunking_id(ncid, varid, storage, chunksizes) result(ierr) + integer, intent(in) :: ncid + integer, intent(in) :: varid + integer, intent(out) :: storage + integer (kind=PIO_OFFSET_KIND), intent(out) :: chunksizes(*) + integer(kind=PIO_OFFSET_KIND) :: cchunksizes(PIO_MAX_VAR_DIMS) + integer :: ndims, i + + interface + integer(C_INT) function PIOc_inq_var_chunking(ncid, varid, storage, cchunksizes) & + bind(C, name="PIOc_inq_var_chunking") + use iso_c_binding + integer(C_INT), value :: ncid + integer(C_INT), value :: varid + integer(C_INT) :: storage + integer(C_SIZE_T) :: cchunksizes(*) + end function PIOc_inq_var_chunking + end interface + + ierr = PIOc_inq_var_chunking(ncid, varid-1, storage, cchunksizes) + ierr = pio_inq_varndims(ncid, varid, ndims) + do i = 1, ndims + chunksizes(i) = cchunksizes(ndims - i + 1) + enddo + + end function inq_var_chunking_id + !> !! @public !! @ingroup PIO_inquire_variable @@ -1362,7 +1555,9 @@ end function PIOc_inq_varid ierr = PIOc_inq_varid(ncid, trim(name)//C_NULL_CHAR, varid) ! the fortran value is one based while the c value is 0 based - varid = varid+1 + if (ierr == 0) then + varid = varid+1 + endif end function inq_varid_id !> @@ -1704,12 +1899,12 @@ end function def_var_deflate_desc !! Changes chunking settings for a netCDF-4/HDF5 variable. !! @author Ed Hartnett !< - integer function def_var_chunking(file, vardesc, storage, chunksizes) result(ierr) + integer function def_var_chunking_desc(file, vardesc, storage, chunksizes) result(ierr) type (File_desc_t), intent(in) :: file type (var_desc_t), intent(in) :: vardesc integer, intent(in) :: storage integer, intent(in) :: chunksizes(:) - integer(C_INT) :: cchunksizes(PIO_MAX_VAR_DIMS) + integer(kind=PIO_OFFSET_KIND) :: cchunksizes(PIO_MAX_VAR_DIMS) integer :: ndims, i interface @@ -1719,16 +1914,16 @@ integer (C_INT) function PIOc_def_var_chunking(ncid, varid, storage, chunksizes) integer(c_int), value :: ncid integer(c_int), value :: varid integer(c_int), value :: storage - integer(c_int) :: chunksizes(*) + integer(c_size_t) :: chunksizes(*) end function PIOc_def_var_chunking end interface ndims = size(chunksizes) do i=1,ndims - cchunksizes(i) = chunksizes(ndims-i+1)-1 + cchunksizes(i) = chunksizes(ndims-i+1) enddo ierr = PIOc_def_var_chunking(file%fh, vardesc%varid-1, storage, cchunksizes) - end function def_var_chunking + end function def_var_chunking_desc !> !! @ingroup PIO_set_chunk_cache diff --git a/src/flib/pio_support.F90 b/src/flib/pio_support.F90 index ae212d1bbdc..686da26fed2 100644 --- a/src/flib/pio_support.F90 +++ b/src/flib/pio_support.F90 @@ -1,3 +1,4 @@ +#include "config.h" !> !! @file !! Internal code for compiler workarounds, aborts and debug functions. diff --git a/src/flib/pio_types.F90 b/src/flib/pio_types.F90 index 970c2c83402..844514f6171 100644 --- a/src/flib/pio_types.F90 +++ b/src/flib/pio_types.F90 @@ -1,3 +1,4 @@ +#include "config.h" !> !! @file !! Derived datatypes and constants for PIO Fortran API. diff --git a/src/flib/piodarray.F90.in b/src/flib/piodarray.F90.in index dfd2b5339a2..6971d5ceb77 100644 --- a/src/flib/piodarray.F90.in +++ b/src/flib/piodarray.F90.in @@ -1,4 +1,5 @@ #define __PIO_FILE__ 'piodarray' +#include "config.h" !> !! @file !! Read and write routines for decomposed data. @@ -325,6 +326,8 @@ contains integer(C_SIZE_T) :: tlen tlen = size(array) + ! array is intent out but may not be fully filled by read_darray + array = 0 call read_darray_internal_{TYPE} (File%fh, vardesc%varid, iodesc%ioid, tlen, array, iostat) end subroutine read_darray_{DIMS}d_{TYPE} diff --git a/src/flib/piolib_mod.F90 b/src/flib/piolib_mod.F90 index 21c174355f1..ce5f118b1c2 100644 --- a/src/flib/piolib_mod.F90 +++ b/src/flib/piolib_mod.F90 @@ -30,13 +30,52 @@ !! Create a new IO System, designating numbers of I/O and computation !! tasks in Fortran. !! +!! Use the Fortran generic function PIO_init() to initialize the IO +!! System. The PIO_init() function will call init_intracom(). +!! +!! This code from examples/f03/examplePio.F90 demonstrates how to +!! initialize the IO system for intracom mode. +!! +!! @code +!! call PIO_init(this%myRank, & ! MPI rank +!! MPI_COMM_WORLD, & ! MPI communicator +!! this%niotasks, & ! Number of iotasks (ntasks/stride) +!! this%numAggregator, & ! number of aggregators to use +!! this%stride, & ! stride +!! PIO_rearr_subset, & ! do not use any form of rearrangement +!! this%pioIoSystem, & ! iosystem +!! base=this%optBase) ! base (optional argument) +!! @endcode +!! !! @defgroup PIO_finalize Free an IOSystem !! Free an IO System, releasing all resources in Fortran. !! +!! Use the Fortran generic function PIO_finalize() to finalize the IO +!! System, freeing all associated resources. The PIO_finalize() +!! function will call finalize(). +!! +!! This code from examples/f03/examplePio.F90 demonstrates how to +!! finalize the IO system. +!! +!! @code +!! call PIO_finalize(this%pioIoSystem, ierr) +!! @endcode +!! !! @defgroup PIO_initdecomp Define a Decomposition !! Define a new decomposition of variables to distributed arrays in !! Fortran. !! +!! Use the generic function PIO_initdecomp() to call the underlying Fortran functions. +!! +!! - PIO_initdecomp_dof_i4() +!! - PIO_initdecomp_dof_i8() +!! - initdecomp_1dof_nf_i4() +!! - initdecomp_1dof_nf_i8() +!! - initdecomp_1dof_bin_i4() +!! - initdecomp_1dof_bin_i8() +!! - initdecomp_2dof_nf_i4() +!! - initdecomp_2dof_nf_i8() +!! !! @defgroup PIO_getnumiotasks Get Number IO Tasks !! Get the number of IO tasks in Fortran. !! @@ -46,6 +85,12 @@ !! @defgroup PIO_seterrorhandling Error Handling for Fortran !! Set the behavior if an error is encountered in Fortran. !! +!! Use the generic functions to call the underlying Fortran functions. +!! +!! Generic Function | Function(s) +!! ---------------- | ----------- +!! PIO_seterrorhandling() | seterrorhandlingfile(), seterrorhandlingiosystem(), seterrorhandlingiosysid() +!! !! @defgroup PIO_get_local_array_size Get Local Array Size !! Get the local size of the distributed array in a decomposition in !! Fortran. @@ -938,7 +983,7 @@ subroutine init_intracom(comp_rank, comp_comm, num_iotasks, num_aggregator, stri integer(i4), intent(in) :: rearr type (iosystem_desc_t), intent(out) :: iosystem ! io descriptor to initalize integer(i4), intent(in),optional :: base - type (pio_rearr_opt_t), intent(in), optional :: rearr_opts + type (pio_rearr_opt_t), intent(in), optional, target :: rearr_opts integer :: lbase integer :: ierr @@ -952,7 +997,7 @@ integer(c_int) function PIOc_Init_Intracomm_from_F90(f90_comp_comm, num_iotasks, integer(C_INT), value :: stride integer(C_INT), value :: base integer(C_INT), value :: rearr - type(pio_rearr_opt_t) :: rearr_opts + type(C_PTR), value :: rearr_opts integer(C_INT) :: iosysidp end function PIOc_Init_Intracomm_from_F90 end interface @@ -965,8 +1010,11 @@ end function PIOc_Init_Intracomm_from_F90 #endif lbase=0 if(present(base)) lbase=base - ierr = PIOc_Init_Intracomm_from_F90(comp_comm,num_iotasks,stride,lbase,rearr,rearr_opts,iosystem%iosysid) - + if(present(rearr_opts)) then + ierr = PIOc_Init_Intracomm_from_F90(comp_comm,num_iotasks,stride,lbase,rearr,C_LOC(rearr_opts),iosystem%iosysid) + else + ierr = PIOc_Init_Intracomm_from_F90(comp_comm,num_iotasks,stride,lbase,rearr,C_NULL_PTR,iosystem%iosysid) + endif call CheckMPIReturn("Bad Initialization in PIO_Init_Intracomm: ", ierr,__FILE__,__LINE__) #ifdef TIMING call t_stopf("PIO:init") diff --git a/src/flib/pionfatt_mod.F90.in b/src/flib/pionfatt_mod.F90.in index cc4a3cd409d..ebc0ce20504 100644 --- a/src/flib/pionfatt_mod.F90.in +++ b/src/flib/pionfatt_mod.F90.in @@ -1,4 +1,5 @@ #define __PIO_FILE__ "pionfatt_mod.F90" +#include "config.h" !> !! @file !! @brief NetCDF attribute interface to PIO @@ -34,7 +35,6 @@ module pionfatt_mod module procedure put_att_1d_vid_{TYPE} end interface - !> !! @private !< @@ -45,6 +45,15 @@ module pionfatt_mod module procedure get_att_1d_{TYPE}, get_att_desc_1d_{TYPE}, get_att_1d_id_{TYPE} end interface + !> + !! @private + !< + public :: inq_var_fill + interface inq_var_fill + ! TYPE double,int,short,real + module procedure inq_var_fill_{TYPE} + end interface inq_var_fill + !> @cond doxygen_cant_handle_so_exclude private :: modName character(len=*), parameter :: modName='pionfatt_mod' @@ -107,8 +116,7 @@ module pionfatt_mod end function PIOc_put_att_float end interface interface - ! TYPE int,double,short - integer(C_INT) function PIOc_get_att_float (ncid, varid, name, op) & + integer(C_INT) function PIOc_get_att_float (ncid, varid, name, op) & bind(C,name="PIOc_get_att_float") use iso_c_binding integer(C_INT), value :: ncid @@ -117,9 +125,42 @@ module pionfatt_mod real(C_FLOAT), intent(out) :: op end function PIOc_get_att_float end interface + interface + integer(C_INT) function PIOc_inq_var_fill (ncid, varid, no_fill, fillvalue) & + bind(C, name="PIOc_inq_var_fill") + use iso_c_binding + integer(C_INT), value :: ncid + integer(C_INT), value :: varid + integer(C_INT), intent(out) :: no_fill + type(C_PTR), value :: fillvalue + end function PIOc_inq_var_fill + end interface !> @endcond contains + !pl The next line is needed by genf90.pl, do not remove it. + ! TYPE real,double,int,short + !> + !! @public + !! @ingroup PIO_inq_var_fill + !! @brief Inquires about var fill value + !! @details + !! @param File @copydoc file_desc_t + !! @param vdesc : The netcdf variable descriptor + !! @param no_fill : whether this variable has no_fill enabled + !! @param fillvalue : the fillvalue used for this variable, returns default if not set. + !! @retval ierr @copydoc error_return + !< + integer function inq_var_fill_{TYPE} (File, vdesc, no_fill, fillvalue) result(ierr) + type (File_desc_t), intent(in) :: File + type(var_desc_t), intent(in) :: vdesc + ! fillvalue needs to not be optional to avoid ambiguity + integer, intent(out) :: no_fill + {VTYPE}, target, intent(out) :: fillvalue + + ierr = PIOc_inq_var_fill (File%fh, vdesc%varid-1, no_fill, C_LOC(fillvalue)) + + end function inq_var_fill_{TYPE} !> !! @public diff --git a/src/flib/pionfget_mod.F90.in b/src/flib/pionfget_mod.F90.in index 3fe5462d95a..de9a22fde8e 100644 --- a/src/flib/pionfget_mod.F90.in +++ b/src/flib/pionfget_mod.F90.in @@ -1,4 +1,5 @@ #define __PIO_FILE__ "pionfget_mod.F90" +#include "config.h" !> !! @file !! @brief Read Routines for non-decomposed NetCDF data. @@ -15,7 +16,7 @@ module pionfget_mod #ifdef TIMING use perf_mod, only : t_startf, t_stopf ! _EXTERNAL #endif - use pio_kinds, only: i2,i4,r4,r8 + use pio_kinds, only: i2,i4,r4,r8, pio_offset_kind use pio_types, only : file_desc_t, var_desc_t use pio_support, only : replace_c_null implicit none @@ -201,7 +202,7 @@ CONTAINS !> !! @public !! @ingroup PIO_get_var -!! @brief Writes an netcdf attribute to a file +!! @brief Writes data to a file !! @details !! @param File @ref file_desc_t !! @param vardesc @ref var_desc_t @@ -227,7 +228,7 @@ CONTAINS !> !! @public !! @ingroup PIO_get_var -!! @brief Writes an netcdf attribute to a file +!! @brief Gets data from a file !! @details !! @param File @ref file_desc_t !! @param varid : The netcdf variable identifier @@ -275,7 +276,7 @@ CONTAINS !> !! @public !! @ingroup PIO_get_var -!! @brief Writes an netcdf attribute to a file +!! @brief Gets data from a file !! @details !! @param File @ref file_desc_t !! @param vardesc @ref var_desc_t @@ -315,7 +316,7 @@ CONTAINS !> !! @public !! @ingroup PIO_get_var -!! @brief Writes an netcdf attribute to a file +!! @brief Gets data from a file !! @details !! @param File @ref file_desc_t !! @param varid : The netcdf variable identifier @@ -356,20 +357,24 @@ CONTAINS integer, intent(in) :: varid character(len=*), intent(out) :: ival{DIMSTR} ival = ' ' - ierr = get_var_text_internal(File%fh, varid, size(ival), ival) + ierr = get_var_text_internal(File%fh, varid, size(ival), ival, len(ival)) end function get_var_{DIMS}d_text - integer function get_var_text_internal (ncid,varid, nstrs, ival) result(ierr) + integer function get_var_text_internal (ncid,varid, nstrs, ival, strlen) result(ierr) integer, intent(in) :: ncid integer, intent(in) :: varid integer, intent(in) :: nstrs - character(len=*), intent(out) :: ival(*) + integer, intent(in) :: strlen + character(len=strlen), intent(out) :: ival(*) integer :: j + do j=1,nstrs + ival(j) = C_NULL_CHAR + enddo ierr = PIOc_get_var_text(ncid, varid-1, ival) do j=1,nstrs - call replace_c_null(ival(j)) + call replace_c_null(ival(j), int(strlen,kind=PIO_OFFSET_KIND)) end do end function get_var_text_internal @@ -393,11 +398,14 @@ CONTAINS integer, intent(in) :: count(:) {VTYPE}, target, intent(out) :: ival(*) integer(C_SIZE_T), allocatable :: cstart(:), ccount(:) - integer :: i, ndims + integer :: i, ndims, indims ierr = pio_inq_varndims(ncid,varid, ndims) allocate(cstart(ndims),ccount(ndims)) - do i=1,ndims + indims = size(start) + cstart = 0 + ccount = 1 + do i=ndims-indims+1,ndims cstart(i) = start(ndims-i+1)-1 ccount(i) = count(ndims-i+1) enddo @@ -448,7 +456,7 @@ CONTAINS !> !! @public !! @ingroup PIO_get_var -!! @brief Writes an netcdf attribute to a file +!! @brief Gets data from a file !! @details !! @param File @ref file_desc_t !! @param vardesc @ref var_desc_t diff --git a/src/flib/pionfput_mod.F90.in b/src/flib/pionfput_mod.F90.in index 727c7d0dbcd..33024fd963e 100644 --- a/src/flib/pionfput_mod.F90.in +++ b/src/flib/pionfput_mod.F90.in @@ -1,4 +1,5 @@ #define __PIO_FILE__ "pionfput_mod.F90" +#include "config.h" !> !! @file !! @brief Write routines for non-decomposed NetCDF data. diff --git a/src/gptl/CMakeLists.txt b/src/gptl/CMakeLists.txt index 5f73687f23d..7b5e977f63a 100644 --- a/src/gptl/CMakeLists.txt +++ b/src/gptl/CMakeLists.txt @@ -95,7 +95,6 @@ endif () #===== MPI ===== if (PIO_USE_MPISERIAL) - find_package (MPISERIAL COMPONENTS C Fortran REQUIRED) if (MPISERIAL_C_FOUND AND MPISERIAL_Fortran_FOUND) target_compile_definitions (gptl PRIVATE HAVE_MPI) @@ -109,8 +108,7 @@ if (PIO_USE_MPISERIAL) set (MPI_C_LIBRARIES ${MPISERIAL_C_LIBRARIES}) set (MPI_Fortran_INCLUDE_PATH ${MPISERIAL_Fortran_INCLUDE_DIRS}) endif () -else () - find_package (MPI REQUIRED) +else() if (MPI_C_FOUND AND MPI_Fortran_FOUND) target_compile_definitions (gptl PUBLIC HAVE_MPI) diff --git a/src/ncint/ncintdispatch.c b/src/ncint/ncintdispatch.c index 6cd39f3caa2..78b2f577b7d 100644 --- a/src/ncint/ncintdispatch.c +++ b/src/ncint/ncintdispatch.c @@ -109,10 +109,10 @@ NC_Dispatch NCINT_dispatcher = { NC_NOTNC4_inq_enum_member, NC_NOTNC4_inq_enum_ident, NC_NOTNC4_def_opaque, - NC_NOTNC4_def_var_deflate, + PIO_NCINT_def_var_deflate, NC_NOTNC4_def_var_fletcher32, - NC_NOTNC4_def_var_chunking, - NC_NOTNC4_def_var_endian, + PIO_NCINT_def_var_chunking, + PIOc_def_var_endian, NC_NOTNC4_def_var_filter, NC_NOTNC4_set_var_chunk_cache, NC_NOTNC4_get_var_chunk_cache, @@ -871,7 +871,20 @@ PIO_NCINT_inq_var_all(int ncid, int varid, char *name, nc_type *xtypep, int *no_fill, void *fill_valuep, int *endiannessp, unsigned int *idp, size_t *nparamsp, unsigned int *params) { - return PIOc_inq_var(ncid, varid, name, xtypep, ndimsp, dimidsp, nattsp); + int ret; + + ret = PIOc_inq_var(ncid, varid, name, xtypep, ndimsp, dimidsp, nattsp); + + if (!ret) + ret = PIOc_inq_var_chunking(ncid, varid, contiguousp, (MPI_Offset *)chunksizesp); + + if (!ret) + ret = PIOc_inq_var_deflate(ncid, varid, shufflep, deflatep, deflate_levelp); + + if (!ret) + ret = PIOc_inq_var_endian(ncid, varid, endiannessp); + + return ret; } /** @@ -951,3 +964,55 @@ PIO_NCINT_inq_type_equal(int ncid1, nc_type typeid1, int ncid2, *equalp = typeid1 == typeid2 ? 1 : 0; return NC_NOERR; } + +/** + * @internal This functions sets deflate settings for a + * netCDF-4 variable. It is called by nc_def_var_deflate(). + * + * @param ncid the ncid of the open file. + * @param varid the ID of the variable. + * @param shuffle non-zero to turn on shuffle filter. + * @param deflate non-zero to turn on zlib compression for this + * variable. + * @param deflate_level 1 to 9, with 1 being faster and 9 being more + * compressed. + * + * @returns ::NC_NOERR for success + * @author Ed Hartnett + */ +int +PIO_NCINT_def_var_deflate(int ncid, int varid, int shuffle, int deflate, + int deflate_level) +{ + return PIOc_def_var_deflate(ncid, varid, shuffle, deflate, deflate_level); +} + +/** + * @internal Set chunksizes for a variable. + * + * This function only applies to netCDF-4 files. When used with netCDF + * classic files, the error PIO_ENOTNC4 will be returned. + * + * Chunksizes have important performance repercussions. NetCDF + * attempts to choose sensible chunk sizes by default, but for best + * performance check chunking against access patterns. + * + * See the netCDF + * variable documentation for details about the operation of this + * function. + * + * @param ncid the ncid of the open file. + * @param varid the ID of the variable to set chunksizes for. + * @param storage NC_CONTIGUOUS or NC_CHUNKED. + * @param chunksizesp an array of chunksizes. Must have a chunksize for + * every variable dimension. + * @return PIO_NOERR for success, otherwise an error code. + * @ingroup PIO_def_var_c + * @author Ed Hartnett + */ +int +PIO_NCINT_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp) +{ + return PIOc_def_var_chunking(ncid, varid, storage, (const PIO_Offset *)chunksizesp); +} diff --git a/src/ncint/ncintdispatch.h b/src/ncint/ncintdispatch.h index 5e0e8d4ba00..7204993b634 100644 --- a/src/ncint/ncintdispatch.h +++ b/src/ncint/ncintdispatch.h @@ -145,6 +145,14 @@ extern "C" { PIO_NCINT_inq_type_equal(int ncid1, nc_type typeid1, int ncid2, nc_type typeid2, int *equalp); + extern int + PIO_NCINT_def_var_deflate(int ncid, int varid, int shuffle, int deflate, + int deflate_level); + + extern int + PIO_NCINT_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp); + + #if defined(__cplusplus) } #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 115c732b51c..ebd9878d46b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -26,3 +26,7 @@ if (PIO_ENABLE_FORTRAN) message (STATUS "Cannot build performance test without gptl timing library") endif () endif() + +if (NETCDF_INTEGRATION) + add_subdirectory(ncint) +endif () diff --git a/tests/cunit/CMakeLists.txt b/tests/cunit/CMakeLists.txt index 7d0cfcda796..788641bb2ea 100644 --- a/tests/cunit/CMakeLists.txt +++ b/tests/cunit/CMakeLists.txt @@ -94,8 +94,7 @@ if (NOT PIO_USE_MPISERIAL) target_link_libraries (test_darray_fill pioc) add_executable (test_decomp_frame EXCLUDE_FROM_ALL test_decomp_frame.c test_common.c) target_link_libraries (test_decomp_frame pioc) - if (PIO_USE_MALLOC) - add_executable (test_perf2 EXCLUDE_FROM_ALL test_perf2.c test_common.c) + add_executable (test_perf2 EXCLUDE_FROM_ALL test_perf2.c test_common.c) target_link_libraries (test_perf2) add_executable (test_darray_async_simple EXCLUDE_FROM_ALL test_darray_async_simple.c test_common.c) target_link_libraries (test_darray_async_simple pioc) @@ -113,7 +112,8 @@ if (NOT PIO_USE_MPISERIAL) target_link_libraries (test_async_manyproc pioc) add_executable (test_async_1d EXCLUDE_FROM_ALL test_async_1d.c) target_link_libraries (test_async_1d pioc) - endif () + add_executable (test_simple EXCLUDE_FROM_ALL test_simple.c test_common.c) + target_link_libraries (test_simple pioc) endif () add_executable (test_spmd EXCLUDE_FROM_ALL test_spmd.c test_common.c) target_link_libraries (test_spmd pioc) @@ -136,23 +136,22 @@ add_dependencies (tests test_decomp_uneven) add_dependencies (tests test_decomps) add_dependencies (tests test_darray_fill) add_dependencies (tests test_decomp_frame) -if(PIO_USE_MALLOC) # add_dependencies (tests test_perf2) - add_dependencies (tests test_darray_async_simple) - add_dependencies (tests test_darray_async) - add_dependencies (tests test_darray_async_many) - add_dependencies (tests test_darray_2sync) - add_dependencies (tests test_async_multicomp) - add_dependencies (tests test_async_multi2) - add_dependencies (tests test_async_manyproc) - add_dependencies (tests test_async_1d) -endif () +add_dependencies (tests test_darray_async_simple) +add_dependencies (tests test_darray_async) +add_dependencies (tests test_darray_async_many) +add_dependencies (tests test_darray_2sync) +add_dependencies (tests test_async_multicomp) +add_dependencies (tests test_async_multi2) +add_dependencies (tests test_async_manyproc) +add_dependencies (tests test_async_1d) +add_dependencies (tests test_simple) # Test Timeout in seconds. if (PIO_VALGRIND_CHECK) set (DEFAULT_TEST_TIMEOUT 480) else () - set (DEFAULT_TEST_TIMEOUT 240) + set (DEFAULT_TEST_TIMEOUT 480) endif () # All tests need a certain number of tasks, but they should be able to @@ -162,6 +161,7 @@ set (AT_LEAST_TWO_TASKS 3) set (AT_LEAST_THREE_TASKS 4) set (AT_LEAST_FOUR_TASKS 5) set (AT_LEAST_EIGHT_TASKS 9) +set (EXACTLY_FOUR_TASKS 4) if (PIO_USE_MPISERIAL) add_test(NAME test_pioc @@ -275,40 +275,38 @@ else () EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_fill NUMPROCS ${AT_LEAST_FOUR_TASKS} TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - if(PIO_USE_MALLOC) - add_mpi_test(test_darray_2sync - EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_2sync - NUMPROCS ${AT_LEAST_FOUR_TASKS} - TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - add_mpi_test(test_darray_async_simple - EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_async_simple - NUMPROCS ${AT_LEAST_FOUR_TASKS} - TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(test_darray_2sync + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_2sync + NUMPROCS ${AT_LEAST_FOUR_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(test_darray_async_simple + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_async_simple + NUMPROCS ${AT_LEAST_FOUR_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) # add_mpi_test(test_perf2 # EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_perf2 # NUMPROCS ${AT_LEAST_FOUR_TASKS} # TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - add_mpi_test(test_darray_async - EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_async - NUMPROCS ${AT_LEAST_FOUR_TASKS} - TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - add_mpi_test(test_darray_async_many - EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_async_many - NUMPROCS ${AT_LEAST_FOUR_TASKS} - TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - add_mpi_test(test_async_multicomp - EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_async_multicomp - NUMPROCS ${AT_LEAST_FOUR_TASKS} - TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - add_mpi_test(test_async_multi2 - EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_async_multi2 - NUMPROCS ${AT_LEAST_FOUR_TASKS} - TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - add_mpi_test(test_async_manyproc - EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_async_manyproc - NUMPROCS ${AT_LEAST_EIGHT_TASKS} - TIMEOUT ${DEFAULT_TEST_TIMEOUT}) - endif () + add_mpi_test(test_darray_async + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_async + NUMPROCS ${AT_LEAST_FOUR_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(test_darray_async_many + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_darray_async_many + NUMPROCS ${AT_LEAST_FOUR_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(test_async_multicomp + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_async_multicomp + NUMPROCS ${AT_LEAST_FOUR_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(test_async_multi2 + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_async_multi2 + NUMPROCS ${AT_LEAST_FOUR_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(test_async_manyproc + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_async_manyproc + NUMPROCS ${AT_LEAST_EIGHT_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) add_mpi_test(test_decomp_uneven EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_decomp_uneven NUMPROCS ${AT_LEAST_FOUR_TASKS} @@ -317,5 +315,9 @@ else () EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_decomps NUMPROCS ${AT_LEAST_FOUR_TASKS} TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(test_simple + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/test_simple + NUMPROCS ${EXACTLY_FOUR_TASKS} + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) endif () MESSAGE("CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}") diff --git a/tests/cunit/Makefile.am b/tests/cunit/Makefile.am index 22e38106497..7a8edd61941 100644 --- a/tests/cunit/Makefile.am +++ b/tests/cunit/Makefile.am @@ -19,7 +19,7 @@ test_decomp_uneven test_decomps test_rearr test_darray_async_simple \ test_darray_async test_darray_async_many test_darray_2sync \ test_async_multicomp test_async_multi2 test_async_manyproc \ test_darray_fill test_decomp_frame test_perf2 test_async_perf \ -test_darray_vard test_async_1d test_darray_append +test_darray_vard test_async_1d test_darray_append test_simple if RUN_TESTS # Tests will run from a bash script. @@ -66,9 +66,12 @@ test_perf2_SOURCES = test_perf2.c test_common.c pio_tests.h test_async_perf_SOURCES = test_async_perf.c test_common.c pio_tests.h test_darray_vard_SOURCES = test_darray_vard.c test_common.c pio_tests.h test_async_1d_SOURCES = test_async_1d.c pio_tests.h +test_simple_SOURCES = test_simple.c test_common.c pio_tests.h # Distribute the test script. -EXTRA_DIST = run_tests.sh CMakeLists.txt test_darray_frame.c +EXTRA_DIST = run_tests.sh.in CMakeLists.txt test_darray_frame.c # Clean up files produced during testing. CLEANFILES = *.nc *.log decomp*.txt *.clog2 *.slog2 + +DISTCLEANFILES = run_tests.sh diff --git a/tests/cunit/pio_tests.h b/tests/cunit/pio_tests.h index 561b2c0376d..72948e53f26 100644 --- a/tests/cunit/pio_tests.h +++ b/tests/cunit/pio_tests.h @@ -64,6 +64,7 @@ void test_stop_mpe_log(int state, const char *msg); #define ERR_WRONG 1112 #define ERR_GPTL 1113 #define ERR_MPI 1114 +#define ERR_MEM 1115 /** The meaning of life, the universe, and everything. */ #define TEST_VAL_42 42 diff --git a/tests/cunit/run_tests.sh b/tests/cunit/run_tests.sh.in old mode 100755 new mode 100644 similarity index 89% rename from tests/cunit/run_tests.sh rename to tests/cunit/run_tests.sh.in index 39575e0f196..0d322960da6 --- a/tests/cunit/run_tests.sh +++ b/tests/cunit/run_tests.sh.in @@ -13,12 +13,12 @@ printf 'running PIO tests...\n' # test_darray_multivar3 PIO_TESTS='test_intercomm2 test_async_mpi test_spmd test_rearr test_async_simple '\ 'test_async_3proc test_async_4proc test_iosystem2_simple test_iosystem2_simple2 '\ -'test_iosystem2 test_iosystem3_simple test_iosystem3_simple2 test_iosystem3 test_pioc '\ +'test_iosystem2 test_iosystem3_simple test_iosystem3_simple2 test_iosystem3 test_simple test_pioc '\ 'test_pioc_unlim test_pioc_putget test_pioc_fill test_darray test_darray_multi '\ 'test_darray_multivar test_darray_multivar2 test_darray_1d '\ 'test_darray_3d test_decomp_uneven test_decomps test_darray_async_simple '\ 'test_darray_async test_darray_async_many test_darray_2sync test_async_multicomp '\ -'test_darray_fill test_darray_vard test_async_1d test_darray_append' +'test_darray_fill test_darray_vard test_async_1d test_darray_append test_simple' success1=true success2=true @@ -26,7 +26,7 @@ for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi @@ -38,7 +38,7 @@ for TEST in $PIO_TESTS_8 do success2=false echo "running ${TEST}" - mpiexec -n 8 ./${TEST} && success2=true + @WITH_MPIEXEC@ -n 8 ./${TEST} && success2=true if test $success2 = false; then break fi diff --git a/tests/cunit/test_common.c b/tests/cunit/test_common.c index df5d5997504..e6a2b615824 100644 --- a/tests/cunit/test_common.c +++ b/tests/cunit/test_common.c @@ -137,10 +137,9 @@ get_iotypes(int *num_flavors, int *flavors) num++; format[fmtidx++] = PIO_IOTYPE_PNETCDF; #endif -#ifdef _NETCDF + /* NetCDF is always present. */ num++; format[fmtidx++] = PIO_IOTYPE_NETCDF; -#endif #ifdef _NETCDF4 num += 2; format[fmtidx++] = PIO_IOTYPE_NETCDF4C; diff --git a/tests/cunit/test_darray_append.c b/tests/cunit/test_darray_append.c index 260668dbe55..d2e8b2113a0 100644 --- a/tests/cunit/test_darray_append.c +++ b/tests/cunit/test_darray_append.c @@ -79,7 +79,6 @@ int test_darray_append(int iosysid, int ioid, int num_flavors, int *flavor, int int varid; /* The ID of the netCDF varable. */ int varid2; /* The ID of a netCDF varable of different type. */ int varid3; /* the ID of a variable with no unlimited dimension. */ - int wrong_varid = TEST_VAL_42; /* A wrong ID. */ int ret; /* Return code. */ MPI_Datatype mpi_type; int type_size; /* size of a variable of type pio_type */ @@ -188,9 +187,6 @@ int test_darray_append(int iosysid, int ioid, int num_flavors, int *flavor, int if (other_type && (ret = PIOc_setframe(ncid, varid2, 0))) ERR(ret); - int frame = 0; - int flushtodisk = 0; - /* These should not work. */ if (PIOc_write_darray(ncid + TEST_VAL_42, varid, ioid, arraylen, test_data, fillvalue) != PIO_EBADID) ERR(ERR_WRONG); diff --git a/tests/cunit/test_darray_frame.c b/tests/cunit/test_darray_frame.c index 949e90ebfb4..41f43452360 100644 --- a/tests/cunit/test_darray_frame.c +++ b/tests/cunit/test_darray_frame.c @@ -192,7 +192,7 @@ int main(int argc, char **argv) /* Initialize test. */ if ((ret = pio_test_init2(argc, argv, &my_rank, &ntasks, MIN_NTASKS, - MIN_NTASKS, 3, &test_comm))) + MIN_NTASKS, -1, &test_comm))) ERR(ERR_INIT); if ((ret = PIOc_set_iosystem_error_handling(PIO_DEFAULT, PIO_RETURN_ERROR, NULL))) diff --git a/tests/cunit/test_iosystem3.c b/tests/cunit/test_iosystem3.c index 1c91b00c5c4..e63c7e38c67 100644 --- a/tests/cunit/test_iosystem3.c +++ b/tests/cunit/test_iosystem3.c @@ -56,7 +56,7 @@ int create_file(MPI_Comm comm, int iosysid, int format, char *filename, return ret; /* Write an attribute. */ - if ((ret = PIOc_put_att_text(ncid, varid, attname, strnlen(filename, PIO_TF_MAX_STR_LEN), + if ((ret = PIOc_put_att_text(ncid, varid, attname, strlen(filename), filename))) return ret; @@ -94,11 +94,11 @@ int check_file(MPI_Comm comm, int iosysid, int format, int ncid, char *filename, /* Check the attribute. Null terminating byte deliberately ignored * to match fortran code. */ - if (!(att_data = malloc(strnlen(filename, PIO_TF_MAX_STR_LEN) * sizeof(char)))) + if (!(att_data = malloc(strlen(filename) * sizeof(char)))) return PIO_ENOMEM; if ((ret = PIOc_get_att(ncid, varid, attname, att_data))) return ret; - if (strncmp(att_data, filename, strnlen(filename, PIO_TF_MAX_STR_LEN))) + if (strncmp(att_data, filename, strlen(filename))) return ERR_WRONG; free(att_data); diff --git a/tests/cunit/test_pioc.c b/tests/cunit/test_pioc.c index c85e341e4ab..46913328ba6 100644 --- a/tests/cunit/test_pioc.c +++ b/tests/cunit/test_pioc.c @@ -1570,18 +1570,19 @@ int test_nc4(int iosysid, int num_flavors, int *flavor, int my_rank) if ((ret = PIOc_def_var_chunking(ncid, 0, NC_CHUNKED, chunksize))) ERR(ret); - /* Setting deflate should not work with parallel iotype. */ - ret = PIOc_def_var_deflate(ncid, 0, 0, 1, 1); - if (flavor[fmt] == PIO_IOTYPE_NETCDF4P) - { - if (ret == PIO_NOERR) - ERR(ERR_WRONG); - } - else - { - if (ret != PIO_NOERR) - ERR(ERR_WRONG); - } + /* Setting deflate works with parallel iotype starting + * with netcdf-c-4.7.4. If present, HAVE_PAR_FILTERS will + * be defined. */ + ret = PIOc_def_var_deflate(ncid, 0, 0, 1, 1); +#ifdef HAVE_PAR_FILTERS + if (ret) + ERR(ret); +#else + if (flavor[fmt] == PIO_IOTYPE_NETCDF4C && ret) + ERR(ret); + if (flavor[fmt] == PIO_IOTYPE_NETCDF4P && !ret) + ERR(ERR_WRONG); +#endif /* Check that the inq_varname function works. */ if ((ret = PIOc_inq_varname(ncid, 0, NULL))) @@ -1611,10 +1612,18 @@ int test_nc4(int iosysid, int num_flavors, int *flavor, int my_rank) if (shuffle || !deflate || deflate_level != 1) ERR(ERR_AWFUL); - /* For parallel netCDF-4, no compression available. :-( */ + /* For parallel netCDF-4, we turned on deflate above, if + * HAVE_PAR_FILTERS is defined. */ if (flavor[fmt] == PIO_IOTYPE_NETCDF4P) - if (shuffle || deflate) + { +#ifdef HAVE_PAR_FILTERS + if (shuffle || !deflate || deflate_level != 1) + ERR(ERR_AWFUL); +#else + if (shuffle || deflate) ERR(ERR_AWFUL); +#endif /* HAVE_PAR_FILTERS */ + } /* Check setting the chunk cache for the variable. */ if ((ret = PIOc_set_var_chunk_cache(ncid, 0, VAR_CACHE_SIZE, VAR_CACHE_NELEMS, diff --git a/tests/cunit/test_simple.c b/tests/cunit/test_simple.c new file mode 100644 index 00000000000..630c7441b35 --- /dev/null +++ b/tests/cunit/test_simple.c @@ -0,0 +1,161 @@ +/* + * This very simple test for PIO runs on 4 ranks. + * + * @author Ed Hartnett + */ +#include +#include +#include + +/* The name of this test. */ +#define TEST_NAME "test_simple" +#define DIM_NAME "a_dim" +#define DIM_NAME_UNLIM "an_unlimited_dim" +#define VAR_NAME "a_var" +#define DIM_LEN 4 +#define NDIM1 1 +#define NDIM2 2 + +int main(int argc, char **argv) +{ + int my_rank; + int ntasks; + int num_iotasks = 1; + int iosysid, ioid; + int gdimlen, elements_per_pe; + PIO_Offset *compmap; + int ncid, dimid[NDIM2], varid; + int num_flavors; /* Number of PIO netCDF flavors in this build. */ + int flavor[NUM_FLAVORS]; /* iotypes for the supported netCDF IO flavors. */ + int *data, *data_in; + int i, f; + int ret; + + /* Initialize MPI. */ + if ((ret = MPI_Init(&argc, &argv))) + MPIERR(ret); + + /* Learn my rank and the total number of processors. */ + if ((ret = MPI_Comm_rank(MPI_COMM_WORLD, &my_rank))) + MPIERR(ret); + if ((ret = MPI_Comm_size(MPI_COMM_WORLD, &ntasks))) + MPIERR(ret); + + /* PIOc_set_log_level(4); */ + if (ntasks != 1 && ntasks != 4) + { + if (!my_rank) + printf("Test must be run on 1 or 4 tasks.\n"); + return ERR_AWFUL; + } + + /* Turn off logging, to prevent error messages from being logged + * when we intentionally call functions we know will fail. */ + PIOc_set_log_level(-1); + + /* Change error handling so we can test inval parameters. */ + if ((ret = PIOc_set_iosystem_error_handling(PIO_DEFAULT, PIO_RETURN_ERROR, NULL))) + ERR(ret); + + /* Initialize the IOsystem. */ + if ((ret = PIOc_Init_Intracomm(MPI_COMM_WORLD, num_iotasks, 1, 0, PIO_REARR_BOX, + &iosysid))) + ERR(ret); + + /* Find out which IOtypes are available in this build by calling + * this function from test_common.c. */ + if ((ret = get_iotypes(&num_flavors, flavor))) + ERR(ret); + + /* Initialize the decomposition. */ + gdimlen = DIM_LEN; + elements_per_pe = DIM_LEN/ntasks; + if (!(compmap = malloc(elements_per_pe * sizeof(PIO_Offset)))) + ERR(ERR_MEM); + for (i = 0; i < elements_per_pe; i++) + compmap[i] = my_rank + i; + if ((ret = PIOc_init_decomp(iosysid, PIO_INT, NDIM1, &gdimlen, elements_per_pe, compmap, + &ioid, PIO_REARR_BOX, NULL, NULL))) + ERR(ret); + free(compmap); + + /* Create one record of data. */ + if (!(data = malloc(elements_per_pe * sizeof(int)))) + ERR(ERR_MEM); + for (i = 0; i < elements_per_pe; i++) + data[i] = my_rank + i; + + /* Storage to read one record back in. */ + if (!(data_in = malloc(elements_per_pe * sizeof(int)))) + ERR(ERR_MEM); + + /* Create a file with each available IOType. */ + for (f = 0; f < num_flavors; f++) + { + char filename[NC_MAX_NAME + 1]; + + /* Create a file. */ + sprintf(filename, "%s_%d.nc", TEST_NAME, flavor[f]); + if ((ret = PIOc_createfile(iosysid, &ncid, &flavor[f], filename, NC_CLOBBER))) + ERR(ret); + + /* Define dims. */ + if ((ret = PIOc_def_dim(ncid, DIM_NAME_UNLIM, PIO_UNLIMITED, &dimid[0]))) + ERR(ret); + if ((ret = PIOc_def_dim(ncid, DIM_NAME, DIM_LEN, &dimid[1]))) + ERR(ret); + + /* Define a var. */ + if ((ret = PIOc_def_var(ncid, VAR_NAME, PIO_INT, NDIM2, dimid, &varid))) + ERR(ret); + if ((ret = PIOc_enddef(ncid))) + ERR(ret); + + /* Write a record of data. Each compute task writes its local + * array of data. */ + if ((ret = PIOc_setframe(ncid, varid, 0))) + ERR(ret); + if ((ret = PIOc_write_darray(ncid, varid, ioid, elements_per_pe, data, NULL))) + ERR(ret); + + /* Close the file. */ + if ((ret = PIOc_closefile(ncid))) + ERR(ret); + + /* Check the file. */ + { + /* Reopen the file. */ + if ((ret = PIOc_openfile(iosysid, &ncid, &flavor[f], filename, NC_NOWRITE))) + ERR(ret); + + /* Read the local array of data for this task and confirm correctness. */ + if ((ret = PIOc_setframe(ncid, varid, 0))) + ERR(ret); + if ((ret = PIOc_read_darray(ncid, varid, ioid, elements_per_pe, data_in))) + ERR(ret); + for (i = 0; i < elements_per_pe; i++) + if (data_in[i] != data[i]) ERR(ERR_WRONG); + + /* Close the file. */ + if ((ret = PIOc_closefile(ncid))) + ERR(ret); + } + } /* next IOType */ + + /* Free resources. */ + free(data); + free(data_in); + if ((ret = PIOc_freedecomp(iosysid, ioid))) + ERR(ret); + + /* Finalize the IOsystem. */ + if ((ret = PIOc_finalize(iosysid))) + ERR(ret); + + printf("%d %s SUCCESS!!\n", my_rank, TEST_NAME); + + /* Finalize MPI. */ + MPI_Finalize(); + + return 0; +} diff --git a/tests/fncint/Makefile.am b/tests/fncint/Makefile.am index f45c1ca5810..3437e54570c 100644 --- a/tests/fncint/Makefile.am +++ b/tests/fncint/Makefile.am @@ -3,8 +3,8 @@ # Ed Hartnett 7/3/19 -# Put together AM_CPPFLAGS and AM_LDFLAGS. -include $(top_srcdir)/set_flags.am +# Find the pio.mod file. +AM_CPPFLAGS = -I$(top_srcdir)/src/flib # Link to the PIO Fortran and C libraries. LDADD = ${top_builddir}/src/flib/libpiof.la ${top_builddir}/src/clib/libpioc.la @@ -33,3 +33,5 @@ EXTRA_DIST = run_tests.sh # Clean up files produced during testing. CLEANFILES = *.nc *.log + +DISTCLEANFILES = run_tests.sh diff --git a/tests/fncint/run_tests.sh b/tests/fncint/run_tests.sh.in similarity index 90% rename from tests/fncint/run_tests.sh rename to tests/fncint/run_tests.sh.in index 1c4121b9155..4d9ea52e636 100755 --- a/tests/fncint/run_tests.sh +++ b/tests/fncint/run_tests.sh.in @@ -16,7 +16,7 @@ for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi diff --git a/tests/general/Makefile.am b/tests/general/Makefile.am index 68ece2cd2fd..2a198588898 100644 --- a/tests/general/Makefile.am +++ b/tests/general/Makefile.am @@ -6,11 +6,11 @@ # Parallel builds don't currently work in this directory. .NOTPARALLEL: -# Put together AM_CPPFLAGS and AM_LDFLAGS. -include $(top_srcdir)/set_flags.am +# Find the pio.mod file. +AM_CPPFLAGS = -I$(top_srcdir)/src/flib -LDADD = libpio_tutil.la \ -${top_builddir}/src/flib/libpiof.la \ +# Link to our test, fortran, and C libraries. +LDADD = libpio_tutil.la ${top_builddir}/src/flib/libpiof.la \ ${top_builddir}/src/clib/libpioc.la # There is a test utility mod file in this subdir which must be built. @@ -89,7 +89,7 @@ pio_rearr_opts2.F90:pio_rearr_opts2.F90.in pio_rearr_opts.F90:pio_rearr_opts.F90.in # Distribute the test script. -EXTRA_DIST = CMakeLists.txt run_tests.sh ncdf_fail.F90.in \ +EXTRA_DIST = CMakeLists.txt run_tests.sh.in ncdf_fail.F90.in \ ncdf_get_put.F90.in ncdf_inq.F90.in ncdf_simple_tests.F90.in \ pio_decomp_fillval.F90.in pio_decomp_frame_tests.F90.in \ pio_decomp_tests_1d.F90.in pio_decomp_tests_2d.F90.in \ @@ -101,3 +101,5 @@ pio_rearr_opts2.F90.in pio_rearr_opts.F90.in # Clean up files produced during testing. CLEANFILES = *.nc *.log *.mod + +DISTCLEANFILES = run_tests.sh diff --git a/tests/general/ncdf_fail.F90.in b/tests/general/ncdf_fail.F90.in index dfc09148a49..eed98aad6fa 100644 --- a/tests/general/ncdf_fail.F90.in +++ b/tests/general/ncdf_fail.F90.in @@ -1,3 +1,4 @@ +#include "config.h" MODULE ncdf_fail_tgv use pio_tutil implicit none diff --git a/tests/general/ncdf_get_put.F90.in b/tests/general/ncdf_get_put.F90.in index 7453fe32ede..2d00474cd00 100644 --- a/tests/general/ncdf_get_put.F90.in +++ b/tests/general/ncdf_get_put.F90.in @@ -1,3 +1,4 @@ +#include "config.h" PIO_TF_TEMPLATE PIO_TF_AUTO_TEST_SUB_BEGIN test_put_1datt Implicit none diff --git a/tests/general/ncdf_inq.F90.in b/tests/general/ncdf_inq.F90.in index 51586d7df27..9745bd1b8e2 100644 --- a/tests/general/ncdf_inq.F90.in +++ b/tests/general/ncdf_inq.F90.in @@ -1,3 +1,4 @@ +#include "config.h" MODULE ncdf_inq_tests_tgv use pio_tutil character(len=PIO_TF_MAX_STR_LEN), parameter :: tgv_fname = "pio_ncdf_inq_test_file.nc" diff --git a/tests/general/ncdf_simple_tests.F90.in b/tests/general/ncdf_simple_tests.F90.in index 272997d0a1c..12368f13000 100644 --- a/tests/general/ncdf_simple_tests.F90.in +++ b/tests/general/ncdf_simple_tests.F90.in @@ -1,3 +1,4 @@ +#include "config.h" MODULE ncdf_simple_tests_tgv use pio_tutil ! tgv in prefix corresponds to module name (ncdf_simple_tests_tgv) diff --git a/tests/general/pio_decomp_fillval.F90.in b/tests/general/pio_decomp_fillval.F90.in index 432adbfbfe3..0e5c7cb34b9 100644 --- a/tests/general/pio_decomp_fillval.F90.in +++ b/tests/general/pio_decomp_fillval.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! nc write 1d array with fillvalues (the holes are explicitly specified) PIO_TF_TEMPLATE PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_explicit_fval @@ -14,6 +15,8 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_explicit_fval PIO_TF_FC_DATA_TYPE, dimension(VEC_LOCAL_SZ) :: wbuf, rbuf, exp_val ! The buffer fillvalue to be used when writing data PIO_TF_FC_DATA_TYPE, PARAMETER :: BUF_FILLVAL = -2 + integer :: no_fill + PIO_TF_FC_DATA_TYPE :: fillval integer, dimension(1) :: dims integer :: pio_dim integer :: i, ierr @@ -49,7 +52,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_explicit_fval write(filename,'(a,i1)') "test_pio_decomp_fillval_tests.testfile",i PIO_TF_LOG(0,*) "Testing : PIO_TF_DATA_TYPE : ", iotype_descs(i) - ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) + ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) PIO_TF_CHECK_ERR(ierr, "Could not create file " // trim(filename)) ierr = PIO_def_dim(pio_file, 'PIO_TF_test_dim', dims(1), pio_dim) @@ -72,8 +75,10 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_explicit_fval call PIO_read_darray(pio_file, pio_var, riodesc, rbuf, ierr) PIO_TF_CHECK_ERR(ierr, "Failed to read darray : " // trim(filename)) - PIO_TF_CHECK_VAL((rbuf, exp_val), "Got wrong val") + ierr = PIO_inq_var_fill(pio_file, pio_var, no_fill, fillval) + PIO_TF_CHECK_ERR(ierr, "Failed to inquire var fill: " // trim(filename)) + PIO_TF_CHECK_VAL((fillval, BUF_FILLVAL), "Got wrong val") call PIO_closefile(pio_file) call PIO_deletefile(pio_tf_iosystem_, filename) @@ -104,6 +109,8 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_implicit_fval ! The buffer fillvalue to be used when writing data PIO_TF_FC_DATA_TYPE, PARAMETER :: BUF_FILLVAL = -2 integer, dimension(1) :: dims + integer :: no_fill + PIO_TF_FC_DATA_TYPE :: fillval integer :: pio_dim integer :: i, ierr ! iotypes = valid io types @@ -113,7 +120,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_implicit_fval ! compdof is only specified for valid data values, the data holes are ! implicitly stated (by not specifying them rather than filling it with 0s) - wcompdof_sz = min(pio_tf_world_rank_+1, VEC_LOCAL_SZ) + wcompdof_sz = min(pio_tf_world_rank_+1, VEC_LOCAL_SZ) allocate(wcompdof(wcompdof_sz)) allocate(wbuf(wcompdof_sz)) @@ -125,7 +132,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_implicit_fval do i=1,wcompdof_sz wcompdof(i) = VEC_LOCAL_SZ * pio_tf_world_rank_ + compdof_rel_disps(i) end do - ! Read everything - including fillvalues that should have been + ! Read everything - including fillvalues that should have been ! written for locations unspecified in wcompdof(:) i.e., ! wcompdof(wcompdof_sz:VEC_LOCAL_SZ] rcompdof = VEC_LOCAL_SZ * pio_tf_world_rank_ + compdof_rel_disps @@ -136,7 +143,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_implicit_fval wbuf(i) = wcompdof(i) exp_val(i) = wbuf(i) end do - ! We expect the values (wcompdof_sz:VEC_LOCAL_SZ] to be read as + ! We expect the values (wcompdof_sz:VEC_LOCAL_SZ] to be read as ! user specified fill values do i=wcompdof_sz+1,VEC_LOCAL_SZ exp_val(i) = BUF_FILLVAL @@ -151,7 +158,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_implicit_fval filename = "test_pio_decomp_fillval_tests.testfile" do i=1,num_iotypes PIO_TF_LOG(0,*) "Testing : PIO_TF_DATA_TYPE : ", iotype_descs(i) - ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) + ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) PIO_TF_CHECK_ERR(ierr, "Could not create file " // trim(filename)) ierr = PIO_def_dim(pio_file, 'PIO_TF_test_dim', dims(1), pio_dim) @@ -174,8 +181,10 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_write_1d_implicit_fval call PIO_read_darray(pio_file, pio_var, riodesc, rbuf, ierr) PIO_TF_CHECK_ERR(ierr, "Failed to read darray : " // trim(filename)) - PIO_TF_CHECK_VAL((rbuf, exp_val), "Got wrong val") + ierr = PIO_inq_var_fill(pio_file, pio_var, no_fill, fillval) + PIO_TF_CHECK_ERR(ierr, "Failed to inquire var fill: " // trim(filename)) + PIO_TF_CHECK_VAL((fillval, BUF_FILLVAL), "Got wrong val") call PIO_closefile(pio_file) call PIO_deletefile(pio_tf_iosystem_, filename) @@ -201,11 +210,14 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_read_1d_explicit_fval character(len=PIO_TF_MAX_STR_LEN) :: filename type(io_desc_t) :: wiodesc, riodesc integer, dimension(VEC_LOCAL_SZ) :: wcompdof, rcompdof, compdof_rel_disps - ! Compdof value to suggest that data point is a hole + ! Compdof value to suggest that data point is a hole integer, parameter :: PIO_COMPDOF_FILLVAL = 0 PIO_TF_FC_DATA_TYPE, dimension(VEC_LOCAL_SZ) :: wbuf, rbuf, exp_val ! The buffer fillvalue used to initialize data PIO_TF_FC_DATA_TYPE, PARAMETER :: BUF_FILLVAL = -2 + ! fillvalue returned from pio_inq_var_fill + PIO_TF_FC_DATA_TYPE :: fillval + integer, dimension(1) :: dims integer :: pio_dim integer :: i, ierr @@ -213,6 +225,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_read_1d_explicit_fval integer, dimension(:), allocatable :: iotypes character(len=PIO_TF_MAX_STR_LEN), dimension(:), allocatable :: iotype_descs integer :: num_iotypes + integer :: no_fill ! used for pio_inq_var_fill do i=1,VEC_LOCAL_SZ compdof_rel_disps(i) = i @@ -228,7 +241,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_read_1d_explicit_fval ! We don't want to read even indices (BUF_FILLVAL == -2) do i=1,VEC_LOCAL_SZ,2 rcompdof(i) = PIO_COMPDOF_FILLVAL - exp_val(i) = BUF_FILLVAL + exp_val(i) = PIO_COMPDOF_FILLVAL end do call PIO_initdecomp(pio_tf_iosystem_, PIO_TF_DATA_TYPE, dims, wcompdof, wiodesc) @@ -240,9 +253,11 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_read_1d_explicit_fval filename = "test_pio_decomp_fillval_tests.testfile" do i=1,num_iotypes PIO_TF_LOG(0,*) "Testing : PIO_TF_DATA_TYPE : ", iotype_descs(i) - ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) + ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) PIO_TF_CHECK_ERR(ierr, "Could not create file " // trim(filename)) + PIO_TF_LOG(0,*) "Testing : filename : ", trim(filename) + ierr = PIO_def_dim(pio_file, 'PIO_TF_test_dim', dims(1), pio_dim) PIO_TF_CHECK_ERR(ierr, "Failed to define a dim : " // trim(filename)) @@ -266,6 +281,11 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_read_1d_explicit_fval PIO_TF_CHECK_VAL((rbuf, exp_val), "Got wrong val") + ierr = PIO_inq_var_fill(pio_file, pio_var, no_fill, fillval) + PIO_TF_CHECK_ERR(ierr, "Failed to inquire var fill: " // trim(filename)) + PIO_TF_CHECK_VAL((fillval, BUF_FILLVAL), "Got wrong val") + + call PIO_closefile(pio_file) call PIO_deletefile(pio_tf_iosystem_, filename) end do @@ -303,7 +323,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_read_1d_implicit_fval ! compdof is only specified for valid data values, the data holes are ! implicitly stated (by not specifying them rather than filling it with 0s) - rcompdof_sz = min(pio_tf_world_rank_+1, VEC_LOCAL_SZ) + rcompdof_sz = min(pio_tf_world_rank_+1, VEC_LOCAL_SZ) allocate(rcompdof(rcompdof_sz)) allocate(rbuf(rcompdof_sz)) allocate(exp_val(rcompdof_sz)) @@ -333,7 +353,7 @@ PIO_TF_AUTO_TEST_SUB_BEGIN nc_read_1d_implicit_fval filename = "test_pio_decomp_fillval_tests.testfile" do i=1,num_iotypes PIO_TF_LOG(0,*) "Testing : PIO_TF_DATA_TYPE : ", iotype_descs(i) - ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) + ierr = PIO_createfile(pio_tf_iosystem_, pio_file, iotypes(i), filename, PIO_CLOBBER) PIO_TF_CHECK_ERR(ierr, "Could not create file " // trim(filename)) ierr = PIO_def_dim(pio_file, 'PIO_TF_test_dim', dims(1), pio_dim) diff --git a/tests/general/pio_decomp_frame_tests.F90.in b/tests/general/pio_decomp_frame_tests.F90.in index 791d748052b..70edaf6fbbd 100644 --- a/tests/general/pio_decomp_frame_tests.F90.in +++ b/tests/general/pio_decomp_frame_tests.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Get a 3D column decomposition ! If force_rearrange is FALSE, the decomposition is such that ! # All even procs have VEC_HGT_SZ blocks of diff --git a/tests/general/pio_decomp_tests.F90.in b/tests/general/pio_decomp_tests.F90.in index b6d7f06d0a4..cb6f9398691 100644 --- a/tests/general/pio_decomp_tests.F90.in +++ b/tests/general/pio_decomp_tests.F90.in @@ -1,3 +1,4 @@ +#include "config.h" PIO_TF_AUTO_TEST_SUB_BEGIN init_decomp_1d_get_loc_sz implicit none integer, parameter :: VEC_LOCAL_SZ = 7 diff --git a/tests/general/pio_decomp_tests_1d.F90.in b/tests/general/pio_decomp_tests_1d.F90.in index 866be4c4a8f..52acc3eb4c9 100644 --- a/tests/general/pio_decomp_tests_1d.F90.in +++ b/tests/general/pio_decomp_tests_1d.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Get a block cyclic decomposition ! If force_rearrange is FALSE, the decomposition is such that ! # All even procs have VEC_LOCAL_SZ elements diff --git a/tests/general/pio_decomp_tests_2d.F90.in b/tests/general/pio_decomp_tests_2d.F90.in index 5cd711294f7..25b2a488432 100644 --- a/tests/general/pio_decomp_tests_2d.F90.in +++ b/tests/general/pio_decomp_tests_2d.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Get a 2D column decomposition ! If force_rearrange is FALSE, the decomposition is such that ! # All even procs have VEC_COL_SZ rows of VEC_ROW_SZ elements diff --git a/tests/general/pio_decomp_tests_3d.F90.in b/tests/general/pio_decomp_tests_3d.F90.in index 79569dbaa4e..17a20b2d0e7 100644 --- a/tests/general/pio_decomp_tests_3d.F90.in +++ b/tests/general/pio_decomp_tests_3d.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Get a 3D column decomposition ! If force_rearrange is FALSE, the decomposition is such that ! # All even procs have VEC_HGT_SZ blocks of diff --git a/tests/general/pio_fail.F90.in b/tests/general/pio_fail.F90.in index 464fc5c5d2a..796670bd87f 100644 --- a/tests/general/pio_fail.F90.in +++ b/tests/general/pio_fail.F90.in @@ -1,3 +1,4 @@ +#include "config.h" PIO_TF_AUTO_TEST_SUB_BEGIN fail_rank_even LOGICAL cond ! Even procs fail diff --git a/tests/general/pio_file_fail.F90.in b/tests/general/pio_file_fail.F90.in index a4b99acb43c..8ef10631809 100644 --- a/tests/general/pio_file_fail.F90.in +++ b/tests/general/pio_file_fail.F90.in @@ -1,3 +1,4 @@ +#include "config.h" PIO_TF_TEST_SUB_BEGIN create_file_always_fail(iotype, filename) implicit none integer, intent(in) :: iotype diff --git a/tests/general/pio_file_simple_tests.F90.in b/tests/general/pio_file_simple_tests.F90.in index af5604b1798..9fc177ec42a 100644 --- a/tests/general/pio_file_simple_tests.F90.in +++ b/tests/general/pio_file_simple_tests.F90.in @@ -1,3 +1,4 @@ +#include "config.h" PIO_TF_TEST_SUB_BEGIN create_file_no_opts(iotype, filename) implicit none integer, intent(in) :: iotype diff --git a/tests/general/pio_init_finalize.F90.in b/tests/general/pio_init_finalize.F90.in index ab36f00b6f2..27e03f8ea76 100644 --- a/tests/general/pio_init_finalize.F90.in +++ b/tests/general/pio_init_finalize.F90.in @@ -1,3 +1,4 @@ +#include "config.h" PIO_TF_AUTO_TEST_SUB_BEGIN init_finalize ! The default test driver should initialize and finalize PIO PRINT *, "Hello world" diff --git a/tests/general/pio_iosystem_tests.F90.in b/tests/general/pio_iosystem_tests.F90.in index c5610c5b0ad..2bbf399ec16 100644 --- a/tests/general/pio_iosystem_tests.F90.in +++ b/tests/general/pio_iosystem_tests.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Split comm world into two comms (one with even procs and the other ! with odd procs SUBROUTINE split_world_odd_even(new_comm, new_rank, new_size, is_even) diff --git a/tests/general/pio_iosystem_tests2.F90.in b/tests/general/pio_iosystem_tests2.F90.in index 50a900b4a3d..6d900b73336 100644 --- a/tests/general/pio_iosystem_tests2.F90.in +++ b/tests/general/pio_iosystem_tests2.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Split comm world into two comms (one with even procs and the other ! with odd procs SUBROUTINE split_world_odd_even(new_comm, new_rank, new_size, is_even) diff --git a/tests/general/pio_iosystem_tests3.F90.in b/tests/general/pio_iosystem_tests3.F90.in index fad87a4beb5..6477e05b067 100644 --- a/tests/general/pio_iosystem_tests3.F90.in +++ b/tests/general/pio_iosystem_tests3.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Split comm world into two comms (even procs and odd procs) and ! rank == overlapped_rank included in both comms SUBROUTINE split_world_two_with_overlap(new_comms, new_ranks, new_sizes, overlapped_rank) diff --git a/tests/general/pio_rearr.F90.in b/tests/general/pio_rearr.F90.in index 1cddf87707a..202ad109585 100644 --- a/tests/general/pio_rearr.F90.in +++ b/tests/general/pio_rearr.F90.in @@ -1,3 +1,4 @@ +#include "config.h" ! Create a file with a global attribute (filename) SUBROUTINE create_file(comm, iosys, iotype, fname, attname, dimname, ret) use pio_tutil diff --git a/tests/general/pio_rearr_opts.F90.in b/tests/general/pio_rearr_opts.F90.in index a47695cb752..d209860c2f7 100644 --- a/tests/general/pio_rearr_opts.F90.in +++ b/tests/general/pio_rearr_opts.F90.in @@ -1,3 +1,4 @@ +#include "config.h" MODULE pio_rearr_opts_tgv use pio_tutil character(len=PIO_TF_MAX_STR_LEN), parameter ::tgv_fname ="pio_rearr_opts_test.nc" diff --git a/tests/general/pio_rearr_opts2.F90.in b/tests/general/pio_rearr_opts2.F90.in index a46565b5e59..0d6a48c8a83 100644 --- a/tests/general/pio_rearr_opts2.F90.in +++ b/tests/general/pio_rearr_opts2.F90.in @@ -1,3 +1,4 @@ +#include "config.h" MODULE pio_rearr_opts_tgv use pio_tutil character(len=PIO_TF_MAX_STR_LEN), parameter ::tgv_fname ="pio_rearr_opts2_test.nc" diff --git a/tests/general/run_tests.sh b/tests/general/run_tests.sh.in similarity index 94% rename from tests/general/run_tests.sh rename to tests/general/run_tests.sh.in index 63d89e56092..b847f84acc8 100755 --- a/tests/general/run_tests.sh +++ b/tests/general/run_tests.sh.in @@ -23,7 +23,7 @@ for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi diff --git a/tests/general/util/pio_tf_f90gen.pl b/tests/general/util/pio_tf_f90gen.pl index 8c493f717b1..10b7c087749 100755 --- a/tests/general/util/pio_tf_f90gen.pl +++ b/tests/general/util/pio_tf_f90gen.pl @@ -54,7 +54,7 @@ sub init_predef_types $template_predef_typename_types{"PIO_TF_DATA_TYPE"} = []; $template_predef_typename_types{"PIO_TF_FC_DATA_TYPE"} = []; push(@{$template_predef_typename_types{"PIO_TF_DATA_TYPE"}}, "PIO_int"); - push(@{$template_predef_typename_types{"PIO_TF_FC_DATA_TYPE"}}, "integer"); + push(@{$template_predef_typename_types{"PIO_TF_FC_DATA_TYPE"}}, "integer(kind=fc_int)"); push(@{$template_predef_typename_types{"PIO_TF_DATA_TYPE"}}, "PIO_short"); push(@{$template_predef_typename_types{"PIO_TF_FC_DATA_TYPE"}}, "integer(kind=fc_short)"); push(@{$template_predef_typename_types{"PIO_TF_DATA_TYPE"}}, "PIO_real"); @@ -566,9 +566,9 @@ sub parse_and_store_gen_templ_funcs } if($annotate_source){ if($out_line =~ /[^#]/){ - $out_line .= "\n"; + $out_line .= "\n"; }else{ - $out_line = $out_line . " ! $base_file_name:$ifline_num" . "\n"; + $out_line = $out_line . " ! $base_file_name:$ifline_num" . "\n"; } } if($verbose) { print "Adding \"$out_line\" to ${$ref_templ_funcname}\n"; } diff --git a/tests/general/util/pio_tutil.F90 b/tests/general/util/pio_tutil.F90 index 181c897f88d..92fecc0c8ed 100644 --- a/tests/general/util/pio_tutil.F90 +++ b/tests/general/util/pio_tutil.F90 @@ -35,6 +35,7 @@ MODULE pio_tutil ! integer types INTEGER, PARAMETER, PUBLIC :: fc_short = selected_int_kind(4) + INTEGER, PARAMETER, PUBLIC :: fc_int = selected_int_kind(6) ! Misc constants INTEGER, PARAMETER :: PIO_TF_MAX_STR_LEN=100 @@ -91,6 +92,10 @@ MODULE pio_tutil ! integer arrays INTERFACE PIO_TF_Check_val_ MODULE PROCEDURE & + PIO_TF_Check_int_val_val, & + PIO_TF_Check_short_val_val, & + PIO_TF_Check_real_val_val, & + PIO_TF_Check_double_val_val, & PIO_TF_Check_int_arr_val, & PIO_TF_Check_int_arr_arr, & PIO_TF_Check_int_arr_arr_tol, & @@ -295,11 +300,9 @@ SUBROUTINE PIO_TF_Get_nc_iotypes(iotypes, iotype_descs, num_iotypes) ! netcdf, netcdf4p, netcdf4c num_iotypes = num_iotypes + 3 #else -#ifdef _NETCDF - ! netcdf + ! netcdf is always present. num_iotypes = num_iotypes + 1 #endif -#endif #ifdef _PNETCDF ! pnetcdf num_iotypes = num_iotypes + 1 @@ -328,12 +331,10 @@ SUBROUTINE PIO_TF_Get_nc_iotypes(iotypes, iotype_descs, num_iotypes) iotype_descs(i) = "NETCDF4P" i = i + 1 #else -#ifdef _NETCDF - ! netcdf + ! netcdf is always present. iotypes(i) = PIO_iotype_netcdf iotype_descs(i) = "NETCDF" i = i + 1 -#endif #endif END SUBROUTINE @@ -355,14 +356,6 @@ SUBROUTINE PIO_TF_Get_undef_nc_iotypes(iotypes, iotype_descs, num_iotypes) num_iotypes = 0 ! First find the number of io types -#ifndef _NETCDF - ! netcdf - num_iotypes = num_iotypes + 1 -#ifndef _NETCDF4 - ! netcdf4p, netcdf4c - num_iotypes = num_iotypes + 2 -#endif -#endif #ifndef _PNETCDF ! pnetcdf num_iotypes = num_iotypes + 1 @@ -378,21 +371,6 @@ SUBROUTINE PIO_TF_Get_undef_nc_iotypes(iotypes, iotype_descs, num_iotypes) iotypes(i) = PIO_iotype_pnetcdf iotype_descs(i) = "PNETCDF" i = i + 1 -#endif -#ifndef _NETCDF - ! netcdf - iotypes(i) = PIO_iotype_netcdf - iotype_descs(i) = "NETCDF" - i = i + 1 -#ifndef _NETCDF4 - ! netcdf4p, netcdf4c - iotypes(i) = PIO_iotype_netcdf4c - iotype_descs(i) = "NETCDF4C" - i = i + 1 - iotypes(i) = PIO_iotype_netcdf4p - iotype_descs(i) = "NETCDF4P" - i = i + 1 -#endif #endif END SUBROUTINE @@ -416,11 +394,9 @@ SUBROUTINE PIO_TF_Get_iotypes(iotypes, iotype_descs, num_iotypes) ! netcdf, netcdf4p, netcdf4c num_iotypes = num_iotypes + 3 #else -#ifdef _NETCDF - ! netcdf + ! netcdf is always present. num_iotypes = num_iotypes + 1 #endif -#endif #ifdef _PNETCDF ! pnetcdf num_iotypes = num_iotypes + 1 @@ -449,12 +425,10 @@ SUBROUTINE PIO_TF_Get_iotypes(iotypes, iotype_descs, num_iotypes) iotype_descs(i) = "NETCDF4P" i = i + 1 #else -#ifdef _NETCDF - ! netcdf + ! netcdf is always present. iotypes(i) = PIO_iotype_netcdf iotype_descs(i) = "NETCDF" i = i + 1 -#endif #endif END SUBROUTINE @@ -476,14 +450,6 @@ SUBROUTINE PIO_TF_Get_undef_iotypes(iotypes, iotype_descs, num_iotypes) ! First find the number of io types num_iotypes = 0 -#ifndef _NETCDF - ! netcdf - num_iotypes = num_iotypes + 1 -#ifndef _NETCDF4 - ! netcdf4p, netcdf4c - num_iotypes = num_iotypes + 2 -#endif -#endif #ifndef _PNETCDF ! pnetcdf num_iotypes = num_iotypes + 1 @@ -494,27 +460,6 @@ SUBROUTINE PIO_TF_Get_undef_iotypes(iotypes, iotype_descs, num_iotypes) ALLOCATE(iotype_descs(num_iotypes)) i = 1 -#ifndef _NETCDF - ! netcdf - iotypes(i) = PIO_iotype_netcdf - iotype_descs(i) = "NETCDF" - i = i + 1 -#ifndef _PNETCDF - ! pnetcdf - iotypes(i) = PIO_iotype_pnetcdf - iotype_descs(i) = "PNETCDF" - i = i + 1 -#endif -#ifndef _NETCDF4 - ! netcdf4p, netcdf4c - iotypes(i) = PIO_iotype_netcdf4c - iotype_descs(i) = "NETCDF4C" - i = i + 1 - iotypes(i) = PIO_iotype_netcdf4p - iotype_descs(i) = "NETCDF4P" - i = i + 1 -#endif -#endif END SUBROUTINE ! Returns a list of PIO base types @@ -666,6 +611,27 @@ LOGICAL FUNCTION PIO_TF_Check_int_arr_arr_tol(arr, exp_arr, tol) PIO_TF_Check_int_arr_arr_tol = PIO_TF_Check_int_arr_arr(arr, exp_arr) END FUNCTION + LOGICAL FUNCTION PIO_TF_Check_int_val_val(val1, val2) + INTEGER, INTENT(IN) :: val1, val2 + + PIO_TF_Check_int_val_val = val1 == val2 + END FUNCTION + LOGICAL FUNCTION PIO_TF_Check_short_val_val(val1, val2) + INTEGER(kind=fc_short), INTENT(IN) :: val1, val2 + + PIO_TF_Check_short_val_val = val1 == val2 + END FUNCTION + LOGICAL FUNCTION PIO_TF_Check_real_val_val(val1, val2) + real(kind=fc_real), INTENT(IN) :: val1, val2 + + PIO_TF_Check_real_val_val = val1 == val2 + END FUNCTION + LOGICAL FUNCTION PIO_TF_Check_double_val_val(val1, val2) + real(kind=fc_double), INTENT(IN) :: val1, val2 + + PIO_TF_Check_double_val_val = val1 == val2 + END FUNCTION + LOGICAL FUNCTION PIO_TF_Check_int_arr_val(arr, val) INTEGER, DIMENSION(:), INTENT(IN) :: arr INTEGER, INTENT(IN) :: val diff --git a/tests/ncint/CMakeLists.txt b/tests/ncint/CMakeLists.txt new file mode 100644 index 00000000000..f2aa6966828 --- /dev/null +++ b/tests/ncint/CMakeLists.txt @@ -0,0 +1,31 @@ +# This is part of the PIO library. +# +# This is the cmake file to build the test directory for netCDF integration. +# +# Ed Hartnett 8/19/20 + +include (LibMPI) + +include_directories("${CMAKE_SOURCE_DIR}/tests/ncint") +include_directories("${CMAKE_BINARY_DIR}") + +set (my_tests tst_async_multi tst_ncint_async_perf + tst_ncint_perf tst_pio_async tst_pio_udf tst_var_compress) + +# Test Timeout in seconds. +if (PIO_VALGRIND_CHECK) + set (DEFAULT_TEST_TIMEOUT 480) +else () + set (DEFAULT_TEST_TIMEOUT 240) +endif () + +FOREACH(tst ${my_tests}) + add_executable (${tst} EXCLUDE_FROM_ALL ${tst}.c) + add_dependencies (tests ${tst}) + target_link_libraries (${tst} pioc) + add_mpi_test(${tst} + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/${tst} + NUMPROCS 4 + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) +ENDFOREACH() + diff --git a/tests/ncint/Makefile.am b/tests/ncint/Makefile.am index b18ed51224a..9ed42251ba3 100644 --- a/tests/ncint/Makefile.am +++ b/tests/ncint/Makefile.am @@ -9,7 +9,7 @@ LDADD = ${top_builddir}/src/clib/libpioc.la # Build the test for make check. check_PROGRAMS = tst_pio_udf tst_pio_async tst_async_multi \ -tst_ncint_async_perf tst_ncint_perf +tst_ncint_async_perf tst_ncint_perf tst_var_compress tst_pio_udf_SOURCES = tst_pio_udf.c pio_err_macros.h tst_pio_async_SOURCES = tst_pio_async.c pio_err_macros.h @@ -23,7 +23,9 @@ TESTS = run_tests.sh run_perf.sh endif # RUN_TESTS # Distribute the test script. -EXTRA_DIST = run_tests.sh run_perf.sh +EXTRA_DIST = run_tests.sh.in run_perf.sh.in # Clean up files produced during testing. CLEANFILES = *.nc *.log + +DISTCLEANFILES = run_tests.sh run_perf.sh diff --git a/tests/ncint/run_perf.sh b/tests/ncint/run_perf.sh.in similarity index 91% rename from tests/ncint/run_perf.sh rename to tests/ncint/run_perf.sh.in index 7f0d5fd9f53..1eb2d9460ec 100755 --- a/tests/ncint/run_perf.sh +++ b/tests/ncint/run_perf.sh.in @@ -20,7 +20,7 @@ for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi diff --git a/tests/ncint/run_tests.sh b/tests/ncint/run_tests.sh.in similarity index 79% rename from tests/ncint/run_tests.sh rename to tests/ncint/run_tests.sh.in index c21727ce557..72b5060c5cc 100755 --- a/tests/ncint/run_tests.sh +++ b/tests/ncint/run_tests.sh.in @@ -10,7 +10,7 @@ trap exit INT TERM printf 'running PIO tests...\n' -PIO_TESTS='tst_pio_udf tst_pio_async tst_async_multi' +PIO_TESTS='tst_pio_udf tst_pio_async tst_async_multi tst_var_compress' success1=true success2=true @@ -18,7 +18,7 @@ for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi @@ -30,7 +30,7 @@ done # do # success2=false # echo "running ${TEST}" -# mpiexec -n 8 ./${TEST} && success2=true +# @WITH_MPIEXEC@ -n 8 ./${TEST} && success2=true # if test $success2 = false; then # break # fi diff --git a/tests/ncint/tst_ncint_async_perf.c b/tests/ncint/tst_ncint_async_perf.c index 6b60f14f802..7a8cb5a6984 100644 --- a/tests/ncint/tst_ncint_async_perf.c +++ b/tests/ncint/tst_ncint_async_perf.c @@ -162,10 +162,11 @@ main(int argc, char **argv) printf("%s,\t%d,\t%d,\t%d,\t%8.3f,\t%8.1f,\t%8.3f\n", mode_name[m], ntasks, num_io_procs, 1, delta_in_sec, num_megabytes, mb_per_sec); + + free(my_data); + if (nc_free_decomp(ioid)) PERR; } /* next mode flag */ - free(my_data); - if (nc_free_decomp(ioid)) PERR; if (nc_free_iosystem(iosysid)) PERR; } } diff --git a/tests/ncint/tst_ncint_perf.c b/tests/ncint/tst_ncint_perf.c index 2e857c76c67..a5833cc0dbf 100644 --- a/tests/ncint/tst_ncint_perf.c +++ b/tests/ncint/tst_ncint_perf.c @@ -154,10 +154,11 @@ main(int argc, char **argv) printf("%s,\t%d,\t%d,\t%d,\t%8.3f,\t%8.1f,\t%8.3f\n", mode_name[m], ntasks, num_io_procs, 1, delta_in_sec, num_megabytes, mb_per_sec); - } /* next mode flag */ + + free(my_data); + if (nc_free_decomp(ioid)) PERR; - free(my_data); - if (nc_free_decomp(ioid)) PERR; + } /* next mode flag */ } if (nc_free_iosystem(iosysid)) PERR; diff --git a/tests/ncint/tst_var_compress.c b/tests/ncint/tst_var_compress.c new file mode 100644 index 00000000000..e7fc492a029 --- /dev/null +++ b/tests/ncint/tst_var_compress.c @@ -0,0 +1,154 @@ +/* Test netcdf integration layer of the PIO library. + + Test variable compression settings with the netCDF integration + layer. + + Ed Hartnett, 9/3/20 +*/ + +#include "config.h" +#include "pio_err_macros.h" +#include + +#define FILE_NAME "tst_var_compress.nc" +#define VAR_NAME "data_var" +#define DIM_NAME_UNLIMITED "dim_unlimited" +#define DIM_NAME_X "dim_x" +#define DIM_NAME_Y "dim_y" +#define DIM_LEN_X 4 +#define DIM_LEN_Y 4 +#define NDIM2 2 +#define NDIM3 3 +#define TEST_VAL_42 42 +#define DEFLATE_LEVEL 4 + +int +run_var_compress_test(int my_rank, int ntasks, int iosysid) +{ + int ncid, ioid; + int dimid[NDIM3], varid; + int dimlen[NDIM3] = {NC_UNLIMITED, DIM_LEN_X, DIM_LEN_Y}; + size_t chunksizes[NDIM3] = {1, 1, 1}; + size_t elements_per_pe; + size_t *compdof; /* The decomposition mapping. */ + int *my_data; + int i; + + /* Turn on logging for PIO library. */ + /* PIOc_set_log_level(3); */ + + /* Create a file with a 3D record var. */ + if (nc_create(FILE_NAME, NC_PIO|NC_NETCDF4, &ncid)) PERR; + if (nc_def_dim(ncid, DIM_NAME_UNLIMITED, dimlen[0], &dimid[0])) PERR; + if (nc_def_dim(ncid, DIM_NAME_X, dimlen[1], &dimid[1])) PERR; + if (nc_def_dim(ncid, DIM_NAME_Y, dimlen[2], &dimid[2])) PERR; + if (nc_def_var(ncid, VAR_NAME, NC_INT, NDIM3, dimid, &varid)) PERR; + if (nc_def_var_deflate(ncid, varid, 1, 1, DEFLATE_LEVEL)) PERR; + if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksizes)) PERR; + if (nc_def_var_endian(ncid, varid, NC_ENDIAN_BIG)) PERR; + + /* Calculate a decomposition for distributed arrays. */ + elements_per_pe = DIM_LEN_X * DIM_LEN_Y / ntasks; + if (!(compdof = malloc(elements_per_pe * sizeof(size_t)))) + PERR; + for (i = 0; i < elements_per_pe; i++) + compdof[i] = my_rank * elements_per_pe + i; + + /* Create the PIO decomposition for this test. */ + if (nc_def_decomp(iosysid, PIO_INT, NDIM2, &dimlen[1], elements_per_pe, + compdof, &ioid, 1, NULL, NULL)) PERR; + free(compdof); + + /* Create some data on this processor. */ + if (!(my_data = malloc(elements_per_pe * sizeof(int)))) PERR; + for (i = 0; i < elements_per_pe; i++) + my_data[i] = my_rank * 10 + i; + + /* Write some data with distributed arrays. */ + if (nc_put_vard_int(ncid, varid, ioid, 0, my_data)) PERR; + if (nc_close(ncid)) PERR; + + { + int shuffle_in, deflate_in, deflate_level_in, storage_in; + int *data_in; + size_t chunksizes_in[NDIM3]; + int endian_in; + int d; + + /* Open the file. */ + if (nc_open(FILE_NAME, NC_PIO, &ncid)) PERR; + + /* Check the variable deflate. */ + if (nc_inq_var_deflate(ncid, 0, &shuffle_in, &deflate_in, &deflate_level_in)) PERR; + printf("%d %d %d\n", shuffle_in, deflate_in, deflate_level_in); + /* if (shuffle_in || !deflate_in || deflate_level_in != DEFLATE_LEVEL) PERR; */ + + /* Check the chunking. */ + if (nc_inq_var_chunking(ncid, 0, &storage_in, chunksizes_in)) PERR; + for (d = 0; d < NDIM3; d++) + if (chunksizes_in[d] != chunksizes[d]) PERR; + if (storage_in != NC_CHUNKED) PERR; + + /* Check the endianness. */ + if (nc_inq_var_endian(ncid, 0, &endian_in)) PERR; + if (endian_in != NC_ENDIAN_BIG) PERR; + + /* Read distributed arrays. */ + if (!(data_in = malloc(elements_per_pe * sizeof(int)))) PERR; + if (nc_get_vard_int(ncid, varid, ioid, 0, data_in)) PERR; + + /* Check results. */ + for (i = 0; i < elements_per_pe; i++) + if (data_in[i] != my_data[i]) PERR; + + /* Close file. */ + if (nc_close(ncid)) PERR; + + /* Free resources. */ + free(data_in); + } + free(my_data); + if (nc_free_decomp(ioid)) PERR; + + return 0; +} + +int +main(int argc, char **argv) +{ + int iosysid; + int my_rank; + int ntasks; + + /* Initialize MPI. */ + if (MPI_Init(&argc, &argv)) PERR; + + /* Learn my rank and the total number of processors. */ + if (MPI_Comm_rank(MPI_COMM_WORLD, &my_rank)) PERR; + if (MPI_Comm_size(MPI_COMM_WORLD, &ntasks)) PERR; + + if (!my_rank) + printf("\n*** Testing netCDF integration layer with var compression.\n"); + + /* Only run tests if netCDF-4 is present in the build. */ +#ifdef _NETCDF4 + + if (!my_rank) + printf("*** testing var compression with netCDF integration layer..."); + + /* Initialize the intracomm. */ + if (nc_def_iosystem(MPI_COMM_WORLD, 1, 1, 0, 0, &iosysid)) PERR; + + /* Run the tests. */ + if (run_var_compress_test(my_rank, ntasks, iosysid)) PERR; + + /* Free the iosystem. */ + if (nc_free_iosystem(iosysid)) PERR; + + PSUMMARIZE_ERR; +#endif /* _NETCDF4 */ + + /* Finalize MPI. */ + MPI_Finalize(); + PFINAL_RESULTS; +} diff --git a/tests/performance/Makefile.am b/tests/performance/Makefile.am index 751b970be92..1841a80d80d 100644 --- a/tests/performance/Makefile.am +++ b/tests/performance/Makefile.am @@ -6,8 +6,8 @@ # Parallel builds don't currently work in this directory. .NOTPARALLEL: -# Put together AM_CPPFLAGS and AM_LDFLAGS. -include $(top_srcdir)/set_flags.am +# Find the pio.mod file. +AM_CPPFLAGS = -I$(top_srcdir)/src/flib # Link to test util library and PIO Fortran and C libs. LDADD = $(top_builddir)/src/gptl/libperf_mod.la \ @@ -33,7 +33,9 @@ TESTS = run_tests.sh endif # RUN_TESTS EXTRA_DIST = CMakeLists.txt gensimple.pl Pioperformance.md pioperf.nl \ -run_tests.sh +run_tests.sh.in # Clean up files produced during testing. CLEANFILES = *.nc *.log *.mod + +DISTCLEANFILES = run_tests.sh diff --git a/tests/performance/pioperformance.F90 b/tests/performance/pioperformance.F90 index cb293158740..8a5e2e732b0 100644 --- a/tests/performance/pioperformance.F90 +++ b/tests/performance/pioperformance.F90 @@ -1,3 +1,4 @@ +#include "config.h" #define VARINT 1 !#define VARREAL 1 !#define VARDOUBLE 1 diff --git a/tests/performance/run_tests.sh b/tests/performance/run_tests.sh.in similarity index 90% rename from tests/performance/run_tests.sh rename to tests/performance/run_tests.sh.in index 780ad7b791d..1dc6d25b628 100755 --- a/tests/performance/run_tests.sh +++ b/tests/performance/run_tests.sh.in @@ -17,7 +17,7 @@ for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index eaf7c0f5694..27298336b54 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -1,3 +1,6 @@ +# This is the CMake build file for the tests/unit tests of the PIO library. + +# Jim Edwards include (LibMPI) include_directories("${CMAKE_SOURCE_DIR}/tests/unit") @@ -35,6 +38,11 @@ endif () add_dependencies (tests pio_unit_test) +# Add ftst_vars.F90. +add_executable (ftst_vars_chunking EXCLUDE_FROM_ALL ftst_vars_chunking.F90) +target_link_libraries (ftst_vars_chunking piof) +add_dependencies (tests ftst_vars_chunking) + # Test Timeout in seconds. set (DEFAULT_TEST_TIMEOUT 60) @@ -55,6 +63,10 @@ else () EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/pio_unit_test NUMPROCS 4 TIMEOUT ${DEFAULT_TEST_TIMEOUT}) + add_mpi_test(ftst_vars_chunking + EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/ftst_vars_chunking + NUMPROCS 4 + TIMEOUT ${DEFAULT_TEST_TIMEOUT}) endif () if (PIO_HDF5_LOGGING) diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 33264e29011..867857ef97e 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -6,14 +6,20 @@ # Parallel builds don't currently work in this directory. .NOTPARALLEL: -# Put together AM_CPPFLAGS and AM_LDFLAGS. -include $(top_srcdir)/set_flags.am +# Find the pio.mod file. +AM_CPPFLAGS = -I$(top_srcdir)/src/flib + +# Link to the PIO C and Fortran libraries. +LDADD = ${top_builddir}/src/flib/libpiof.la \ +${top_builddir}/src/clib/libpioc.la # Build the test for make check. -check_PROGRAMS = pio_unit_test_driver +check_PROGRAMS = pio_unit_test_driver ftst_vars_chunking pio_unit_test_driver_SOURCES = driver.F90 pio_unit_test_driver_LDADD = libglobal_vars.la libncdf_tests.la \ -libbasic_tests.la ${top_builddir}/src/flib/libpiof.la ${top_builddir}/src/clib/libpioc.la +libbasic_tests.la ${top_builddir}/src/flib/libpiof.la \ +${top_builddir}/src/clib/libpioc.la +ftst_vars_chunking_SOURCES = ftst_vars_chunking.F90 # Build these uninstalled convenience libraries. noinst_LTLIBRARIES = libglobal_vars.la libncdf_tests.la \ @@ -30,7 +36,10 @@ TESTS = run_tests.sh endif # RUN_TESTS # Distribute the test script. -EXTRA_DIST = CMakeLists.txt run_tests.sh input.nl not_netcdf.ieee +EXTRA_DIST = CMakeLists.txt run_tests.sh input.nl not_netcdf.ieee \ +run_tests.sh.in # Clean up files produced during testing. CLEANFILES = *.nc *.log *.mod + +DISTCLEANFILES = run_tests.sh diff --git a/tests/unit/basic_tests.F90 b/tests/unit/basic_tests.F90 index 541fa92cd12..b9f72692be4 100644 --- a/tests/unit/basic_tests.F90 +++ b/tests/unit/basic_tests.F90 @@ -3,6 +3,7 @@ !! @brief Module containing basic unit tests that are run for both !! binary and netcdf file types. !< +#include "config.h" module basic_tests @@ -285,7 +286,7 @@ Subroutine test_open(test_id, err_msg) call mpi_abort(MPI_COMM_WORLD, 0, ret_val2) end if - ret_val = PIO_set_log_level(3) + !ret_val = PIO_set_log_level(3) ret_val = PIO_inq_unlimdim(pio_file, unlimdimid) if(unlimdimid /= -1) then err_msg = "Error in inq_unlimdim" @@ -293,7 +294,7 @@ Subroutine test_open(test_id, err_msg) print *,__FILE__,__LINE__,iotype, trim(err_msg) call mpi_abort(MPI_COMM_WORLD, 0, ret_val2) end if - ret_val = PIO_set_log_level(0) + !ret_val = PIO_set_log_level(0) ! Close file call PIO_closefile(pio_file) diff --git a/tests/unit/driver.F90 b/tests/unit/driver.F90 index d3f3a83fd7c..6c3975d9b47 100644 --- a/tests/unit/driver.F90 +++ b/tests/unit/driver.F90 @@ -2,6 +2,7 @@ !! @file !! @brief The driver for PIO unit tests !< +#include "config.h" Program pio_unit_test_driver use pio @@ -64,13 +65,6 @@ Program pio_unit_test_driver ! Ignore namelist values if PIO not built with correct options ! (i.e. don't test pnetcdf if not built with pnetcdf) -#ifndef _NETCDF - if (ltest_netcdf) then - write(*,"(A,1x,A)") "WARNING: can not test netcdf files because PIO", & - "was not compiled with -D_NETCDF" - ltest_netcdf = .false. - end if -#endif #ifndef _NETCDF4 if (ltest_netcdf4p) then write(*,"(A,1x,A)") "WARNING: can not test netcdf4p files because PIO", & diff --git a/tests/unit/ftst_vars_chunking.F90 b/tests/unit/ftst_vars_chunking.F90 new file mode 100644 index 00000000000..af04112d5fa --- /dev/null +++ b/tests/unit/ftst_vars_chunking.F90 @@ -0,0 +1,98 @@ + ! This is a test of the PIO Fortran library. + + ! This tests var functions. + + ! Ed Hartnett, 8/28/20 +#include "config.h" + +program ftst_vars_chunking + use mpi + use pio + use pio_nf + + integer, parameter :: NUM_IOTYPES = 2 + integer, parameter :: NDIM2 = 2 + + type(iosystem_desc_t) :: pio_iosystem + type(file_desc_t) :: pio_file + type(var_desc_t) :: pio_var + integer :: my_rank, ntasks + integer :: niotasks = 1, stride = 1 + character(len=64) :: filename = 'ftst_vars_chunking.nc' + character(len=64) :: dim_name_1 = 'influence_on_Roman_history' + character(len=64) :: dim_name_2 = 'age_at_death' + character(len=64) :: var_name = 'Caesar' + integer :: dimid1, dimid2, dim_len1 = 40, dim_len2 = 80 + integer :: chunksize1 = 10, chunksize2 = 20 + integer :: storage_in + integer (kind=PIO_OFFSET_KIND) :: chunksizes_in(NDIM2) + integer :: iotype(NUM_IOTYPES) = (/ PIO_iotype_netcdf4c, PIO_iotype_netcdf4p /) + integer :: iotype_idx, ierr + + ! Set up MPI + call MPI_Init(ierr) + call MPI_Comm_rank(MPI_COMM_WORLD, my_rank, ierr) + call MPI_Comm_size(MPI_COMM_WORLD, ntasks , ierr) + + ! This whole test only works for netCDF/HDF5 files, because it is + ! about chunking. +#ifdef _NETCDF4 + if (my_rank .eq. 0) print *,'Testing variables...' + + ! Initialize PIO. + call PIO_init(my_rank, MPI_COMM_WORLD, niotasks, 0, stride, & + PIO_rearr_subset, pio_iosystem, base=1) + + ! Set error handling for test. + call PIO_seterrorhandling(pio_iosystem, PIO_RETURN_ERROR) + call PIO_seterrorhandling(PIO_DEFAULT, PIO_RETURN_ERROR) + + ! Uncomment (and build with --enable-logging) to turn on logging. + !ret_val = PIO_set_log_level(3) + + ! Try this test for NETCDF4C and NETCDF4P. + do iotype_idx = 1, NUM_IOTYPES + + ! Create a file. + ierr = PIO_createfile(pio_iosystem, pio_file, iotype(iotype_idx), filename) + if (ierr .ne. PIO_NOERR) stop 3 + + ! Define dims. + ret_val = PIO_def_dim(pio_file, dim_name_1, dim_len1, dimid1) + if (ierr .ne. PIO_NOERR) stop 5 + ret_val = PIO_def_dim(pio_file, dim_name_2, dim_len2, dimid2) + if (ierr .ne. PIO_NOERR) stop 6 + + ! Define a var. + ret_val = PIO_def_var(pio_file, var_name, PIO_int, (/dimid1, dimid2/), pio_var) + if (ierr .ne. PIO_NOERR) stop 7 + + ! Define chunking for var. + ret_val = PIO_def_var_chunking(pio_file, pio_var, 0, (/chunksize1, chunksize2/)) + if (ierr .ne. PIO_NOERR) stop 9 + + ! Close the file. + call PIO_closefile(pio_file) + + ! Open the file. + ret_val = PIO_openfile(pio_iosystem, pio_file, iotype(iotype_idx), filename, PIO_nowrite) + if (ierr .ne. PIO_NOERR) stop 23 + + ! Find var chunksizes using varid. + ret_val = PIO_inq_var_chunking(pio_file, 1, storage_in, chunksizes_in) + if (ierr .ne. PIO_NOERR) stop 25 + if (chunksizes_in(1) .ne. chunksize1) stop 26 + if (chunksizes_in(2) .ne. chunksize2) stop 26 + + ! Close the file. + call PIO_closefile(pio_file) + + end do ! next IOTYPE + + ! Finalize PIO. + call PIO_finalize(pio_iosystem, ierr) + + if (my_rank .eq. 0) print *,'SUCCESS!' +#endif + call MPI_Finalize(ierr) +end program ftst_vars_chunking diff --git a/tests/unit/global_vars.F90 b/tests/unit/global_vars.F90 index f3347ba38c9..79318357c65 100644 --- a/tests/unit/global_vars.F90 +++ b/tests/unit/global_vars.F90 @@ -2,16 +2,16 @@ !! @file !! @brief Module containing variables used across all unit test files !< +#include "config.h" module global_vars use pio + use mpi Implicit None public - include 'mpif.h' ! _EXTERNAL - integer, parameter :: str_len = pio_max_name, ntest=4 integer, parameter ::NETCDF =1, & NETCDF4P=2, & diff --git a/tests/unit/ncdf_tests.F90 b/tests/unit/ncdf_tests.F90 index 66f529a729b..765132751e3 100644 --- a/tests/unit/ncdf_tests.F90 +++ b/tests/unit/ncdf_tests.F90 @@ -2,6 +2,7 @@ !! @file !! @brief Module containing netcdf-specific PIO unit tests !< +#include "config.h" module ncdf_tests @@ -469,15 +470,22 @@ Subroutine test_nc4(test_id, err_msg) ! deflate_level_2 = 4 deflate_level = 1 deflate_level_2 = 1 - ret_val = PIO_set_log_level(3) ret_val = PIO_def_var_deflate(pio_file, pio_var, shuffle, deflate, & deflate_level) - ! Should not have worked except for netCDF-4/HDF5 serial. + ! Should not have worked except for netCDF-4/HDF5 sequential, and + ! perhaps parallel. if (iotype .eq. PIO_iotype_netcdf4c .and. ret_val .ne. PIO_NOERR) then err_msg = "Could not turn on compression for variable foo2222" call PIO_closefile(pio_file) return + else if (iotype .eq. PIO_iotype_netcdf4p) then + !err_msg = "Could not turn on compression for variable foo2222" + ! if (ret_val .ne. PIO_NOERR) then + ! call PIO_closefile(pio_file) + ! return + ! end if + ! return else if (iotype .eq. PIO_iotype_pnetcdf .and. ret_val .eq. PIO_NOERR) then err_msg = "Did not get expected error when trying to turn deflate on for pnetcdf file" call PIO_closefile(pio_file) @@ -486,10 +494,6 @@ Subroutine test_nc4(test_id, err_msg) err_msg = "Did not get expected error when trying to turn deflate on for netcdf classic file" call PIO_closefile(pio_file) return - else if (iotype .eq. PIO_iotype_netcdf4p .and. ret_val .eq. PIO_NOERR) then - err_msg = "Did not get expected error when trying to turn deflate on for parallel netcdf-4 file" - call PIO_closefile(pio_file) - return end if print*, 'testing PIO_put_att' @@ -514,7 +518,7 @@ Subroutine test_nc4(test_id, err_msg) print*, 'testing PIO_inq_var_deflate' ret_val = PIO_inq_var_deflate(pio_file, pio_var, shuffle, deflate, my_deflate_level) - ! Should not have worked except for netCDF-4/HDF5 serial. + ! Should not have worked except for netCDF-4/HDF5 sequential, and maybe parallel. if (iotype .eq. PIO_iotype_netcdf4c) then if (ret_val .ne. PIO_NOERR) then err_msg = "Got error trying to inquire about deflate on for serial netcdf-4 file" @@ -528,22 +532,19 @@ Subroutine test_nc4(test_id, err_msg) return end if end if + else if (iotype .eq. PIO_iotype_netcdf4p) then + ! if (ret_val .eq. PIO_NOERR) then + ! print *,shuffle, deflate, deflate_level, my_deflate_level + ! if (shuffle .ne. 0 .or. deflate .ne. 1 .or. my_deflate_level .ne. deflate_level) then + ! err_msg = "Wrong values for deflate and shuffle for parallel netcdf-4 file" + ! call PIO_closefile(pio_file) + ! return + ! end if + ! end if else if ((iotype .eq. PIO_iotype_pnetcdf .or. iotype .eq. PIO_iotype_netcdf) .and. ret_val .eq. PIO_NOERR) then err_msg = "Did not get expected error when trying to check deflate for non-netcdf-4 file" call PIO_closefile(pio_file) return - else if (iotype .eq. PIO_iotype_netcdf4p) then - if (ret_val .ne. PIO_NOERR) then - err_msg = "Got error trying to inquire about deflate on for parallel netcdf-4 file" - call PIO_closefile(pio_file) - return - else - if (shuffle .ne. 0 .or. deflate .ne. 0) then - err_msg = "Wrong values for deflate and shuffle for parallel netcdf-4 file" - call PIO_closefile(pio_file) - return - end if - end if end if ! Try to turn on compression for this variable. @@ -551,7 +552,7 @@ Subroutine test_nc4(test_id, err_msg) ret_val = PIO_def_var_deflate(pio_file, pio_var%varid, shuffle, deflate, & deflate_level_2) - ! Should not have worked except for netCDF-4/HDF5 serial. + ! Should not have worked except for netCDF-4/HDF5. if (iotype .eq. PIO_iotype_netcdf4c .and. ret_val .ne. PIO_NOERR) then err_msg = "Could not turn on compression for variable foo2222 second time" call PIO_closefile(pio_file) @@ -564,10 +565,10 @@ Subroutine test_nc4(test_id, err_msg) err_msg = "Did not get expected error when trying to turn deflate on for netcdf classic file" call PIO_closefile(pio_file) return - else if (iotype .eq. PIO_iotype_netcdf4p .and. ret_val .eq. PIO_NOERR) then - err_msg = "Did not get expected error when trying to turn deflate on for parallel netcdf-4 file" - call PIO_closefile(pio_file) - return + else if (iotype .eq. PIO_iotype_netcdf4p) then +! err_msg = "Could not turn on compression for variable foo2222 second time" +! call PIO_closefile(pio_file) +! return end if ! Leave define mode @@ -600,17 +601,17 @@ Subroutine test_nc4(test_id, err_msg) call PIO_closefile(pio_file) return else if (iotype .eq. PIO_iotype_netcdf4p) then - if (ret_val .ne. PIO_NOERR) then - err_msg = "Got error trying to inquire about deflate on for parallel netcdf-4 file" - call PIO_closefile(pio_file) - return - else - if (shuffle .ne. 0 .or. deflate .ne. 0) then - err_msg = "Wrong values for deflate and shuffle for parallel netcdf-4 file" - call PIO_closefile(pio_file) - return - end if - end if + ! if (ret_val .ne. PIO_NOERR) then + ! err_msg = "Got error trying to inquire about deflate on for parallel netcdf-4 file" + ! call PIO_closefile(pio_file) + ! return + ! else + ! if (shuffle .ne. 0 .or. deflate .ne. 1 .or. my_deflate_level .ne. deflate_level_2) then + ! err_msg = "Wrong values for deflate and shuffle for parallel netcdf-4 file" + ! call PIO_closefile(pio_file) + ! return + ! end if + ! end if end if ! Write foo2 diff --git a/tests/unit/run_tests.sh b/tests/unit/run_tests.sh.in similarity index 81% rename from tests/unit/run_tests.sh rename to tests/unit/run_tests.sh.in index 0f7c61ee178..77511ff974a 100755 --- a/tests/unit/run_tests.sh +++ b/tests/unit/run_tests.sh.in @@ -10,14 +10,14 @@ trap exit INT TERM printf 'running PIO tests...\n' -PIO_TESTS='pio_unit_test_driver' +PIO_TESTS='pio_unit_test_driver ftst_vars_chunking' success1=true for TEST in $PIO_TESTS do success1=false echo "running ${TEST}" - mpiexec -n 4 ./${TEST} && success1=true + @WITH_MPIEXEC@ -n 4 ./${TEST} && success1=true if test $success1 = false; then break fi