diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml new file mode 100644 index 000000000..a607e1741 --- /dev/null +++ b/.github/workflows/build_wheels.yml @@ -0,0 +1,52 @@ +name: swiftest + +on: + release: + types: [published] + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-11, macos-12, macos-13] + cibw_archs: [x86_64] + include: + - os: ubuntu-latest + cibw_archs: "aarch64" + env: + SYSTEM_VERSION_COMPAT: 0 + + steps: + - name: Set up QEMU + if: matrix.cibw_archs == 'aarch64' + uses: docker/setup-qemu-action@v2 + with: + platforms: arm64 + - uses: actions/checkout@v3 + - name: Build wheels + uses: pypa/cibuildwheel@v2.15.0 + env: + CIBW_ARCHS: ${{ matrix.cibw_archs }} + with: + package-dir: . + output-dir: wheelhouse + config-file: "{package}/pyproject.toml" + + - uses: actions/upload-artifact@v3 + with: + path: ./wheelhouse/*.whl + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build sdist + run: pipx run build --sdist + + - uses: actions/upload-artifact@v3 + with: + path: dist/*.tar.gz \ No newline at end of file diff --git a/.github/workflows/draft-pdf.yml b/.github/workflows/draft-pdf.yml new file mode 100644 index 000000000..656359398 --- /dev/null +++ b/.github/workflows/draft-pdf.yml @@ -0,0 +1,23 @@ +on: [push] + +jobs: + paper: + runs-on: ubuntu-latest + name: Paper Draft + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Build draft PDF + uses: openjournals/openjournals-draft-action@master + with: + journal: joss + # This should be the path to the paper within your repo. + paper-path: paper/paper.md + - name: Upload + uses: actions/upload-artifact@v1 + with: + name: paper + # This is the output path where Pandoc will write the compiled + # PDF. Note, this should be the same directory as the input + # paper.md + path: paper/paper.pdf \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9c5ee861f..06fee4819 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,8 @@ swiftest_driver.sh !CMakeLists.txt !*.cmake -!COPYING.txt +!COPYING +!LICENSE !CHANGELOG !README.md !README_figs/** @@ -18,10 +19,13 @@ swiftest_driver.sh !README.swifter dump* !**/.gitignore +!.github/workflows/*.yml !setup.py !examples/** !swiftest/** !tests/** +!.zenodo.json +!CITATION.cff *ipynb_checkpoints **/.DS_Store !version.txt @@ -36,6 +40,7 @@ _dependencies #Documentation +!mkdocs.yml !docs/* !docs/*/* !docs/*/*/* @@ -55,4 +60,7 @@ netcdf-c-* netcdf-fortran-* zlib-* +actions-runner* +env/** +venv/** diff --git a/.zenodo.json b/.zenodo.json new file mode 100644 index 000000000..db7b69cbf --- /dev/null +++ b/.zenodo.json @@ -0,0 +1,58 @@ +{ + "description": "Official release for the Journal of Open Source Software.", + "license" : "GPLv3+", + "title": "profminton/swiftest: v2023.10.2", + "version": "v2023.10.2", + "upload_type": "software", + "publication_date": "2023-10-07", + "creators": [ + { + "name": "Carlisle Wishard", + "affiliation": [ + "Department of Earth, Atmospheric, and Planetary Sciences, Purdue University, USA", + "Evansville Museum of Arts, History & Science, USA" + ], + "orcid": "0009-0001-0733-3268" + }, + { + "name": "Jennifer Pouplin", + "affiliation": [ + "Department of Earth, Atmospheric, and Planetary Sciences, Purdue University, USA", + "School of Aeronautics and Astronautics, Purdue University, USA" + ] + }, + { + "name": "Jacob Elliott", + "affiliation": "Department of Earth, Atmospheric, and Planetary Sciences, Purdue University, USA" + }, + { + "name": "Dana Singh", + "affiliation": "SAIC, Princeton, NJ, USA" + }, + { + "name": "Kaustub Anand", + "affiliation": [ + "Department of Earth, Atmospheric, and Planetary Sciences, Purdue University, USA", + "Department of Physics and Astronomy, Purdue University, USA" + ] + }, + { + "name": "David Minton", + "affiliation": "Department of Earth, Atmospheric, and Planetary Sciences, Purdue University, USA", + "orcid": "0000-0003-1656-9704" + } + ], + "access_right": "open", + "related_identifiers": [ + { + "scheme": "url", + "identifier": "https://github.com/profminton/swiftest/tree/v2023.10.2", + "relation": "isSupplementTo" + }, + { + "scheme": "doi", + "identifier": "10.5281/zenodo.8417147", + "relation": "isVersionOf" + } + ] +} diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..adac9fea2 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,22 @@ +cff-version: 1.1.0 +message: "If you use this software, please cite it as below." +authors: + - name: Wishard + given-names: Carlislse + orcid: https://orcid.org/0009-0001-0733-3268 + - family-names: Pouplin + given-names: Jennifer + - family-names: Elliott + given-names: Jacob + - family-names: Dana + given-names: Singh + - family-names: Anand + given-names: Kaustub + - family-names: Minton + given-names: David + affiliation: "1" + orcid: https://orcid.org/0000-0003-1656-9704 +title: profminton/swiftest: v2023.10.2 +version: v2023.10.2 +date-released: 2023-10-07 + \ 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 cb2aa413c..4ce195ac5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,74 +12,110 @@ # Define the project and the depencies that it has ################################################## CMAKE_MINIMUM_REQUIRED(VERSION 3.6.0...3.27.1) +SET(SKBUILD_PROJECT_NAME "swiftest" CACHE STRING "Name of project set by scikit-build") +SET(SKBUILD_SCRIPTS_DIR "${CMAKE_SOURCE_DIR}/bin" CACHE STRING "Install location of binary executable") # Get version stored in text file FILE(READ "version.txt" VERSION) -PROJECT(swiftest VERSION ${VERSION} LANGUAGES C Fortran) +PROJECT(${SKBUILD_PROJECT_NAME} LANGUAGES C Fortran VERSION ${VERSION}) + +# Use the old method to get Python packages, as that's what scikit-build uses +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" OFF) +OPTION(BUILD_SHARED_LIBS "Build using shared libraries" ON) + +INCLUDE(GNUInstallDirs) +IF (SKBUILD) + SET(INSTALL_BINDIR ${SKBUILD_PLATLIB_DIR}/${SKBUILD_PROJECT_NAME}) + SET(INSTALL_LIBDIR ${SKBUILD_PLATLIB_DIR}/${SKBUILD_PROJECT_NAME}) + SET(INSTALL_INCLUDEDIR ${INSTALL_LIBDIR}) + IF (APPLE) + SET(CMAKE_INSTALL_RPATH "@loader_path") + ELSEIF (LINUX) + SET(CMAKE_INSTALL_RPATH $ORIGIN) + ENDIF () +ELSE () + SET(INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR}) + SET(INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}) + SET(INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) +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 ldpath +FILE(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules" LOCAL_MODULE_PATH) +LIST(APPEND CMAKE_MODULE_PATH ${LOCAL_MODULE_PATH}) + +IF (CMAKE_Fortran_COMPILER_ID MATCHES "^Intel") + SET(COMPILER_OPTIONS "Intel" CACHE STRING "Compiler identified as Intel") +ELSEIF (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + SET(COMPILER_OPTIONS "GNU" CACHE STRING "Compiler identified as gfortran") +ELSE () + MESSAGE(FATAL_ERROR "Compiler ${CMAKE_Fortran_COMPILER_ID} not recognized!") +ENDIF () # 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() -# Ensure scikit-build modules -FIND_PACKAGE(Python3 COMPONENTS Interpreter Development.Module REQUIRED) -IF (NOT SKBUILD) - EXECUTE_PROCESS( - COMMAND "${Python3_EXECUTABLE}" - -c "import os, skbuild; print(os.path.dirname(skbuild.__file__))" - OUTPUT_VARIABLE SKBLD_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - FILE(TO_CMAKE_PATH ${SKBLD_DIR} SKBLD_DIR) - LIST(APPEND CMAKE_MODULE_PATH "${SKBLD_DIR}/resources/cmake") - MESSAGE(STATUS "Looking in ${SKBLD_DIR}/resources/cmake for CMake modules") -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 () -# Detect when building against a conda environment set the _using_conda variable -# for use both in this file and in the parent -GET_FILENAME_COMPONENT(_python_bin_dir ${Python3_EXECUTABLE} DIRECTORY) -IF(EXISTS "${_python_bin_dir}/../conda-meta") - MESSAGE("-- Detected conda environment, setting INSTALL_RPATH_USE_LINK_PATH") - SET(_using_conda On) -ELSE() - SET(_using_conda Off) -ENDIF() +# Ensure scikit-build modules +FIND_PACKAGE(Python COMPONENTS Interpreter Development.Module REQUIRED) -# Add our local modules to the module path -FILE(TO_CMAKE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules" LOCAL_MODULE_PATH) -LIST(APPEND CMAKE_MODULE_PATH ${LOCAL_MODULE_PATH}) -# Define some directories that are important to the build SET(SRC "${CMAKE_SOURCE_DIR}/src") -SET(LIB "${CMAKE_SOURCE_DIR}/lib") -SET(BIN "${CMAKE_SOURCE_DIR}/bin") -SET(MOD "${CMAKE_SOURCE_DIR}/include") SET(PY "${CMAKE_SOURCE_DIR}/swiftest") +##################################### +# Tell how to install this executable +##################################### +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 CACHE PATH "Path for install") +ENDIF() + + # Make sure paths are correct for Unix or Windows style FILE(TO_CMAKE_PATH ${SRC} SRC) -FILE(TO_CMAKE_PATH ${LIB} LIB) -FILE(TO_CMAKE_PATH ${BIN} BIN) -FILE(TO_CMAKE_PATH ${MOD} MOD) FILE(TO_CMAKE_PATH ${PY} PY) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB}) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIB}) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN}) +# Set the name of the swiftest library +SET(SWIFTEST_LIBRARY ${SKBUILD_PROJECT_NAME}) -# Have the .mod files placed in the lib folder -SET(CMAKE_Fortran_MODULE_DIRECTORY ${MOD}) +# 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) -# The source for the SWIFTEST binary and have it placed in the bin folder -ADD_SUBDIRECTORY(${SRC} ${BIN}) +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}) # Add a distclean target to the Makefile diff --git a/COPYING.txt b/COPYING similarity index 100% rename from COPYING.txt rename to COPYING diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..965bb4c26 --- /dev/null +++ b/LICENSE @@ -0,0 +1,10 @@ +Copyright 2023 - David Minton +The Swiftest development team: David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, Dana Singh, & Kaustub Anand + +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. \ No newline at end of file diff --git a/README.md b/README.md index 4a7577922..9d414b765 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,8 @@ The Swiftest CMake configuration comes with several customization options: | Set Fortran compiler path | \-DCMAKE_Fortran_COMPILER=/path/to/fortran/compiler | | Set path to make program | \-DCMAKE_MAKE_PROGRAM=/path/to/make | | Enable/Disable shared libraries (Intel only) | \-DBUILD_SHARED_LIBS=[**ON\|OFF] | -| Add additional include path | \-DCMAKE_Fortran_FLAGS="-I/path/to/libries | +| Add additional include path | \-DCMAKE_Fortran_FLAGS="-I/path/to/libraries | +| Install prefix | \-DCMAKE_INSTALL_PREFIX=["/path/to/install"\|**"/usr/local"**] | To see a list of all possible options available to CMake: @@ -137,7 +138,7 @@ To see a list of all possible options available to CMake: $ cmake -B build -S . -LA ``` -The Swiftest executable, called ```swiftest_driver```, should now be created in the ```bin/``` directory. +The Swiftest executable, called `swiftest_driver`, should now be created in the `bin/` directory. **Download the `swiftest_driver` as a Docker or Singularity container.** diff --git a/README_tables/add_body_kwargs.md b/README_tables/add_body_kwargs.md index 4e341a83d..59f52078f 100644 --- a/README_tables/add_body_kwargs.md +++ b/README_tables/add_body_kwargs.md @@ -15,7 +15,7 @@ | ```Gmass``` | Gravitational mass value(s) of bodies. Only for massive bodies. Only ```mass``` **OR** ```Gmass``` may be set. | float or array-like of floats | ```radius``` | Radius value(s) of bodies. Only for massive bodies. | float or array-like of floats | ```rhill``` | Hill Radius value(s) of bodies. Only for massive bodies. | float or array-like of floats -| ```rot``` | Rotation rate vector(s) of bodies in radians/sec. Only for massive bodies. Only used if ```rotation``` is set to ```True```. | (n,3) array-like of floats +| ```rot``` | Rotation rate vector(s) of bodies in degrees/sec. Only for massive bodies. Only used if ```rotation``` is set to ```True```. | (n,3) array-like of floats | ```Ip``` | Principal axes moments of inertia vector(s) of bodies. Only for massive bodies. Only used if ```rotation``` is set to ```True```. | (n,3) array-like of floats | ```J2``` | The unitless value of the spherical harmonic term equal to J2*R^2 where R is the radius of the central body. | float or array-like of floats | ```J4``` | The unitless value of the spherical harmonic term equal to J4*R^4 where R is the radius of the central body. | float or array-like of floats 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 0c92d1077..113f9e526 100755 --- a/buildscripts/_build_getopts.sh +++ b/buildscripts/_build_getopts.sh @@ -13,11 +13,15 @@ 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|{/usr/local}] [-m MACOSX_DEPLOYMENT_TARGET|{11.0}]" -PREFIX=/usr/local -DEPENDENCY_DIR="${ROOT_DIR}/_dependencies" -MACOSX_DEPLOYMENT_TARGET="13.0" +USTMT="Usage: ${0} [-d /path/to/dependency/source] [-p /prefix/path] [-m MACOSX_DEPLOYMENT_TARGET]" +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 d) @@ -45,27 +49,9 @@ while getopts ":d:p:m:h" ARG; do esac done -read -r OS ARCH < <($SCRIPT_DIR/get_platform.sh) - -if [ -z ${DEPENDENCY_ENV_VARS+x} ]; then - . ${SCRIPT_DIR}/set_compilers.sh - - LD_LIBRARY_PATH="${PREFIX}/lib:${LD_LIBRARY_PATH}" - CPPFLAGS="${CPPFLAGS} -isystem ${PREFIX}/include" - LDFLAGS="${LDFLAGS} -L${PREFIX}/lib" - CPATH="${CPATH} ${PREFIX}/include}" - - HDF5_ROOT="${PREFIX}" - HDF5_LIBDIR="${HDF5_ROOT}/lib" - HDF5_INCLUDE_DIR="${HDF5_ROOT}/include" - HDF5_PLUGIN_PATH="${HDF5_LIBDIR}/plugin" - NCDIR="${PREFIX}" - NFDIR="${PREFIX}" - NETCDF_FORTRAN_HOME=${NFDIR} - NETCDF_HOME=${NCDIR} - - DEPENDENCY_ENV_VARS=true -fi +BUILD_DIR=${BUILD_DIR:-"${HOME}/Downloads"} +PREFIX=${PREFIX:-"/usr/local"} +DEPENDENCY_DIR=${DEPENDENCY_DIR:-${BUILD_DIR}} mkdir -p ${DEPENDENCY_DIR} mkdir -p ${PREFIX}/lib diff --git a/buildscripts/build_all.sh b/buildscripts/build_all.sh deleted file mode 100755 index d93933abe..000000000 --- a/buildscripts/build_all.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# This script will generate cross-platform wheels for the Swiftest Python package using Docker. If it is called from MacOS it will -# also generate a Mac build. -# -# 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. - -# Determine the platform and architecture -set -a -SCRIPT_DIR=$(realpath $(dirname $0)) -ARGS=$@ -. ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} - -set -e -${SCRIPT_DIR}/build_dependencies.sh ${ARGS} -${SCRIPT_DIR}/build_swiftest.sh ${ARGS} \ No newline at end of file diff --git a/buildscripts/build_dependencies.sh b/buildscripts/build_dependencies.sh index f1eb625c3..32ac73ea9 100755 --- a/buildscripts/build_dependencies.sh +++ b/buildscripts/build_dependencies.sh @@ -16,84 +16,45 @@ SCRIPT_DIR=$(realpath $(dirname $0)) set -a ARGS=$@ . ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} - -ZLIB_VER="1.3" -HDF5_VER="1_14_2" -NC_VER="4.9.2" -NF_VER="4.6.1" - -printf "*********************************************************\n" -printf "* FETCHING DEPENCENCY SOURCES *\n" -printf "*********************************************************\n" -printf "Copying files to ${DEPENDENCY_DIR}\n" -mkdir -p ${DEPENDENCY_DIR} -if [ ! -d ${DEPENDENCY_DIR}/zlib-${ZLIB_VER} ]; then - [ -d ${DEPENDENCY_DIR}/zlib-* ] && rm -rf ${DEPENDENCY_DIR}/zlib-* - curl -L https://github.com/madler/zlib/releases/download/v${ZLIB_VER}/zlib-${ZLIB_VER}.tar.gz | tar xvz -C ${DEPENDENCY_DIR} -fi - -printf "Checking if HDF5 source exists\n" -if [[ (-d ${DEPENDENCY_DIR}/hdfsrc) && (-f ${DEPENDENCY_DIR}/hdfsrc/README.md) ]]; then - OLDVER=$(grep version ${DEPENDENCY_DIR}/hdfsrc/README.md | awk '{print $3}' | sed 's/\./_/g') - printf "Existing copy of HDF5 source detected\n" - printf "Existing version : ${OLDVER}\n" - printf "Requested version: ${HDF5_VER}\n" - if [ "$OLDVER" != "${HDF5_VER}" ]; then - printf "Existing version of HDF5 source doesn't match requested. Deleting\n" - rm -rf ${DEPENDENCY_DIR}/hdfsrc - fi -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 - -if [ ! -d ${DEPENDENCY_DIR}/netcdf-c-${NC_VER} ]; then - [ -d ${DEPENDENCY_DIR}/netcdf-c-* ] && rm -rf ${DEPENDENCY_DIR}/netcdf-c-* - curl -s -L https://github.com/Unidata/netcdf-c/archive/refs/tags/v${NC_VER}.tar.gz | tar xvz -C ${DEPENDENCY_DIR} -fi - -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 - -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" - set -e -if [ ! -f ${PREFIX}/lib/libz.a ]; then - ${SCRIPT_DIR}/build_zlib.sh ${ARGS} -else - echo "Found: ${PREFIX}/lib/libz.a" -fi +cd $ROOT_DIR -if [ ! -f ${PREFIX}/lib/libhdf5.a ]; then - ${SCRIPT_DIR}/build_hdf5.sh ${ARGS} -else - echo "Found: ${PREFIX}/lib/libhdf5.a" +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 - -if [ ! -f ${PREFIX}/lib/libnetcdf.a ]; then - ${SCRIPT_DIR}/build_netcdf-c.sh ${ARGS} -else - echo "Found: ${PREFIX}/lib/libnetcdf.a" +# Get the OpenMP Libraries +if [ $OS = "MacOSX" ]; then + ${SCRIPT_DIR}/get_lomp.sh ${ARGS} fi -if [ ! -f ${PREFIX}/lib/libnetcdff.a ]; then - ${SCRIPT_DIR}/build_netcdf-fortran.sh ${ARGS} -else - echo "Found: ${PREFIX}/lib/libnetcdff.a" -fi +${SCRIPT_DIR}/build_zlib.sh ${ARGS} +${SCRIPT_DIR}/build_hdf5.sh ${ARGS} +${SCRIPT_DIR}/build_netcdf-c.sh ${ARGS} +${SCRIPT_DIR}/build_netcdf-fortran.sh ${ARGS} printf "\n" printf "*********************************************************\n" printf "* DEPENDENCIES ARE BUILT *\n" printf "*********************************************************\n" printf "Dependencys are installed to: ${PREFIX}\n\n" + + diff --git a/buildscripts/build_hdf5.sh b/buildscripts/build_hdf5.sh index 9f170e0a1..3f93d036b 100755 --- a/buildscripts/build_hdf5.sh +++ b/buildscripts/build_hdf5.sh @@ -10,14 +10,49 @@ # 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" + +printf "*********************************************************\n" +printf "* FETCHING HDF5 SOURCE *\n" +printf "*********************************************************\n" +printf "Copying files to ${DEPENDENCY_DIR}\n" + +printf "Checking if HDF5 source exists\n" +if [[ (-d ${DEPENDENCY_DIR}/hdfsrc) && (-f ${DEPENDENCY_DIR}/hdfsrc/README.md) ]]; then + OLDVER=$(grep version ${DEPENDENCY_DIR}/hdfsrc/README.md | awk '{print $3}' | sed 's/\./_/g') + printf "Existing copy of HDF5 source detected\n" + printf "Existing version : ${OLDVER}\n" + printf "Requested version: ${HDF5_VER}\n" + if [ "$OLDVER" != "${HDF5_VER}" ]; then + printf "Existing version of HDF5 source doesn't match requested. Deleting\n" + rm -rf ${DEPENDENCY_DIR}/hdfsrc + fi +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 STATIC LIBRARY *\n" +printf "* BUILDING HDF5 LIBRARY *\n" printf "*********************************************************\n" printf "LIBS: ${LIBS}\n" printf "CFLAGS: ${CFLAGS}\n" @@ -28,26 +63,44 @@ 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="--disable-shared --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 printf "hdf5 could not be compiled.\n" exit 1 fi - -make distclean - diff --git a/buildscripts/build_netcdf-c.sh b/buildscripts/build_netcdf-c.sh index 82bc78380..ee7415cbf 100755 --- a/buildscripts/build_netcdf-c.sh +++ b/buildscripts/build_netcdf-c.sh @@ -11,14 +11,35 @@ # 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" + printf "*********************************************************\n" -printf "* BUILDING NETCDF-C STATIC LIBRARY *\n" +printf "* FETCHING NETCDF-C SOURCE *\n" +printf "*********************************************************\n" +printf "Copying files to ${DEPENDENCY_DIR}\n" + +if [ ! -d ${DEPENDENCY_DIR}/netcdf-c-${NC_VER} ]; then + [ -d ${DEPENDENCY_DIR}/netcdf-c-* ] && rm -rf ${DEPENDENCY_DIR}/netcdf-c-* + curl -s -L https://github.com/Unidata/netcdf-c/archive/refs/tags/v${NC_VER}.tar.gz | tar xvz -C ${DEPENDENCY_DIR} +fi + +printf "\n" +printf "*********************************************************\n" +printf "* BUILDING NETCDF-C LIBRARY *\n" printf "*********************************************************\n" printf "LIBS: ${LIBS}\n" printf "CFLAGS: ${CFLAGS}\n" @@ -30,23 +51,30 @@ printf "HDF5_ROOT: ${HDF5_ROOT}\n" printf "*********************************************************\n" cd ${DEPENDENCY_DIR}/netcdf-c-* -COPTS="--disable-shared --disable-dap --disable-byterange --disable-testsets --prefix=${PREFIX}" -if [ ! $OS = "MacOSX" ]; then - COPTS="${COPTS} --disable-libxml2" -fi -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 printf "netcdf-c could not be compiled."\n exit 1 -fi - -make distclean \ No newline at end of file +fi \ No newline at end of file diff --git a/buildscripts/build_netcdf-fortran.sh b/buildscripts/build_netcdf-fortran.sh index 9e9a877cd..c82f24573 100755 --- a/buildscripts/build_netcdf-fortran.sh +++ b/buildscripts/build_netcdf-fortran.sh @@ -14,12 +14,31 @@ SCRIPT_DIR=$(realpath $(dirname $0)) set -a ARGS=$@ . ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} +. ${SCRIPT_DIR}/set_compilers.sh -LIBS="$(${PREFIX}/bin/nc-config --libs --static)" +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" +printf "* FETCHING NETCDF-FORTRAN SOURCE *\n" +printf "*********************************************************\n" +printf "Copying files to ${DEPENDENCY_DIR}\n" +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 STATIC LIBRARY *\n" +printf "* BUILDING NETCDF-FORTRAN LIBRARY *\n" printf "*********************************************************\n" printf "LIBS: ${LIBS}\n" printf "CFLAGS: ${CFLAGS}\n" @@ -30,18 +49,26 @@ printf "LDFLAGS: ${LDFLAGS}\n" printf "*********************************************************\n" cd ${DEPENDENCY_DIR}/netcdf-fortran-* -./configure --disable-shared --with-pic --disable-zstandard-plugin --enable-large-file-tests=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 printf "netcdf-fortran could not be compiled.\n" exit 1 -fi - -make distclean - +fi \ No newline at end of file diff --git a/buildscripts/build_swiftest.sh b/buildscripts/build_swiftest.sh deleted file mode 100755 index c4f06bb4c..000000000 --- a/buildscripts/build_swiftest.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -# This script will build the Swiftest package. It is assumed that compatible dependencies have been built already before this is run -# -# 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. -set -a -if [ -z ${SCRIPT_DIR+x} ]; then SCRIPT_DIR=$(realpath $(dirname $0)); fi -ARGS=$@ -. ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} - -# Determine if we are in the correct directory (the script can either be run from the Swiftest project root directory or the -# buildscripts directory) -if [ ! -f "${ROOT_DIR}/setup.py" ]; then - echo "Error: setup.py not found" - exit 1 -fi - -printf "Using ${OS} compilers:\nFC: ${FC}\nCC: ${CC}\nCXX: ${CXX}\n\n" -printf "Installing to ${PREFIX}\n" -printf "Dependency libraries in ${PREFIX}\n" - - -SKBUILD_CONFIGURE_OPTIONS="-DBUILD_SHARED_LIBS=OFF" - -if [ $OS = "Intel" ]; then - FCFLAGS="${CFLAGS} -standard-semantics" - SKBUILD_CONFIGURE_OPTIONS="${SKBUILD_CONFIGURE_OPTIONS} -DMACHINE_CODE_VALUE=\"SSE2\"" -else - SKBUILD_CONFIGURE_OPTIONS="${SKBUILD_CONFIGURE_OPTIONS} -DMACHINE_CODE_VALUE=\"generic\"" -fi - -read -r OS ARCH < <($SCRIPT_DIR/get_platform.sh) -echo $OS $ARCH - -cd $ROOT_DIR - -printf "\n" -printf "*********************************************************\n" -printf "* BUILDING SWIFTEST *\n" -printf "*********************************************************\n" -printf "LIBS: ${LIBS}\n" -printf "CFLAGS: ${CFLAGS}\n" -printf "FFLAGS: ${FFLAGS}\n" -printf "FCFLAGS: ${FCFLAGS}\n" -printf "CPPFLAGS: ${CPPFLAGS}\n" -printf "CPATH: ${CPATH}\n" -printf "LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}\n" -printf "LDFLAGS: ${LDFLAGS}\n" -printf "NETCDF_FORTRAN_HOME: ${NETCDF_FORTRAN_HOME}\n" -printf "SKBUILD_CONFIGURE_OPTIONS: ${SKBUILD_CONFIGURE_OPTIONS}\n" -if [ $OS = "MacOSX" ]; then - printf "MACOSX_DEPLOYMENT_TARGET: ${MACOSX_DEPLOYMENT_TARGET}\n" -fi -printf "*********************************************************\n" - -python3 -m pip install build pip -python3 -m build --sdist -if [ $OS = "MacOSX" ]; then - cibuildwheel --platform macos -elif [ $OS = "Linux" ]; then - cibuildwheel --platform linux -fi \ No newline at end of file diff --git a/buildscripts/build_zlib.sh b/buildscripts/build_zlib.sh index d65cad4f6..337e6a839 100755 --- a/buildscripts/build_zlib.sh +++ b/buildscripts/build_zlib.sh @@ -14,9 +14,31 @@ 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" printf "*********************************************************\n" -printf "* BUILDING ZLIB STATIC LIBRARY *\n" +printf "* FETCHING ZLIB SOURCE *\n" +printf "*********************************************************\n" +printf "Copying files to ${DEPENDENCY_DIR}\n" +mkdir -p ${DEPENDENCY_DIR} +if [ ! -d ${DEPENDENCY_DIR}/zlib-${ZLIB_VER} ]; then + [ -d ${DEPENDENCY_DIR}/zlib-* ] && rm -rf ${DEPENDENCY_DIR}/zlib-* + curl -L https://github.com/madler/zlib/releases/download/v${ZLIB_VER}/zlib-${ZLIB_VER}.tar.gz | tar xvz -C ${DEPENDENCY_DIR} +fi + +printf "*********************************************************\n" +printf "* BUILDING ZLIB LIBRARY *\n" printf "*********************************************************\n" printf "LIBS: ${LIBS}\n" printf "CFLAGS: ${CFLAGS}\n" @@ -27,17 +49,16 @@ printf "LDFLAGS: ${LDFLAGS}\n" printf "*********************************************************\n" cd ${DEPENDENCY_DIR}/zlib-* -./configure --prefix=${PREFIX} --static -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 printf "zlib could not be compiled.\n" exit 1 -fi - -make distclean \ No newline at end of file +fi \ No newline at end of file diff --git a/buildscripts/get_lomp.sh b/buildscripts/get_lomp.sh new file mode 100755 index 000000000..d72213dbc --- /dev/null +++ b/buildscripts/get_lomp.sh @@ -0,0 +1,87 @@ +#!/bin/bash +# This script will download the correct OpenMP library for a given MacOS deployment target +# +# 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. + +# Determine the platform and architecture +SCRIPT_DIR=$(realpath $(dirname $0)) +set -a +ARGS=$@ +. ${SCRIPT_DIR}/_build_getopts.sh ${ARGS} +printf "MACOSX_DEPLOYMENT_TARGET: ${MACOSX_DEPLOYMENT_TARGET}\n" + +TARGET_MAJOR=`echo $MACOSX_DEPLOYMENT_TARGET | cut -d. -f1` +TARGET_MINOR=`echo $MACOSX_DEPLOYMENT_TARGET | cut -d. -f2` +TARGET_REV=`echo $MACOSX_DEPLOYMENT_TARGET | cut -d. -f3` + +#Figure out which version to get +case $TARGET_MAJOR in + 14) + OMPVER="16.0.4" + DVER="20" + ;; + 13) + OMPVER="14.0.6" + DVER="20" + ;; + 12) + if ((TARGET_MINOR>=5)); then + OMPVER="14.0.6" + DVER="20" + else + OMPVER="13.0.0" + DVER="21" + fi + ;; + 11) + if ((TARGET_MINOR>=3)); then + OMPVER="12.0.1" + DVER="20" + else + OMPVER="11.0.1" + DVER="20" + fi + ;; + 10) + DVER="17" + case $TARGET_MINOR in + 15) + case $TARGET_REV in + 4) + OMPVER="10.0.0" + ;; + 2) + OMPVER="9.0.1" + ;; + esac + ;; + 14) + case $TARGET_REV in + 4) + OMPVER="8.0.1" + ;; + 3) + OMPVER="7.1.0" + ;; + esac + ;; + *) + OMPVER="7.1.0" + ;; + esac + ;; +esac + +filename="openmp-${OMPVER}-darwin${DVER}-Release.tar.gz" +#Download and install the libraries +printf "Downloading ${filename}\n" +curl -O https://mac.r-project.org/openmp/${filename} && \ + sudo tar fvxz ${filename} -C / && \ + rm ${filename} \ No newline at end of file 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/intelbash.sh b/buildscripts/intelbash.sh new file mode 100755 index 000000000..7f42e5534 --- /dev/null +++ b/buildscripts/intelbash.sh @@ -0,0 +1,5 @@ +#!/bin/bash +ARGS=$@ + +eval "$(/usr/local/bin/brew shellenv)" +arch -x86_64 /bin/bash -c "${ARGS}" diff --git a/buildscripts/set_compilers.sh b/buildscripts/set_compilers.sh index 3ff88f8b1..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 - Intel|Linux|MacOSX) + Linux|MacOSX|Intel) ;; *) echo "Unknown compiler type: $OS" @@ -26,117 +27,36 @@ case "$OS" in esac set -a -# Only replace compiler definitions if they are not already set case $OS in - Intel) - if [ ! -v FC ]; then - if command -v ifx &> /dev/null; then - FC=$(command -v ifx) - elif command -v ifort &> /dev/null; then - FC=$(command -v mpiifort) - else - printf "Error. Cannot find valid Intel Fortran compiler.\n" - exit 1 - fi - fi - if [ ! -v F77 ]; then - F77="${FC}" - fi - - if [ ! -v CC ]; then - if command -v icx &> /dev/null; then - CC=$(command -v icx) - elif command -v icc &> /dev/null; then - CC=$(command -v icc) - else - printf "Error. Cannot find valid Intel C compiler.\n" - exit 1 - fi - fi - - if [ ! -v CXX ]; then - if command -v icpx &> /dev/null; then - CXX=$(command -v icpx) - elif command -v icpc &> /dev/null; then - CXX=$(command -v icpc) - else - printf "Error. Cannot find valid Intel C++ compiler.\n" - exit 1 - fi - fi - - if command -v mpiifort &> /dev/null; then - I_MPI_F90=${FC} - FC=$(command -v mpiifort) - fi - - if command -v mpiicc &> /dev/null; then - I_MPI_CC =${CC} - CC=$(command -v mpiicc) - fi - - if command -v mpiicpc &> /dev/null; then - I_MPI_CXX =${CXX} - CXX=$(command -v mpiicpc) - fi - - CPP=${CPP:-$HOMEBRE_PREFIX/bin/cpp-13} - ;; Linux) - FC=${FC:-$(command -v gfortran)} - CC=${CC:-$(command -v gcc)} - CXX=${CXX:-$(command -v g++)} - CPP=${CPP:-$(command -v cpp)} + . ${SCRIPT_DIR}/set_environment_linux.sh + FC=$(command -v gfortran) + CC=$(command -v gcc) + CXX=$(command -v g++) + CPP=$(command -v cpp) ;; MacOSX) - if [ $ARCH = "arm64" ]; then - if $(brew --version &> /dev/null); then - brew install llvm@16 libomp - else - echo \"Please install Homebrew first\" - exit 1 - fi - COMPILER_PREFIX=${COMPILER_PREFIX:-"${HOMEBREW_PREFIX}/opt/llvm"} - CC=${CC:-${COMPILER_PREFIX}/bin/clang} - CXX=${CXX:-${COMPILER_PREFIX}/bin/clang++} - CPP=${CPP:-${COMPILER_PREFIX}/bin/clang-cpp} - AR=${AR:-${COMPILER_PREFIX}/bin/llvm-ar} - NM=${NM:-${COMPILER_PREFIX}/bin/llvm-nm} - RANLIB=${RANLIB:-${COMPILER_PREFIX}/bin/llvm-ranlib} - FROOT=$(realpath $(dirname $(command -v gfortran))/..) - FC=$(command -v gfortran) - LD_LIBRARY_PATH="${COMPILER_PREFIX}/lib:${FROOT}/lib:${LD_LIBRARY_PATH}" - LDFLAGS="-L${HOMEBREW_PREFIX}/opt/llvm/lib/c++ -Wl,-rpath,${HOMEBREW_PREFIX}/opt/llvm/lib/c+ -L${HOMEBREW_PREFIX}/opt/libomp/lib -Wl,-no_compact_unwind" - CPPFLAGS="-isystem ${HOMEBREW_PREFIX}/opt/libomp/include" - LIBS="-lomp ${LIBS}" - CPATH="${FROOT}/include:${CPATH}" - CXXFLAGS="${CFLAGS} ${CXXFLAGS}" - FCFLAGS="${CFLAGS} ${FCFLAGS}" - CFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -Wno-deprecated-non-prototype ${CFLAGS}" - else - if $(brew --version &> /dev/null); then - brew install gcc - else - echo \"Please install Homebrew first\" - exit 1 - fi - COMPILER_PREFIX=${COMPILER_PREFIX:-"${HOMEBREW_PREFIX}/Cellar/gcc/13.1.0/"} - CC=${CC:-${COMPILER_PREFIX}/bin/gcc-13} - CXX=${CXX:-${COMPILER_PREFIX}/bin/g++-13} - CPP=${CPP:-${COMPILER_PREFIX}/bin/cpp-13} - AR=${AR:-${COMPILER_PREFIX}/bin/gcc-ar-13} - NM=${NM:-${COMPILER_PREFIX}/bin/gcc-nm-13} - RANLIB=${RANLIB:-${COMPILER_PREFIX}/bin/gcc-ranlib-13} - FC=${FC:-${COMPILER_PREFIX}/bin/gfortran-13} - LD_LIBRARY_PATH="${COMPILER_PREFIX}/lib/gcc/13:${LD_LIBRARY_PATH}" - LDFLAGS="-L${HOMEBREW_PREFIX}/opt/llvm/lib/c++ -Wl,-rpath,${HOMEBREW_PREFIX}/opt/llvm/lib/c+ -Wl,-no_compact_unwind" - CPPFLAGS="-isystem ${HOMEBREW_PREFIX}/opt/libomp/include" - LIBS="-lgomp ${LIBS}" - CPATH="${FROOT}/include:${CPATH}" - CXXFLAGS="${CFLAGS} ${CXXFLAGS}" - FCFLAGS="${CFLAGS} ${FCFLAGS}" - CFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET} -Wno-deprecated-non-prototype ${CFLAGS}" - fi + . ${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}" + FFLAGS=$FCFLAGS + LD_LIBRARY_PATH="" + CPATH="" + COMPILER_PREFIX="/usr" + CC=${COMPILER_PREFIX}/bin/clang + CXX=${COMPILER_PREFIX}/bin/clang++ + CPP=${COMPILER_PREFIX}/bin/cpp + AR=${COMPILER_PREFIX}/bin/ar + NM=${COMPILER_PREFIX}/bin/nm + 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" @@ -145,4 +65,5 @@ case $OS in exit 1 ;; esac -F77=${FC} \ No newline at end of file +F77=${FC} +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_macos.sh b/buildscripts/set_environment_macos.sh new file mode 100755 index 000000000..cd51f1865 --- /dev/null +++ b/buildscripts/set_environment_macos.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Sets environment flags on MacOS +set -a +SCRIPT_DIR=$(realpath $(dirname $0)) +ROOT_DIR=$(realpath ${SCRIPT_DIR}/..) +MACOSX_DEPLOYMENT_TARGET="$(sw_vers -productVersion)" +PREFIX="/usr/local" +HOMEBREW_PREFIX="$(brew --prefix)" +LD_LIBRARY_PATH="/usr/local/lib:${PREFIX}/lib:${HOMEBREW_PREFIX}/lib" +LDFLAGS="-Wl,-rpath,${ROOT_DIR}/lib -Wl,-no_compact_unwind -L${PREFIX}/lib -L${HOMEBREW_PREFIX}/lib" +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" +CXXFLAGS="${CFLAGS}" +HDF5_ROOT="${PREFIX}" +HDF5_LIBDIR="${HDF5_ROOT}/lib" +HDF5_INCLUDE_DIR="${HDF5_ROOT}/include" +HDF5_PLUGIN_PATH="${HDF5_LIBDIR}/plugin" +NCDIR="${PREFIX}" +NFDIR="${PREFIX}" +NETCDF_FORTRAN_HOME="${NFDIR}" +NETCDF_FORTRAN_INCLUDE="${NFDIR}/include" +FC="$(command -v gfortran-12)" +F77="${FC}" +CC="/usr/bin/clang" +CXX="/usr/bin/clang++" +CPP="/usr/bin/cpp" +AR="/usr/bin/ar" +NM="/usr/bin/nm" +RANLIB="/usr/bin/ranlib" \ No newline at end of file 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/FindCython.cmake b/cmake/Modules/FindCython.cmake deleted file mode 100644 index c59f0307c..000000000 --- a/cmake/Modules/FindCython.cmake +++ /dev/null @@ -1,89 +0,0 @@ -#.rst: -# -# Find ``cython`` executable. -# -# This module will set the following variables in your project: -# -# ``CYTHON_EXECUTABLE`` -# path to the ``cython`` program -# -# ``CYTHON_VERSION`` -# version of ``cython`` -# -# ``CYTHON_FOUND`` -# true if the program was found -# -# For more information on the Cython project, see https://cython.org/. -# -# *Cython is a language that makes writing C extensions for the Python language -# as easy as Python itself.* -# -#============================================================================= -# Copyright 2011 Kitware, Inc. -# Modified 2023 by David A. Minton (daminton@purdue.edu) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#============================================================================= - -# Use the Cython executable that lives next to the Python executable -# if it is a local installation. -if(Python_EXECUTABLE) - get_filename_component(_python_path ${Python_EXECUTABLE} PATH) -elseif(Python3_EXECUTABLE) - get_filename_component(_python_path ${Python3_EXECUTABLE} PATH) -elseif(DEFINED PYTHON_EXECUTABLE) - get_filename_component(_python_path ${PYTHON_EXECUTABLE} PATH) -endif() - -if(DEFINED _python_path) - find_program(CYTHON_EXECUTABLE - NAMES cython cython.bat cython3 - HINTS ${_python_path} - DOC "path to the cython executable") -else() - find_program(CYTHON_EXECUTABLE - NAMES cython cython.bat cython3 - DOC "path to the cython executable") -endif() - -if(CYTHON_EXECUTABLE) - set(CYTHON_version_command "${CYTHON_EXECUTABLE} --version") # Added quotes to prevent the string from having a ; inserted in the space - - execute_process(COMMAND ${CYTHON_version_command} - OUTPUT_VARIABLE CYTHON_version_output - ERROR_VARIABLE CYTHON_version_error - RESULT_VARIABLE CYTHON_version_result - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_STRIP_TRAILING_WHITESPACE) - - if(NOT ${CYTHON_version_result} EQUAL 0) - set(_error_msg "Command \"${CYTHON_version_command}\" failed with") - set(_error_msg "${_error_msg} output:\n${CYTHON_version_error}") - message(SEND_ERROR "${_error_msg}") - else() - if("${CYTHON_version_output}" MATCHES "^[Cc]ython version ([^,]+)") - set(CYTHON_VERSION "${CMAKE_MATCH_1}") - else() - if("${CYTHON_version_error}" MATCHES "^[Cc]ython version ([^,]+)") - set(CYTHON_VERSION "${CMAKE_MATCH_1}") - endif() - endif() - endif() -endif() - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cython REQUIRED_VARS CYTHON_EXECUTABLE) - -mark_as_advanced(CYTHON_EXECUTABLE) - -include(UseCython) diff --git a/cmake/Modules/FindNETCDF.cmake b/cmake/Modules/FindNETCDF.cmake deleted file mode 100644 index c93c81e75..000000000 --- a/cmake/Modules/FindNETCDF.cmake +++ /dev/null @@ -1,155 +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 - -IF (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - FIND_PATH(NFBIN - NAMES nf-config - HINTS - 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") - SET(NETCDF "netcdf") -ELSE () - IF (CMAKE_SYSTEM_NAME STREQUAL "Windows") - SET(NETCDFF "netcdff.lib") - SET(NETCDF "netcdf.lib") - ELSE () - SET(NETCDFF "libnetcdff.a") - SET(NETCDF "libnetcdf.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 - ENV NETCDF_HOME - ENV LD_LIBRARY_PATH - PATH_SUFFIXES - lib - ${CMAKE_LIBRARY_ARCHITECTURE} - REQUIRED - ) - - MESSAGE(STATUS "NetCDF-C Library: ${NETCDF_LIBRARY}") - IF (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") - 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 () - -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 d094009ed..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) @@ -71,7 +72,7 @@ FUNCTION(SET_COMPILE_FLAG FLAGVAR FLAGVAL LANG) # Now, loop over each flag FOREACH(flag ${FLAGLIST}) - + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo_append "Checking compiler option ${flag}: ") UNSET(FLAG_WORKS) # Check the flag for the given language IF(LANG STREQUAL "C") @@ -79,37 +80,21 @@ 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") # If this worked, use these flags, otherwise use other flags IF(FLAG_WORKS) + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo "OK") # Append this flag to the end of the list that already exists SET(${FLAGVAR} "${FLAGVAL} ${flag}" CACHE STRING "Set the ${FLAGVAR} flags" FORCE) SET(FLAG_FOUND TRUE) BREAK() # We found something that works, so exit + ELSE(FLAG_WORKS) + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E echo "NO") ENDIF(FLAG_WORKS) ENDFOREACH(flag ${FLAGLIST}) diff --git a/cmake/Modules/SetFortranFlags.cmake b/cmake/Modules/SetFortranFlags.cmake deleted file mode 100644 index 5d319f5d4..000000000 --- a/cmake/Modules/SetFortranFlags.cmake +++ /dev/null @@ -1,539 +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. - -###################################################### -# Determine and set the Fortran compiler flags we want -###################################################### - -#################################################################### -# Make sure that the default build type is RELEASE if not specified. -#################################################################### -INCLUDE(SetCompileFlag) - -# Make sure the build type is uppercase -STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT) - -SET(BUILD_TYPE_MSG "Choose the type of build, options are DEBUG, RELEASE, PROFILE, or TESTING.") - -IF(BT STREQUAL "RELEASE") - SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING - ${BUILD_TYPE_MSG} - FORCE) -ELSEIF(BT STREQUAL "DEBUG") - SET (CMAKE_BUILD_TYPE DEBUG CACHE STRING - ${BUILD_TYPE_MSG} - FORCE) -ELSEIF(BT STREQUAL "TESTING") - SET (CMAKE_BUILD_TYPE TESTING CACHE STRING - ${BUILD_TYPE_MSG} - FORCE) -ELSEIF(BT STREQUAL "PROFILE") - SET (CMAKE_BUILD_TYPE PROFILE CACHE STRING - ${BUILD_TYPE_MSG} - FORCE) -ELSEIF(NOT BT) - SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING - ${BUILD_TYPE_MSG} - FORCE) - MESSAGE(STATUS "CMAKE_BUILD_TYPE not given, defaulting to RELEASE") -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) - -######################################################################## -# Determine the appropriate flags for this compiler for each build type. -# For each option type, a list of possible flags is given that work -# for various compilers. The first flag that works is chosen. -# If none of the flags work, nothing is added (unless the REQUIRED -# flag is given in the call). This way unknown compiles are supported. -####################################################################### - -##################### -### 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 - ) - # Compile code assuming that IEEE signaling NaNs may generate user-visible traps during floating-point operations. - # Setting this option disables optimizations that may change the number of exceptions visible with signaling NaNs. - 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) - ) -ELSEIF (COMPILER_OPTIONS STREQUAL "Intel") - # Disables right margin wrapping in list-directed output - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-no-wrap-margin" # Intel - "/wrap-margin-" # Intel Windows - ) - - # Aligns a variable to a specified boundary and offset - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-align all -align array64byte" # Intel - "/align:all /align:array64byte" # Intel Windows - ) - - # Enables changing the variable and array memory layout - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-pad" # Intel - "/Qpad" # Intel Windows - ) -ENDIF () - -IF (NOT BUILD_SHARED_LIBS) - 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}" - Fortran "-static-intel" # Intel - ) - # Use static Intel MPI libraries - 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 (USE_OPENMP) - SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - Fortran "-lgomp" - ) - ENDIF (USE_OPENMP) - ENDIF () - -ENDIF (NOT BUILD_SHARED_LIBS) - -IF (USE_SIMD) - - IF (COMPILER_OPTIONS STREQUAL "Intel") - SET(MACHINE_CODE_VALUE "Host" CACHE STRING "Tells the compiler which processor features it may target, including which instruction sets and optimizations it may generate.") - - IF (MACHINE_CODE_VALUE STREQUAL "generic") - SET(MACHINE_CODE_VALUE "SSE2" CACHE STRING "SSE2 is the safest option when compiling for non-host compatibility" FORCE) - ENDIF() - - # Enables OpenMP SIMD compilation when OpenMP parallelization is disabled. - IF (NOT USE_OPENMP) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-qno-openmp -qopenmp-simd" # Intel - Fortran "/Qopenmp- /Qopenmp-simd" # Intel Windows - ) - ENDIF (NOT USE_OPENMP) - - # Optimize for an old enough processor that it should run on most computers - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-x${MACHINE_CODE_VALUE}" # Intel - "/Qx${MACHINE_CODE_VALUE}" # Intel Windows - ) - - # Generate an extended set of vector functions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-vecabi=cmdtarget" # Intel - "/Qvecabi:cmdtarget" # Intel Windows - ) - 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}" - 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) - ENDIF () - - IF (APPLE) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-mtune=${MACHINE_CODE_VALUE}" - ) - ELSE () - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-march=${MACHINE_CODE_VALUE}" - ) - 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 ### -################### -IF (CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "TESTING" ) - # Disable optimizations - IF (COMPILER_OPTIONS STREQUAL "Intel") - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran REQUIRED "-O0" # All compilers not on Windows - "/Od" # Intel Windows - ) - - # Turn on all warnings - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-warn all" # Intel - "/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 - "/stand:f18" # Intel Windows - ) - - # Traceback - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-traceback" # Intel Group - "/traceback" # Intel Windows - ) - - # Check everything - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-check all" # Intel - "/check:all" # Intel Windows - ) - - # Initializes matrices/arrays with NaN values - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-init=snan,arrays" # Intel - "/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 - "/nogen-interfaces" # Intel Windows - ) - - # Does not generate aposition independent executable - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-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 - "/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 - "/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 "-fpe0" # Intel - "/fpe:0" # Intel Windows - ) - - # Enables debug info - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-debug all" # Intel - "/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 "-no-ip" # Intel - "/Qip-" # Intel Windows - ) - - # Disables prefetch insertion optimization - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-qno-opt-prefetch" # Intel - "/Qopt-prefetch-" # Intel Windows - ) - - ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran REQUIRED "-Og" # GNU (gfortran) - ) - - # Turn on all warnings - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-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 - ) - - # 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 - ) - # 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 - ) - - # 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 - ) - - # Traceback - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fbacktrace" # GNU (gfortran) - ) - - # Sanitize - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fsanitize=address, undefined" # Gnu - ) - - # Check everything - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fcheck=all" # GNU - ) - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-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 - ) - - # Generates non position-independent code - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-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 - ) - - # 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 - ) - - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fstack-check" # GNU - ) - ENDIF () - -ENDIF () - -##################### -### TESTING FLAGS ### -##################### - -IF (CMAKE_BUILD_TYPE STREQUAL "TESTING" ) - - # Optimizations - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_TESTING "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran REQUIRED "-O3" # All compilers not on Windows - "/O3" # Intel Windows - ) -ENDIF () - -##################### -### RELEASE FLAGS ### -##################### -# 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") - # Unroll loops - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-unroll" # Intel - "/unroll" # Intel Windows - - ) - - # Inline functions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-inline" # Intel - "/Qinline" # Intel Windows - ) - - # Calls the Matrix Multiply library - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-qopt-matmul" # Intel - "/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 - "/align:all" # Intel Windows - ) - - # No floating-point exceptions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-fp-model no-except" # Intel - "/fp:no-except" # Intel Windows - ) - - # Generate fused multiply-add instructions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-fma" # Intel - "/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 - "-qmkl" # Intel - "/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 "-ip" # Intel - "/Qip" # Intel Windows - ) - - ELSEIF(COMPILER_OPTIONS STREQUAL "GNU") - # Unroll loops - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-funroll-loops" # GNU - ) - - # Inline functions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-finline-functions" # GNU - ) - ENDIF () - -ENDIF () - -##################### -### MATH FLAGS ### -##################### -IF (COMPILER_OPTIONS STREQUAL "Intel") - - # Some subroutines require more strict floating point operation optimizations for repeatability - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" - Fortran "-fp-model=precise" # Intel - "/fp:precise" # Intel Windows - ) - - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" - Fortran "-prec-div" # Intel - "/Qprec-div" # Intel Windows - ) - - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" - Fortran "-prec-sqrt" # Intel - "/Qprec-sqrt" # Intel Windows - ) - - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" - Fortran "-assume protect-parens" # Intel - "/assume:protect-parens" # Intel Windows - ) - - # Improves floating-point precision and consistency - SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" - Fortran "-mp1" # Intel - "/Qprec" # 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 - "/fp:fast" # Intel Windows - ) - - -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 -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran ${STRICTMATH_FLAGS} -) - -##################### -### PROFILE FLAGS ### -##################### -IF (CMAKE_BUILD_TYPE STREQUAL "PROFILE") - - IF (COMPILER_OPTIONS STREQUAL "Intel") - # Enables the optimization reports to be generated - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_PROFILE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-O2 -pg -qopt-report=5 -traceback -p -g3" # Intel - "/O2 /Qopt-report:5 /traceback /Z7" # Intel Windows - ) - ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") - # Enables the optimization reports to be generated - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_PROFILE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-O2 -pg -fbacktrace" # GNU - ) - ENDIF () -ENDIF () diff --git a/cmake/Modules/SetSwiftestFlags.cmake b/cmake/Modules/SetSwiftestFlags.cmake new file mode 100644 index 000000000..d49f42245 --- /dev/null +++ b/cmake/Modules/SetSwiftestFlags.cmake @@ -0,0 +1,680 @@ +# 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. + +###################################################### +# Determine and set the Fortran compiler flags we want +###################################################### + +#################################################################### +# Make sure that the default build type is RELEASE if not specified. +#################################################################### +INCLUDE(SetCompileFlag) + +# Make sure the build type is uppercase +STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT) + +SET(BUILD_TYPE_MSG "Choose the type of build, options are DEBUG, RELEASE, PROFILE, or TESTING.") + +IF(BT STREQUAL "RELEASE") + SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING + ${BUILD_TYPE_MSG} + FORCE) +ELSEIF(BT STREQUAL "DEBUG") + SET (CMAKE_BUILD_TYPE DEBUG CACHE STRING + ${BUILD_TYPE_MSG} + FORCE) +ELSEIF(BT STREQUAL "TESTING") + SET (CMAKE_BUILD_TYPE TESTING CACHE STRING + ${BUILD_TYPE_MSG} + FORCE) +ELSEIF(BT STREQUAL "PROFILE") + SET (CMAKE_BUILD_TYPE PROFILE CACHE STRING + ${BUILD_TYPE_MSG} + FORCE) +ELSEIF(NOT BT) + SET(CMAKE_BUILD_TYPE RELEASE CACHE STRING + ${BUILD_TYPE_MSG} + FORCE) + MESSAGE(STATUS "CMAKE_BUILD_TYPE not given, defaulting to RELEASE") +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() + +######################################################################## +# Determine the appropriate flags for this compiler for each build type. +# For each option type, a list of possible flags is given that work +# for various compilers. The first flag that works is chosen. +# If none of the flags work, nothing is added (unless the REQUIRED +# flag is given in the call). This way unknown compiles are supported. +####################################################################### + +IF (CMAKE_SYSTEM_NAME STREQUAL "Windows") + SET(WINOPT True) +ELSE () + SET(WINOPT False) +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 + ) + # Compile code assuming that IEEE signaling NaNs may generate user-visible traps during floating-point operations. + # Setting this option disables optimizations that may change the number of exceptions visible with signaling NaNs. + 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" + ) +ELSEIF (COMPILER_OPTIONS STREQUAL "Intel") + # Disables right margin wrapping in list-directed output + IF (WINOPT) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "/wrap-margin-" # Intel Windows + ) + # Aligns a variable to a specified boundary and offset + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "/align:all /align:array64byte" # Intel + ) + # Enables changing the variable and array memory layout + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "/Qpad" # Intel Windows + ) + ELSE () + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-no-wrap-margin" # Intel + ) + # Aligns a variable to a specified boundary and offset + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-align all -align array64byte" # Intel + ) + # Enables changing the variable and array memory layout + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-pad" # Intel Windows + ) + ENDIF () +ENDIF () + +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}" + Fortran "-static-intel" # Intel + ) + # Use static Intel MPI libraries + 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") + 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" + "-lgomp" + ) + ENDIF (USE_OPENMP) + ENDIF () +ENDIF () + +IF (USE_SIMD) + IF (COMPILER_OPTIONS STREQUAL "Intel") + SET(MACHINE_CODE_VALUE "Host" CACHE STRING "Tells the compiler which processor features it may target, including which instruction sets and optimizations it may generate.") + + IF (MACHINE_CODE_VALUE STREQUAL "generic") + SET(MACHINE_CODE_VALUE "SSE2" CACHE STRING "SSE2 is the safest option when compiling for non-host compatibility" FORCE) + ENDIF() + + # Enables OpenMP SIMD compilation when OpenMP parallelization is disabled. + IF (NOT USE_OPENMP) + IF (WINOPT) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "/Qopenmp- /Qopenmp-simd" # Intel + ) + ELSE () + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-qno-openmp -qopenmp-simd>" # Intel + ) + ENDIF () + ENDIF (NOT USE_OPENMP) + + # Optimize for an old enough processor that it should run on most computers + IF (WINOPT) + 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}" + Fortran "/Qvecabi:cmdtarget" # Intel Windows + ) + ELSE () + 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}" + 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}" + 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) + ENDIF () + + IF (APPLE) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-mtune=${MACHINE_CODE_VALUE}" + ) + ELSE () + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-march=${MACHINE_CODE_VALUE}" + ) + 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 ### +################### +IF (CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "TESTING" ) + # Disable optimizations + IF (COMPILER_OPTIONS STREQUAL "Intel") + IF (WINOPT) + 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 + ) + + # Does not set denormal results from floating-point calculations to zero + 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 + ) + ELSE () + 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 + ) + 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 + ) + 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 + ) + # 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 + ) + # 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 + ) + # Traceback + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fbacktrace" # GNU (gfortran) + ) + # Sanitize + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + 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 + ) + 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 + ) + 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 + ) + # Generates non position-independent code + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + 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 + ) + 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 + ) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fstack-check" # GNU + ) + SET_COMPILE_FLAG(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}" + C "-fstack-check" # GNU + ) + ENDIF () +ENDIF () + +##################### +### TESTING FLAGS ### +##################### + +IF (CMAKE_BUILD_TYPE STREQUAL "TESTING" ) + # Optimizations + IF (WINOPT) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_TESTING "${CMAKE_Fortran_FLAGS_DEBUG}" + 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}" + 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 () + +##################### +### RELEASE FLAGS ### +##################### +# 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 "/Qunroll" # Intel Windows + ) + # Inline functions + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + 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: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 + ) + ELSE () + # Unroll loops + 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 + ) + + # Calls the Matrix Multiply library + 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 + ) + + # Generate fused multiply-add instructions + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + 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 "-mkl=cluster" + "-mkl" + "-qmkl=cluster" + "-qmkl" + ) + # Enables additional interprocedural optimizations for a single file compilation + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-ip" # Intel + ) + ENDIF () + + ELSEIF(COMPILER_OPTIONS STREQUAL "GNU") + # Unroll loops + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-funroll-loops" # GNU + ) + # Inline functions + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" + 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 + ) + ELSE () + # Some subroutines require more strict floating point operation optimizations for repeatability + SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" + Fortran "-fp-model=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 +SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran ${STRICTMATH_FLAGS} +) + +##################### +### PROFILE FLAGS ### +##################### +IF (CMAKE_BUILD_TYPE STREQUAL "PROFILE") + IF (COMPILER_OPTIONS STREQUAL "Intel") + # Enables the optimization reports to be generated + IF (WINOPT) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_PROFILE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "/O2 /Qopt-report:5 /traceback /Z7" # Intel Windows + ) + ELSE () + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_PROFILE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-O2 -pg -qopt-report=5 -traceback -p -g3" # Intel + ) + ENDIF () + ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") + # Enables the optimization reports to be generated + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_PROFILE "${CMAKE_Fortran_FLAGS_RELEASE}" + Fortran "-O2 -pg -fbacktrace" # GNU + ) + ENDIF () +ENDIF () 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 d01195c6c..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}/..") @@ -19,7 +20,7 @@ ELSE() SET(TOPDIR "${CMAKE_SOURCE_DIR}") ENDIF() -SET(CIBW_DIR "_skbuild" "swiftest.egg-info") +SET(CIBW_DIR "_skbuild" "swiftest.egg-info" "_cmake_test_compile") MACRO(GET_PARENT_DIRECTORIES search_string return_list grandparents) FILE(GLOB_RECURSE new_list ${search_string}) @@ -46,8 +47,10 @@ FILE(GLOB_RECURSE CMAKEINSTALL "${TOPDIR}/*cmake_install.cmake" FILE(GLOB_RECURSE MAKEFILE "${TOPDIR}/*Makefile") FILE(GLOB_RECURSE CMAKETESTFILES "${TOPDIR}/*CTestTestfile.cmake") SET(TOPDIRECTORIES "${TOPDIR}/lib" + "${TOPDIR}/libexec" "${TOPDIR}/bin" "${TOPDIR}/include" + "${TOPDIR}/share" ) # CMake has trouble finding directories recursively, so locate these diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..000ea3455 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,17 @@ +# Welcome to MkDocs + +For full documentation visit [mkdocs.org](https://www.mkdocs.org). + +## Commands + +* `mkdocs new [dir-name]` - Create a new project. +* `mkdocs serve` - Start the live-reloading docs server. +* `mkdocs build` - Build the documentation site. +* `mkdocs -h` - Print help message and exit. + +## Project layout + + mkdocs.yml # The configuration file. + docs/ + index.md # The documentation homepage. + ... # Other markdown pages, images and other files. diff --git a/environment.yml b/environment.yml index 015c642f1..933cb3fe1 100644 --- a/environment.yml +++ b/environment.yml @@ -7,9 +7,9 @@ channels: dependencies: - python>=3.8 - numpy>=1.24.3 - - pandas>=1.5.3 - scipy>=1.10.1 - xarray>=2022.11.0 + - distributed>=2022.1 - dask>=2022.1 - bottleneck>=1.3.5 - h5netcdf>=1.0.2 @@ -20,4 +20,4 @@ dependencies: - tqdm>=4.65.0 - x264>=1!157.20191217 - ffmpeg>=4.3.2 - - py>=1.11 \ No newline at end of file + - cython>=3.0.0 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/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..d15a0315d --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,6 @@ +site_name: MkLorum +site_url: https://example.com/ +nav: + - Home: index.md + - About: about.md +theme: readthedocs \ No newline at end of file diff --git a/paper/paper.bib b/paper/paper.bib index fddf9bdaf..6e6260224 100644 --- a/paper/paper.bib +++ b/paper/paper.bib @@ -1,32 +1,174 @@ -@article{Levison:1994, - Author = {{Levison}, H. and {Duncan}, M.}, - Journal = {Icarus}, - Title = {{The Long-Term Dynamical Behavior of Short-Period Comets}}, - Year = 1994, - Month = mar, - Volume = 108, - DOI = {10.1006/icar.1994.1039}, - url = {https://www.sciencedirect.com/science/article/pii/S0019103584710396?via%3Dihub} +@article{Chambers:1999, + author = {{Chambers}, J.~E.}, + title = "{A hybrid symplectic integrator that permits close encounters between massive bodies}", + journal = {Monthly Notices of the Royal Astronomical Society}, + keywords = {ACCRETION, ACCRETION DISCS, METHODS: NUMERICAL, CELESTIAL MECHANICS, STELLAR DYNAMICS, SOLAR SYSTEM: GENERAL}, + year = 1999, + month = apr, + volume = {304}, + number = {4}, + pages = {793-799}, + doi = {10.1046/j.1365-8711.1999.02379.x}, + adsurl = {https://ui.adsabs.harvard.edu/abs/1999MNRAS.304..793C}, + adsnote = {Provided by the SAO/NASA Astrophysics Data System} } @article{Duncan:1998, - Author = {{Duncan}, M., {Levison}, H., and {Lee}, M. H.}, - Journal = {The Astronomical Journal}, - Title = {{A Multiple Time Step Symplectic Algorithm for Integrating Close Encounters}}, - Year = 1998, - Month = oct, - Volume = 116, - DOI = {10.1086/300541}, - url = {https://iopscience.iop.org/article/10.1086/300541} + title = {A {Multiple} {Time} {Step} {Symplectic} {Algorithm} for {Integrating} {Close} {Encounters}}, + volume = {116}, + url = {http://stacks.iop.org/1538-3881/116/i=4/a=2067}, + doi = {10.1086/300541}, + number = {4}, + journal = {The Astronomical Journal}, + author = {Duncan, Martin J. and Levison, Harold~F. and Lee, Man Hoi}, + month = oct, + year = {1998}, + pages = {2067--2077}, +} + + +@article{Grimm:2022, + title = {{GENGA}. {II}. {GPU} {Planetary} {N}-body {Simulations} with {Non}-{Newtonian} {Forces} and {High} {Number} of {Particles}}, + volume = {932}, + issn = {0004-637X}, + url = {https://dx.doi.org/10.3847/1538-4357/ac6dd2}, + doi = {10.3847/1538-4357/ac6dd2}, + language = {en}, + number = {2}, + urldate = {2023-10-06}, + journal = {The Astrophysical Journal}, + author = {Grimm, Simon L. and Stadel, Joachim G. and Brasser, Ramon and Meier, Matthias M. M. and Mordasini, Christoph}, + month = jun, + year = {2022}, + pages = {124}, +} + + +@misc{kaufmann_swifter_nodate, + title = {Swifter}, + url = {https://www.boulder.swri.edu/swifter/}, + abstract = {The Swifter software package, written by David E. Kaufmann, is a completely redesigned and improved version of the Swift package of Hal Levison and Martin Duncan. Like Swift, Swifter is designed to integrate a set of mutually gravitationally interacting bodies together with a group of massless test particles that feel the gravitational influence of the massive bodies but do not affect each other or the massive bodies. In addition, the SyMBA integrator supports a second class of massive bodies whose masses are less than some user-specified value. These bodies gravitationally interact with the more massive bodies, but do not interact with each other. Seven integration techniques are included in the current beta release of Swifter:}, + urldate = {2023-10-06}, + journal = {Swifter — an improved solar system integration software package}, + author = {Kaufmann, David E.}, } @article{Leinhardt:2012, - Author = {{Leinhardt}, Z. and {Stewart}, S.}, - Journal = {The Astronomical Journal}, - Title = {{Collisions between Gravity-dominated Bodies. I. Outcome Regimes and Scaling Laws.}}, - Year = 2012, - Month = dec, - Volume = 745, - DOI = {10.1088/0004-637X/745/1/79}, - url = {https://iopscience.iop.org/article/10.1088/0004-637X/745/1/79} + title = {Collisions between {Gravity}-dominated {Bodies}. {I}. {Outcome} {Regimes} and {Scaling} {Laws}}, + volume = {745}, + url = {http://stacks.iop.org/0004-637X/745/i=1/a=79}, + doi = {10.1088/0004-637X/745/1/79}, + number = {1}, + journal = {The Astrophysical Journal}, + author = {Leinhardt, Zoë M and Stewart, Sarah T}, + month = jan, + year = {2012}, + pages = {79}, +} + + +@article{Levison:1994, + author = {{Levison}, Harold F. and {Duncan}, M.}, + title = {{The Long-Term Dynamical Behavior of Short-Period Comets}}, + journal = {Icarus}, + year = 1994, + month = mar, + volume = 108, + doi = {10.1006/icar.1994.1039}, + url = {https://www.sciencedirect.com/science/article/pii/S0019103584710396?via%3Dihub} +} + + +@article{Levison:2000, + title = {Symplectically {Integrating} {Close} {Encounters} with the {Sun}}, + volume = {120}, + issn = {0004-6256}, + url = {http://dx.doi.org/10.1086/301553}, + doi = {10.1086/301553}, + number = {4}, + journal = {The Astronomical Journal}, + author = {{Levison}, Harold F. and {Duncan}, Martin J.}, + month = oct, + year = {2000}, + pages = {2117--2123}, +} + +@article{Moore:2011, + title = {{QYMSYM}: {A} {GPU}-accelerated hybrid symplectic integrator that permits close encounters}, + volume = {16}, + url = {http://adsabs.harvard.edu/cgi-bin/nph-data_query?bibcode=2011NewA...16..445M&link_type=ABSTRACT}, + doi = {10.1016/j.newast.2011.03.009}, + number = {7}, + journal = {New Astronomy}, + author = {Moore, Alexander and Quillen, Alice C.}, + month = nov, + year = {2011}, + pages = {445--455}, +} + +@article{Rein:2012, + title = {{REBOUND}: an open-source multi-purpose {N}-body code for collisional dynamics}, + volume = {537}, + url = {http://www.aanda.org/10.1051/0004-6361/201118085}, + doi = {10.1051/0004-6361/201118085}, + journal = {Astronomy \& Astrophysics}, + author = {{Rein}, Hanno and {Liu}, S. F.}, + month = jan, + year = {2012}, + pages = {A128}, +} + + +@article{Rein:2015, + title = {WHFAST: a fast and unbiased implementation of a symplectic {Wisdom}–{Holman} integrator for long-term gravitational simulations}, + volume = {452}, + issn = {0035-8711}, + shorttitle = {whfast}, + url = {https://doi.org/10.1093/mnras/stv1257}, + doi = {10.1093/mnras/stv1257}, + number = {1}, + urldate = {2023-10-06}, + journal = {Monthly Notices of the Royal Astronomical Society}, + author = {{Rein}, Hanno and {Tamayo}, Daniel}, + month = sep, + year = {2015}, + pages = {376--388}, +} + +@article{Saha:1994, + title = {Long-term planetary integration with individual time steps}, + volume = {108}, + url = {http://adsabs.harvard.edu/cgi-bin/nph-data_query?bibcode=1994AJ....108.1962S&link_type=ABSTRACT}, + doi = {10.1086/117210}, + journal = {The Astronomical Journal}, + author = {Saha, Prasenjit and Tremaine, Scott}, + month = nov, + year = {1994}, + pages = {1962--1969}, +} + +@article{Stewart:2012, + title = {Collisions between {Gravity}-dominated {Bodies}. {II}. {The} {Diversity} of {Impact} {Outcomes} during the {End} {Stage} of {Planet} {Formation}}, + volume = {751}, + url = {http://stacks.iop.org/0004-637X/751/i=1/a=32}, + doi = {10.1088/0004-637X/751/1/32}, + number = {1}, + journal = {The Astrophysical Journal}, + author = {Stewart, Sarah T and Leinhardt, Zoë M}, + month = jan, + year = {2012}, + pages = {32}, +} + + +@article{Wisdom:1991, + title = {Symplectic maps for the n-body problem}, + volume = {102}, + url = {http://adsabs.harvard.edu/cgi-bin/bib_query?1991AJ....102.1528W}, + doi = {10.1086/115978}, + journal = {The Astronomical Journal}, + author = {Wisdom, Jack and Holman, Matthew}, + month = oct, + year = {1991}, + pages = {1528--1538}, } diff --git a/paper/paper.md b/paper/paper.md index f5c8c6310..402c75632 100644 --- a/paper/paper.md +++ b/paper/paper.md @@ -9,48 +9,77 @@ tags: - Planetary Systems authors: - name: Carlisle Wishard + affiliation: "1,4" orcid: 0009-0001-0733-3268 equal-contrib: true - corresponding: true - affiliation: 1 - - name: David Minton - equal-contrib: true - affiliation: 1 - name: Jennifer Pouplin - affiliation: "1" - - name: Jake Elliott + affiliation: "1,3" + - name: Jacob Elliott affiliation: "1" - name: Dana Singh + affiliation: "5" + - name: Kaustub Anand + affiliation: "1, 2" + - name: David Minton affiliation: "1" + orcid: 0000-0003-1656-9704 + equal-contrib: true + corresponding: true affiliations: - - name: Department of Earth, Atmospheric, and Planetary Sciences, Purdue University, USA - index: 1 -date: 05 April 2023 + - name: Department of Earth, Atmospheric, and Planetary Sciences, Purdue University, USA + index: 1 + - name: School of Aeronautics and Astronautics, Purdue University, USA + index: 2 + - name: Department of Physics and Astronomy, Purdue University, USA + index: 3 + - name: Evansville Museum of Arts, History & Science, USA + index: 4 + - name : SAIC, Princeton, NJ, USA + index: 5 + +date: 06 October 2023 bibliography: paper.bib --- # Summary - -The dynamical evolution of planetary systems is dominated by gravitational interactions between massive bodies. Determining the orbits of massive bodies over long time scales is the first step towards understanding the formation and evolution of planets, moons, asteroids, comets, and more. To model these systems, which often include hundreds or thousands of gravitationally interacting bodies, a numerical tool called an \textit{n}-body integrator is often employed. +`Swiftest` is a software package designed to model the long-term dynamics of system of bodies in orbit around a dominant central body, such a planetary system around a star, or a satellite system around a planet. The main body of the program is written in Modern Fortran, taking advantage of the object-oriented capabilities included with Fortran 2003 and the parallel capabilities included with Fortran 2008 and Fortran 2018. `Swiftest` also includes a Python package that allows the user to quickly generate input, run simulations, and process output from the simulations. `Swiftest` uses a NetCDF output file format which makes data analysis with the `Swiftest` Python package a streamlined and flexible process for the user. # Statement of Need +Building off a strong legacy, including its predecessors `Swifter` [@kaufmann_swifter_nodate] and `Swift` [@Levison:1994], `Swiftest` takes the next step in modeling the dynamics of planetary systems by improving the performance and ease of use of software, and by introducing a new collisional fragmentation model. Currently, `Swiftest` includes the four main symplectic integrators included in its predecessors: -`Swiftest` is a software package designed to model gravitationally dominated systems. The main body of the program is written in Modern Fortran, taking advantage of the object-oriented capabilities included with Fortran 2003 and the parallel capabilities included with Fortran 2008 and Fortran 2018. `Swiftest` also includes a Python package that allows the user to quickly generate input and process output from the main integrator. `Swiftest` uses a NetCDF output file format which makes data analysis with the `Swiftest` Python package a streamlined and flexible process for the user. +WHM + : Wisdom-Holman method. `WHM` is a symplectic integrator that is best suited for cases in which the orbiting bodies do not have close encounters with each other. For details see @Wisdom:1991. -Building off a strong legacy, including its predecessors `Swifter` [@Duncan:1998] and `Swift` [@Levison:1994], `Swiftest` takes the next step in modeling gravitationally dominated systems by including collisional fragmentation. Our collisional fragmentation algorithm, `Fraggle` (based on the work of @Leinhardt:2012), is designed to resolve collisions between massive bodies and generate collisional debris. `Swiftest` fully incorporates this debris into the gravitational system, evolving these new bodies along with pre-existing bodies. This allows for a more complete model of the orbital evolution of the system and the growth of massive bodies. +RMVS + : Regularized Mixed Variable Symplectic. `RMVS` is an extension of `WHM` that handles close approaches between test particles and massive bodies. For details, see @Levison:1994. -The combination of modern programming practices, flexible data processing tools, and the latest advances in the field of collisional dynamics make `Swiftest` the ideal tool for studying the formation of planetary systems, the growth of planetary moons, the evolution of asteroid families, and beyond. +HELIO + : Democratic Heliocentric method. This is a basic symplectic integrator that uses democratic heliocentric coordinates instead of the Jacobi coordinates used by `WHM`. Like `WHM` it is not suited for simulating close encounters between orbiting bodies. For details, see @Duncan:1998. -# Performance +SyMBA + : Symplectic Massive Body Algorithm. This is an extension of `HELIO` that handles close approaches between massive bodies and any of the other objects in the simulation. It also includes semi-interacting massive bodies that can gravitationally influence fully massive bodies but not each other. This algorithm is described in the @Duncan:1998. See also @Levison:2000. + +All of the integrators that are currently implemented are based symplectic integrators, which are designed to model massive bodies (e.g. planets) or test particles (e.g. asteroids) in orbit of a single dominant central body (e.g. the Sun) for very long periods of times (e.g. Gy). The core components of `Swiftest` were inherited from the `Swift`/`Swifter` codebase, but have been somewhat modified for performance. The `Swift`-family of integrators are most comparable to other symplectic integrators, which are among the most popular numerical methods used to study the long-term dynamics of planetary systems. + +The `SyMBA` integrator included in `Swiftest` is most similar to the hybrid symplectic integrator `MERCURY6` [@Chambers:1999], the `MERCURIUS` integrator of `REBOUND` [@Rein:2012;@Rein:2015], and the GPU-enabled hybrid symplectic integrators such as `QYMSYM` [@Moore:2011] and `GENGA II` [@Grimm:2022], with some important distinctions. The hybrid symplectic integrators typically employ a symplectic method, such as the original WHM method in Jacobi coordinates or the modified method that uses the Democratic Heliocentric coordinates, only when bodies are far from each other relative to their gravitational spheres of influence (some multiple of a Hill's sphere). When bodies approach each other, the integration is smoothly switched to a non-symplectic method, such as Bulirsch-Stoer or IAS15. In contrast, `SyMBA` is a multi-step method that recursively subdivides the step size of bodies undergoing close approach with each other. +In addition `Swiftest` contains a number of significant enhancements relative to its predecessors: + +- It includes a fully symplectic implementation of the post-Newtonian correction (General Relativity) as described in @Saha:1994. +- Output data is stored in NetCDF4 (HDF5) format, making data analysis, cross-platform compatibility, and portability far more robust than the flat binary file formats used by its predecessors. +- It makes use of CPU-based parallelization via OpenMP. It also makes use of SIMD instructions, but these are available only when compiled for target host machine rather than when installed from PyPI via pip. +- Simulations can be run by means of a standalone binary driver program, similar to its predecessors, or from a compiled Python module. Both the standalone driver and Python module link to the same compiled library, so simulations run by either method are identical. +- It comes with an extensive set of Python scripts to help generate simulation initial conditions and post-process simulation results. +- It includes the `Fraggle` collisional fragmentation model that is used to generate collisional fragments on trajectories that conserve linear and angular momentum and lose the appropriate amount of collisional energy for inelastic collisions between massive bodies in `SyMBA` simulations. The collisional outcome is determined using standard methods based on the work of @Leinhardt:2012 and @Stewart:2012. + +# Performance Modeling the behavior of thousands of fully interacting bodies over long timescales is computationally expensive, with typical runs taking weeks or months to complete. The addition of collisional fragmentation can quickly generate hundreds or thousands of new bodies in a short time period, creating further computational challenges for traditional \textit{n}-body integrators. As a result, enhancing computational performance was a key aspect of the development of `Swiftest`. Here we show a comparison between the performance of `Swift`, `Swifter-OMP` (a parallel version of `Swifter`), and `Swiftest` on simulations with 1k, 2k, 8k, and 16k fully interacting bodies. The number of cores dedicated to each run is varied from 1 to 24 to test the parallel performance of each program. \autoref{fig:performance} shows the results of this performance test. We can see that `Swiftest` outperforms `Swifter-OMP` and `Swift` in each simulation set, even when run in serial. When run in parallel, `Swiftest` shows a significant performance boost when the number of bodies is increased. The improved performance of `Swiftest` compared to `Swifter-OMP` and `Swift` is a critical step forward in \textit{n}-body modeling, providing a powerful tool for modeling the dynamical evolution of planetary systems. -![Performance testing of `Swiftest` on systems of (a) 1k, (b) 2k, (c) 8k, and (d) 16k fully interacting massive bodies. All simulations were run using the \textit{SyMBA} integrator included in `Swift`, `Swifter-OMP`, and `Swiftest`. Speedup is measured relative to `Swift` (dashed), with an ideal 1:1 speedup relative to `Swiftest` in serial shown as an upper limit (dotted). The performance of `Swifter-OMP` is shown in green while the performance of `Swiftest` is shown in blue. All simulations were run on the Purdue University Rosen Center for Advanced Computing Brown Community Cluster. Brown contains 550 Dell compute nodes, with each node containing 2 12-core Intel Xeon Gold Sky Lake processors, resulting in 24 cores per node. Each node has 96 GB of memory. \label{fig:performance}](performance.png) +![Performance testing of `Swiftest` on systems of (a) 1k, (b) 2k, (c) 8k, and (d) 16k fully interacting massive bodies. All simulations were run using the \textit{SyMBA} integrator included in `Swift`, `Swifter-OMP` (and earlier attempt to parallelize `Swifter`), and `Swiftest`. Speedup is measured relative to `Swiftest` for 1 CPU (dashed), with an ideal 1:1 speedup shown as an upper limit (dotted). The performance of `Swifter-OMP` is shown in green while the performance of `Swiftest` is shown in blue. All simulations were run on the Purdue University Rosen Center for Advanced Computing Brown Community Cluster. Brown contains 550 Dell compute nodes, with each node containing 2 12-core Intel Xeon Gold Sky Lake processors, resulting in 24 cores per node. Each node has 96 GB of memory. \label{fig:performance}](performance.png) # Acknowledgements - `Swiftest` was developed at Purdue University and was funded under the NASA Emerging Worlds and Solar System Workings programs. Active development by the Purdue Swiftest Team is ongoing and contributions from the community are highly encouraged. # References diff --git a/paper/performance.png b/paper/performance.png index 7a425e840..7f95d781e 100644 Binary files a/paper/performance.png and b/paper/performance.png differ diff --git a/pyproject.toml b/pyproject.toml index d81ff9775..0424270c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,31 +1,132 @@ +[project] +name = "swiftest" +version = "2023.10.3" +authors=[ + {name = 'David A. Minton', email='daminton@purdue.edu'}, + {name = 'Carlisle Wishard'}, + {name = 'Jennifer Pouplin'}, + {name = 'Jake Elliott'}, + {name = 'Dana Singh'}, + {name = 'Kaustub Anand'}, +] +maintainers = [ + {name = 'David A. Minton', email='daminton@purdue.edu'}, +] +readme = "README.md" +requires-python=">=3.8" +license={file = "LICENSE"} +classifiers=[ +'Development Status :: 3 - Alpha', +'Intended Audience :: Science/Research', +'Topic :: Scientific/Engineering :: Astronomy', +'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', +'Programming Language :: Python :: 3', +] +keywords=['astronomy','astrophysics', 'planetary', 'n-body', 'integrator', 'symplectic', 'wisdom-holman', 'symba'] +dependencies = [ + 'numpy>=1.24.3', + 'scipy>=1.10.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.66', + 'cython>=3.0.0', + 'mkdocs>=1.5.3' +] + +[project.urls] +Repository = 'https://github.itap.purdue.edu/MintonGroup/swiftest' + [build-system] requires = [ - "setuptools>=42", - "scikit-build>=0.17", - "cmake>=3.5.0", + "scikit-build-core", "cython>=3.0.0", - "ninja", "pytest", ] -build-backend = "setuptools.build_meta" +build-backend = "scikit_build_core.build" + +[tool.scikit-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] -environment = {SKBUILD_CONFIGURE_OPTIONS="-DBUILD_SHARED_LIBS=OFF"} test-command = "pytest {package}/tests" -test-requires = ['pytest','cython'] -test-skip = "cp312-*" +test-requires = ['pytest'] skip = "pp* *i686 *-manylinux_i686 *_ppc64le *_s390x *-musllinux* *-win32" +build-verbosity = 1 -[tool.cibuildwheel.linux] -environment = {FFLAGS="${FFLAGS} -fPIC", CFLAGS="${CFLAGS} -fPIC", LDFLAGS="${LDFLAGS} -fPIE", LIBS="-lgomp"} +[tool.cibuildwheel.macos.environment] +ROOT_DIR="$(pwd)" +MACOSX_DEPLOYMENT_TARGET="$(sw_vers -productVersion)" +PREFIX="/usr/local" +HOMEBREW_PREFIX="$(brew --prefix)" +ARCH="$(uname -m)" +LD_LIBRARY_PATH="/usr/local/lib:${PREFIX}/lib:${HOMEBREW_PREFIX}/lib" +LDFLAGS="-Wl,-rpath,${ROOT_DIR}/lib -Wl,-no_compact_unwind -L${PREFIX}/lib -L${HOMEBREW_PREFIX}/lib" +CPATH="/usr/local/include:${PREFIX}/include:${HOMEBREW_PREFIX}/include:${ROOT_DIR}/include" +CPPFLAGS="-isystem ${PREFIX}/include -isystem /usr/local/include" +LIBS="-lomp" +FCFLAGS="-mmacos-version-min=${MACOSX_DEPLOYMENT_TARGET} -arch ${ARCH}" +FFFLAGS="${FCFLAGS}" +CFLAGS="${FCFLAGS} -Wno-deprecated-non-prototype -arch ${ARCH}" +CXXFLAGS="${CFLAGS}" +HDF5_ROOT="${PREFIX}" +HDF5_LIBDIR="${HDF5_ROOT}/lib" +HDF5_INCLUDE_DIR="${HDF5_ROOT}/include" +HDF5_PLUGIN_PATH="${HDF5_LIBDIR}/plugin" +NCDIR="${PREFIX}" +NFDIR="${PREFIX}" +NETCDF_FORTRAN_HOME="${NFDIR}" +NETCDF_FORTRAN_INCLUDE="${NFDIR}/include" +FC="$(command -v gfortran-12)" +F77="${FC}" +CC="/usr/bin/clang" +CXX="/usr/bin/clang++" +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 = [ - "yum install doxygen -y || apt-get install doxygen -y", - "buildscripts/build_dependencies.sh -d /_dependencies -p /usr/local", + "brew install coreutils", + "LIBS=\"\" buildscripts/build_dependencies.sh -p ${PREFIX} -d ${HOME}/Downloads -m ${MACOSX_DEPLOYMENT_TARGET}" ] -[tool.cibuildwheel.macos] +[tool.cibuildwheel.linux] +skip = "cp312-* pp* -manylinux_i686* *-musllinux*" before-all = [ - "buildscripts/build_dependencies.sh -d ${TMPDIR} -p ${TMPDIR} -m ${MACOSX_DEPLOYMENT_TARGET}" + "yum install doxygen libxml2-devel libcurl-devel -y", + "buildscripts/build_dependencies.sh -p /usr/local" ] +[tool.cibuildwheel.linux.environment] +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" - \ No newline at end of file +[[tool.scikit-build.generate]] +path = "version.txt" +location = "source" +template = '''${version}''' \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e8492468c..79d85b58b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ scipy>=1.10.1 xarray>=2022.11.0 dask>=2022.1 bottleneck>=1.3.5 +distributed>=2022.1 h5netcdf>=1.0.2 netcdf4>=1.6.2 matplotlib>=3.7.1 diff --git a/setup.py b/setup.py deleted file mode 100644 index a327a2cce..000000000 --- a/setup.py +++ /dev/null @@ -1,63 +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. -""" - -from skbuild import setup -from pathlib import Path - -with open('version.txt') as version_file: - version = version_file.read().strip() - -setup(name='swiftest', - version=version, - author='David A. Minton', - author_email='daminton@purdue.edu', - url='https://github.itap.purdue.edu/MintonGroup/swiftest', - long_description=Path("README.md").read_text(encoding="utf-8"), - long_description_content_type="text/markdown", - python_requires=">=3.8", - license="GPLv3", - classifiers=[ - # How mature is this project? Common values are - # 3 - Alpha - # 4 - Beta - # 5 - Production/Stable - 'Development Status :: 3 - Alpha', - - # Indicate who your project is intended for - 'Intended Audience :: Science/Research', - 'Topic :: Scientific/Engineering :: Astronomy', - - # Pick your license as you wish (should match "license" above) - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - - # Specify the Python versions you support here. In particular, ensure - # that you indicate whether you support Python 2, Python 3 or both. - 'Programming Language :: Python :: 3', - ], - keywords='astronomy astrophysics planetary nbody integrator symplectic wisdom-holman', - install_requires= [ - 'numpy>=1.24.3', - 'scipy>=1.10.1', - 'xarray>=2022.11.0', - 'dask>=2022.1', - 'bottleneck>=1.3.5', - 'h5netcdf>=1.0.2', - 'netcdf4>=1.6.2', - 'matplotlib>=3.7.1', - 'astropy>=5.1', - 'astroquery>=0.4.6', - 'tqdm>=4.65.0', - 'cython>=3.0.0', - ], - packages=['swiftest'], - test_suite="swiftest.tests", - ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 403336a8f..925d70005 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,28 +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) - -IF (CMAKE_Fortran_COMPILER_ID MATCHES "^Intel") - SET(COMPILER_OPTIONS "Intel" CACHE STRING "Compiler identified as Intel") -ELSEIF (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") - SET(COMPILER_OPTIONS "GNU" CACHE STRING "Compiler identified as gfortran") -ELSE () - MESSAGE(FATAL_ERROR "Compiler not recognized!") -ENDIF () - -INCLUDE(SetParallelizationLibrary) -INCLUDE(SetUpNetCDF) -IF (COMPILER_OPTIONS STREQUAL "Intel") - 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 @@ -148,22 +126,24 @@ ADD_EXECUTABLE(${SWIFTEST_DRIVER} ${DRIVER_src}) # Add the needed libraries ##################################################### # Create a library from the source files, except the driver -SET(SWIFTEST_LIBRARY swiftest) + 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} ") SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY LINK_FLAGS "${OpenMP_Fortran_FLAGS} ") ENDIF() +IF (CMAKE_SYSTEM_NAME STREQUAL "Windows") + SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY LINK_FLAGS "/NODEFAULTLIB") +ENDIF() + IF(USE_COARRAY) TARGET_COMPILE_DEFINITIONS(${SWIFTEST_LIBRARY} PUBLIC -DCOARRAY) TARGET_COMPILE_DEFINITIONS(${SWIFTEST_DRIVER} PUBLIC -DCOARRAY) @@ -172,10 +152,9 @@ IF(USE_COARRAY) ENDIF(USE_COARRAY) # Check to see if the compiler allows for local-spec in do concurrent statements. Set a preprocessor variable if it does -IF (USE_OPENMP) - SET(TESTFILE "${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}") - SET(TESTFILE "${TESTFILE}/CMakeTmp/testFortranDoConcurrentLoc.f90") - FILE(WRITE "${TESTFILE}" +SET(TESTFILE "${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}") +SET(TESTFILE "${TESTFILE}/CMakeTmp/testFortranDoConcurrentLoc.f90") +FILE(WRITE "${TESTFILE}" " program TestDoConcurrentLoc integer :: i @@ -185,27 +164,36 @@ do concurrent(i = 1:10) shared(a) end do end program TestDoConcurrentLoc ") - TRY_COMPILE(DOCONLOC_WORKS ${CMAKE_BINARY_DIR} ${TESTFILE} - COMPILE_DEFINITIONS "${CMAKE_Fortran_FLAGS}" OUTPUT_VARIABLE OUTPUT) - IF (DOCONLOC_WORKS) - TARGET_COMPILE_DEFINITIONS(${SWIFTEST_DRIVER} PRIVATE -DDOCONLOC) - ENDIF (DOCONLOC_WORKS) -ENDIF (USE_OPENMP) - - -##################################### -# Tell how to install this executable -##################################### -IF(WIN32) - SET(CMAKE_INSTALL_PREFIX "C:\\Program Files") - FILE(TO_CMAKE_PATH ${CMAKE_INSTALL_PREFIX} CMAKE_INSTALL_PREFIX) -ELSE() - SET(CMAKE_INSTALL_PREFIX /usr/local) -ENDIF(WIN32) -INSTALL(TARGETS ${SWIFTEST_DRIVER} ${SWIFTEST_LIBRARY} - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - INCLUDES DESTINATION include -) +TRY_COMPILE(DOCONLOC_WORKS ${CMAKE_BINARY_DIR} ${TESTFILE} COMPILE_DEFINITIONS "${CMAKE_Fortran_FLAGS}" OUTPUT_VARIABLE OUTPUT) +IF (DOCONLOC_WORKS) + MESSAGE(STATUS "DO CONCURRENT supports locality-spec") + TARGET_COMPILE_DEFINITIONS(${SWIFTEST_DRIVER} PRIVATE -DDOCONLOC) +ELSE () + MESSAGE(STATUS "DO CONCURRENT does not support locality-spec") +ENDIF (DOCONLOC_WORKS) + +# Check to see if quad precision is supported +SET(TESTFILE "${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}") +SET(TESTFILE "${TESTFILE}/CMakeTmp/testFortranQuadPrecisionReal.f90") +FILE(WRITE "${TESTFILE}" +" +program TestQuadPrecisionReal +integer, parameter :: QP = selected_Real_kind(30) +real(QP) :: x +end program TestQuadPrecisionReal +") +TRY_COMPILE(QUADPREC ${CMAKE_BINARY_DIR} ${TESTFILE} COMPILE_DEFINITIONS "${CMAKE_Fortran_FLAGS}" OUTPUT_VARIABLE OUTPUT) +IF (QUADPREC) + MESSAGE(STATUS "Quad precision real is supported") + TARGET_COMPILE_DEFINITIONS(${SWIFTEST_DRIVER} PRIVATE -DQUADPREC) +ELSE () + MESSAGE(STATUS "Quad precision real is not supported") +ENDIF () +# Define the install locations +INSTALL(TARGETS ${SWIFTEST_DRIVER} ${SWIFTEST_LIBRARY} + RUNTIME DESTINATION ${INSTALL_BINDIR} + LIBRARY DESTINATION ${INSTALL_LIBDIR} + ARCHIVE DESTINATION ${INSTALL_LIBDIR} + INCLUDES DESTINATION ${INSTALL_INCLUDEDIR} +) diff --git a/src/coarray/coarray_clone.f90 b/src/coarray/coarray_clone.f90 index 893cff147..ea33f8544 100644 --- a/src/coarray/coarray_clone.f90 +++ b/src/coarray/coarray_clone.f90 @@ -469,6 +469,7 @@ module subroutine coarray_component_clone_lgt_arr1D(var,src_img) end subroutine coarray_component_clone_lgt_arr1D +#ifdef QUADPREC module subroutine coarray_component_clone_QP(var,src_img) !! author: David A. Minton !! @@ -503,5 +504,6 @@ module subroutine coarray_component_clone_QP(var,src_img) return end subroutine coarray_component_clone_QP +#endif end submodule s_coarray_clone \ No newline at end of file diff --git a/src/coarray/coarray_module.f90 b/src/coarray/coarray_module.f90 index b034f8786..22ce10c55 100644 --- a/src/coarray/coarray_module.f90 +++ b/src/coarray/coarray_module.f90 @@ -71,11 +71,13 @@ module subroutine coarray_component_clone_lgt_arr1D(var,src_img) integer(I4B), intent(in),optional :: src_img end subroutine coarray_component_clone_lgt_arr1D +#ifdef QUADPREC module subroutine coarray_component_clone_QP(var,src_img) implicit none real(QP), intent(inout) :: var integer(I4B), intent(in),optional :: src_img end subroutine coarray_component_clone_QP +#endif end interface 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 309a5d14e..d1a466d29 100644 --- a/src/globals/globals_module.f90 +++ b/src/globals/globals_module.f90 @@ -24,7 +24,11 @@ module globals integer, parameter :: SP = real32 !! Symbolic name for kind types of single-precision reals integer, parameter :: DP = real64 !! Symbolic name for kind types of double-precision reals - integer, parameter :: QP = real128 !! Symbolic name for kind types of quad-precision reals +#ifdef QUADPREC + integer, parameter :: QP = selected_Real_kind(30) !! Symbolic name for kind types of quad-precision reals +#else + integer, parameter :: QP = real64 !! Stick to DP +#endif real(DP), parameter :: PIBY2 = 1.570796326794896619231321691639751442099_DP !! Definition of /(\pi / 2\) real(DP), parameter :: PI = 3.141592653589793238462643383279502884197_DP !! Definition of /(\pi\) @@ -44,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.8.0" !! Swiftest version + character(*), parameter :: VERSION = "2023.10.3" !! Swiftest version !> Symbolic name for integrator types character(*), parameter :: UNKNOWN_INTEGRATOR = "UKNOWN INTEGRATOR" diff --git a/src/globals/globals_module.f90.in b/src/globals/globals_module.f90.in index 8d107af1e..ef22ab97a 100644 --- a/src/globals/globals_module.f90.in +++ b/src/globals/globals_module.f90.in @@ -24,7 +24,11 @@ module globals integer, parameter :: SP = real32 !! Symbolic name for kind types of single-precision reals integer, parameter :: DP = real64 !! Symbolic name for kind types of double-precision reals - integer, parameter :: QP = real128 !! Symbolic name for kind types of quad-precision reals +#ifdef QUADPREC + integer, parameter :: QP = selected_Real_kind(30) !! Symbolic name for kind types of quad-precision reals +#else + integer, parameter :: QP = real64 !! Stick to DP +#endif real(DP), parameter :: PIBY2 = 1.570796326794896619231321691639751442099_DP !! Definition of /(\pi / 2\) real(DP), parameter :: PI = 3.141592653589793238462643383279502884197_DP !! Definition of /(\pi\) diff --git a/src/misc/solver_module.f90 b/src/misc/solver_module.f90 index 872db6428..81f2cab40 100644 --- a/src/misc/solver_module.f90 +++ b/src/misc/solver_module.f90 @@ -20,7 +20,9 @@ module solver interface solve_linear_system module procedure solve_linear_system_dp +#ifdef QUADPREC module procedure solve_linear_system_qp +#endif end interface interface solve_roots @@ -81,7 +83,7 @@ function solve_linear_system_dp(A,b,n,lerr) result(x) return end function solve_linear_system_dp - +#ifdef QUADPREC function solve_linear_system_qp(A,b,n,lerr) result(x) !! Author: David A. Minton !! @@ -115,7 +117,7 @@ function solve_linear_system_qp(A,b,n,lerr) result(x) return end function solve_linear_system_qp - +#endif function solve_wbs(u) result(x) ! solve with backward substitution !! Based on code available on Rosetta Code: https://rosettacode.org/wiki/Gaussian_elimination#Fortran diff --git a/src/operator/operator_cross.f90 b/src/operator/operator_cross.f90 index 72c24a176..3ca3e28cf 100644 --- a/src/operator/operator_cross.f90 +++ b/src/operator/operator_cross.f90 @@ -42,6 +42,7 @@ pure module function operator_cross_dp(A, B) result(C) return end function operator_cross_dp +#ifdef QUADPREC pure module function operator_cross_qp(A, B) result(C) implicit none real(QP), dimension(:), intent(in) :: A, B @@ -53,6 +54,7 @@ pure module function operator_cross_qp(A, B) result(C) C(3) = A(1) * B(2) - A(2) * B(1) return end function operator_cross_qp +#endif pure module function operator_cross_i1b(A, B) result(C) implicit none @@ -124,6 +126,7 @@ pure module function operator_cross_el_dp(A, B) result(C) return end function operator_cross_el_dp +#ifdef QUADPREC pure module function operator_cross_el_qp(A, B) result(C) implicit none real(QP), dimension(:,:), intent(in) :: A, B @@ -137,6 +140,7 @@ pure module function operator_cross_el_qp(A, B) result(C) end do return end function operator_cross_el_qp +#endif pure module function operator_cross_el_i1b(A, B) result(C) implicit none diff --git a/src/operator/operator_mag.f90 b/src/operator/operator_mag.f90 index 721e4a930..5c3d6538e 100644 --- a/src/operator/operator_mag.f90 +++ b/src/operator/operator_mag.f90 @@ -65,6 +65,7 @@ pure module function operator_mag_el_dp(A) result(B) return end function operator_mag_el_dp +#ifdef QUADPREC pure module function operator_mag_el_qp(A) result(B) implicit none real(QP), dimension(:,:), intent(in) :: A @@ -79,6 +80,7 @@ pure module function operator_mag_el_qp(A) result(B) end do return end function operator_mag_el_qp +#endif end submodule s_operator_mag diff --git a/src/operator/operator_module.f90 b/src/operator/operator_module.f90 index 8c351236b..93879117a 100644 --- a/src/operator/operator_module.f90 +++ b/src/operator/operator_module.f90 @@ -37,12 +37,14 @@ pure module function operator_cross_dp(A, B) result(C) real(DP), dimension(NDIM) :: C end function operator_cross_dp +#ifdef QUADPREC pure module function operator_cross_qp(A, B) result(C) !$omp declare simd(operator_cross_qp) implicit none real(QP), dimension(:), intent(in) :: A, B real(QP), dimension(NDIM) :: C end function operator_cross_qp +#endif pure module function operator_cross_i1b(A, B) result(C) !$omp declare simd(operator_cross_i1b) @@ -84,11 +86,13 @@ pure module function operator_cross_el_dp(A, B) result(C) real(DP), dimension(:,:), allocatable :: C end function operator_cross_el_dp +#ifdef QUADPREC pure module function operator_cross_el_qp(A, B) result(C) implicit none real(QP), dimension(:,:), intent(in) :: A, B real(QP), dimension(:,:), allocatable :: C end function operator_cross_el_qp +#endif pure module function operator_cross_el_i1b(A, B) result(C) implicit none @@ -134,13 +138,14 @@ pure module function operator_mag_dp(A) result(B) real(DP) :: B end function operator_mag_dp +#ifdef QUADPREC pure module function operator_mag_qp(A) result(B) !$omp declare simd(operator_mag_qp) implicit none real(QP), dimension(:), intent(in) :: A real(QP) :: B end function operator_mag_qp - +#endif pure module function operator_mag_el_sp(A) result(B) implicit none real(SP), dimension(:,:), intent(in) :: A @@ -153,11 +158,14 @@ pure module function operator_mag_el_dp(A) result(B) real(DP), dimension(:), allocatable :: B end function operator_mag_el_dp +#ifdef QUADPREC pure module function operator_mag_el_qp(A) result(B) implicit none real(QP), dimension(:,:), intent(in) :: A real(QP), dimension(:), allocatable :: B end function operator_mag_el_qp +#endif + end interface @@ -180,12 +188,14 @@ pure module function operator_unit_dp(A) result(B) real(DP), dimension(NDIM) :: B end function operator_unit_dp +#ifdef QUADPREC pure module function operator_unit_qp(A) result(B) !$omp declare simd(operator_unit_qp) implicit none real(QP), dimension(:), intent(in) :: A real(QP), dimension(NDIM) :: B end function operator_unit_qp +#endif pure module function operator_unit_el_sp(A) result(B) implicit none @@ -199,11 +209,13 @@ pure module function operator_unit_el_dp(A) result(B) real(DP), dimension(:,:), allocatable :: B end function operator_unit_el_dp +#ifdef QUADPREC pure module function operator_unit_el_qp(A) result(B) implicit none real(QP), dimension(:,:), intent(in) :: A real(QP), dimension(:,:), allocatable :: B end function operator_unit_el_qp +#endif end interface diff --git a/src/operator/operator_unit.f90 b/src/operator/operator_unit.f90 index 2a14f6645..067df74eb 100644 --- a/src/operator/operator_unit.f90 +++ b/src/operator/operator_unit.f90 @@ -56,7 +56,7 @@ pure module function operator_unit_dp(A) result(B) return end function operator_unit_dp - +#ifdef QUADPREC pure module function operator_unit_qp(A) result(B) implicit none ! Arguments @@ -75,7 +75,7 @@ pure module function operator_unit_qp(A) result(B) return end function operator_unit_qp - +#endif pure module function operator_unit_el_sp(A) result(B) implicit none @@ -116,6 +116,7 @@ pure module function operator_unit_el_dp(A) result(B) return end function operator_unit_el_dp +#ifdef QUADPREC pure module function operator_unit_el_qp(A) result(B) implicit none ! Arguments @@ -134,6 +135,7 @@ pure module function operator_unit_el_qp(A) result(B) return end function operator_unit_el_qp +#endif end submodule s_operator_unit diff --git a/src/swiftest/swiftest_io.f90 b/src/swiftest/swiftest_io.f90 index 9eb3bed2c..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 @@ -2774,7 +3085,7 @@ module subroutine swiftest_io_param_writer_one_logical(param_name, param_value, return end subroutine swiftest_io_param_writer_one_logical - +#ifdef QUADPREC module subroutine swiftest_io_param_writer_one_QP(param_name, param_value, unit) !! author: David A. Minton !! @@ -2794,7 +3105,7 @@ module subroutine swiftest_io_param_writer_one_QP(param_name, param_value, unit) return end subroutine swiftest_io_param_writer_one_QP - +#endif module subroutine swiftest_io_read_in_body(self, param) !! author: The Purdue Swiftest Team - David A. Minton, Carlisle A. Wishard, Jennifer L.L. Pouplin, and Jacob R. Elliott @@ -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/src/swiftest/swiftest_module.f90 b/src/swiftest/swiftest_module.f90 index 7437c49bc..acddf4d04 100644 --- a/src/swiftest/swiftest_module.f90 +++ b/src/swiftest/swiftest_module.f90 @@ -850,12 +850,14 @@ module subroutine swiftest_io_param_writer_one_logical(param_name, param_value, integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_logical +#ifdef QUADPREC module subroutine swiftest_io_param_writer_one_QP(param_name, param_value, unit) implicit none character(len=*), intent(in) :: param_name !! Name of parameter to print real(QP), intent(in) :: param_value !! Value of parameter to print integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_QP +#endif end interface io_param_writer_one interface diff --git a/src/swiftest/swiftest_util.f90 b/src/swiftest/swiftest_util.f90 index 6659bf69e..94813be38 100644 --- a/src/swiftest/swiftest_util.f90 +++ b/src/swiftest/swiftest_util.f90 @@ -3331,22 +3331,22 @@ module subroutine swiftest_util_version() !! Adapted from David E. Kaufmann's Swifter routine: util_version.f90 implicit none write(*, 200) VERSION - 200 format(/, "************* Swiftest: Version ", f3.1, " *************", //, & - "Based off of Swifter:", //, & - "Authors:", //, & - " The Purdue University Swiftest Development team ", /, & - " Lead by David A. Minton ", /, & - " Carlisle Wishard, Jennifer Pouplin, Jacob Elliott, Dana Singh." & - "Please address comments and questions to:", //, & - " David A. Minton", /, & - " Department Earth, Atmospheric, & Planetary Sciences ",/, & - " Purdue University", /, & - " 550 Stadium Mall Drive", /, & - " West Lafayette, Indiana 47907", /, & - " 765-250-8034 ", /, & - " daminton@purdue.edu", /, & - "Special thanks to Hal Levison and Martin Duncan for the original",/,& - "SWIFTER and SWIFT codes that made this possible.", //, & + 200 format(/, "************* Swiftest: Version ", f3.1, " *************",/, & + "Based off of Swifter:",/, & + "Authors:",/, & + " The Purdue University Swiftest Development team ",/, & + " Lead by David A. Minton ",/, & + " Carlisle Wishard, Jennifer Pouplin, Jacob Elliott, Dana Singh.",/,& + "Please address comments and questions to:",/, & + " David A. Minton",/, & + " Department Earth, Atmospheric, & Planetary Sciences ",/, & + " Purdue University",/, & + " 550 Stadium Mall Drive",/, & + " West Lafayette, Indiana 47907", /, & + " 765-494-3292 ",/, & + " daminton@purdue.edu",/, & + "Special thanks to Hal Levison, Martin Duncan, and David Kaufmann",/, & + "for the original SWIFTER and SWIFT codes that made this possible.",/, & "************************************************", /) diff --git a/swiftest/CMakeLists.txt b/swiftest/CMakeLists.txt index 9a73977af..45f02ca0d 100644 --- a/swiftest/CMakeLists.txt +++ b/swiftest/CMakeLists.txt @@ -7,37 +7,35 @@ # You should have received a copy of the GNU General Public License along with Swiftest. # If not, see: https://www.gnu.org/licenses. -# Use the old method to get Python packages, as that's what scikit-build uses -CMAKE_POLICY(SET CMP0148 OLD) - -SET(CYTHON_FLAGS - "--directive binding=True,boundscheck=False,wraparound=False,embedsignature=True,always_allow_keywords=True" - CACHE STRING "The directives for Cython compilation.") -FIND_PACKAGE(Cython REQUIRED) -FIND_PACKAGE(PythonExtensions REQUIRED) +SET(SWIFTEST_BINDINGS _bindings) -# Avoid Cython/Python3.8 minor incompatibility warnings, see -# https://github.com/cython/cython/issues/3474. Note that this option is a bit -# expansive, but it's a temporary fix and we'll be testing on other Python -# versions concurrently so it shouldn't hide any real issues. ). -IF(${PYTHON_VERSION_MAJOR} EQUAL 3 - AND ${PYTHON_VERSION_MINOR} EQUAL 8 - AND NOT WIN32) - ADD_COMPILE_OPTIONS("-Wno-deprecated-declarations") -ENDIF() +# 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}" ${CYTHON_ARGS} ) -SET(SWIFTEST_BINDINGS _bindings) +PYTHON_ADD_LIBRARY(${SWIFTEST_BINDINGS} MODULE "${CMAKE_CURRENT_BINARY_DIR}/${SWIFTEST_BINDINGS}.c" WITH_SOABI) -ADD_CYTHON_TARGET(${SWIFTEST_BINDINGS}) -ADD_LIBRARY(${SWIFTEST_BINDINGS} MODULE ${SWIFTEST_BINDINGS}) IF (NOT BUILD_SHARED_LIBS) SET_PROPERTY(TARGET ${SWIFTEST_BINDINGS} PROPERTY POSITION_INDEPENDENT_CODE) ENDIF () -IF(USE_OPENMP OR USE_SIMD) - SET_PROPERTY(TARGET ${SWIFTEST_BINDINGS} APPEND_STRING PROPERTY COMPILE_FLAGS "${OpenMP_Fortran_FLAGS} ") -ENDIF() +TARGET_LINK_LIBRARIES(${SWIFTEST_BINDINGS} PUBLIC ${SWIFTEST_LIBRARY} netCDF::netcdff HDF5::HDF5) +TARGET_INCLUDE_DIRECTORIES(${SWIFTEST_BINDINGS} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) -TARGET_LINK_LIBRARIES(${SWIFTEST_BINDINGS} swiftest ${NETCDF_LIBRARIES}) -PYTHON_EXTENSION_MODULE(${SWIFTEST_BINDINGS}) -TARGET_INCLUDE_DIRECTORIES(${SWIFTEST_BINDINGS} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${MOD} ${NETCDF_INCLUDE_DIR}) -INSTALL(TARGETS ${SWIFTEST_BINDINGS} LIBRARY DESTINATION swiftest) \ No newline at end of file +# Define the install locations +INSTALL(TARGETS ${SWIFTEST_BINDINGS} LIBRARY DESTINATION ${INSTALL_LIBDIR}) \ No newline at end of file diff --git a/swiftest/init_cond.py b/swiftest/init_cond.py index 978fe9808..87ebdaa33 100644 --- a/swiftest/init_cond.py +++ b/swiftest/init_cond.py @@ -147,7 +147,7 @@ def get_rotpole(jpl): rot = np.full(3,np.nan) else: print(f"Physical properties found for {namelist[0]}") - Gmass *= 1e-9 # JPL returns GM in units of km**3 / s**2 + Gmass *= 1e9 # JPL returns GM in units of km**3 / s**2, so convert to SI rotrate = get_rotrate(jpl.raw_response) if rotrate is None: @@ -389,6 +389,9 @@ def solar_system_horizons(name: str, Gmass += Gmass_charon if Gmass is not None: + # Convert from SI to system units + Gmass *= param['TU2S'] ** 2 / param['DU2M'] ** 3 + if param['CHK_CLOSE']: Rpl /= param['DU2M'] 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 a4fb2c126..e668262f6 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -2023.8.0 \ No newline at end of file +2023.10.3 \ No newline at end of file