From 25e5a1fb0c069be50bbdb25e6853b79edbd6c04b Mon Sep 17 00:00:00 2001 From: Jim Edwards Date: Wed, 4 Nov 2020 13:53:11 -0700 Subject: [PATCH] Squashed 'src/externals/pio2/' changes from 602f71c6d..134c5209d 134c5209d Merge pull request #1771 from jedwards4b/fortran_interface_updates c91eb59c0 back out setting of fillvalue in pio_darray f3b63c9cc untabify 01830e4eb fix whitespace 5ae954910 try again 94ff81b6a undo last change and see if travisci will pass 91520c20c read_darray sets fillvalue 736c0745c add target attribute 7bd521922 more minor changes 0ba4b787d implement pio_inq_var_fill in fortran, add tests e7d621b0b Merge pull request #1769 from jedwards4b/cdash_test_fixes 3eac73356 undo unessasary change 3d8956df3 fix pgi version and openmpi test error fed328b7c Merge pull request #1767 from jedwards4b/update_cheyenne_tests e47b8f108 update cheyenne modules for ctest c90a7a287 Merge pull request #1761 from jedwards4b/remove_pio_use_malloc 3e432479a untabify c files b7b9b52e1 untabify pio_darray.c 9fc01568a Merge branch 'master' into remove_pio_use_malloc b241756e7 Merge pull request #1763 from jedwards4b/fix_int_overflow 1c9dd2823 fix integer overflow issue noted in nag compiler 9d3470f5e fix doc generation error 34809b99a fully remove pio_use_malloc macro b9855cdb5 Merge pull request #1759 from jedwards4b/add_flib_set_fill 78d28a329 add set_fill to fortran interface 6f9fb5e1b Merge pull request #1754 from NCAR/ejh_release 9efeee459 changed version numbers and so library numbers fd8b8c111 Merge pull request #1753 from NCAR/ejh_no_compress 00104f88b no longer turn on deflate for vars automatically d0d4a98f8 Merge pull request #1752 from NCAR/ejh_bget d048ed581 working on cmake test build cbf9b1728 working on cmake test build 4c545508b merged 14672d4d0 working on cmake test build a98bf4a15 Merge branch 'master' into ejh_bget 14ba34643 Merge pull request #1751 from NCAR/ejh_docs 668bdd323 more bget fixes c9923271a added cmake to test build bad9cee8c removed bget 2f3ed1128 removed bget d23ae965a more fortran doc work d751d495d improving fortran docs e97f23923 improving fortran docs 3a77973ad Merge pull request #1747 from NCAR/ejh_ncint_deflate 73eaa0c70 added endianness f97e66681 now testind def_var_endian 9c88c0eb8 now properly getting chunksizes thru ncint c298e796f developing test 09dc75601 added deflate to the test 58533898a modifying tst_var_compress f11724cc0 added tst_var_compress.c 39b0940bd merged master 64cdf4bdb Merge pull request #1746 from NCAR/ejh_mpi_check 286f52932 removed cmake build from github testing c2492f10a dealing with der_var_endian and def_var_chunking in netcdf integration layer 245a21257 adding PIO_NCINT_def_var_deflate b25c930d2 added check for MPI c5696275e Merge pull request #1743 from NCAR/ejh_more_tests_2 261d8b6fe increased time-out c6c613863 added cmake build to a4.yml adbb0d801 removed flags from fortran cmake build 63662f583 Merge pull request #1742 from NCAR/ejh_flags 666731d02 removed unused VARN pre-processor defines 3ce5db5d2 Merge pull request #1741 from NCAR/ejh_more_testing_2 81de16eab adding Fortran to build summary 6ec562a44 MPIEXEC in examples/f03 directory, also set FC in fortran build e835926b6 turning on fortran build in github CI, also fixing mpiexec in tests/performance a5fb922e0 handle mpiexec for fncint and general dirs 9e4a39ecb trying to get gcc version 3c02032ff Merge pull request #1738 from NCAR/ejh_more_testing eb23c9f03 fixing order of chunksizes 15a191b55 fixing order of chunksizes e37d19ae2 fixed chunksizes type size error in F90 api 13cb7c7fe fixed shell script with new test name f1e58bd7f renamed test 5ff984444 fixed docs 5c2ae6522 adding pio_inq_var_chunking 66754676c more test development f114fbc32 further test development a54de425a further test development cbed9880c further test development cdc01a165 turn of netcdf integration in github workflow 05ce8e39b added ftst_vars.F90 to CMake build 9d3ff03fa added ftst_vars.F90 to CMake build e9f4f755d starting to add ftst_vars.F90 2987785d5 turning on ncint f6feb76b1 Merge pull request #1737 from NCAR/ejh_flags_next 5f8e9fa71 more testing in new workflow 71eace1ca more testing in new workflow c2919cb03 more testing in new workflow 87e38c547 more testing in new workflow dd0400c9b more testing in new workflow 1733a7a48 adding mpich workflow a31c6f8e0 adding mpich workflow 138f4f14a adding mpich workflow d677d0765 adding mpich workflow 28429a54c fixing MPIEXEC in library summary for CMake builds 22d11602a Merge pull request #1735 from NCAR/ejh_cmake f130a86da adding fields to build summary f835a8d7f removing unneeded logging pre-processor macro from CMake build 9d8c81a61 clean up 1b788c9b7 more fixing for flib and clib, now fixing _PNETCDF e6960d9a9 more fixing for flib and clib 1bb4b5749 now fixing for flib 510e955f1 fixing CMake determination of _NETCDF4 843f6d906 commented out more unneeded flag setting in cmake adf6308d1 commented out more unneeded flag setting in cmake 6d767b2b1 commented out more unneeded flag setting in cmake d37b976bd taking away flag from CMake build 54ee841cc Merge pull request #1734 from NCAR/ejh_doc_fix 35742c688 now ncint tests repect WITH_MPIEXEC 151affd85 now ncint tests repect WITH_MPIEXEC 181373a76 fixing docs, cleanup of test workflow e715d0778 Merge pull request #1733 from NCAR/ejh_openmpi_2 7b874db3a clean up 7ddbfe753 trying to deal with MPIEXEC in CMake 41b1588a4 trying to deal with MPIEXEC in CMake 280c4b9ae trying to deal with MPIEXEC in CMake b501e625d trying to deal with MPIEXEC in CMake 7bcf9f33e trying to deal with MPIEXEC in CMake f5906b12e trying to deal with MPIEXEC in CMake 672259c4f trying to deal with MPIEXEC in CMake 48157639e trying to deal with MPIEXEC in CMake ba379cc66 trying to deal with MPIEXEC in CMake 2138bd3e6 trying to deal with MPIEXEC in CMake b2820c2c6 trying to deal with MPIEXEC in CMake e80292528 trying to deal with MPIEXEC in CMake b1fabeea1 trying to deal with MPIEXEC in CMake 4174cf9a4 trying to deal with MPIEXEC in CMake 74223248a trying to deal with MPIEXEC in CMake deed51058 trying to deal with MPIEXEC in CMake d561d64c0 trying to deal with MPIEXEC in CMake c0466f9ac more work on cmake build 6eb1b7a25 more cmake build 1ac66e0e0 more cmake build 51791cba4 more cmake build fc04c721a more cmake build afb423be5 more cmake build ddb380f70 more cmake build 9e654d80a more cmake build 4c1ca9eb9 more cmake build feada9c08 more cmake build f2bbbbf9c more cmake build e23ce03d6 more cmake build 101381853 more cmake build 081b86327 more cmake build 36b7c7bae more cmake build f38d8ae16 more cmake build c16d88a5c more cmake build 7f547ee06 starting to add cmake build of C library 00e667f64 Merge pull request #1731 from NCAR/ejh_openmpi 0f2db9d11 converting more tests to use new --with-mpiexec option c7fc47aac converting more tests to use new --with-mpiexec option dc8275df5 converting more tests to use new --with-mpiexec option 2af2aeb4f adding tests/cunit/run_tests.sh.in db613c3e5 adding tests/cunit/run_tests.sh.in e4fb33c03 adding --with-mpiexec option to configure 2d908a13a adding --with-mpiexec option to configure d76dd49b6 trying to get openmpi mpiexec working 3822956e3 trying to get openmpi mpiexec working 558a3b9c4 trying to get openmpi mpiexec working ba2b71983 trying to get openmpi mpiexec working 493353ae8 trying to get openmpi mpiexec working dcb5e0807 trying to get openmpi mpiexec working a96671fd6 trying to get openmpi mpiexec working f283a8030 trying to get openmpi mpiexec working 0903e6223 trying to get openmpi mpiexec working 5a96af866 trying to get openmpi mpiexec working 2d9bf6b69 adding PIO b35ee2110 adding PIO 2bf634f90 adding PIO cc1dc81ab adding PIO 8b243ca4c adding PIO 3681f56be adding PIO 0c5dbbd37 adding PIO 11203423d adding PIO 8984b2654 adding PIO 7a5c3f306 adding PIO 8f865959e adding PIO 4d1a70939 adding PIO 61ef8dede adding netcdf-fortran and pnetcdf 6d2b2a9aa adding netcdf-fortran and pnetcdf 35dda9d5b adding netcdf-fortran and pnetcdf 49ab2d773 adding netcdf-c 1199dd36c adding HDF5 1c5ab7603 adding HDF5 ae45f2bf9 adding HDF5 ab7782790 adding HDF5 dc6eb09b9 adding HDF5 2b766e2d2 fixing apt-get for curl 5d9b54b65 building openmpi 0697d04d8 building openmpi 0043527ad Merge pull request #1725 from NCAR/ejh_next_9 41b62fb6f fixed warning, turned of -Werror for fortran to try and get github workflow building c76f148b7 fixed warning, turned of -Werror for fortran to try and get github workflow building 32640e6f5 fixed warning, turned of -Werror for fortran to try and get github workflow building 3b6387898 fixed warning, turned of -Werror for fortran to try and get github workflow building fb4052a00 turning on -Wall for strict autotools build aa9f62cfa turning on -Wall for strict autotools build 1085b9521 Merge branch 'master' into ejh_next_9 23c5c50df Merge pull request #1726 from jedwards4b/reduce_search_netcdf 43f131525 remove more redundant find_package calls 6526724a8 add space cc11af948 no netcdf fortran in this test 8b97bd5b0 remove debug print statements 57f939fdf only search for netcdf at top level fe2fb7a7b removed extra workflow for now 5acda4b96 error out of cmake if netcdf-c dispatch table wont work for netcdf integration 52367bd73 trying to add another workflow a043a91fd trying to add another workflow 9be18aed4 took comments out of workflow file b26239d50 adding netCDF interation to build summary and pio_meta.h f1a83f3c1 Merge pull request #1715 from NCAR/ejh_ncint e57c5aa1c properly dealing with ncint_mod.F90 in cmake build 78dd092ef clean up 15527bf8e cleaned up cmake_config.h.in a604f76f3 added new github workflow for netCDF integration with cmake 08c7999e2 now all ncint tests work 444f0233d more work on ncint in cmake build 6bd5fa473 moved cmake build of ncint into src/clib dir, now test works! 9f57a5cc5 ncint build working! eaa065607 now building ncint directory with cmake cab47c393 merged changes from master a59a55b19 Merge pull request #1722 from NCAR/ejh_next_7 a1a04ef2e moved .f90 to .F90 089a7ecc6 turning off logging in a test 5b7f80104 more fortran flag cleanup 5f190e84e more fortran flag cleanup 7067c6331 cleanup of flags in test/unit autotools build 4d6e4f864 more flag cleanup a91eed922 more flag cleanup db93ea51b more changes so that all fortran files use config.h 0a10f86bc adding some cmakedefines 6213867ab cleanup of flag use in src/flib 4f80a53a9 Merge pull request #1720 from NCAR/ejh_next_6 0b2bebe4b removed unneeded pre-processor symbol from cmake_config.h.in 9b942c5bf Merge pull request #1719 from NCAR/ejh_next_5 b258478c3 removed troublesome strnlen() function 85edfb827 removed more unneeded pre-processor stuff 1ac844fff removed more unneeded pre-processor stuff 8a82deae2 removed more unneeded pre-processor stuff 8a8ba30d3 more removal of unneeded pre-processor symbols 4754ab5f4 removed unneeded check of _NETCDF ad4eddb75 removed NETCDF flag c99eb2896 Merge pull request #1718 from NCAR/ejh_next_3 4430bcd2c changed build summary 2676343e7 clean up travis file 7153ec973 removed constant 084f1c18c Merge pull request #1716 from NCAR/ejh_next 90d9af625 removed config constant that is unused anywhere... f269769d9 fixed setting of configure define in cmake b38aaefb2 starting to add ncint code to cmake build a28ec8c22 fixing cmake use of defines c5794a848 trying to fix cmake build 768c0c4a6 merged master a9ed7f1d4 Merge pull request #1714 from NCAR/ejh_fix_cmake_2 b9855320d fixed creation of config.h on read-only filesystem 52ac327ff adding support for NETCDF_INTEGRATION option to cmake, also fixing cmake build issue in read-only directories 116cd6eb1 Merge pull request #1710 from NCAR/ejh_cmake_fix 03006885f including HAVE_PAR_FILTERS in cmake config.h eed7d4886 Merge pull request #1707 from NCAR/ejh_cache_2 c0aa71a63 now trying caching for cmake build fc96bb3cf now trying caching for cmake build 6d93e738d now trying caching for cmake build 359bc447a now trying caching for cmake build 9b46b90e1 now trying caching for cmake build e307f964e now trying caching for strict pnetcdf build ab5f23485 now trying caching for pnetcdf build 7e4002993 now trying caching for pnetcdf build e11337c10 now install pnetcdf in subdirectory 23766326c Merge pull request #1705 from NCAR/ejh_fix_makefile 658b209b4 fixed makefile 9d4dbb773 Merge pull request #1700 from NCAR/ejh_4_7_2 ce1828aae took out caching attempt 09a7b2cf9 added comment bb3fc1423 cmake determination of par filters presence 5e5132326 attempting to cache pnetcdf build in workflow 348294616 changed fortran test to ignore deflate tests on NETCDF4P iotype f591b8c22 now use HAVE_PAR_FILTERS in test_pioc.c 8a298dca3 now check for netcdf-c disptach version in autoconf and cmake f66d558c6 fixed detection of 4.7.2 in autoconf to work for old netcdf releases that don't have netcdf_meta.h 042ea8157 added nc-config output to travis 3f4504890 added nc-config output to travis e049af45b added nc-config output to travis 8ac93feb5 added nc-config output to travis 783ff4d29 added nc-config output to travis 4ed861e07 added nc-config output to travis e0eb09028 disallow netcdf-c-4.7.2 for both cmake and autotools builds a14b65b3d Merge pull request #1698 from NCAR/ejh_test_simple ee339d016 fixed cmake running on 4 procs 62d09eecf called MPI_Finalize() in test_simple.c 8f40a3ae1 cleaned up simple test 39d4c796b merged master eedc46cd1 Merge pull request #1696 from NCAR/ejh_fix_test_leak 4438bf5a7 turns out we need fortran for pnetcdf 28fcb4852 turn off cxx and fortran for pnetcdf build 56243cfc0 turn off netcdf-integration in travis testing 88cf3d137 turn on netcdf-integration in travis testing abef381ae fixed memory leaks in tests 64a117c58 Merge pull request #1690 from NCAR/ejh_docs_2 e663bf300 removing redundant build 05ad86b24 turning on fortran build for autotools 90a1a2076 turning on fortran build for autotools 087658592 turning on fortran build for autotools dd9d7ddc7 trying doc build a different way 0cdc421a5 trying doc build a different way 0e6e349ea trying doc build a different way 282e3381c now can turn on deflate with netcdf-4 parallel e7cdd55ce got working for current state of play 3d4b09eab now reading and checking data aee02f360 getting test_simple working a430197eb getting test_simple working 09965b853 added unlimited dim, also creating decomp 137db078f now creating dim and var in test_simple 0c1589224 starting to fill in test_simple 56ea154d0 developing simple test 958d9b91a added test_simple.c git-subtree-dir: src/externals/pio2 git-subtree-split: 134c5209d8dd1b304dac16246ff794f255fbebb0 --- .github/workflows/a3.yml | 147 ++ .github/workflows/a4.yml | 147 ++ .github/workflows/autotools.yml | 35 +- .github/workflows/cmake.yml | 32 +- .github/workflows/cmake_ncint.yml | 60 + .github/workflows/strict_autotools.yml | 41 +- .travis.yml | 16 +- CMakeLists.txt | 138 +- Makefile.am | 2 +- cmake/LibMPI.cmake | 10 + cmake_config.h.in | 21 +- configure.ac | 91 +- ctest/runcdash-nwscla-gnu.sh | 12 +- ctest/runcdash-nwscla-intel.sh | 10 +- ctest/runcdash-nwscla-pgi.sh | 18 +- examples/basic/gdecomp_mod.F90 | 4 - examples/basic/testpio.F90 | 4 - examples/c/Makefile.am | 4 +- examples/c/{run_tests.sh => run_tests.sh.in} | 4 +- examples/f03/CMakeLists.txt | 2 +- examples/f03/Makefile.am | 10 +- .../f03/{examplePio.f90 => examplePio.F90} | 1 + .../f03/{run_tests.sh => run_tests.sh.in} | 2 +- libpio.settings.in | 6 +- set_flags.am | 18 - src/clib/CMakeLists.txt | 40 +- src/clib/Makefile.am | 6 +- src/clib/bget.c | 1677 ----------------- src/clib/bget.h | 41 - src/clib/pio_darray.c | 100 +- src/clib/pio_darray_int.c | 132 +- src/clib/pio_file.c | 2 +- src/clib/pio_internal.h | 10 - src/clib/pio_meta.h.in | 2 + src/clib/pio_nc.c | 6 - src/clib/pio_nc4.c | 10 +- src/clib/pio_rearrange.c | 4 +- src/clib/pioc.c | 16 +- src/clib/pioc_support.c | 8 - src/flib/CMakeLists.txt | 35 +- src/flib/Makefile.am | 36 +- src/flib/pio.F90 | 5 +- src/flib/pio_kinds.F90 | 1 + src/flib/pio_nf.F90 | 211 ++- src/flib/pio_support.F90 | 1 + src/flib/pio_types.F90 | 1 + src/flib/piodarray.F90.in | 3 + src/flib/piolib_mod.F90 | 56 +- src/flib/pionfatt_mod.F90.in | 47 +- src/flib/pionfget_mod.F90.in | 32 +- src/flib/pionfput_mod.F90.in | 1 + src/gptl/CMakeLists.txt | 4 +- src/ncint/ncintdispatch.c | 73 +- src/ncint/ncintdispatch.h | 8 + tests/CMakeLists.txt | 4 + tests/cunit/CMakeLists.txt | 90 +- tests/cunit/Makefile.am | 7 +- tests/cunit/pio_tests.h | 1 + tests/cunit/{run_tests.sh => run_tests.sh.in} | 8 +- tests/cunit/test_common.c | 3 +- tests/cunit/test_darray_append.c | 4 - tests/cunit/test_darray_frame.c | 2 +- tests/cunit/test_iosystem3.c | 6 +- tests/cunit/test_pioc.c | 37 +- tests/cunit/test_simple.c | 161 ++ tests/fncint/Makefile.am | 6 +- .../fncint/{run_tests.sh => run_tests.sh.in} | 2 +- tests/general/Makefile.am | 12 +- tests/general/ncdf_fail.F90.in | 1 + tests/general/ncdf_get_put.F90.in | 1 + tests/general/ncdf_inq.F90.in | 1 + tests/general/ncdf_simple_tests.F90.in | 1 + tests/general/pio_decomp_fillval.F90.in | 44 +- tests/general/pio_decomp_frame_tests.F90.in | 1 + tests/general/pio_decomp_tests.F90.in | 1 + tests/general/pio_decomp_tests_1d.F90.in | 1 + tests/general/pio_decomp_tests_2d.F90.in | 1 + tests/general/pio_decomp_tests_3d.F90.in | 1 + tests/general/pio_fail.F90.in | 1 + tests/general/pio_file_fail.F90.in | 1 + tests/general/pio_file_simple_tests.F90.in | 1 + tests/general/pio_init_finalize.F90.in | 1 + tests/general/pio_iosystem_tests.F90.in | 1 + tests/general/pio_iosystem_tests2.F90.in | 1 + tests/general/pio_iosystem_tests3.F90.in | 1 + tests/general/pio_rearr.F90.in | 1 + tests/general/pio_rearr_opts.F90.in | 1 + tests/general/pio_rearr_opts2.F90.in | 1 + .../general/{run_tests.sh => run_tests.sh.in} | 2 +- tests/general/util/pio_tf_f90gen.pl | 6 +- tests/general/util/pio_tutil.F90 | 94 +- tests/ncint/CMakeLists.txt | 31 + tests/ncint/Makefile.am | 6 +- tests/ncint/{run_perf.sh => run_perf.sh.in} | 2 +- tests/ncint/{run_tests.sh => run_tests.sh.in} | 6 +- tests/ncint/tst_ncint_async_perf.c | 5 +- tests/ncint/tst_ncint_perf.c | 7 +- tests/ncint/tst_var_compress.c | 154 ++ tests/performance/Makefile.am | 8 +- tests/performance/pioperformance.F90 | 1 + .../{run_tests.sh => run_tests.sh.in} | 2 +- tests/unit/CMakeLists.txt | 12 + tests/unit/Makefile.am | 19 +- tests/unit/basic_tests.F90 | 5 +- tests/unit/driver.F90 | 8 +- tests/unit/ftst_vars_chunking.F90 | 98 + tests/unit/global_vars.F90 | 4 +- tests/unit/ncdf_tests.F90 | 71 +- tests/unit/{run_tests.sh => run_tests.sh.in} | 4 +- 109 files changed, 1903 insertions(+), 2451 deletions(-) create mode 100644 .github/workflows/a3.yml create mode 100644 .github/workflows/a4.yml create mode 100644 .github/workflows/cmake_ncint.yml rename examples/c/{run_tests.sh => run_tests.sh.in} (87%) rename examples/f03/{examplePio.f90 => examplePio.F90} (99%) rename examples/f03/{run_tests.sh => run_tests.sh.in} (91%) delete mode 100644 set_flags.am delete mode 100644 src/clib/bget.c delete mode 100644 src/clib/bget.h rename tests/cunit/{run_tests.sh => run_tests.sh.in} (89%) mode change 100755 => 100644 create mode 100644 tests/cunit/test_simple.c rename tests/fncint/{run_tests.sh => run_tests.sh.in} (90%) rename tests/general/{run_tests.sh => run_tests.sh.in} (94%) create mode 100644 tests/ncint/CMakeLists.txt rename tests/ncint/{run_perf.sh => run_perf.sh.in} (91%) rename tests/ncint/{run_tests.sh => run_tests.sh.in} (79%) create mode 100644 tests/ncint/tst_var_compress.c rename tests/performance/{run_tests.sh => run_tests.sh.in} (90%) create mode 100644 tests/unit/ftst_vars_chunking.F90 rename tests/unit/{run_tests.sh => run_tests.sh.in} (81%) 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