Add interface to the MiMiC framework for multiscale simulations

This commit is contained in:
antalik 2025-12-28 15:00:33 +01:00 committed by GitHub
parent 09db961365
commit ee2a10ba22
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 1456 additions and 23 deletions

View file

@ -164,6 +164,8 @@ cmake_dependent_option(CP2K_USE_SIRIUS "Enable SIRIUS support"
${CP2K_USE_EVERYTHING} "CP2K_USE_MPI" OFF)
cmake_dependent_option(CP2K_USE_SPLA "Enable SpLA support"
${CP2K_USE_EVERYTHING} "CP2K_USE_MPI" OFF)
cmake_dependent_option(CP2K_USE_MIMIC "Enable MIMIC support"
${CP2K_USE_EVERYTHING} "CP2K_USE_MPI" OFF)
cmake_dependent_option(
CP2K_USE_LIBXSMM "Enable libxsmm support" ${CP2K_USE_EVERYTHING}
"NOT CP2K_USE_ACCEL MATCHES \"OPENCL\"" ON)
@ -816,6 +818,10 @@ if(CP2K_USE_LIBTORCH)
endif()
endif()
if(CP2K_USE_MIMIC)
find_package(MiMiC REQUIRED)
endif()
if(CP2K_USE_MPI_F08 AND NOT MPI_Fortran_HAVE_F08_MODULE)
message(
FATAL_ERROR
@ -1008,6 +1014,11 @@ if(CP2K_USE_SPLA_GEMM_OFFLOADING)
message(" - SpLA GEMM offloading\n\n")
endif()
if(CP2K_USE_MIMIC)
message(" - MiMiC\n" " - include directories: ${CP2K_MIMIC_INCLUDE_DIRS}\n"
" - libraries: ${CP2K_MIMIC_LINK_LIBRARIES}\n\n")
endif()
if(CP2K_USE_DFTD4)
message(" - DFTD4\n" " - include directories : ${dftd4_INCLUDE_DIRS}\n"
" - libraries : ${dftd4_LINK_LIBRARIES}\n\n")
@ -1140,6 +1151,10 @@ if(NOT CP2K_USE_SPLA)
message(" - SpLA")
endif()
if(NOT CP2K_USE_MIMIC)
message(" - MiMiC")
endif()
if(NOT CP2K_USE_HDF5)
message(" - HDF5")
endif()

View file

@ -0,0 +1,71 @@
#!-------------------------------------------------------------------------------------------------!
#! CP2K: A general program to perform molecular dynamics simulations !
#! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
#! !
#! SPDX-License-Identifier: GPL-2.0-or-later !
#!-------------------------------------------------------------------------------------------------!
include(FindPackageHandleStandardArgs)
include(cp2k_utils)
# ! Use PkgConfig to look for modules named mclf and mcl, LOOK for .pc files
find_package(PkgConfig REQUIRED)
if(PKG_CONFIG_FOUND)
pkg_check_modules(CP2K_MIMIC IMPORTED_TARGET GLOBAL mclf mcl)
endif()
# ! Using CP2K_UTILS
if(NOT CP2K_MIMIC_FOUND)
cp2k_set_default_paths(MIMIC "MiMiC")
cp2k_find_libraries(MIMIC mclf)
cp2k_find_libraries(MIMICc mcl)
endif()
if(NOT CP2K_MIMIC_FOUND)
find_library(CP2K_MIMIC_LIBRARIES mclf PATH_SUFFIXES MiMiC)
find_library(CP2K_MIMICc_LIBRARIES mcl PATH_SUFFIXES MiMiC)
set(CP2K_MIMIC_FOUND True)
endif()
if(CP2K_MIMIC_FOUND)
set(CP2K_MIMIC_LINK_LIBRARIES
"${CP2K_MIMIC_LIBRARIES};${CP2K_MIMICc_LIBRARIES}")
endif()
if(NOT CP2K_MIMIC_INCLUDE_DIRS)
cp2k_include_dirs(MIMIC "mcl.mod")
endif()
if(NOT CP2K_MIMIC_INCLUDE_DIRS)
find_path(CP2K_MIMIC_INCLUDE_DIRS "mcl.mod" PATH_SUFFIXES MiMiC)
endif()
if(CP2K_MIMIC_INCLUDE_DIRS)
find_package_handle_standard_args(
MiMiC DEFAULT_MSG CP2K_MIMIC_FOUND CP2K_MIMIC_LINK_LIBRARIES
CP2K_MIMIC_INCLUDE_DIRS)
else()
find_package_handle_standard_args(MiMiC DEFAULT_MSG CP2K_MIMIC_FOUND
CP2K_MIMIC_LINK_LIBRARIES)
endif()
if(CP2K_MIMIC_FOUND)
if(NOT TARGET CP2K::MIMIC::mclf)
add_library(CP2K::MIMIC::mclf INTERFACE IMPORTED)
add_library(CP2K::MIMIC::mcl INTERFACE IMPORTED)
endif()
if(CP2K_MIMIC_INCLUDE_DIRS)
set_target_properties(
CP2K::MIMIC::mclf CP2K::MIMIC::mcl
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CP2K_MIMIC_INCLUDE_DIRS}")
endif()
target_link_libraries(CP2K::MIMIC::mclf
INTERFACE "${CP2K_MIMIC_LINK_LIBRARIES}")
target_link_libraries(CP2K::MIMIC::mcl
INTERFACE "${CP2K_MIMIC_LINK_LIBRARIES}")
endif()
mark_as_advanced(CP2K_MIMIC_FOUND CP2K_MIMIC_LINK_LIBRARIES
CP2K_MIMIC_INCLUDE_DIRS)

View file

@ -236,3 +236,12 @@ greenX - Open-source file format and library. Support for greenX can be enabled
- Pass `-DCP2K_USE_HDF5=ON` to CMake to enable HDF5 support.
- HDF5 is a hard dependency for SIRIUS and TREXIO, but can also be used by itself to allow
read/write functionalities of QCSchema files in the active space module.
## MIMIC (multiscale simulations)
MiMiC - Multiscale simulation framework
- Interface realized through MCL library, which can be downloaded from
<https://https://mimic-project.org>
- For more information about the framework and supported programs see <https://mimic-project.org>
- Pass `-DCP2K_USE_MIMIC=ON` to CMake

View file

@ -1081,6 +1081,9 @@ list(
input/input_section_types.F
input/input_val_types.F)
list(APPEND CP2K_SRCS_F mimic/mimic_communicator.F mimic/mimic_loop.F
mimic/mcl_wrapper/mcl_api.F mimic/mcl_wrapper/mcl_requests.F)
list(
APPEND
CP2K_SRCS_F
@ -1733,6 +1736,8 @@ target_link_libraries(
$<$<AND:$<BOOL:${CP2K_USE_FFTW3_}>,$<BOOL:${CP2K_ENABLE_FFTW3_THREADS_SUPPORT}>>:cp2k::FFTW3::fftw3_threads>
$<$<AND:$<BOOL:${CP2K_USE_FFTW3_}>,$<BOOL:${CP2K_ENABLE_FFTW3_OPENMP_SUPPORT}>>:cp2k::FFTW3::fftw3_omp>
$<$<BOOL:${CP2K_USE_SPLA}>:SPLA::spla>
$<$<BOOL:${CP2K_USE_MIMIC}>:CP2K::MIMIC::mclf>
$<$<BOOL:${CP2K_USE_MIMIC}>:CP2K::MIMIC::mcl>
$<$<BOOL:${CP2K_USE_LIBINT2}>:cp2k::Libint2::int2>
$<$<BOOL:${CP2K_USE_COSMA}>:cp2k::cosma>
$<$<BOOL:${CP2K_USE_DLAF}>:DLAF::Fortran>
@ -1794,6 +1799,7 @@ target_compile_definitions(
$<$<BOOL:${CCP2K_USE_SIRIUS_DFTD4}>:__SIRIUS_DFTD4>
$<$<BOOL:${CCP2K_USE_SIRIUS_NLCG}>:__SIRIUS_NLCG>
$<$<BOOL:${CP2K_USE_SIRIUS_VCSQNM}>:__SIRIUS_VCSQNM>
$<$<BOOL:${CP2K_USE_MIMIC}>:__MIMIC>
$<$<STREQUAL:"${CP2K_BLAS_VENDOR}","MKL">:__MKL>
$<$<STREQUAL:"${CP2K_BLAS_VENDOR}","Apple">:__ACCELERATE>
$<$<BOOL:${CP2K_USE_CUSOLVER_MP}>:__CUSOLVERMP>

View file

@ -222,6 +222,9 @@ CONTAINS
#if defined(__LIBTORCH)
flags = TRIM(flags)//" libtorch"
#endif
#if defined(__MIMIC)
flags = TRIM(flags)//" mimic"
#endif
#if defined(__OFFLOAD_CUDA)
flags = TRIM(flags)//" offload_cuda"
#endif

View file

@ -137,7 +137,8 @@ MODULE input_constants
do_tamc = 17, &
tree_mc_run = 18, &
driver_run = 19, &
negf_run = 20
negf_run = 20, &
mimic_run = 21
! Run Types of Atom Code
INTEGER, PARAMETER, PUBLIC :: atom_no_run = 1, &

View file

@ -20,11 +20,11 @@ MODULE input_cp2k_check
cp_unit_set_release,&
cp_unit_set_type
USE input_constants, ONLY: &
do_region_global, do_thermo_al, do_thermo_csvr, do_thermo_gle, do_thermo_nose, &
do_thermo_same_as_part, negf_run, npt_f_ensemble, npt_i_ensemble, npt_ia_ensemble, &
vdw_nl_LMKLL, xc_funct_b3lyp, xc_funct_beefvdw, xc_funct_blyp, xc_funct_bp, &
xc_funct_hcth120, xc_funct_no_shortcut, xc_funct_olyp, xc_funct_pade, xc_funct_pbe, &
xc_funct_pbe0, xc_funct_tpss, xc_funct_xwpbe, xc_none, xc_vdw_fun_nonloc
do_qs, do_region_global, do_thermo_al, do_thermo_csvr, do_thermo_gle, do_thermo_nose, &
do_thermo_same_as_part, mimic_run, negf_run, npt_f_ensemble, npt_i_ensemble, &
npt_ia_ensemble, vdw_nl_LMKLL, xc_funct_b3lyp, xc_funct_beefvdw, xc_funct_blyp, &
xc_funct_bp, xc_funct_hcth120, xc_funct_no_shortcut, xc_funct_olyp, xc_funct_pade, &
xc_funct_pbe, xc_funct_pbe0, xc_funct_tpss, xc_funct_xwpbe, xc_none, xc_vdw_fun_nonloc
USE input_keyword_types, ONLY: keyword_type
USE input_parsing, ONLY: section_vals_parse
USE input_section_types, ONLY: &
@ -69,9 +69,10 @@ CONTAINS
CHARACTER(len=*), PARAMETER :: routineN = 'check_cp2k_input'
INTEGER :: handle, iforce_eval, nforce_eval, &
run_type
LOGICAL :: explicit, explicit_embed, explicit_mix
INTEGER :: force_eval_method, handle, iforce_eval, &
nforce_eval, run_type
LOGICAL :: apply_ext_potential, do_center, &
explicit, explicit_embed, explicit_mix
TYPE(section_vals_type), POINTER :: section, section1, section2, section3, &
section4, sections
@ -130,6 +131,30 @@ CONTAINS
CALL xc_functionals_expand(section2, section1)
END DO
! additional checks for a MiMiC run
IF (run_type == mimic_run) THEN
! disable CENTER_COORDINATES
CALL section_vals_val_get(sections, "SUBSYS%TOPOLOGY%CENTER_COORDINATES%_SECTION_PARAMETERS_", &
l_val=do_center)
IF (do_center) THEN
CALL section_vals_val_set(sections, &
"SUBSYS%TOPOLOGY%CENTER_COORDINATES%_SECTION_PARAMETERS_", &
l_val=.FALSE.)
CPWARN("Turning off CENTER_COORDINATES for a MiMiC run.")
END IF
! do not allow the use of external potential
section => section_vals_get_subs_vals(sections, "DFT%EXTERNAL_POTENTIAL")
CALL section_vals_get(section, explicit=apply_ext_potential)
IF (apply_ext_potential) &
CPABORT("The EXTERNAL_POTENTIAL section is not allowed for the MiMiC runtype.")
! force eval methods supported with MiMiC
CALL section_vals_val_get(sections, "METHOD", i_val=force_eval_method)
IF (force_eval_method /= do_qs) &
CPABORT("At the moment, only Quickstep method is supported with MiMiC.")
END IF
CALL timestop(handle)
END SUBROUTINE check_cp2k_input

View file

@ -53,8 +53,8 @@ MODULE input_cp2k_global
do_fft_fftw3, do_fft_sg, do_opt_basis, do_optimize_input, do_scalapack, do_swarm, do_tamc, &
do_test, do_tree_mc, do_tree_mc_ana, driver_run, ehrenfest, energy_force_run, energy_run, &
fftw_plan_estimate, fftw_plan_exhaustive, fftw_plan_measure, fftw_plan_patient, gaussian, &
geo_opt_run, linear_response_run, mol_dyn_run, mon_car_run, negf_run, none_run, pint_run, &
real_time_propagation, tree_mc_run, vib_anal
geo_opt_run, linear_response_run, mimic_run, mol_dyn_run, mon_car_run, negf_run, none_run, &
pint_run, real_time_propagation, tree_mc_run, vib_anal
USE input_keyword_types, ONLY: keyword_create,&
keyword_release,&
keyword_type
@ -396,13 +396,14 @@ CONTAINS
"BAND", "CELL_OPT", "WFN_OPT", "WAVEFUNCTION_OPTIMIZATION", &
"MOLECULAR_DYNAMICS", "GEOMETRY_OPTIMIZATION", "MONTECARLO", &
"LINEAR_RESPONSE", "NORMAL_MODES", "RT_PROPAGATION", &
"EHRENFEST_DYN", "TAMC", "TMC", "DRIVER", "NEGF"), &
"EHRENFEST_DYN", "TAMC", "TMC", "DRIVER", "NEGF", "MIMIC"), &
enum_i_vals=[none_run, energy_run, energy_force_run, mol_dyn_run, &
geo_opt_run, mon_car_run, debug_run, &
bsse_run, linear_response_run, pint_run, vib_anal, do_band, &
cell_opt_run, energy_run, energy_run, mol_dyn_run, geo_opt_run, &
mon_car_run, linear_response_run, &
vib_anal, real_time_propagation, ehrenfest, do_tamc, tree_mc_run, driver_run, negf_run], &
vib_anal, real_time_propagation, ehrenfest, do_tamc, tree_mc_run, &
driver_run, negf_run, mimic_run], &
enum_desc=s2a("Perform no tasks", "Computes energy", "Computes energy and forces", &
"Molecular Dynamics", "Geometry Optimization", "Monte Carlo", &
"Performs a Debug analysis", "Basis set superposition error", "Linear Response", &
@ -415,7 +416,8 @@ CONTAINS
"Temperature Accelerated Monte Carlo (TAMC)", &
"Tree Monte Carlo (TMC), a pre-sampling MC algorithm", &
"i-PI driver mode", &
"Non-equilibrium Green's function method"))
"Non-equilibrium Green's function method", &
"Run as a client in a simulation through the MiMiC framework"))
CALL section_add_keyword(section, keyword)
CALL keyword_release(keyword)

