!--------------------------------------------------------------------------------------------------! ! CP2K: A general program to perform molecular dynamics simulations ! ! Copyright (C) 2000 - 2020 CP2K developers group ! !--------------------------------------------------------------------------------------------------! ! ************************************************************************************************** !> \brief Interface to the Libint-Library or a c++ wrapper. !> \par History !> 11.2007 created [Manuel Guidon] !> 10.2009 refactored [Manuel Guidon] !> \author Manuel Guidon ! ************************************************************************************************** MODULE libint_wrapper #if(__LIBINT) #include #include #endif ! maximum angular momentum to be supported in CP2K-LIBINT interface #:set libint_max_am_supported = 8 USE ISO_C_BINDING, ONLY: C_F_POINTER, & C_F_PROCPOINTER, & C_NULL_PTR, & C_FUNPTR USE kinds, ONLY: dp #if(__LIBINT) USE libint_f, ONLY: & libint2_build, libint2_build_eri, libint2_build_eri1, libint2_cleanup_eri, & libint2_cleanup_eri1, libint2_init_eri, libint2_init_eri1, libint2_static_cleanup, & libint2_static_init, libint_t, libint2_max_am_eri, libint2_init_3eri, libint2_cleanup_3eri, & libint2_init_2eri, libint2_cleanup_2eri!,& !libint2_build_3eri #endif USE orbital_pointers, ONLY: nco #include "./base/base_uses.f90" IMPLICIT NONE PRIVATE PUBLIC :: cp_libint_t, prim_data_f_size, build_eri_size, build_deriv1_eri_size, & libint_max_am, libderiv_max_am1, cp_libint_get_eris, cp_libint_get_derivs, & cp_libint_init_eri, cp_libint_init_eri1, cp_libint_cleanup_eri, & cp_libint_cleanup_eri1, cp_libint_static_init, cp_libint_static_cleanup, & get_ssss_f_val, cp_libint_set_contrdepth, cp_libint_set_params_eri_screen, & cp_libint_set_params_eri, cp_libint_set_params_eri_deriv, & cp_libint_init_3eri, cp_libint_cleanup_3eri, cp_libint_get_3eris, & cp_libint_init_2eri, cp_libint_cleanup_2eri, cp_libint_get_2eris CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'libint_wrapper' #if(__LIBINT) INTEGER, PARAMETER :: libint_max_am = libint2_max_am_eri #else INTEGER, PARAMETER :: libint_max_am = 0 #endif INTEGER, PARAMETER :: libderiv_max_am1 = libint_max_am INTEGER, PARAMETER :: prim_data_f_size = 4*(libint_max_am) + 1 INTEGER, PARAMETER :: libint_vrr_classes_size = 2*(libint_max_am) + 1 INTEGER, PARAMETER :: libint_dvrr_classes_size = 2*(libderiv_max_am1) + 1 INTEGER, PARAMETER :: build_eri_size = libint_max_am INTEGER, PARAMETER :: build_deriv1_eri_size = libderiv_max_am1 TYPE :: cp_libint_t PRIVATE #if(__LIBINT) TYPE(libint_t), DIMENSION(1) :: prv #else INTEGER :: unused = -1 #endif END TYPE #if(__LIBINT) !Fortran 2-center and 3-center integrals are bugged in libint 2.5. More specifically, the !dimensions of the following array are mixed up. This should be fixed from libint 2.6 on. !Then, one will be able to simply USE libint2_build_3eri & libint2_build_2eri, as currently !commented above TYPE(C_FUNPTR), DIMENSION(0:LIBINT2_MAX_AM, 0:LIBINT2_MAX_AM, 0:LIBINT2_MAX_AM_3eri), & BIND(C) :: libint2_build_3eri TYPE(C_FUNPTR), DIMENSION(0:LIBINT2_MAX_AM_2eri, 0:LIBINT2_MAX_AM_2eri), & BIND(C) :: libint2_build_2eri #endif CONTAINS SUBROUTINE cp_libint_set_params_eri_screen(libint, A, B, C, D, P, Q, W, ZetaInv, EtaInv, ZetapEtaInv, Rho, m_max, F) TYPE(cp_libint_t) :: libint REAL(KIND=dp), INTENT(IN), DIMENSION(3) :: A, B, C, D, P, Q, W REAL(KIND=dp), INTENT(IN) :: ZetaInv, EtaInv, ZetapEtaInv, Rho INTEGER, INTENT(IN) :: m_max REAL(KIND=dp), DIMENSION(:) :: F #if(__LIBINT) libint%prv(1)%AB_x(1) = A(1) - B(1) libint%prv(1)%AB_y(1) = A(2) - B(2) libint%prv(1)%AB_z(1) = A(3) - B(3) libint%prv(1)%CD_x(1) = C(1) - D(1) libint%prv(1)%CD_y(1) = C(2) - D(2) libint%prv(1)%CD_z(1) = C(3) - D(3) libint%prv(1)%PA_x(1) = P(1) - A(1) libint%prv(1)%PA_y(1) = P(2) - A(2) libint%prv(1)%PA_z(1) = P(3) - A(3) libint%prv(1)%QC_x(1) = Q(1) - C(1) libint%prv(1)%QC_y(1) = Q(2) - C(2) libint%prv(1)%QC_z(1) = Q(3) - C(3) libint%prv(1)%WP_x(1) = W(1) - P(1) libint%prv(1)%WP_y(1) = W(2) - P(2) libint%prv(1)%WP_z(1) = W(3) - P(3) libint%prv(1)%WQ_x(1) = W(1) - Q(1) libint%prv(1)%WQ_y(1) = W(2) - Q(2) libint%prv(1)%WQ_z(1) = W(3) - Q(3) libint%prv(1)%oo2z(1) = 0.5_dp*ZetaInv libint%prv(1)%oo2e(1) = 0.5_dp*EtaInv libint%prv(1)%oo2ze(1) = 0.5_dp*ZetapEtaInv libint%prv(1)%roz(1) = Rho*ZetaInv libint%prv(1)%roe(1) = Rho*EtaInv #:for m_max in range(0, 4*libint_max_am_supported) #if 4*LIBINT2_MAX_AM_eri > ${m_max}$ - 1 IF (${m_max}$ .LE. m_max) & libint%prv(1)%f_aB_s___0__s___1___TwoPRep_s___0__s___1___Ab__up_${m_max}$ (1) & = F(${m_max}$+1) #endif #:endfor #else MARK_USED(libint) MARK_USED(A) MARK_USED(B) MARK_USED(C) MARK_USED(D) MARK_USED(P) MARK_USED(Q) MARK_USED(W) MARK_USED(ZetaInv) MARK_USED(EtaInv) MARK_USED(ZetapEtaInv) MARK_USED(Rho) MARK_USED(m_max) MARK_USED(F) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_set_params_eri_deriv(libint, A, B, C, D, P, Q, W, zeta_A, zeta_B, zeta_C, zeta_D, & ZetaInv, EtaInv, ZetapEtaInv, Rho, m_max, F) TYPE(cp_libint_t) :: libint REAL(KIND=dp), INTENT(IN), DIMENSION(3) :: A, B, C, D, P, Q, W REAL(KIND=dp), INTENT(IN) :: zeta_A, zeta_B, zeta_C, zeta_D, ZetaInv, EtaInv, ZetapEtaInv, Rho INTEGER, INTENT(IN) :: m_max REAL(KIND=dp), DIMENSION(:) :: F #if(__LIBINT) REAL(KIND=dp) :: gammap, gammaq, gammapq, rhop, rhoq libint%prv(1)%AB_x(1) = A(1) - B(1) libint%prv(1)%AB_y(1) = A(2) - B(2) libint%prv(1)%AB_z(1) = A(3) - B(3) libint%prv(1)%CD_x(1) = C(1) - D(1) libint%prv(1)%CD_y(1) = C(2) - D(2) libint%prv(1)%CD_z(1) = C(3) - D(3) libint%prv(1)%PA_x(1) = P(1) - A(1) libint%prv(1)%PA_y(1) = P(2) - A(2) libint%prv(1)%PA_z(1) = P(3) - A(3) libint%prv(1)%PB_x(1) = P(1) - B(1) libint%prv(1)%PB_y(1) = P(2) - B(2) libint%prv(1)%PB_z(1) = P(3) - B(3) libint%prv(1)%QC_x(1) = Q(1) - C(1) libint%prv(1)%QC_y(1) = Q(2) - C(2) libint%prv(1)%QC_z(1) = Q(3) - C(3) libint%prv(1)%WP_x(1) = W(1) - P(1) libint%prv(1)%WP_y(1) = W(2) - P(2) libint%prv(1)%WP_z(1) = W(3) - P(3) libint%prv(1)%WQ_x(1) = W(1) - Q(1) libint%prv(1)%WQ_y(1) = W(2) - Q(2) libint%prv(1)%WQ_z(1) = W(3) - Q(3) libint%prv(1)%two_alpha0_bra(1) = 2.0_dp*Zeta_A libint%prv(1)%two_alpha0_ket(1) = 2.0_dp*Zeta_B libint%prv(1)%two_alpha1_ket(1) = 2.0_dp*Zeta_D gammap = Zeta_A + Zeta_B gammaq = Zeta_C + Zeta_D gammapq = gammap*gammaq/(gammap + gammaq) libint%prv(1)%alpha1_rho_over_zeta2(1) = Zeta_A*gammapq/(gammap*gammap) libint%prv(1)%alpha2_rho_over_zeta2(1) = Zeta_B*gammapq/(gammap*gammap) libint%prv(1)%alpha4_rho_over_eta2(1) = Zeta_D*gammapq/(gammaq*gammaq) libint%prv(1)%alpha1_over_zetapluseta(1) = Zeta_A/(gammap + gammaq) libint%prv(1)%alpha2_over_zetapluseta(1) = Zeta_B/(gammap + gammaq) libint%prv(1)%alpha4_over_zetapluseta(1) = Zeta_D/(gammap + gammaq) rhop = Zeta_A*Zeta_B/gammap rhoq = Zeta_C*Zeta_D/gammaq libint%prv(1)%rho12_over_alpha1(1) = rhop/Zeta_A libint%prv(1)%rho34_over_alpha3(1) = rhoq/Zeta_C libint%prv(1)%oo2z(1) = 0.5_dp*ZetaInv libint%prv(1)%oo2e(1) = 0.5_dp*EtaInv libint%prv(1)%oo2ze(1) = 0.5_dp*ZetapEtaInv libint%prv(1)%roz(1) = Rho*ZetaInv libint%prv(1)%roe(1) = Rho*EtaInv #:for m_max in range(0, 4*libint_max_am_supported) #if 4*LIBINT2_MAX_AM_eri > ${m_max}$ - 1 IF (${m_max}$ .LE. m_max) & libint%prv(1)%f_aB_s___0__s___1___TwoPRep_s___0__s___1___Ab__up_${m_max}$ (1) & ! ERROR: __LIBINT_MAX_AM is too large = F(${m_max}$+1) #endif #:endfor #else MARK_USED(libint) MARK_USED(A) MARK_USED(B) MARK_USED(C) MARK_USED(D) MARK_USED(P) MARK_USED(Q) MARK_USED(W) MARK_USED(zeta_A) MARK_USED(zeta_B) MARK_USED(zeta_C) MARK_USED(zeta_D) MARK_USED(ZetaInv) MARK_USED(EtaInv) MARK_USED(ZetapEtaInv) MARK_USED(Rho) MARK_USED(m_max) MARK_USED(F) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_set_params_eri(libint, A, B, C, D, ZetaInv, EtaInv, ZetapEtaInv, Rho, P, Q, W, m_max, F) TYPE(cp_libint_t) :: libint REAL(KIND=dp), INTENT(IN), DIMENSION(3) :: A, B, C, D, P, Q, W REAL(KIND=dp), INTENT(IN) :: ZetaInv, EtaInv, ZetapEtaInv, Rho REAL(KIND=dp), DIMENSION(:) :: F INTEGER, INTENT(IN) :: m_max #if(__LIBINT) libint%prv(1)%AB_x(1) = A(1) - B(1) libint%prv(1)%AB_y(1) = A(2) - B(2) libint%prv(1)%AB_z(1) = A(3) - B(3) libint%prv(1)%CD_x(1) = C(1) - D(1) libint%prv(1)%CD_y(1) = C(2) - D(2) libint%prv(1)%CD_z(1) = C(3) - D(3) libint%prv(1)%PA_x(1) = P(1) - A(1) libint%prv(1)%PA_y(1) = P(2) - A(2) libint%prv(1)%PA_z(1) = P(3) - A(3) libint%prv(1)%QC_x(1) = Q(1) - C(1) libint%prv(1)%QC_y(1) = Q(2) - C(2) libint%prv(1)%QC_z(1) = Q(3) - C(3) libint%prv(1)%WP_x(1) = W(1) - P(1) libint%prv(1)%WP_y(1) = W(2) - P(2) libint%prv(1)%WP_z(1) = W(3) - P(3) libint%prv(1)%WQ_x(1) = W(1) - Q(1) libint%prv(1)%WQ_y(1) = W(2) - Q(2) libint%prv(1)%WQ_z(1) = W(3) - Q(3) libint%prv(1)%oo2z(1) = 0.5_dp*ZetaInv libint%prv(1)%oo2e(1) = 0.5_dp*EtaInv libint%prv(1)%oo2ze(1) = 0.5_dp*ZetapEtaInv libint%prv(1)%roz(1) = Rho*ZetaInv libint%prv(1)%roe(1) = Rho*EtaInv #:for m_max in range(0, 4*libint_max_am_supported) #if 4*LIBINT2_MAX_AM_eri > ${m_max}$ - 1 IF (${m_max}$ .LE. m_max) & libint%prv(1)%f_aB_s___0__s___1___TwoPRep_s___0__s___1___Ab__up_${m_max}$ (1) & ! ERROR: __LIBINT_MAX_AM is too large = F(${m_max}$+1) #endif #:endfor #else MARK_USED(libint) MARK_USED(A) MARK_USED(B) MARK_USED(C) MARK_USED(D) MARK_USED(P) MARK_USED(Q) MARK_USED(W) MARK_USED(ZetaInv) MARK_USED(EtaInv) MARK_USED(ZetapEtaInv) MARK_USED(Rho) MARK_USED(m_max) MARK_USED(F) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE ! ************************************************************************************************** !> \brief ... !> \param n_d ... !> \param n_c ... !> \param n_b ... !> \param n_a ... !> \param lib ... !> \param p_work ... !> \param a_mysize ... ! ************************************************************************************************** SUBROUTINE cp_libint_get_eris(n_d, n_c, n_b, n_a, lib, p_work, a_mysize) INTEGER, INTENT(IN) :: n_d, n_c, n_b, n_a TYPE(cp_libint_t) :: lib REAL(dp), DIMENSION(:), POINTER :: p_work INTEGER :: a_mysize(1) #if(__LIBINT) PROCEDURE(libint2_build), POINTER :: pbuild CALL C_F_PROCPOINTER(libint2_build_eri(n_d, n_c, n_b, n_a), pbuild) CALL pbuild(lib%prv) CALL C_F_POINTER(lib%prv(1)%targets(1), p_work, SHAPE=a_mysize) #else MARK_USED(n_d) MARK_USED(n_c) MARK_USED(n_b) MARK_USED(n_a) MARK_USED(lib) MARK_USED(p_work) MARK_USED(a_mysize) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE cp_libint_get_eris ! ************************************************************************************************** !> \brief ... !> \param n_c ... !> \param n_b ... !> \param n_a ... !> \param lib ... !> \param p_work ... !> \param a_mysize ... ! ************************************************************************************************** SUBROUTINE cp_libint_get_3eris(n_c, n_b, n_a, lib, p_work, a_mysize) INTEGER, INTENT(IN) :: n_c, n_b, n_a TYPE(cp_libint_t) :: lib REAL(dp), DIMENSION(:), POINTER :: p_work INTEGER :: a_mysize(1) #if(__LIBINT) PROCEDURE(libint2_build), POINTER :: pbuild CALL C_F_PROCPOINTER(libint2_build_3eri(n_c, n_b, n_a), pbuild) CALL pbuild(lib%prv) CALL C_F_POINTER(lib%prv(1)%targets(1), p_work, SHAPE=a_mysize) #else MARK_USED(n_c) MARK_USED(n_b) MARK_USED(n_a) MARK_USED(lib) MARK_USED(p_work) MARK_USED(a_mysize) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE cp_libint_get_3eris ! ************************************************************************************************** !> \brief ... !> \param n_c ... !> \param n_b ... !> \param n_a ... !> \param lib ... !> \param p_work ... !> \param a_mysize ... ! ************************************************************************************************** SUBROUTINE cp_libint_get_2eris(n_b, n_a, lib, p_work, a_mysize) INTEGER, INTENT(IN) :: n_b, n_a TYPE(cp_libint_t) :: lib REAL(dp), DIMENSION(:), POINTER :: p_work INTEGER :: a_mysize(1) #if(__LIBINT) PROCEDURE(libint2_build), POINTER :: pbuild CALL C_F_PROCPOINTER(libint2_build_2eri(n_b, n_a), pbuild) CALL pbuild(lib%prv) CALL C_F_POINTER(lib%prv(1)%targets(1), p_work, SHAPE=a_mysize) #else MARK_USED(n_b) MARK_USED(n_a) MARK_USED(lib) MARK_USED(p_work) MARK_USED(a_mysize) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE ! ************************************************************************************************** !> \brief ... !> \param n_d ... !> \param n_c ... !> \param n_b ... !> \param n_a ... !> \param lib ... !> \param work_forces ... !> \param a_mysize ... ! ************************************************************************************************** SUBROUTINE cp_libint_get_derivs(n_d, n_c, n_b, n_a, lib, work_forces, a_mysize) INTEGER, INTENT(IN) :: n_d, n_c, n_b, n_a TYPE(cp_libint_t) :: lib REAL(dp), DIMENSION(nco(n_a)*nco(n_b)*nco(n_c)*nco & (n_d), 12) :: work_forces INTEGER :: a_mysize(1) #if(__LIBINT) REAL(dp), DIMENSION(:), POINTER :: p_work PROCEDURE(libint2_build), POINTER :: pbuild INTEGER :: i, k #endif #if(__LIBINT) CALL C_F_PROCPOINTER(libint2_build_eri1(n_d, n_c, n_b, n_a), pbuild) CALL pbuild(lib%prv) DO k = 1, 12 IF (k == 4 .OR. k == 5 .OR. k == 6) CYCLE CALL C_F_POINTER(lib%prv(1)%targets(k), p_work, SHAPE=a_mysize) DO i = 1, a_mysize(1) work_forces(i, k) = p_work(i) ENDDO ENDDO #else MARK_USED(n_d) MARK_USED(n_c) MARK_USED(n_b) MARK_USED(n_a) MARK_USED(lib) MARK_USED(work_forces) MARK_USED(a_mysize) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE cp_libint_get_derivs FUNCTION get_ssss_f_val(lib) TYPE(cp_libint_t) :: lib REAL(KIND=dp) :: get_ssss_f_val get_ssss_f_val = 0 #if(__LIBINT) get_ssss_f_val = lib%prv(1)%f_aB_s___0__s___1___TwoPRep_s___0__s___1___Ab__up_0(1) #else MARK_USED(lib) MARK_USED(get_ssss_f_val) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END FUNCTION SUBROUTINE cp_libint_init_eri(lib, max_am) TYPE(cp_libint_t) :: lib INTEGER :: max_am #if(__LIBINT) CALL libint2_init_eri(lib%prv, max_am, C_NULL_PTR) #else MARK_USED(lib) MARK_USED(max_am) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_set_contrdepth(lib, contrdepth) TYPE(cp_libint_t) :: lib INTEGER :: contrdepth #if(__LIBINT) #if LIBINT_CONTRACTED_INTS lib%prv(1)%contrdepth = contrdepth #else MARK_USED(lib) MARK_USED(contrdepth) #endif #else MARK_USED(lib) MARK_USED(contrdepth) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_init_eri1(lib, max_am) TYPE(cp_libint_t) :: lib INTEGER :: max_am #if(__LIBINT) CALL libint2_init_eri1(lib%prv, max_am, C_NULL_PTR) #else MARK_USED(lib) MARK_USED(max_am) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_init_3eri(lib, max_am) TYPE(cp_libint_t) :: lib INTEGER :: max_am #if(__LIBINT) CALL libint2_init_3eri(lib%prv, max_am, C_NULL_PTR) #else MARK_USED(lib) MARK_USED(max_am) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_init_2eri(lib, max_am) TYPE(cp_libint_t) :: lib INTEGER :: max_am #if(__LIBINT) CALL libint2_init_2eri(lib%prv, max_am, C_NULL_PTR) #else MARK_USED(lib) MARK_USED(max_am) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_cleanup_eri(lib) TYPE(cp_libint_t) :: lib #if(__LIBINT) CALL libint2_cleanup_eri(lib%prv) #else MARK_USED(lib) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_cleanup_eri1(lib) TYPE(cp_libint_t) :: lib #if(__LIBINT) CALL libint2_cleanup_eri1(lib%prv) #else MARK_USED(lib) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_cleanup_3eri(lib) TYPE(cp_libint_t) :: lib #if(__LIBINT) CALL libint2_cleanup_3eri(lib%prv) #else MARK_USED(lib) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_cleanup_2eri(lib) TYPE(cp_libint_t) :: lib #if(__LIBINT) CALL libint2_cleanup_2eri(lib%prv) #else MARK_USED(lib) CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_static_init() #if(__LIBINT) CALL libint2_static_init() #else CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE SUBROUTINE cp_libint_static_cleanup() #if(__LIBINT) CALL libint2_static_cleanup() #else CPABORT("This CP2K executable has not been linked against the required library libint.") #endif END SUBROUTINE END MODULE libint_wrapper