now molscat can be built using cmake

This commit is contained in:
Guillaume Raffy 2026-02-20 14:32:46 +01:00
parent 06b83b1561
commit f4abe26b1f
2 changed files with 303 additions and 1 deletions

215
CMakeLists.txt Normal file
View File

@ -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
$<$<BOOL:${SAVE}>:-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)
$<$<PLATFORM_ID:Linux>:-mcmodel=large> # Required on Linux
$<$<BOOL:${OpenMP_Fortran_FOUND}>:-fopenmp> # Compile with fopenmp option if OpenMP libs are found
# Config-specific options: RELEASE
$<$<CONFIG:RELEASE>:-O3> # Optimization level at 3 for Release
$<$<AND:$<BOOL:${LINK_TIME_OPTIMIZATION}>,$<CONFIG:RELEASE>>:-flto> # Activate link time optimizations so that gfortran can inline some function calls
#$<$<CONFIG:RELEASE>:-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
$<$<CONFIG:RELEASE>:-finit-local-zero> # Init variables to zero/false/null
# Config-specific options: DEBUG
$<$<CONFIG:DEBUG>:-O0> # Optimization level at 0
$<$<CONFIG:DEBUG>:-g> # Include symbols in executable for easier debugging
$<$<CONFIG:DEBUG>:-fno-omit-frame-pointer>
$<$<CONFIG:DEBUG>:-fbacktrace> # Generates extra information in the object file to provide source file traceback information when a severe error occurs at run time
$<$<CONFIG:DEBUG>:-Wall> # Enable all warnings
$<$<CONFIG:DEBUG>:-Wextra> # Enable extra warnings
$<$<CONFIG:DEBUG>:-Wno-conversion> # Disable warnings such as Warning: Possible change of value in conversion from REAL(8) to INTEGER(4) at (1) [-Wconversion]
$<$<CONFIG:DEBUG>:-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
$<$<CONFIG:DEBUG>:-fsanitize=address> # Address sanitizer
$<$<AND:$<NOT:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>>,$<CONFIG:DEBUG>>:-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
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-finit-integer=333333333>
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-finit-real=snan>
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-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.
$<$<BOOL:${ENABLE_CODE_COVERAGE}>:--coverage -Wno-coverage-invalid-line-number> # Code coverage (same as -fprofile-arcs -ftest-coverage at compile time)
$<$<BOOL:${ENABLE_PROFILING}>:-g> # The profiler requires both the debug and profile directives (-g and -p)
$<$<BOOL:${ENABLE_PROFILING}>:-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
$<$<PLATFORM_ID:Linux>:-mcmodel=large> # Required on Linux
$<$<BOOL:${OpenMP_Fortran_FOUND}>:-qopenmp> # Compile with qopenmp option if OpenMP libs are found
# Config-specific options: RELEASE
$<$<CONFIG:RELEASE>:-O3> # Optimization level at 3 for Release
$<$<AND:$<BOOL:${LINK_TIME_OPTIMIZATION}>,$<CONFIG:RELEASE>>:-ipo> # activate interprocediral optimization (aka link time optimization)
$<$<CONFIG:RELEASE>:-init=zero> # Init variables to zero/false/null
# Config-specific options: DEBUG
$<$<CONFIG:DEBUG>:-O0> # Disable all optimizations
$<$<CONFIG:DEBUG>:-g> # Generates complete debugging information
$<$<CONFIG:DEBUG>:-traceback> # Generates extra information in the object file to provide source file traceback information when a severe error occurs at run time
$<$<CONFIG:DEBUG>:-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
#$<$<CONFIG:DEBUG>:-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.
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-init=zero> # Init integer and logical variables to zero/false/null instead of random to avoid random bugs
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-init=snan> # Init real variables to signaling nans to detect uninitialized variables
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-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)
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-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.
# $<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-fpe-all=0>
# $<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-no-ftz=0>
# $<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-traceback=0>
$<$<BOOL:${ENABLE_PROFILING}>:-g> # The profiler requires both the debug and profile directives (-g and -p)
$<$<BOOL:${ENABLE_PROFILING}>:-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)
$<$<CONFIG:DEBUG>:-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
$<$<PLATFORM_ID:Linux>:-mcmodel=large> # Required on Linux
$<$<BOOL:${OpenMP_Fortran_FOUND}>:-qopenmp> # Compile with qopenmp option if OpenMP libs are found
# Config-specific options: RELEASE
$<$<CONFIG:RELEASE>:-O3> # Optimization level at 3 for Release
$<$<AND:$<BOOL:${LINK_TIME_OPTIMIZATION}>,$<CONFIG:RELEASE>>:-ipo> # activate interprocediral optimization (aka link time optimization)
$<$<CONFIG:RELEASE>:-init=zero> # Init variables to zero/false/null
# Config-specific options: DEBUG
$<$<CONFIG:DEBUG>:-O0> # Disable all optimizations
$<$<CONFIG:DEBUG>:-g> # Generates complete debugging information
$<$<CONFIG:DEBUG>:-traceback> # Generates extra information in the object file to provide source file traceback information when a severe error occurs at run time
#$<$<CONFIG:DEBUG>:-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.
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-init=zero> # Init integer and logical variables to zero/false/null instead of random to avoid random bugs
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-init=snan> # Init real variables to signaling nans to detect uninitialized variables
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-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)
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-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.
# $<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-fpe-all=0>
# $<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-no-ftz=0>
# $<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-traceback=0>
$<$<BOOL:${ENABLE_PROFILING}>:-g> # The profiler requires both the debug and profile directives (-g and -p)
$<$<BOOL:${ENABLE_PROFILING}>:-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)
$<$<CONFIG:DEBUG>:-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
$<$<CONFIG:DEBUG>:-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
$<$<CONFIG:DEBUG>:-fsanitize=address> # Address sanitizer
$<$<BOOL:${ENABLE_CODE_COVERAGE}>:--coverage> # Code coverage (same as -lgcov at link time)
)
elseif (CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM") # Intel (ifx)
target_link_options(molscat
PUBLIC
$<$<AND:$<BOOL:${ENABLE_UNINIT_VAR_RUNTIME_DETECTOR}>,$<CONFIG:DEBUG>>:-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()

View File

@ -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