# CMake project file for molscat cmake_minimum_required (VERSION 3.13) project (molscat VERSION 14.0) enable_language (Fortran) message("Fortran compiler ID: ${CMAKE_Fortran_COMPILER_ID}") # get in Fortran_COMPILER_NAME the name of the compiler (eg ifx) get_filename_component (Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME) message("Fortran compiler: ${Fortran_COMPILER_NAME}") find_package( BLAS REQUIRED ) find_package( LAPACK REQUIRED ) message(STATUS "BLAS_LIBRARIES = ${BLAS_LIBRARIES}") message(STATUS "LAPACK_LIBRARIES = ${LAPACK_LIBRARIES}") add_executable(molscat potenl_pes.f POTEN_rigidXD.f90 SUBROUTINES_F77.f v14_new.f vrtp_co_co2.f ) ################################################################################ # # COMPILE OPTIONS # ################################################################################ # GNU (gfortran) if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") target_compile_options(molscat PUBLIC # Non-specific options -std=legacy # Allow pre-Fortran 77 syntax (e.g. arbitrary length arrays) -ffree-line-length-none # Allow arbitrary long lines. Needed as preprocessing could generate long line lengths. # -fdefault-integer-8 # -finteger-4-integer-8 $<$:-fno-automatic> # Put local variables on the heap instead of the stack. As a side effect, all affected variables receive the save attribute (persistance between calls). This flag conflicts with -fopenmp (f951: Warning: Flag ‘-fno-automatic’ overwrites ‘-frecursive’ implied by ‘-fopenmp’) $<$:-mcmodel=large> # Required on Linux $<$:-fopenmp> # Compile with fopenmp option if OpenMP libs are found # Config-specific options: RELEASE $<$:-O3> # Optimization level at 3 for Release $<$,$>:-flto> # Activate link time optimizations so that gfortran can inline some function calls #$<$:-fopt-info> # You can get some information from gfortran with the flag -fopt-info that will tell you about optimizations missed or performed by the compiler $<$:-finit-local-zero> # Init variables to zero/false/null # Config-specific options: DEBUG $<$:-O0> # Optimization level at 0 $<$:-g> # Include symbols in executable for easier debugging $<$:-fno-omit-frame-pointer> $<$:-fbacktrace> # Generates extra information in the object file to provide source file traceback information when a severe error occurs at run time $<$:-Wall> # Enable all warnings $<$:-Wextra> # Enable extra warnings $<$:-Wno-conversion> # Disable warnings such as Warning: Possible change of value in conversion from REAL(8) to INTEGER(4) at (1) [-Wconversion] $<$:-Wno-compare-reals> # Disable warnings such as "Warning: Equality comparison for REAL(8) at (1) [-Wcompare-reals]" as they are often fine when comparing with 2 hardcoded zero constants $<$:-fsanitize=address> # Address sanitizer $<$>,$>:-Wuninitialized> # Emit warnings for uninitialized variables. Disable -Wuninitialized when ENABLE_UNINIT_VAR_RUNTIME_DETECTOR is on because the the -finit-* options then used make -Wuninitialized have no effect, see gfortran documentation : # Finally, note that enabling any of the -finit-* options will silence warnings that would have been emitted by -Wuninitialized for the affected local variables. # handle ENABLE_UNINIT_VAR_RUNTIME_DETECTOR # don't initialize local variables to zero : initialize them with dummy values to force failures which help detect uninitialized variables as -Wuninitialized doesn't detect everything (see issue #38 or https://stackoverflow.com/questions/39591300/gfortran-wuninitialized-flag-misses-variable-in-do-loop) # by default, gfortran initializes integers to 0, but not ifort : as a result, some bugs in the code are hidden with gfortran default options # set (CMAKE_Fortran_FLAGS_DEBUG "${CMAKE_Fortran_FLAGS_DEBUG} -fno-init-local-zero") # initialize variables to something else than 0 to force the programe to behave badly in case of unitialized variables $<$,$>:-finit-integer=333333333> $<$,$>:-finit-real=snan> $<$,$>:-ffpe-trap=invalid,zero,overflow> # The --coverage option of the Gcc compiler, which is synonymous with -fprofile-arcs and -ftest-coverage for compilation and -lgcov for linking, allows the generation of code coverage data files after program execution. After tests performed with Check, the test executable produces a .gcno (Gcov notes) file and a .gcda (Gcov data) file for each file compiled with the -fprofile-arcs option and used during the test (see gcc manual). # These files are then used by the lcov tool to produce a code coverage report in HTML format. $<$:--coverage -Wno-coverage-invalid-line-number> # Code coverage (same as -fprofile-arcs -ftest-coverage at compile time) $<$:-g> # The profiler requires both the debug and profile directives (-g and -p) $<$:-p> # The profiler requires both the debug and profile directives (-g and -p) ) # Intel (ifort) elseif (Fortran_COMPILER_NAME STREQUAL "ifort") target_compile_options(molscat PUBLIC # Non-specific options # force arrays to be allocated on the heap instead of the stack, this removes segmentation faults crash, not sure why # the following option means : automatic arrays and arrays created for temporary computations are allocated on the stack if their size can be determined at compile time and if it doesn't exceed 10kb. # this option seems necessary for big values of kmax (eg kmax=5000), according to bdesrousseaux, otherwise the user will experience a segmentation fault. I guess that without this option, the stack becomes too small to contain such big arrays... -heap-arrays # Put everything on the heap # "-extend-source 132" # Allow arbitrary long lines (132 seems the longest allowed with ifort). Needed as preprocessing could generate long lines. -no-wrap-margin # Don't wrap output files $<$:-mcmodel=large> # Required on Linux $<$:-qopenmp> # Compile with qopenmp option if OpenMP libs are found # Config-specific options: RELEASE $<$:-O3> # Optimization level at 3 for Release $<$,$>:-ipo> # activate interprocediral optimization (aka link time optimization) $<$:-init=zero> # Init variables to zero/false/null # Config-specific options: DEBUG $<$:-O0> # Disable all optimizations $<$:-g> # Generates complete debugging information $<$:-traceback> # Generates extra information in the object file to provide source file traceback information when a severe error occurs at run time $<$:-fp-stack-check> # Tell the compiler to generate extra code after every function call to ensure that the floating-point stack is in the expected state #$<$:-warn all> # Enable all warnings # handle ENABLE_UNINIT_VAR_RUNTIME_DETECTOR # Force à NaN toutes les variables de type intrinsèque ainsi que les tableaux non initialisés. Cette option implique -fpe0. Pour éviter de récupérer des exceptions, qui ne soient pas relatives à des variables non-initialisées, nous recommandons de réduire le niveau d'optimisation à -O1 ou -O0 ou alors d'utiliser -fp-speculation=safe pour faire la détection de variables non-initialisés. $<$,$>:-init=zero> # Init integer and logical variables to zero/false/null instead of random to avoid random bugs $<$,$>:-init=snan> # Init real variables to signaling nans to detect uninitialized variables $<$,$>:-init=arrays> # also initialize arrays to avoid random behaviours caused by use of uninitialized variables # check uses of uninitialized variables in run time # this is very useful as these are always bugs that cause the program to behave randomly with ifort (gfortran initializes data with zero) $<$,$>:-check uninit> # Cette combinaison d'options stoppe l'exécution dès qu'une exception (overflow, underflow, division par zéro, opération invalide,…) se produit; elle indique à quel niveau du code elle s'est produite. Le contrôle s'opère dans chaque subroutine, contrairement à l'option -fpe0 qui agit uniquement sur le programme principal. # $<$,$>:-fpe-all=0> # $<$,$>:-no-ftz=0> # $<$,$>:-traceback=0> $<$:-g> # The profiler requires both the debug and profile directives (-g and -p) $<$:-p> # The profiler requires both the debug and profile directives (-g and -p) -diag-disable 6717,7712 # disable warning #6717 (This name has not been given an explicit type. [LMAXP]) until all variables have been declared explicitely (implicit None) # -diag-disable 7712 # disable remark #7712: This variable has not been used. until all variables have been declared explicitely (implicit None) $<$:-warn all,nounused,nodeclarations,errors> # Enable all warnings except for some that have not been fixed yet, and treat warnings as errors for a zero warning policy ) # Intel (Fortran_COMPILER_NAME=ifx, Fortran_COMPILER_ID=IntelLLVM) elseif (Fortran_COMPILER_NAME STREQUAL "ifx") target_compile_options(molscat PUBLIC # Non-specific options # force arrays to be allocated on the heap instead of the stack, this removes segmentation faults crash, not sure why # the following option means : automatic arrays and arrays created for temporary computations are allocated on the stack if their size can be determined at compile time and if it doesn't exceed 10kb. # this option seems necessary for big values of kmax (eg kmax=5000), according to bdesrousseaux, otherwise the user will experience a segmentation fault. I guess that without this option, the stack becomes too small to contain such big arrays... -heap-arrays # Put everything on the heap # "-extend-source 132" # Allow arbitrary long lines (132 seems the longest allowed with ifort). Needed as preprocessing could generate long lines. -no-wrap-margin # Don't wrap output files $<$:-mcmodel=large> # Required on Linux $<$:-qopenmp> # Compile with qopenmp option if OpenMP libs are found # Config-specific options: RELEASE $<$:-O3> # Optimization level at 3 for Release $<$,$>:-ipo> # activate interprocediral optimization (aka link time optimization) $<$:-init=zero> # Init variables to zero/false/null # Config-specific options: DEBUG $<$:-O0> # Disable all optimizations $<$:-g> # Generates complete debugging information $<$:-traceback> # Generates extra information in the object file to provide source file traceback information when a severe error occurs at run time #$<$:-warn all> # Enable all warnings # handle ENABLE_UNINIT_VAR_RUNTIME_DETECTOR # Force à NaN toutes les variables de type intrinsèque ainsi que les tableaux non initialisés. Cette option implique -fpe0. Pour éviter de récupérer des exceptions, qui ne soient pas relatives à des variables non-initialisées, nous recommandons de réduire le niveau d'optimisation à -O1 ou -O0 ou alors d'utiliser -fp-speculation=safe pour faire la détection de variables non-initialisés. $<$,$>:-init=zero> # Init integer and logical variables to zero/false/null instead of random to avoid random bugs $<$,$>:-init=snan> # Init real variables to signaling nans to detect uninitialized variables $<$,$>:-init=arrays> # also initialize arrays to avoid random behaviours caused by use of uninitialized variables # check uses of uninitialized variables in run time # this is very useful as these are always bugs that cause the program to behave randomly with ifort (gfortran initializes data with zero) $<$,$>:-check uninit> # Cette combinaison d'options stoppe l'exécution dès qu'une exception (overflow, underflow, division par zéro, opération invalide,…) se produit; elle indique à quel niveau du code elle s'est produite. Le contrôle s'opère dans chaque subroutine, contrairement à l'option -fpe0 qui agit uniquement sur le programme principal. # $<$,$>:-fpe-all=0> # $<$,$>:-no-ftz=0> # $<$,$>:-traceback=0> $<$:-g> # The profiler requires both the debug and profile directives (-g and -p) $<$:-p> # The profiler requires both the debug and profile directives (-g and -p) -diag-disable 6717,7712 # disable warning #6717 (This name has not been given an explicit type. [LMAXP]) until all variables have been declared explicitely (implicit None) # -diag-disable 7712 # disable remark #7712: This variable has not been used. until all variables have been declared explicitely (implicit None) $<$:-warn all,nounused,nodeclarations,errors> # Enable all warnings except for some that have not been fixed yet, and treat warnings as errors for a zero warning policy ) else() message(FATAL_ERROR "Unsupported Fortran compiler: ${CMAKE_Fortran_COMPILER_ID} (${Fortran_COMPILER_NAME})") endif() ################################################################################ # # LINK OPTIONS # ################################################################################ # Link Blas and Lapack libraries if(Fortran_COMPILER_NAME STREQUAL "ifx") if(BLA_VENDOR STREQUAL "Intel10_64lp") # -- BLAS_LIBRARIES = /opt/intel/oneapi-2024.2.1/mkl/2024.2/lib/libmkl_intel_lp64.so;/opt/intel/oneapi-2024.2.1/mkl/2024.2/lib/libmkl_intel_thread.so;/opt/intel/oneapi-2024.2.1/mkl/2024.2/lib/libmkl_core.so;/opt/intel/oneapi-2024.2.1/compiler/2024.2/lib/libiomp5.so;-lm;-ldl # -- LAPACK_LIBRARIES = /opt/intel/oneapi-2024.2.1/mkl/2024.2/lib/libmkl_intel_lp64.so;/opt/intel/oneapi-2024.2.1/mkl/2024.2/lib/libmkl_intel_thread.so;/opt/intel/oneapi-2024.2.1/mkl/2024.2/lib/libmkl_core.so;/opt/intel/oneapi-2024.2.1/compiler/2024.2/lib/libiomp5.so;-lm;-ldl;-lm;-ldl # in this case, BLAS_LIBRARIES and LAPACK_LIBRARIES are the same, and linking bith would cause ifx to faiol with the error: # "ld: attempted static link of dynamic object `/opt/intel/oneapi-2024.2.1/mkl/2024.2/lib/libmkl_intel_lp64.so' target_link_libraries(molscat PUBLIC "${BLAS_LIBRARIES}") else() target_link_libraries(molscat PUBLIC "${BLAS_LIBRARIES}") target_link_libraries(molscat PUBLIC "${LAPACK_LIBRARIES}") endif() else() target_link_libraries(molscat PUBLIC "${BLAS_LIBRARIES}") target_link_libraries(molscat PUBLIC "${LAPACK_LIBRARIES}") endif() # GNU (gfortran) if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") target_link_libraries(molscat PUBLIC $<$:-fsanitize=address> # Address sanitizer (beware: tests showed that with -fsanitize=address memory is not actually released when deallocate is called. Is this a true memory leak in address sanitizer?) ) # Intel (ifort) elseif (Fortran_COMPILER_NAME STREQUAL "ifort") endif() # GNU (gfortran) if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") target_link_options(molscat PUBLIC $<$:-fsanitize=address> # Address sanitizer $<$:--coverage> # Code coverage (same as -lgcov at link time) ) elseif (CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM") # Intel (ifx) target_link_options(molscat PUBLIC $<$,$>:-check uninit> # https://community.intel.com/t5/Intel-Fortran-Compiler/Linking-errors-when-using-memory-sanitizer-in-fortran-project/td-p/1521476: When you compile with -check uninit (or -check all) you also need to link with that compiler option. ) endif()