14
src/mimic/PACKAGE Normal file
View file

@ -0,0 +1,14 @@
{
"description": "Wrapper for the MiMiC routines",
"requires": [
"mcl_wrapper",
"../",
"../base",
"../common",
"../input",
"../mpiwrap",
"../subsys",
"../pw",
"../pw_env",
],
}

View file

@ -0,0 +1,6 @@
{
"description": "Wrapper for the MCL routines",
"requires": [
"../../base",
],
}

View file

@ -0,0 +1,98 @@
!--------------------------------------------------------------------------------------------------!
! CP2K: A general program to perform molecular dynamics simulations !
! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
! !
! SPDX-License-Identifier: GPL-2.0-or-later !
!--------------------------------------------------------------------------------------------------!
! **************************************************************************************************
!> \brief Wrapper module for MiMiC Communication Library (MCL) routines
!> \par History
!> 05.2025 Created [AA]
!> \author Andrej Antalik
! **************************************************************************************************
MODULE mcl_api
USE kinds, ONLY: int_4, int_8, sp, dp
#if defined(__MIMIC)
USE mcl, ONLY: mcl_finalize, mcl_get_api_version, mcl_get_program_id, mcl_receive, mcl_send
#endif
#include "../../base/base_uses.f90"
IMPLICIT NONE
#:include 'mcl_wrapper.fypp'
PRIVATE
PUBLIC :: mcl_finalize, mcl_get_api_version, mcl_get_program_id, mcl_receive, mcl_send
#if !defined(__MIMIC)
#:for direction in mcl_direction
INTERFACE mcl_${direction}$
MODULE PROCEDURE mcl_${direction}$_char
#:for kind_l in mcl_kind_labels
#:for dim_l in mcl_dimension_labels
MODULE PROCEDURE mcl_${direction}$_${kind_l}$_${dim_l}$
#:endfor
#:endfor
END INTERFACE
#:endfor
CONTAINS
SUBROUTINE mcl_finalize()
CPABORT("This CP2K executable has not been linked against MiMiC.")
END SUBROUTINE mcl_finalize
SUBROUTINE mcl_get_api_version(version)
INTEGER, DIMENSION(3) :: version, dummy_version
CPABORT("This CP2K executable has not been linked against MiMiC.")
dummy_version = version
END SUBROUTINE mcl_get_api_version
SUBROUTINE mcl_get_program_id(id)
INTEGER :: id, dummy_id
CPABORT("This CP2K executable has not been linked against MiMiC.")
dummy_id = id
END SUBROUTINE mcl_get_program_id
#:for direction in mcl_direction
SUBROUTINE mcl_${direction}$_char(buffer, length, tag, remote_id, err)
CHARACTER(LEN=*), TARGET :: buffer
INTEGER :: length, tag, remote_id, dummy_integer
INTEGER, OPTIONAL, INTENT(OUT) :: err
CHARACTER(LEN=:), ALLOCATABLE :: dummy_char
CPABORT("This CP2K executable has not been linked against MiMiC.")
dummy_integer = length
dummy_integer = tag
dummy_integer = remote_id
err = dummy_integer
dummy_char = TRIM(buffer)
END SUBROUTINE mcl_${direction}$_char
#:for kind_v, kind_l in zip(mcl_kinds, mcl_kind_labels)
#:for dim_v, dim_l in zip(mcl_dimensions, mcl_dimension_labels)
SUBROUTINE mcl_${direction}$_${kind_l}$_${dim_l}$ (buffer, length, tag, remote_id, err)
${kind_v}$${dim_v}$, TARGET :: buffer
INTEGER :: length, tag, remote_id, dummy_integer
INTEGER, OPTIONAL, INTENT(OUT) :: err
${kind_v}$${dim_v}$, POINTER :: dummy_buffer
CPABORT("This CP2K executable has not been linked against MiMiC.")
dummy_integer = length
dummy_integer = tag
dummy_integer = remote_id
err = dummy_integer
dummy_buffer => buffer
END SUBROUTINE mcl_${direction}$_${kind_l}$_${dim_l}$
#:endfor
#:endfor
#:endfor
#endif
END MODULE mcl_api

