LCOV - code coverage report
Current view: top level - src - libgrpp_integrals.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:b310db4) Lines: 41.8 % 249 104
Test Date: 2026-10-23 01:10:43 Functions: 60.0 % 5 3

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Local and semi-local ECP integrals using the libgrpp library
      10              : ! **************************************************************************************************
      11              : 
      12              : MODULE libgrpp_integrals
      13              :    USE ai_cartesian_operators,          ONLY: apply_cartesian_operator
      14              :    USE kinds,                           ONLY: dp
      15              :    USE libgrpp,                         ONLY: libgrpp_init,&
      16              :                                               libgrpp_type1_integrals,&
      17              :                                               libgrpp_type1_integrals_gradient,&
      18              :                                               libgrpp_type2_integrals,&
      19              :                                               libgrpp_type2_integrals_gradient
      20              :    USE mathconstants,                   ONLY: pi
      21              :    USE orbital_pointers,                ONLY: nco,&
      22              :                                               ncoset
      23              : #include "./base/base_uses.f90"
      24              : 
      25              :    IMPLICIT NONE
      26              :    PRIVATE
      27              : 
      28              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'libgrpp_integrals'
      29              : 
      30              :    PUBLIC :: libgrpp_semilocal_integrals, libgrpp_local_integrals, &
      31              :              libgrpp_local_forces_ref, libgrpp_semilocal_forces_ref
      32              : 
      33              : CONTAINS
      34              : 
      35              : ! **************************************************************************************************
      36              : !> \brief Local ECP integrals using libgrpp
      37              : !> \param la_max_set ...
      38              : !> \param la_min_set ...
      39              : !> \param npgfa ...
      40              : !> \param rpgfa ...
      41              : !> \param zeta ...
      42              : !> \param lb_max_set ...
      43              : !> \param lb_min_set ...
      44              : !> \param npgfb ...
      45              : !> \param rpgfb ...
      46              : !> \param zetb ...
      47              : !> \param npot_ecp ...
      48              : !> \param alpha_ecp ...
      49              : !> \param coeffs_ecp ...
      50              : !> \param nrpot_ecp ...
      51              : !> \param rpgfc ...
      52              : !> \param rab ...
      53              : !> \param dab ...
      54              : !> \param rac ...
      55              : !> \param dac ...
      56              : !> \param dbc ...
      57              : !> \param vab ...
      58              : !> \param pab ...
      59              : !> \param force_a ...
      60              : !> \param force_b ...
      61              : ! **************************************************************************************************
      62            0 :    SUBROUTINE libgrpp_local_integrals(la_max_set, la_min_set, npgfa, rpgfa, zeta, &
      63            0 :                                       lb_max_set, lb_min_set, npgfb, rpgfb, zetb, &
      64            0 :                                       npot_ecp, alpha_ecp, coeffs_ecp, nrpot_ecp, &
      65            0 :                                       rpgfc, rab, dab, rac, dac, dbc, vab, pab, force_a, force_b)
      66              : 
      67              :       INTEGER, INTENT(IN)                                :: la_max_set, la_min_set, npgfa
      68              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa, zeta
      69              :       INTEGER, INTENT(IN)                                :: lb_max_set, lb_min_set, npgfb
      70              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb, zetb
      71              :       INTEGER, INTENT(IN)                                :: npot_ecp
      72              :       REAL(KIND=dp), DIMENSION(1:npot_ecp), INTENT(IN)   :: alpha_ecp, coeffs_ecp
      73              :       INTEGER, DIMENSION(1:npot_ecp), INTENT(IN)         :: nrpot_ecp
      74              :       REAL(KIND=dp), INTENT(IN)                          :: rpgfc
      75              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab
      76              :       REAL(KIND=dp), INTENT(IN)                          :: dab
      77              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rac
      78              :       REAL(KIND=dp), INTENT(IN)                          :: dac, dbc
      79              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: vab
      80              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
      81              :          OPTIONAL                                        :: pab
      82              :       REAL(KIND=dp), DIMENSION(3), INTENT(INOUT), &
      83              :          OPTIONAL                                        :: force_a, force_b
      84              : 
      85              :       INTEGER                                            :: a_offset, a_start, b_offset, b_start, i, &
      86              :                                                             ipgf, j, jpgf, li, lj, ncoa, ncob
      87              :       LOGICAL                                            :: calc_forces
      88              :       REAL(dp)                                           :: expi, expj, fac_a, fac_b, mindist, &
      89              :                                                             normi, normj, prefi, prefj, zeti, zetj
      90            0 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: tmp, tmpx, tmpy, tmpz
      91              :       REAL(dp), DIMENSION(3)                             :: ra, rb, rc
      92              : 
      93            0 :       CALL libgrpp_init()
      94              : 
      95            0 :       calc_forces = .FALSE.
      96            0 :       IF (PRESENT(pab) .AND. PRESENT(force_a) .AND. PRESENT(force_b)) calc_forces = .TRUE.
      97              : 
      98              :       IF (calc_forces) THEN
      99              : 
     100              :          !Note: warning against numerical stability of libgrpp gradients. The day the library becomes
     101              :          !      stable, this routine can be used immediatly as is, and the warning removed.
     102              :          CALL cp_warn(__LOCATION__, &
     103              :                       "ECP gradients calculated with the libgrpp library are, to this date, not numerically stable. "// &
     104            0 :                       "Please use the reference routine 'libgrpp_local_forces_ref' instead.")
     105              : 
     106              :          !there is a weird feature of libgrpp gradients, which is such that the gradient is calculated
     107              :          !for a point in space, and not with respect to an atomic center. For example, if atoms A and
     108              :          !B are the same (and C is different), then d<A | U_C | B>/dPx = d<A | U_C | B>/dAx + d<A | U_C | B>/dBx
     109              :          !Because we want the forces on centers A and B seprately, we need a case study on atomic positions
     110              :          !We always calculate the gradient wrt to atomic position of A and B, and we scale accordingly
     111              : 
     112            0 :          mindist = 1.0E-6_dp
     113              :          !If ra != rb != rc
     114            0 :          IF (dab >= mindist .AND. dbc >= mindist .AND. dac >= mindist) THEN
     115              :             fac_a = 1.0_dp
     116              :             fac_b = 1.0_dp
     117              : 
     118              :             !If ra = rb, but ra != rc
     119            0 :          ELSE IF (dab < mindist .AND. dac >= mindist) THEN
     120              :             fac_a = 0.5_dp
     121              :             fac_b = 0.5_dp
     122              : 
     123              :             !IF ra != rb but ra = rc
     124            0 :          ELSE IF (dab >= mindist .AND. dac < mindist) THEN
     125              :             fac_a = 0.5_dp
     126              :             fac_b = 1.0_dp
     127              : 
     128              :             !IF ra != rb but rb = rc
     129            0 :          ELSE IF (dab >= mindist .AND. dbc < mindist) THEN
     130              :             fac_a = 1.0_dp
     131              :             fac_b = 0.5_dp
     132              : 
     133              :             !If all atoms the same --> no force
     134              :          ELSE
     135            0 :             calc_forces = .FALSE.
     136              :          END IF
     137              :       END IF
     138              : 
     139              :       !libgrpp requires absolute positions, not relative ones
     140            0 :       ra(:) = 0.0_dp
     141            0 :       rb(:) = rab(:)
     142            0 :       rc(:) = rac(:)
     143              : 
     144            0 :       ALLOCATE (tmp(nco(la_max_set)*nco(lb_max_set)))
     145            0 :       IF (calc_forces) THEN
     146            0 :          ALLOCATE (tmpx(nco(la_max_set)*nco(lb_max_set)))
     147            0 :          ALLOCATE (tmpy(nco(la_max_set)*nco(lb_max_set)))
     148            0 :          ALLOCATE (tmpz(nco(la_max_set)*nco(lb_max_set)))
     149              :       END IF
     150              : 
     151            0 :       DO ipgf = 1, npgfa
     152            0 :          IF (rpgfa(ipgf) + rpgfc < dac) CYCLE
     153            0 :          zeti = zeta(ipgf)
     154            0 :          a_start = (ipgf - 1)*ncoset(la_max_set)
     155              : 
     156            0 :          DO jpgf = 1, npgfb
     157            0 :             IF (rpgfb(jpgf) + rpgfc < dbc) CYCLE
     158            0 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) CYCLE
     159            0 :             zetj = zetb(jpgf)
     160            0 :             b_start = (jpgf - 1)*ncoset(lb_max_set)
     161              : 
     162            0 :             DO li = la_min_set, la_max_set
     163            0 :                a_offset = a_start + ncoset(li - 1)
     164            0 :                ncoa = nco(li)
     165            0 :                prefi = 2.0_dp**li*(2.0_dp/pi)**0.75_dp
     166            0 :                expi = 0.25_dp*REAL(2*li + 3, dp)
     167            0 :                normi = 1.0_dp/(prefi*zeti**expi)
     168              : 
     169            0 :                DO lj = lb_min_set, lb_max_set
     170            0 :                   b_offset = b_start + ncoset(lj - 1)
     171            0 :                   ncob = nco(lj)
     172            0 :                   prefj = 2.0_dp**lj*(2.0_dp/pi)**0.75_dp
     173            0 :                   expj = 0.25_dp*REAL(2*lj + 3, dp)
     174            0 :                   normj = 1.0_dp/(prefj*zetj**expj)
     175              : 
     176            0 :                   tmp(1:ncoa*ncob) = 0.0_dp
     177              :                   !libgrpp implicitely normalizes cartesian Gaussian. In CP2K, we do not, hence
     178              :                   !the 1/norm coefficients for PGFi and PGFj
     179              :                   CALL libgrpp_type1_integrals(ra, li, 1, [normi], [zeti], &
     180              :                                                rb, lj, 1, [normj], [zetj], &
     181              :                                                rc, [npot_ecp], nrpot_ecp, &
     182            0 :                                                coeffs_ecp, alpha_ecp, tmp)
     183              : 
     184              :                   !note: tmp array is in C row-major ordering
     185            0 :                   DO j = 1, ncob
     186            0 :                      DO i = 1, ncoa
     187            0 :                         vab(a_offset + i, b_offset + j) = vab(a_offset + i, b_offset + j) + tmp((i - 1)*ncob + j)
     188              :                      END DO
     189              :                   END DO
     190              : 
     191            0 :                   IF (calc_forces) THEN
     192            0 :                      tmpx(1:ncoa*ncob) = 0.0_dp
     193            0 :                      tmpy(1:ncoa*ncob) = 0.0_dp
     194            0 :                      tmpz(1:ncoa*ncob) = 0.0_dp
     195              : 
     196              :                      !force wrt to atomic position A
     197              :                      CALL libgrpp_type1_integrals_gradient(ra, li, 1, [normi], [zeti], &
     198              :                                                            rb, lj, 1, [normj], [zetj], &
     199              :                                                            rc, [npot_ecp], nrpot_ecp, &
     200              :                                                            coeffs_ecp, alpha_ecp, ra, &
     201            0 :                                                            tmpx, tmpy, tmpz)
     202              : 
     203              :                      !note: tmp array is in C row-major ordering
     204              :                      !note: zero-gradients sometime comes out as NaN, hence tampval==tmpval check
     205            0 :                      DO j = 1, ncob
     206            0 :                         DO i = 1, ncoa
     207            0 :                            force_a(1) = force_a(1) + fac_a*pab(a_offset + i, b_offset + j)*tmpx((i - 1)*ncob + j)
     208            0 :                            force_a(2) = force_a(2) + fac_a*pab(a_offset + i, b_offset + j)*tmpy((i - 1)*ncob + j)
     209            0 :                            force_a(3) = force_a(3) + fac_a*pab(a_offset + i, b_offset + j)*tmpz((i - 1)*ncob + j)
     210              :                         END DO
     211              :                      END DO
     212              : 
     213            0 :                      tmpx(1:ncoa*ncob) = 0.0_dp
     214            0 :                      tmpy(1:ncoa*ncob) = 0.0_dp
     215            0 :                      tmpz(1:ncoa*ncob) = 0.0_dp
     216              : 
     217              :                      !force wrt to atomic position B
     218              :                      CALL libgrpp_type1_integrals_gradient(ra, li, 1, [normi], [zeti], &
     219              :                                                            rb, lj, 1, [normj], [zetj], &
     220              :                                                            rc, [npot_ecp], nrpot_ecp, &
     221              :                                                            coeffs_ecp, alpha_ecp, rb, &
     222            0 :                                                            tmpx, tmpy, tmpz)
     223              : 
     224              :                      !note: tmp array is in C row-major ordering
     225              :                      !note: zero-gradients sometime comes out as NaN, hence tampval==tmpval check
     226            0 :                      DO j = 1, ncob
     227            0 :                         DO i = 1, ncoa
     228            0 :                            force_b(1) = force_b(1) + fac_b*pab(a_offset + i, b_offset + j)*tmpx((i - 1)*ncob + j)
     229            0 :                            force_b(2) = force_b(2) + fac_b*pab(a_offset + i, b_offset + j)*tmpy((i - 1)*ncob + j)
     230            0 :                            force_b(3) = force_b(3) + fac_b*pab(a_offset + i, b_offset + j)*tmpz((i - 1)*ncob + j)
     231              :                         END DO
     232              :                      END DO
     233              :                   END IF
     234              : 
     235              :                END DO !lj
     236              :             END DO !li
     237              : 
     238              :          END DO !jpgf
     239              :       END DO !ipgf
     240            0 :    END SUBROUTINE libgrpp_local_integrals
     241              : 
     242              : ! **************************************************************************************************
     243              : !> \brief Semi-local ECP integrals using libgrpp.
     244              : !> \param la_max_set ...
     245              : !> \param la_min_set ...
     246              : !> \param npgfa ...
     247              : !> \param rpgfa ...
     248              : !> \param zeta ...
     249              : !> \param lb_max_set ...
     250              : !> \param lb_min_set ...
     251              : !> \param npgfb ...
     252              : !> \param rpgfb ...
     253              : !> \param zetb ...
     254              : !> \param lmax_ecp ...
     255              : !> \param npot_ecp ...
     256              : !> \param alpha_ecp ...
     257              : !> \param coeffs_ecp ...
     258              : !> \param nrpot_ecp ...
     259              : !> \param rpgfc ...
     260              : !> \param rab ...
     261              : !> \param dab ...
     262              : !> \param rac ...
     263              : !> \param dac ...
     264              : !> \param dbc ...
     265              : !> \param vab ...
     266              : !> \param pab ...
     267              : !> \param force_a ...
     268              : !> \param force_b ...
     269              : ! **************************************************************************************************
     270        25266 :    SUBROUTINE libgrpp_semilocal_integrals(la_max_set, la_min_set, npgfa, rpgfa, zeta, &
     271        25266 :                                           lb_max_set, lb_min_set, npgfb, rpgfb, zetb, &
     272              :                                           lmax_ecp, npot_ecp, alpha_ecp, coeffs_ecp, nrpot_ecp, &
     273        50532 :                                           rpgfc, rab, dab, rac, dac, dbc, vab, pab, force_a, force_b)
     274              : 
     275              :       INTEGER, INTENT(IN)                                :: la_max_set, la_min_set, npgfa
     276              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa, zeta
     277              :       INTEGER, INTENT(IN)                                :: lb_max_set, lb_min_set, npgfb
     278              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb, zetb
     279              :       INTEGER, INTENT(IN)                                :: lmax_ecp
     280              :       INTEGER, DIMENSION(0:10), INTENT(IN)               :: npot_ecp
     281              :       REAL(KIND=dp), DIMENSION(1:15, 0:10), INTENT(IN)   :: alpha_ecp, coeffs_ecp
     282              :       INTEGER, DIMENSION(1:15, 0:10), INTENT(IN)         :: nrpot_ecp
     283              :       REAL(KIND=dp), INTENT(IN)                          :: rpgfc
     284              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab
     285              :       REAL(KIND=dp), INTENT(IN)                          :: dab
     286              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rac
     287              :       REAL(KIND=dp), INTENT(IN)                          :: dac, dbc
     288              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: vab
     289              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
     290              :          OPTIONAL                                        :: pab
     291              :       REAL(KIND=dp), DIMENSION(3), INTENT(INOUT), &
     292              :          OPTIONAL                                        :: force_a, force_b
     293              : 
     294              :       INTEGER                                            :: a_offset, a_start, b_offset, b_start, i, &
     295              :                                                             ipgf, j, jpgf, li, lj, lk, ncoa, ncob
     296              :       LOGICAL                                            :: calc_forces
     297              :       REAL(dp)                                           :: expi, expj, fac_a, fac_b, mindist, &
     298              :                                                             normi, normj, prefi, prefj, zeti, zetj
     299        25266 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: tmp, tmpx, tmpy, tmpz
     300              :       REAL(dp), DIMENSION(3)                             :: ra, rb, rc
     301              : 
     302        25266 :       CALL libgrpp_init()
     303              : 
     304        25266 :       calc_forces = .FALSE.
     305        25266 :       IF (PRESENT(pab) .AND. PRESENT(force_a) .AND. PRESENT(force_b)) calc_forces = .TRUE.
     306              : 
     307              :       IF (calc_forces) THEN
     308              : 
     309              :          !Note: warning against numerical stability of libgrpp gradients. The day the library becomes
     310              :          !      stable, this routine can be used immediatly as is, and the warning removed.
     311              :          CALL cp_warn(__LOCATION__, &
     312              :                       "ECP gradients calculated with the libgrpp library are, to this date, not numerically stable. "// &
     313            0 :                       "Please use the reference routine 'libgrpp_semilocal_forces_ref' instead.")
     314              : 
     315              :          !there is a weird feature of libgrpp gradients, which is such that the gradient is calculated
     316              :          !for a point in space, and not with respect to an atomic center. For example, if atoms A and
     317              :          !B are the same (and C is different), then d<A | U_C | B>/dPx = d<A | U_C | B>/dAx + d<A | U_C | B>/dBx
     318              :          !Because we want the forces on centers A and B seprately, we need a case study on atomic positions
     319              :          !We always calculate the gradient wrt to atomic position of A and B, and we scale accordingly
     320              : 
     321            0 :          mindist = 1.0E-6_dp
     322              :          !If ra != rb != rc
     323            0 :          IF (dab >= mindist .AND. dbc >= mindist .AND. dac >= mindist) THEN
     324              :             fac_a = 1.0_dp
     325              :             fac_b = 1.0_dp
     326              : 
     327              :             !If ra = rb, but ra != rc
     328            0 :          ELSE IF (dab < mindist .AND. dac >= mindist) THEN
     329              :             fac_a = 0.5_dp
     330              :             fac_b = 0.5_dp
     331              : 
     332              :             !IF ra != rb but ra = rc
     333            0 :          ELSE IF (dab >= mindist .AND. dac < mindist) THEN
     334              :             fac_a = 0.5_dp
     335              :             fac_b = 1.0_dp
     336              : 
     337              :             !IF ra != rb but rb = rc
     338            0 :          ELSE IF (dab >= mindist .AND. dbc < mindist) THEN
     339              :             fac_a = 1.0_dp
     340              :             fac_b = 0.5_dp
     341              : 
     342              :             !If all atoms the same --> no force
     343              :          ELSE
     344            0 :             calc_forces = .FALSE.
     345              :          END IF
     346              :       END IF
     347              : 
     348              :       !libgrpp requires absolute positions, not relative ones
     349        25266 :       ra(:) = 0.0_dp
     350        25266 :       rb(:) = rab(:)
     351        25266 :       rc(:) = rac(:)
     352              : 
     353        75798 :       ALLOCATE (tmp(nco(la_max_set)*nco(lb_max_set)))
     354        25266 :       IF (calc_forces) THEN
     355            0 :          ALLOCATE (tmpx(nco(la_max_set)*nco(lb_max_set)))
     356            0 :          ALLOCATE (tmpy(nco(la_max_set)*nco(lb_max_set)))
     357            0 :          ALLOCATE (tmpz(nco(la_max_set)*nco(lb_max_set)))
     358              :       END IF
     359              : 
     360        91907 :       DO ipgf = 1, npgfa
     361        66641 :          IF (rpgfa(ipgf) + rpgfc < dac) CYCLE
     362        35523 :          zeti = zeta(ipgf)
     363        35523 :          a_start = (ipgf - 1)*ncoset(la_max_set)
     364              : 
     365       158643 :          DO jpgf = 1, npgfb
     366        97854 :             IF (rpgfb(jpgf) + rpgfc < dbc) CYCLE
     367        51568 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) CYCLE
     368        44746 :             zetj = zetb(jpgf)
     369        44746 :             b_start = (jpgf - 1)*ncoset(lb_max_set)
     370              : 
     371       160773 :             DO li = la_min_set, la_max_set
     372        49386 :                a_offset = a_start + ncoset(li - 1)
     373        49386 :                ncoa = nco(li)
     374        49386 :                prefi = 2.0_dp**li*(2.0_dp/pi)**0.75_dp
     375        49386 :                expi = 0.25_dp*REAL(2*li + 3, dp)
     376        49386 :                normi = 1.0_dp/(prefi*zeti**expi)
     377              : 
     378       208306 :                DO lj = lb_min_set, lb_max_set
     379        61066 :                   b_offset = b_start + ncoset(lj - 1)
     380        61066 :                   ncob = nco(lj)
     381        61066 :                   prefj = 2.0_dp**lj*(2.0_dp/pi)**0.75_dp
     382        61066 :                   expj = 0.25_dp*REAL(2*lj + 3, dp)
     383        61066 :                   normj = 1.0_dp/(prefj*zetj**expj)
     384              : 
     385              :                   !Loop over ECP angular momentum
     386       262700 :                   DO lk = 0, lmax_ecp
     387       992356 :                      tmp(1:ncoa*ncob) = 0.0_dp
     388              :                      !libgrpp implicitely normalizes cartesian Gaussian. In CP2K, we do not, hence
     389              :                      !the 1/norm coefficients for PGFi and PGFj
     390              :                      CALL libgrpp_type2_integrals(ra, li, 1, [normi], [zeti], &
     391              :                                                   rb, lj, 1, [normj], [zetj], &
     392              :                                                   rc, lk, [npot_ecp(lk)], nrpot_ecp(:, lk), &
     393       913488 :                                                   coeffs_ecp(:, lk), alpha_ecp(:, lk), tmp)
     394              : 
     395              :                      !note: tmp array is in C row-major ordering
     396       508019 :                      DO j = 1, ncob
     397      1348127 :                         DO i = 1, ncoa
     398      1195879 :                            vab(a_offset + i, b_offset + j) = vab(a_offset + i, b_offset + j) + tmp((i - 1)*ncob + j)
     399              :                         END DO
     400              :                      END DO
     401              : 
     402       213314 :                      IF (calc_forces) THEN
     403              : 
     404            0 :                         tmpx(1:ncoa*ncob) = 0.0_dp
     405            0 :                         tmpy(1:ncoa*ncob) = 0.0_dp
     406            0 :                         tmpz(1:ncoa*ncob) = 0.0_dp
     407              : 
     408              :                         !force wrt to atomic position A
     409              :                         CALL libgrpp_type2_integrals_gradient(ra, li, 1, [normi], [zeti], &
     410              :                                                               rb, lj, 1, [normj], [zetj], &
     411              :                                                               rc, lk, [npot_ecp(lk)], nrpot_ecp(:, lk), &
     412              :                                                               coeffs_ecp(:, lk), alpha_ecp(:, lk), ra, &
     413            0 :                                                               tmpx, tmpy, tmpz)
     414              : 
     415              :                         !note: tmp array is in C row-major ordering
     416              :                         !note: zero-gradients sometime comes out as NaN, hence tampval==tmpval check
     417            0 :                         DO j = 1, ncob
     418            0 :                            DO i = 1, ncoa
     419            0 :                               force_a(1) = force_a(1) + fac_a*pab(a_offset + i, b_offset + j)*tmpx((i - 1)*ncob + j)
     420            0 :                               force_a(2) = force_a(2) + fac_a*pab(a_offset + i, b_offset + j)*tmpy((i - 1)*ncob + j)
     421            0 :                               force_a(3) = force_a(3) + fac_a*pab(a_offset + i, b_offset + j)*tmpz((i - 1)*ncob + j)
     422              :                            END DO
     423              :                         END DO
     424              : 
     425            0 :                         tmpx(1:ncoa*ncob) = 0.0_dp
     426            0 :                         tmpy(1:ncoa*ncob) = 0.0_dp
     427            0 :                         tmpz(1:ncoa*ncob) = 0.0_dp
     428              : 
     429              :                         !force wrt to atomic position B
     430              :                         CALL libgrpp_type2_integrals_gradient(ra, li, 1, [normi], [zeti], &
     431              :                                                               rb, lj, 1, [normj], [zetj], &
     432              :                                                               rc, lk, [npot_ecp(lk)], nrpot_ecp(:, lk), &
     433              :                                                               coeffs_ecp(:, lk), alpha_ecp(:, lk), rb, &
     434            0 :                                                               tmpx, tmpy, tmpz)
     435              :                         !note: tmp array is in C row-major ordering
     436              :                         !note: zero-gradients sometime comes out as NaN, hence tampval==tmpval check
     437            0 :                         DO j = 1, ncob
     438            0 :                            DO i = 1, ncoa
     439            0 :                               force_b(1) = force_b(1) + fac_b*pab(a_offset + i, b_offset + j)*tmpx((i - 1)*ncob + j)
     440            0 :                               force_b(2) = force_b(2) + fac_b*pab(a_offset + i, b_offset + j)*tmpy((i - 1)*ncob + j)
     441            0 :                               force_b(3) = force_b(3) + fac_b*pab(a_offset + i, b_offset + j)*tmpz((i - 1)*ncob + j)
     442              :                            END DO
     443              :                         END DO
     444              : 
     445              :                      END IF !calc_forces
     446              : 
     447              :                   END DO !lk
     448              : 
     449              :                END DO !lj
     450              :             END DO !li
     451              : 
     452              :          END DO !jpgf
     453              :       END DO !ipgf
     454        25266 :    END SUBROUTINE libgrpp_semilocal_integrals
     455              : 
     456              : ! **************************************************************************************************
     457              : !> \brief Reference local ECP force routine using l+-1 integrals. No call is made to the numerically
     458              : !>        unstable gradient routine of libgrpp. Calculates both the integrals and the forces.
     459              : !> \param la_max_set ...
     460              : !> \param la_min_set ...
     461              : !> \param npgfa ...
     462              : !> \param rpgfa ...
     463              : !> \param zeta ...
     464              : !> \param lb_max_set ...
     465              : !> \param lb_min_set ...
     466              : !> \param npgfb ...
     467              : !> \param rpgfb ...
     468              : !> \param zetb ...
     469              : !> \param npot_ecp ...
     470              : !> \param alpha_ecp ...
     471              : !> \param coeffs_ecp ...
     472              : !> \param nrpot_ecp ...
     473              : !> \param rpgfc ...
     474              : !> \param rab ...
     475              : !> \param dab ...
     476              : !> \param rac ...
     477              : !> \param dac ...
     478              : !> \param dbc ...
     479              : !> \param vab ...
     480              : !> \param pab ...
     481              : !> \param force_a ...
     482              : !> \param force_b ...
     483              : !> \note: this is a reference routine, which has no reason to be used once the libgrpp gradients
     484              : !>        become numerically stable
     485              : ! **************************************************************************************************
     486            0 :    SUBROUTINE libgrpp_local_forces_ref(la_max_set, la_min_set, npgfa, rpgfa, zeta, &
     487            0 :                                        lb_max_set, lb_min_set, npgfb, rpgfb, zetb, &
     488            0 :                                        npot_ecp, alpha_ecp, coeffs_ecp, nrpot_ecp, &
     489            0 :                                        rpgfc, rab, dab, rac, dac, dbc, vab, pab, force_a, force_b)
     490              : 
     491              :       INTEGER, INTENT(IN)                                :: la_max_set, la_min_set, npgfa
     492              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa, zeta
     493              :       INTEGER, INTENT(IN)                                :: lb_max_set, lb_min_set, npgfb
     494              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb, zetb
     495              :       INTEGER, INTENT(IN)                                :: npot_ecp
     496              :       REAL(KIND=dp), DIMENSION(1:npot_ecp), INTENT(IN)   :: alpha_ecp, coeffs_ecp
     497              :       INTEGER, DIMENSION(1:npot_ecp), INTENT(IN)         :: nrpot_ecp
     498              :       REAL(KIND=dp), INTENT(IN)                          :: rpgfc
     499              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab
     500              :       REAL(KIND=dp), INTENT(IN)                          :: dab
     501              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rac
     502              :       REAL(KIND=dp), INTENT(IN)                          :: dac, dbc
     503              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: vab
     504              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: pab
     505              :       REAL(KIND=dp), DIMENSION(3), INTENT(INOUT)         :: force_a, force_b
     506              : 
     507              :       INTEGER                                            :: a_offset, a_offset_f, a_start, &
     508              :                                                             a_start_f, b_offset, b_offset_f, &
     509              :                                                             b_start, b_start_f, i, ipgf, j, jpgf, &
     510              :                                                             li, lj, ncoa, ncob
     511              :       REAL(dp)                                           :: expi, expj, normi, normj, prefi, prefj, &
     512              :                                                             zeti, zetj
     513            0 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: tmp
     514              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: vab_f
     515              :       REAL(dp), DIMENSION(3)                             :: ra, rb, rc
     516              : 
     517            0 :       CALL libgrpp_init()
     518              : 
     519              :       !Contains the integrals necessary for the forces, with angular momenta from lmin-1 to lmax+1
     520            0 :       ALLOCATE (vab_f(npgfa*ncoset(la_max_set + 1), npgfb*ncoset(lb_max_set + 1)))
     521            0 :       vab_f(:, :) = 0.0_dp
     522              : 
     523              :       !libgrpp requires absolute positions, not relative ones
     524            0 :       ra(:) = 0.0_dp
     525            0 :       rb(:) = rab(:)
     526            0 :       rc(:) = rac(:)
     527              : 
     528            0 :       ALLOCATE (tmp(nco(la_max_set + 1)*nco(lb_max_set + 1)))
     529              : 
     530            0 :       DO ipgf = 1, npgfa
     531            0 :          IF (rpgfa(ipgf) + rpgfc < dac) CYCLE
     532            0 :          zeti = zeta(ipgf)
     533            0 :          a_start = (ipgf - 1)*ncoset(la_max_set)
     534            0 :          a_start_f = (ipgf - 1)*ncoset(la_max_set + 1)
     535              : 
     536            0 :          DO jpgf = 1, npgfb
     537            0 :             IF (rpgfb(jpgf) + rpgfc < dbc) CYCLE
     538            0 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) CYCLE
     539            0 :             zetj = zetb(jpgf)
     540            0 :             b_start = (jpgf - 1)*ncoset(lb_max_set)
     541            0 :             b_start_f = (jpgf - 1)*ncoset(lb_max_set + 1)
     542              : 
     543            0 :             DO li = MAX(0, la_min_set - 1), la_max_set + 1
     544            0 :                a_offset = a_start + ncoset(li - 1)
     545            0 :                a_offset_f = a_start_f + ncoset(li - 1)
     546            0 :                ncoa = nco(li)
     547            0 :                prefi = 2.0_dp**li*(2.0_dp/pi)**0.75_dp
     548            0 :                expi = 0.25_dp*REAL(2*li + 3, dp)
     549            0 :                normi = 1.0_dp/(prefi*zeti**expi)
     550              : 
     551            0 :                DO lj = MAX(0, lb_min_set - 1), lb_max_set + 1
     552            0 :                   b_offset = b_start + ncoset(lj - 1)
     553            0 :                   b_offset_f = b_start_f + ncoset(lj - 1)
     554            0 :                   ncob = nco(lj)
     555            0 :                   prefj = 2.0_dp**lj*(2.0_dp/pi)**0.75_dp
     556            0 :                   expj = 0.25_dp*REAL(2*lj + 3, dp)
     557            0 :                   normj = 1.0_dp/(prefj*zetj**expj)
     558              : 
     559            0 :                   tmp(1:ncoa*ncob) = 0.0_dp
     560              :                   !libgrpp implicitely normalizes cartesian Gaussian. In CP2K, we do not, hence
     561              :                   !the 1/norm coefficients for PGFi and PGFj
     562              :                   CALL libgrpp_type1_integrals(ra, li, 1, [normi], [zeti], &
     563              :                                                rb, lj, 1, [normj], [zetj], &
     564              :                                                rc, [npot_ecp], nrpot_ecp, &
     565            0 :                                                coeffs_ecp, alpha_ecp, tmp)
     566              : 
     567              :                   !the l+-1 integrals for gradient calculation
     568            0 :                   DO j = 1, ncob
     569            0 :                      DO i = 1, ncoa
     570              :                         vab_f(a_offset_f + i, b_offset_f + j) = &
     571            0 :                            vab_f(a_offset_f + i, b_offset_f + j) + tmp((i - 1)*ncob + j)
     572              :                      END DO
     573              :                   END DO
     574              : 
     575              :                   !the actual integrals
     576            0 :                   IF (li >= la_min_set .AND. li <= la_max_set .AND. lj >= lb_min_set .AND. lj <= lb_max_set) THEN
     577            0 :                      DO j = 1, ncob
     578            0 :                         DO i = 1, ncoa
     579            0 :                            vab(a_offset + i, b_offset + j) = vab(a_offset + i, b_offset + j) + tmp((i - 1)*ncob + j)
     580              :                         END DO
     581              :                      END DO
     582              :                   END IF
     583              : 
     584              :                END DO !lj
     585              :             END DO !li
     586              : 
     587              :          END DO !jpgf
     588              :       END DO !ipgf
     589              : 
     590              :       CALL contract_basis_center_forces(la_max_set, npgfa, zeta, lb_max_set, npgfb, zetb, &
     591            0 :                                         vab_f, pab, force_a, force_b)
     592            0 :    END SUBROUTINE libgrpp_local_forces_ref
     593              : 
     594              : ! **************************************************************************************************
     595              : !> \brief Reference semi-local ECP forces using l+-1 integrals. No call is made to the numerically
     596              : !>        unstable gradient routine of libgrpp. Calculates both the integrals and the forces.
     597              : !> \param la_max_set ...
     598              : !> \param la_min_set ...
     599              : !> \param npgfa ...
     600              : !> \param rpgfa ...
     601              : !> \param zeta ...
     602              : !> \param lb_max_set ...
     603              : !> \param lb_min_set ...
     604              : !> \param npgfb ...
     605              : !> \param rpgfb ...
     606              : !> \param zetb ...
     607              : !> \param lmax_ecp ...
     608              : !> \param npot_ecp ...
     609              : !> \param alpha_ecp ...
     610              : !> \param coeffs_ecp ...
     611              : !> \param nrpot_ecp ...
     612              : !> \param rpgfc ...
     613              : !> \param rab ...
     614              : !> \param dab ...
     615              : !> \param rac ...
     616              : !> \param dac ...
     617              : !> \param dbc ...
     618              : !> \param vab ...
     619              : !> \param pab ...
     620              : !> \param force_a ...
     621              : !> \param force_b ...
     622              : !> \note: this is a reference routine, which has no reason to be used once the libgrpp gradients
     623              : !>        become numerically stable
     624              : ! **************************************************************************************************
     625        12394 :    SUBROUTINE libgrpp_semilocal_forces_ref(la_max_set, la_min_set, npgfa, rpgfa, zeta, &
     626        12394 :                                            lb_max_set, lb_min_set, npgfb, rpgfb, zetb, &
     627              :                                            lmax_ecp, npot_ecp, alpha_ecp, coeffs_ecp, nrpot_ecp, &
     628        12394 :                                            rpgfc, rab, dab, rac, dac, dbc, vab, pab, force_a, force_b)
     629              : 
     630              :       INTEGER, INTENT(IN)                                :: la_max_set, la_min_set, npgfa
     631              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa, zeta
     632              :       INTEGER, INTENT(IN)                                :: lb_max_set, lb_min_set, npgfb
     633              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb, zetb
     634              :       INTEGER, INTENT(IN)                                :: lmax_ecp
     635              :       INTEGER, DIMENSION(0:10), INTENT(IN)               :: npot_ecp
     636              :       REAL(KIND=dp), DIMENSION(1:15, 0:10), INTENT(IN)   :: alpha_ecp, coeffs_ecp
     637              :       INTEGER, DIMENSION(1:15, 0:10), INTENT(IN)         :: nrpot_ecp
     638              :       REAL(KIND=dp), INTENT(IN)                          :: rpgfc
     639              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab
     640              :       REAL(KIND=dp), INTENT(IN)                          :: dab
     641              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rac
     642              :       REAL(KIND=dp), INTENT(IN)                          :: dac, dbc
     643              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: vab
     644              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: pab
     645              :       REAL(KIND=dp), DIMENSION(3), INTENT(INOUT)         :: force_a, force_b
     646              : 
     647              :       INTEGER                                            :: a_offset, a_offset_f, a_start, &
     648              :                                                             a_start_f, b_offset, b_offset_f, &
     649              :                                                             b_start, b_start_f, i, ipgf, j, jpgf, &
     650              :                                                             li, lj, lk, ncoa, ncob
     651              :       REAL(dp)                                           :: expi, expj, normi, normj, prefi, prefj, &
     652              :                                                             zeti, zetj
     653        12394 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: tmp
     654              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: vab_f
     655              :       REAL(dp), DIMENSION(3)                             :: ra, rb, rc
     656              : 
     657        12394 :       CALL libgrpp_init()
     658              : 
     659              :       !Contains the integrals necessary for the forces, with angular momenta from lmin-1 to lmax+1
     660        49576 :       ALLOCATE (vab_f(npgfa*ncoset(la_max_set + 1), npgfb*ncoset(lb_max_set + 1)))
     661        12394 :       vab_f(:, :) = 0.0_dp
     662              : 
     663              :       !libgrpp requires absolute positions, not relative ones
     664        12394 :       ra(:) = 0.0_dp
     665        12394 :       rb(:) = rab(:)
     666        12394 :       rc(:) = rac(:)
     667              : 
     668        37182 :       ALLOCATE (tmp(nco(la_max_set + 1)*nco(lb_max_set + 1)))
     669              : 
     670        49748 :       DO ipgf = 1, npgfa
     671        37354 :          IF (rpgfa(ipgf) + rpgfc < dac) CYCLE
     672        18255 :          zeti = zeta(ipgf)
     673        18255 :          a_start = (ipgf - 1)*ncoset(la_max_set)
     674        18255 :          a_start_f = (ipgf - 1)*ncoset(la_max_set + 1)
     675              : 
     676        86379 :          DO jpgf = 1, npgfb
     677        55730 :             IF (rpgfb(jpgf) + rpgfc < dbc) CYCLE
     678        27194 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) CYCLE
     679        22925 :             zetj = zetb(jpgf)
     680        22925 :             b_start = (jpgf - 1)*ncoset(lb_max_set)
     681        22925 :             b_start_f = (jpgf - 1)*ncoset(lb_max_set + 1)
     682              : 
     683       118496 :             DO li = MAX(0, la_min_set - 1), la_max_set + 1
     684        58217 :                a_offset = a_start + ncoset(li - 1)
     685        58217 :                a_offset_f = a_start_f + ncoset(li - 1)
     686        58217 :                ncoa = nco(li)
     687        58217 :                prefi = 2.0_dp**li*(2.0_dp/pi)**0.75_dp
     688        58217 :                expi = 0.25_dp*REAL(2*li + 3, dp)
     689        58217 :                normi = 1.0_dp/(prefi*zeti**expi)
     690              : 
     691       269451 :                DO lj = MAX(0, lb_min_set - 1), lb_max_set + 1
     692       155504 :                   b_offset = b_start + ncoset(lj - 1)
     693       155504 :                   b_offset_f = b_start_f + ncoset(lj - 1)
     694       155504 :                   ncob = nco(lj)
     695       155504 :                   prefj = 2.0_dp**lj*(2.0_dp/pi)**0.75_dp
     696       155504 :                   expj = 0.25_dp*REAL(2*lj + 3, dp)
     697       155504 :                   normj = 1.0_dp/(prefj*zetj**expj)
     698              : 
     699              :                   !Loop over ECP angular momentum
     700       604682 :                   DO lk = 0, lmax_ecp
     701      4296425 :                      tmp(1:ncoa*ncob) = 0.0_dp
     702              :                      !libgrpp implicitely normalizes cartesian Gaussian. In CP2K, we do not, hence
     703              :                      !the 1/norm coefficients for PGFi and PGFj
     704              :                      CALL libgrpp_type2_integrals(ra, li, 1, [normi], [zeti], &
     705              :                                                   rb, lj, 1, [normj], [zetj], &
     706              :                                                   rc, lk, [npot_ecp(lk)], nrpot_ecp(:, lk), &
     707      2345766 :                                                   coeffs_ecp(:, lk), alpha_ecp(:, lk), tmp)
     708              : 
     709              :                      !the l+-1 integrals for gradient calculation
     710      1641983 :                      DO j = 1, ncob
     711      5547447 :                         DO i = 1, ncoa
     712              :                            vab_f(a_offset_f + i, b_offset_f + j) = &
     713      5156486 :                               vab_f(a_offset_f + i, b_offset_f + j) + tmp((i - 1)*ncob + j)
     714              :                         END DO
     715              :                      END DO
     716              : 
     717              :                      !the actual integrals
     718       546465 :                      IF (li >= la_min_set .AND. li <= la_max_set .AND. lj >= lb_min_set .AND. lj <= lb_max_set) THEN
     719       269345 :                         DO j = 1, ncob
     720       665286 :                            DO i = 1, ncoa
     721       581189 :                               vab(a_offset + i, b_offset + j) = vab(a_offset + i, b_offset + j) + tmp((i - 1)*ncob + j)
     722              :                            END DO
     723              :                         END DO
     724              :                      END IF
     725              : 
     726              :                   END DO !lk
     727              : 
     728              :                END DO !lj
     729              :             END DO !li
     730              : 
     731              :          END DO !jpgf
     732              :       END DO !ipgf
     733              : 
     734              :       CALL contract_basis_center_forces(la_max_set, npgfa, zeta, lb_max_set, npgfb, zetb, &
     735        12394 :                                         vab_f, pab, force_a, force_b)
     736        12394 :    END SUBROUTINE libgrpp_semilocal_forces_ref
     737              : 
     738              : ! **************************************************************************************************
     739              : !> \brief Contract the bra and ket basis-center derivatives of precomputed ECP integrals.
     740              : !> \param la_max highest bra shell
     741              : !> \param npgfa number of bra primitives
     742              : !> \param zeta bra Gaussian exponents
     743              : !> \param lb_max highest ket shell
     744              : !> \param npgfb number of ket primitives
     745              : !> \param zetb ket Gaussian exponents
     746              : !> \param vab primitive integrals including raised shells and zero screened blocks
     747              : !> \param pab primitive density block
     748              : !> \param force_a accumulated bra-center force
     749              : !> \param force_b accumulated ket-center force
     750              : ! **************************************************************************************************
     751        61970 :    SUBROUTINE contract_basis_center_forces(la_max, npgfa, zeta, lb_max, npgfb, zetb, &
     752        12394 :                                            vab, pab, force_a, force_b)
     753              :       INTEGER, INTENT(IN)                                :: la_max, npgfa
     754              :       REAL(KIND=dp), INTENT(IN)                          :: zeta(:)
     755              :       INTEGER, INTENT(IN)                                :: lb_max, npgfb
     756              :       REAL(KIND=dp), INTENT(IN)                          :: zetb(:), vab(:, :), pab(:, :)
     757              :       REAL(KIND=dp), INTENT(INOUT)                       :: force_a(3), force_b(3)
     758              : 
     759              :       INTEGER                                            :: i, j, na, nb
     760        12394 :       REAL(KIND=dp), ALLOCATABLE                         :: deriv_ab(:, :, :)
     761              : 
     762        12394 :       na = npgfa*ncoset(la_max)
     763        12394 :       nb = npgfb*ncoset(lb_max)
     764        61970 :       ALLOCATE (deriv_ab(na, nb, 3))
     765              :       CALL apply_cartesian_operator(la_max, 0, npgfa, lb_max, 0, npgfb, vab, deriv_ab, &
     766        12394 :                                     right=.FALSE., derivative=.TRUE., exponents=zeta)
     767       130309 :       DO j = 1, nb
     768      1235245 :          DO i = 1, na
     769      4537659 :             force_a = force_a + deriv_ab(i, j, :)*pab(i, j)
     770              :          END DO
     771              :       END DO
     772              :       CALL apply_cartesian_operator(la_max, 0, npgfa, lb_max, 0, npgfb, vab, deriv_ab, &
     773        12394 :                                     right=.TRUE., derivative=.TRUE., exponents=zetb)
     774       130309 :       DO j = 1, nb
     775      1235245 :          DO i = 1, na
     776      4537659 :             force_b = force_b + deriv_ab(i, j, :)*pab(i, j)
     777              :          END DO
     778              :       END DO
     779        12394 :    END SUBROUTINE contract_basis_center_forces
     780              : 
     781              : END MODULE libgrpp_integrals
        

Generated by: LCOV version 2.0-1