diff --git a/.gitignore b/.gitignore index 8135a42d5..19b8038d1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,8 @@ swiftest_driver.sh !CMakeLists.txt !*.cmake -!COPYING.txt +!COPYING +!LICENSE !CHANGELOG !README.md !README_figs/** @@ -26,7 +27,6 @@ dump* *ipynb_checkpoints **/.DS_Store !version.txt -!LICENSE.txt !requirements.txt !pyproject.toml **/_skbuild @@ -57,4 +57,6 @@ netcdf-c-* netcdf-fortran-* zlib-* -actions-runner* \ No newline at end of file +actions-runner* + +env/** \ No newline at end of file diff --git a/CMakeFiles/3.27.0/CMakeCCompiler.cmake b/CMakeFiles/3.27.0/CMakeCCompiler.cmake new file mode 100644 index 000000000..a1b553d9c --- /dev/null +++ b/CMakeFiles/3.27.0/CMakeCCompiler.cmake @@ -0,0 +1,74 @@ +set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "AppleClang") +set(CMAKE_C_COMPILER_VERSION "15.0.0.15000040") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Darwin") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar") +set(CMAKE_C_COMPILER_AR "") +set(CMAKE_RANLIB "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib") +set(CMAKE_C_COMPILER_RANLIB "") +set(CMAKE_LINKER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld") +set(CMAKE_MT "") +set(CMAKE_TAPI "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) +set(CMAKE_C_LINKER_DEPFILE_SUPPORTED FALSE) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/local/include;/opt/homebrew/include;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/include;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/include;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/local/lib;/opt/homebrew/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/CMakeFiles/3.27.0/CMakeFortranCompiler.cmake b/CMakeFiles/3.27.0/CMakeFortranCompiler.cmake new file mode 100644 index 000000000..12e12ebd9 --- /dev/null +++ b/CMakeFiles/3.27.0/CMakeFortranCompiler.cmake @@ -0,0 +1,64 @@ +set(CMAKE_Fortran_COMPILER "/opt/homebrew/bin/gfortran-12") +set(CMAKE_Fortran_COMPILER_ARG1 "") +set(CMAKE_Fortran_COMPILER_ID "GNU") +set(CMAKE_Fortran_COMPILER_VERSION "12.3.0") +set(CMAKE_Fortran_COMPILER_WRAPPER "") +set(CMAKE_Fortran_PLATFORM_ID "") +set(CMAKE_Fortran_SIMULATE_ID "") +set(CMAKE_Fortran_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_Fortran_SIMULATE_VERSION "") + + +set(CMAKE_Fortran_COMPILER_SYSROOT "/Library/Developer/CommandLineTools/SDKs/MacOSX13.sdk/usr") +set(CMAKE_COMPILER_SYSROOT "/Library/Developer/CommandLineTools/SDKs/MacOSX13.sdk/usr") + +set(CMAKE_AR "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar") +set(CMAKE_Fortran_COMPILER_AR "/opt/homebrew/bin/gcc-ar-12") +set(CMAKE_RANLIB "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib") +set(CMAKE_TAPI "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi") +set(CMAKE_Fortran_COMPILER_RANLIB "/opt/homebrew/bin/gcc-ranlib-12") +set(CMAKE_COMPILER_IS_GNUG77 1) +set(CMAKE_Fortran_COMPILER_LOADED 1) +set(CMAKE_Fortran_COMPILER_WORKS TRUE) +set(CMAKE_Fortran_ABI_COMPILED TRUE) + +set(CMAKE_Fortran_COMPILER_ENV_VAR "FC") + +set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 1) + +set(CMAKE_Fortran_COMPILER_ID_RUN 1) +set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95;f03;F03;f08;F08) +set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_Fortran_LINKER_PREFERENCE 20) +set(CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED FALSE) +if(UNIX) + set(CMAKE_Fortran_OUTPUT_EXTENSION .o) +else() + set(CMAKE_Fortran_OUTPUT_EXTENSION .obj) +endif() + +# Save compiler ABI information. +set(CMAKE_Fortran_SIZEOF_DATA_PTR "8") +set(CMAKE_Fortran_COMPILER_ABI "") +set(CMAKE_Fortran_LIBRARY_ARCHITECTURE "") + +if(CMAKE_Fortran_SIZEOF_DATA_PTR AND NOT CMAKE_SIZEOF_VOID_P) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_Fortran_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_Fortran_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_Fortran_COMPILER_ABI}") +endif() + +if(CMAKE_Fortran_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + + +set(CMAKE_Fortran_SYSROOT_FLAG "-isysroot") +set(CMAKE_Fortran_OSX_DEPLOYMENT_TARGET_FLAG "-mmacosx-version-min=") + +set(CMAKE_Fortran_IMPLICIT_INCLUDE_DIRECTORIES "/opt/homebrew/Cellar/gcc@12/12.3.0/lib/gcc/12/gcc/aarch64-apple-darwin22/12/finclude;/usr/local/include;/opt/homebrew/include;/opt/homebrew/Cellar/gcc@12/12.3.0/lib/gcc/12/gcc/aarch64-apple-darwin22/12/include;/opt/homebrew/Cellar/gcc@12/12.3.0/lib/gcc/12/gcc/aarch64-apple-darwin22/12/include-fixed;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk/usr/include") +set(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES "gfortran;emutls_w;gcc;quadmath;emutls_w;gcc;gcc") +set(CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES "/usr/local/lib;/opt/homebrew/lib;/opt/homebrew/Cellar/gcc@12/12.3.0/lib/gcc/12/gcc/aarch64-apple-darwin22/12;/opt/homebrew/Cellar/gcc@12/12.3.0/lib/gcc/12/gcc;/opt/homebrew/Cellar/gcc@12/12.3.0/lib/gcc/12") +set(CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/CMakeFiles/3.27.0/CMakeSystem.cmake b/CMakeFiles/3.27.0/CMakeSystem.cmake new file mode 100644 index 000000000..ac5601a0f --- /dev/null +++ b/CMakeFiles/3.27.0/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Darwin-22.6.0") +set(CMAKE_HOST_SYSTEM_NAME "Darwin") +set(CMAKE_HOST_SYSTEM_VERSION "22.6.0") +set(CMAKE_HOST_SYSTEM_PROCESSOR "arm64") + + + +set(CMAKE_SYSTEM "Darwin-22.6.0") +set(CMAKE_SYSTEM_NAME "Darwin") +set(CMAKE_SYSTEM_VERSION "22.6.0") +set(CMAKE_SYSTEM_PROCESSOR "arm64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44cbb743e..4ce195ac5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,12 @@ IF (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.27") CMAKE_POLICY(SET CMP0148 OLD) ENDIF () +# Set some options the user may choose +OPTION(USE_COARRAY "Use Coarray Fortran for parallelization of test particles" OFF) +OPTION(USE_OPENMP "Use OpenMP for parallelization" ON) +OPTION(USE_SIMD "Use SIMD vectorization" ON) +OPTION(BUILD_SHARED_LIBS "Build using shared libraries" ON) + INCLUDE(GNUInstallDirs) IF (SKBUILD) SET(INSTALL_BINDIR ${SKBUILD_PLATLIB_DIR}/${SKBUILD_PROJECT_NAME}) @@ -43,7 +49,7 @@ ENDIF () # Have the .mod files placed in the include folder SET(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mod) -# Add our local modules to the module path +# Add our local modules to the module ldpath FILE(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules" LOCAL_MODULE_PATH) LIST(APPEND CMAKE_MODULE_PATH ${LOCAL_MODULE_PATH}) @@ -55,33 +61,40 @@ ELSE () MESSAGE(FATAL_ERROR "Compiler ${CMAKE_Fortran_COMPILER_ID} not recognized!") ENDIF () -# Set some options the user may choose -OPTION(USE_COARRAY "Use Coarray Fortran for parallelization of test particles" OFF) -OPTION(USE_OPENMP "Use OpenMP for parallelization" ON) -OPTION(USE_SIMD "Use SIMD vectorization" ON) -OPTION(BUILD_SHARED_LIBS "Build using shared libraries" ON) - # The following section is modified from Numpy f2py documentation IF(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) MESSAGE(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there.\n") ENDIF() +FIND_PACKAGE(NETCDF_Fortran REQUIRED) +IF (MSVC) + FIND_PACKAGE(HDF5 NAMES hdf5 COMPONENTS C HL REQUIRED CONFIG) + MESSAGE(STATUS "HDF5_FOUND: ${HDF5_FOUND}") + MESSAGE(STATUS "HDF5_VERSION: ${HDF5_VERSION}") + MESSAGE(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}") + MESSAGE(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}") +ELSE () + FIND_PACKAGE(HDF5 COMPONENTS C HL REQUIRED) +ENDIF () + # Ensure scikit-build modules FIND_PACKAGE(Python COMPONENTS Interpreter Development.Module REQUIRED) -# Define some directories that are important to the build + SET(SRC "${CMAKE_SOURCE_DIR}/src") SET(PY "${CMAKE_SOURCE_DIR}/swiftest") ##################################### # Tell how to install this executable ##################################### -IF(WIN32) +IF(CMAKE_SYSTEM_NAME STREQUAL "Windows") SET(CMAKE_INSTALL_PREFIX "C:\\Program Files\\swiftest") FILE(TO_CMAKE_PATH ${CMAKE_INSTALL_PREFIX} CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "Path for install") ELSE() - SET(CMAKE_INSTALL_PREFIX /usr/local) -ENDIF(WIN32) + SET(CMAKE_INSTALL_PREFIX /usr/local CACHE PATH "Path for install") +ENDIF() + # Make sure paths are correct for Unix or Windows style FILE(TO_CMAKE_PATH ${SRC} SRC) @@ -90,6 +103,17 @@ FILE(TO_CMAKE_PATH ${PY} PY) # Set the name of the swiftest library SET(SWIFTEST_LIBRARY ${SKBUILD_PROJECT_NAME}) +# Determine compiler options +IF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) + MESSAGE(FATAL_ERROR "Fortran compiler does not support F90") +ENDIF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) +INCLUDE(SetParallelizationLibrary) + +IF (COMPILER_OPTIONS STREQUAL "Intel" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + INCLUDE(SetMKL) +ENDIF () +INCLUDE(SetSwiftestFlags) + # The source for the SWIFTEST binary and have it placed in the bin folder ADD_SUBDIRECTORY(${SRC} ${CMAKE_INSTALL_BINDIR}) ADD_SUBDIRECTORY(${PY}) diff --git a/COPYING.txt b/COPYING similarity index 100% rename from COPYING.txt rename to COPYING diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/buildscripts/.gitignore b/buildscripts/.gitignore index e2ee4346f..9cfaceeed 100644 --- a/buildscripts/.gitignore +++ b/buildscripts/.gitignore @@ -1 +1,2 @@ -!*.sh \ No newline at end of file +!*.sh +!windows/*.cmake \ No newline at end of file diff --git a/buildscripts/_build_getopts.sh b/buildscripts/_build_getopts.sh index ac9e9586b..113f9e526 100755 --- a/buildscripts/_build_getopts.sh +++ b/buildscripts/_build_getopts.sh @@ -13,9 +13,14 @@ set -a SCRIPT_DIR=$(realpath $(dirname $0)) ROOT_DIR=$(realpath ${SCRIPT_DIR}/..) +# Get platform and architecture +read -r OS ARCH < <($SCRIPT_DIR/get_platform.sh) + # Parse arguments USTMT="Usage: ${0} [-d /path/to/dependency/source] [-p /prefix/path] [-m MACOSX_DEPLOYMENT_TARGET]" -MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"$(sw_vers --ProductVersion)"} +if [ $OS = "MacOSX" ]; then + MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"$(sw_vers --ProductVersion)"} +fi while getopts ":d:p:m:h" ARG; do case "${ARG}" in @@ -44,9 +49,8 @@ while getopts ":d:p:m:h" ARG; do esac done -read -r OS ARCH < <($SCRIPT_DIR/get_platform.sh) -BUILD_DIR=${BUILD_DIR:-$(mktemp -ut swiftest_build.XXXXXXXX)} -PREFIX=${PREFIX:-${ROOT_DIR}} +BUILD_DIR=${BUILD_DIR:-"${HOME}/Downloads"} +PREFIX=${PREFIX:-"/usr/local"} DEPENDENCY_DIR=${DEPENDENCY_DIR:-${BUILD_DIR}} mkdir -p ${DEPENDENCY_DIR} diff --git a/buildscripts/build_dependencies.sh b/buildscripts/build_dependencies.sh index 8d8027aa6..32ac73ea9 100755 --- a/buildscripts/build_dependencies.sh +++ b/buildscripts/build_dependencies.sh @@ -16,21 +16,36 @@ SCRIPT_DIR=$(realpath $(dirname $0)) set -a ARGS=$@ . ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} - +set -e cd $ROOT_DIR -printf "*********************************************************\n" -printf "* STARTING DEPENDENCY BUILD *\n" -printf "*********************************************************\n" -printf "Using ${OS} compilers:\nFC: ${FC}\nCC: ${CC}\nCXX: ${CXX}\n" -printf "Installing to ${PREFIX}\n" -printf "\n" + +if ! command -v ninja &> /dev/null; then + NINJA_VER="1.11.1" + + printf "*********************************************************\n" + printf "* FETCHING NINJA SOURCE *\n" + printf "*********************************************************\n" + printf "Copying files to ${DEPENDENCY_DIR}\n" + mkdir -p ${DEPENDENCY_DIR} + if [ ! -d ${DEPENDENCY_DIR}/ninja-${NINJA_VER} ]; then + [ -d ${DEPENDENCY_DIR}/zlib-* ] && rm -rf ${DEPENDENCY_DIR}/zlib-* + curl -L https://github.com/ninja-build/ninja/archive/refs/tags/v${NINJA_VER}.tar.gz | tar xvz -C ${DEPENDENCY_DIR} + fi + cd ${DEPENDENCY_DIR}/ninja-* + cmake -B build -S . -DCMAKE_INSTALL_PREFIX=${PREFIX} + cmake --build build + if [ -w ${PREFIX} ]; then + cmake --install build + else + sudo cmake --install build + fi +fi # Get the OpenMP Libraries if [ $OS = "MacOSX" ]; then ${SCRIPT_DIR}/get_lomp.sh ${ARGS} fi -set -e ${SCRIPT_DIR}/build_zlib.sh ${ARGS} ${SCRIPT_DIR}/build_hdf5.sh ${ARGS} ${SCRIPT_DIR}/build_netcdf-c.sh ${ARGS} diff --git a/buildscripts/build_hdf5.sh b/buildscripts/build_hdf5.sh index d351bd47d..3f93d036b 100755 --- a/buildscripts/build_hdf5.sh +++ b/buildscripts/build_hdf5.sh @@ -10,12 +10,26 @@ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # You should have received a copy of the GNU General Public License along with Swiftest. # If not, see: https://www.gnu.org/licenses. + +HDF5_VER="1_14_2" +ZLIB_VER="1.3" + SCRIPT_DIR=$(realpath $(dirname $0)) set -a ARGS=$@ . ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} +. ${SCRIPT_DIR}/set_compilers.sh + + +NPROC=$(nproc) + +printf "*********************************************************\n" +printf "* STARTING DEPENDENCY BUILD *\n" +printf "*********************************************************\n" +printf "Using ${OS} compilers:\nFC: ${FC}\nCC: ${CC}\nCXX: ${CXX}\n" +printf "Installing to ${PREFIX}\n" +printf "\n" -HDF5_VER="1_14_2" printf "*********************************************************\n" printf "* FETCHING HDF5 SOURCE *\n" printf "*********************************************************\n" @@ -36,8 +50,6 @@ fi if [ ! -d ${DEPENDENCY_DIR}/hdfsrc ]; then curl -s -L https://github.com/HDFGroup/hdf5/releases/download/hdf5-${HDF5_VER}/hdf5-${HDF5_VER}.tar.gz | tar xvz -C ${DEPENDENCY_DIR} fi - - printf "\n" printf "*********************************************************\n" printf "* BUILDING HDF5 LIBRARY *\n" @@ -51,20 +63,41 @@ printf "LDFLAGS: ${LDFLAGS}\n" printf "*********************************************************\n" cd ${DEPENDENCY_DIR}/hdfsrc + +HDF5_ROOT=${PREFIX} +ZLIB_ROOT=${PREFIX} +SZIP_ROOT=${PREFIX} +if [ $OS = "MacOSX" ]; then + ZLIB_LIBRARY="${ZLIB_ROOT}/lib/libz.dylib" +else + ZLIB_LIBRARY="${ZLIB_ROOT}/lib/libz.so" +fi + +ARGLIST="-DCMAKE_INSTALL_PREFIX:PATH=${HDF5_ROOT} \ + -DHDF5_ALLOW_EXTERNAL_SUPPORT:STRING="NO" \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DZLIB_LIBRARY:FILEPATH=${ZLIB_LIBRARY} \ + -DZLIB_INCLUDE_DIR:PATH=${ZLIB_ROOT}/include \ + -DZLIB_USE_EXTERNAL:BOOL=OFF \ + -DHDF5_ENABLE_SZIP_SUPPORT:BOOL=OFF \ + -DHDF5_ENABLE_PLUGIN_SUPPORT:BOOL=OFF \ + -DHDF5_BUILD_CPP_LIB:BOOL=OFF \ + -DHDF5_BUILD_FORTRAN:BOOL=OFF \ + -DHDF5_BUILD_EXAMPLES:BOOL=ON \ + -DBUILD_TESTING:BOOL=ON \ + -DHDF5_BUILD_JAVA:BOOL=OFF" + if [ $OS = "MacOSX" ]; then - read -r OS ARCH < <($SCRIPT_DIR/get_platform.sh) - if [ $ARCH = "arm64" ]; then - printf "Manually setting bin/config.sub to arm-apple-darwin\n" - printf "echo arm-apple-darwin" > bin/config.sub - fi + ARGLIST="${ARGLIST} -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=OFF" fi -COPTS="--enable-build-mode=production --enable-tests=no --enable-tools=no --disable-fortran --disable-java --disable-cxx --prefix=${PREFIX} --with-zlib=${PREFIX}" -./configure ${COPTS} -make + +cmake -B build -C ./config/cmake/cacheinit.cmake -G Ninja ${ARGLIST} . + +cmake --build build -j${NPROC} --config Release if [ -w ${PREFIX} ]; then - make install + cmake --install build else - sudo make install + sudo cmake --install build fi if [ $? -ne 0 ]; then diff --git a/buildscripts/build_netcdf-c.sh b/buildscripts/build_netcdf-c.sh index 8f692fac1..ee7415cbf 100755 --- a/buildscripts/build_netcdf-c.sh +++ b/buildscripts/build_netcdf-c.sh @@ -11,11 +11,19 @@ # You should have received a copy of the GNU General Public License along with Swiftest. # If not, see: https://www.gnu.org/licenses. SCRIPT_DIR=$(realpath $(dirname $0)) - set -a ARGS=$@ . ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} +. ${SCRIPT_DIR}/set_compilers.sh + +NPROC=$(nproc) +printf "*********************************************************\n" +printf "* STARTING DEPENDENCY BUILD *\n" +printf "*********************************************************\n" +printf "Using ${OS} compilers:\nFC: ${FC}\nCC: ${CC}\nCXX: ${CXX}\n" +printf "Installing to ${PREFIX}\n" +printf "\n" NC_VER="4.9.2" @@ -43,15 +51,27 @@ printf "HDF5_ROOT: ${HDF5_ROOT}\n" printf "*********************************************************\n" cd ${DEPENDENCY_DIR}/netcdf-c-* -COPTS="--disable-testsets --disable-nczarr --prefix=${PREFIX}" -printf "COPTS: ${COPTS}\n" -./configure $COPTS -make && make check +NCDIR="${PREFIX}" +ZLIB_ROOT=${PREFIX} +cmake -B build -S . -G Ninja \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DHDF5_DIR:PATH=${HDF5_ROOT}/cmake \ + -DHDF5_ROOT:PATH=${HDF5_ROOT} \ + -DCMAKE_FIND_ROOT_PATH:PATH="${PREFIX}" \ + -DCMAKE_INSTALL_PREFIX:STRING="${NCDIR}" \ + -DENABLE_DAP:BOOL=OFF \ + -DENABLE_BYTERANGE:BOOL=OFF \ + -DENABLE_NCZARR:BOOL=OFF \ + -DENABLE_NCZARR_FILTERS:BOOL=OFF \ + -DENABLE_LIBXML2:BOOL=OFF \ + -DCMAKE_INSTALL_LIBDIR="lib" \ + -DENABLE_REMOTE_FORTRAN_BOOTSTRAP:BOOL=ON +cmake --build build -j${NPROC} if [ -w ${PREFIX} ]; then - make install + cmake --install build else - sudo make install + sudo cmake --install build fi if [ $? -ne 0 ]; then diff --git a/buildscripts/build_netcdf-fortran.sh b/buildscripts/build_netcdf-fortran.sh index aea5e71aa..c82f24573 100755 --- a/buildscripts/build_netcdf-fortran.sh +++ b/buildscripts/build_netcdf-fortran.sh @@ -14,6 +14,16 @@ SCRIPT_DIR=$(realpath $(dirname $0)) set -a ARGS=$@ . ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} +. ${SCRIPT_DIR}/set_compilers.sh + +NPROC=$(nproc) + +printf "*********************************************************\n" +printf "* STARTING DEPENDENCY BUILD *\n" +printf "*********************************************************\n" +printf "Using ${OS} compilers:\nFC: ${FC}\nCC: ${CC}\nCXX: ${CXX}\n" +printf "Installing to ${PREFIX}\n" +printf "\n" NF_VER="4.6.1" printf "*********************************************************\n" @@ -24,7 +34,8 @@ if [ ! -d ${DEPENDENCY_DIR}/netcdf-fortran-${NF_VER} ]; then [ -d ${DEPENDENCY_DIR}/netcdf-fortran-* ] && rm -rf ${DEPENDENCY_DIR}/netcdf-fortran-* curl -s -L https://github.com/Unidata/netcdf-fortran/archive/refs/tags/v${NF_VER}.tar.gz | tar xvz -C ${DEPENDENCY_DIR} fi - +CFLAGS="$(nc-config --cflags) $CFLAGS" +LIBS="$(nc-config --libs) $LIBS" printf "\n" printf "*********************************************************\n" printf "* BUILDING NETCDF-FORTRAN LIBRARY *\n" @@ -38,12 +49,23 @@ printf "LDFLAGS: ${LDFLAGS}\n" printf "*********************************************************\n" cd ${DEPENDENCY_DIR}/netcdf-fortran-* -./configure --enable-large-file-tests=no --enable-static=no --enable-filter-test=no --prefix=${PREFIX} -make && make check i +NFDIR="${PREFIX}" +NCLIBDIR=$(${NCDIR}/bin/nc-config --libdir) +if [ $OS = "MacOSX" ]; then + netCDF_LIBRARIES="${NCLIBDIR}/libnetcdf.dylib" +else + netCDF_LIBRARIES="${NCLIBDIR}/libnetcdf.so" +fi +cmake -B build -S . -G Ninja \ + -DnetCDF_INCLUDE_DIR:PATH="${NCDIR}/include" \ + -DnetCDF_LIBRARIES:FILEPATH="${netCDF_LIBRARIES}" \ + -DCMAKE_INSTALL_PREFIX:PATH=${NFDIR} \ + -DCMAKE_INSTALL_LIBDIR="lib" +cmake --build build -j${NPROC} if [ -w ${PREFIX} ]; then - make install + cmake --install build else - sudo make install + sudo cmake --install build fi if [ $? -ne 0 ]; then diff --git a/buildscripts/build_zlib.sh b/buildscripts/build_zlib.sh index e21b75b47..337e6a839 100755 --- a/buildscripts/build_zlib.sh +++ b/buildscripts/build_zlib.sh @@ -14,7 +14,16 @@ SCRIPT_DIR=$(realpath $(dirname $0)) set -a ARGS=$@ . ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} +. ${SCRIPT_DIR}/set_compilers.sh +NPROC=$(nproc) + +printf "*********************************************************\n" +printf "* STARTING DEPENDENCY BUILD *\n" +printf "*********************************************************\n" +printf "Using ${OS} compilers:\nFC: ${FC}\nCC: ${CC}\nCXX: ${CXX}\n" +printf "Installing to ${PREFIX}\n" +printf "\n" ZLIB_VER="1.3" @@ -40,12 +49,13 @@ printf "LDFLAGS: ${LDFLAGS}\n" printf "*********************************************************\n" cd ${DEPENDENCY_DIR}/zlib-* -./configure --prefix=${PREFIX} -make +cmake -B build -S . -G Ninja -DCMAKE_INSTALL_PREFIX=${PREFIX} + +cmake --build build -j${NPROC} if [ -w ${PREFIX} ]; then - make install + cmake --install build else - sudo make install + sudo cmake --install build fi if [ $? -ne 0 ]; then diff --git a/buildscripts/install_editable_debug.sh b/buildscripts/install_editable_debug.sh new file mode 100755 index 000000000..d3d1fe721 --- /dev/null +++ b/buildscripts/install_editable_debug.sh @@ -0,0 +1,21 @@ +#!/bin/zsh +# installs an editable (local) package in debug mode +set -a +SCRIPT_DIR=$(realpath $(dirname $0)) +ROOT_DIR=$(realpath ${SCRIPT_DIR}/..) +VENV_DIR=${ROOT_DIR}/env +cd ${ROOT_DIR} +python3 -m venv ${VENV_DIR} +. ${VENV_DIR}/bin/activate +python3 -m pip install --upgrade pip +pip install scikit-build-core pyproject-metadata pathspec ninja cython +pip install --config-settings=editable.rebuild=true \ + --config-settings=build-dir="build/{wheel_tag}" \ + --config-settings=cmake.build-type="Debug" \ + --config-settings=cmake.args="-DUSE_SIMD=ON" \ + --config-settings=cmake.args="-DUSE_OPENMP=ON" \ + --no-build-isolation \ + -ve . +mkdir -p $HOME/.local/lib +LIBFILE=$(realpath ${ROOT_DIR}/build/*/bin/*swiftest.*) +ln -s $LIBFILE $HOME/.local/lib \ No newline at end of file diff --git a/buildscripts/set_compilers.sh b/buildscripts/set_compilers.sh index 7523628ee..70dd9f71e 100755 --- a/buildscripts/set_compilers.sh +++ b/buildscripts/set_compilers.sh @@ -13,9 +13,10 @@ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # You should have received a copy of the GNU General Public License along with Swiftest. # If not, see: https://www.gnu.org/licenses. -# Parse arguments +SCRIPT_DIR=$(realpath $(dirname $0)) +ROOT_DIR=$(realpath ${SCRIPT_DIR}/..) case "$OS" in - Linux|MacOSX) + Linux|MacOSX|Intel) ;; *) echo "Unknown compiler type: $OS" @@ -25,17 +26,17 @@ case "$OS" in ;; esac - set -a -# Only replace compiler definitions if they are not already set case $OS in Linux) + . ${SCRIPT_DIR}/set_environment_linux.sh FC=$(command -v gfortran) CC=$(command -v gcc) CXX=$(command -v g++) CPP=$(command -v cpp) ;; MacOSX) + . ${SCRIPT_DIR}/set_environment_macos.sh FC=${HOMEBREW_PREFIX}/bin/gfortran-12 CFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -Wno-deprecated-non-prototype -arch ${ARCH}" FCFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -arch ${ARCH}" @@ -51,6 +52,12 @@ case $OS in RANLIB=${COMPILER_PREFIX}/bin/ranlib LDFLAGS="-Wl,-no_compact_unwind" ;; + Intel) + FC=$(command -v ifx) + CC=$(command -v icx) + CXX=$(command -v icpx) + CPP=$(command -v cpp) + ;; *) printf "Unknown compiler type: ${OS}\n" echo "Valid options are Intel, Linux, or MacOSX" @@ -59,5 +66,4 @@ case $OS in ;; esac F77=${FC} - -printf "Using ${OS} compilers:\nFC: ${FC}\nCC: ${CC}\nCXX: ${CXX}\n\n" \ No newline at end of file +F95=${FC} \ No newline at end of file diff --git a/buildscripts/set_environment_linux.sh b/buildscripts/set_environment_linux.sh new file mode 100755 index 000000000..a7c566d59 --- /dev/null +++ b/buildscripts/set_environment_linux.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Sets environment flags on Linux +set -a +PREFIX="/usr/local" +NCDIR="${PREFIX}" +NFDIR="${PREFIX}" +NETCDF_FORTRAN_HOME="${NFDIR}" +NETCDF_FORTRAN_INCLUDE="${NFDIR}/include" +HDF5_ROOT="${PREFIX}" +HDF5_LIBDIR="${HDF5_ROOT}/lib" +HDF5_INCLUDE_DIR="${HDF5_ROOT}/include" +HDF5_PLUGIN_PATH="${HDF5_LIBDIR}/plugin" +LD_LIBRARY_PATH="${PREFIX}/lib" +CPATH="${PREFIX}/include:" +HDF5_DIR="${HDF5_ROOT}/cmake" +PATH="${HDF5_ROOT}/bin:${PATH}" +CMAKE_INSTALL_LIBDIR="lib" \ No newline at end of file diff --git a/buildscripts/set_environment.sh b/buildscripts/set_environment_macos.sh similarity index 86% rename from buildscripts/set_environment.sh rename to buildscripts/set_environment_macos.sh index e1cffbc64..cd51f1865 100755 --- a/buildscripts/set_environment.sh +++ b/buildscripts/set_environment_macos.sh @@ -11,6 +11,7 @@ LDFLAGS="-Wl,-rpath,${ROOT_DIR}/lib -Wl,-no_compact_unwind -L${PREFIX}/lib -L${ CPATH="/usr/local/include:${PREFIX}/include:${HOMEBREW_PREFIX}/include:${ROOT_DIR}/include" CPPFLAGS="-isystem ${PREFIX}/include -isystem /usr/local/include -Xclang -fopenmp" LIBS="-lomp" +CFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -Wno-deprecated-non-prototype -arch ${ARCH}" FCFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}" FFFLAGS="${FCFLAGS}" CFLAGS="${FCFLAGS} -Wno-deprecated-non-prototype" @@ -19,10 +20,10 @@ HDF5_ROOT="${PREFIX}" HDF5_LIBDIR="${HDF5_ROOT}/lib" HDF5_INCLUDE_DIR="${HDF5_ROOT}/include" HDF5_PLUGIN_PATH="${HDF5_LIBDIR}/plugin" -NETCDF_FORTRAN_HOME="${PREFIX}" -NETCDF_INCLUDE="${PREFIX}" NCDIR="${PREFIX}" NFDIR="${PREFIX}" +NETCDF_FORTRAN_HOME="${NFDIR}" +NETCDF_FORTRAN_INCLUDE="${NFDIR}/include" FC="$(command -v gfortran-12)" F77="${FC}" CC="/usr/bin/clang" diff --git a/buildscripts/windows/hdf5-cacheinit-windows.cmake b/buildscripts/windows/hdf5-cacheinit-windows.cmake new file mode 100644 index 000000000..d622c5430 --- /dev/null +++ b/buildscripts/windows/hdf5-cacheinit-windows.cmake @@ -0,0 +1,43 @@ +# +# Copyright by The HDF Group. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the COPYING file, which can be found at the root of the source code +# distribution tree, or in https://www.hdfgroup.org/licenses. +# If you do not have access to either file, you may request a copy from +# help@hdfgroup.org. +# +# This is the CMakeCache file. + +######################### +# cache entries for building as part of the Swiftest project +######################### + +set (HDF_PACKAGE_NAMESPACE "hdf5::" CACHE STRING "Name for HDF package namespace (can be empty)" FORCE) +set (HDF5_BUILD_CPP_LIB OFF CACHE BOOL "Build C++ support" FORCE) +set (HDF5_BUILD_FORTRAN OFF CACHE BOOL "Build FORTRAN support" FORCE) +set (HDF5_BUILD_JAVA OFF CACHE BOOL "Build JAVA support" FORCE) +set (HDF5_BUILD_GENERATORS OFF CACHE BOOL "Build Test Generators" FORCE) +set (BUILD_TESTING OFF CACHE BOOL "Build testing" FORCE) +set (HDF5_BUILD_EXAMPLES OFF CACHE BOOL "Build examples" FORCE) +set (HDF5_ENABLE_ALL_WARNINGS OFF CACHE BOOL "Enable all warnings" FORCE) +set (HDF5_ALLOW_EXTERNAL_SUPPORT "NO" CACHE STRING "Allow External Library Building (NO GIT TGZ)" FORCE) +set_property (CACHE HDF5_ALLOW_EXTERNAL_SUPPORT PROPERTY STRINGS NO GIT TGZ) +set (BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries" FORCE) + +######################## +# compression options +######################## +SET(ZLIB_LIBRARY "C:/Program Files (x86)/zlib/lib/zlib.lib" CACHE FILEPATH "ZLIB library file" FORCE) +SET(ZLIB_INCLUDE_DIR "C:/Program Files (x86)/zlib/include" CACHE PATH "ZLIB include directory" FORCE) +set (ZLIB_PACKAGE_NAME "zlib" CACHE STRING "Name of ZLIB package" FORCE) +set (ZLIB_USE_LOCALCONTENT OFF CACHE BOOL "Use local file for ZLIB FetchContent" FORCE) +set (LIBAEC_USE_LOCALCONTENT OFF CACHE BOOL "Use local file for LIBAEC FetchContent" FORCE) +set (ENABLE_SZIP OFF CACHE BOOL "Enable SZIP" FORCE) + +######################## +# filter plugin options +######################## +set (HDF5_ENABLE_PLUGIN_SUPPORT OFF CACHE BOOL "Enable plugins" FORCE) diff --git a/buildscripts/windows/netcdf-c-cacheinit-windows.cmake b/buildscripts/windows/netcdf-c-cacheinit-windows.cmake new file mode 100644 index 000000000..34f405d91 --- /dev/null +++ b/buildscripts/windows/netcdf-c-cacheinit-windows.cmake @@ -0,0 +1,55 @@ +# $Id: ConfigUser.cmake 9785 2012-02-29 09:56:54Z fwobbe $ +# +# Copyright (c) 2012, Florian Wobbe +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +# +# Use this file to override variables +# + +# Where netcdf will be installed: +set (CMAKE_INSTALL_PREFIX "C:/Program Files/netCDF" CACHE PATH "Where netcdf will be installed" FORCE) +set (CMAKE_FIND_ROOT_PATH "C:/Program Files" CACHE PATH "Location of find directories" FORCE) +set (BUILD_SHARED_LIBS OFF CACHE BOOL "Build with shared libraries" FORCE) + +# Location of HFD4, HDF5 and zlib +set (HDF5_DIR "C:/Program Files/HDF_Group/HDF5/1.14.2/cmake" CACHE PATH "Location of HDF5 cmake files" FORCE) +set (HDF5_ROOT "C:/Program Files/HDF_Group/HDF5/1.14.2" CACHE PATH "Location of HDF5" FORCE) + +SET(ZLIB_LIBRARY "C:/Program Files (x86)/zlib/lib/zlib.lib" CACHE FILEPATH "ZLIB library file" FORCE) +SET(ZLIB_INCLUDE_DIR "C:/Program Files (x86)/zlib/include" CACHE PATH "ZLIB include directory" FORCE) + +# Set build type can be: empty, Debug, Release, RelWithDebInfo or MinSizeRel +set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) + +if(MSVC) + # Automatically adds compiler definitions to all subdirectories too. + add_definitions(/D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN) + # Disable all warnings + string (REPLACE "/W3" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /w") +endif(MSVC) + +set(ENABLE_DAP OFF CACHE BOOL "Enable DAP" FORCE) +set(ENABLE_BYTERANGE OFF CACHE BOOL "Enable BYTERANGE" FORCE) +set(ENABLE_NCZARR OFF CACHE BOOL "Enable NCZARR" FORCE) +set(ENABLE_LIBXML2 OFF CACHE BOOL "Enable LIBXML2" FORCE) +SET(ENABLE_FILTER_TESTING OFF CACHE BOOL "Enable Filter Testing" FORCE) +SET(ENABLE_PLUGINS OFF CACHE BOOL "Enable Plugins" FORCE) diff --git a/buildscripts/windows/netcdf-fortran-cacheinit-windows.cmake b/buildscripts/windows/netcdf-fortran-cacheinit-windows.cmake new file mode 100644 index 000000000..1d1f807b6 --- /dev/null +++ b/buildscripts/windows/netcdf-fortran-cacheinit-windows.cmake @@ -0,0 +1,6 @@ +SET(netCDF_DIR "C:/Program Files/netCDF/lib/cmake/netCDF" CACHE PATH "Location of NetCDF-C cmake config files" FORCE) +SET(HDF5_DIR "C:/Program Files/HDF5_Group/HDF5/1.14.2/cmake" CACHE PATH "Location of HDF5 cmake config files" FORCE) +SET(HDF5_ROOT "C:/Program Files/HDF5_Group/HDF5/1.14.2" CACHE PATH "Location of HDF5" FORCE) +SET(BUILD_SHARED_LIBS OFF CACHE BOOL "Use shared libraries" FORCE) +SET(CMAKE_INSTALL_PREFIX "C:/Program Files/NC4F" CACHE PATH "Installation location" FORCE) +SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Compile build type" FORCE) \ No newline at end of file diff --git a/buildscripts/windows/swiftest-cacheinint-windows.cmake b/buildscripts/windows/swiftest-cacheinint-windows.cmake new file mode 100644 index 000000000..c5c42aa64 --- /dev/null +++ b/buildscripts/windows/swiftest-cacheinint-windows.cmake @@ -0,0 +1,7 @@ +SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) +SET(USE_OPENMP ON CACHE BOOL "Use OpenMP" FORCE) +SET(USE_SIMD OFF CACHE BOOL "Use SIMD instructions" FORCE) +SET(netCDF-Fortran_DIR "C:/Program Files/NC4F/lib/cmake/netCDF" CACHE PATH "Location of NetCDF-Fortran cmake config files" FORCE) +SET(HDF5_DIR "C:/Program Files/HDF5_Group/HDF5/1.14.2/cmake" CACHE PATH "Location of HDF5 cmake config files" FORCE) +SET(HDF5_ROOT "C:/Program Files/HDF5_Group/HDF5/1.14.2" CACHE PATH "Location of HDF5" FORCE) +SET(HDF5_USE_STATIC_LIBRARIES ON CACHE BOOL "Use static HDF5 libraries" FORCE) \ No newline at end of file diff --git a/cmake/Modules/FindNETCDF.cmake b/cmake/Modules/FindNETCDF.cmake deleted file mode 100644 index 05f91e77c..000000000 --- a/cmake/Modules/FindNETCDF.cmake +++ /dev/null @@ -1,207 +0,0 @@ -# Copyright 2022 - David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, & Dana Singh -# This file is part of Swiftest. -# Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -# Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# You should have received a copy of the GNU General Public License along with Swiftest. -# If not, see: https://www.gnu.org/licenses. - -# - Finds the NetCDF libraries - -SET(NFPREFIX_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Location of provided NetCDF-Fortran dependencies") -SET(NFINCLUDE_DIR "${NFPREFIX_DIR}/include" CACHE PATH "Location of provided netcdf.mod") -IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - FIND_PATH(NFBIN - NAMES nf-config - HINTS - NFPREFIX_DIR - ENV NETCDF_FORTRAN_HOME - ENV PATH - PATH_SUFFIXES - bin - ) - - IF (NFBIN) - SET(CMD "${NFBIN}/nf-config") - LIST(APPEND CMD "--includedir") - MESSAGE(STATUS "Searching for NetCDF-Fortran include directory using ${CMD}") - EXECUTE_PROCESS(COMMAND ${CMD} OUTPUT_VARIABLE NFINCLUDE_DIR ERROR_VARIABLE ERR RESULT_VARIABLE RES OUTPUT_STRIP_TRAILING_WHITESPACE) - IF (NFINCLUDE_DIR) - MESSAGE(STATUS "Found in ${NFINCLUDE_DIR}") - ELSE () - MESSAGE(STATUS "Cannot execute ${CMD}") - MESSAGE(STATUS "OUTPUT: ${NFINCLUDE_DIR}") - MESSAGE(STATUS "RESULT: ${RES}") - MESSAGE(STATUS "ERROR : ${ERR}") - ENDIF () - - SET(CMD "${NFBIN}/nf-config") - LIST(APPEND CMD "--prefix") - MESSAGE(STATUS "Searching for NetCDF-Fortran library directory using ${CMD}") - EXECUTE_PROCESS(COMMAND ${CMD} OUTPUT_VARIABLE NFPREFIX_DIR ERROR_VARIABLE ERR RESULT_VARIABLE RES OUTPUT_STRIP_TRAILING_WHITESPACE) - IF (NFPREFIX_DIR) - MESSAGE(STATUS "Found in ${NFPREFIX_DIR}") - ELSE () - MESSAGE(STATUS "Cannot execute ${CMD}") - MESSAGE(STATUS "OUTPUT: ${NFPREFIX_DIR}") - MESSAGE(STATUS "RESULT: ${RES}") - MESSAGE(STATUS "ERROR : ${ERR}") - ENDIF () - ENDIF() -ENDIF() - -MESSAGE(STATUS "\nNETCDF_INCLUDE: $ENV{NETCDF_INCLUDE}\nNETCDF_FORTRAN_HOME: $ENV{NETCDF_FORTRAN_HOME}\n") -FIND_PATH(NETCDF_INCLUDE_DIR - NAMES netcdf.mod - HINTS - ${NFINCLUDE_DIR} - ENV NETCDF_INCLUDE - ENV NETCDF_FORTRAN_HOME - ENV CPATH - PATH_SUFFIXES - include - modules - mod - REQUIRED -) - -MESSAGE(STATUS "NetCDF-Fortran include directory: ${NETCDF_INCLUDE_DIR}") - -IF (BUILD_SHARED_LIBS) - SET(NETCDFF "netcdff") -ELSE () - SET(NCPREFIX_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Location of provided NetCDF-C dependencies") - SET(H5PREFIX_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Location of provided HDF5 dependencies") - SET(ZPREFIX_DIR ${CMAKE_SOURCE_DIR} CACHE PATH "Location of provided zlib dependencies") - IF (CMAKE_SYSTEM_NAME STREQUAL "Windows") - SET(NETCDFF "netcdff.lib") - SET(NETCDF "netcdf.lib") - SET(HDF5 "libhdf5.lib") - SET(HDF5_HL "libhdf5_hl.lib") - SET(ZLIB "zlibstatic.lib") - ELSE () - SET(NETCDFF "libnetcdff.a") - SET(NETCDF "libnetcdf.a") - SET(HDF5 "libhdf5.a") - SET(HDF5_HL "libhdf5_hl.a") - SET(ZLIB "libz.a") - ENDIF() -ENDIF() - -FIND_LIBRARY(NETCDF_FORTRAN_LIBRARY - NAMES ${NETCDFF} - HINTS - ${NFPREFIX_DIR} - ENV NETCDF_FORTRAN_HOME - ENV NETCDF_HOME - ENV LD_LIBRARY_PATH - PATH_SUFFIXES - lib - ${CMAKE_LIBRARY_ARCHITECTURE} - REQUIRED -) - -MESSAGE(STATUS "NetCDF-Fortran Library: ${NETCDF_FORTRAN_LIBRARY}") - -IF (BUILD_SHARED_LIBS) - SET(NETCDF_LIBRARIES ${NETCDF_FORTRAN_LIBRARY} CACHE STRING "NetCDF Fortran library") -ELSE () - FIND_LIBRARY(NETCDF_LIBRARY - NAMES ${NETCDF} - HINTS - ${NCPREFIX_DIR} - ENV NETCDF_HOME - ENV LD_LIBRARY_PATH - PATH_SUFFIXES - lib - ${CMAKE_LIBRARY_ARCHITECTURE} - REQUIRED - ) - - MESSAGE(STATUS "NetCDF-C Library: ${NETCDF_LIBRARY}") - IF (CMAKE_SYSTEM_NAME STREQUAL "Windows") - FIND_LIBRARY(HDF5_LIBRARY - NAMES ${HDF5} - HINTS - ${H5PREFIX_DIR} - ENV HDF5_ROOT - ENV LD_LIBRARY_PATH - PATH_SUFFIXES - lib - ${CMAKE_LIBRARY_ARCHITECTURE} - REQUIRED - ) - - FIND_LIBRARY(HDF5_HL_LIBRARY - NAMES ${HDF5_HL} - HINTS - ${H5PREFIX_DIR} - ENV HDF5_ROOT - ENV LD_LIBRARY_PATH - PATH_SUFFIXES - lib - ${CMAKE_LIBRARY_ARCHITECTURE} - REQUIRED - ) - - FIND_LIBRARY(Z_LIBRARY - NAMES ${ZLIB} - HINTS - ${ZPREFIX_DIR} - ENV ZLIB_ROOT - ENV LD_LIBRARY_PATH - PATH_SUFFIXES - lib - ${CMAKE_LIBRARY_ARCHITECTURE} - REQUIRED - ) - - LIST(APPEND EXTRA_FLAGS ${HDF5_LIBRARY} ${HDF5_HL_LIBRARY} ${Z_LIBRARY}) - - ELSE () - FIND_PATH(NCBIN - NAMES nc-config - HINTS - ENV NETCDF_HOME - ENV PATH - PATH_SUFFIXES - bin - ) - - IF (NCBIN) # The nc-config utility is available. Parse its output for unique flags - SET(CMD "${NCBIN}/nc-config") - LIST(APPEND CMD "--libs") - LIST(APPEND CMD "--static") - MESSAGE(STATUS "NetCDF configuration command: ${CMD}") - EXECUTE_PROCESS(COMMAND ${CMD} OUTPUT_VARIABLE EXTRA_FLAGS ERROR_VARIABLE ERR RESULT_VARIABLE RES OUTPUT_STRIP_TRAILING_WHITESPACE) - IF (EXTRA_FLAGS) - SEPARATE_ARGUMENTS(EXTRA_FLAGS NATIVE_COMMAND "${EXTRA_FLAGS}") - LIST(REMOVE_DUPLICATES EXTRA_FLAGS) - LIST(FILTER EXTRA_FLAGS EXCLUDE REGEX "netcdf+") - MESSAGE(STATUS "Extra library flags: ${EXTRA_FLAGS}") - ELSE () - MESSAGE(STATUS "Cannot execute ${CMD}") - MESSAGE(STATUS "OUTPUT: ${EXTRA_FLAGS}") - MESSAGE(STATUS "RESUL : ${RES}") - MESSAGE(STATUS "ERROR : ${ERR}") - MESSAGE(FATAL_ERROR "Cannot configure NetCDF for static") - ENDIF () - ELSE () - MESSAGE(FATAL_ERROR "Cannot find nc-config") - ENDIF () - ENDIF() - - IF (DEFINED ENV{LIBS}) - STRING(STRIP "$ENV{LIBS}" LIBS) - SEPARATE_ARGUMENTS(LIBS NATIVE_COMMAND "${LIBS}") - LIST(APPEND EXTRA_FLAGS ${LIBS}) - ENDIF() - - # Note for posterity: When building static libraries, NETCDF_FORTRAN_LIBRARY must come *before* NETCDF_LIBRARY. Otherwise you get a bunch of "undefined reference to" errors - SET(NETCDF_LIBRARIES ${NETCDF_FORTRAN_LIBRARY} ${NETCDF_LIBRARY} ${EXTRA_FLAGS} CACHE STRING "NetCDF Fortran and dependant static libraries") -ENDIF () -MESSAGE(STATUS "NetCDF dependencies: ${NETCDF_LIBRARIES}") - -SET(NETCDF_FOUND TRUE) -MARK_AS_ADVANCED(NETCDF_LIBRARIES NETCDF_INCLUDE_DIR) \ No newline at end of file diff --git a/cmake/Modules/FindNETCDF_Fortran.cmake b/cmake/Modules/FindNETCDF_Fortran.cmake new file mode 100644 index 000000000..ee56789a5 --- /dev/null +++ b/cmake/Modules/FindNETCDF_Fortran.cmake @@ -0,0 +1,184 @@ +# Copyright 2022 - David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, & Dana Singh +# This file is part of Swiftest. +# Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +# Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# You should have received a copy of the GNU General Public License along with Swiftest. +# If not, see: https://www.gnu.org/licenses. + +# - Finds the NetCDF libraries +# Tries to find the cmake config files first. Otherwise, try to find the libraries and headers by hand + +IF (NOT netCDF-Fortran_DIR) + IF (CMAKE_SYSTEM_NAME STREQUAL "Windows") + FILE(GLOB LIBDIRS "C:/Program Files*/NC4F") + LIST(SORT LIBDIRS) + LIST(GET LIBDIRS -1 LIBPREFIX) + SET(netCDF-Fortran_DIR "${LIBPREFIX}/lib/cmake/netCDF" CACHE PATH "Location of provided netCDF-FortranConfig.cmake file") + ELSE() + SET(netCDF-Fortran_DIR "/usr/local/lib/cmake/netCDF" CACHE PATH "Location of provided netCDF-FortranConfig.cmake file") + ENDIF () +ENDIF() + +MESSAGE(STATUS "Looking for netCDF-FortranConfig.cmake in ${netCDF-Fortran_DIR}") +FIND_PACKAGE(netCDF-Fortran QUIET) +IF (netCDF-Fortran_FOUND) + MESSAGE(STATUS "Found the NetCDF library via cmake configuration files") +ELSE () + MESSAGE(STATUS "No cmake configuration files detected. Searching for library files manually.") + IF (CMAKE_SYSTEM_NAME STREQUAL "Linux") + SET(NFPREFIX_DIR "/usr/local" CACHE PATH "Location of provided NetCDF-Fortran dependencies") + SET(NFINCLUDE_DIR "/usr/local/include" CACHE PATH "Location of provided netcdf.mod") + IF (NOT BUILD_SHARED_LIBS) + SET(NCPREFIX_DIR "/usr/local" CACHE PATH "Location of provided NetCDF-C dependencies") + SET(H5PREFIX_DIR "/usr/local" CACHE PATH "Location of provided HDF5 dependencies") + SET(ZPREFIX_DIR "/usr/local" CACHE PATH "Location of provided zlib dependencies") + ENDIF () + ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Darwin") + IF (DEFINED ENV{HOMEBREW_PREFIX}) + SET(LIBPREFIX "$ENV{HOMEBREW_PREFIX}") + ELSE () + SET(LIBPREFIX "/usr/local") + ENDIF() + + SET(NFPREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided NetCDF-Fortran dependencies") + SET(NFINCLUDE_DIR "${LIBPREFIX}/include" CACHE PATH "Location of provided netcdf.mod") + IF (NOT BUILD_SHARED_LIBS) + SET(NCPREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided NetCDF-C dependencies") + SET(H5PREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided HDF5 dependencies") + SET(ZPREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided zlib dependencies") + ENDIF () + ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Windows") + FILE(GLOB LIBDIRS "C:/Program Files*/NC4F") + LIST(SORT LIBDIRS) + LIST(GET LIBDIRS -1 LIBPREFIX) + SET(NFPREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided NetCDF-Fortran dependencies") + SET(NFINCLUDE_DIR "${LIBPREFIX}/include" CACHE PATH "Location of provided netcdf.mod") + IF (NOT BUILD_SHARED_LIBS) + # Assumes that the dependency libraries are packaged with NetCDF-C. + FILE(GLOB LIBDIRS "C:/Program Files*/netCDF*") + LIST(SORT LIBDIRS) + LIST(GET LIBDIRS -1 LIBPREFIX) + SET(NCPREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided NetCDF-C dependencies") + SET(H5PREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided HDF5 dependencies") + SET(ZPREFIX_DIR "${LIBPREFIX}" CACHE PATH "Location of provided zlib dependencies") + ENDIF () + ENDIF () + + IF(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + FIND_FILE(NFBIN + NAMES nf-config + HINTS + NFPREFIX_DIR + ENV NETCDF_FORTRAN_HOME + ENV PATH + PATH_SUFFIXES + bin + ) + + IF (NFBIN) + SET(CMD "${NFBIN}") + LIST(APPEND CMD "--includedir") + MESSAGE(STATUS "Searching for NetCDF-Fortran include directory using ${CMD}") + EXECUTE_PROCESS(COMMAND ${CMD} OUTPUT_VARIABLE NFINCLUDE_DIR ERROR_VARIABLE ERR RESULT_VARIABLE RES OUTPUT_STRIP_TRAILING_WHITESPACE) + IF (NFINCLUDE_DIR) + MESSAGE(STATUS "Found in ${NFINCLUDE_DIR}") + ELSE () + MESSAGE(STATUS "Cannot execute ${CMD}") + MESSAGE(STATUS "OUTPUT: ${NFINCLUDE_DIR}") + MESSAGE(STATUS "RESULT: ${RES}") + MESSAGE(STATUS "ERROR : ${ERR}") + ENDIF () + + SET(CMD "${NFBIN}") + LIST(APPEND CMD "--prefix") + MESSAGE(STATUS "Searching for NetCDF-Fortran library directory using ${CMD}") + EXECUTE_PROCESS(COMMAND ${CMD} OUTPUT_VARIABLE NFPREFIX_DIR ERROR_VARIABLE ERR RESULT_VARIABLE RES OUTPUT_STRIP_TRAILING_WHITESPACE) + IF (NFPREFIX_DIR) + MESSAGE(STATUS "Found in ${NFPREFIX_DIR}") + ELSE () + MESSAGE(STATUS "Cannot execute ${CMD}") + MESSAGE(STATUS "OUTPUT: ${NFPREFIX_DIR}") + MESSAGE(STATUS "RESULT: ${RES}") + MESSAGE(STATUS "ERROR : ${ERR}") + ENDIF () + ENDIF() + ENDIF() + + FIND_PATH(NETCDF_FORTRAN_INCLUDE_DIR + NAMES netcdf.mod + HINTS + ${NFINCLUDE_DIR} + ENV NETCDF_INCLUDE + ENV NETCDF_FORTRAN_HOME + ENV CPATH + PATH_SUFFIXES + include + modules + mod + REQUIRED + ) + + IF (BUILD_SHARED_LIBS) + SET(NETCDFF "netcdff") + ELSE () + IF (CMAKE_SYSTEM_NAME STREQUAL "Windows") + SET(NETCDFF "netcdff.lib") + SET(NETCDF "netcdf.lib") + SET(HDF5 "libhdf5.lib") + SET(HDF5_HL "libhdf5_hl.lib") + SET(ZLIB "zlib.lib") + ELSE () + SET(NETCDFF "libnetcdff.a") + SET(NETCDF "libnetcdf.a") + SET(HDF5 "libhdf5.a") + SET(HDF5_HL "libhdf5_hl.a") + SET(ZLIB "libz.a") + ENDIF() + ENDIF() + + FIND_LIBRARY(NFLIB + NAMES ${NETCDFF} + PATHS + ${NFPREFIX_DIR} + ENV NETCDF_FORTRAN_HOME + ENV NETCDF_HOME + ENV LD_LIBRARY_PATH + PATH_SUFFIXES + lib + ${CMAKE_LIBRARY_ARCHITECTURE} + REQUIRED + ) + ADD_LIBRARY(netCDF::netcdff UNKNOWN IMPORTED PUBLIC) + IF (CMAKE_SYSTEM_NAME STREQUAL "Windows" AND BUILD_SHARED_LIBS) + # Get the DLL added in + FIND_FILE(NFDLL + NAMES "netcdff.dll" + HINTS + NFPREFIX_DIR + ENV NETCDF_FORTRAN_HOME + ENV PATH + PATH_SUFFIXES + bin + ) + SET_TARGET_PROPERTIES(netCDF::netcdff PROPERTIES + IMPORTED_IMPLIB "${NFLIB}" + IMPORTED_LOCATION "${NFDLL}" + INTERFACE_INCLUDE_DIRECTORIES "${NETCDF_FORTRAN_INCLUDE_DIR}" + ) + MESSAGE(STATUS "NetCDF-Fortran dll: ${NFDLL}") + ELSE () + SET_TARGET_PROPERTIES(netCDF::netcdff PROPERTIES + IMPORTED_LOCATION "${NFLIB}" + INTERFACE_INCLUDE_DIRECTORIES "${NETCDF_FORTRAN_INCLUDE_DIR}" + ) + ENDIF() + + MESSAGE(STATUS "NetCDF-Fortran library: ${NFLIB}") + MESSAGE(STATUS "NetCDF-Fortran include directory: ${NETCDF_FORTRAN_INCLUDE_DIR}") +ENDIF () + + +SET(NETCDF_FORTRAN_FOUND TRUE) +MARK_AS_ADVANCED(NETCDF_FORTRAN_LIBRARY NETCDF_FORTRAN_INCLUDE_DIR) \ No newline at end of file diff --git a/cmake/Modules/FindOpenMP_Fortran.cmake b/cmake/Modules/FindOpenMP_Fortran.cmake index 33eda8f5b..2b5b80ef4 100644 --- a/cmake/Modules/FindOpenMP_Fortran.cmake +++ b/cmake/Modules/FindOpenMP_Fortran.cmake @@ -34,7 +34,7 @@ IF (COMPILER_OPTIONS STREQUAL "Intel") ) ELSE () SET (OpenMP_Fortran_FLAG_CANDIDATES - "/Qopenmp-simd-" # Intel Windows + "/Qopenmp /Qopenmp-simd-" # Intel Windows ) ENDIF (USE_SIMD) ELSE () diff --git a/cmake/Modules/SetCompileFlag.cmake b/cmake/Modules/SetCompileFlag.cmake index 69e3526f8..f5644e266 100644 --- a/cmake/Modules/SetCompileFlag.cmake +++ b/cmake/Modules/SetCompileFlag.cmake @@ -36,6 +36,7 @@ INCLUDE(${CMAKE_ROOT}/Modules/CheckCCompilerFlag.cmake) INCLUDE(${CMAKE_ROOT}/Modules/CheckCXXCompilerFlag.cmake) +INCLUDE(${CMAKE_ROOT}/Modules/CheckFortranCompilerFlag.cmake) FUNCTION(SET_COMPILE_FLAG FLAGVAR FLAGVAL LANG) @@ -79,26 +80,7 @@ FUNCTION(SET_COMPILE_FLAG FLAGVAR FLAGVAL LANG) ELSEIF(LANG STREQUAL "CXX") CHECK_CXX_COMPILER_FLAG("${flag}" FLAG_WORKS) ELSEIF(LANG STREQUAL "Fortran") - # There is no nice function to do this for FORTRAN, so we must manually - # create a test program and check if it compiles with a given flag. - SET(TESTFILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}") - SET(TESTFILE "${TESTFILE}/CMakeTmp/testFortranFlags.f90") - FILE(WRITE "${TESTFILE}" -" -program dummyprog - i = 5 -end program dummyprog -") - TRY_COMPILE(FLAG_WORKS ${CMAKE_BINARY_DIR} ${TESTFILE} - COMPILE_DEFINITIONS "${flag}" OUTPUT_VARIABLE OUTPUT) - - # Check that the output message doesn't match any errors - FOREACH(rx ${FAIL_REGEX}) - IF("${OUTPUT}" MATCHES "${rx}") - SET(FLAG_WORKS FALSE) - ENDIF("${OUTPUT}" MATCHES "${rx}") - ENDFOREACH(rx ${FAIL_REGEX}) - + CHECK_Fortran_COMPILER_FLAG("${flag}" FLAG_WORKS) ELSE() MESSAGE(FATAL_ERROR "Unknown language in SET_COMPILE_FLAGS: ${LANG}") ENDIF(LANG STREQUAL "C") diff --git a/cmake/Modules/SetFortranFlags.cmake b/cmake/Modules/SetSwiftestFlags.cmake similarity index 82% rename from cmake/Modules/SetFortranFlags.cmake rename to cmake/Modules/SetSwiftestFlags.cmake index c5514e749..470f5c210 100644 --- a/cmake/Modules/SetFortranFlags.cmake +++ b/cmake/Modules/SetSwiftestFlags.cmake @@ -46,14 +46,13 @@ ELSE() MESSAGE(FATAL_ERROR "CMAKE_BUILD_TYPE not valid! ${BUILD_TYPE_MSG}") ENDIF(BT STREQUAL "RELEASE") - ######################################################### # If the compiler flags have already been set, return now ######################################################### IF(CMAKE_Fortran_FLAGS_RELEASE AND CMAKE_Fortran_FLAGS_TESTING AND CMAKE_Fortran_FLAGS_DEBUG AND CMAKE_Fortran_FLAGS_PROFILE ) RETURN () -ENDIF(CMAKE_Fortran_FLAGS_RELEASE AND CMAKE_Fortran_FLAGS_TESTING AND CMAKE_Fortran_FLAGS_DEBUG AND CMAKE_Fortran_FLAGS_PROFILE) +ENDIF() ######################################################################## # Determine the appropriate flags for this compiler for each build type. @@ -72,13 +71,11 @@ ENDIF () ### GENERAL FLAGS ### ##################### - # Free form IF (COMPILER_OPTIONS STREQUAL "GNU") SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-ffree-form" # GNU ) - # Don't add underscores in symbols for C-compatability SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-fno-underscoring" # GNU @@ -88,12 +85,10 @@ IF (COMPILER_OPTIONS STREQUAL "GNU") SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-fsignaling-nans " # GNU ) - # Allows for lines longer than 80 characters without truncation SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-ffree-line-length-512" # GNU (gfortran) ) - # Sets the dialect standard SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-std=f2018" @@ -131,7 +126,6 @@ IF (NOT BUILD_SHARED_LIBS AND NOT WINOPT) SET_COMPILE_FLAG(CMAKE_FORTRAN_FLAGS "${CMAKE_FORTRAN_FLAGS}" Fortran "-fPIC" ) - IF (COMPILER_OPTIONS STREQUAL "Intel") # Use static Intel libraries SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" @@ -141,27 +135,27 @@ IF (NOT BUILD_SHARED_LIBS AND NOT WINOPT) SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" Fortran "-static_mpi" # Intel ) - IF (USE_OPENMP) SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" Fortran "-qopenmp-link=static" # Intel ) ENDIF (USE_OPENMP) - ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") - # # Set GNU static libraries - # SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - # Fortran "-static-libgfortran" - # ) - # SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - # Fortran "-static-libgcc" - # ) - # SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - # Fortran "-static-libstdc++" - # ) - # SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - # Fortran "-static-libquadmath" - # ) + IF (NOT BUILD_SHARED_LIBS) + # Set GNU static libraries + SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" + Fortran "-static-libgfortran" + ) + SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" + Fortran "-static-libgcc" + ) + SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" + Fortran "-static-libstdc++" + ) + SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" + Fortran "-static-libquadmath" + ) + ENDIF () IF (USE_OPENMP) SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" Fortran "-lomp" @@ -194,55 +188,52 @@ IF (USE_SIMD) # Optimize for an old enough processor that it should run on most computers IF (WINOPT) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "/Qx${MACHINE_CODE_VALUE}" # Intel - ) - # Generate an extended set of vector functions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + ) + # Generate an extended set of vector functions + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "/Qvecabi:cmdtarget" # Intel Windows - ) + ) ELSE () - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-x${MACHINE_CODE_VALUE}" # Intel - ) - # Generate an extended set of vector functions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + ) + # Generate an extended set of vector functions + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-vecabi=cmdtarget" # Intel - ) + ) ENDIF () ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") SET(MACHINE_CODE_VALUE "native" CACHE STRING "Tells the compiler which processor features it may target, including which instruction sets and optimizations it may generate.") - # Enables OpenMP SIMD compilation when OpenMP parallelization is disabled. IF (NOT USE_OPENMP) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-fno-openmp -fopenmp-simd" # GNU - ) + ) ENDIF (NOT USE_OPENMP) IF (MACHINE_CODE_VALUE STREQUAL "Host") - SET(MACHINE_CODE_VALUE "native" CACHE STRING "native is the GNU equivalent of Host" FORCE) + SET(MACHINE_CODE_VALUE "native" CACHE STRING "native is the GNU equivalent of Host" FORCE) ENDIF () IF (APPLE) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-mtune=${MACHINE_CODE_VALUE}" - ) + ) ELSE () - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-march=${MACHINE_CODE_VALUE}" - ) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + ) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" Fortran "-mtune=${MACHINE_CODE_VALUE}" - ) + ) ENDIF () - ENDIF () SET(MACHINE_CODE_VALUE ${MACHINE_CODE_VALUE} CACHE STRING "Tells the compiler which processor features it may target, including which instruction sets and optimizations it may generate.") ENDIF (USE_SIMD) - ################### ### DEBUG FLAGS ### ################### @@ -253,32 +244,35 @@ IF (CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "TESTING" ) SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran REQUIRED "/Od" # Intel Windows ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C REQUIRED "/0d" + ) # Turn on all warnings SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/warn:all" # Intel Windows ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "/warn:all" # Intel Windows + ) # Tells the compiler to issue compile-time messages for nonstandard language elements (Fortran 2018). SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/stand:f18" # Intel Windows ) - # Traceback SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/traceback" # Intel Windows ) - # Check everything SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/check:all" # Intel Windows ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "/check:all" # Intel Windows + ) # Initializes matrices/arrays with NaN values SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/Qinit:snan,arrays" # Intel Windows ) - # Does not generate an interface block for each routine in a source file SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/nogen-interfaces" # Intel Windows @@ -288,27 +282,25 @@ IF (CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "TESTING" ) SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/Qftz-" # Intel Windows ) - # Enables floating-point invalid, divide-by-zero, and overflow exceptions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/fpe-all:0" # Intel Windows ) - # Enables floating-point invalid, divide-by-zero, and overflow exceptions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/fpe:0" # Intel Windows ) - # Enables debug info SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/debug:all" # Intel Windows ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "/debug:all" # Intel Windows + ) # Disables additional interprocedural optimizations for a single file compilation SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/Qip-" # Intel Windows ) - # Disables prefetch insertion optimization SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "/Qopt-prefetch-" # Intel Windows @@ -317,145 +309,166 @@ IF (CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "TESTING" ) SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran REQUIRED "-O0" # All compilers not on Windows ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C REQUIRED "-O0" # All compilers not on Windows + ) # Turn on all warnings SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-warn all" # Intel ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-Wall" # Intel + ) # Tells the compiler to issue compile-time messages for nonstandard language elements (Fortran 2018). SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-stand f18" # Intel ) - # Traceback SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-traceback" # Intel Group ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-traceback" # Intel Group + ) # Check everything SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-check all" # Intel ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-check=conversions,stack,uninit" # Intel + ) # Initializes matrices/arrays with NaN values SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-init=snan,arrays" # Intel ) - # Does not generate an interface block for each routine in a source file SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-nogen-interfaces" # Intel ) - # Does not generate aposition independent executable SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-no-pie" # Intel ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-no-pie" # Intel + ) # Does not set denormal results from floating-point calculations to zero SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-no-ftz" # Intel ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-no-ftz" # Intel + ) # Enables floating-point invalid, divide-by-zero, and overflow exceptions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-fpe-all=0" # Intel ) - # Enables floating-point invalid, divide-by-zero, and overflow exceptions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-fpe0" # Intel ) - # Enables debug info SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-debug all" # Intel ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-debug all" # Intel + ) # Disables additional interprocedural optimizations for a single file compilation SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-no-ip" # Intel ) - # Disables prefetch insertion optimization SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran "-qno-opt-prefetch" # Intel ) - ENDIF () - ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" Fortran REQUIRED "-Og" # GNU (gfortran) ) - + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C REQUIRED "-Og" # GNU (gfortran) + ) # Turn on all warnings SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-Wall" # GNU + Fortran "-Wall" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-Wall" # GNU ) # This enables some extra warning flags that are not enabled by -Wall SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-Wextra" # GNU + Fortran "-Wextra" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-Wextra" # GNU ) - # Disable the warning that arrays may be uninitialized, which comes up due to a known bug in gfortran SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-Wno-maybe-uninitialized" # GNU + Fortran "-Wno-maybe-uninitialized" # GNU ) # Disable the warning about unused dummy arguments. These primarily occur due to interface rules for type-bound procedures used in extendable types. SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-Wno-unused-dummy-argument" # GNU + Fortran "-Wno-unused-dummy-argument" # GNU ) - # Tells the compiler to issue compile-time messages for nonstandard language elements (Fortran 2018). SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fstd=f2018" # GNU + Fortran "-fstd=f2018" # GNU ) - # Traceback SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fbacktrace" # GNU (gfortran) + Fortran "-fbacktrace" # GNU (gfortran) ) - # Sanitize SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fsanitize=address, undefined" # Gnu + Fortran "-fsanitize=address, undefined" # Gnu + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-fsanitize=address, undefined" # Gnu ) - # Check everything SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fcheck=all" # GNU + Fortran "-fcheck=all" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-fcheck=all" # GNU ) SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fstack-check" # GNU + Fortran "-fstack-check" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-fstack-check" # GNU ) - # Initializes matrices/arrays with NaN values SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-finit-real=snan" # GNU + Fortran "-finit-real=snan" # GNU ) - # Generates non position-independent code SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fno-PIE" # GNU + Fortran "-fno-PIE" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-fno-PIE" # GNU ) - # Enables floating-point invalid, divide-by-zero, and overflow exceptions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-ffpe-trap=zero,overflow,underflow" # GNU + Fortran "-ffpe-trap=zero,overflow,underflow" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-ffpe-trap=zero,overflow,underflow" # GNU ) - # List of floating-point exceptions, whose flag status is printed to ERROR_UNIT when invoking STOP and ERROR STOP SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-ffpe-summary=all" # GNU + Fortran "-ffpe-summary=all" # GNU ) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fstack-check" # GNU + Fortran "-fstack-check" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-fstack-check" # GNU ) ENDIF () - ENDIF () ##################### @@ -463,15 +476,20 @@ ENDIF () ##################### IF (CMAKE_BUILD_TYPE STREQUAL "TESTING" ) - # Optimizations IF (WINOPT) SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_TESTING "${CMAKE_Fortran_FLAGS_DEBUG}" - REQUIRED "/O3" # Intel Windows + Fortran REQUIRED "/O3" # Intel Windows + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_TESTING "${CMAKE_C_FLAGS_DEBUG}" + C REQUIRED "/O3" # Intel Windows ) ELSE () SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_TESTING "${CMAKE_Fortran_FLAGS_DEBUG}" - REQUIRED "-O3" # All compilers not on Windows + Fortran REQUIRED "-O3" # All compilers not on Windows + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_TESTING "${CMAKE_C_FLAGS_DEBUG}" + C REQUIRED "-O3" # All compilers not on Windows ) ENDIF () ENDIF () @@ -481,47 +499,38 @@ ENDIF () ##################### # NOTE: agressive optimizations (-O3) are already turned on by default - IF (CMAKE_BUILD_TYPE STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE STREQUAL "PROFILE") - IF (COMPILER_OPTIONS STREQUAL "Intel") IF (WINOPT) # Unroll loops SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "/unroll" # Intel Windows + Fortran "/Qunroll" # Intel Windows ) - # Inline functions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "/Qinline" # Intel Windows + Fortran "/inline" # Intel Windows ) - # Calls the Matrix Multiply library SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "/Qopt-matmul" # Intel Windows ) - # Aligns a variable to a specified boundary and offset SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "/align:all" # Intel Windows ) - # No floating-point exceptions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "/fp:no-except" # Intel Windows + Fortran "/fp:except-" # Intel Windows ) - # Generate fused multiply-add instructions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "/Qfma" # Intel Windows ) - # Tells the compiler to link to certain libraries in the Intel oneAPI Math Kernel Library (oneMKL). SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "/Qmkl:cluster" # Intel Windows "/Qmkl" # Intel Windows ) - # Enables additional interprocedural optimizations for a single file compilation SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "/Qip" # Intel Windows @@ -531,7 +540,6 @@ IF (CMAKE_BUILD_TYPE STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE STREQUAL "PROFILE") SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "-unroll" # Intel ) - # Inline functions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "-inline" # Intel @@ -541,12 +549,10 @@ IF (CMAKE_BUILD_TYPE STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE STREQUAL "PROFILE") SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "-qopt-matmul" # Intel ) - # Aligns a variable to a specified boundary and offset SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "-align all" # Intel ) - # No floating-point exceptions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "-fp-model no-except" # Intel @@ -554,15 +560,13 @@ IF (CMAKE_BUILD_TYPE STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE STREQUAL "PROFILE") # Generate fused multiply-add instructions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-fma" # Intel + Fortran "-fma" # Intel ) - # Tells the compiler to link to certain libraries in the Intel oneAPI Math Kernel Library (oneMKL). SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "-qmkl=cluster" # Intel "-qmkl" # Intel ) - # Enables additional interprocedural optimizations for a single file compilation SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" Fortran "-ip" # Intel @@ -572,45 +576,37 @@ IF (CMAKE_BUILD_TYPE STREQUAL "RELEASE" OR CMAKE_BUILD_TYPE STREQUAL "PROFILE") ELSEIF(COMPILER_OPTIONS STREQUAL "GNU") # Unroll loops SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-funroll-loops" # GNU - ) - + Fortran "-funroll-loops" # GNU + ) # Inline functions SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-finline-functions" # GNU - ) + Fortran "-finline-functions" # GNU + ) ENDIF () - ENDIF () ##################### ### MATH FLAGS ### ##################### IF (COMPILER_OPTIONS STREQUAL "Intel") - IF (WINOPT) # Some subroutines require more strict floating point operation optimizations for repeatability SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "/fp:precise" # Intel Windows ) - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "/Qprec-div" # Intel Windows ) - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "/Qprec-sqrt" # Intel Windows ) - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "/assume:protect-parens" # Intel Windows ) - # Improves floating-point precision and consistency SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "/Qprec" # Intel Windows ) - # Most subroutines can use aggressive optimization of floating point operations without problems. SET_COMPILE_FLAG(FASTMATH_FLAGS "${FASTMATH_FLAGS}" Fortran "/fp:fast" # Intel Windows @@ -620,46 +616,37 @@ IF (COMPILER_OPTIONS STREQUAL "Intel") SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "-fp-module=precise" # Intel ) - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "-prec-div" # Intel ) - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "-prec-sqrt" # Intel ) - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "-assume protect-parens" # Intel ) - # Improves floating-point precision and consistency SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "-mp1" # Intel Windows ) - # Most subroutines can use aggressive optimization of floating point operations without problems. SET_COMPILE_FLAG(FASTMATH_FLAGS "${FASTMATH_FLAGS}" Fortran "-fp-model=fast" # Intel Windows ) - ENDIF () - ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") - # Some subroutines require more strict floating point operation optimizations for repeatability SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "-fno-unsafe-math-optimizations" # GNU - ) + ) # Disable transformations and optimizations that assume default floating-point rounding behavior. SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" Fortran "-frounding-math" - ) - + ) # Most subroutines can use aggressive optimization of floating point operations without problems. SET_COMPILE_FLAG(FASTMATH_FLAGS "${FASTMATH_FLAGS}" Fortran "-ffast-math" # GNU - ) + ) ENDIF () # Debug mode always uses strict math @@ -671,7 +658,6 @@ SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" ### PROFILE FLAGS ### ##################### IF (CMAKE_BUILD_TYPE STREQUAL "PROFILE") - IF (COMPILER_OPTIONS STREQUAL "Intel") # Enables the optimization reports to be generated IF (WINOPT) diff --git a/cmake/Modules/SetUpNetCDF.cmake b/cmake/Modules/SetUpNetCDF.cmake deleted file mode 100644 index fad06d4f5..000000000 --- a/cmake/Modules/SetUpNetCDF.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2022 - David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, & Dana Singh -# This file is part of Swiftest. -# Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -# Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -# You should have received a copy of the GNU General Public License along with Swiftest. -# If not, see: https://www.gnu.org/licenses. - -# Find NetCDF if not already found -IF(NOT NETCDF_FOUND) - ENABLE_LANGUAGE(C) # Some libraries need a C compiler to find - FIND_PACKAGE(NETCDF REQUIRED) -ENDIF(NOT NETCDF_FOUND) - diff --git a/distclean.cmake b/distclean.cmake index c0ce74642..19d766f08 100644 --- a/distclean.cmake +++ b/distclean.cmake @@ -12,6 +12,7 @@ # We want to start from the top of the source dir, so if we are in build # we want to start one directory up +CMAKE_POLICY(SET CMP0009 NEW) GET_FILENAME_COMPONENT(BASEDIR ${CMAKE_SOURCE_DIR} NAME) IF(${BASEDIR} STREQUAL "build") SET(TOPDIR "${CMAKE_SOURCE_DIR}/..") diff --git a/examples/Chambers2013/.gitignore b/examples/Chambers2013/.gitignore index 64af50e94..0ea510e82 100644 --- a/examples/Chambers2013/.gitignore +++ b/examples/Chambers2013/.gitignore @@ -1,5 +1,6 @@ * !.gitignore -!init_cond.py +!initial_conditions.py !scattermovie.py +!run_simulation.py !README.txt diff --git a/examples/Chambers2013/init_cond.py b/examples/Chambers2013/initial_conditions.py similarity index 77% rename from examples/Chambers2013/init_cond.py rename to examples/Chambers2013/initial_conditions.py index d5c9f9f19..596d6829c 100755 --- a/examples/Chambers2013/init_cond.py +++ b/examples/Chambers2013/initial_conditions.py @@ -32,7 +32,8 @@ import matplotlib.pyplot as plt # Initialize simulation object -sim = swiftest.Simulation(compute_conservation_values=True, rotation=True, init_cond_format="EL",collision_model="fraggle",encounter_save="none") +sim = swiftest.Simulation(compute_conservation_values=True, rotation=True, init_cond_format="EL",collision_model="fraggle",encounter_save="none") +sim.clean() # Add bodies described in Chambers (2013) Sec. 2.1, with the uniform spatial distribution and two bodies sizes (big and small) Nb = 14 @@ -40,6 +41,7 @@ Mb = 2.8e-7 * 14 / Nb Ms = 2.8e-8 * 140 / Ns dens = 3000.0 * sim.KG2MU / sim.M2DU**3 +rot = 1e-6 / sim.TU2S # Use a small but non-zero value for the initial rotation state to prevent divide-by-zero errors in analysis mtiny = 1e-2 * Ms minimum_fragment_mass = 1e-5 * Ms @@ -55,37 +57,33 @@ def a_profile(n_bodies): The region with a < 0.7 AU deviates from this law, declining linearly with decreasing distance until R = 0 at 0.3 AU. The outer edge of the disk is 2 AU in all cases. """ - def sample(r_inner, r_break, r_outer, slope1, slope2): - """ - Define the functions to pull random semi-major axes from a distribution using a rejection sampling method - This defines a 2-slope model with a break at r_break - Based on (https://stackoverflow.com/questions/66874819/random-numbers-with-user-defined-continuous-probability-distribution) - """ - while True: - x = rng.uniform(r_inner, r_outer, size=1) + def sample(r_inner, r_break, r_outer, slope1, slope2, size): + """ + Define the functions to pull random semi-major axes from a distribution using a rejection sampling method + This defines a 2-slope model with a break at r_break + Based on (https://stackoverflow.com/questions/66874819/random-numbers-with-user-defined-continuous-probability-distribution) + """ + y=np.ones([size]) + pdf=np.zeros([size]) + x=np.empty_like(y) + while np.any(y>pdf): + x = np.where(y>pdf,rng.uniform(r_inner, r_outer, size=size),x) - # The proportionality factor A ensures that the PDF approaches the same value on either side of the break point - # Assumes the break point is the max of the PDF - if x < r_break: - slope = slope1 + 1 - A = 1.0 - else: - slope = slope2 + 1 - A = r_break**(slope1-slope2) - y = rng.uniform(0, A*r_break**slope, size=1) - pdf = A*x**(slope) - if (y < pdf): - return x - + # The proportionality factor A ensures that the PDF approaches the same value on either side of the break point + # Assumes the break point is the max of the PDF + A=np.where(x < r_break,1.0,r_break**(slope1-slope2)) + slope=np.where(x < r_break,slope1+1,slope2+1) + y = np.where(y>pdf,rng.uniform(0, A*r_break**slope, size=size),y) + pdf = np.where(y>pdf,A*x**(slope),pdf) + return x + a_inner = 0.3 a_break = 0.7 a_outer = 2.0 slope1 = 1.0 slope2 = -1.5 - - a_vals = np.zeros(n_bodies) - for k in range(n_bodies): - a_vals[k] = sample(a_inner, a_break, a_outer, slope1, slope2) + + a_vals = sample(a_inner, a_break, a_outer, slope1, slope2, n_bodies) return a_vals # Define the initial orbital elements of the big and small bodies @@ -107,8 +105,8 @@ def sample(r_inner, r_break, r_outer, slope1, slope2): capmvals = rng.uniform(0.0, 360.0, Ns) Ipvalb = np.full((Nb,3), 0.4) Ipvals = np.full((Ns,3), 0.4) -rotvalb = np.zeros_like(Ipvalb) -rotvals = np.zeros_like(Ipvals) +rotvalb = np.full_like(Ipvalb,rot) +rotvals = np.full_like(Ipvals,rot) noise_digits = 4 # Approximately the number of digits of precision to vary the mass values to avoid duplicate masses epsilon = np.finfo(float).eps @@ -132,8 +130,7 @@ def sample(r_inner, r_break, r_outer, slope1, slope2): sim.set_parameter(mtiny=mtiny, minimum_fragment_mass=minimum_fragment_mass, nfrag_reduction=nfrag_reduction) sim.set_parameter(tstop=3e8, dt=6.0875/365.25, istep_out=60000, dump_cadence=10) -sim.clean() -sim.write_param() +sim.save() # Plot the initial conditions fig = plt.figure(figsize=(8.5, 11)) diff --git a/examples/Chambers2013/run_simulation.py b/examples/Chambers2013/run_simulation.py new file mode 100755 index 000000000..5ae2fb2a3 --- /dev/null +++ b/examples/Chambers2013/run_simulation.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 + +""" + Copyright 2023 - David Minton + This file is part of Swiftest. + Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with Swiftest. + If not, see: https://www.gnu.org/licenses. +""" + +""" +This will run the simulation from a set of initial conditions. The simulation parameters in this file are set to generate +a very short simulation for testing purposes. Edit the values passed to the run() function as necessary. + +Input +------ +simdata/param.in : ASCII Swiftest parameter input file. + +Output +------ +Outputs are stored in the /simdata subdirectory. + +""" +import swiftest +sim = swiftest.Simulation(read_param=True) + +# Original run parameters +# sim.run(tstop=3e8, dt=6.0875/365.25, istep_out=60000, dump_cadence=10,integreator="symba") +# +sim.run(tstop=10000.0, dt=6.0875/365.25, istep_out=10000, dump_cadence=0, integrator="symba") diff --git a/examples/Chambers2013/scattermovie.py b/examples/Chambers2013/scattermovie.py index 98b0645ef..e1eda643a 100755 --- a/examples/Chambers2013/scattermovie.py +++ b/examples/Chambers2013/scattermovie.py @@ -15,6 +15,15 @@ Creates a movie from a set of Swiftest output files. All simulation outputs are stored in the /simdata subdirectory. +**NOTE: You must have ffmpeg installed on your system before running this script. For instance, on MacOS: + +```brew install ffmpeg``` + +on Ubuntu: + +```sudo apt-get install ffmpeg``` + + Input ------ param.in : ASCII Swiftest parameter input file. @@ -33,6 +42,8 @@ from matplotlib import animation import matplotlib.colors as mcolors from collections import namedtuple + + plt.switch_backend('agg') titletext = "Chambers (2013)" @@ -108,8 +119,8 @@ def init_plot(self): self.ax.set_ylabel(ylabel[plot_style], fontsize='16', labelpad=1) leg = plt.legend(loc="upper left", scatterpoints=1, fontsize=10) - for i,l in enumerate(leg.legendHandles): - leg.legendHandles[i]._sizes = [20] + for i,l in enumerate(leg.legend_handles): + leg.legend_handles[i]._sizes = [20] if plot_style == "arotscatter": self.ax.set_yscale('log') diff --git a/examples/Fragmentation/Fragmentation_Movie.py b/examples/Fragmentation/Fragmentation_Movie.py index 4905e05f6..b7154f4bb 100755 --- a/examples/Fragmentation/Fragmentation_Movie.py +++ b/examples/Fragmentation/Fragmentation_Movie.py @@ -14,22 +14,24 @@ Generates and runs a set of Swiftest input files from initial conditions with the SyMBA integrator. All simulation outputs are stored in the subdirectory named after their collisional regime. +**NOTE: You must have ffmpeg installed on your system before running this script. For instance, on MacOS: + +```brew install ffmpeg``` + +on Ubuntu: + +```sudo apt-get install ffmpeg``` + + Inputs _______ -None. +User selects which collisional movie to generate Output ------ -collisions.log : An ASCII file containing the information of any collisional events that occured. -collisions.nc : A NetCDF file containing the collision output. -data.nc : A NetCDF file containing the simulation output. -encounters.nc : A NetCDF file containing the encounter output. -init_cond.nc : A NetCDF file containing the initial conditions for the simulation. -param.00...0.in : A series of parameter input files containing the parameters for the simulation at every output stage. -param.in : An ASCII file containing the inital parameters for the simulation. -param.restart.in : An ASCII file containing the parameters for the simulation at the last output. -swiftest.log : An ASCII file containing the information on the status of the simulation as it runs. -collision.mp4 : A movie file named after the collisional regime depicting the collision. + +Files are stored in directories for each collision type name requested +[COLLISION_TYPE].mp4 : A movie file named after the collisional regime depicting the collision. """ @@ -48,6 +50,22 @@ movie_titles = dict(zip(available_movie_styles, movie_title_list)) num_movie_frames = 1000 + +# ---------------------------------------------------------------------------------------------------------------------- +# To increase the number of bodies generated in each collision type, decrease the value of the corresponding nfrag_reduction number +# ---------------------------------------------------------------------------------------------------------------------- +nfrag_reduction = {"disruption_headon" : 10.0, + "disruption_off_axis" : 10.0, + "supercatastrophic_headon" : 10.0, + "supercatastrophic_off_axis" : 10.0, + "hitandrun_disrupt" : 10.0, + "hitandrun_pure" : 1.0, + "merge" : 1.0, + "merge_spinner" : 1.0, + } + + + # These initial conditions were generated by trial and error names = ["Target","Projectile"] pos_vectors = {"disruption_headon" : [np.array([1.0, -5.0e-05, 0.0]), @@ -124,16 +142,6 @@ "merge_spinner" : 5.0e-3, } -nfrag_reduction = {"disruption_headon" : 1.0, - "disruption_off_axis" : 1.0, - "supercatastrophic_headon" : 1.0, - "supercatastrophic_off_axis" : 10.0, - "hitandrun_disrupt" : 1.0, - "hitandrun_pure" : 1.0, - "merge" : 1.0, - "merge_spinner" : 1.0, - } - density = 3000 * swiftest.AU2M**3 / swiftest.MSun GU = swiftest.GMSun * swiftest.YR2S**2 / swiftest.AU2M**3 body_radius = body_Gmass.copy() @@ -358,7 +366,11 @@ def vec_props(self, c): # Set fragmentation parameters minimum_fragment_gmass = 0.01 * body_Gmass[style][1] gmtiny = 0.50 * body_Gmass[style][1] - sim.set_parameter(collision_model="fraggle", encounter_save="both", gmtiny=gmtiny, minimum_fragment_gmass=minimum_fragment_gmass, nfrag_reduction=nfrag_reduction[style]) + sim.set_parameter(collision_model="fraggle", + encounter_save="both", + gmtiny=gmtiny, + minimum_fragment_gmass=minimum_fragment_gmass, + nfrag_reduction=nfrag_reduction[style]) sim.run(dt=5e-4, tstop=tstop[style], istep_out=1, dump_cadence=0) print("Generating animation") diff --git a/examples/Multibody_Fragmentation/Multibody_Movie.py b/examples/Multibody_Fragmentation/Multibody_Movie.py index 7c3d28359..dde262355 100755 --- a/examples/Multibody_Fragmentation/Multibody_Movie.py +++ b/examples/Multibody_Fragmentation/Multibody_Movie.py @@ -14,6 +14,15 @@ Generates, runs, and processes a set of initial conditions for a multi-body super-catastrophic distruption collisional event. All Swiftest output files are stored in the /supercatastrophic_multi subdirectory. +**NOTE: You must have ffmpeg installed on your system before running this script. For instance, on MacOS: + +```brew install ffmpeg``` + +on Ubuntu: + +```sudo apt-get install ffmpeg``` + + Inputs _______ None. @@ -47,6 +56,16 @@ movie_titles = dict(zip(available_movie_styles, movie_title_list)) num_movie_frames = 1000 + +# ---------------------------------------------------------------------------------------------------------------------- +# To increase the number of bodies generated in each collision type, decrease the value of the corresponding nfrag_reduction number +# ---------------------------------------------------------------------------------------------------------------------- +nfrag_reduction = { + "supercatastrophic_multi" : 5.0, + } + + + # These initial conditions were generated by trial and error names = ["Body1","Body2","Body3","Body4"] @@ -287,7 +306,12 @@ def vec_props(self, c): # Set fragmentation parameters minimum_fragment_gmass = 0.05 * body_Gmass[style][1] gmtiny = 0.10 * body_Gmass[style][1] - sim.set_parameter(collision_model="fraggle", encounter_save="both", gmtiny=gmtiny, minimum_fragment_gmass=minimum_fragment_gmass, verbose=False) + sim.set_parameter(collision_model="fraggle", + encounter_save="both", + gmtiny=gmtiny, + minimum_fragment_gmass=minimum_fragment_gmass, + nfrag_reduction=nfrag_reduction[style], + verbose=False) sim.run(dt=5e-4, tstop=tstop[style], istep_out=1, dump_cadence=0) print("Generating animation") diff --git a/examples/helio_gr_test/helio_gr_test.py b/examples/helio_gr_test/helio_gr_test.py old mode 100644 new mode 100755 diff --git a/pyproject.toml b/pyproject.toml index 3e59ce1c6..2789589fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "swiftest" -version = "2023.9.3" +version = "2023.10.1" authors=[ {name = 'David A. Minton', email='daminton@purdue.edu'}, {name = 'Carlisle Wishard'}, @@ -14,7 +14,7 @@ maintainers = [ ] readme = "README.md" requires-python=">=3.8" -license={file = "LICENSE.txt"} +license={file = "LICENSE"} classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Science/Research', @@ -26,16 +26,17 @@ keywords=['astronomy','astrophysics', 'planetary', 'nbody integrator', 'symplect dependencies = [ 'numpy>=1.24.3', 'scipy>=1.10.1', - 'xarray>=2022.11.0', - 'dask>=2022.1', - 'distributed>=2022.1', - 'bottleneck>=1.3.5', - 'h5netcdf>=1.0.2', - 'netcdf4>=1.6.2', - 'matplotlib>=3.7.1', - 'astropy>=5.1', + 'xarray>=2023.1', + 'dask>=2023.5', + 'distributed>=2023.5', + 'bottleneck>=1.3', + 'h5netcdf>=1.1', + 'h5py>=3.9', + 'netcdf4>=1.6', + 'matplotlib>=3.7', + 'astropy>=5.2', 'astroquery>=0.4.6', - 'tqdm>=4.65.0', + 'tqdm>=4.66', 'cython>=3.0.0', ] @@ -54,17 +55,18 @@ build-backend = "scikit_build_core.build" cmake.args = ["-DUSE_SIMD=OFF"] sdist.include = ["src/globals/globals_module.f90.in","swiftest/*.py","swiftest/*.pyx","swiftest/*.h"] build-dir = "build/{wheel_tag}" +cmake.verbose = true [tool.cibuildwheel] test-command = "pytest {package}/tests" test-requires = ['pytest'] -skip = "cp312-* pp* *i686 *-manylinux_i686 *_ppc64le *_s390x *-musllinux* *-win32" +skip = "pp* *i686 *-manylinux_i686 *_ppc64le *_s390x *-musllinux* *-win32" build-verbosity = 1 [tool.cibuildwheel.macos.environment] ROOT_DIR="$(pwd)" MACOSX_DEPLOYMENT_TARGET="$(sw_vers -productVersion)" -PREFIX="${ROOT_DIR}" +PREFIX="/usr/local" HOMEBREW_PREFIX="$(brew --prefix)" ARCH="$(uname -m)" LD_LIBRARY_PATH="/usr/local/lib:${PREFIX}/lib:${HOMEBREW_PREFIX}/lib" @@ -72,7 +74,7 @@ LDFLAGS="-Wl,-rpath,${ROOT_DIR}/lib -Wl,-no_compact_unwind -L${PREFIX}/lib -L${ CPATH="/usr/local/include:${PREFIX}/include:${HOMEBREW_PREFIX}/include:${ROOT_DIR}/include" CPPFLAGS="-isystem ${PREFIX}/include -isystem /usr/local/include" LIBS="-lomp" -FCFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -arch ${ARCH}" +FCFLAGS="-mmacos-version-min=${MACOSX_DEPLOYMENT_TARGET} -arch ${ARCH}" FFFLAGS="${FCFLAGS}" CFLAGS="${FCFLAGS} -Wno-deprecated-non-prototype -arch ${ARCH}" CXXFLAGS="${CFLAGS}" @@ -80,10 +82,10 @@ HDF5_ROOT="${PREFIX}" HDF5_LIBDIR="${HDF5_ROOT}/lib" HDF5_INCLUDE_DIR="${HDF5_ROOT}/include" HDF5_PLUGIN_PATH="${HDF5_LIBDIR}/plugin" -NETCDF_FORTRAN_HOME="${PREFIX}" -NETCDF_INCLUDE="${PREFIX}" NCDIR="${PREFIX}" NFDIR="${PREFIX}" +NETCDF_FORTRAN_HOME="${NFDIR}" +NETCDF_FORTRAN_INCLUDE="${NFDIR}/include" FC="$(command -v gfortran-12)" F77="${FC}" CC="/usr/bin/clang" @@ -92,23 +94,36 @@ CPP="/usr/bin/cpp" AR="/usr/bin/ar" NM="/usr/bin/nm" RANLIB="/usr/bin/ranlib" +netCDF-Fortran_DIR="${PREFIX}/lib/cmake/netCDF" [tool.cibuildwheel.macos] before-all = [ "brew install coreutils", - "LIBS=\"\" buildscripts/build_dependencies.sh -p ${PREFIX} -d ${PREFIX}/build -m ${MACOSX_DEPLOYMENT_TARGET}" + "LIBS=\"\" buildscripts/build_dependencies.sh -p ${PREFIX} -d ${HOME}/Downloads -m ${MACOSX_DEPLOYMENT_TARGET}" ] [tool.cibuildwheel.linux] +skip = "cp312-* pp* -manylinux_i686* *-musllinux*" before-all = [ "yum install doxygen libxml2-devel libcurl-devel -y", "buildscripts/build_dependencies.sh -p /usr/local" ] [tool.cibuildwheel.linux.environment] -NETCDF_FORTRAN_HOME="/usr/local" -NETCDF_INCLUDE="/usr/local/include" -LD_LIBRARY_PATH="/usr/local/lib:/project/lib" -CPATH="/usr/local/include:/project/include" +PREFIX="/usr/local" +NCDIR="${PREFIX}" +NFDIR="${PREFIX}" +NETCDF_FORTRAN_HOME="${NFDIR}" +NETCDF_FORTRAN_INCLUDE="${NFDIR}/include" +HDF5_ROOT="${PREFIX}" +HDF5_LIBDIR="${HDF5_ROOT}/lib" +HDF5_INCLUDE_DIR="${HDF5_ROOT}/include" +HDF5_PLUGIN_PATH="${HDF5_LIBDIR}/plugin" +LD_LIBRARY_PATH="${PREFIX}/lib:/project/lib:${HDF5_LIBDIR}" +CPATH="${PREFIX}/include:/project/include:${HDF5_INCLUDE_DIR}" +netCDF-Fortran_DIR="${PREFIX}/lib/cmake/netCDF" +HDF5_DIR="${HDF5_ROOT}/cmake" +PATH="${HDF5_ROOT}/bin:${PATH}" +CMAKE_INSTALL_LIBDIR="lib" [[tool.scikit-build.generate]] path = "version.txt" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e6c638d33..925d70005 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,20 +12,6 @@ set(GLOBAL_MODULE_IN ${SRC}/globals/globals_module.f90.in) set(GLOBAL_MODULE_OUT ${SRC}/globals/globals_module.f90) CONFIGURE_FILE(${GLOBAL_MODULE_IN} ${GLOBAL_MODULE_OUT}) -IF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) - MESSAGE(FATAL_ERROR "Fortran compiler does not support F90") -ENDIF(NOT CMAKE_Fortran_COMPILER_SUPPORTS_F90) - -INCLUDE(SetParallelizationLibrary) -INCLUDE(SetUpNetCDF) -IF (COMPILER_OPTIONS STREQUAL "Intel" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - INCLUDE(SetMKL) -ENDIF () - -# This INCLUDE statement executes code that sets the compile flags for DEBUG, -# RELEASE, PROFILING, and TESTING. -INCLUDE(SetFortranFlags) - # Add the source files SET(STRICT_MATH_FILES ${SRC}/collision/collision_generate.f90 @@ -136,22 +122,18 @@ ENDIF() SET(SWIFTEST_DRIVER swiftest_driver) ADD_EXECUTABLE(${SWIFTEST_DRIVER} ${DRIVER_src}) -# Be sure the executable gets packaged with the wheel -#SET_PROPERTY(TARGET ${SWIFTEST_DRIVER} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${SKBUILD_SCRIPTS_DIR}) - ##################################################### # Add the needed libraries ##################################################### # Create a library from the source files, except the driver + ADD_LIBRARY(${SWIFTEST_LIBRARY} ${SWIFTEST_src}) IF (NOT BUILD_SHARED_LIBS) SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} PROPERTY POSITION_INDEPENDENT_CODE) ENDIF () -TARGET_INCLUDE_DIRECTORIES(${SWIFTEST_LIBRARY} PUBLIC ${NETCDF_INCLUDE_DIR}) -TARGET_INCLUDE_DIRECTORIES(${SWIFTEST_DRIVER} PUBLIC ${NETCDF_INCLUDE_DIR}) -TARGET_LINK_LIBRARIES(${SWIFTEST_LIBRARY} PUBLIC ${NETCDF_LIBRARIES}) -TARGET_LINK_LIBRARIES(${SWIFTEST_DRIVER} PUBLIC ${SWIFTEST_LIBRARY} ${NETCDF_LIBRARIES}) +TARGET_LINK_LIBRARIES(${SWIFTEST_LIBRARY} PUBLIC netCDF::netcdff HDF5::HDF5) +TARGET_LINK_LIBRARIES(${SWIFTEST_DRIVER} PUBLIC ${SWIFTEST_LIBRARY} netCDF::netcdff HDF5::HDF5) IF(USE_OPENMP OR USE_SIMD) SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY COMPILE_FLAGS "${OpenMP_Fortran_FLAGS} ") diff --git a/src/fraggle/fraggle_generate.f90 b/src/fraggle/fraggle_generate.f90 index aeeae27d9..746e768d2 100644 --- a/src/fraggle/fraggle_generate.f90 +++ b/src/fraggle/fraggle_generate.f90 @@ -635,7 +635,7 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu real(DP), dimension(NDIM) :: vimp_unit, rimp, vrot, vdisp, L_residual, L_residual_unit, L_residual_best, dL, drot, rot_new real(DP), dimension(NDIM) :: dL_metric real(DP) :: vimp, vmag, vesc, dE, E_residual, E_residual_best, E_residual_last, ke_avail, ke_remove, dE_best, fscale - real(DP) :: dE_metric, mfrag, rn, dL1_mag, dE_conv, vumag + real(DP) :: dE_metric, mfrag, rn, dL1_mag, dE_conv, vumag, L_mag_factor integer(I4B), dimension(:), allocatable :: vsign real(DP), dimension(:), allocatable :: vscale real(DP), dimension(:), allocatable :: dLi_mag @@ -644,8 +644,8 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu real(DP), parameter :: hitandrun_vscale = 0.25_DP real(DP) :: vmin_guess real(DP) :: vmax_guess - integer(I4B), parameter :: MAXLOOP = 25 - integer(I4B), parameter :: MAXTRY = 10 + integer(I4B), parameter :: MAXLOOP = 50 + integer(I4B), parameter :: MAXTRY = 50 integer(I4B), parameter :: MAXANGMTM = 1000 class(collision_fraggle), allocatable :: collider_local character(len=STRMAX) :: message @@ -754,9 +754,10 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu ! Try to put residual angular momentum into the spin, but if this would go past the spin barrier, then put it into ! velocity shear instead call collider_local%get_energy_and_momentum(nbody_system, param, phase="after") - L_residual(:) = (collider_local%L_total(:,2) - collider_local%L_total(:,1)) + L_mag_factor = .mag.(collider_local%L_total(:,1) + collider_local%L_total(:,2)) + L_residual(:) = (collider_local%L_total(:,2) / L_mag_factor - collider_local%L_total(:,1) / L_mag_factor) L_residual_unit(:) = .unit. L_residual(:) - if (nsteps == 1) L_residual_best(:) = L_residual(:) + if (nsteps == 1) L_residual_best(:) = L_residual(:) * L_mag_factor ! Use equipartition of spin kinetic energy to distribution spin angular momentum #ifdef DOCONLOC @@ -768,7 +769,7 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu (fragments%radius(i) / fragments%radius(istart))**2 * & (fragments%Ip(3,i) / fragments%Ip(3,istart)))**(1.5_DP) end do - dL1_mag = .mag.L_residual(:) / sum(dLi_mag(istart:fragments%nbody)) + dL1_mag = .mag.L_residual(:) * L_mag_factor / sum(dLi_mag(istart:fragments%nbody)) do i = istart,fragments%nbody dL(:) = -dL1_mag * dLi_mag(i) * L_residual_unit(:) @@ -789,20 +790,22 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu fragments%rot(:,i) = fragments%rotmag(i) * .unit. fragments%rot(:,i) end if end if - L_residual(:) = L_residual(:) + drot(:) * fragments%Ip(3,i) * fragments%mass(i) * fragments%radius(i)**2 + L_residual(:) = L_residual(:) + drot(:) * fragments%Ip(3,i) * fragments%mass(i) * fragments%radius(i)**2 & + / L_mag_factor end do ! Put any remaining residual into velocity shear angmtm: do j = 1, MAXANGMTM if (j == MAXANGMTM) exit inner call collider_local%get_energy_and_momentum(nbody_system, param, phase="after") - L_residual(:) = (collider_local%L_total(:,2) - collider_local%L_total(:,1)) - dL_metric(:) = abs(L_residual(:)) / .mag.(collider_local%L_total(:,1)) / MOMENTUM_SUCCESS_METRIC + L_mag_factor = .mag.(collider_local%L_total(:,1) + collider_local%L_total(:,2)) + L_residual(:) = (collider_local%L_total(:,2) / L_mag_factor - collider_local%L_total(:,1)/L_mag_factor) + dL_metric(:) = abs(L_residual(:)) / MOMENTUM_SUCCESS_METRIC if (all(dL_metric(:) <= 1.0_DP)) exit angmtm do i = istart, fragments%nbody - dL(:) = -L_residual(:) * fragments%mass(i) / sum(fragments%mass(istart:fragments%nbody)) + dL(:) = -L_residual(:) * L_mag_factor * fragments%mass(i) / sum(fragments%mass(istart:fragments%nbody)) call collision_util_velocity_torque(dL, fragments%mass(i), fragments%rc(:,i), fragments%vc(:,i)) end do call collision_util_shift_vector_to_origin(fragments%mass, fragments%vc) @@ -817,8 +820,9 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu E_residual_last = E_residual E_residual = dE + impactors%Qloss - L_residual(:) = (collider_local%L_total(:,2) - collider_local%L_total(:,1)) - dL_metric(:) = abs(L_residual(:)) / .mag.collider_local%L_total(:,1) / MOMENTUM_SUCCESS_METRIC + L_mag_factor = .mag.(collider_local%L_total(:,1) + collider_local%L_total(:,2)) + L_residual(:) = (collider_local%L_total(:,2) / L_mag_factor - collider_local%L_total(:,1) / L_mag_factor) + dL_metric(:) = abs(L_residual(:)) / MOMENTUM_SUCCESS_METRIC dE_conv = abs(E_residual - E_residual_last) / abs(E_residual_last) ! Check if we've converged on our constraints @@ -826,7 +830,7 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu if ((abs(E_residual) < abs(E_residual_best)) .or. ((dE < 0.0_DP) .and. (dE_best >= 0.0_DP))) then ! This is our best case so far. Save it for posterity E_residual_best = E_residual - L_residual_best(:) = L_residual(:) + L_residual_best(:) = L_residual(:) * L_mag_factor dE_best = dE nsteps_best = nsteps @@ -877,8 +881,9 @@ module subroutine fraggle_generate_vel_vec(collider, nbody_system, param, lfailu // trim(adjustl(message)) // " steps.") call collider%get_energy_and_momentum(nbody_system, param, phase="after") - L_residual(:) = (collider%L_total(:,2) - collider%L_total(:,1)) - call collision_util_velocity_torque(-L_residual(:), collider%fragments%mtot, impactors%rbcom, impactors%vbcom) + L_mag_factor = .mag.(collider%L_total(:,1) + collider%L_total(:,2)) + L_residual(:) = (collider%L_total(:,2) / L_mag_factor - collider%L_total(:,1)) / L_mag_factor + call collision_util_velocity_torque(-L_residual(:) * L_mag_factor, collider%fragments%mtot, impactors%rbcom, impactors%vbcom) #ifdef DOCONLOC do concurrent(i = 1:nfrag) shared(collider, impactors) diff --git a/src/globals/globals_module.f90 b/src/globals/globals_module.f90 index d826bbb1c..def76b400 100644 --- a/src/globals/globals_module.f90 +++ b/src/globals/globals_module.f90 @@ -48,7 +48,7 @@ module globals integer(I4B), parameter :: UPPERCASE_OFFSET = iachar('A') - iachar('a') !! ASCII character set parameter for lower to upper !! conversion - offset between upper and lower - character(*), parameter :: VERSION = "2023.9.3" !! Swiftest version + character(*), parameter :: VERSION = "2023.10.1" !! Swiftest version !> Symbolic name for integrator types character(*), parameter :: UNKNOWN_INTEGRATOR = "UKNOWN INTEGRATOR" diff --git a/src/swiftest/swiftest_io.f90 b/src/swiftest/swiftest_io.f90 index 9a8095116..40a9d286b 100644 --- a/src/swiftest/swiftest_io.f90 +++ b/src/swiftest/swiftest_io.f90 @@ -22,14 +22,16 @@ module subroutine swiftest_io_compact_output(self, param, timer) interface fmt !! author: David Minton !! - !! Formats a pair of variables and corresponding values for the compact display output. Generic interface for different variable types to format. + !! Formats a pair of variables and corresponding values for the compact display output. Generic interface for different + !! variable types to format. procedure :: fmt_I4B, fmt_I8B, fmt_DP end interface ! Arguments class(swiftest_nbody_system), intent(in) :: self !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Input colleciton of user-defined parameters - class(*), intent(in) :: timer !! Object used for computing elapsed wall time (must be unlimited polymorphic because the walltimer module requires base) + class(*), intent(in) :: timer !! Object used for computing elapsed wall time (must be unlimited + !! polymorphic because the walltimer module requires base) ! Internals character(len=:), allocatable :: formatted_output @@ -41,17 +43,20 @@ module subroutine swiftest_io_compact_output(self, param, timer) formatted_output = formatted_output // fmt("NPLM",pl%nplm) end select if (param%lenergy) then - formatted_output = formatted_output // fmt("LTOTERR",self%L_total_error) // fmt("ETOTERR",self%te_error) // fmt("MTOTERR",self%Mtot_error) & - // fmt("KEOERR",self%ke_orbit_error) // fmt("PEERR",self%pe_error) // fmt("EORBERR",self%E_orbit_error) & - // fmt("EUNTRERR",self%E_untracked_error) // fmt("LESCERR",self%L_escape_error) // fmt("MESCERR",self%Mescape_error) + formatted_output = formatted_output // fmt("LTOTERR",self%L_total_error) // fmt("ETOTERR",self%te_error) & + // fmt("MTOTERR",self%Mtot_error) // fmt("KEOERR",self%ke_orbit_error) // fmt("PEERR",self%pe_error) & + // fmt("EORBERR",self%E_orbit_error) // fmt("EUNTRERR",self%E_untracked_error) & + // fmt("LESCERR",self%L_escape_error) // fmt("MESCERR",self%Mescape_error) if (param%lclose) formatted_output = formatted_output // fmt("ECOLLERR",self%Ecoll_error) - if (param%lrotation) formatted_output = formatted_output // fmt("KESPINERR",self%ke_spin_error) // fmt("LSPINERR",self%L_spin_error) + if (param%lrotation) formatted_output = formatted_output // fmt("KESPINERR",self%ke_spin_error) & + // fmt("LSPINERR",self%L_spin_error) end if if (.not. timer%main_is_started) then ! This is the start of a new run formatted_output = formatted_output // fmt("WT",0.0_DP) // fmt("IWT",0.0_DP) // fmt("WTPS",0.0_DP) else - formatted_output = formatted_output // fmt("WT",timer%wall_main) // fmt("IWT",timer%wall_step) // fmt("WTPS",timer%wall_per_substep) + formatted_output = formatted_output // fmt("WT",timer%wall_main) // fmt("IWT",timer%wall_step) & + // fmt("WTPS",timer%wall_per_substep) end if write(*,*) formatted_output end select @@ -123,12 +128,13 @@ module subroutine swiftest_io_conservation_report(self, param, lterminal) real(DP), dimension(NDIM) :: L_total_now, L_orbit_now, L_spin_now real(DP) :: ke_orbit_now, ke_spin_now, pe_now, E_orbit_now, be_now, be_cb_now, be_cb_orig, te_now real(DP) :: GMtot_now - character(len=*), parameter :: EGYTERMFMT = '(" DL/L0 = ", ES12.5, "; DE_orbit/|E0| = ", ES12.5, "; DE_total/|E0| = ", ES12.5, "; DM/M0 = ", ES12.5)' + character(len=*), parameter :: EGYTERMFMT = '(" DL/L0 = ", ES12.5, "; DE_orbit/|E0| = ", ES12.5,' & + //'"; DE_total/|E0| = ", ES12.5, "; DM/M0 = ", ES12.5)' associate(nbody_system => self, pl => self%pl, cb => self%cb, npl => self%pl%nbody, display_unit => param%display_unit) select type(self) - class is (helio_nbody_system) ! Don't convert vh to vb for Helio-based integrators, because they are already have that calculated + class is (helio_nbody_system) ! Don't convert vh to vb for Helio-based integrators, because it's already calculated class is (whm_nbody_system) call pl%vh2vb(cb) end select @@ -168,12 +174,14 @@ module subroutine swiftest_io_conservation_report(self, param, lterminal) nbody_system%pe_error = (pe_now - nbody_system%pe_orig) / abs(nbody_system%E_orbit_orig) be_cb_orig = -(3 * cb%GM0**2 / param%GU) / (5 * cb%R0) - nbody_system%be_error = (be_now - nbody_system%be_orig) / abs(nbody_system%te_orig) + (be_cb_now - be_cb_orig) / abs(nbody_system%te_orig) + nbody_system%be_error = (be_now - nbody_system%be_orig) / abs(nbody_system%te_orig) + (be_cb_now - be_cb_orig) & + / abs(nbody_system%te_orig) nbody_system%E_orbit_error = (E_orbit_now - nbody_system%E_orbit_orig) / abs(nbody_system%E_orbit_orig) nbody_system%Ecoll_error = nbody_system%E_collisions / abs(nbody_system%te_orig) nbody_system%E_untracked_error = nbody_system%E_untracked / abs(nbody_system%te_orig) - nbody_system%te_error = (nbody_system%te - nbody_system%te_orig - nbody_system%E_collisions - nbody_system%E_untracked) / abs(nbody_system%te_orig) + (be_cb_now - be_cb_orig) / abs(nbody_system%te_orig) + nbody_system%te_error = (nbody_system%te - nbody_system%te_orig - nbody_system%E_collisions - nbody_system%E_untracked)& + / abs(nbody_system%te_orig) + (be_cb_now - be_cb_orig) / abs(nbody_system%te_orig) nbody_system%L_orbit_error = norm2(L_orbit_now(:) - nbody_system%L_orbit_orig(:)) / norm2(nbody_system%L_total_orig(:)) nbody_system%L_spin_error = norm2(L_spin_now(:) - nbody_system%L_spin_orig(:)) / norm2(nbody_system%L_total_orig(:)) @@ -185,7 +193,8 @@ module subroutine swiftest_io_conservation_report(self, param, lterminal) if (this_image() == 1 .or. param%log_output) then #endif if (lterminal) then - write(display_unit, EGYTERMFMT) nbody_system%L_total_error, nbody_system%E_orbit_error, nbody_system%te_error,nbody_system%Mtot_error + write(display_unit, EGYTERMFMT) nbody_system%L_total_error, nbody_system%E_orbit_error, nbody_system%te_error, & + nbody_system%Mtot_error if (param%log_output) flush(display_unit) end if @@ -251,9 +260,11 @@ module subroutine swiftest_io_display_run_information(self, param, integration_t #endif if (phase_val == 0) then if (param%lrestart) then - write(param%display_unit, *) " *************** Swiftest restart " // trim(adjustl(param%integrator)) // " *************** " + write(param%display_unit, *) " *************** Swiftest " // VERSION // " restart " // & + trim(adjustl(param%integrator)) // " *************** " else - write(param%display_unit, *) " *************** Swiftest start " // trim(adjustl(param%integrator)) // " *************** " + write(param%display_unit, *) " *************** Swiftest " // VERSION // " start " // & + trim(adjustl(param%integrator)) // " *************** " end if if (param%display_style == "PROGRESS") then call pbar%reset(param%nloops) @@ -306,6 +317,7 @@ module subroutine swiftest_io_display_run_information(self, param, integration_t if (phase_val == -1) then write(param%display_unit, *)" *************** Swiftest stop " // trim(adjustl(param%integrator)) // " *************** " if (param%display_style == "COMPACT") write(*,*) "SWIFTEST STOP" // trim(adjustl(param%integrator)) + if (param%log_output) close(param%display_unit) end if #ifdef COARRAY @@ -360,13 +372,17 @@ module subroutine swiftest_io_dump_system(self, param, system_history) class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters class(swiftest_storage), intent(inout) :: system_history !! Stores the system history between output dumps ! Internals - class(swiftest_parameters), allocatable :: param_restart !! Local parameters variable used to parameters change input file names - !! to dump file-specific values without changing the user-defined values + class(swiftest_parameters), allocatable :: param_restart !! Local parameters variable used to parameters change input file + !! names to dump file-specific values without changing the + !! user-defined values character(len=:), allocatable :: param_file_name character(len=STRMAX) :: time_text ! Dump the encounter history if necessary - if (param%lenc_save_trajectory .or. param%lenc_save_closest .and. allocated(self%encounter_history)) call self%encounter_history%dump(param) + if (param%lenc_save_trajectory & + .or. param%lenc_save_closest & + .and. allocated(self%encounter_history)) & + call self%encounter_history%dump(param) if (allocated(self%collision_history)) call self%collision_history%dump(param) ! Dump the nbody_system history to file @@ -454,8 +470,10 @@ module subroutine swiftest_io_get_args(integrator, param_file_name, display_styl ! Arguments character(len=:), intent(inout), allocatable :: integrator !! Symbolic code of the requested integrator character(len=:), intent(inout), allocatable :: param_file_name !! Name of the input parameters file - character(len=:), intent(inout), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD" - logical, intent(in) :: from_cli !! If true, get command-line arguments. Otherwise, use the values of the input variables + character(len=:), intent(inout), allocatable :: display_style !! Style of the output display + !! {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD" + logical, intent(in) :: from_cli !! If true, get command-line arguments. Otherwise, use the + !! values of the input variables ! Internals character(len=STRMAX), dimension(:), allocatable :: arg character(len=STRMAX), dimension(3) :: tmp_arg @@ -543,7 +561,7 @@ end subroutine swiftest_io_get_args module function swiftest_io_get_token(buffer, ifirst, ilast, ierr) result(token) !! author: David A. Minton !! - !! Retrieves a character token from an input string. Here a token is defined as any set of contiguous non-blank characters not + !! Retrieves a character token from an input string. Here a token is defined as any set of contiguous non-blank characters not !! beginning with or containing "!". If "!" is present, any remaining part of the buffer including the "!" is ignored !! !! Adapted from David E. Kaufmann's Swifter routine swiftest_io_get_token.f90 @@ -675,35 +693,44 @@ module subroutine swiftest_io_netcdf_get_t0_values_system(self, nc, param) associate (cb => self%cb) call nc%open(param, readonly=.true.) call nc%find_tslot(param%t0, tslot) - call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%time_dimid, len=itmax), "netcdf_io_get_t0_values_system time_dimid" ) - call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%name_dimid, len=idmax), "netcdf_io_get_t0_values_system name_dimid" ) + call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%time_dimid, len=itmax), "netcdf_io_get_t0_values_system time_dimid") + call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%name_dimid, len=idmax), "netcdf_io_get_t0_values_system name_dimid") allocate(vals(idmax)) - call netcdf_io_check( nf90_get_var(nc%id, nc%time_varid, rtemp, start=[tslot], count=[1]), "netcdf_io_get_t0_values_system time_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%time_varid, rtemp, start=[tslot], count=[1]), & + "netcdf_io_get_t0_values_system time_varid" ) if (param%lenergy) then - call netcdf_io_check( nf90_get_var(nc%id, nc%KE_orb_varid, rtemp, start=[tslot], count=[1]), "netcdf_io_get_t0_values_system KE_orb_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%KE_orb_varid, rtemp, start=[tslot], count=[1]), & + "netcdf_io_get_t0_values_system KE_orb_varid" ) self%ke_orbit_orig = rtemp(1) - call netcdf_io_check( nf90_get_var(nc%id, nc%KE_spin_varid, rtemp, start=[tslot], count=[1]), "netcdf_io_get_t0_values_system KE_spin_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%KE_spin_varid, rtemp, start=[tslot], count=[1]), & + "netcdf_io_get_t0_values_system KE_spin_varid" ) self%ke_spin_orig = rtemp(1) - call netcdf_io_check( nf90_get_var(nc%id, nc%PE_varid, rtemp, start=[tslot], count=[1]), "netcdf_io_get_t0_values_system PE_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%PE_varid, rtemp, start=[tslot], count=[1]), & + "netcdf_io_get_t0_values_system PE_varid" ) self%pe_orig = rtemp(1) - call netcdf_io_check( nf90_get_var(nc%id, nc%BE_varid, rtemp, start=[tslot], count=[1]), "netcdf_io_get_t0_values_system BE_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%BE_varid, rtemp, start=[tslot], count=[1]), & + "netcdf_io_get_t0_values_system BE_varid" ) self%be_orig = rtemp(1) - call netcdf_io_check( nf90_get_var(nc%id, nc%TE_varid, rtemp, start=[tslot], count=[1]), "netcdf_io_get_t0_values_system TE_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%TE_varid, rtemp, start=[tslot], count=[1]), & + "netcdf_io_get_t0_values_system TE_varid" ) self%te_orig = rtemp(1) self%E_orbit_orig = self%ke_orbit_orig + self%pe_orig - call netcdf_io_check( nf90_get_var(nc%id, nc%L_orbit_varid, self%L_orbit_orig(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_get_t0_values_system L_orbit_varid" ) - call netcdf_io_check( nf90_get_var(nc%id, nc%L_spin_varid, self%L_spin_orig(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_get_t0_values_system L_spin_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%L_orbit_varid, self%L_orbit_orig(:), start=[1,tslot], count=[NDIM,1]), & + "netcdf_io_get_t0_values_system L_orbit_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%L_spin_varid, self%L_spin_orig(:), start=[1,tslot], count=[NDIM,1]), & + "netcdf_io_get_t0_values_system L_spin_varid" ) self%L_total_orig(:) = self%L_orbit_orig(:) + self%L_spin_orig(:) - call netcdf_io_check( nf90_get_var(nc%id, nc%Gmass_varid, vals, start=[1,tslot], count=[idmax,1]), "netcdf_io_get_t0_values_system Gmass_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%Gmass_varid, vals, start=[1,tslot], count=[idmax,1]), & + "netcdf_io_get_t0_values_system Gmass_varid" ) call nc%get_valid_masks(plmask,tpmask) self%GMtot_orig = vals(1) + sum(vals(2:idmax), plmask(:)) @@ -711,13 +738,16 @@ module subroutine swiftest_io_netcdf_get_t0_values_system(self, nc, param) cb%dGM = cb%Gmass - cb%GM0 mass0 = cb%GM0 / param%GU - call netcdf_io_check( nf90_get_var(nc%id, nc%radius_varid, rtemp, start=[1,tslot], count=[1,1]), "netcdf_io_get_t0_values_system radius_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%radius_varid, rtemp, start=[1,tslot], count=[1,1]), & + "netcdf_io_get_t0_values_system radius_varid" ) cb%R0 = rtemp(1) if (param%lrotation) then - call netcdf_io_check( nf90_get_var(nc%id, nc%rot_varid, rot0, start=[1,1,tslot], count=[NDIM,1,1]), "netcdf_io_get_t0_values_system rot_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%rot_varid, rot0, start=[1,1,tslot], count=[NDIM,1,1]), & + "netcdf_io_get_t0_values_system rot_varid" ) rot0(:) = rot0(:) * DEG2RAD - call netcdf_io_check( nf90_get_var(nc%id, nc%Ip_varid, Ip0, start=[1,1,tslot], count=[NDIM,1,1]), "netcdf_io_get_t0_values_system Ip_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%Ip_varid, Ip0, start=[1,1,tslot], count=[NDIM,1,1]), & + "netcdf_io_get_t0_values_system Ip_varid" ) cb%L0(:) = Ip0(3) * mass0 * cb%R0**2 * rot0(:) L(:) = cb%Ip(3) * cb%mass * cb%radius**2 * cb%rot(:) cb%dL(:) = L(:) - cb%L0 @@ -725,10 +755,14 @@ module subroutine swiftest_io_netcdf_get_t0_values_system(self, nc, param) ! Retrieve the current bookkeeping variables call nc%find_tslot(self%t, tslot) - call netcdf_io_check( nf90_get_var(nc%id, nc%L_escape_varid, self%L_escape(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_get_t0_values_system L_escape_varid" ) - call netcdf_io_check( nf90_get_var(nc%id, nc%GMescape_varid, self%GMescape, start=[tslot]), "netcdf_io_get_t0_values_system GMescape_varid" ) - call netcdf_io_check( nf90_get_var(nc%id, nc%E_collisions_varid, self%E_collisions, start=[tslot]), "netcdf_io_get_t0_values_system E_collisions_varid" ) - call netcdf_io_check( nf90_get_var(nc%id, nc%E_untracked_varid, self%E_untracked, start=[tslot]), "netcdf_io_get_t0_values_system E_untracked_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%L_escape_varid, self%L_escape(:), start=[1,tslot], count=[NDIM,1]), & + "netcdf_io_get_t0_values_system L_escape_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%GMescape_varid, self%GMescape, start=[tslot]), & + "netcdf_io_get_t0_values_system GMescape_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%E_collisions_varid, self%E_collisions, start=[tslot]), & + "netcdf_io_get_t0_values_system E_collisions_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%E_untracked_varid, self%E_untracked, start=[tslot]), & + "netcdf_io_get_t0_values_system E_untracked_varid" ) end if @@ -784,115 +818,194 @@ module subroutine swiftest_io_netcdf_initialize_output(self, param) nc%lfile_is_open = .true. ! Dimensions - call netcdf_io_check( nf90_def_dim(nc%id, nc%time_dimname, NF90_UNLIMITED, nc%time_dimid), "netcdf_io_initialize_output nf90_def_dim time_dimid" ) ! Simulation time dimension - call netcdf_io_check( nf90_def_dim(nc%id, nc%space_dimname, NDIM, nc%space_dimid), "netcdf_io_initialize_output nf90_def_dim space_dimid" ) ! 3D space dimension - call netcdf_io_check( nf90_def_dim(nc%id, nc%name_dimname, NF90_UNLIMITED, nc%name_dimid), "netcdf_io_initialize_output nf90_def_dim name_dimid" ) ! dimension to store particle id numbers - call netcdf_io_check( nf90_def_dim(nc%id, nc%str_dimname, NAMELEN, nc%str_dimid), "netcdf_io_initialize_output nf90_def_dim str_dimid" ) ! Dimension for string variables (aka character arrays) + call netcdf_io_check( nf90_def_dim(nc%id, nc%time_dimname, NF90_UNLIMITED, nc%time_dimid), & + "netcdf_io_initialize_output nf90_def_dim time_dimid" ) ! Simulation time dimension + call netcdf_io_check( nf90_def_dim(nc%id, nc%space_dimname, NDIM, nc%space_dimid), & + "netcdf_io_initialize_output nf90_def_dim space_dimid" ) ! 3D space dimension + call netcdf_io_check( nf90_def_dim(nc%id, nc%name_dimname, NF90_UNLIMITED, nc%name_dimid), & + "netcdf_io_initialize_output nf90_def_dim name_dimid" ) ! dimension to store particle id numbers + call netcdf_io_check( nf90_def_dim(nc%id, nc%str_dimname, NAMELEN, nc%str_dimid), & + "netcdf_io_initialize_output nf90_def_dim str_dimid" ) ! Dimension for string variables ! Dimension coordinates - call netcdf_io_check( nf90_def_var(nc%id, nc%time_dimname, nc%out_type, nc%time_dimid, nc%time_varid), "netcdf_io_initialize_output nf90_def_var time_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%space_dimname, NF90_CHAR, nc%space_dimid, nc%space_varid), "netcdf_io_initialize_output nf90_def_var space_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%name_dimname, NF90_CHAR, [nc%str_dimid, nc%name_dimid], nc%name_varid), "netcdf_io_initialize_output nf90_def_var name_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%time_dimname, nc%out_type, nc%time_dimid, nc%time_varid), & + "netcdf_io_initialize_output nf90_def_var time_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%space_dimname, NF90_CHAR, nc%space_dimid, nc%space_varid), & + "netcdf_io_initialize_output nf90_def_var space_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%name_dimname, NF90_CHAR, [nc%str_dimid, nc%name_dimid], nc%name_varid), & + "netcdf_io_initialize_output nf90_def_var name_varid" ) ! Variables - call netcdf_io_check( nf90_def_var(nc%id, nc%id_varname, NF90_INT, nc%name_dimid, nc%id_varid), "netcdf_io_initialize_output nf90_def_var id_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%status_varname, NF90_INT, [nc%name_dimid, nc%time_dimid], nc%status_varid), "netcdf_io_initialize_output nf90_def_var status_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%npl_varname, NF90_INT, nc%time_dimid, nc%npl_varid), "netcdf_io_initialize_output nf90_def_var npl_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%ntp_varname, NF90_INT, nc%time_dimid, nc%ntp_varid), "netcdf_io_initialize_output nf90_def_var ntp_varid" ) - if (param%lmtiny_pl) call netcdf_io_check( nf90_def_var(nc%id, nc%nplm_varname, NF90_INT, nc%time_dimid, nc%nplm_varid), "netcdf_io_initialize_output nf90_def_var nplm_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%ptype_varname, NF90_CHAR, [nc%str_dimid, nc%name_dimid], nc%ptype_varid), "netcdf_io_initialize_output nf90_def_var ptype_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%id_varname, NF90_INT, nc%name_dimid, nc%id_varid), & + "netcdf_io_initialize_output nf90_def_var id_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%status_varname, NF90_INT, [nc%name_dimid, nc%time_dimid], nc%status_varid), & + "netcdf_io_initialize_output nf90_def_var status_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%npl_varname, NF90_INT, nc%time_dimid, nc%npl_varid), & + "netcdf_io_initialize_output nf90_def_var npl_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%ntp_varname, NF90_INT, nc%time_dimid, nc%ntp_varid), & + "netcdf_io_initialize_output nf90_def_var ntp_varid" ) + if (param%lmtiny_pl) call netcdf_io_check( nf90_def_var(nc%id, nc%nplm_varname, NF90_INT, nc%time_dimid, nc%nplm_varid), & + "netcdf_io_initialize_output nf90_def_var nplm_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%ptype_varname, NF90_CHAR, [nc%str_dimid, nc%name_dimid], nc%ptype_varid), & + "netcdf_io_initialize_output nf90_def_var ptype_varid" ) if ((param%out_form == "XV") .or. (param%out_form == "XVEL")) then - call netcdf_io_check( nf90_def_var(nc%id, nc%rh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], nc%rh_varid), "netcdf_io_initialize_output nf90_def_var rh_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%vh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], nc%vh_varid), "netcdf_io_initialize_output nf90_def_var vh_varid" ) - - !! When GR is enabled, we need to save the pseudovelocity vectors in addition to the true heliocentric velocity vectors, otherwise - !! we cannnot expect bit-identical runs from restarted runs with GR enabled due to floating point errors during the conversion. + call netcdf_io_check( nf90_def_var(nc%id, nc%rh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], & + nc%rh_varid), "netcdf_io_initialize_output nf90_def_var rh_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%vh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], & + nc%vh_varid), "netcdf_io_initialize_output nf90_def_var vh_varid" ) + + !! When GR is enabled, we need to save the pseudovelocity vectors in addition to the true heliocentric velocity vectors, + !! otherwise !! we cannnot expect bit-identical runs from restarted runs with GR enabled due to floating point errors + !! during the conversion. if (param%lgr) then - call netcdf_io_check( nf90_def_var(nc%id, nc%gr_pseudo_vh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], nc%gr_pseudo_vh_varid), "netcdf_io_initialize_output nf90_def_var gr_psuedo_vh_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%gr_pseudo_vh_varname, nc%out_type, & + [nc%space_dimid, nc%name_dimid, nc%time_dimid], nc%gr_pseudo_vh_varid), & + "netcdf_io_initialize_output nf90_def_var gr_psuedo_vh_varid" ) nc%lpseudo_vel_exists = .true. end if end if if ((param%out_form == "EL") .or. (param%out_form == "XVEL")) then - call netcdf_io_check( nf90_def_var(nc%id, nc%a_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%a_varid), "netcdf_io_initialize_output nf90_def_var a_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%e_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%e_varid), "netcdf_io_initialize_output nf90_def_var e_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%inc_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%inc_varid), "netcdf_io_initialize_output nf90_def_var inc_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%capom_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%capom_varid), "netcdf_io_initialize_output nf90_def_var capom_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%omega_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%omega_varid), "netcdf_io_initialize_output nf90_def_var omega_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%capm_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%capm_varid), "netcdf_io_initialize_output nf90_def_var capm_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%varpi_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%varpi_varid), "netcdf_io_initialize_output nf90_def_var varpi_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%lam_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%lam_varid), "netcdf_io_initialize_output nf90_def_var lam_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%f_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%f_varid), "netcdf_io_initialize_output nf90_def_var f_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%cape_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%cape_varid), "netcdf_io_initialize_output nf90_def_var cape_varid" ) - end if - - call netcdf_io_check( nf90_def_var(nc%id, nc%Gmass_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%Gmass_varid), "netcdf_io_initialize_output nf90_def_var Gmass_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%mass_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%mass_varid), "netcdf_io_initialize_output nf90_def_var mass_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%rhill_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%rhill_varid), "netcdf_io_initialize_output nf90_def_var rhill_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%a_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%a_varid), & + "netcdf_io_initialize_output nf90_def_var a_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%e_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%e_varid), & + "netcdf_io_initialize_output nf90_def_var e_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%inc_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%inc_varid), & + "netcdf_io_initialize_output nf90_def_var inc_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%capom_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], & + nc%capom_varid), & + "netcdf_io_initialize_output nf90_def_var capom_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%omega_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], & + nc%omega_varid), & + "netcdf_io_initialize_output nf90_def_var omega_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%capm_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], & + nc%capm_varid), & + "netcdf_io_initialize_output nf90_def_var capm_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%varpi_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], & + nc%varpi_varid), & + "netcdf_io_initialize_output nf90_def_var varpi_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%lam_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%lam_varid), & + "netcdf_io_initialize_output nf90_def_var lam_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%f_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%f_varid), & + "netcdf_io_initialize_output nf90_def_var f_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%cape_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%cape_varid),& + "netcdf_io_initialize_output nf90_def_var cape_varid" ) + end if + + call netcdf_io_check( nf90_def_var(nc%id, nc%Gmass_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%Gmass_varid), & + "netcdf_io_initialize_output nf90_def_var Gmass_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%mass_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%mass_varid), & + "netcdf_io_initialize_output nf90_def_var mass_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%rhill_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%rhill_varid), & + "netcdf_io_initialize_output nf90_def_var rhill_varid" ) if (param%lclose) then - call netcdf_io_check( nf90_def_var(nc%id, nc%radius_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%radius_varid), "netcdf_io_initialize_output nf90_def_var radius_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%radius_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], & + nc%radius_varid), & + "netcdf_io_initialize_output nf90_def_var radius_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%origin_time_varname, nc%out_type, nc%name_dimid, nc%origin_time_varid), "netcdf_io_initialize_output nf90_def_var origin_time_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%origin_time_varname, nc%out_type, nc%name_dimid, nc%origin_time_varid), & + "netcdf_io_initialize_output nf90_def_var origin_time_varid" ) call netcdf_io_check( nf90_def_var(nc%id, nc%origin_type_varname, NF90_CHAR, [nc%str_dimid, nc%name_dimid], & - nc%origin_type_varid), "netcdf_io_initialize_output nf90_create" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%origin_rh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], nc%origin_rh_varid), "netcdf_io_initialize_output nf90_def_var origin_rh_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%origin_vh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], nc%origin_vh_varid), "netcdf_io_initialize_output nf90_def_var origin_vh_varid" ) - - call netcdf_io_check( nf90_def_var(nc%id, nc%collision_id_varname, NF90_INT, nc%name_dimid, nc%collision_id_varid), "netcdf_io_initialize_output nf90_def_var collision_id_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%discard_time_varname, nc%out_type, nc%name_dimid, nc%discard_time_varid), "netcdf_io_initialize_output nf90_def_var discard_time_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%discard_rh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], nc%discard_rh_varid), "netcdf_io_initialize_output nf90_def_var discard_rh_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%discard_vh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], nc%discard_vh_varid), "netcdf_io_initialize_output nf90_def_var discard_vh_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%discard_body_id_varname, NF90_INT, nc%name_dimid, nc%discard_body_id_varid), "netcdf_io_initialize_output nf90_def_var discard_body_id_varid" ) + nc%origin_type_varid), & + "netcdf_io_initialize_output nf90_create" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%origin_rh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], & + nc%origin_rh_varid), & + "netcdf_io_initialize_output nf90_def_var origin_rh_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%origin_vh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], & + nc%origin_vh_varid), & + "netcdf_io_initialize_output nf90_def_var origin_vh_varid" ) + + call netcdf_io_check( nf90_def_var(nc%id, nc%collision_id_varname, NF90_INT, nc%name_dimid, nc%collision_id_varid), & + "netcdf_io_initialize_output nf90_def_var collision_id_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%discard_time_varname, nc%out_type, nc%name_dimid, nc%discard_time_varid), & + "netcdf_io_initialize_output nf90_def_var discard_time_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%discard_rh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], & + nc%discard_rh_varid), & + "netcdf_io_initialize_output nf90_def_var discard_rh_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%discard_vh_varname, nc%out_type, [nc%space_dimid, nc%name_dimid], & + nc%discard_vh_varid), & + "netcdf_io_initialize_output nf90_def_var discard_vh_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%discard_body_id_varname, NF90_INT, nc%name_dimid, & + nc%discard_body_id_varid), & + "netcdf_io_initialize_output nf90_def_var discard_body_id_varid" ) end if if (param%lrotation) then - call netcdf_io_check( nf90_def_var(nc%id, nc%Ip_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], nc%Ip_varid), "netcdf_io_initialize_output nf90_def_var Ip_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%rot_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], nc%rot_varid), "netcdf_io_initialize_output nf90_def_var rot_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%Ip_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], & + nc%Ip_varid), & + "netcdf_io_initialize_output nf90_def_var Ip_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%rot_varname, nc%out_type, [nc%space_dimid, nc%name_dimid, nc%time_dimid], & + nc%rot_varid), & + "netcdf_io_initialize_output nf90_def_var rot_varid" ) end if ! if (param%ltides) then - ! call netcdf_io_check( nf90_def_var(nc%id, nc%k2_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%k2_varid), "netcdf_io_initialize_output nf90_def_var k2_varid" ) - ! call netcdf_io_check( nf90_def_var(nc%id, nc%q_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%Q_varid), "netcdf_io_initialize_output nf90_def_var Q_varid" ) + ! call netcdf_io_check( nf90_def_var(nc%id, nc%k2_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%k2_varid), & + ! "netcdf_io_initialize_output nf90_def_var k2_varid" ) + ! call netcdf_io_check( nf90_def_var(nc%id, nc%q_varname, nc%out_type, [nc%name_dimid, nc%time_dimid], nc%Q_varid), & + ! "netcdf_io_initialize_output nf90_def_var Q_varid" ) ! end if if (param%lenergy) then - call netcdf_io_check( nf90_def_var(nc%id, nc%ke_orb_varname, nc%out_type, nc%time_dimid, nc%KE_orb_varid), "netcdf_io_initialize_output nf90_def_var KE_orb_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%ke_spin_varname, nc%out_type, nc%time_dimid, nc%KE_spin_varid), "netcdf_io_initialize_output nf90_def_var KE_spin_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%pe_varname, nc%out_type, nc%time_dimid, nc%PE_varid), "netcdf_io_initialize_output nf90_def_var PE_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%be_varname, nc%out_type, nc%time_dimid, nc%BE_varid), "netcdf_io_initialize_output nf90_def_var BE_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%te_varname, nc%out_type, nc%time_dimid, nc%TE_varid), "netcdf_io_initialize_output nf90_def_var TE_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%L_orbit_varname, nc%out_type, [nc%space_dimid, nc%time_dimid], nc%L_orbit_varid), "netcdf_io_initialize_output nf90_def_var L_orbit_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%L_spin_varname, nc%out_type, [nc%space_dimid, nc%time_dimid], nc%L_spin_varid), "netcdf_io_initialize_output nf90_def_var L_spin_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%L_escape_varname, nc%out_type, [nc%space_dimid, nc%time_dimid], nc%L_escape_varid), "netcdf_io_initialize_output nf90_def_var L_escape_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%E_collisions_varname, nc%out_type, nc%time_dimid, nc%E_collisions_varid), "netcdf_io_initialize_output nf90_def_var E_collisions_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%E_untracked_varname, nc%out_type, nc%time_dimid, nc%E_untracked_varid), "netcdf_io_initialize_output nf90_def_var E_untracked_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%GMescape_varname, nc%out_type, nc%time_dimid, nc%GMescape_varid), "netcdf_io_initialize_output nf90_def_var GMescape_varid" ) - end if - - call netcdf_io_check( nf90_def_var(nc%id, nc%j2rp2_varname, nc%out_type, nc%time_dimid, nc%j2rp2_varid), "netcdf_io_initialize_output nf90_def_var j2rp2_varid" ) - call netcdf_io_check( nf90_def_var(nc%id, nc%j4rp4_varname, nc%out_type, nc%time_dimid, nc%j4rp4_varid), "netcdf_io_initialize_output nf90_def_var j4rp4_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%ke_orb_varname, nc%out_type, nc%time_dimid, nc%KE_orb_varid), & + "netcdf_io_initialize_output nf90_def_var KE_orb_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%ke_spin_varname, nc%out_type, nc%time_dimid, nc%KE_spin_varid), & + "netcdf_io_initialize_output nf90_def_var KE_spin_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%pe_varname, nc%out_type, nc%time_dimid, nc%PE_varid), & + "netcdf_io_initialize_output nf90_def_var PE_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%be_varname, nc%out_type, nc%time_dimid, nc%BE_varid), & + "netcdf_io_initialize_output nf90_def_var BE_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%te_varname, nc%out_type, nc%time_dimid, nc%TE_varid), & + "netcdf_io_initialize_output nf90_def_var TE_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%L_orbit_varname, nc%out_type, [nc%space_dimid, nc%time_dimid], & + nc%L_orbit_varid), & + "netcdf_io_initialize_output nf90_def_var L_orbit_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%L_spin_varname, nc%out_type, [nc%space_dimid, nc%time_dimid], & + nc%L_spin_varid), & + "netcdf_io_initialize_output nf90_def_var L_spin_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%L_escape_varname, nc%out_type, [nc%space_dimid, nc%time_dimid], & + nc%L_escape_varid), & + "netcdf_io_initialize_output nf90_def_var L_escape_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%E_collisions_varname, nc%out_type, nc%time_dimid, nc%E_collisions_varid), & + "netcdf_io_initialize_output nf90_def_var E_collisions_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%E_untracked_varname, nc%out_type, nc%time_dimid, nc%E_untracked_varid), & + "netcdf_io_initialize_output nf90_def_var E_untracked_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%GMescape_varname, nc%out_type, nc%time_dimid, nc%GMescape_varid), & + "netcdf_io_initialize_output nf90_def_var GMescape_varid" ) + end if + + call netcdf_io_check( nf90_def_var(nc%id, nc%j2rp2_varname, nc%out_type, nc%time_dimid, nc%j2rp2_varid), & + "netcdf_io_initialize_output nf90_def_var j2rp2_varid" ) + call netcdf_io_check( nf90_def_var(nc%id, nc%j4rp4_varname, nc%out_type, nc%time_dimid, nc%j4rp4_varid), & + "netcdf_io_initialize_output nf90_def_var j4rp4_varid" ) ! Set fill mode to NaN for all variables - call netcdf_io_check( nf90_inquire(nc%id, nVariables=nvar), "netcdf_io_initialize_output nf90_inquire nVariables" ) + call netcdf_io_check( nf90_inquire(nc%id, nVariables=nvar), "netcdf_io_initialize_output nf90_inquire nVariables" ) do varid = 1, nvar - call netcdf_io_check( nf90_inquire_variable(nc%id, varid, xtype=vartype, ndims=ndims), "netcdf_io_initialize_output nf90_inquire_variable" ) + call netcdf_io_check( nf90_inquire_variable(nc%id, varid, xtype=vartype, ndims=ndims), & + "netcdf_io_initialize_output nf90_inquire_variable" ) select case(vartype) case(NF90_INT) if (varid == nc%status_varid) then ! Be sure the status variable fill value is the INACTIVE symbolic value - call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, INACTIVE), "netcdf_io_netcdf_initialize_output nf90_def_var_fill status variable" ) + call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, INACTIVE), & + "netcdf_io_netcdf_initialize_output nf90_def_var_fill status variable" ) else - call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, NF90_FILL_INT), "netcdf_io_initialize_output nf90_def_var_fill NF90_INT" ) + call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, NF90_FILL_INT), & + "netcdf_io_initialize_output nf90_def_var_fill NF90_INT" ) end if case(NF90_FLOAT) - call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, sfill), "netcdf_io_initialize_output nf90_def_var_fill NF90_FLOAT" ) + call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, sfill), & + "netcdf_io_initialize_output nf90_def_var_fill NF90_FLOAT" ) case(NF90_DOUBLE) - call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, dfill), "netcdf_io_initialize_output nf90_def_var_fill NF90_DOUBLE" ) + call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, dfill), & + "netcdf_io_initialize_output nf90_def_var_fill NF90_DOUBLE" ) case(NF90_CHAR) - call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, 0), "netcdf_io_initialize_output nf90_def_var_fill NF90_CHAR" ) + call netcdf_io_check( nf90_def_var_fill(nc%id, varid, NO_FILL, 0), & + "netcdf_io_initialize_output nf90_def_var_fill NF90_CHAR" ) end select end do @@ -900,9 +1013,11 @@ module subroutine swiftest_io_netcdf_initialize_output(self, param) if (param%lclose) then select case (vartype) case(NF90_FLOAT) - call netcdf_io_check( nf90_def_var_fill(nc%id, nc%discard_time_varid, NO_FILL, huge(1.0_SP)), "netcdf_io_initialize_output nf90_def_var_fill discard_time NF90_FLOAT" ) + call netcdf_io_check( nf90_def_var_fill(nc%id, nc%discard_time_varid, NO_FILL, huge(1.0_SP)), & + "netcdf_io_initialize_output nf90_def_var_fill discard_time NF90_FLOAT" ) case(NF90_DOUBLE) - call netcdf_io_check( nf90_def_var_fill(nc%id, nc%discard_time_varid, NO_FILL, huge(1.0_DP)), "netcdf_io_initialize_output nf90_def_var_fill discard_time NF90_DOUBLE" ) + call netcdf_io_check( nf90_def_var_fill(nc%id, nc%discard_time_varid, NO_FILL, huge(1.0_DP)), & + "netcdf_io_initialize_output nf90_def_var_fill discard_time NF90_DOUBLE" ) end select end if @@ -910,7 +1025,8 @@ module subroutine swiftest_io_netcdf_initialize_output(self, param) call netcdf_io_check( nf90_enddef(nc%id), "netcdf_io_initialize_output nf90_enddef" ) ! Add in the space dimension coordinates - call netcdf_io_check( nf90_put_var(nc%id, nc%space_varid, nc%space_coords, start=[1], count=[NDIM]), "netcdf_io_initialize_output nf90_put_var space" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%space_varid, nc%space_coords, start=[1], count=[NDIM]), & + "netcdf_io_initialize_output nf90_put_var space" ) end associate return @@ -945,57 +1061,82 @@ module subroutine swiftest_io_netcdf_open(self, param, readonly) self%lfile_is_open = .true. ! Dimensions - call netcdf_io_check( nf90_inq_dimid(nc%id, nc%time_dimname, nc%time_dimid), "swiftest_io_netcdf_open nf90_inq_dimid time_dimid" ) - call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%time_dimid, nc%time_dimname, len=nc%max_tslot), "swiftest_io_netcdf_open nf90_inquire_dimension max_tslot" ) - call netcdf_io_check( nf90_inq_dimid(nc%id, nc%space_dimname, nc%space_dimid), "swiftest_io_netcdf_open nf90_inq_dimid space_dimid" ) - call netcdf_io_check( nf90_inq_dimid(nc%id, nc%name_dimname, nc%name_dimid), "swiftest_io_netcdf_open nf90_inq_dimid name_dimid" ) - call netcdf_io_check( nf90_inq_dimid(nc%id, nc%str_dimname, nc%str_dimid), "swiftest_io_netcdf_open nf90_inq_dimid str_dimid" ) + call netcdf_io_check( nf90_inq_dimid(nc%id, nc%time_dimname, nc%time_dimid), & + "swiftest_io_netcdf_open nf90_inq_dimid time_dimid" ) + call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%time_dimid, nc%time_dimname, len=nc%max_tslot), & + "swiftest_io_netcdf_open nf90_inquire_dimension max_tslot" ) + call netcdf_io_check( nf90_inq_dimid(nc%id, nc%space_dimname, nc%space_dimid), & + "swiftest_io_netcdf_open nf90_inq_dimid space_dimid" ) + call netcdf_io_check( nf90_inq_dimid(nc%id, nc%name_dimname, nc%name_dimid), & + "swiftest_io_netcdf_open nf90_inq_dimid name_dimid" ) + call netcdf_io_check( nf90_inq_dimid(nc%id, nc%str_dimname, nc%str_dimid), & + "swiftest_io_netcdf_open nf90_inq_dimid str_dimid" ) ! Dimension coordinates - call netcdf_io_check( nf90_inq_varid(nc%id, nc%time_dimname, nc%time_varid), "swiftest_io_netcdf_open nf90_inq_varid time_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%space_dimname, nc%space_varid), "swiftest_io_netcdf_open nf90_inq_varid space_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%name_dimname, nc%name_varid), "swiftest_io_netcdf_open nf90_inq_varid name_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%time_dimname, nc%time_varid), & + "swiftest_io_netcdf_open nf90_inq_varid time_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%space_dimname, nc%space_varid), & + "swiftest_io_netcdf_open nf90_inq_varid space_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%name_dimname, nc%name_varid), & + "swiftest_io_netcdf_open nf90_inq_varid name_varid" ) ! Required Variables - call netcdf_io_check( nf90_inq_varid(nc%id, nc%id_varname, nc%id_varid), "swiftest_io_netcdf_open nf90_inq_varid name_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%Gmass_varname, nc%Gmass_varid), "swiftest_io_netcdf_open nf90_inq_varid Gmass_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%id_varname, nc%id_varid), & + "swiftest_io_netcdf_open nf90_inq_varid name_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%Gmass_varname, nc%Gmass_varid), & + "swiftest_io_netcdf_open nf90_inq_varid Gmass_varid" ) if ((param%out_form == "XV") .or. (param%out_form == "XVEL")) then - call netcdf_io_check( nf90_inq_varid(nc%id, nc%rh_varname, nc%rh_varid), "swiftest_io_netcdf_open nf90_inq_varid rh_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%vh_varname, nc%vh_varid), "swiftest_io_netcdf_open nf90_inq_varid vh_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%rh_varname, nc%rh_varid), & + "swiftest_io_netcdf_open nf90_inq_varid rh_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%vh_varname, nc%vh_varid), & + "swiftest_io_netcdf_open nf90_inq_varid vh_varid" ) if (param%lgr) then - !! check if pseudovelocity vectors exist in this file. If they are, set the correct flag so we know whe should not do the conversion. + !! check if pseudovelocity vectors exist in this file. If they are, set the correct flag so we know whe should not + !! do the conversion. status = nf90_inq_varid(nc%id, nc%gr_pseudo_vh_varname, nc%gr_pseudo_vh_varid) nc%lpseudo_vel_exists = (status == NF90_NOERR) if (param%lrestart .and. .not.nc%lpseudo_vel_exists) then - write(*,*) "Warning! Pseudovelocity not found in input file for GR enabled run. If this is a restarted run, bit-identical trajectories are not guarunteed!" + write(*,*) "Warning! Pseudovelocity not found in input file for GR enabled run. " & + // "If this is a restarted run, bit-identical trajectories are not guarunteed!" end if end if end if if ((param%out_form == "EL") .or. (param%out_form == "XVEL")) then - call netcdf_io_check( nf90_inq_varid(nc%id, nc%a_varname, nc%a_varid), "swiftest_io_netcdf_open nf90_inq_varid a_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%e_varname, nc%e_varid), "swiftest_io_netcdf_open nf90_inq_varid e_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%inc_varname, nc%inc_varid), "swiftest_io_netcdf_open nf90_inq_varid inc_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%capom_varname, nc%capom_varid), "swiftest_io_netcdf_open nf90_inq_varid capom_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%omega_varname, nc%omega_varid), "swiftest_io_netcdf_open nf90_inq_varid omega_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%capm_varname, nc%capm_varid), "swiftest_io_netcdf_open nf90_inq_varid capm_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%a_varname, nc%a_varid), & + "swiftest_io_netcdf_open nf90_inq_varid a_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%e_varname, nc%e_varid), & + "swiftest_io_netcdf_open nf90_inq_varid e_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%inc_varname, nc%inc_varid), & + "swiftest_io_netcdf_open nf90_inq_varid inc_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%capom_varname, nc%capom_varid), & + "swiftest_io_netcdf_open nf90_inq_varid capom_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%omega_varname, nc%omega_varid), & + "swiftest_io_netcdf_open nf90_inq_varid omega_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%capm_varname, nc%capm_varid), & + "swiftest_io_netcdf_open nf90_inq_varid capm_varid" ) end if if (param%lclose) then - call netcdf_io_check( nf90_inq_varid(nc%id, nc%radius_varname, nc%radius_varid), "swiftest_io_netcdf_open nf90_inq_varid radius_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%radius_varname, nc%radius_varid), & + "swiftest_io_netcdf_open nf90_inq_varid radius_varid" ) end if if (param%lrotation) then - call netcdf_io_check( nf90_inq_varid(nc%id, nc%Ip_varname, nc%Ip_varid), "swiftest_io_netcdf_open nf90_inq_varid Ip_varid" ) - call netcdf_io_check( nf90_inq_varid(nc%id, nc%rot_varname, nc%rot_varid), "swiftest_io_netcdf_open nf90_inq_varid rot_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%Ip_varname, nc%Ip_varid), & + "swiftest_io_netcdf_open nf90_inq_varid Ip_varid" ) + call netcdf_io_check( nf90_inq_varid(nc%id, nc%rot_varname, nc%rot_varid), & + "swiftest_io_netcdf_open nf90_inq_varid rot_varid" ) end if ! if (param%ltides) then - ! call netcdf_io_check( nf90_inq_varid(nc%id, nc%k2_varname, nc%k2_varid), "swiftest_io_netcdf_open nf90_inq_varid k2_varid" ) - ! call netcdf_io_check( nf90_inq_varid(nc%id, nc%q_varname, nc%Q_varid), "swiftest_io_netcdf_open nf90_inq_varid Q_varid" ) + ! call netcdf_io_check( nf90_inq_varid(nc%id, nc%k2_varname, nc%k2_varid), & + ! "swiftest_io_netcdf_open nf90_inq_varid k2_varid" ) + ! call netcdf_io_check( nf90_inq_varid(nc%id, nc%q_varname, nc%Q_varid), & + ! "swiftest_io_netcdf_open nf90_inq_varid Q_varid" ) ! end if ! Optional variables The User Doesn't Need to Know About @@ -1049,17 +1190,22 @@ end subroutine swiftest_io_netcdf_open module subroutine swiftest_io_netcdf_get_valid_masks(self, plmask, tpmask, plmmask, Gmtiny) !! author: David A. Minton !! - !! Given an open NetCDF, returns logical masks indicating which bodies in the body arrays are active pl and tp type at the current time. - !! Uses the value of tslot stored in the NetCDF parameter object as the definition of current time + !! Given an open NetCDF, returns logical masks indicating which bodies in the body arrays are active pl and tp type at the + !! current time. Uses the value of tslot stored in the NetCDF parameter object as the definition of current time use, intrinsic :: ieee_exceptions use, intrinsic :: ieee_arithmetic implicit none ! Arguments - class(swiftest_netcdf_parameters), intent(inout) :: self !! Parameters used to identify a particular NetCDF dataset - logical, dimension(:), allocatable, intent(out) :: plmask !! Logical mask indicating which bodies are massive bodies - logical, dimension(:), allocatable, intent(out) :: tpmask !! Logical mask indicating which bodies are test particles - logical, dimension(:), allocatable, intent(out), optional :: plmmask !! Logical mask indicating which bodies are fully interacting massive bodies - real(DP), intent(in), optional :: Gmtiny !! The cutoff G*mass between semi-interacting and fully interacting massive bodies + class(swiftest_netcdf_parameters), intent(inout) :: self !! Parameters used to identify a particular NetCDF + !! dataset + logical, dimension(:), allocatable, intent(out) :: plmask !! Logical mask indicating which bodies are massive + !! bodies + logical, dimension(:), allocatable, intent(out) :: tpmask !! Logical mask indicating which bodies are test + !! particles + logical, dimension(:), allocatable, intent(out), optional :: plmmask !! Logical mask indicating which bodies are fully + !! interacting massive bodies + real(DP), intent(in), optional :: Gmtiny !! The cutoff G*mass between semi-interacting and fully + !! interacting massive bodies ! Internals real(DP), dimension(:), allocatable :: Gmass, a real(DP), dimension(:,:), allocatable :: rh @@ -1071,7 +1217,8 @@ module subroutine swiftest_io_netcdf_get_valid_masks(self, plmask, tpmask, plmma call ieee_get_halting_mode(IEEE_ALL,fpe_halting_modes) ! Save the current halting modes so we can turn them off temporarily call ieee_set_halting_mode(IEEE_ALL,.false.) - call netcdf_io_check( nf90_inquire_dimension(self%id, self%name_dimid, len=idmax), "swiftest_io_netcdf_get_valid_masks nf90_inquire_dimension name_dimid" ) + call netcdf_io_check( nf90_inquire_dimension(self%id, self%name_dimid, len=idmax), & + "swiftest_io_netcdf_get_valid_masks nf90_inquire_dimension name_dimid" ) allocate(Gmass(idmax)) allocate(tpmask(idmax)) @@ -1079,24 +1226,28 @@ module subroutine swiftest_io_netcdf_get_valid_masks(self, plmask, tpmask, plmma allocate(lvalid(idmax)) associate(tslot => self%tslot) - call netcdf_io_check( nf90_get_var(self%id, self%Gmass_varid, Gmass, start=[1,tslot], count=[idmax,1]), "swiftest_io_netcdf_get_valid_masks nf90_getvar Gmass_varid" ) + call netcdf_io_check( nf90_get_var(self%id, self%Gmass_varid, Gmass, start=[1,tslot], count=[idmax,1]), & + "swiftest_io_netcdf_get_valid_masks nf90_getvar Gmass_varid" ) status = nf90_inq_varid(self%id, self%status_varname, self%status_varid) if (status == NF90_NOERR) then allocate(body_status(idmax)) - call netcdf_io_check( nf90_get_var(self%id, self%status_varid, body_status, start=[1, tslot], count=[idmax,1]), "swiftest_io_netcdf_get_valid_masks nf90_getvar status_varid" ) + call netcdf_io_check( nf90_get_var(self%id, self%status_varid, body_status, start=[1, tslot], count=[idmax,1]), & + "swiftest_io_netcdf_get_valid_masks nf90_getvar status_varid" ) lvalid(:) = body_status(:) /= INACTIVE else status = nf90_inq_varid(self%id, self%rh_varname, self%rh_varid) if (status == NF90_NOERR) then allocate(rh(NDIM,idmax)) - call netcdf_io_check( nf90_get_var(self%id, self%rh_varid, rh, start=[1, 1, tslot], count=[NDIM,idmax,1]), "swiftest_io_netcdf_get_valid_masks nf90_getvar rh_varid" ) + call netcdf_io_check( nf90_get_var(self%id, self%rh_varid, rh, start=[1, 1, tslot], count=[NDIM,idmax,1]), & + "swiftest_io_netcdf_get_valid_masks nf90_getvar rh_varid" ) lvalid(:) = ieee_is_normal(rh(1,:)) else status = nf90_inq_varid(self%id, self%a_varname, self%a_varid) if (status == NF90_NOERR) then allocate(a(idmax)) - call netcdf_io_check( nf90_get_var(self%id, self%a_varid, a, start=[1, tslot], count=[idmax,1]), "swiftest_io_netcdf_get_valid_masks nf90_getvar a_varid" ) + call netcdf_io_check( nf90_get_var(self%id, self%a_varid, a, start=[1, tslot], count=[idmax,1]), & + "swiftest_io_netcdf_get_valid_masks nf90_getvar a_varid" ) lvalid(:) = ieee_is_normal(a(:)) else lvalid(:) = .false. @@ -1149,7 +1300,8 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier associate(cb => self%cb, pl => self%pl, tp => self%tp, tslot => nc%tslot) call nc%open(param, readonly=.true.) call nc%find_tslot(self%t, tslot) - call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%time_dimid, len=nc%max_tslot), "netcdf_io_read_frame_system nf90_inquire_dimension time_dimid" ) + call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%time_dimid, len=nc%max_tslot), & + "netcdf_io_read_frame_system nf90_inquire_dimension time_dimid" ) tslot = min(tslot, nc%max_tslot) call self%read_hdr(nc, param) @@ -1159,12 +1311,14 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier ntp = tp%nbody call pl%setup(npl, param) call tp%setup(ntp, param) - call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%name_dimid, len=idmax), "netcdf_io_read_frame_system nf90_inquire_dimension name_dimid" ) + call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%name_dimid, len=idmax), & + "netcdf_io_read_frame_system nf90_inquire_dimension name_dimid" ) allocate(rtemp(idmax)) allocate(vectemp(NDIM,idmax)) allocate(itemp(idmax)) - call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%str_dimid, len=str_max), "netcdf_io_read_frame_system nf90_inquire_dimension str_dimid" ) + call netcdf_io_check( nf90_inquire_dimension(nc%id, nc%str_dimid, len=str_max), & + "netcdf_io_read_frame_system nf90_inquire_dimension str_dimid" ) call nc%get_valid_masks(plmask, tpmask) @@ -1187,20 +1341,24 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier ! Now read in each variable and split the outputs by body type if ((param%in_form == "XV") .or. (param%in_form == "XVEL")) then - call netcdf_io_check( nf90_get_var(nc%id, nc%rh_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), "netcdf_io_read_frame_system nf90_getvar rh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%rh_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar rh_varid" ) do i = 1, NDIM if (npl > 0) pl%rh(i,:) = pack(vectemp(i,:), plmask(:)) if (ntp > 0) tp%rh(i,:) = pack(vectemp(i,:), tpmask(:)) end do if (param%lgr .and. nc%lpseudo_vel_exists) then - call netcdf_io_check( nf90_get_var(nc%id, nc%gr_pseudo_vh_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), "netcdf_io_read_frame_system nf90_getvar gr_pseudo_vh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%gr_pseudo_vh_varid, vectemp, start=[1, 1, tslot], & + count=[NDIM,idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar gr_pseudo_vh_varid" ) do i = 1, NDIM if (npl > 0) pl%vh(i,:) = pack(vectemp(i,:), plmask(:)) if (ntp > 0) tp%vh(i,:) = pack(vectemp(i,:), tpmask(:)) end do else - call netcdf_io_check( nf90_get_var(nc%id, nc%vh_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), "netcdf_io_read_frame_system nf90_getvar vh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%vh_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar vh_varid" ) do i = 1, NDIM if (npl > 0) pl%vh(i,:) = pack(vectemp(i,:), plmask(:)) if (ntp > 0) tp%vh(i,:) = pack(vectemp(i,:), tpmask(:)) @@ -1209,40 +1367,46 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier end if if ((param%in_form == "EL") .or. (param%in_form == "XVEL")) then - call netcdf_io_check( nf90_get_var(nc%id, nc%a_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar a_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%a_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar a_varid" ) if (.not.allocated(pl%a)) allocate(pl%a(npl)) if (.not.allocated(tp%a)) allocate(tp%a(ntp)) if (npl > 0) pl%a(:) = pack(rtemp, plmask) if (ntp > 0) tp%a(:) = pack(rtemp, tpmask) - call netcdf_io_check( nf90_get_var(nc%id, nc%e_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar e_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%e_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar e_varid" ) if (.not.allocated(pl%e)) allocate(pl%e(npl)) if (.not.allocated(tp%e)) allocate(tp%e(ntp)) if (npl > 0) pl%e(:) = pack(rtemp, plmask) if (ntp > 0) tp%e(:) = pack(rtemp, tpmask) - call netcdf_io_check( nf90_get_var(nc%id, nc%inc_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar inc_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%inc_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar inc_varid" ) rtemp = rtemp * DEG2RAD if (.not.allocated(pl%inc)) allocate(pl%inc(npl)) if (.not.allocated(tp%inc)) allocate(tp%inc(ntp)) if (npl > 0) pl%inc(:) = pack(rtemp, plmask) if (ntp > 0) tp%inc(:) = pack(rtemp, tpmask) - call netcdf_io_check( nf90_get_var(nc%id, nc%capom_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar capom_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%capom_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar capom_varid" ) rtemp = rtemp * DEG2RAD if (.not.allocated(pl%capom)) allocate(pl%capom(npl)) if (.not.allocated(tp%capom)) allocate(tp%capom(ntp)) if (npl > 0) pl%capom(:) = pack(rtemp, plmask) if (ntp > 0) tp%capom(:) = pack(rtemp, tpmask) - call netcdf_io_check( nf90_get_var(nc%id, nc%omega_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar omega_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%omega_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar omega_varid" ) rtemp = rtemp * DEG2RAD if (.not.allocated(pl%omega)) allocate(pl%omega(npl)) if (.not.allocated(tp%omega)) allocate(tp%omega(ntp)) if (npl > 0) pl%omega(:) = pack(rtemp, plmask) if (ntp > 0) tp%omega(:) = pack(rtemp, tpmask) - call netcdf_io_check( nf90_get_var(nc%id, nc%capm_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar capm_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%capm_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar capm_varid" ) rtemp = rtemp * DEG2RAD if (.not.allocated(pl%capm)) allocate(pl%capm(npl)) if (.not.allocated(tp%capm)) allocate(tp%capm(ntp)) @@ -1251,7 +1415,8 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier end if - call netcdf_io_check( nf90_get_var(nc%id, nc%Gmass_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar Gmass_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%Gmass_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar Gmass_varid" ) cb%Gmass = rtemp(1) cb%mass = cb%Gmass / param%GU @@ -1270,7 +1435,8 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier end if if (param%lclose) then - call netcdf_io_check( nf90_get_var(nc%id, nc%radius_varid, rtemp, start=[1, tslot], count=[idmax,1]), "netcdf_io_read_frame_system nf90_getvar radius_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%radius_varid, rtemp, start=[1, tslot], count=[idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar radius_varid" ) cb%radius = rtemp(1) if (npl > 0) pl%radius(:) = pack(rtemp, plmask) @@ -1281,13 +1447,15 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier cb%R0 = cb%radius if (param%lrotation) then - call netcdf_io_check( nf90_get_var(nc%id, nc%Ip_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), "netcdf_io_read_frame_system nf90_getvar Ip_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%Ip_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar Ip_varid" ) cb%Ip(:) = vectemp(:,1) do i = 1, NDIM if (npl > 0) pl%Ip(i,:) = pack(vectemp(i,:), plmask(:)) end do - call netcdf_io_check( nf90_get_var(nc%id, nc%rot_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), "netcdf_io_read_frame_system nf90_getvar rot_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%rot_varid, vectemp, start=[1, 1, tslot], count=[NDIM,idmax,1]), & + "netcdf_io_read_frame_system nf90_getvar rot_varid" ) vectemp(:,:) = vectemp(:,:) * DEG2RAD cb%rot(:) = vectemp(:,1) do i = 1, NDIM @@ -1299,25 +1467,29 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier end if ! if (param%ltides) then - ! call netcdf_io_check( nf90_get_var(nc%id, nc%k2_varid, rtemp, start=[1, tslot]), "netcdf_io_read_frame_system nf90_getvar k2_varid" ) + ! call netcdf_io_check( nf90_get_var(nc%id, nc%k2_varid, rtemp, start=[1, tslot]), & + ! "netcdf_io_read_frame_system nf90_getvar k2_varid" ) ! cb%k2 = rtemp(1) ! if (npl > 0) pl%k2(:) = pack(rtemp, plmask) - ! call netcdf_io_check( nf90_get_var(nc%id, nc%Q_varid, rtemp, start=[1, tslot]), "netcdf_io_read_frame_system nf90_getvar Q_varid" ) + ! call netcdf_io_check( nf90_get_var(nc%id, nc%Q_varid, rtemp, start=[1, tslot]), & + ! "netcdf_io_read_frame_system nf90_getvar Q_varid" ) ! cb%Q = rtemp(1) ! if (npl > 0) pl%Q(:) = pack(rtemp, plmask) ! end if status = nf90_inq_varid(nc%id, nc%j2rp2_varname, nc%j2rp2_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%j2rp2_varid, cb%j2rp2, start=[tslot]), "netcdf_io_read_frame_system nf90_getvar j2rp2_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%j2rp2_varid, cb%j2rp2, start=[tslot]), & + "netcdf_io_read_frame_system nf90_getvar j2rp2_varid" ) else cb%j2rp2 = 0.0_DP end if status = nf90_inq_varid(nc%id, nc%j4rp4_varname, nc%j4rp4_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%j4rp4_varid, cb%j4rp4, start=[tslot]), "netcdf_io_read_frame_system nf90_getvar j4rp4_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%j4rp4_varid, cb%j4rp4, start=[tslot]), & + "netcdf_io_read_frame_system nf90_getvar j4rp4_varid" ) else cb%j4rp4 = 0.0_DP end if @@ -1349,8 +1521,8 @@ module subroutine swiftest_io_netcdf_read_hdr_system(self, nc, param) !! author: David A. Minton !! !! Reads header information (variables that change with time, but not particle id). - !! This subroutine swiftest_significantly improves the output over the original binary file, allowing us to track energy, momentum, and other quantities that - !! previously were handled as separate output files. + !! This subroutine swiftest_significantly improves the output over the original binary file, allowing us to track energy, + !! momentum, and other quantities that previously were handled as separate output files. implicit none ! Arguments class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object @@ -1361,7 +1533,8 @@ module subroutine swiftest_io_netcdf_read_hdr_system(self, nc, param) logical, dimension(:), allocatable :: plmask, tpmask, plmmask associate(tslot => nc%tslot) - call netcdf_io_check( nf90_get_var(nc%id, nc%time_varid, self%t, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar time_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%time_varid, self%t, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar time_varid" ) if (param%lmtiny_pl) then call nc%get_valid_masks(plmask, tpmask, plmmask, param%GMTINY) else @@ -1370,14 +1543,16 @@ module subroutine swiftest_io_netcdf_read_hdr_system(self, nc, param) status = nf90_inq_varid(nc%id, nc%npl_varname, nc%npl_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%npl_varid, self%pl%nbody, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar npl_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%npl_varid, self%pl%nbody, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar npl_varid" ) else self%pl%nbody = count(plmask(:)) end if status = nf90_inq_varid(nc%id, nc%ntp_varname, nc%ntp_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%ntp_varid, self%tp%nbody, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar ntp_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%ntp_varid, self%tp%nbody, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar ntp_varid" ) else self%tp%nbody = count(tpmask(:)) end if @@ -1385,7 +1560,8 @@ module subroutine swiftest_io_netcdf_read_hdr_system(self, nc, param) if (param%lmtiny_pl) then status = nf90_inq_varid(nc%id, nc%nplm_varname, nc%nplm_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%nplm_varid, self%pl%nplm, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar nplm_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%nplm_varid, self%pl%nplm, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar nplm_varid" ) else self%pl%nplm = count(plmmask(:)) end if @@ -1393,27 +1569,43 @@ module subroutine swiftest_io_netcdf_read_hdr_system(self, nc, param) if (param%lenergy) then status = nf90_inq_varid(nc%id, nc%ke_orb_varname, nc%KE_orb_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%KE_orb_varid, self%ke_orbit, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar KE_orb_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%KE_orb_varid, self%ke_orbit, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar KE_orb_varid" ) status = nf90_inq_varid(nc%id, nc%ke_spin_varname, nc%KE_spin_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%KE_spin_varid, self%ke_spin, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar KE_spin_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%KE_spin_varid, self%ke_spin, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar KE_spin_varid" ) status = nf90_inq_varid(nc%id, nc%pe_varname, nc%PE_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%PE_varid, self%pe, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar PE_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%PE_varid, self%pe, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar PE_varid" ) status = nf90_inq_varid(nc%id, nc%be_varname, nc%BE_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%BE_varid, self%be, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar BE_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%BE_varid, self%be, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar BE_varid" ) status = nf90_inq_varid(nc%id, nc%te_varname, nc%TE_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%TE_varid, self%te, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar TE_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%TE_varid, self%te, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar TE_varid" ) status = nf90_inq_varid(nc%id, nc%L_orbit_varname, nc%L_orbit_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%L_orbit_varid, self%L_orbit(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_read_hdr_system nf90_getvar L_orbit_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%L_orbit_varid, self%L_orbit(:), & + start=[1,tslot], count=[NDIM,1]), & + "netcdf_io_read_hdr_system nf90_getvar L_orbit_varid" ) status = nf90_inq_varid(nc%id, nc%L_spin_varname, nc%L_spin_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%L_spin_varid, self%L_spin(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_read_hdr_system nf90_getvar L_spin_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%L_spin_varid, self%L_spin(:), start=[1,tslot], & + count=[NDIM,1]), & + "netcdf_io_read_hdr_system nf90_getvar L_spin_varid" ) status = nf90_inq_varid(nc%id, nc%L_escape_varname, nc%L_escape_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%L_escape_varid, self%L_escape(:), start=[1, tslot], count=[NDIM,1]), "netcdf_io_read_hdr_system nf90_getvar L_escape_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%L_escape_varid, self%L_escape(:), & + start=[1, tslot], count=[NDIM,1]), & + "netcdf_io_read_hdr_system nf90_getvar L_escape_varid" ) status = nf90_inq_varid(nc%id, nc%E_collisions_varname, nc%E_collisions_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%E_collisions_varid, self%E_collisions, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar E_collisions_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%E_collisions_varid, self%E_collisions, & + start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar E_collisions_varid" ) status = nf90_inq_varid(nc%id, nc%E_untracked_varname, nc%E_untracked_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%E_untracked_varid, self%E_untracked, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar E_untracked_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%E_untracked_varid, self%E_untracked, & + start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar E_untracked_varid" ) status = nf90_inq_varid(nc%id, nc%GMescape_varname, nc%GMescape_varid) - if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%GMescape_varid, self%GMescape, start=[tslot]), "netcdf_io_read_hdr_system nf90_getvar GMescape_varid" ) + if (status == NF90_NOERR) call netcdf_io_check( nf90_get_var(nc%id, nc%GMescape_varid, self%GMescape, start=[tslot]), & + "netcdf_io_read_hdr_system nf90_getvar GMescape_varid" ) end if end associate @@ -1428,11 +1620,13 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, !! Reads particle information metadata from file implicit none ! Arguments - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object + class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - logical, dimension(:), intent(in) :: plmask !! Logical array indicating which index values belong to massive bodies - logical, dimension(:), intent(in) :: tpmask !! Logical array indicating which index values belong to test particles + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + logical, dimension(:), intent(in) :: plmask !! Logical array indicating which index values belong to massive + !! bodies + logical, dimension(:), intent(in) :: tpmask !! Logical array indicating which index values belong to test + !! particles ! Internals integer(I4B) :: i, idmax, status @@ -1470,7 +1664,7 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, tpind(:) = pack([(i, i = 1, idmax)], tpmask(:)) end if - call netcdf_io_check( nf90_get_var(nc%id, nc%id_varid, itemp), "netcdf_io_read_particle_info_system nf90_getvar id_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%id_varid, itemp), "netcdf_io_read_particle_info_system nf90_getvar id_varid") cb%id = itemp(1) pl%id(:) = pack(itemp, plmask) tp%id(:) = pack(itemp, tpmask) @@ -1478,7 +1672,8 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, pl%id(:) = pack([(i,i=0,idmax-1)],plmask) tp%id(:) = pack([(i,i=0,idmax-1)],tpmask) - call netcdf_io_check( nf90_get_var(nc%id, nc%name_varid, ctemp, count=[NAMELEN, idmax]), "netcdf_io_read_particle_info_system nf90_getvar name_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%name_varid, ctemp, count=[NAMELEN, idmax]), & + "netcdf_io_read_particle_info_system nf90_getvar name_varid" ) call cb%info%set_value(name=ctemp(1)) do i = 1, npl call pl%info(i)%set_value(name=ctemp(plind(i))) @@ -1517,7 +1712,8 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, if (param%lclose) then status = nf90_inq_varid(nc%id, nc%origin_type_varname, nc%origin_type_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%origin_type_varid, ctemp, count=[NAMELEN, idmax]), "netcdf_io_read_particle_info_system nf90_getvar origin_type_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%origin_type_varid, ctemp, count=[NAMELEN, idmax]), & + "netcdf_io_read_particle_info_system nf90_getvar origin_type_varid" ) else ctemp = "Initial Conditions" end if @@ -1532,7 +1728,8 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, status = nf90_inq_varid(nc%id, nc%origin_time_varname, nc%origin_time_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%origin_time_varid, rtemp), "netcdf_io_read_particle_info_system nf90_getvar origin_time_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%origin_time_varid, rtemp), & + "netcdf_io_read_particle_info_system nf90_getvar origin_time_varid" ) else rtemp = param%t0 end if @@ -1547,9 +1744,11 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, status = nf90_inq_varid(nc%id, nc%origin_rh_varname, nc%origin_rh_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%origin_rh_varid, vectemp(:,:)), "netcdf_io_read_particle_info_system nf90_getvar origin_rh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%origin_rh_varid, vectemp(:,:)), & + "netcdf_io_read_particle_info_system nf90_getvar origin_rh_varid" ) else if ((param%out_form == "XV") .or. (param%out_form == "XVEL")) then - call netcdf_io_check( nf90_get_var(nc%id, nc%rh_varid, vectemp(:,:)), "netcdf_io_read_particle_info_system nf90_getvar rh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%rh_varid, vectemp(:,:)), & + "netcdf_io_read_particle_info_system nf90_getvar rh_varid" ) else vectemp(:,:) = 0._DP end if @@ -1563,9 +1762,11 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, status = nf90_inq_varid(nc%id, nc%origin_vh_varname, nc%origin_vh_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%origin_vh_varid, vectemp(:,:)), "netcdf_io_read_particle_info_system nf90_getvar origin_vh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%origin_vh_varid, vectemp(:,:)), & + "netcdf_io_read_particle_info_system nf90_getvar origin_vh_varid" ) else if ((param%out_form == "XV") .or. (param%out_form == "XVEL")) then - call netcdf_io_check( nf90_get_var(nc%id, nc%vh_varid, vectemp(:,:)), "netcdf_io_read_particle_info_system nf90_getvar vh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%vh_varid, vectemp(:,:)), & + "netcdf_io_read_particle_info_system nf90_getvar vh_varid" ) else vectemp(:,:) = 0._DP end if @@ -1579,7 +1780,8 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, status = nf90_inq_varid(nc%id, nc%collision_id_varname, nc%collision_id_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%collision_id_varid, itemp), "netcdf_io_read_particle_info_system nf90_getvar collision_id_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%collision_id_varid, itemp), & + "netcdf_io_read_particle_info_system nf90_getvar collision_id_varid" ) do i = 1, npl call pl%info(i)%set_value(collision_id=itemp(plind(i))) end do @@ -1590,7 +1792,8 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, status = nf90_inq_varid(nc%id, nc%discard_time_varname, nc%discard_time_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%discard_time_varid, rtemp), "netcdf_io_read_particle_info_system nf90_getvar discard_time_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%discard_time_varid, rtemp), & + "netcdf_io_read_particle_info_system nf90_getvar discard_time_varid" ) call cb%info%set_value(discard_time=rtemp(1)) do i = 1, npl call pl%info(i)%set_value(discard_time=rtemp(plind(i))) @@ -1602,7 +1805,8 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, status = nf90_inq_varid(nc%id, nc%discard_rh_varname, nc%discard_rh_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%discard_rh_varid, vectemp(:,:)), "netcdf_io_read_particle_info_system nf90_getvar discard_rh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%discard_rh_varid, vectemp(:,:)), & + "netcdf_io_read_particle_info_system nf90_getvar discard_rh_varid" ) do i = 1, npl call pl%info(i)%set_value(discard_rh=vectemp(:,plind(i))) end do @@ -1613,7 +1817,8 @@ module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, status = nf90_inq_varid(nc%id, nc%discard_vh_varname, nc%discard_vh_varid) if (status == NF90_NOERR) then - call netcdf_io_check( nf90_get_var(nc%id, nc%discard_vh_varid, vectemp(:,:)), "netcdf_io_read_particle_info_system nf90_getvar discard_vh_varid" ) + call netcdf_io_check( nf90_get_var(nc%id, nc%discard_vh_varid, vectemp(:,:)), & + "netcdf_io_read_particle_info_system nf90_getvar discard_vh_varid" ) do i = 1, npl call pl%info(i)%set_value(discard_vh=vectemp(:,plind(i))) end do @@ -1642,7 +1847,8 @@ module subroutine swiftest_io_netcdf_write_frame_body(self, nc, param) ! Internals integer(I4B) :: i, j, idslot, old_mode, tmp integer(I4B), dimension(:), allocatable :: ind - real(DP), dimension(NDIM) :: vh !! Temporary variable to store heliocentric velocity values when converting from pseudovelocity in GR-enabled runs + real(DP), dimension(NDIM) :: vh !! Temporary variable to store heliocentric velocity values when converting + !! from pseudovelocity in GR-enabled runs real(DP) :: a, e, inc, omega, capom, capm, varpi, lam, f, cape, capf #ifdef COARRAY integer(I4B) :: ntp @@ -1664,22 +1870,29 @@ module subroutine swiftest_io_netcdf_write_frame_body(self, nc, param) do i = 1, n j = ind(i) call nc%find_idslot(self%id(j), idslot) - !! Convert from pseudovelocity to heliocentric without replacing the current value of pseudovelocity + ! Convert from pseudovelocity to heliocentric without replacing the current value of pseudovelocity if (param%lgr) call swiftest_gr_pseudovel2vel(param, self%mu(j), self%rh(:, j), self%vh(:, j), vh(:)) if ((param%out_form == "XV") .or. (param%out_form == "XVEL")) then - call netcdf_io_check( nf90_put_var(nc%id, nc%rh_varid, self%rh(:, j), start=[1,idslot, tslot], count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var rh_varid" ) - if (param%lgr) then !! Convert from pseudovelocity to heliocentric without replacing the current value of pseudovelocity - call netcdf_io_check( nf90_put_var(nc%id, nc%vh_varid, vh(:), start=[1,idslot, tslot], count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var vh_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%gr_pseudo_vh_varid, self%vh(:, j), start=[1,idslot, tslot],count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var gr_pseudo_vhx_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%rh_varid, self%rh(:, j), start=[1,idslot, tslot], count=[NDIM,1,1]),& + "netcdf_io_write_frame_body nf90_put_var rh_varid" ) + if (param%lgr) then ! Convert from pseudovelocity to heliocentric without replacing the current value of + ! pseudovelocity + call netcdf_io_check( nf90_put_var(nc%id, nc%vh_varid, vh(:), start=[1,idslot, tslot], count=[NDIM,1,1]), & + "netcdf_io_write_frame_body nf90_put_var vh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%gr_pseudo_vh_varid, self%vh(:, j), start=[1,idslot, tslot], & + count=[NDIM,1,1]), & + "netcdf_io_write_frame_body nf90_put_var gr_pseudo_vhx_varid" ) else - call netcdf_io_check( nf90_put_var(nc%id, nc%vh_varid, self%vh(:, j), start=[1,idslot, tslot], count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var vh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%vh_varid, self%vh(:, j), start=[1,idslot, tslot], & + count=[NDIM,1,1]), & + "netcdf_io_write_frame_body nf90_put_var vh_varid" ) end if end if if ((param%out_form == "EL") .or. (param%out_form == "XVEL")) then - if (param%lgr) then !! For GR-enabled runs, use the true value of velocity computed above + if (param%lgr) then ! For GR-enabled runs, use the true value of velocity computed above call swiftest_orbel_xv2el(self%mu(j), self%rh(1,j), self%rh(2,j), self%rh(3,j), & vh(1), vh(2), vh(3), & a, e, inc, capom, omega, capm, varpi, lam, f, cape, capf) @@ -1688,48 +1901,78 @@ module subroutine swiftest_io_netcdf_write_frame_body(self, nc, param) self%vh(1,j), self%vh(2,j), self%vh(3,j), & a, e, inc, capom, omega, capm, varpi, lam, f, cape, capf) end if - call netcdf_io_check( nf90_put_var(nc%id, nc%a_varid, a, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body a_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%e_varid, e, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body e_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%inc_varid, inc * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body inc_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%capom_varid, capom * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body capom_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%omega_varid, omega * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body omega_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%capm_varid, capm * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body capm_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%varpi_varid, varpi * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body varpi_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%lam_varid, lam * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body lam_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%f_varid, f * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body f_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%a_varid, a, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body a_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%e_varid, e, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body e_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%inc_varid, inc * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body inc_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%capom_varid, capom * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body capom_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%omega_varid, omega * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body omega_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%capm_varid, capm * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body capm_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%varpi_varid, varpi * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body varpi_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%lam_varid, lam * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body lam_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%f_varid, f * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body f_varid" ) if (e < 1.0_DP) then - call netcdf_io_check( nf90_put_var(nc%id, nc%cape_varid, cape * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body cape_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%cape_varid, cape * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body cape_varid" ) else if (e > 1.0_DP) then - call netcdf_io_check( nf90_put_var(nc%id, nc%cape_varid, capf * RAD2DEG, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body (capf) cape_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%cape_varid, capf * RAD2DEG, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body (capf) cape_varid" ) end if end if select type(self) class is (swiftest_pl) ! Additional output if the passed polymorphic object is a massive body - call netcdf_io_check( nf90_put_var(nc%id, nc%Gmass_varid, self%Gmass(j), start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body Gmass_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%mass_varid, self%mass(j), start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body mass_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%Gmass_varid, self%Gmass(j), start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body Gmass_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%mass_varid, self%mass(j), start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body mass_varid" ) if (param%lrhill_present) then - call netcdf_io_check( nf90_put_var(nc%id, nc%rhill_varid, self%rhill(j), start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body rhill_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%rhill_varid, self%rhill(j), start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body rhill_varid" ) end if - if (param%lclose) call netcdf_io_check( nf90_put_var(nc%id, nc%radius_varid, self%radius(j), start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body radius_varid" ) + if (param%lclose) call netcdf_io_check( nf90_put_var(nc%id, nc%radius_varid, self%radius(j), & + start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body radius_varid" ) if (param%lrotation) then - call netcdf_io_check( nf90_put_var(nc%id, nc%Ip_varid, self%Ip(:, j), start=[1,idslot, tslot], count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var body Ip_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%rot_varid, self%rot(:, j) * RAD2DEG, start=[1,idslot, tslot], count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var body rotx_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%Ip_varid, self%Ip(:, j), start=[1,idslot, tslot], & + count=[NDIM,1,1]), & + "netcdf_io_write_frame_body nf90_put_var body Ip_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%rot_varid, self%rot(:, j) * RAD2DEG, start=[1,idslot, tslot], & + count=[NDIM,1,1]), & + "netcdf_io_write_frame_body nf90_put_var body rotx_varid" ) end if ! if (param%ltides) then - ! call netcdf_io_check( nf90_put_var(nc%id, nc%k2_varid, self%k2(j), start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body k2_varid" ) - ! call netcdf_io_check( nf90_put_var(nc%id, nc%Q_varid, self%Q(j), start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body Q_varid" ) + ! call netcdf_io_check( nf90_put_var(nc%id, nc%k2_varid, self%k2(j), start=[idslot, tslot]), & + ! "netcdf_io_write_frame_body nf90_put_var body k2_varid" ) + ! call netcdf_io_check( nf90_put_var(nc%id, nc%Q_varid, self%Q(j), start=[idslot, tslot]), & + ! "netcdf_io_write_frame_body nf90_put_var body Q_varid" ) ! end if class is (swiftest_tp) - call netcdf_io_check( nf90_put_var(nc%id, nc%Gmass_varid, 0.0_DP, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body Gmass_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%mass_varid, 0.0_DP, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body mass_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%Gmass_varid, 0.0_DP, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body Gmass_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%mass_varid, 0.0_DP, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body mass_varid" ) if (param%lrhill_present) then - call netcdf_io_check( nf90_put_var(nc%id, nc%rhill_varid, 0.0_DP, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body rhill_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%rhill_varid, 0.0_DP, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body rhill_varid" ) end if - if (param%lclose) call netcdf_io_check( nf90_put_var(nc%id, nc%radius_varid, 0.0_DP, start=[idslot, tslot]), "netcdf_io_write_frame_body nf90_put_var body radius_varid" ) + if (param%lclose) call netcdf_io_check( nf90_put_var(nc%id, nc%radius_varid, 0.0_DP, start=[idslot, tslot]), & + "netcdf_io_write_frame_body nf90_put_var body radius_varid" ) if (param%lrotation) then - call netcdf_io_check( nf90_put_var(nc%id, nc%Ip_varid, [0.0_DP,0.0_DP,0.0_DP], start=[1,idslot, tslot], count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var body Ip_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%rot_varid, [0.0_DP,0.0_DP,0.0_DP], start=[1,idslot, tslot], count=[NDIM,1,1]), "netcdf_io_write_frame_body nf90_put_var body rotx_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%Ip_varid, [0.0_DP,0.0_DP,0.0_DP], start=[1,idslot, tslot], & + count=[NDIM,1,1]), & + "netcdf_io_write_frame_body nf90_put_var body Ip_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%rot_varid, [0.0_DP,0.0_DP,0.0_DP], start=[1,idslot, tslot], & + count=[NDIM,1,1]), & + "netcdf_io_write_frame_body nf90_put_var body rotx_varid" ) end if end select end do @@ -1741,11 +1984,13 @@ module subroutine swiftest_io_netcdf_write_frame_body(self, nc, param) class is (swiftest_tp) call nc%get_valid_masks(plmask, tpmask) ntp = count(tpmask(:)) - call netcdf_io_check( nf90_put_var(nc%id, nc%ntp_varid, ntp, start=[nc%tslot]), "netcdf_io_write_frame_body nf90_put_var ntp_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%ntp_varid, ntp, start=[nc%tslot]), & + "netcdf_io_write_frame_body nf90_put_var ntp_varid" ) end select #endif - call netcdf_io_check( nf90_set_fill(nc%id, old_mode, tmp), "netcdf_io_write_frame_body nf90_set_fill old_mode" ) + call netcdf_io_check( nf90_set_fill(nc%id, old_mode, tmp), & + "netcdf_io_write_frame_body nf90_set_fill old_mode" ) return end subroutine swiftest_io_netcdf_write_frame_body @@ -1766,23 +2011,35 @@ module subroutine swiftest_io_netcdf_write_frame_cb(self, nc, param) associate(tslot => nc%tslot) call self%write_info(nc, param) - call netcdf_io_check( nf90_set_fill(nc%id, NF90_NOFILL, old_mode), "swiftest_io_netcdf_write_frame_cb nf90_set_fill" ) + call netcdf_io_check( nf90_set_fill(nc%id, NF90_NOFILL, old_mode), & + "swiftest_io_netcdf_write_frame_cb nf90_set_fill" ) call nc%find_idslot(self%id, idslot) - call netcdf_io_check( nf90_put_var(nc%id, nc%id_varid, self%id, start=[idslot]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb id_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%status_varid, ACTIVE, start=[idslot, tslot]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb id_varid" ) - - call netcdf_io_check( nf90_put_var(nc%id, nc%Gmass_varid, self%Gmass, start=[idslot, tslot]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb Gmass_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%mass_varid, self%mass, start=[idslot, tslot]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb mass_varid" ) - if (param%lclose) call netcdf_io_check( nf90_put_var(nc%id, nc%radius_varid, self%radius, start=[idslot, tslot]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb radius_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%j2rp2_varid, self%j2rp2, start=[tslot]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb j2rp2_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%j4rp4_varid, self%j4rp4, start=[tslot]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb j4rp4_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%id_varid, self%id, start=[idslot]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb id_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%status_varid, ACTIVE, start=[idslot, tslot]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb id_varid" ) + + call netcdf_io_check( nf90_put_var(nc%id, nc%Gmass_varid, self%Gmass, start=[idslot, tslot]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb Gmass_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%mass_varid, self%mass, start=[idslot, tslot]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb mass_varid" ) + if (param%lclose) call netcdf_io_check( nf90_put_var(nc%id, nc%radius_varid, self%radius, start=[idslot, tslot]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb radius_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%j2rp2_varid, self%j2rp2, start=[tslot]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb j2rp2_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%j4rp4_varid, self%j4rp4, start=[tslot]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb j4rp4_varid" ) if (param%lrotation) then - call netcdf_io_check( nf90_put_var(nc%id, nc%Ip_varid, self%Ip(:), start=[1, idslot, tslot], count=[NDIM,1,1]), "swiftest_io_netcdf_write_frame_cb nf90_put_var cb Ip_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%rot_varid, self%rot(:) * RAD2DEG, start=[1, idslot, tslot], count=[NDIM,1,1]), "swiftest_io_netcdf_write_frame_cby nf90_put_var cb rot_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%Ip_varid, self%Ip(:), start=[1, idslot, tslot], count=[NDIM,1,1]), & + "swiftest_io_netcdf_write_frame_cb nf90_put_var cb Ip_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%rot_varid, self%rot(:) * RAD2DEG, start=[1, idslot, tslot], & + count=[NDIM,1,1]), & + "swiftest_io_netcdf_write_frame_cby nf90_put_var cb rot_varid" ) end if - call netcdf_io_check( nf90_set_fill(nc%id, old_mode, tmp), "swiftest_io_netcdf_write_frame_cb nf90_set_fill old_mode" ) + call netcdf_io_check( nf90_set_fill(nc%id, old_mode, tmp), & + "swiftest_io_netcdf_write_frame_cb nf90_set_fill old_mode" ) end associate return @@ -1818,8 +2075,8 @@ module subroutine swiftest_io_netcdf_write_hdr_system(self, nc, param) !! author: David A. Minton !! !! Writes header information (variables that change with time, but not particle id). - !! This subroutine swiftest_significantly improves the output over the original binary file, allowing us to track energy, momentum, and other quantities that - !! previously were handled as separate output files. + !! This subroutine swiftest_significantly improves the output over the original binary file, allowing us to track energy, + !! momentum, and other quantities that previously were handled as separate output files. implicit none ! Arguments class(swiftest_nbody_system), intent(in) :: self !! Swiftest nbody system object @@ -1829,25 +2086,40 @@ module subroutine swiftest_io_netcdf_write_hdr_system(self, nc, param) integer(I4B) :: tslot call nc%find_tslot(self%t, tslot) - call netcdf_io_check( nf90_put_var(nc%id, nc%time_varid, self%t, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var time_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%npl_varid, self%pl%nbody, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var npl_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%time_varid, self%t, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var time_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%npl_varid, self%pl%nbody, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var npl_varid" ) #ifndef COARRAY - call netcdf_io_check( nf90_put_var(nc%id, nc%ntp_varid, self%tp%nbody, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var ntp_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%ntp_varid, self%tp%nbody, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var ntp_varid" ) #endif - if (param%lmtiny_pl) call netcdf_io_check( nf90_put_var(nc%id, nc%nplm_varid, self%pl%nplm, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var nplm_varid" ) + if (param%lmtiny_pl) call netcdf_io_check( nf90_put_var(nc%id, nc%nplm_varid, self%pl%nplm, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var nplm_varid" ) if (param%lenergy) then - call netcdf_io_check( nf90_put_var(nc%id, nc%KE_orb_varid, self%ke_orbit, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var KE_orb_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%KE_spin_varid, self%ke_spin, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var KE_spin_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%PE_varid, self%pe, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var PE_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%BE_varid, self%be, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var BE_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%TE_varid, self%te, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var TE_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%L_orbit_varid, self%L_orbit(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_write_hdr_system nf90_put_var L_orbit_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%L_spin_varid, self%L_spin(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_write_hdr_system nf90_put_var L_spin_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%L_escape_varid, self%L_escape(:), start=[1,tslot], count=[NDIM,1]), "netcdf_io_write_hdr_system nf90_put_var L_escape_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%E_collisions_varid, self%E_collisions, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var E_collisions_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%E_untracked_varid, self%E_untracked, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var E_untracked_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%GMescape_varid, self%GMescape, start=[tslot]), "netcdf_io_write_hdr_system nf90_put_var GMescape_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%KE_orb_varid, self%ke_orbit, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var KE_orb_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%KE_spin_varid, self%ke_spin, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var KE_spin_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%PE_varid, self%pe, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var PE_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%BE_varid, self%be, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var BE_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%TE_varid, self%te, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var TE_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%L_orbit_varid, self%L_orbit(:), start=[1,tslot], count=[NDIM,1]), & + "netcdf_io_write_hdr_system nf90_put_var L_orbit_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%L_spin_varid, self%L_spin(:), start=[1,tslot], count=[NDIM,1]), & + "netcdf_io_write_hdr_system nf90_put_var L_spin_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%L_escape_varid, self%L_escape(:), start=[1,tslot], count=[NDIM,1]), & + "netcdf_io_write_hdr_system nf90_put_var L_escape_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%E_collisions_varid, self%E_collisions, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var E_collisions_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%E_untracked_varid, self%E_untracked, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var E_untracked_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%GMescape_varid, self%GMescape, start=[tslot]), & + "netcdf_io_write_hdr_system nf90_put_var GMescape_varid" ) end if return @@ -1869,7 +2141,8 @@ module subroutine swiftest_io_netcdf_write_info_body(self, nc, param) character(len=NAMELEN) :: charstring character(len=NAMELEN), dimension(self%nbody) :: origin_type - call netcdf_io_check( nf90_set_fill(nc%id, NF90_NOFILL, old_mode), "netcdf_io_write_info_body nf90_set_fill NF90_NOFILL" ) + call netcdf_io_check( nf90_set_fill(nc%id, NF90_NOFILL, old_mode), & + "netcdf_io_write_info_body nf90_set_fill NF90_NOFILL" ) select type(self) class is (swiftest_body) @@ -1881,27 +2154,44 @@ module subroutine swiftest_io_netcdf_write_info_body(self, nc, param) do i = 1, n j = ind(i) call nc%find_idslot(self%id(j), idslot) - call netcdf_io_check( nf90_put_var(nc%id, nc%id_varid, self%id(j), start=[idslot]), "netcdf_io_write_info_body nf90_put_var id_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%status_varid, self%status(j), start=[idslot,tslot]), "netcdf_io_write_info_body nf90_put_var status_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%id_varid, self%id(j), start=[idslot]), & + "netcdf_io_write_info_body nf90_put_var id_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%status_varid, self%status(j), start=[idslot,tslot]), & + "netcdf_io_write_info_body nf90_put_var status_varid" ) charstring = trim(adjustl(self%info(j)%name)) - call netcdf_io_check( nf90_put_var(nc%id, nc%name_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), "netcdf_io_write_info_body nf90_put_var name_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%name_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), & + "netcdf_io_write_info_body nf90_put_var name_varid" ) charstring = trim(adjustl(self%info(j)%particle_type)) - call netcdf_io_check( nf90_put_var(nc%id, nc%ptype_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), "netcdf_io_write_info_body nf90_put_var particle_type_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%ptype_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), & + "netcdf_io_write_info_body nf90_put_var particle_type_varid" ) if (param%lclose) then charstring = trim(adjustl(self%info(j)%origin_type)) origin_type(i) = charstring - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_type_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), "netcdf_io_write_info_body nf90_put_var origin_type_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_time_varid, self%info(j)%origin_time, start=[idslot]), "netcdf_io_write_info_body nf90_put_var origin_time_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_rh_varid, self%info(j)%origin_rh(:), start=[1,idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var origin_rh_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_vh_varid, self%info(j)%origin_vh(:), start=[1,idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var origin_vh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_type_varid, charstring, start=[1, idslot], & + count=[NAMELEN, 1]), & + "netcdf_io_write_info_body nf90_put_var origin_type_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_time_varid, self%info(j)%origin_time, start=[idslot]), & + "netcdf_io_write_info_body nf90_put_var origin_time_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_rh_varid, self%info(j)%origin_rh(:), start=[1,idslot], & + count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var origin_rh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_vh_varid, self%info(j)%origin_vh(:), start=[1,idslot], & + count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var origin_vh_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%collision_id_varid, self%info(j)%collision_id, start=[idslot]), "netcdf_io_write_info_body nf90_put_var collision_id_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%discard_time_varid, self%info(j)%discard_time, start=[idslot]), "netcdf_io_write_info_body nf90_put_var discard_time_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%discard_rh_varid, self%info(j)%discard_rh(:), start=[1,idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var discard_rh_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%discard_vh_varid, self%info(j)%discard_vh(:), start=[1,idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var discard_vh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%collision_id_varid, self%info(j)%collision_id, start=[idslot]), & + "netcdf_io_write_info_body nf90_put_var collision_id_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%discard_time_varid, self%info(j)%discard_time, start=[idslot]), & + "netcdf_io_write_info_body nf90_put_var discard_time_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%discard_rh_varid, self%info(j)%discard_rh(:), start=[1,idslot], & + count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var discard_rh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%discard_vh_varid, self%info(j)%discard_vh(:), start=[1,idslot], & + count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var discard_vh_varid" ) end if end do @@ -1926,30 +2216,44 @@ module subroutine swiftest_io_netcdf_write_info_cb(self, nc, param) character(len=NAMELEN) :: charstring ! This string of spaces of length NAMELEN is used to clear out any old data left behind inside the string variables - call netcdf_io_check( nf90_set_fill(nc%id, NF90_NOFILL, old_mode), "netcdf_io_write_info_cb nf90_set_fill NF90_NOFILL" ) + call netcdf_io_check( nf90_set_fill(nc%id, NF90_NOFILL, old_mode), & + "netcdf_io_write_info_cb nf90_set_fill NF90_NOFILL" ) call nc%find_idslot(self%id, idslot) - call netcdf_io_check( nf90_put_var(nc%id, nc%id_varid, self%id, start=[idslot]), "netcdf_io_write_info_cb nf90_put_var id_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%id_varid, self%id, start=[idslot]), & + "netcdf_io_write_info_cb nf90_put_var id_varid" ) charstring = trim(adjustl(self%info%name)) - call netcdf_io_check( nf90_put_var(nc%id, nc%name_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), "netcdf_io_write_info_cb nf90_put_var name_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%name_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), & + "netcdf_io_write_info_cb nf90_put_var name_varid" ) charstring = trim(adjustl(self%info%particle_type)) - call netcdf_io_check( nf90_put_var(nc%id, nc%ptype_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), "netcdf_io_write_info_cb nf90_put_var ptype_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%ptype_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), & + "netcdf_io_write_info_cb nf90_put_var ptype_varid" ) if (param%lclose) then charstring = trim(adjustl(self%info%origin_type)) - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_type_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), "netcdf_io_write_info_body nf90_put_var cb origin_type_varid" ) - - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_time_varid, self%info%origin_time, start=[idslot]), "netcdf_io_write_info_body nf90_put_var cb origin_time_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_rh_varid, self%info%origin_rh(:), start=[1, idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var cb origin_rh_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%origin_vh_varid, self%info%origin_vh(:), start=[1, idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var cb origin_vh_varid" ) - - call netcdf_io_check( nf90_put_var(nc%id, nc%collision_id_varid, self%info%collision_id, start=[idslot]), "netcdf_io_write_info_body nf90_put_var cb collision_id_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%discard_time_varid, self%info%discard_time, start=[idslot]), "netcdf_io_write_info_body nf90_put_var cb discard_time_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%discard_rh_varid, self%info%discard_rh(:), start=[1, idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var cb discard_rh_varid" ) - call netcdf_io_check( nf90_put_var(nc%id, nc%discard_vh_varid, self%info%discard_vh(:), start=[1, idslot], count=[NDIM,1]), "netcdf_io_write_info_body nf90_put_var cb discard_vh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_type_varid, charstring, start=[1, idslot], count=[NAMELEN, 1]), & + "netcdf_io_write_info_body nf90_put_var cb origin_type_varid" ) + + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_time_varid, self%info%origin_time, start=[idslot]), & + "netcdf_io_write_info_body nf90_put_var cb origin_time_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_rh_varid, self%info%origin_rh(:), start=[1, idslot], count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var cb origin_rh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%origin_vh_varid, self%info%origin_vh(:), start=[1, idslot], count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var cb origin_vh_varid" ) + + call netcdf_io_check( nf90_put_var(nc%id, nc%collision_id_varid, self%info%collision_id, start=[idslot]), & + "netcdf_io_write_info_body nf90_put_var cb collision_id_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%discard_time_varid, self%info%discard_time, start=[idslot]), & + "netcdf_io_write_info_body nf90_put_var cb discard_time_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%discard_rh_varid, self%info%discard_rh(:), start=[1, idslot], & + count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var cb discard_rh_varid" ) + call netcdf_io_check( nf90_put_var(nc%id, nc%discard_vh_varid, self%info%discard_vh(:), start=[1, idslot], & + count=[NDIM,1]), & + "netcdf_io_write_info_body nf90_put_var cb discard_vh_varid" ) end if call netcdf_io_check( nf90_set_fill(nc%id, old_mode, tmp) ) @@ -1990,8 +2294,10 @@ module subroutine swiftest_io_param_reader(self, unit, iotype, v_list, iostat, i ! Arguments class(swiftest_parameters), intent(inout) :: self !! Collection of parameters integer(I4B), intent(in) :: unit !! File unit number - character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT. - !! If you do not include a char-literal-constant, the iotype argument contains only DT. + character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the + !! text from the char-literal-constant, prefixed with DT. + !! If you do not include a char-literal-constant, the iotype + !! argument contains only DT. character(len=*), intent(in) :: v_list(:) !! The first element passes the integrator code to the reader integer(I4B), intent(out) :: iostat !! IO status code character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0 @@ -2195,8 +2501,9 @@ module subroutine swiftest_io_param_reader(self, unit, iotype, v_list, iostat, i if (param_value == "YES" .or. param_value == 'T') param%lcoarray = .true. case("SEED") read(param_value, *) nseeds_from_file - ! Because the number of seeds can vary between compilers/systems, we need to make sure we can handle cases in which the input file has a different - ! number of seeds than the current nbody_system. If the number of seeds in the file is smaller than required, we will use them as a source to fill in the missing elements. + ! Because the number of seeds can vary between compilers/systems, we need to make sure we can handle cases in + ! which the input file has a different number of seeds than the current nbody_system. If the number of seeds in + ! the file is smaller than required, we will use them as a source to fill in the missing elements. ! If the number of seeds in the file is larger than required, we will truncate the seed array. if (nseeds_from_file > nseeds) then nseeds = nseeds_from_file @@ -2447,7 +2754,8 @@ module subroutine swiftest_io_param_reader(self, unit, iotype, v_list, iostat, i select case(param%integrator) case(INT_WHM, INT_RMVS, INT_HELIO) case default - write(iomsg, *) "Coarray-based parallelization of test particles are not compatible with this integrator. This parameter will be ignored." + write(iomsg, *) "Coarray-based parallelization of test particles are not compatible with this integrator. " & + // "This parameter will be ignored." param%lcoarray = .false. end select #else @@ -2496,7 +2804,8 @@ module subroutine swiftest_io_param_reader(self, unit, iotype, v_list, iostat, i function time_stretcher(fstep_out) result(ans) !! author: David A. Minton !! - !! Equation for the time stretchinf function. Solving the roots of this equation gives the time stretching factor for non-linear file output cadence. + !! Equation for the time stretchinf function. Solving the roots of this equation gives the time stretching factor for + !! non-linear file output cadence. implicit none ! Arguments real(DP), intent(in) :: fstep_out @@ -2524,10 +2833,12 @@ module subroutine swiftest_io_param_writer(self, unit, iotype, v_list, iostat, i !! Adapted from Martin Duncan's Swift routine io_param_restart.f implicit none ! Arguments - class(swiftest_parameters),intent(in) :: self !! Collection of parameters + class(swiftest_parameters),intent(in) :: self !! Collection of parameters integer, intent(in) :: unit !! File unit number - character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT. - !! If you do not include a char-literal-constant, the iotype argument contains only DT. + character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the + !! text from the char-literal-constant, prefixed with DT. + !! If you do not include a char-literal-constant, the iotype + !! argument contains only DT. integer, intent(in) :: v_list(:) !! Not used in this procedure integer, intent(out) :: iostat !! IO status code character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0 @@ -3207,7 +3518,7 @@ module subroutine swiftest_io_initialize_output_file_system(self, nc, param) call nc%open(param) case('NEW') if (fileExists) then - errmsg = trim(adjustl(param%outfile)) // " already exists! You must specify OUT_STAT = APPEND, REPLACE, or UNKNOWN" + errmsg = trim(adjustl(param%outfile))// " already exists! You must specify OUT_STAT = APPEND, REPLACE, or UNKNOWN" goto 667 end if call nc%initialize(param) diff --git a/src/swiftest/swiftest_kick.f90 b/src/swiftest/swiftest_kick.f90 index d0700d321..cfd9ef54c 100644 --- a/src/swiftest/swiftest_kick.f90 +++ b/src/swiftest/swiftest_kick.f90 @@ -191,7 +191,7 @@ module subroutine swiftest_kick_getacch_int_all_tri_rad_pl(npl, nplm, r, Gmass, ahj(:,:) = 0.0_DP !$omp parallel do default(private) schedule(static)& !$omp shared(npl, nplm, r, Gmass, radius) & - !$omp reduction(+:ahi,j) + !$omp reduction(+:ahi,ahj) do i = 1, nplm #ifdef DOCONLOC do concurrent(j = i+1:npl) shared(i,r,radius,ahi,ahj,Gmass) local(rx,ry,rz,rji2,rlim2) diff --git a/swiftest/CMakeLists.txt b/swiftest/CMakeLists.txt index 1925932b4..45f02ca0d 100644 --- a/swiftest/CMakeLists.txt +++ b/swiftest/CMakeLists.txt @@ -9,22 +9,32 @@ SET(SWIFTEST_BINDINGS _bindings) -FIND_PROGRAM(CYTHON "cython") +# Find the Cython executable, but don't look in the cmake root directory (due how cmake and cython are installed on the RCAC system) +FIND_PROGRAM(CYTHON + NAMES "cython" + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_FIND_ROOT_PATH + ) +MESSAGE(STATUS "Cython executable path: ${CYTHON}") +SET(CYTHON_ARGS "${CMAKE_CURRENT_SOURCE_DIR}/${SWIFTEST_BINDINGS}.pyx" "--output-file" "${CMAKE_CURRENT_BINARY_DIR}/${SWIFTEST_BINDINGS}.c") +STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT) +IF (BT STREQUAL "DEBUG") + LIST(APPEND CYTHON_ARGS "--gdb") +endif () ADD_CUSTOM_COMMAND( OUTPUT "${SWIFTEST_BINDINGS}.c" DEPENDS "${SWIFTEST_BINDINGS}.pyx" VERBATIM - COMMAND "${CYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/${SWIFTEST_BINDINGS}.pyx" --output-file - "${CMAKE_CURRENT_BINARY_DIR}/${SWIFTEST_BINDINGS}.c") + COMMAND "${CYTHON}" ${CYTHON_ARGS} ) PYTHON_ADD_LIBRARY(${SWIFTEST_BINDINGS} MODULE "${CMAKE_CURRENT_BINARY_DIR}/${SWIFTEST_BINDINGS}.c" WITH_SOABI) IF (NOT BUILD_SHARED_LIBS) SET_PROPERTY(TARGET ${SWIFTEST_BINDINGS} PROPERTY POSITION_INDEPENDENT_CODE) - TARGET_LINK_LIBRARIES(${SWIFTEST_BINDINGS} PUBLIC ${SWIFTEST_LIBRARY} ${NETCDF_LIBRARIES}) -ELSE () - TARGET_LINK_LIBRARIES(${SWIFTEST_BINDINGS} PUBLIC ${SWIFTEST_LIBRARY}) ENDIF () +TARGET_LINK_LIBRARIES(${SWIFTEST_BINDINGS} PUBLIC ${SWIFTEST_LIBRARY} netCDF::netcdff HDF5::HDF5) TARGET_INCLUDE_DIRECTORIES(${SWIFTEST_BINDINGS} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # Define the install locations diff --git a/swiftest/simulation_class.py b/swiftest/simulation_class.py index d6627c325..eee68f963 100644 --- a/swiftest/simulation_class.py +++ b/swiftest/simulation_class.py @@ -412,15 +412,16 @@ def run(self,dask: bool = False, **kwargs): if len(kwargs) > 0: self.set_parameter(**kwargs) - # Write out the current parameter set before executing run - self.write_param() - if self.codename != "Swiftest": warnings.warn(f"Running an integration is not yet supported for {self.codename}",stacklevel=2) return + # Save initial conditions if not self.restart: self.clean() + + # Write out the current parameter set before executing run + self.write_param(verbose=False,**kwargs) print(f"Running a {self.codename} {self.integrator} run from tstart={self.param['TSTART']} {self.TU_name} to tstop={self.param['TSTOP']} {self.TU_name}") @@ -2176,10 +2177,8 @@ def add_solar_system_body(self, dsnew = init_cond.vec2xr(self.param,**kwargs) dsnew = self._combine_and_fix_dsnew(dsnew) - if dsnew['npl'] > 0 or dsnew['ntp'] > 0: + if dsnew['id'].max(dim='name') > 0 and dsnew['name'].size > 0: self.save(verbose=False) - - self.init_cond = self.data.copy(deep=True) diff --git a/tests/.gitignore b/tests/.gitignore index bb2dc8eb5..1025d6c0a 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,3 +1,3 @@ !.gitignore -!test_*.py +!swiftest_tests.py simdata/** diff --git a/tests/test_input_output.py b/tests/test_input_output.py deleted file mode 100755 index 714104d12..000000000 --- a/tests/test_input_output.py +++ /dev/null @@ -1,333 +0,0 @@ -#!/usr/bin/env python3 - -""" - Copyright 2023 - David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, & Dana Singh - This file is part of Swiftest. - Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with Swiftest. - If not, see: https://www.gnu.org/licenses. -""" - -""" -Tests that energy and momentum errors are within tolerances in a Swiftest simulation - -Input ------- - -Output ------- -None -""" - -import swiftest -import unittest -import os -import shutil -import numpy as np -from numpy.random import default_rng - -rng = default_rng(seed=123) - -major_bodies = ["Sun","Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"] -param = {} - - -class TestSwiftest(unittest.TestCase): - - def test01_gen_ic(self): - """ - Tests that Swiftest is able to successfully generate a set of initial conditions in a file without any exceptions being raised - """ - print("\ntest_gen_ic: Test whether we can generate simulation initial conditions test") - # Files that are expected to be generated: - simdir = "simdata" - file_list = [simdir, os.path.join(simdir,"param.in"), os.path.join(simdir,"init_cond.nc")] - - sim = swiftest.Simulation() - sim.clean() -#!/usr/bin/env python3 - -""" - Copyright 2023 - David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, & Dana Singh - This file is part of Swiftest. - Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with Swiftest. - If not, see: https://www.gnu.org/licenses. -""" - -""" -Tests that energy and momentum errors are within tolerances in a Swiftest simulation - -Input ------- - -Output ------- -None -""" - -import swiftest -import unittest -import os -import shutil -import numpy as np -from numpy.random import default_rng - -rng = default_rng(seed=123) - -major_bodies = ["Sun","Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"] -param = {} - - -class TestSwiftest(unittest.TestCase): - - def test01_gen_ic(self): - """ - Tests that Swiftest is able to successfully generate a set of initial conditions in a file without any exceptions being raised - """ - print("\ntest_gen_ic: Test whether we can generate simulation initial conditions test") - # Files that are expected to be generated: - simdir = "simdata" - file_list = [simdir, os.path.join(simdir,"param.in"), os.path.join(simdir,"init_cond.nc")] - - sim = swiftest.Simulation() - sim.clean() - - # Add the modern planets and the Sun using the JPL Horizons Database. - # Add the modern planets and the Sun using the JPL Horizons Database. - sim.add_solar_system_body(major_bodies) - - # Display the run configuration parameters. - param = sim.get_parameter(verbose=False) - sim.save() - - for f in file_list: - self.assertTrue(os.path.exists(f)) - - def test02_read_ic(self): - """ - Tests that Swiftest is able to read a set of pre-existing initial conditions files and that they contain the correct data - """ - print("\ntest_read_ic: Test whether we can read back initial conditions files created by test_gen_ic") - sim = swiftest.Simulation(read_param=True) - # Check if all names in Dataset read in from file match the expected list of names - self.assertTrue((major_bodies == sim.init_cond['name']).all(), msg="Name mismatch in Dataset") - - # Check to see if all parameter values read in from file match the expected parameters saved when generating the file - self.assertTrue(all([v == param[k] for k,v in sim.param.items() if k in param])) - - def test03_integrators(self): - """ - Tests that Swiftest is able to integrate a collection of massive bodies and test particles with all available integrators - """ - print("\ntest_integrators: Tests that Swiftest is able to integrate a collection of massive bodies and test particles with all available integrators") - sim = swiftest.Simulation(read_param=True) - - # Add 10 user-defined test particles. - ntp = 10 - - name_tp = [f"TestParticle_{i:02}" for i in range(1,ntp+1)] - a_tp = rng.uniform(0.3, 1.5, ntp) - e_tp = rng.uniform(0.0, 0.2, ntp) - inc_tp = rng.uniform(0.0, 10, ntp) - capom_tp = rng.uniform(0.0, 360.0, ntp) - omega_tp = rng.uniform(0.0, 360.0, ntp) - capm_tp = rng.uniform(0.0, 360.0, ntp) - - integrators= ["whm","helio","rmvs","symba"] - sim.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) - sim.set_parameter(tstart=0.0, tstop=0.02, dt=0.01, istep_out=1, dump_cadence=0) - integrators= ["whm","helio","rmvs","symba"] - for i in integrators: - try: - sim.run(integrator=i) - except: - self.fail(f"Failed with integrator {i}") - - - def test04_conservation(self): - """ - Tests that Swiftest conserves mass, energy, and momentum to within acceptable tolerances. - """ - print("\ntest_conservation: Tests that Swiftest conserves mass, energy, and momentum to within acceptable tolerances.") - - # Error limits - L_slope_limit = 1e-10 - E_slope_limit = 1e-8 - GM_limit = 1e-14 - - sim = swiftest.Simulation() - sim.clean() - - sim.add_solar_system_body(major_bodies) - - dt = 0.01 - nout = 1000 - tstop = 1e4 - tstep_out = tstop / nout - - sim.run(tstart=0.0, tstop=tstop, dt=dt, tstep_out=tstep_out, dump_cadence=0, compute_conservation_values=True, integrator="symba") - - def fit_func(x,slope,b): - """ - Linear function for curve fitting - """ - return slope * x + b - - # Calculate the angular momentum error - sim.data['L_tot'] = sim.data['L_orbit'] + sim.data['L_spin'] + sim.data['L_escape'] - sim.data['DL'] = sim.data['L_tot'] - sim.data['L_tot'].isel(time=0) - L_error = swiftest.tool.magnitude(sim.data,'DL') / swiftest.tool.magnitude(sim.data.isel(time=0), 'L_tot') - - # Calculate the energy error - E_error = (sim.data['TE'] - sim.data['TE'].isel(time=0)) / sim.data['TE'].isel(time=0) - - # Calculate the mass error - sim.data['GMtot'] = sim.data['Gmass'].sum(dim='name',skipna=True) + sim.data['GMescape'] - GM_error = (sim.data['GMtot'] - sim.data['GMtot'].isel(time=0)) / sim.data['GMtot'].isel(time=0) - GM_final = GM_error.isel(time=-1).values - - # Compute the slope of the error vs time fit - E_fit_result = E_error.curvefit("time",fit_func) - L_fit_result = L_error.curvefit("time",fit_func) - - E_slope = E_fit_result['curvefit_coefficients'].sel(param='slope').values - L_slope = L_fit_result['curvefit_coefficients'].sel(param='slope').values - - # Print the final errors - print("\n") - print(f"Angular momentum error slope: {L_slope:.2e}/{sim.TU_name}") - print(f"Energy error slope: {E_slope:.2e}/{sim.TU_name}") - print(f"Final Mass Error: {GM_final:.2e}") - - self.assertLess(np.abs(L_slope),L_slope_limit, msg=f"Angular Momentum Error of {L_slope:.2e}/{sim.TU_name} higher than threshold value of {L_slope_limit:.2e}/{sim.TU_name}") - self.assertLess(np.abs(E_slope),E_slope_limit, msg=f"Energy Error of {E_slope:.2e}/{sim.TU_name} higher than threshold value of {E_slope_limit:.2e}/{sim.TU_name}") - self.assertLess(np.abs(GM_final),GM_limit, msg=f"Mass Error of {GM_final:.2e} higher than threshold value of {GM_limit:.2e}") - -if __name__ == '__main__': - unittest.main() - if os.path.exists("simdir"): - shutil.rmtree("simdir") - - # Add the modern planets and the Sun using the JPL Horizons Database. - # Add the modern planets and the Sun using the JPL Horizons Database. - sim.add_solar_system_body(major_bodies) - - # Display the run configuration parameters. - param = sim.get_parameter(verbose=False) - sim.save() - - for f in file_list: - self.assertTrue(os.path.exists(f)) - - print("\ntest_read_ic: Test whether we can read back initial conditions files created by test_gen_ic") - sim = swiftest.Simulation(read_param=True) - # Check if all names in Dataset read in from file match the expected list of names - self.assertTrue((major_bodies == sim.init_cond['name']).all(), msg="Name mismatch in Dataset") - - # Check to see if all parameter values read in from file match the expected parameters saved when generating the file - self.assertTrue(all([v == param[k] for k,v in sim.param.items() if k in param])) - - def test02_integrators(self): - """ - Tests that Swiftest is able to integrate a collection of massive bodies and test particles with all available integrators - """ - print("\ntest_integrators: Tests that Swiftest is able to integrate a collection of massive bodies and test particles with all available integrators") - sim = swiftest.Simulation() - sim.clean() - - # Add the modern planets and the Sun using the JPL Horizons Database. - # Add the modern planets and the Sun using the JPL Horizons Database. - sim.add_solar_system_body(major_bodies) - - # Display the run configuration parameters. - param = sim.get_parameter(verbose=False) - sim.save() - - # Add 10 user-defined test particles. - ntp = 10 - - name_tp = [f"TestParticle_{i:02}" for i in range(1,ntp+1)] - a_tp = rng.uniform(0.3, 1.5, ntp) - e_tp = rng.uniform(0.0, 0.2, ntp) - inc_tp = rng.uniform(0.0, 10, ntp) - capom_tp = rng.uniform(0.0, 360.0, ntp) - omega_tp = rng.uniform(0.0, 360.0, ntp) - capm_tp = rng.uniform(0.0, 360.0, ntp) - - integrators= ["helio","whm","rmvs","symba"] - sim.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) - sim.set_parameter(tstart=0.0, tstop=0.10, dt=0.01, istep_out=1, dump_cadence=0) - for i in integrators: - sim.run(integrator=i) - - - def test03_conservation(self): - """ - Tests that Swiftest conserves mass, energy, and momentum to within acceptable tolerances. - """ - print("\ntest_conservation: Tests that Swiftest conserves mass, energy, and momentum to within acceptable tolerances.") - - # Error limits - L_slope_limit = 1e-10 - E_slope_limit = 1e-8 - GM_limit = 1e-14 - - sim = swiftest.Simulation() - sim.clean() - - sim.add_solar_system_body(major_bodies) - - dt = 0.01 - nout = 1000 - tstop = 1e4 - tstep_out = tstop / nout - - sim.run(tstart=0.0, tstop=tstop, dt=dt, tstep_out=tstep_out, dump_cadence=0, compute_conservation_values=True, integrator="symba") - - def fit_func(x,slope,b): - """ - Linear function for curve fitting - """ - return slope * x + b - - # Calculate the angular momentum error - sim.data['L_tot'] = sim.data['L_orbit'] + sim.data['L_spin'] + sim.data['L_escape'] - sim.data['DL'] = sim.data['L_tot'] - sim.data['L_tot'].isel(time=0) - L_error = swiftest.tool.magnitude(sim.data,'DL') / swiftest.tool.magnitude(sim.data.isel(time=0), 'L_tot') - - # Calculate the energy error - E_error = (sim.data['TE'] - sim.data['TE'].isel(time=0)) / sim.data['TE'].isel(time=0) - - # Calculate the mass error - sim.data['GMtot'] = sim.data['Gmass'].sum(dim='name',skipna=True) + sim.data['GMescape'] - GM_error = (sim.data['GMtot'] - sim.data['GMtot'].isel(time=0)) / sim.data['GMtot'].isel(time=0) - GM_final = GM_error.isel(time=-1).values - - # Compute the slope of the error vs time fit - E_fit_result = E_error.curvefit("time",fit_func) - L_fit_result = L_error.curvefit("time",fit_func) - - E_slope = E_fit_result['curvefit_coefficients'].sel(param='slope').values - L_slope = L_fit_result['curvefit_coefficients'].sel(param='slope').values - - # Print the final errors - print("\n") - print(f"Angular momentum error slope: {L_slope:.2e}/{sim.TU_name}") - print(f"Energy error slope: {E_slope:.2e}/{sim.TU_name}") - print(f"Final Mass Error: {GM_final:.2e}") - - self.assertLess(np.abs(L_slope),L_slope_limit, msg=f"Angular Momentum Error of {L_slope:.2e}/{sim.TU_name} higher than threshold value of {L_slope_limit:.2e}/{sim.TU_name}") - self.assertLess(np.abs(E_slope),E_slope_limit, msg=f"Energy Error of {E_slope:.2e}/{sim.TU_name} higher than threshold value of {E_slope_limit:.2e}/{sim.TU_name}") - self.assertLess(np.abs(GM_final),GM_limit, msg=f"Mass Error of {GM_final:.2e} higher than threshold value of {GM_limit:.2e}") - -if __name__ == '__main__': - unittest.main() - if os.path.exists("simdir"): - shutil.rmtree("simdir") diff --git a/tests/test_swiftest.py b/tests/test_swiftest.py new file mode 100755 index 000000000..63f07829c --- /dev/null +++ b/tests/test_swiftest.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +""" + Copyright 2023 - David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, & Dana Singh + This file is part of Swiftest. + Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with Swiftest. + If not, see: https://www.gnu.org/licenses. +""" + +""" +Tests that energy and momentum errors are within tolerances in a Swiftest simulation + +Input +------ + +Output +------ +None +""" + +import swiftest +import unittest +import os +import numpy as np +from numpy.random import default_rng +from astroquery.jplhorizons import Horizons +import datetime + +rng = default_rng(seed=123) + +major_bodies = ["Sun","Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"] +param = {} + +class TestSwiftest(unittest.TestCase): + + def test_gen_ic(self): + """ + Tests that Swiftest is able to successfully generate a set of initial conditions in a file without any exceptions being raised + """ + print("\ntest_gen_ic: Test whether we can generate simulation initial conditions test") + # Files that are expected to be generated: + simdir = "simdata" + file_list = [simdir, os.path.join(simdir,"param.in"), os.path.join(simdir,"init_cond.nc")] + + sim = swiftest.Simulation() + sim.clean() + + # Add the modern planets and the Sun using the JPL Horizons Database. + sim.add_solar_system_body(major_bodies) + sim.save() + + for f in file_list: + self.assertTrue(os.path.exists(f)) + return + + + def test_read_ic(self): + """ + Tests that Swiftest is able to read a set of pre-existing initial conditions files and that they contain the correct data + """ + print("\ntest_read_ic: Test whether we can read back initial conditions files created by test_gen_ic") + sim = swiftest.Simulation() + sim.clean() + + # Add the modern planets and the Sun using the JPL Horizons Database. + sim.add_solar_system_body(major_bodies) + sim.save() + # Check if all names in Dataset read in from file match the expected list of names + self.assertTrue((major_bodies == sim.init_cond['name']).all(), msg="Name mismatch in Dataset") + + # Check to see if all parameter values read in from file match the expected parameters saved when generating the file + self.assertTrue(all([v == param[k] for k,v in sim.param.items() if k in param])) + return + + + def test_integrators(self): + """ + Tests that Swiftest is able to integrate a collection of massive bodies and test particles with all available integrators + """ + print("\ntest_integrators: Tests that Swiftest is able to integrate a collection of massive bodies and test particles with all available integrators") + sim = swiftest.Simulation() + + # Add the modern planets and the Sun using the JPL Horizons Database. + sim.add_solar_system_body(major_bodies) + sim.clean() + + # Add 10 user-defined test particles. + ntp = 10 + + name_tp = [f"TestParticle_{i:02}" for i in range(1,ntp+1)] + a_tp = rng.uniform(0.3, 1.5, ntp) + e_tp = rng.uniform(0.0, 0.2, ntp) + inc_tp = rng.uniform(0.0, 10, ntp) + capom_tp = rng.uniform(0.0, 360.0, ntp) + omega_tp = rng.uniform(0.0, 360.0, ntp) + capm_tp = rng.uniform(0.0, 360.0, ntp) + + integrators= ["whm","helio","rmvs","symba"] + sim.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) + sim.set_parameter(tstart=0.0, tstop=0.02, dt=0.01, istep_out=1, dump_cadence=0) + integrators= ["whm","helio","rmvs","symba"] + for i in integrators: + try: + sim.run(integrator=i) + except: + self.fail(f"Failed with integrator {i}") + return + + def test_conservation(self): + """ + Tests that Swiftest conserves mass, energy, and momentum to within acceptable tolerances. + """ + print("\ntest_conservation: Tests that Swiftest conserves mass, energy, and momentum to within acceptable tolerances.") + + # Error limits + L_slope_limit = 1e-10 + E_slope_limit = 1e-8 + GM_limit = 1e-14 + + sim = swiftest.Simulation() + sim.clean() + + sim.add_solar_system_body(major_bodies) + + dt = 0.01 + nout = 1000 + tstop = 1e4 + tstep_out = tstop / nout + + sim.run(tstart=0.0, tstop=tstop, dt=dt, tstep_out=tstep_out, dump_cadence=0, compute_conservation_values=True, integrator="symba") + + def fit_func(x,slope,b): + """ + Linear function for curve fitting + """ + return slope * x + b + + # Calculate the angular momentum error + sim.data['L_tot'] = sim.data['L_orbit'] + sim.data['L_spin'] + sim.data['L_escape'] + sim.data['DL'] = sim.data['L_tot'] - sim.data['L_tot'].isel(time=0) + L_error = swiftest.tool.magnitude(sim.data,'DL') / swiftest.tool.magnitude(sim.data.isel(time=0), 'L_tot') + + # Calculate the energy error + E_error = (sim.data['TE'] - sim.data['TE'].isel(time=0)) / sim.data['TE'].isel(time=0) + + # Calculate the mass error + sim.data['GMtot'] = sim.data['Gmass'].sum(dim='name',skipna=True) + sim.data['GMescape'] + GM_error = (sim.data['GMtot'] - sim.data['GMtot'].isel(time=0)) / sim.data['GMtot'].isel(time=0) + GM_final = GM_error.isel(time=-1).values + + # Compute the slope of the error vs time fit + E_fit_result = E_error.curvefit("time",fit_func) + L_fit_result = L_error.curvefit("time",fit_func) + + E_slope = E_fit_result['curvefit_coefficients'].sel(param='slope').values + L_slope = L_fit_result['curvefit_coefficients'].sel(param='slope').values + + # Print the final errors + print("\n") + print(f"Angular momentum error slope: {L_slope:.2e}/{sim.TU_name}") + print(f"Energy error slope: {E_slope:.2e}/{sim.TU_name}") + print(f"Final Mass Error: {GM_final:.2e}") + + self.assertLess(np.abs(L_slope),L_slope_limit, msg=f"Angular Momentum Error of {L_slope:.2e}/{sim.TU_name} higher than threshold value of {L_slope_limit:.2e}/{sim.TU_name}") + self.assertLess(np.abs(E_slope),E_slope_limit, msg=f"Energy Error of {E_slope:.2e}/{sim.TU_name} higher than threshold value of {E_slope_limit:.2e}/{sim.TU_name}") + self.assertLess(np.abs(GM_final),GM_limit, msg=f"Mass Error of {GM_final:.2e} higher than threshold value of {GM_limit:.2e}") + return + + def test_gr(self): + """ + Tests that GR is working correctly by computing the precession of Mercury's longitude of periapsis and comparing it to + values obtained from the JPL/Horizons ephemeris service + """ + print("\ntest_gr: Tests that GR is working correctly.") + + # Error limits + dvarpi_limit = 1e-3 + integrators= ["whm","helio","rmvs","symba"] + + # Initialize the simulation object as a variable. Define the directory in which the output will be placed. + tstep_out = 10.0 + sim = swiftest.Simulation(tstop=1000.0, dt=0.005, tstep_out=tstep_out, dump_cadence=0,general_relativity=True) + sim.add_solar_system_body(["Sun","Mercury","Venus","Earth","Mars","Jupiter","Saturn","Uranus","Neptune"]) + + # Get the start and end date of the simulation so we can compare with the real solar system. + start_date = sim.ephemeris_date + tstop_d = sim.param['TSTOP'] * sim.param['TU2S'] / swiftest.JD2S + + stop_date = (datetime.datetime.fromisoformat(start_date) + datetime.timedelta(days=tstop_d)).isoformat() + + #Get the ephemerides of Mercury for the same timeframe as the simulation. + obj = Horizons(id='1', location='@sun', + epochs={'start':start_date, 'stop':stop_date, + 'step':'10y'}) + el = obj.elements() + t = (el['datetime_jd']-el['datetime_jd'][0]) / 365.25 + varpi_obs = el['w'] + el['Omega'] + dvarpi_obs = np.diff(varpi_obs) / np.diff(t) + dvarpi_obs_mean = np.mean(dvarpi_obs) + + for i in integrators: + sim.run(integrator=i) + varpi_sim = sim.data['varpi'].sel(name="Mercury") + dvarpi_gr = np.diff(varpi_sim) / tstep_out + dvarpi_err = np.mean(dvarpi_obs - dvarpi_gr) / dvarpi_obs_mean + print(f'{i}: Mercury precession rate error {dvarpi_err:.2e} "/{sim.TU_name}') + self.assertLess(np.abs(dvarpi_err),dvarpi_limit,msg=f'{dvarpi_err:.2e} /{sim.TU_name} is higher than threshold value of {dvarpi_limit:.2e} "/{sim.TU_name}') + + return + + +if __name__ == '__main__': + os.environ["HDF5_USE_FILE_LOCKING"]="FALSE" + unittest.main() \ No newline at end of file diff --git a/version.txt b/version.txt index bb764935a..ea516b56c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2023.9.3 \ No newline at end of file +2023.10.1 \ No newline at end of file