View file

@ -0,0 +1,42 @@
!--------------------------------------------------------------------------------------------------!
! CP2K: A general program to perform molecular dynamics simulations !
! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
! !
! SPDX-License-Identifier: GPL-2.0-or-later !
!--------------------------------------------------------------------------------------------------!
! **************************************************************************************************
!> \brief Wrapper module for MiMiC Communication Library (MCL) request labels
!> \par History
!> 05.2025 Created [AA]
!> \author Andrej Antalik
! **************************************************************************************************
MODULE mcl_requests
#:include 'mcl_wrapper.fypp'
#if defined(__MIMIC)
#:for label in mcl_implemented_labels
USE mcl, ONLY: ${label}$
#:endfor
#endif
IMPLICIT NONE
PRIVATE
#:for label in mcl_implemented_labels
PUBLIC :: ${label}$
#:endfor
#if !defined(__MIMIC)
#:set req_value = -1
#:for label in mcl_implemented_labels
#:set req_value = req_value - 1
INTEGER, PARAMETER :: ${label}$ = ${req_value}$
#:endfor
#endif
END MODULE mcl_requests

View file

@ -0,0 +1,50 @@
#!-------------------------------------------------------------------------------------------------!
#! CP2K: A general program to perform molecular dynamics simulations !
#! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
#! !
#! SPDX-License-Identifier: GPL-2.0-or-later !
#!-------------------------------------------------------------------------------------------------!
#:mute
#:set mcl_implemented_labels = [ &
"MCL_DATA", &
"MCL_LENGTH", &
"MCL_REQUEST", &
"MCL_EXIT", &
"MCL_SEND_CLIENT_ID", &
"MCL_SEND_CLIENT_NAME", &
"MCL_SEND_CLIENT_RUNTYPE", &
"MCL_SEND_CLIENT_APIVER", &
"MCL_RUNTYPE_QM_RS_GRID", &
"MCL_SEND_NUM_PARTICLES", &
"MCL_SEND_NUM_PARTICLE_SPECIES", &
"MCL_SEND_PARTICLE_SPECIES_IDS", &
"MCL_SEND_NUM_FRAGMENTS", &
"MCL_SEND_NUM_PARTICLES_IN_FRAGMENTS", &
"MCL_SEND_PARTICLE_IDS_IN_FRAGMENTS", &
"MCL_SEND_NUM_CONSTR_BONDS", &
"MCL_SEND_NUM_CONSTR_ANGLES", &
"MCL_SEND_PARTICLE_MULTIPOLES", &
"MCL_SEND_NUCLEAR_CHARGES", &
"MCL_SEND_SPECIES_MASSES", &
"MCL_SEND_SPECIES_ELEMENTS", &
"MCL_SEND_SPECIES_LABELS", &
"MCL_SEND_PARTICLE_POSITIONS", &
"MCL_RECV_PARTICLE_POSITIONS", &
"MCL_SEND_PARTICLE_FORCES", &
"MCL_SEND_ENERGY", &
"MCL_SEND_BOX_ORIGIN", &
"MCL_SEND_BOX_VECTORS", &
"MCL_SEND_BOX_NUM_GRIDPOINTS", &
"MCL_SEND_BOX_GRIDPOINT_COORDS", &
"MCL_SEND_DENSITY", &
"MCL_RECV_POTENTIAL_ON_GRIDPOINTS", &
"MCL_SEND_REFERENCE_CHARGES", &
"MCL_COMPUTE_FORCES"]
#:set mcl_direction = ["send", "receive"]
#:set mcl_kinds = ["INTEGER(KIND=int_4)", "INTEGER(KIND=int_8)", "REAL(KIND=sp)", "REAL(KIND=dp)"]
#:set mcl_kind_labels = ["i4", "i8", "sp", "dp"]
#:set mcl_dimensions = ["", ", DIMENSION(:)", ", DIMENSION(:,:)", ", DIMENSION(:,:,:)"]
#:set mcl_dimension_labels = ["0d", "1d", "2d", "3d"]
#:endmute

View file

