From bd1fb58dd097f73ff49aabaa30c4803db46c202b Mon Sep 17 00:00:00 2001 From: MintoDA1 <51412913+MintoDA1@users.noreply.github.com> Date: Tue, 1 Aug 2023 17:20:35 -0400 Subject: [PATCH] Reorganized testing and made the compiler-option finding much more robust and efficient by getting the compiler id first instead of trying every possible flag. --- .gitignore | 2 +- CMakeLists.txt | 30 +- cmake/Modules/FindCoarray_Fortran.cmake | 51 +- cmake/Modules/FindOpenMP_Fortran.cmake | 37 +- cmake/Modules/SetFortranFlags.cmake | 663 ++++++++++++++---------- distclean.cmake | 1 - python/swiftest/tests/test_suite.py | 166 ++++++ src/CMakeLists.txt | 2 - test/CMakeLists.txt | 17 + test/test_suite.py | 3 + 10 files changed, 647 insertions(+), 325 deletions(-) create mode 100755 python/swiftest/tests/test_suite.py create mode 100644 test/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 79550f93d..5c64de306 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,7 @@ dump* !examples/** *ipynb_checkpoints **/.DS_Store -!test/test_suite.py +!python/swiftest/tests/test_suite.py #Documentation !docs/* diff --git a/CMakeLists.txt b/CMakeLists.txt index c2248e313..b165d0d7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,8 @@ PROJECT(Swiftest Fortran) # Set the Swiftest version SET(VERSION 1.0.0) +INCLUDE(CTest) + # Add our local modlues to the module path SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules/") @@ -27,29 +29,32 @@ 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 () + # 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(CONTAINERIZE "Compiling for use in a Docker/Singularity container" OFF) OPTION(BUILD_SHARED_LIBS "Build using shared libraries" ON) INCLUDE(${CMAKE_MODULE_PATH}/SetParallelizationLibrary.cmake) INCLUDE(${CMAKE_MODULE_PATH}/SetUpNetCDF.cmake) -INCLUDE(${CMAKE_MODULE_PATH}/SetMKL.cmake) +IF (COMPILER_OPTIONS STREQUAL "Intel") + INCLUDE(${CMAKE_MODULE_PATH}/SetMKL.cmake) +ENDIF () # This INCLUDE statement executes code that sets the compile flags for DEBUG, # RELEASE, PROFILING, and TESTING. INCLUDE(${CMAKE_MODULE_PATH}/SetFortranFlags.cmake) INCLUDE_DIRECTORIES($ENV{NETCDF_FORTRAN_HOME}/include;$ENV{NETCDF_HOME}/include) - -# There is an error in CMAKE with this flag for pgf90. Unset it -GET_FILENAME_COMPONENT(FCNAME ${CMAKE_Fortran_COMPILER} NAME) -IF(FCNAME STREQUAL "pgf90") - UNSET(CMAKE_SHARED_LIBRARY_LINK_Fortran_FLAGS) -ENDIF(FCNAME STREQUAL "pgf90") - ############################################################ # Define the actual files and folders that make up the build ############################################################ @@ -62,6 +67,7 @@ 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(TEST ${CMAKE_SOURCE_DIR}/test) # Have the .mod files placed in the lib folder SET(CMAKE_Fortran_MODULE_DIRECTORY ${MOD}) @@ -69,9 +75,11 @@ SET(CMAKE_Fortran_MODULE_DIRECTORY ${MOD}) # The source for the SWIFTEST binary and have it placed in the bin folder ADD_SUBDIRECTORY(${SRC} ${BIN}) +# Set up test directory +ENABLE_TESTING() +ADD_SUBDIRECTORY(${TEST}) + # Add a distclean target to the Makefile ADD_CUSTOM_TARGET(distclean COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/distclean.cmake ) - - diff --git a/cmake/Modules/FindCoarray_Fortran.cmake b/cmake/Modules/FindCoarray_Fortran.cmake index 314371326..93f73f466 100644 --- a/cmake/Modules/FindCoarray_Fortran.cmake +++ b/cmake/Modules/FindCoarray_Fortran.cmake @@ -27,27 +27,40 @@ INCLUDE (${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT) IF(BT STREQUAL "DEBUG") - SET (Coarray_Fortran_FLAG_CANDIDATES - #Intel - "-coarray=single" - #Intel windows - "/Qcoarray:single" - #Gnu - "-fcoarray=single" - #Empty, if compiler automatically accepts coarray - " " + IF (COMPILER_OPTIONS STREQUAL "Intel") + SET (Coarray_Fortran_FLAG_CANDIDATES + #Intel + "-coarray=single" + #Intel windows + "/Qcoarray:single" + #Empty, if compiler automatically accepts coarray + " " + ) + ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") + SET (Coarray_Fortran_FLAG_CANDIDATES + #Gnu + "-fcoarray=single" + #Empty, if compiler automatically accepts coarray + " " ) + ENDIF() ELSE() - SET (Coarray_Fortran_FLAG_CANDIDATES - #Intel - "-coarray=distributed" - #Intel windows - "/Qcoarray:distributed" - #Gnu - "-fcoarray=lib -lcaf_mpi" - #Empty, if compiler automatically accepts coarray - " " - ) + IF (COMPILER_OPTIONS STREQUAL "Intel") + SET (Coarray_Fortran_FLAG_CANDIDATES + #Intel + "-coarray=distributed" + #Intel windows + "/Qcoarray:distributed" + #Empty, if compiler automatically accepts coarray + " " + ) + ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") + SET (Coarray_Fortran_FLAG_CANDIDATES + #Gnu + "-fcoarray=lib -lcaf_mpi" + #Empty, if compiler automatically accepts coarray + " " + ) ENDIF() diff --git a/cmake/Modules/FindOpenMP_Fortran.cmake b/cmake/Modules/FindOpenMP_Fortran.cmake index 06d679e7c..d3a0bc29b 100644 --- a/cmake/Modules/FindOpenMP_Fortran.cmake +++ b/cmake/Modules/FindOpenMP_Fortran.cmake @@ -25,19 +25,30 @@ INCLUDE (${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) -IF (USE_SIMD) - SET (OpenMP_Fortran_FLAG_CANDIDATES - "-qopenmp" # Intel - "/Qopenmp" # Intel Windows - "-fopenmp" # GNU - ) -ELSE () - SET (OpenMP_Fortran_FLAG_CANDIDATES - "-qopenmp -qno-openmp-simd" # Intel - "/Qopenmp-simd-" # Intel Windows - "-fopenmp" # GNU - ) -ENDIF (USE_SIMD) +IF (COMPILER_OPTIONS STREQUAL "Intel") + IF (USE_SIMD) + SET (OpenMP_Fortran_FLAG_CANDIDATES + "-qopenmp" # Intel + "/Qopenmp" # Intel Windows + ) + ELSE () + SET (OpenMP_Fortran_FLAG_CANDIDATES + "-qopenmp -qno-openmp-simd" # Intel + "/Qopenmp-simd-" # Intel Windows + ) + ENDIF (USE_SIMD) +ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") + IF (USE_SIMD) + SET (OpenMP_Fortran_FLAG_CANDIDATES + "-fopenmp" # GNU + ) + ELSE () + SET (OpenMP_Fortran_FLAG_CANDIDATES + "-fopenmp -fno-openmp-simd" # GNU + ) + ENDIF (USE_SIMD) + +ENDIF () IF (DEFINED OpenMP_Fortran_FLAGS) SET (OpenMP_Fortran_FLAG_CANDIDATES) diff --git a/cmake/Modules/SetFortranFlags.cmake b/cmake/Modules/SetFortranFlags.cmake index e3b0030ad..a7c46e10d 100644 --- a/cmake/Modules/SetFortranFlags.cmake +++ b/cmake/Modules/SetFortranFlags.cmake @@ -46,15 +46,6 @@ ELSE() MESSAGE(FATAL_ERROR "CMAKE_BUILD_TYPE not valid! ${BUILD_TYPE_MSG}") ENDIF(BT STREQUAL "RELEASE") -IF (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") - IF (APPLE) - SET(MACHINE_CODE_VALUE "tune=native" CACHE STRING "Tells the compiler which processor features it may target, including which instruction sets and optimizations it may generate.") - ELSE () - SET(MACHINE_CODE_VALUE "arch=native" CACHE STRING "Tells the compiler which processor features it may target, including which instruction sets and optimizations it may generate.") - ENDIF () -ELSE () - 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.") -ENDIF () ######################################################### # If the compiler flags have already been set, return now @@ -77,340 +68,456 @@ ENDIF(CMAKE_Fortran_FLAGS_RELEASE AND CMAKE_Fortran_FLAGS_TESTING AND CMAKE_Fort ##################### # Free form -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) - ) +IF (COMPILER_OPTIONS STREQUAL "GNU") + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-ffree-form" # GNU + ) -# 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 - ) + # 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 - ) + # 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 + # 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) - # Use static Intel libraries - SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - Fortran "-static-intel" # Intel - "-static-libgfortran -static-libgcc" # GNU - ) - # Use static Intel MPI libraries - SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - Fortran "-static_mpi" # Intel - ) - - IF (USE_OPENMP) + + IF (COMPILER_OPTIONS STREQUAL "Intel") + # Use static Intel libraries SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" - Fortran "-qopenmp-link=static" # Intel + Fortran "-static-intel" # Intel + ) + # Use static Intel MPI libraries + SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" + Fortran "-static_mpi" # Intel ) - ENDIF (USE_OPENMP) -ENDIF () + + IF (USE_OPENMP) + SET_COMPILE_FLAG(CMAKE_Fortran_LINK_FLAGS "${CMAKE_Fortran_LINK_FLAGS}" + Fortran "-qopenmp-link=static" # Intel + ) + ENDIF (USE_OPENMP) + ELSEIF (COMPIELR_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" + ) + ENDIF () + +ENDIF (NOT BUILD_SHARED_LIBS) IF (USE_SIMD) - # Enables OpenMP SIMD compilation when OpenMP parallelization is disabled. - IF (NOT USE_OPENMP) + 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 (COMPILER_OPTIONS STREQUAL "Intel") + + # 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 "-qno-openmp -qopenmp-simd" # Intel - Fortran "/Qopenmp- /Qopenmp-simd" # Intel Windows + Fortran "-vecabi=cmdtarget" # Intel + "/Qvecabi:cmdtarget" # Intel Windows + ) + ELSEIF (COMPILER_OPTIONS STREQUAL "GNU") + + # 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) + 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 - "-m${MACHINE_CODE_VALUE}" # GNU - ) + IF (MACHINE_CODE_VALUE STREQUAL "host") + 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.") + ENDIF () - # Generate an extended set of vector functions - SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" - Fortran "-vecabi=cmdtarget" # Intel - Fortran "/Qvecabi:cmdtarget" # Intel Windows + IF (APPLE) + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-mtune=${MACHINE_CODE_VALUE}" ) -ENDIF (USE_SIMD) - + ELSE () + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" + Fortran "-march=${MACHINE_CODE_VALUE}" + ) + ENDIF () + ENDIF () +ENDIF (USE_SIMD) ################### ### DEBUG FLAGS ### ################### - -# Disable optimizations -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran REQUIRED "-O0" # All compilers not on Windows - "/Od" # Intel Windows - "-Og" # GNU (gfortran) - ) - -# Turn on all warnings -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-warn all" # Intel - "/warn:all" # Intel Windows - "-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 "-stand f18" # Intel - "/stand:f18" # Intel Windows - "-fstd=f2018" # GNU +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 "-traceback" # Intel Group - "/traceback" # Intel Windows - "-fbacktrace" # GNU (gfortran) + # 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 "-check all" # Intel - "/check:all" # Intel Windows - "-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 "-init=snan,arrays" # Intel - "/Qinit:snan,arrays" # Intel Windows - "-finit-real=snan" # GNU + # Sanitize + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fsanitize=address, undefined" # Gnu ) -# 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 + # Check everything + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fcheck=all" # GNU ) - -# 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 + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fstack-check" # GNU ) -# 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 - "-ffpe-trap=zero,overflow,underflow" # GNU + # Initializes matrices/arrays with NaN values + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-finit-real=snan" # 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 + # 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 "-fpe0" # Intel - "/fpe: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 "-ffpe-trap=zero,overflow,underflow" # GNU ) -# Enables debug info -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-debug all" # Intel - "/debug:all" # Intel Windows + # 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 ) -# 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 + SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" + Fortran "-fstack-check" # GNU ) + ENDIF () -# Disables prefetch insertion optimization -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-qno-opt-prefetch" # Intel - "/Qopt-prefetch-" # Intel Windows - ) - -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran "-fstack-check" # GNU - ) +ENDIF () ##################### ### TESTING FLAGS ### ##################### -# Optimizations -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_TESTING "${CMAKE_Fortran_FLAGS_DEBUG}" - Fortran REQUIRED "-O3" # All compilers not on Windows - "/O3" # Intel Windows +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 -# Unroll loops -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-funroll-loops" # GNU - "-unroll" # Intel - "/unroll" # Intel Windows - - ) -# Inline functions -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-inline" # Intel - "/Qinline" # Intel Windows - "-finline-functions" # GNU - ) - -# Calls the Matrix Multiply library -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-qopt-matmul" # Intel - "/Qopt-matmul" # Intel Windows - ) - -# Saves the compiler options and version number to the executable -SET_COMPILE_FLAG(CMAKE_Fortran_FLAGS_RELEASE "${CMAKE_Fortran_FLAGS_RELEASE}" - Fortran "-sox" # 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 - "/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 - ) +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 ### ##################### -# 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 - "-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" - ) +IF (COMPILER_OPTIONS STREQUAL "Intel") -SET_COMPILE_FLAG(STRICTMATH_FLAGS "${STRICTMATH_FLAGS}" - Fortran "-prec-div" # Intel - "/Qprec-div" # Intel Windows - ) + # 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-sqrt" # Intel - "/Qprec-sqrt" # 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 "-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 - "-ffast-math" # GNU - ) + 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} - ) + Fortran ${STRICTMATH_FLAGS} +) ##################### ### PROFILE FLAGS ### ##################### -# 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 - "-O2 -pg -fbacktrace" # GNU - ) +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/distclean.cmake b/distclean.cmake index 00d2e454c..a06162074 100644 --- a/distclean.cmake +++ b/distclean.cmake @@ -44,7 +44,6 @@ 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}/test" "${TOPDIR}/bin" ) diff --git a/python/swiftest/tests/test_suite.py b/python/swiftest/tests/test_suite.py new file mode 100755 index 000000000..d4ddc7c50 --- /dev/null +++ b/python/swiftest/tests/test_suite.py @@ -0,0 +1,166 @@ +#!/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") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c616b7152..2899ae49f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -169,5 +169,3 @@ end program TestDoConcurrentLoc ENDIF (USE_OPENMP) -# Add an automatic test -ADD_TEST(NAME test_suite COMMAND python ${CMAKE_SOURCE_DIR/test/test_suite.py}) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 000000000..17e6a6b62 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,17 @@ +ENABLE_TESTING() +FIND_PACKAGE(Python COMPONENTS Interpreter REQUIRED) + +SET(UNIT_TEST swiftest_test_suite) +ADD_CUSTOM_TARGET(${UNIT_TEST} ALL) +ADD_DEPENDENCIES(${UNIT_TEST} ${SWIFTEST_DRIVER}) + +ADD_TEST(NAME ${UNIT_TEST} COMMAND python ${CMAKE_SOURCE_DIR}/python/swiftest/tests/test_suite.py) + +ADD_CUSTOM_COMMAND( + TARGET ${UNIT_TEST} + COMMENT "Run tests" + POST_BUILD + WORKING_DIRECTORY ${TEST} + COMMAND ${CMAKE_CTEST_COMMAND} "${UNIT_TEST}" --output-on-failures +) + diff --git a/test/test_suite.py b/test/test_suite.py index 5fdf5c21d..d4ddc7c50 100755 --- a/test/test_suite.py +++ b/test/test_suite.py @@ -25,6 +25,7 @@ import swiftest import unittest import os +import shutil import numpy as np from numpy.random import default_rng @@ -161,3 +162,5 @@ def fit_func(x,slope,b): if __name__ == '__main__': unittest.main() + if os.path.exists("simdir"): + shutil.rmtree("simdir")