LCOV - code coverage report
Current view: top level - src/aobasis - ai_overlap3.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 97.6 % 82 80
Test Date: 2026-11-04 00:58:17 Functions: 100.0 % 1 1

            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              : !> \brief Three-center overlap integrals over Cartesian Gaussian functions.
       9              : !> \author Matthias Krack (26.06.2001)
      10              : !> \par Literature
      11              : !>      S. Obara and A. Saika, J. Chem. Phys. 84, 3963 (1986)
      12              : ! **************************************************************************************************
      13              : MODULE ai_overlap3
      14              : 
      15              :    USE ai_cartesian_operators,          ONLY: cartesian_ladder,&
      16              :                                               cartesian_ladder_map
      17              :    USE ai_os_rr,                        ONLY: os_rr_ovlp3
      18              :    USE kinds,                           ONLY: dp
      19              :    USE mathconstants,                   ONLY: pi
      20              :    USE orbital_pointers,                ONLY: indco,&
      21              :                                               ncoset
      22              : #include "../base/base_uses.f90"
      23              : 
      24              :    IMPLICIT NONE
      25              :    PRIVATE
      26              : 
      27              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ai_overlap3'
      28              : 
      29              :    PUBLIC :: overlap3
      30              : 
      31              : CONTAINS
      32              : 
      33              : ! **************************************************************************************************
      34              : !> \brief Calculation of three-center overlap integrals [a|b|c] over primitive
      35              : !>        Cartesian Gaussian functions using separable one-dimensional tables.
      36              : !> \param la_max_set ...
      37              : !> \param npgfa ...
      38              : !> \param zeta ...
      39              : !> \param rpgfa ...
      40              : !> \param la_min_set ...
      41              : !> \param lb_max_set ...
      42              : !> \param npgfb ...
      43              : !> \param zetb ...
      44              : !> \param rpgfb ...
      45              : !> \param lb_min_set ...
      46              : !> \param lc_max_set ...
      47              : !> \param npgfc ...
      48              : !> \param zetc ...
      49              : !> \param rpgfc ...
      50              : !> \param lc_min_set ...
      51              : !> \param rab displacement B - A
      52              : !> \param dab distance between A and B
      53              : !> \param rac displacement C - A
      54              : !> \param dac distance between A and C
      55              : !> \param rbc displacement C - B
      56              : !> \param dbc distance between B and C
      57              : !> \param sabc integrals [a|b|c]
      58              : !> \param sdabc derivative [da/dAi|b|c]
      59              : !> \param sabdc derivative [a|b|dc/dCi]
      60              : !> \param int_abc_ext largest absolute integral in the requested shell ranges
      61              : !> \par History
      62              : !>      05.2014 created (Dorothea Golze)
      63              : !> \author Dorothea Golze
      64              : ! **************************************************************************************************
      65           24 :    SUBROUTINE overlap3(la_max_set, npgfa, zeta, rpgfa, la_min_set, &
      66           48 :                        lb_max_set, npgfb, zetb, rpgfb, lb_min_set, &
      67           24 :                        lc_max_set, npgfc, zetc, rpgfc, lc_min_set, &
      68           24 :                        rab, dab, rac, dac, rbc, dbc, sabc, &
      69           24 :                        sdabc, sabdc, int_abc_ext)
      70              : 
      71              :       INTEGER, INTENT(IN)                                :: la_max_set, npgfa
      72              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: zeta, rpgfa
      73              :       INTEGER, INTENT(IN)                                :: la_min_set, lb_max_set, npgfb
      74              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: zetb, rpgfb
      75              :       INTEGER, INTENT(IN)                                :: lb_min_set, lc_max_set, npgfc
      76              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: zetc, rpgfc
      77              :       INTEGER, INTENT(IN)                                :: lc_min_set
      78              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab
      79              :       REAL(KIND=dp), INTENT(IN)                          :: dab
      80              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rac
      81              :       REAL(KIND=dp), INTENT(IN)                          :: dac
      82              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rbc
      83              :       REAL(KIND=dp), INTENT(IN)                          :: dbc
      84              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: sabc
      85              :       REAL(KIND=dp), DIMENSION(:, :, :, :), &
      86              :          INTENT(INOUT), OPTIONAL                         :: sdabc, sabdc
      87              :       REAL(dp), INTENT(OUT), OPTIONAL                    :: int_abc_ext
      88              : 
      89              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'overlap3'
      90              : 
      91              :       INTEGER :: a_first, a_last, avec(3), axis, b_first, b_last, bvec(3), c_first, c_last, coa, &
      92              :          cob, coc, cvec(3), handle, ia, ib, ic, ipgf, jaxis, jpgf, kaxis, kpgf, la_max, lc_max, &
      93           48 :          na, nb, nc, map_c(4, lc_max_set + 1), map_a(4, la_max_set + 1)
      94              :       REAL(KIND=dp)                                      :: f0, f1, factor, rcp2, value, zet, zetg, &
      95              :                                                             zetp
      96           24 :       REAL(KIND=dp), ALLOCATABLE                         :: derivative_a(:, :, :, :), &
      97           24 :                                                             derivative_c(:, :, :, :), &
      98              :                                                             rr(:, :, :, :)
      99              :       REAL(KIND=dp), DIMENSION(3)                        :: rap, rbp, rcg, rcp
     100              : 
     101           24 :       CALL timeset(routineN, handle)
     102              : 
     103           24 :       la_max = la_max_set
     104           24 :       lc_max = lc_max_set
     105           24 :       IF (PRESENT(sdabc)) la_max = la_max + 1
     106           24 :       IF (PRESENT(sabdc)) lc_max = lc_max + 1
     107          144 :       ALLOCATE (rr(0:la_max, 0:lb_max_set, 0:lc_max, 3))
     108              : 
     109           24 :       a_first = ncoset(la_min_set - 1) + 1
     110           24 :       a_last = ncoset(la_max_set)
     111           24 :       b_first = ncoset(lb_min_set - 1) + 1
     112           24 :       b_last = ncoset(lb_max_set)
     113           24 :       c_first = ncoset(lc_min_set - 1) + 1
     114           24 :       c_last = ncoset(lc_max_set)
     115              : 
     116              :       ! Clear the requested derivative extents, including screened blocks and lower-shell padding.
     117           24 :       IF (PRESENT(sdabc)) THEN
     118       121296 :          sdabc(1:npgfa*a_last, 1:npgfb*b_last, 1:npgfc*c_last, 1:3) = 0.0_dp
     119           72 :          ALLOCATE (derivative_a(0:la_max_set, 0:lb_max_set, 0:lc_max_set, 3))
     120           12 :          CALL cartesian_ladder_map(la_max_set, 0, 0, map_a)
     121              :       END IF
     122           24 :       IF (PRESENT(sabdc)) THEN
     123       121296 :          sabdc(1:npgfa*a_last, 1:npgfb*b_last, 1:npgfc*c_last, 1:3) = 0.0_dp
     124           72 :          ALLOCATE (derivative_c(0:la_max_set, 0:lb_max_set, 0:lc_max_set, 3))
     125           12 :          CALL cartesian_ladder_map(lc_max_set, 0, 0, map_c)
     126              :       END IF
     127           24 :       IF (PRESENT(int_abc_ext)) int_abc_ext = 0.0_dp
     128              : 
     129          144 :       DO ipgf = 1, npgfa
     130          120 :          na = (ipgf - 1)*a_last
     131          744 :          DO jpgf = 1, npgfb
     132          600 :             nb = (jpgf - 1)*b_last
     133          600 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
     134            0 :                sabc(na + 1:na + a_last, nb + 1:nb + b_last, 1:npgfc*c_last) = 0.0_dp
     135              :                CYCLE
     136              :             END IF
     137          600 :             zetp = 1.0_dp/(zeta(ipgf) + zetb(jpgf))
     138          600 :             f1 = zetb(jpgf)*zetp
     139         2400 :             rcp = f1*rab - rac
     140         2400 :             rcp2 = DOT_PRODUCT(rcp, rcp)
     141         2820 :             DO kpgf = 1, npgfc
     142         2100 :                nc = (kpgf - 1)*c_last
     143         2100 :                IF ((rpgfb(jpgf) + rpgfc(kpgf) < dbc) .OR. &
     144              :                    (rpgfa(ipgf) + rpgfc(kpgf) < dac)) THEN
     145            0 :                   sabc(na + 1:na + a_last, nb + 1:nb + b_last, nc + 1:nc + c_last) = 0.0_dp
     146              :                   CYCLE
     147              :                END IF
     148              : 
     149         2100 :                zet = zeta(ipgf) + zetb(jpgf) + zetc(kpgf)
     150         2100 :                zetg = 1.0_dp/zet
     151         2100 :                f0 = (pi*zetg)**1.5_dp
     152         2100 :                f0 = f0*EXP(-(zeta(ipgf)*f1*dab*dab + zetc(kpgf)*zetg*rcp2/zetp))
     153              : 
     154              :                ! G is the product center of all three Gaussians. The 1D tables are normalized;
     155              :                ! the three-dimensional [s|s|s] prefactor f0 is applied only on reconstruction.
     156         8400 :                rap = zetg*(zetb(jpgf)*rab + zetc(kpgf)*rac)
     157         8400 :                rbp = zetg*(-zeta(ipgf)*rab + zetc(kpgf)*rbc)
     158         8400 :                rcg = -zetg*(zeta(ipgf)*rac + zetb(jpgf)*rbc)
     159         2100 :                CALL os_rr_ovlp3(rap, la_max, rbp, lb_max_set, rcg, lc_max, zet, rr)
     160              : 
     161              :                ! Differentiate the original A and C basis functions after three-center table construction.
     162         2100 :                IF (PRESENT(sdabc)) THEN
     163         4200 :                   DO axis = 1, 3
     164         8250 :                      DO ic = 0, lc_max_set
     165              :                         CALL cartesian_ladder(rr(:, :, ic, axis), derivative_a(:, :, ic, axis), &
     166         7200 :                                               map_a, .TRUE., zeta(ipgf), 0.0_dp, .FALSE.)
     167              :                      END DO
     168              :                   END DO
     169              :                END IF
     170         2100 :                IF (PRESENT(sabdc)) THEN
     171         4200 :                   DO axis = 1, 3
     172        10500 :                      DO ib = 0, lb_max_set
     173              :                         CALL cartesian_ladder(rr(0:la_max_set, ib, :, axis), derivative_c(:, ib, :, axis), &
     174         9450 :                                               map_c, .TRUE., zetc(kpgf), 0.0_dp, .TRUE.)
     175              :                      END DO
     176              :                   END DO
     177              :                END IF
     178              : 
     179         7200 :                DO coc = c_first, c_last
     180        18000 :                   cvec = indco(:, coc)
     181         4500 :                   ic = nc + coc
     182        24600 :                   DO cob = b_first, b_last
     183        72000 :                      bvec = indco(:, cob)
     184        18000 :                      ib = nb + cob
     185        94500 :                      DO coa = a_first, a_last
     186       288000 :                         avec = indco(:, coa)
     187        72000 :                         ia = na + coa
     188              :                         value = f0*rr(avec(1), bvec(1), cvec(1), 1)* &
     189        72000 :                                 rr(avec(2), bvec(2), cvec(2), 2)*rr(avec(3), bvec(3), cvec(3), 3)
     190        72000 :                         sabc(ia, ib, ic) = value
     191        72000 :                         IF (PRESENT(int_abc_ext)) int_abc_ext = MAX(int_abc_ext, ABS(value))
     192        90000 :                         IF (PRESENT(sdabc) .OR. PRESENT(sabdc)) THEN
     193       144000 :                            DO axis = 1, 3
     194       108000 :                               jaxis = MOD(axis, 3) + 1
     195       108000 :                               kaxis = MOD(axis + 1, 3) + 1
     196              :                               factor = f0*rr(avec(jaxis), bvec(jaxis), cvec(jaxis), jaxis)* &
     197       108000 :                                        rr(avec(kaxis), bvec(kaxis), cvec(kaxis), kaxis)
     198       108000 :                               IF (PRESENT(sdabc)) THEN
     199       108000 :                                  sdabc(ia, ib, ic, axis) = factor*derivative_a(avec(axis), bvec(axis), cvec(axis), axis)
     200              :                               END IF
     201       144000 :                               IF (PRESENT(sabdc)) THEN
     202       108000 :                                  sabdc(ia, ib, ic, axis) = factor*derivative_c(avec(axis), bvec(axis), cvec(axis), axis)
     203              :                               END IF
     204              :                            END DO
     205              :                         END IF
     206              :                      END DO
     207              :                   END DO
     208              :                END DO
     209              :             END DO
     210              :          END DO
     211              :       END DO
     212              : 
     213           24 :       CALL timestop(handle)
     214              : 
     215           48 :    END SUBROUTINE overlap3
     216              : 
     217              : END MODULE ai_overlap3
        

Generated by: LCOV version 2.0-1