@ -0,0 +1,711 @@
!--------------------------------------------------------------------------------------------------!
! CP2K: A general program to perform molecular dynamics simulations !
! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
! !
! SPDX-License-Identifier: GPL-2.0-or-later !
!--------------------------------------------------------------------------------------------------!
! **************************************************************************************************
!> \brief Module containing a MiMiC communicator class
!> \par History
!> 05.2025 Created [AA]
!> \author Andrej Antalik
! **************************************************************************************************
MODULE mimic_communicator
USE atomic_kind_list_types, ONLY: atomic_kind_list_type
USE atomic_kind_types, ONLY: get_atomic_kind
USE cp_control_types, ONLY: dft_control_type
USE cp_result_methods, ONLY: get_results
USE cp_result_types, ONLY: cp_result_type
USE cp_subsys_types, ONLY: cp_subsys_get,&
cp_subsys_type
USE cp_units, ONLY: cp_unit_from_cp2k
USE force_env_types, ONLY: force_env_get,&
force_env_type
USE kinds, ONLY: default_string_length,&
dp
USE mcl_api, ONLY: mcl_finalize,&
mcl_get_api_version,&
mcl_get_program_id,&
mcl_receive,&
mcl_send
USE mcl_requests, ONLY: MCL_DATA,&
MCL_LENGTH,&
MCL_REQUEST,&
MCL_RUNTYPE_QM_RS_GRID
USE message_passing, ONLY: mp_para_env_type
USE particle_list_types, ONLY: particle_list_type
USE pw_env_types, ONLY: pw_env_get,&
pw_env_type
USE pw_pool_types, ONLY: pw_pool_type
USE pw_types, ONLY: pw_r3d_rs_type
USE qs_energy_types, ONLY: qs_energy_type
USE qs_environment_types, ONLY: get_qs_env,&
qs_environment_type,&
set_qs_env
USE qs_kind_types, ONLY: get_qs_kind,&
qs_kind_type
USE qs_ks_types, ONLY: qs_ks_env_type,&
set_ks_env
USE qs_rho_types, ONLY: qs_rho_get,&
qs_rho_type
#include "../base/base_uses.f90"
IMPLICIT NONE
PRIVATE
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mimic_communicator'
! **************************************************************************************************
!> \brief MiMiC communicator class that facilitates MiMiC client-server data exchange
!> \par History
!> 05.2025 Created [AA]
! **************************************************************************************************
TYPE, PUBLIC :: mimic_communicator_type
PRIVATE
!> communication
TYPE(mp_para_env_type), POINTER :: para_env => Null()
LOGICAL :: is_ionode
INTEGER :: mcl_server = 0, &
client_id = -1
!> CP2K data
TYPE(force_env_type), POINTER :: force_env => Null()
TYPE(pw_pool_type), POINTER :: pw_info => Null()
TYPE(particle_list_type), POINTER :: atoms => Null()
TYPE(atomic_kind_list_type), POINTER :: kinds => Null()
TYPE(qs_energy_type), POINTER :: energy => Null()
TYPE(pw_r3d_rs_type), POINTER :: potential => Null()
TYPE(qs_rho_type), POINTER :: density => Null()
INTEGER :: n_atoms = -1, &
n_kinds = -1, &
n_spins = -1
INTEGER, DIMENSION(:, :), ALLOCATABLE :: npts_pproc
!> beginning index of the local buffer in the global buffer diminished by 1
INTEGER, DIMENSION(:), ALLOCATABLE :: lb_pproc
CONTAINS
PROCEDURE :: initialize
PROCEDURE :: finalize
PROCEDURE :: receive_request
PROCEDURE :: send_value
PROCEDURE :: send_client_info
PROCEDURE :: send_atom_info
PROCEDURE :: send_kind_info
PROCEDURE :: send_box_info
PROCEDURE :: send_result
PROCEDURE :: send_grid_coordinates
PROCEDURE :: send_density
PROCEDURE :: send_forces
PROCEDURE :: send_positions
PROCEDURE :: receive_positions
PROCEDURE :: receive_potential
END TYPE mimic_communicator_type
CONTAINS
! **************************************************************************************************
!> \brief Initialize the communicator by loading data and saving pointers to relevant data
!> \param this ...
!> \param force_env ...
!> \par History
!> 05.2025 Created [AA]
! **************************************************************************************************
SUBROUTINE initialize(this, force_env)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
TYPE(force_env_type), TARGET :: force_env
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':initialize'
TYPE(cp_subsys_type), POINTER :: subsys
TYPE(dft_control_type), POINTER :: dft_control
TYPE(pw_env_type), POINTER :: pw_env
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(qs_ks_env_type), POINTER :: ks_env
INTEGER :: handle
CALL timeset(routineN, handle)
CALL mcl_get_program_id(this%client_id)
NULLIFY (subsys, qs_env, ks_env, pw_env)
this%force_env => force_env
CALL force_env_get(this%force_env, subsys=subsys, para_env=this%para_env, qs_env=qs_env)
CALL cp_subsys_get(subsys, natom=this%n_atoms, particles=this%atoms, &
nkind=this%n_kinds, atomic_kinds=this%kinds)
CALL get_qs_env(qs_env, energy=this%energy, vee=this%potential, rho=this%density, &
dft_control=dft_control, ks_env=ks_env, pw_env=pw_env)
CALL pw_env_get(pw_env, auxbas_pw_pool=this%pw_info)
this%is_ionode = this%para_env%is_source()
ALLOCATE (this%npts_pproc(3, 0:this%para_env%num_pe - 1), source=0)
this%npts_pproc(:, this%para_env%mepos) = this%pw_info%pw_grid%npts_local
CALL this%para_env%sum(this%npts_pproc)
ALLOCATE (this%lb_pproc(0:this%para_env%num_pe - 1), source=0)
this%lb_pproc(this%para_env%mepos) = this%pw_info%pw_grid%bounds_local(1, 1) &
- this%pw_info%pw_grid%bounds(1, 1)
CALL this%para_env%sum(this%lb_pproc)
this%n_spins = dft_control%nspins
CALL set_qs_env(qs_env, mimic=.TRUE.)
dft_control%apply_external_potential = .TRUE.
dft_control%eval_external_potential = .FALSE.
! allocate external electrostatic potential
IF (ASSOCIATED(this%potential)) THEN
CALL this%potential%release()
DEALLOCATE (this%potential)
END IF
ALLOCATE (this%potential)
CALL this%pw_info%create_pw(this%potential)
CALL set_ks_env(ks_env, vee=this%potential)
CALL timestop(handle)
END SUBROUTINE initialize
! **************************************************************************************************
!> \brief Finalize the simulation by deallocating memory
!> \param this ...
! **************************************************************************************************
SUBROUTINE finalize(this)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':finalize'
INTEGER :: handle
CALL timeset(routineN, handle)
CALL this%para_env%sync()
CALL mcl_finalize()
CALL timestop(handle)
END SUBROUTINE finalize
! **************************************************************************************************
!> \brief Receive a request from the server
!> \param this ...
!> \return ...
! **************************************************************************************************
FUNCTION receive_request(this) RESULT(request)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
INTEGER :: request
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':receive_request'
INTEGER :: handle
CALL timeset(routineN, handle)
request = -1
CALL mcl_receive(request, 1, MCL_REQUEST, this%mcl_server)
CALL this%para_env%bcast(request)
CALL timestop(handle)
END FUNCTION receive_request
! **************************************************************************************************
!> \brief Send the specified single value data to the server
!> \param this ...
!> \param option word corresponding to available options
!> \note Several values hardcoded for now
! **************************************************************************************************
SUBROUTINE send_value(this, option)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*) :: option
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_value'
REAL(dp) :: energy
INTEGER :: handle
CALL timeset(routineN, handle)
SELECT CASE (option)
CASE ("num_atoms", "num_atoms_in_fragments")
CALL mcl_send(this%n_atoms, 1, MCL_DATA, this%mcl_server)
CASE ("num_kinds")
CALL mcl_send(this%n_kinds, 1, MCL_DATA, this%mcl_server)
CASE ("num_fragments")
CALL mcl_send(1, 1, MCL_DATA, this%mcl_server)
CASE ("num_bonds") ! later use to communicate constraints
CALL mcl_send(0, 1, MCL_DATA, this%mcl_server)
CASE ("num_angles") ! later use to communicate constraints
CALL mcl_send(0, 1, MCL_DATA, this%mcl_server)
CASE ("energy")
energy = this%energy%total - this%energy%ee
CALL mcl_send(energy, 1, MCL_DATA, this%mcl_server)
CASE DEFAULT
CPABORT("The value chosen in "//routineN//" is not implemented.")
END SELECT
CALL timestop(handle)
END SUBROUTINE send_value
! **************************************************************************************************
!> \brief Send the specified information about the client to the server
!> \param this ...
!> \param option word corresponding to available options
! **************************************************************************************************
SUBROUTINE send_client_info(this, option)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*) :: option
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_client_info'
CHARACTER(LEN=*), PARAMETER :: client_name = "CP2K"
INTEGER, DIMENSION(3) :: api_version
INTEGER :: handle, length
CALL timeset(routineN, handle)
SELECT CASE (option)
CASE ("id")
CALL mcl_send(this%client_id, 1, MCL_DATA, this%mcl_server)
CASE ("name")
length = LEN(client_name)
CALL mcl_send(length, 1, MCL_LENGTH, this%mcl_server)
CALL mcl_send(client_name, length, MCL_DATA, this%mcl_server)
CASE ("run_type")
CALL mcl_send(MCL_RUNTYPE_QM_RS_GRID, 1, MCL_DATA, this%mcl_server)
CASE ("api_version")
CALL mcl_get_api_version(api_version)
CALL mcl_send(api_version, 3, MCL_DATA, this%mcl_server)
CASE DEFAULT
CPABORT("The value chosen in "//routineN//" is not implemented.")
END SELECT
CALL timestop(handle)
END SUBROUTINE send_client_info
! **************************************************************************************************
!> \brief Send the specified data for each atom to the server
!> \param this ...
!> \param option word corresponding to available options
! **************************************************************************************************
SUBROUTINE send_atom_info(this, option)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*) :: option
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_atom_info'
INTEGER, DIMENSION(:), ALLOCATABLE :: buffer
INTEGER :: handle, i
CALL timeset(routineN, handle)
ALLOCATE (buffer(this%n_atoms))
SELECT CASE (option)
CASE ("kinds")
DO i = 1, this%n_atoms
buffer(i) = this%atoms%els(i)%atomic_kind%kind_number
END DO
CASE ("ids")
DO i = 1, this%n_atoms
buffer(i) = this%atoms%els(i)%atom_index
END DO
CASE DEFAULT
CPABORT("The value chosen in "//routineN//" is not implemented.")
END SELECT
CALL mcl_send(buffer, SIZE(buffer), MCL_DATA, this%mcl_server)
CALL timestop(handle)
END SUBROUTINE send_atom_info
! **************************************************************************************************
!> \brief Send the specified data for each kind to the server
!> \param this ...
!> \param option word corresponding to available options
! **************************************************************************************************
SUBROUTINE send_kind_info(this, option)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*) :: option
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_kind_info'
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kinds
REAL(dp), DIMENSION(:), ALLOCATABLE :: buffer_dp
INTEGER, DIMENSION(:), ALLOCATABLE :: buffer_i
CHARACTER(LEN=:), ALLOCATABLE :: labels
CHARACTER(LEN=default_string_length) :: label
INTEGER :: handle, length, i
CALL timeset(routineN, handle)
SELECT CASE (option)
CASE ("labels")
ALLOCATE (CHARACTER(30*this%n_kinds) :: labels)
labels = ""
DO i = 1, this%n_kinds
CALL get_atomic_kind(this%kinds%els(i), name=label)
labels = TRIM(labels)//TRIM(label)//","
END DO
length = LEN(TRIM(labels)) - 1
CALL mcl_send(length, 1, MCL_LENGTH, this%mcl_server)
CALL mcl_send(labels, length, MCL_DATA, this%mcl_server)
CASE ("elements")
ALLOCATE (buffer_i(this%n_kinds))
DO i = 1, this%n_kinds
CALL get_atomic_kind(this%kinds%els(i), z=buffer_i(i))
END DO
CALL mcl_send(buffer_i, SIZE(buffer_i), MCL_DATA, this%mcl_server)
CASE ("masses")
ALLOCATE (buffer_dp(this%n_kinds))
DO i = 1, this%n_kinds
buffer_dp(i) = cp_unit_from_cp2k(this%kinds%els(i)%mass, "AMU")
END DO
CALL mcl_send(buffer_dp, SIZE(buffer_dp), MCL_DATA, this%mcl_server)
CASE ("nuclear_charges")
NULLIFY (qs_env, qs_kinds)
CALL force_env_get(this%force_env, qs_env=qs_env)
CALL get_qs_env(qs_env, qs_kind_set=qs_kinds)
ALLOCATE (buffer_dp(this%n_kinds))
DO i = 1, this%n_kinds
CALL get_qs_kind(qs_kinds(i), zeff=buffer_dp(i))
END DO
CALL mcl_send(buffer_dp, SIZE(buffer_dp), MCL_DATA, this%mcl_server)
CASE DEFAULT
CPABORT("The value chosen in "//routineN//" is not implemented.")
END SELECT
CALL timestop(handle)
END SUBROUTINE send_kind_info
! **************************************************************************************************
!> \brief Send the specified box information to the server
!> \param this ...
!> \param option word corresponding to available options
! **************************************************************************************************
SUBROUTINE send_box_info(this, option)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*) :: option
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_box_info'
INTEGER, DIMENSION(3) :: npts_glob
REAL(dp), DIMENSION(3) :: origin
REAL(dp), DIMENSION(9) :: box_vectors
INTEGER :: handle, i
CALL timeset(routineN, handle)
npts_glob = this%pw_info%pw_grid%npts
SELECT CASE (option)
CASE ("num_gridpoints")
CALL mcl_send(npts_glob, 3, MCL_DATA, this%mcl_server)
CASE ("origin")
origin = 0.0_dp
CALL mcl_send(origin, 3, MCL_DATA, this%mcl_server)
CASE ("box_vectors")
box_vectors = [(this%pw_info%pw_grid%dh(:, i)*REAL(npts_glob(i), dp), i=1, 3)]
CALL mcl_send(box_vectors, 9, MCL_DATA, this%mcl_server)
CASE DEFAULT
CPABORT("The value chosen in "//routineN//" is not implemented.")
END SELECT
CALL timestop(handle)
END SUBROUTINE send_box_info
! **************************************************************************************************
!> \brief Send the specified result to the server
!> \param this ...
!> \param option word corresponding to available options
! **************************************************************************************************
SUBROUTINE send_result(this, option)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*) :: option
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_result'
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(cp_result_type), POINTER :: results
CHARACTER(LEN=default_string_length) :: description
REAL(KIND=dp), DIMENSION(:), ALLOCATABLE :: buffer
INTEGER :: handle
CALL timeset(routineN, handle)
NULLIFY (qs_env, results)
CALL force_env_get(this%force_env, qs_env=qs_env)
CALL get_qs_env(qs_env, results=results)
SELECT CASE (option)
CASE ("hirshfeld_charges")
description = "[HIRSHFELD-CHARGES]"
ALLOCATE (buffer(this%n_atoms), source=0.0_dp)
CALL get_results(results, description, buffer)
CALL mcl_send(buffer, SIZE(buffer), MCL_DATA, this%mcl_server)
CASE DEFAULT
CPABORT("The value chosen in "//routineN//" is not implemented.")
END SELECT
CALL timestop(handle)
END SUBROUTINE send_result
! **************************************************************************************************
!> \brief Send grid point coordinates to the server
!> \param this ...
! **************************************************************************************************
SUBROUTINE send_grid_coordinates(this)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_grid_coordinates'
INTEGER, DIMENSION(3) :: npts_glob, npts, lb_glob, lb, ub
REAL(dp), DIMENSION(3) :: origin
REAL(dp), DIMENSION(3, 3) :: box_vectors
REAL(dp), DIMENSION(:, :), ALLOCATABLE :: coords
INTEGER :: handle, i, j, k, offset
CALL timeset(routineN, handle)
origin = 0.0_dp
box_vectors = this%pw_info%pw_grid%dh
! number of grid points
npts_glob = this%pw_info%pw_grid%npts
npts = this%pw_info%pw_grid%npts_local
! bounds
lb_glob = this%pw_info%pw_grid%bounds(1, :)
lb = this%pw_info%pw_grid%bounds_local(1, :)
ub = this%pw_info%pw_grid%bounds_local(2, :)
ALLOCATE (coords(3, PRODUCT(npts_glob)), source=0.0_dp)
offset = (lb(1) - lb_glob(1))*PRODUCT(npts(2:))
DO k = lb(3), ub(3)
DO j = lb(2), ub(2)
DO i = lb(1), ub(1)
offset = offset + 1
coords(:, offset) = origin + box_vectors(:, 1)*REAL(i - lb_glob(1), dp) &
+ box_vectors(:, 2)*REAL(j - lb_glob(2), dp) &
+ box_vectors(:, 3)*REAL(k - lb_glob(3), dp)
END DO
END DO
END DO
CALL this%para_env%sum(coords)
CALL mcl_send(coords, SIZE(coords), MCL_DATA, this%mcl_server)
CALL timestop(handle)
END SUBROUTINE send_grid_coordinates
! **************************************************************************************************
!> \brief Receive external potential from the server
!> \param this ...
! **************************************************************************************************
SUBROUTINE receive_potential(this)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':receive_potential'
INTEGER, DIMENSION(3) :: npts, lb, ub
REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET :: buffer
REAL(dp), DIMENSION(:), ALLOCATABLE :: buffer_loc
REAL(dp), DIMENSION(:), POINTER :: buffer_p
INTEGER :: i, j, k, i_proc, offset
INTEGER :: handle, length, tag
CALL timeset(routineN, handle)
NULLIFY (buffer_p)
npts = this%pw_info%pw_grid%npts_local
lb = this%pw_info%pw_grid%bounds_local(1, :)
ub = this%pw_info%pw_grid%bounds_local(2, :)
ALLOCATE (buffer_loc(PRODUCT(npts)))
tag = 1
IF (this%is_ionode) THEN
ALLOCATE (buffer(PRODUCT(this%pw_info%pw_grid%npts)))
! receive potential at the IO process
CALL mcl_receive(buffer, SIZE(buffer), MCL_DATA, this%mcl_server)
! distribute across processes
DO i_proc = 0, this%para_env%num_pe - 1
length = PRODUCT(this%npts_pproc(:, i_proc))
offset = this%lb_pproc(i_proc)*PRODUCT(npts(2:)) + 1
buffer_p => buffer(offset:offset + length - 1)
IF (i_proc /= this%para_env%source) THEN
i = i_proc
CALL this%para_env%send(buffer_p, i, tag)
ELSE
buffer_loc(:) = buffer_p
END IF
END DO
ELSE
CALL this%para_env%recv(buffer_loc, this%para_env%source, tag)
END IF
! set the potential
offset = 0
DO k = lb(3), ub(3)
DO j = lb(2), ub(2)
DO i = lb(1), ub(1)
offset = offset + 1
this%potential%array(i, j, k) = -buffer_loc(offset)
END DO
END DO
END DO
CALL timestop(handle)
END SUBROUTINE receive_potential
! **************************************************************************************************
!> \brief Send electron density to the server
!> \param this ...
! **************************************************************************************************
SUBROUTINE send_density(this)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_density'
INTEGER, DIMENSION(3) :: npts, lb, ub
TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho
REAL(dp), DIMENSION(:), ALLOCATABLE, TARGET :: buffer
REAL(dp), DIMENSION(:), ALLOCATABLE :: buffer_loc
REAL(dp), DIMENSION(:), POINTER :: buffer_p
INTEGER :: i_spin, i_proc, i, j, k, offset
INTEGER :: handle, length, tag
CALL timeset(routineN, handle)
NULLIFY (rho, buffer_p)
CALL qs_rho_get(this%density, rho_r=rho)
npts = this%pw_info%pw_grid%npts_local
lb = this%pw_info%pw_grid%bounds_local(1, :)
ub = this%pw_info%pw_grid%bounds_local(2, :)
ALLOCATE (buffer_loc(PRODUCT(npts)))
! gather density values
buffer_loc = 0.0_dp
DO i_spin = 1, this%n_spins
offset = 0
DO k = lb(3), ub(3)
DO j = lb(2), ub(2)
DO i = lb(1), ub(1)
offset = offset + 1
buffer_loc(offset) = buffer_loc(offset) + rho(i_spin)%array(i, j, k)
END DO
END DO
END DO
END DO
tag = 1
IF (.NOT. this%is_ionode) THEN
CALL this%para_env%send(buffer_loc, this%para_env%source, tag)
ELSE
ALLOCATE (buffer(PRODUCT(this%pw_info%pw_grid%npts)))
! collect from the processes at the IO process
DO i_proc = 0, this%para_env%num_pe - 1
length = PRODUCT(this%npts_pproc(:, i_proc))
offset = this%lb_pproc(i_proc)*PRODUCT(npts(2:)) + 1
buffer_p => buffer(offset:offset + length - 1)
IF (i_proc /= this%para_env%source) THEN
i = i_proc
CALL this%para_env%recv(buffer_p, i, tag)
ELSE
buffer_p = buffer_loc
END IF
END DO
! send the density
CALL mcl_send(buffer, SIZE(buffer), MCL_DATA, this%mcl_server)
END IF
CALL timestop(handle)
END SUBROUTINE send_density
! **************************************************************************************************
!> \brief Send positions of all atoms to the server
!> \param this ...
! **************************************************************************************************
SUBROUTINE send_positions(this)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_positions'
REAL(dp), DIMENSION(:, :), ALLOCATABLE :: buffer
INTEGER :: handle, i_atom
CALL timeset(routineN, handle)
ALLOCATE (buffer(3, this%n_atoms))
DO i_atom = 1, this%n_atoms
buffer(:, i_atom) = this%atoms%els(i_atom)%r
END DO
CALL mcl_send(buffer, SIZE(buffer), MCL_DATA, this%mcl_server)
CALL timestop(handle)
END SUBROUTINE send_positions
! **************************************************************************************************
!> \brief Receive positions of all atoms from the server
!> \param this ...
! **************************************************************************************************
SUBROUTINE receive_positions(this)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':receive_positions'
REAL(dp), DIMENSION(:, :), ALLOCATABLE :: buffer
INTEGER :: handle, i_atom
CALL timeset(routineN, handle)
ALLOCATE (buffer(3, this%n_atoms))
CALL mcl_receive(buffer, SIZE(buffer), MCL_DATA, this%mcl_server)
CALL this%para_env%bcast(buffer)
DO i_atom = 1, this%n_atoms
this%atoms%els(i_atom)%r = buffer(:, i_atom)
END DO
CALL timestop(handle)
END SUBROUTINE receive_positions
! **************************************************************************************************
!> \brief Send QM forces of all atoms to the server
!> \param this ...
! **************************************************************************************************
SUBROUTINE send_forces(this)
CLASS(mimic_communicator_type), INTENT(INOUT) :: this
CHARACTER(LEN=*), PARAMETER :: routineN = moduleN//':send_forces'
REAL(dp), DIMENSION(:, :), ALLOCATABLE :: buffer
INTEGER :: handle, i_atom
CALL timeset(routineN, handle)
ALLOCATE (buffer(3, this%n_atoms))
DO i_atom = 1, this%n_atoms
buffer(:, i_atom) = this%atoms%els(i_atom)%f
END DO
CALL mcl_send(buffer, SIZE(buffer), MCL_DATA, this%mcl_server)
CALL timestop(handle)
END SUBROUTINE send_forces
END MODULE mimic_communicator

139
src/mimic/mimic_loop.F Normal file
View file

@ -0,0 +1,139 @@
!--------------------------------------------------------------------------------------------------!
! CP2K: A general program to perform molecular dynamics simulations !
! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
! !
! SPDX-License-Identifier: GPL-2.0-or-later !
!--------------------------------------------------------------------------------------------------!
! **************************************************************************************************
!> \brief Module containing the main loop for simulations with the MiMiC framework
!> \par History
!> 05.2025 Created [AA]
!> \author Andrej Antalik
! **************************************************************************************************
MODULE mimic_loop
USE force_env_methods, ONLY: force_env_calc_energy_force
USE force_env_types, ONLY: force_env_type
USE mcl_requests, ONLY: &
MCL_COMPUTE_FORCES, MCL_EXIT, MCL_RECV_PARTICLE_POSITIONS, &
MCL_RECV_POTENTIAL_ON_GRIDPOINTS, MCL_SEND_BOX_GRIDPOINT_COORDS, &
MCL_SEND_BOX_NUM_GRIDPOINTS, MCL_SEND_BOX_ORIGIN, MCL_SEND_BOX_VECTORS, &
MCL_SEND_CLIENT_APIVER, MCL_SEND_CLIENT_ID, MCL_SEND_CLIENT_NAME, MCL_SEND_CLIENT_RUNTYPE, &
MCL_SEND_DENSITY, MCL_SEND_ENERGY, MCL_SEND_NUCLEAR_CHARGES, MCL_SEND_NUM_CONSTR_ANGLES, &
MCL_SEND_NUM_CONSTR_BONDS, MCL_SEND_NUM_FRAGMENTS, MCL_SEND_NUM_PARTICLES, &
MCL_SEND_NUM_PARTICLES_IN_FRAGMENTS, MCL_SEND_NUM_PARTICLE_SPECIES, &
MCL_SEND_PARTICLE_FORCES, MCL_SEND_PARTICLE_IDS_IN_FRAGMENTS, MCL_SEND_PARTICLE_POSITIONS, &
MCL_SEND_PARTICLE_SPECIES_IDS, MCL_SEND_REFERENCE_CHARGES, MCL_SEND_SPECIES_ELEMENTS, &
MCL_SEND_SPECIES_LABELS, MCL_SEND_SPECIES_MASSES
USE mimic_communicator, ONLY: mimic_communicator_type
#include "../base/base_uses.f90"
IMPLICIT NONE
PRIVATE
PUBLIC :: do_mimic_loop
CONTAINS
! **************************************************************************************************
!> \brief The main loop for a MiMiC run
!> \param force_env ...
!> \par History
!> 5.2025 created [AA]
! **************************************************************************************************
SUBROUTINE do_mimic_loop(force_env)
TYPE(force_env_type), POINTER :: force_env
CHARACTER(LEN=*), PARAMETER :: routineN = 'do_mimic_loop'
CHARACTER(LEN=32) :: request_str
INTEGER :: handle, request
LOGICAL :: is_last_step
TYPE(mimic_communicator_type) :: mimic_comm
CALL timeset(routineN, handle)
CPASSERT(ASSOCIATED(force_env))
CALL mimic_comm%initialize(force_env)
is_last_step = .FALSE.
DO WHILE (.NOT. is_last_step)
request = mimic_comm%receive_request()
SELECT CASE (request)
CASE (MCL_SEND_CLIENT_ID)
CALL mimic_comm%send_client_info("id")
CASE (MCL_SEND_CLIENT_NAME)
CALL mimic_comm%send_client_info("name")
CASE (MCL_SEND_CLIENT_RUNTYPE)
CALL mimic_comm%send_client_info("run_type")
CASE (MCL_SEND_CLIENT_APIVER)
CALL mimic_comm%send_client_info("api_version")
CASE (MCL_SEND_NUM_PARTICLES)
CALL mimic_comm%send_value("num_atoms")
CASE (MCL_SEND_NUM_PARTICLE_SPECIES)
CALL mimic_comm%send_value("num_kinds")
CASE (MCL_SEND_PARTICLE_SPECIES_IDS)
CALL mimic_comm%send_atom_info("kinds")
CASE (MCL_SEND_NUM_FRAGMENTS)
CALL mimic_comm%send_value("num_fragments")
CASE (MCL_SEND_NUM_PARTICLES_IN_FRAGMENTS)
CALL mimic_comm%send_value("num_atoms_in_fragments")
CASE (MCL_SEND_NUM_CONSTR_BONDS)
CALL mimic_comm%send_value("num_bonds")
CASE (MCL_SEND_NUM_CONSTR_ANGLES)
CALL mimic_comm%send_value("num_angles")
CASE (MCL_SEND_SPECIES_MASSES)
CALL mimic_comm%send_kind_info("masses")
CASE (MCL_SEND_PARTICLE_IDS_IN_FRAGMENTS)
CALL mimic_comm%send_atom_info("ids")
CASE (MCL_SEND_SPECIES_ELEMENTS)
CALL mimic_comm%send_kind_info("elements")
CASE (MCL_SEND_SPECIES_LABELS)
CALL mimic_comm%send_kind_info("labels")
CASE (MCL_SEND_PARTICLE_POSITIONS)
CALL mimic_comm%send_positions()
CASE (MCL_RECV_PARTICLE_POSITIONS)
CALL mimic_comm%receive_positions()
CASE (MCL_SEND_PARTICLE_FORCES)
CALL mimic_comm%send_forces()
CASE (MCL_SEND_ENERGY)
CALL mimic_comm%send_value("energy")
CASE (MCL_SEND_NUCLEAR_CHARGES)
CALL mimic_comm%send_kind_info("nuclear_charges")
CASE (MCL_SEND_BOX_NUM_GRIDPOINTS)
CALL mimic_comm%send_box_info("num_gridpoints")
CASE (MCL_SEND_BOX_ORIGIN)
CALL mimic_comm%send_box_info("origin")
CASE (MCL_SEND_BOX_VECTORS)
CALL mimic_comm%send_box_info("box_vectors")
CASE (MCL_SEND_BOX_GRIDPOINT_COORDS)
CALL mimic_comm%send_grid_coordinates()
CASE (MCL_SEND_DENSITY)
CALL mimic_comm%send_density()
CASE (MCL_RECV_POTENTIAL_ON_GRIDPOINTS)
CALL mimic_comm%receive_potential()
CASE (MCL_SEND_REFERENCE_CHARGES)
CALL mimic_comm%send_result("hirshfeld_charges")
CASE (MCL_COMPUTE_FORCES)
CALL force_env_calc_energy_force(force_env, calc_force=.TRUE.)
CASE (MCL_EXIT)
is_last_step = .TRUE.
CASE DEFAULT
WRITE (request_str, "(I0)") request
CPABORT("Unrecognized MiMiC request: "//TRIM(request_str))
END SELECT
END DO
CALL mimic_comm%finalize()
CALL timestop(handle)
END SUBROUTINE do_mimic_loop
END MODULE mimic_loop

View file

@ -27,6 +27,9 @@ MODULE message_passing
real_8_size, default_string_length
USE machine, ONLY: m_abort
USE mp_perf_env, ONLY: add_perf, add_mp_perf_env, rm_mp_perf_env
#if defined(__MIMIC)
USE mcl, ONLY: mcl_initialize, mcl_is_initialized, mcl_abort
#endif
#include "../base/base_uses.f90"
@ -144,6 +147,11 @@ MODULE message_passing
PUBLIC :: mp_para_env_create, mp_para_env_release, &
mp_para_cart_create, mp_para_cart_release
#if defined(__MIMIC)
! Stores the split world communicator to finalize a MiMiC run
MPI_COMM_TYPE, PRIVATE, SAVE :: mimic_comm_world
#endif
TYPE mp_comm_type
PRIVATE
MPI_COMM_TYPE :: handle = mp_comm_null_handle
@ -1076,6 +1084,9 @@ CONTAINS
CLASS(mp_comm_type), INTENT(OUT) :: mp_comm
#if defined(__parallel)
INTEGER :: ierr, provided_tsl
#if defined(__MIMIC)
INTEGER :: mimic_handle
#endif
!$OMP MASTER
#if defined(__DLAF)
@ -1099,6 +1110,16 @@ CONTAINS
#endif
debug_comm_count = 1
mp_comm = mp_comm_world
#if defined(__MIMIC)
mimic_handle = mp_comm%get_handle()
CALL mcl_initialize(mimic_handle)
CALL mp_comm%set_handle(mimic_handle)
#if defined(__MPI_F08)
mimic_comm_world%mpi_val = mimic_handle
#else
mimic_comm_world = mimic_handle
#endif
#endif
CALL mp_comm%init()
CALL add_mp_perf_env()
END SUBROUTINE mp_world_init
@ -1164,7 +1185,11 @@ CONTAINS
CHARACTER(LEN=default_string_length) :: debug_comm_count_char
#if defined(__parallel)
INTEGER :: ierr
#if defined(__MIMIC)
CALL mpi_barrier(mimic_comm_world, ierr)
#else
CALL mpi_barrier(MPI_COMM_WORLD, ierr) ! call mpi directly to avoid 0 stack pointer
#endif
#endif
CALL rm_mp_perf_env()
@ -1194,11 +1219,18 @@ CONTAINS
! **************************************************************************************************
SUBROUTINE mp_abort()
INTEGER :: ierr
#if defined(__MIMIC)
LOGICAL :: mcl_initialized
#endif
ierr = 0
#if !defined(__NO_ABORT)
#if defined(__parallel)
#if defined(__MIMIC)
CALL mcl_is_initialized(mcl_initialized)
IF (mcl_initialized) CALL mcl_abort(1, ierr)
#endif
CALL mpi_abort(MPI_COMM_WORLD, 1, ierr)
#else
CALL m_abort()

View file

@ -321,7 +321,7 @@ CONTAINS
END IF
! reallocate vee: external electrostatic potential
IF (dft_control%apply_external_potential) THEN
IF (dft_control%apply_external_potential .AND. .NOT. qs_env%mimic) THEN
NULLIFY (vee)
CALL get_qs_env(qs_env, pw_env=new_pw_env, vee=vee)
IF (ASSOCIATED(vee)) THEN

View file

@ -219,6 +219,7 @@ MODULE qs_environment_types
TYPE qs_environment_type
LOGICAL :: qmmm = .FALSE., qmmm_periodic = .FALSE.
LOGICAL :: mimic = .FALSE.
LOGICAL :: requires_mo_derivs = .FALSE.
LOGICAL :: requires_matrix_vxc = .FALSE.
LOGICAL :: has_unit_metric = .FALSE.
@ -341,6 +342,7 @@ CONTAINS
!> \param sab_all ...
!> \param qmmm ...
!> \param qmmm_periodic ...
!> \param mimic ...
!> \param sac_ae ...
!> \param sac_ppl ...
!> \param sac_lri ...
@ -496,7 +498,7 @@ CONTAINS
!> \version 1.0
! **************************************************************************************************
SUBROUTINE get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, &
dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, &
dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, &
sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, &
sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, &
sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, &
@ -536,7 +538,7 @@ CONTAINS
TYPE(mo_set_type), DIMENSION(:), OPTIONAL, POINTER :: mos
TYPE(neighbor_list_set_p_type), DIMENSION(:), &
OPTIONAL, POINTER :: sab_orb, sab_all
LOGICAL, OPTIONAL :: qmmm, qmmm_periodic
LOGICAL, OPTIONAL :: qmmm, qmmm_periodic, mimic
TYPE(neighbor_list_set_p_type), DIMENSION(:), OPTIONAL, POINTER :: sac_ae, sac_ppl, sac_lri, &
sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, &
sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo
@ -679,6 +681,7 @@ CONTAINS
IF (PRESENT(super_cell)) super_cell => qs_env%super_cell
IF (PRESENT(qmmm)) qmmm = qs_env%qmmm
IF (PRESENT(qmmm_periodic)) qmmm_periodic = qs_env%qmmm_periodic
IF (PRESENT(mimic)) mimic = qs_env%mimic
IF (PRESENT(mos)) mos => qs_env%mos
IF (PRESENT(mos_last_converged)) mos_last_converged => qs_env%mos_last_converged
IF (PRESENT(ewald_env)) ewald_env => qs_env%ewald_env
@ -963,6 +966,7 @@ CONTAINS
qs_env%single_point_run = .FALSE.
qs_env%qmmm = .FALSE.
qs_env%qmmm_periodic = .FALSE.
qs_env%mimic = .FALSE.
qs_env%requires_mo_derivs = .FALSE.
qs_env%requires_matrix_vxc = .FALSE.
qs_env%has_unit_metric = .FALSE.
@ -1004,6 +1008,7 @@ CONTAINS
!> \param mos ...
!> \param qmmm ...
!> \param qmmm_periodic ...
!> \param mimic ...
!> \param ewald_env ...
!> \param ewald_pw ...
!> \param mpools ...
@ -1080,7 +1085,7 @@ CONTAINS
!> \version 1.0
! **************************************************************************************************
SUBROUTINE set_qs_env(qs_env, super_cell, &
mos, qmmm, qmmm_periodic, &
mos, qmmm, qmmm_periodic, mimic, &
ewald_env, ewald_pw, mpools, &
rho_external, external_vxc, mask, &
scf_control, rel_control, qs_charges, ks_env, &
@ -1099,7 +1104,7 @@ CONTAINS
TYPE(qs_environment_type), INTENT(INOUT) :: qs_env
TYPE(cell_type), OPTIONAL, POINTER :: super_cell
TYPE(mo_set_type), DIMENSION(:), OPTIONAL, POINTER :: mos
LOGICAL, OPTIONAL :: qmmm, qmmm_periodic
LOGICAL, OPTIONAL :: qmmm, qmmm_periodic, mimic
TYPE(ewald_environment_type), OPTIONAL, POINTER :: ewald_env
TYPE(ewald_pw_type), OPTIONAL, POINTER :: ewald_pw
TYPE(qs_matrix_pools_type), OPTIONAL, POINTER :: mpools
@ -1189,6 +1194,7 @@ CONTAINS
!
IF (PRESENT(qmmm)) qs_env%qmmm = qmmm
IF (PRESENT(qmmm_periodic)) qs_env%qmmm_periodic = qmmm_periodic
IF (PRESENT(mimic)) qs_env%mimic = mimic
IF (PRESENT(mos)) qs_env%mos => mos
IF (PRESENT(mos_last_converged)) qs_env%mos_last_converged => mos_last_converged
IF (PRESENT(ls_scf_env)) qs_env%ls_scf_env => ls_scf_env

View file

@ -203,7 +203,7 @@ CONTAINS
cell=cell, &
dft_control=dft_control)
IF (dft_control%apply_external_potential) THEN
IF (dft_control%apply_external_potential .AND. .NOT. qs_env%mimic) THEN
!ensure that external potential is loaded to grid
IF (dft_control%eval_external_potential) THEN
CALL external_e_potential(qs_env)

View file

@ -17,5 +17,6 @@
"../motion",
"../motion/mc",
"../emd",
"../mimic",
],
}

