LCOV - code coverage report
Current view: top level - src/aobasis - ai_verfc.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 65.7 % 108 71
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              : ! **************************************************************************************************
       9              : !> \brief Build up the nuclear potential part of the core Hamiltonian matrix
      10              : !>      in the case of an allelectron calculation by computing the nuclear
      11              : !>      attraction integral matrix <a|-Z/r|b> and the integral matrix
      12              : !>      <a|Z*erf(r)/r|b>.  The integrals <a|Z*erf(r)/r|b> can be rewritten
      13              : !>      as the three-center Coulomb integrals <ab||c> with a  primitive
      14              : !>      s-type Gaussian function c multiplied by a factor N.
      15              : !>
      16              : !>                       erfc(r)
      17              : !>      <a|V|b> = -Z*<a|---------|b>
      18              : !>                          r
      19              : !>
      20              : !>                       1 - erf(r)
      21              : !>              = -Z*<a|------------|b>
      22              : !>                           r
      23              : !>
      24              : !>                        1           erf(r)
      25              : !>              = -Z*(<a|---|b> - <a|--------|b>)
      26              : !>                        r             r
      27              : !>
      28              : !>                        1
      29              : !>              = -Z*(<a|---|b> - N*<ab||c>)
      30              : !>                        r
      31              : !>
      32              : !>                       1
      33              : !>              = -Z*<a|---|b> + Z*N*<ab||c>
      34              : !>                       r
      35              : !>                   \_______/       \_____/
      36              : !>                       |              |
      37              : !>                    nuclear        coulomb
      38              : !> \par Literature
      39              : !>      S. Obara and A. Saika, J. Chem. Phys. 84, 3963 (1986)
      40              : !> \par Parameters
      41              : !>      -  ax,ay,az  : Angular momentum index numbers of orbital a.
      42              : !>      -  bx,by,bz  : Angular momentum index numbers of orbital b.
      43              : !>      -  coset     : Cartesian orbital set pointer.
      44              : !>      -  dab       : Distance between the atomic centers a and b.
      45              : !>      -  dac       : Distance between the atomic centers a and c.
      46              : !>      -  dbc       : Distance between the atomic centers b and c.
      47              : !>      -  l{a,b}    : Angular momentum quantum number of shell a or b.
      48              : !>      -  l{a,b}_max: Maximum angular momentum quantum number of shell a or b.
      49              : !>      -  l{a,b}_min: Minimum angular momentum quantum number of shell a or b.
      50              : !>      -  ncoset    : Number of orbitals in a Cartesian orbital set.
      51              : !>      -  npgf{a,b} : Degree of contraction of shell a or b.
      52              : !>      -  rab       : Distance vector between the atomic centers a and b.
      53              : !>      -  rab2      : Square of the distance between the atomic centers a and b.
      54              : !>      -  rac       : Distance vector between the atomic centers a and c.
      55              : !>      -  rac2      : Square of the distance between the atomic centers a and c.
      56              : !>      -  rbc2      : Square of the distance between the atomic centers b and c.
      57              : !>      -  rpgf{a,b} : Radius of the primitive Gaussian-type function a or b.
      58              : !>      -  zet{a,b}  : Exponents of the Gaussian-type functions a or b.
      59              : !>      -  zetp      : Reciprocal of the sum of the exponents of orbital a and b.
      60              : !>      -  zetw        : Reciprocal of the sum of the exponents of orbital a, b and c.
      61              : !> \par History
      62              : !>      10.2008 added pVp matrix elements (jens)
      63              : !> \author Matthias Krack (04.10.2000)
      64              : ! **************************************************************************************************
      65              : 
      66              : MODULE ai_verfc
      67              : 
      68              :    USE ai_cartesian_operators,          ONLY: apply_cartesian_operator_pair,&
      69              :                                               cartesian_ladder_map
      70              :    USE ai_os_rr,                        ONLY: os_rr_radial
      71              :    USE gamma,                           ONLY: fgamma => fgamma_0
      72              :    USE kinds,                           ONLY: dp
      73              :    USE mathconstants,                   ONLY: pi
      74              :    USE orbital_pointers,                ONLY: ncoset
      75              : #include "../base/base_uses.f90"
      76              : 
      77              :    IMPLICIT NONE
      78              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ai_verfc'
      79              :    PRIVATE
      80              : 
      81              : ! *** Public subroutines ***
      82              : 
      83              :    PUBLIC :: verfc
      84              : 
      85              : CONTAINS
      86              : 
      87              : ! **************************************************************************************************
      88              : !> \brief   Calculation of the primitive three-center nuclear potential
      89              : !>          integrals <a|Z*erfc(r)/r|b> over Cartesian Gaussian-type
      90              : !>          functions.
      91              : !> \param la_max1 ...
      92              : !> \param npgfa ...
      93              : !> \param zeta ...
      94              : !> \param rpgfa ...
      95              : !> \param la_min1 ...
      96              : !> \param lb_max1 ...
      97              : !> \param npgfb ...
      98              : !> \param zetb ...
      99              : !> \param rpgfb ...
     100              : !> \param lb_min1 ...
     101              : !> \param zetc ...
     102              : !> \param rpgfc ...
     103              : !> \param zc ...
     104              : !> \param cerf ...
     105              : !> \param rab ...
     106              : !> \param rab2 ...
     107              : !> \param rac ...
     108              : !> \param rac2 ...
     109              : !> \param rbc2 ...
     110              : !> \param vabc ...
     111              : !> \param verf ...
     112              : !> \param vnuc ...
     113              : !> \param f ...
     114              : !> \param maxder ...
     115              : !> \param vabc_plus ...
     116              : !> \param vnabc ...
     117              : !> \param pVp_sum ...
     118              : !> \param pVp ...
     119              : !> \param dkh_erfc ...
     120              : !> \date    04.10.2000
     121              : !> \author  Matthias Krack
     122              : !> \version 1.0
     123              : ! **************************************************************************************************
     124      4975432 :    SUBROUTINE verfc(la_max1, npgfa, zeta, rpgfa, la_min1, lb_max1, npgfb, zetb, rpgfb, lb_min1, &
     125     14926296 :                     zetc, rpgfc, zc, cerf, rab, rab2, rac, rac2, rbc2, vabc, verf, vnuc, f, &
     126     14926296 :                     maxder, vabc_plus, vnabc, pVp_sum, pVp, dkh_erfc) !JT
     127              :       INTEGER, INTENT(IN)                                :: la_max1, npgfa
     128              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: zeta, rpgfa
     129              :       INTEGER, INTENT(IN)                                :: la_min1, lb_max1, npgfb
     130              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: zetb, rpgfb
     131              :       INTEGER, INTENT(IN)                                :: lb_min1
     132              :       REAL(KIND=dp), INTENT(IN)                          :: zetc, rpgfc, zc, cerf
     133              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rab
     134              :       REAL(KIND=dp), INTENT(IN)                          :: rab2
     135              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rac
     136              :       REAL(KIND=dp), INTENT(IN)                          :: rac2, rbc2
     137              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: vabc
     138              :       REAL(KIND=dp), DIMENSION(:, :, :)                  :: verf, vnuc
     139              :       REAL(KIND=dp), DIMENSION(0:)                       :: f
     140              :       INTEGER, INTENT(IN), OPTIONAL                      :: maxder
     141              :       REAL(KIND=dp), DIMENSION(:, :), OPTIONAL           :: vabc_plus, vnabc, pVp_sum, pVp
     142              :       LOGICAL, OPTIONAL                                  :: dkh_erfc
     143              : 
     144              :       INTEGER, DIMENSION(2, 3), PARAMETER :: components = RESHAPE([1, 1, 2, 2, 3, 3], [2, 3])
     145              : 
     146              :       INTEGER                                            :: axis, i, ipgf, j, jpgf, la_max, lb_max, &
     147              :                                                             maxder_local, n, na, nap, nb, &
     148              :                                                             ncol_pvp, nmax, nrow_pvp
     149      4975432 :       INTEGER, ALLOCATABLE, DIMENSION(:, :, :)           :: map_a, map_b
     150              :       LOGICAL                                            :: do_dkh
     151              :       REAL(KIND=dp)                                      :: dab, dac, dbc, f0, f1, f4, ferf, fnuc, &
     152              :                                                             rcp2, t, zetp, zetq, zetw
     153      4975432 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: potential, work
     154      4975432 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: derivatives
     155              :       REAL(KIND=dp), DIMENSION(3)                        :: rap, rbp, rcp, rpw
     156              : 
     157              : !   ---------------------------------------------------------------------------
     158              : 
     159      4975432 :       IF (PRESENT(maxder)) THEN
     160     78910605 :          verf(1:ncoset(la_max1), 1:ncoset(lb_max1), 1) = 0._dp
     161     78910605 :          vnuc(1:ncoset(la_max1), 1:ncoset(lb_max1), 1) = 0._dp
     162              :       END IF
     163              : 
     164              :       ! The legacy output uses the full Cartesian B range.
     165              :       MARK_USED(lb_min1)
     166              : 
     167      4975432 :       do_dkh = .FALSE.
     168              : 
     169      4975432 :       IF (PRESENT(pVp)) THEN
     170            0 :          do_dkh = .TRUE.
     171            0 :          pVp = 0.0_dp
     172              :          ! pVp matrices requires angular momentum quantum numbers l+1 and l-1
     173              : 
     174            0 :          la_max = la_max1 + 1
     175            0 :          IF (PRESENT(maxder)) THEN
     176            0 :             IF (maxder > 0) THEN
     177            0 :                la_max = la_max1
     178              :             END IF
     179              :          END IF
     180            0 :          lb_max = lb_max1 + 1
     181              :       ELSE
     182      4975432 :          do_dkh = .FALSE.
     183      4975432 :          la_max = la_max1
     184      4975432 :          lb_max = lb_max1
     185              :       END IF
     186              : 
     187      4975432 :       nmax = la_max + lb_max + 1
     188              : 
     189      4975432 :       maxder_local = 0
     190      4975432 :       IF (PRESENT(maxder)) maxder_local = maxder
     191              : 
     192      4975432 :       IF (do_dkh) THEN
     193              :          ! With maxder > 0, la_max1 includes the extra shells for vabc_plus.
     194              :          ! The pVp output ends at la_max1-maxder_local; its ladder needs one more shell.
     195            0 :          nrow_pvp = ncoset(la_max1 - maxder_local)
     196            0 :          ncol_pvp = ncoset(lb_max1)
     197            0 :          ALLOCATE (map_a(4, nrow_pvp, 3), map_b(4, ncol_pvp, 3))
     198              :          ALLOCATE (potential(ncoset(la_max1 - maxder_local + 1), ncoset(lb_max1 + 1)), &
     199            0 :                    work(nrow_pvp, ncoset(lb_max1 + 1)), derivatives(nrow_pvp, ncol_pvp, 3))
     200            0 :          DO axis = 1, 3
     201            0 :             CALL cartesian_ladder_map(la_max1 - maxder_local, 0, axis, map_a(:, :, axis), source_lmin=0)
     202            0 :             CALL cartesian_ladder_map(lb_max1, 0, axis, map_b(:, :, axis), source_lmin=0)
     203              :          END DO
     204              :       END IF
     205              : 
     206              : !   *** Calculate the distances of the centers a, b and c ***
     207              : 
     208      4975432 :       dab = SQRT(rab2)
     209      4975432 :       dac = SQRT(rac2)
     210      4975432 :       dbc = SQRT(rbc2)
     211              : 
     212              : !   *** Loop over all pairs of primitive Gaussian-type functions ***
     213              : 
     214      4975432 :       na = 0
     215      4975432 :       nap = 0
     216              : 
     217     12505470 :       DO ipgf = 1, npgfa
     218              : 
     219              : !     *** Screening ***
     220              : 
     221      7530038 :          IF (do_dkh) THEN
     222            0 :             IF (dkh_erfc) THEN
     223            0 :                IF (rpgfa(ipgf) + rpgfc < dac) THEN
     224            0 :                   na = na + ncoset(la_max1 - maxder_local) !JT
     225            0 :                   nap = nap + ncoset(la_max1) !JT
     226            0 :                   CYCLE
     227              :                END IF
     228              :             END IF
     229              :          ELSE
     230      7530038 :             IF (rpgfa(ipgf) + rpgfc < dac) THEN
     231      1796992 :                na = na + ncoset(la_max1 - maxder_local) !JT
     232      1796992 :                nap = nap + ncoset(la_max1) !JT
     233      1796992 :                CYCLE
     234              :             END IF
     235              :          END IF
     236              : 
     237      5733046 :          nb = 0
     238              : 
     239     14661503 :          DO jpgf = 1, npgfb
     240              : 
     241              : !       *** Screening ***
     242      8928457 :             IF (do_dkh) THEN
     243            0 :                IF (dkh_erfc) THEN
     244            0 :                   IF ((rpgfb(jpgf) + rpgfc < dbc) .OR. &
     245              :                       (rpgfa(ipgf) + rpgfb(jpgf) < dab)) THEN
     246            0 :                      nb = nb + ncoset(lb_max1) !JT
     247            0 :                      CYCLE
     248              :                   END IF
     249              :                END IF
     250              :             ELSE
     251      8928457 :                IF ((rpgfb(jpgf) + rpgfc < dbc) .OR. &
     252              :                    (rpgfa(ipgf) + rpgfb(jpgf) < dab)) THEN
     253      2557480 :                   nb = nb + ncoset(lb_max1) !JT
     254      2557480 :                   CYCLE
     255              :                END IF
     256              :             END IF
     257              : !       *** Calculate some prefactors ***
     258              : 
     259      6370977 :             zetp = 1.0_dp/(zeta(ipgf) + zetb(jpgf))
     260      6370977 :             zetq = 1.0_dp/zetc
     261      6370977 :             zetw = 1.0_dp/(zeta(ipgf) + zetb(jpgf) + zetc)
     262              : 
     263      6370977 :             f1 = zetb(jpgf)*zetp
     264      6370977 :             f4 = -zetc*zetw
     265              : 
     266      6370977 :             f0 = EXP(-zeta(ipgf)*f1*rab2)
     267              : 
     268      6370977 :             fnuc = 2.0_dp*pi*zetp*f0
     269      6370977 :             ferf = 2.0_dp*SQRT(pi**5*zetw)*zetp*zetq*f0
     270              : 
     271     25483908 :             rap(:) = f1*rab(:)
     272     25483908 :             rcp(:) = rap(:) - rac(:)
     273     25483908 :             rpw(:) = f4*rcp(:)
     274              : 
     275              : !       *** Calculate the incomplete Gamma function values ***
     276              : 
     277      6370977 :             rcp2 = rcp(1)*rcp(1) + rcp(2)*rcp(2) + rcp(3)*rcp(3)
     278              : 
     279      6370977 :             t = rcp2/zetp
     280              : 
     281      6370977 :             CALL fgamma(nmax - 1, t, f)
     282              : 
     283              : !       *** Calculate the basic nuclear attraction integrals [s|A(0)|s]{n} ***
     284              : 
     285     24448707 :             DO n = 1, nmax
     286     24448707 :                vnuc(1, 1, n) = fnuc*f(n - 1)
     287              :             END DO
     288              : 
     289              : !       *** Calculate the incomplete Gamma function values ***
     290              : 
     291      6370977 :             t = -f4*rcp2/zetp
     292              : 
     293      6370977 :             CALL fgamma(nmax - 1, t, f)
     294              : 
     295              : !       *** Calculate the basic three-center Coulomb integrals [ss||s]{n} ***
     296              : 
     297     24448707 :             DO n = 1, nmax
     298     24448707 :                verf(1, 1, n) = ferf*f(n - 1)
     299              :             END DO
     300              : 
     301     25483908 :             rbp = rap - rab
     302     25483908 :             CALL os_rr_radial(rap, la_max, rbp, lb_max, -rcp, zetp, 1.0_dp, nmax - 1, vnuc)
     303      6370977 :             CALL os_rr_radial(rap, la_max, rbp, lb_max, rpw, zetp, -f4, nmax - 1, verf)
     304              : 
     305              : !       *** Add the contribution of the current pair ***
     306              : !       *** of primitive Gaussian-type functions     ***
     307              : 
     308              : !JT
     309      6370977 :             IF (do_dkh) THEN
     310            0 :                DO j = 1, ncoset(lb_max1)
     311            0 :                   DO i = ncoset(la_min1 - 1) + 1, ncoset(la_max1 - maxder_local)
     312            0 :                      vnabc(na + i, nb + j) = vnabc(na + i, nb + j) + cerf*verf(i, j, 1)
     313              :                   END DO
     314              :                END DO
     315            0 :                DO j = 1, ncoset(lb_max1)
     316            0 :                   DO i = ncoset(la_min1 - 1) + 1, ncoset(la_max1 - maxder_local)
     317            0 :                      vabc(na + i, nb + j) = vabc(na + i, nb + j) - zc*vnuc(i, j, 1)
     318              :                   END DO
     319              :                END DO
     320              :             ELSE
     321     27743689 :                DO j = 1, ncoset(lb_max1) !JT
     322     83551426 :                   DO i = ncoset(la_min1 - 1) + 1, ncoset(la_max1 - maxder_local) !JT
     323              :                      vabc(na + i, nb + j) = vabc(na + i, nb + j) - &
     324     77180449 :                                             zc*vnuc(i, j, 1) + cerf*verf(i, j, 1)
     325              :                   END DO
     326              :                END DO
     327              :             END IF
     328              : !JT
     329              : 
     330      6370977 :             IF (PRESENT(maxder)) THEN
     331     12261433 :                DO j = 1, ncoset(lb_max1) !JT
     332     94776709 :                   DO i = 1, ncoset(la_max1) !JT
     333              :                      vabc_plus(nap + i, nb + j) = vabc_plus(nap + i, nb + j) - &
     334     91996685 :                                                   zc*vnuc(i, j, 1) + cerf*verf(i, j, 1)
     335              :                   END DO
     336              :                END DO
     337              :             END IF
     338              : !JTs
     339      6370977 :             IF (do_dkh) THEN
     340              :                ! pVp = sum_i D_Ai D_Bi V; both electronic derivatives change sign.
     341            0 :                potential(:, :) = -zc*vnuc(1:SIZE(potential, 1), 1:SIZE(potential, 2), 1)
     342            0 :                IF (dkh_erfc) THEN
     343            0 :                   potential(:, :) = potential + cerf*verf(1:SIZE(potential, 1), 1:SIZE(potential, 2), 1)
     344              :                END IF
     345              :                CALL apply_cartesian_operator_pair(potential, derivatives, map_a, map_b, components, &
     346            0 :                                                   [.TRUE., .TRUE.], [zeta(ipgf), zetb(jpgf)], [.FALSE., .TRUE.], work)
     347            0 :                pVp(1:nrow_pvp, 1:ncol_pvp) = SUM(derivatives, DIM=3)
     348              : 
     349            0 :                DO j = 1, ncoset(lb_max1)
     350            0 :                   DO i = ncoset(la_min1 - 1) + 1, ncoset(la_max1 - maxder_local)
     351            0 :                      pVp_sum(na + i, nb + j) = pVp_sum(na + i, nb + j) + pVp(i, j)
     352              :                   END DO
     353              :                END DO
     354              :             END IF
     355              : !JTe
     356     12104023 :             nb = nb + ncoset(lb_max1) !JT
     357              : 
     358              :          END DO
     359              : 
     360      5733046 :          na = na + ncoset(la_max1 - maxder_local) !JT
     361     10708478 :          nap = nap + ncoset(la_max1) !JT
     362              : 
     363              :       END DO
     364              : 
     365      4975432 :    END SUBROUTINE verfc
     366              : 
     367              : END MODULE ai_verfc
        

Generated by: LCOV version 2.0-1