From f4abe26b1f033c29a5644011f5f332342d600f11 Mon Sep 17 00:00:00 2001 From: Guillaume Raffy Date: Fri, 20 Feb 2026 14:32:46 +0100 Subject: [PATCH] now molscat can be built using cmake --- CMakeLists.txt | 215 +++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 89 +++++++++++++++++++- 2 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..37e8300 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,215 @@ +# 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() + diff --git a/readme.md b/readme.md index 4a2d746..c400139 100644 --- a/readme.md +++ b/readme.md @@ -3,7 +3,94 @@ This is molscat 14 modified by F. Lique ## how to build ```sh -gfortran -o molscat -std=legacy -mcmodel=large *.f *.f90 +graffy@graffy-ws2:~/work/saboi$ ls -l +total 4 +drwxr-xr-x 3 graffy spm 4096 févr. 20 13:51 molscat_14.git +``` + +create a directory for the build: + +```sh +graffy@graffy-ws2:~/work/saboi$ mkdir molscat_14.build +graffy@graffy-ws2:~/work/saboi$ cd molscat_14.build/ +``` + +configure the build + +```sh +graffy@graffy-ws2:~/work/saboi/molscat_14.build$ cmake ../molscat_14.git/ +-- The C compiler identification is GNU 9.4.0 +-- The CXX compiler identification is GNU 9.4.0 +-- Check for working C compiler: /usr/bin/cc +-- Check for working C compiler: /usr/bin/cc -- works +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Detecting C compile features +-- Detecting C compile features - done +-- Check for working CXX compiler: /usr/bin/c++ +-- Check for working CXX compiler: /usr/bin/c++ -- works +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- The Fortran compiler identification is GNU 9.4.0 +-- Check for working Fortran compiler: /usr/bin/gfortran +-- Check for working Fortran compiler: /usr/bin/gfortran -- works +-- Detecting Fortran compiler ABI info +-- Detecting Fortran compiler ABI info - done +-- Checking whether /usr/bin/gfortran supports Fortran 90 +-- Checking whether /usr/bin/gfortran supports Fortran 90 -- yes +Fortran compiler ID: GNU +Fortran compiler: gfortran +-- Looking for Fortran sgemm +-- Looking for Fortran sgemm - not found +-- Looking for pthread.h +-- Looking for pthread.h - found +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed +-- Looking for pthread_create in pthreads +-- Looking for pthread_create in pthreads - not found +-- Looking for pthread_create in pthread +-- Looking for pthread_create in pthread - found +-- Found Threads: TRUE +-- Looking for Fortran sgemm +-- Looking for Fortran sgemm - found +-- Found BLAS: /usr/lib/x86_64-linux-gnu/libopenblas.so +-- Looking for Fortran cheev +-- Looking for Fortran cheev - found +-- A library with LAPACK API found. +-- BLAS_LIBRARIES = /usr/lib/x86_64-linux-gnu/libopenblas.so +-- LAPACK_LIBRARIES = /usr/lib/x86_64-linux-gnu/libopenblas.so +-- Configuring done +-- Generating done +-- Build files have been written to: /home/graffy/work/saboi/molscat_14.build +``` + +This created the makefile [~/work/saboi/molscat_14.build/Makefile]. + +Build the `moscat` executable using the makefile [~/work/saboi/molscat_14.build/Makefile] + +```sh +graffy@graffy-ws2:~/work/saboi/molscat_14.build$ make +Scanning dependencies of target molscat +[ 16%] Building Fortran object CMakeFiles/molscat.dir/POTEN_rigidXD.f90.o +[ 33%] Building Fortran object CMakeFiles/molscat.dir/potenl_pes.f.o +[ 50%] Building Fortran object CMakeFiles/molscat.dir/SUBROUTINES_F77.f.o +[ 66%] Building Fortran object CMakeFiles/molscat.dir/v14_new.f.o +/home/graffy/work/saboi/molscat_14.git/v14_new.f:10033:10: + +10031 | DO 21 IM2=2,NMID + | 2 +... +Warning: Named COMMON block ‘cmbase’ at (1) shall be of the same size as elsewhere (24248 vs 24256 bytes) +/home/graffy/work/saboi/molscat_14.git/v14_new.f:11:21: + + 11 | COMMON /MEMORY/ MX,IXNEXT,NIPR,IVLFL,X + | 1 +Warning: Named COMMON block ‘memory’ at (1) shall be of the same size as elsewhere (800000016 vs 24 bytes) +[ 83%] Building Fortran object CMakeFiles/molscat.dir/vrtp_co_co2.f.o +[100%] Linking Fortran executable molscat +[100%] Built target molscat ``` ## how to run