View file

@ -75,8 +75,9 @@ MODULE cp2k_runs
bsse_run, cell_opt_run, debug_run, do_atom, do_band, do_cp2k, do_embed, do_farming, &
do_fist, do_ipi, do_mixed, do_nnp, do_opt_basis, do_optimize_input, do_qmmm, do_qs, &
do_sirius, do_swarm, do_tamc, do_test, do_tree_mc, do_tree_mc_ana, driver_run, ehrenfest, &
energy_force_run, energy_run, geo_opt_run, linear_response_run, mol_dyn_run, mon_car_run, &
negf_run, none_run, pint_run, real_time_propagation, rtp_method_bse, tree_mc_run, vib_anal
energy_force_run, energy_run, geo_opt_run, linear_response_run, mimic_run, mol_dyn_run, &
mon_car_run, negf_run, none_run, pint_run, real_time_propagation, rtp_method_bse, &
tree_mc_run, vib_anal
USE input_cp2k, ONLY: create_cp2k_root_section
USE input_cp2k_check, ONLY: check_cp2k_input
USE input_cp2k_global, ONLY: create_global_section
@ -106,6 +107,7 @@ MODULE cp2k_runs
mp_comm_type,&
mp_para_env_release,&
mp_para_env_type
USE mimic_loop, ONLY: do_mimic_loop
USE mscfg_methods, ONLY: do_mol_loop,&
loop_over_molecules
USE neb_methods, ONLY: neb
@ -383,6 +385,8 @@ CONTAINS
CALL neb(root_section, input_declaration, para_env, globenv)
CASE (negf_run)
CALL do_negf(force_env)
CASE (mimic_run)
CALL do_mimic_loop(force_env)
CASE default
CPABORT("")
END SELECT

Binary file not shown.

View file

@ -0,0 +1,7 @@
# runs are executed in the same order as in this file
# the second field tells which test should be run in order to compare with the last available output
# e.g. 0 means do not compare anything, running is enough
# 1 compares the last total energy in the file
# for details see cp2k/tools/do_regtest
"client.inp" = [{matcher="E_total", tol=1e-9, ref=-1.17639095290768}]

View file

@ -0,0 +1,61 @@
&GLOBAL
PREFERRED_FFT_LIBRARY FFTW3
PRINT_LEVEL Low
PROJECT h2
RUN_TYPE MIMIC
&END GLOBAL
&FORCE_EVAL
METHOD Quickstep
&DFT
BASIS_SET_FILE_NAME GTH_BASIS_SETS
POTENTIAL_FILE_NAME GTH_POTENTIALS
&MGRID
CUTOFF 100
NGRIDS 4
REL_CUTOFF 60
&END MGRID
&POISSON
PERIODIC NONE
POISSON_SOLVER MT
&END POISSON
&QS
EPS_DEFAULT 1.0E-10
EXTRAPOLATION PS
EXTRAPOLATION_ORDER 5
&END QS
&SCF
EPS_SCF 5.0E-7
MAX_SCF 1000
SCF_GUESS Atomic
&OT
MINIMIZER DIIS
PRECONDITIONER Full_Single_Inverse
&END OT
&END SCF
&XC
&XC_FUNCTIONAL
&GGA_C_LYP T
&END GGA_C_LYP
&GGA_X_B88 T
&END GGA_X_B88
&END XC_FUNCTIONAL
&END XC
&END DFT
&SUBSYS
&CELL
ABC [Bohr] 10.00 10.00 10.00
ALPHA_BETA_GAMMA 90.00 90.00 90.00
PERIODIC NONE
&END CELL
&COORD
Unit Bohr
H 23.09245158 21.44838997 24.18849265
H 22.33656119 21.54287627 25.34122551
&END COORD
&KIND H
BASIS_SET DZVP-GTH
POTENTIAL GTH-BLYP-q1
&END KIND
&END SUBSYS
&END FORCE_EVAL

View file

@ -4,6 +4,7 @@
# in case a new directory is added just add it at the top of the list..
# the order will be regularly checked and modified...
QS/regtest-moments-kpoints
MIMIC/regtest-qmmm mimic mpiranks==4
QS/regtest-monovalent
QS/regtest-tddfpt-sf-force libint !ifx
QS/regtest-tddfpt-sf libint !ifx

View file

@ -317,6 +317,10 @@ class Config:
env["PIKA_COMMANDLINE_OPTIONS"] = (
f"--pika:bind=none --pika:threads={self.ompthreads}"
)
if cwd is not None and "MIMIC" == cwd.parent.name:
env["MCL_COMM_MODE"] = "TEST_STUB"
env["MCL_PROGRAM"] = "1"
env["MCL_TEST_DATA"] = "MCL_LOG_1"
exe_name = f"{exe_stem}.{self.version}"
cmd = [str(self.binary_dir / exe_name)]
if self.valgrind:

View file

@ -246,6 +246,8 @@ The --with-PKG options follow the rules:
Default = no
--with-ace Enable interface to ML-pace
Default = no
--with-mcl Install MCL library for MiMiC with toolchain.
Default = no
FURTHER INSTRUCTIONS
@ -281,7 +283,8 @@ mpi_list="mpich openmpi intelmpi"
math_list="mkl acml openblas"
lib_list="fftw libint libxc libgrpp libxsmm cosma scalapack elpa dbcsr
cusolvermp plumed spfft spla gsl spglib hdf5 libvdwxc sirius
libvori libtorch deepmd ace dftd4 tblite pugixml libsmeagol trexio greenx gmp"
libvori libtorch deepmd ace dftd4 tblite pugixml libsmeagol
trexio greenx gmp mcl"
package_list="${tool_list} ${mpi_list} ${math_list} ${lib_list}"
# ------------------------------------------------------------------------
@ -336,6 +339,7 @@ with_ninja="__DONTUSE__"
with_dftd4="__DONTUSE__"
with_tblite="__DONTUSE__"
with_libsmeagol="__DONTUSE__"
with_mcl="__DONTUSE__"
# for MPI, we try to detect system MPI variant
if (command -v mpiexec > /dev/null 2>&1); then
@ -697,6 +701,9 @@ while [ $# -ge 1 ]; do
--with-dbcsr*)
with_dbcsr=$(read_with $1)
;;
--with-mcl*)
with_mcl=$(read_with ${1})
;;
--help*)
show_help
exit 0
@ -770,6 +777,10 @@ if [ "${MPI_MODE}" = "no" ]; then
echo "Not using MPI, so COSMA is disabled"
with_cosma="__DONTUSE__"
fi
if [ "${with_mcl}" != "__DONTUSE__" ]; then
echo "Not using MPI, so MCL is disabled"
with_mcl="__DONTUSE__"
fi
else
# if gcc is installed, then mpi needs to be installed too
if [ "${with_gcc}" = "__INSTALL__" ]; then
@ -844,6 +855,7 @@ if [ "${with_spglib}" = "__INSTALL__" ] ||
[ "${with_ninja}" = "__INSTALL__" ] ||
[ "${with_greenx}" = "__INSTALL__" ] ||
[ "${with_dftd4}" = "__INSTALL__" ] ||
[ "${with_mcl}" = "__INSTALL__" ] ||
[ "${with_tblite}" = "__INSTALL__" ]; then
[ "${with_cmake}" = "__DONTUSE__" ] && with_cmake="__INSTALL__"
fi

View file

@ -0,0 +1,112 @@
#!/bin/bash -e
# TODO: Review and if possible fix shellcheck errors.
# shellcheck disable=all
[ "${BASH_SOURCE[0]}" ] && SCRIPT_NAME="${BASH_SOURCE[0]}" || SCRIPT_NAME=$0
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_NAME")/.." && pwd -P)"
mcl_ver="3.0.0"
mcl_sha256="3e740582836fe90e04a693cfc5a219826bcac03217f70ea5570bad6aeafda685"
# shellcheck source=/dev/null
source "${SCRIPT_DIR}"/common_vars.sh
source "${SCRIPT_DIR}"/tool_kit.sh
source "${SCRIPT_DIR}"/signal_trap.sh
source "${INSTALLDIR}"/toolchain.conf
source "${INSTALLDIR}"/toolchain.env
[ -f "${BUILDDIR}/setup_mcl" ] && rm "${BUILDDIR}/setup_mcl"
! [ -d "${BUILDDIR}" ] && mkdir -p "${BUILDDIR}"
cd "${BUILDDIR}"
case "${with_mcl:=__INSTALL__}" in
__INSTALL__)
echo "==================== Installing MCL ===================="
pkg_install_dir="${INSTALLDIR}/mcl-${mcl_ver}"
install_lock_file="${pkg_install_dir}/install_successful"
if verify_checksums "${install_lock_file}"; then
echo "libmcl-${mcl_ver} is already installed, skipping it."
else
if [ -f mcl-${mcl_ver}.tar.gz ]; then
echo "mcl-${mcl_ver}.tar.gz is found"
else
download_pkg_from_urlpath "${mcl_sha256}" mcl-${mcl_ver}.tar.gz \
https://gitlab.com/mimic-project/mcl/-/archive/${mcl_ver}
fi
echo "Installing from scratch into ${pkg_install_dir}"
[ -d mcl-${mcl_ver} ] && rm -rf mcl-${mcl_ver}
tar -xzf mcl-${mcl_ver}.tar.gz
mkdir "mcl-${mcl_ver}/build"
cd "mcl-${mcl_ver}/build"
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=YES \
-DBUILD_FORTRAN_API=YES \
-DCMAKE_INSTALL_PREFIX="${pkg_install_dir}" \
-DCMAKE_VERBOSE_MAKEFILE=ON \
.. > cmake.log 2>&1 || tail -n ${LOG_LINES} cmake.log
CMAKE_BUILD_PARALLEL_LEVEL="$(get_nprocs)" cmake --build . > build.log 2>&1 || tail -n ${LOG_LINES} build.log
CMAKE_BUILD_PARALLEL_LEVEL="$(get_nprocs)" cmake --build . --target install > install.log 2>&1 || tail -n ${LOG_LINES} install.log
write_checksums "${install_lock_file}" "${SCRIPT_DIR}/stage8/$(basename "${SCRIPT_NAME}")"
fi
MCL_LDFLAGS="-L'${pkg_install_dir}/lib/MiMiC' -Wl,-rpath,'${pkg_install_dir}/lib/MiMiC'"
;;
__SYSTEM__)
echo "==================== Finding MCL from system paths ===================="
check_lib -lmclf "mcl"
add_lib_from_paths MCL_LDFLAGS "mclf.*" "$LIB_PATHS"
add_lib_from_paths MCL_LDFLAGS "mcl.*" "$LIB_PATHS"
;;
__DONTUSE__) ;;
*)
echo "==================== Linking MCL to user paths ===================="
pkg_install_dir="${with_mcl}"
# use the lib64 directory if present (multi-abi distros may link lib/ to lib32/ instead)
MCL_LIBDIR="${pkg_install_dir}/lib/MiMiC"
[ -d "${pkg_install_dir}/lib64" ] && MCL_LIBDIR="${pkg_install_dir}/lib64/MiMiC"
check_dir "${MCL_LIBDIR}"
MCL_LDFLAGS="-L'${MCL_LIBDIR}' -Wl,-rpath,'$MCL_LIBDIR}'"
;;
esac
if [ "$with_mcl" != "__DONTUSE__" ]; then
MCL_LIBS="-lmcl -lmclf -lstdc++"
if [ "$with_mcl" != "__SYSTEM__" ]; then
cat << EOF > "${BUILDDIR}/setup_mcl"
prepend_path LD_LIBRARY_PATH "${pkg_install_dir}/lib/MiMiC"
prepend_path LD_RUN_PATH "${pkg_install_dir}/lib/MiMiC"
prepend_path LIBRARY_PATH "${pkg_install_dir}/lib/MiMiC"
export MCL_LIBS="${MCL_LIBS}"
export MCL_ROOT="${pkg_install_dir}"
prepend_path PKG_CONFIG_PATH "$pkg_install_dir/lib/pkgconfig"
prepend_path CMAKE_PREFIX_PATH "$pkg_install_dir"
EOF
fi
cat << EOF >> "${BUILDDIR}/setup_mcl"
export MCL_VER="${mcl_ver}"
export MCL_ROOT="${pkg_install_dir}"
export MCL_LDFLAGS="${MCL_LDFLAGS}"
export MCL_LIBS="${MCL_LIBS}"
export CP_DFLAGS="\${CP_DFLAGS} -D__MIMIC"
export CP_LDFLAGS="\${CP_LDFLAGS} ${MCL_LDFLAGS}"
export CP_LIBS="\${CP_LIBS} ${MCL_LIBS}"
EOF
cat "${BUILDDIR}/setup_mcl" >> "${SETUPFILE}"
fi
load "${BUILDDIR}/setup_mcl"
write_toolchain_env "${INSTALLDIR}"
cd "${ROOTDIR}"
report_timing "MCL"

View file

@ -10,4 +10,5 @@
./scripts/stage8/install_dftd4.sh
./scripts/stage8/install_trexio.sh
./scripts/stage8/install_tblite.sh
./scripts/stage8/install_mcl.sh
#EOF