LCOV - code coverage report
Current view: top level - src/aobasis - ai_elec_field.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 100.0 % 62 62
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 Calculation of Coulomb integrals over Cartesian Gaussian-type functions
      10              : !>      (electron repulsion integrals, ERIs).
      11              : !> \par Literature
      12              : !>      S. Obara and A. Saika, J. Chem. Phys. 84, 3963 (1986)
      13              : !> \par History
      14              : !>      none
      15              : !> \par Parameters
      16              : !>       - ax,ay,az    : Angular momentum index numbers of orbital a.
      17              : !>       - bx,by,bz    : Angular momentum index numbers of orbital b.
      18              : !>       - coset       : Cartesian orbital set pointer.
      19              : !>       - dab         : Distance between the atomic centers a and b.
      20              : !>       - dac         : Distance between the atomic centers a and c.
      21              : !>       - dbc         : Distance between the atomic centers b and c.
      22              : !>       - l{a,b,c}    : Angular momentum quantum number of shell a, b or c.
      23              : !>       - l{a,b,c}_max: Maximum angular momentum quantum number of shell a, b or c.
      24              : !>       - l{a,b,c}_min: Minimum angular momentum quantum number of shell a, b or c.
      25              : !>       - ncoset      : Number of orbitals in a Cartesian orbital set.
      26              : !>       - npgf{a,b}   : Degree of contraction of shell a or b.
      27              : !>       - rab         : Distance vector between the atomic centers a and b.
      28              : !>       - rab2        : Square of the distance between the atomic centers a and b.
      29              : !>       - rac         : Distance vector between the atomic centers a and c.
      30              : !>       - rac2        : Square of the distance between the atomic centers a and c.
      31              : !>       - rbc         : Distance vector between the atomic centers b and c.
      32              : !>       - rbc2        : Square of the distance between the atomic centers b and c.
      33              : !>       - rpgf{a,b,c} : Radius of the primitive Gaussian-type function a, b or c.
      34              : !>       - zet{a,b,c}  : Exponents of the Gaussian-type functions a, b or c.
      35              : !>       - zetp        : Reciprocal of the sum of the exponents of orbital a and b.
      36              : !> \author VW
      37              : ! **************************************************************************************************
      38              : MODULE ai_elec_field
      39              :    USE ai_cartesian_operators,          ONLY: apply_cartesian_operator_pair,&
      40              :                                               cartesian_ladder_map
      41              :    USE ai_os_rr,                        ONLY: os_rr_coul
      42              :    USE kinds,                           ONLY: dp
      43              :    USE mathconstants,                   ONLY: pi
      44              :    USE orbital_pointers,                ONLY: ncoset
      45              : #include "../base/base_uses.f90"
      46              : 
      47              :    IMPLICIT NONE
      48              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ai_elec_field'
      49              :    PRIVATE
      50              : 
      51              :    ! *** Public subroutines ***
      52              : 
      53              :    PUBLIC :: efg
      54              : 
      55              : CONTAINS
      56              : 
      57              : ! **************************************************************************************************
      58              : !> \brief   Calculation of the primitive electric field integrals over
      59              : !>          Cartesian Gaussian-type functions.
      60              : !> \param la_max ...
      61              : !> \param la_min ...
      62              : !> \param npgfa ...
      63              : !> \param rpgfa ...
      64              : !> \param zeta ...
      65              : !> \param lb_max ...
      66              : !> \param lb_min ...
      67              : !> \param npgfb ...
      68              : !> \param rpgfb ...
      69              : !> \param zetb ...
      70              : !> \param rac ...
      71              : !> \param rbc ...
      72              : !> \param rab ...
      73              : !> \param vab ...
      74              : !> \param ldrr1 ...
      75              : !> \param ldrr2 ...
      76              : !> \param rr ...
      77              : !> \date    02.03.2009
      78              : !> \author  VW
      79              : !> \version 1.0
      80              : ! **************************************************************************************************
      81         9222 :    SUBROUTINE efg(la_max, la_min, npgfa, rpgfa, zeta, &
      82        18444 :                   lb_max, lb_min, npgfb, rpgfb, zetb, &
      83         9222 :                   rac, rbc, rab, vab, ldrr1, ldrr2, rr)
      84              :       INTEGER, INTENT(IN)                                :: la_max, la_min, npgfa
      85              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfa, zeta
      86              :       INTEGER, INTENT(IN)                                :: lb_max, lb_min, npgfb
      87              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: rpgfb, zetb
      88              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: rac, rbc, rab
      89              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: vab
      90              :       INTEGER, INTENT(IN)                                :: ldrr1, ldrr2
      91              :       REAL(KIND=dp), DIMENSION(0:ldrr1-1, ldrr2, *), &
      92              :          INTENT(INOUT)                                   :: rr
      93              : 
      94              :       INTEGER, DIMENSION(2, 6), PARAMETER :: &
      95              :          symmetric_components = RESHAPE([1, 1, 1, 2, 1, 3, 2, 2, 2, 3, 3, 3], [2, 6])
      96              :       INTEGER, DIMENSION(2, 9), PARAMETER :: &
      97              :          mixed_components = RESHAPE([1, 1, 2, 1, 3, 1, 1, 2, 2, 2, 3, 2, 1, 3, 2, 3, 3, 3], [2, 9])
      98              : 
      99              :       INTEGER                                            :: axis, first_a, first_b, i, icomp, idir, &
     100              :                                                             ipgf, j, jdir, jpgf, na, nb, ncap, &
     101              :                                                             ncbp, ncol, nrow
     102         9222 :       INTEGER, ALLOCATABLE                               :: map_a(:, :, :), map_ap(:, :, :), &
     103              :                                                             map_b(:, :, :), map_bp(:, :, :)
     104              :       REAL(KIND=dp)                                      :: dab, f0, rab2, trace_third, xhi, za, zb, &
     105              :                                                             zet
     106              :       REAL(KIND=dp), ALLOCATABLE                         :: hessian(:, :, :), tensor(:, :, :), &
     107         9222 :                                                             work(:, :)
     108              :       REAL(KIND=dp), DIMENSION(3)                        :: rap, rbp, rcp
     109              : 
     110         9222 :       first_a = ncoset(la_min - 1) + 1
     111         9222 :       first_b = ncoset(lb_min - 1) + 1
     112         9222 :       nrow = ncoset(la_max) - first_a + 1
     113         9222 :       ncol = ncoset(lb_max) - first_b + 1
     114         9222 :       ncap = ncoset(la_max + 1)
     115         9222 :       ncbp = ncoset(lb_max + 1)
     116       119886 :       ALLOCATE (map_a(4, nrow, 3), map_ap(4, ncap, 3), map_b(4, ncol, 3), map_bp(4, ncbp, 3))
     117       110664 :       ALLOCATE (hessian(nrow, ncol, 6), tensor(nrow, ncol, 9), work(ncap, ncbp))
     118        36888 :       DO axis = 1, 3
     119        27666 :          CALL cartesian_ladder_map(la_max, la_min, axis, map_a(:, :, axis), source_lmin=0)
     120        27666 :          CALL cartesian_ladder_map(la_max + 1, 0, axis, map_ap(:, :, axis))
     121        27666 :          CALL cartesian_ladder_map(lb_max, lb_min, axis, map_b(:, :, axis), source_lmin=0)
     122        36888 :          CALL cartesian_ladder_map(lb_max + 1, 0, axis, map_bp(:, :, axis))
     123              :       END DO
     124              : 
     125              : ! *** Calculate the distance of the centers a and c ***
     126              : 
     127         9222 :       rab2 = rab(1)**2 + rab(2)**2 + rab(3)**2
     128         9222 :       dab = SQRT(rab2)
     129              : 
     130              :       ! *** Loop over all pairs of primitive Gaussian-type functions ***
     131              : 
     132         9222 :       na = 0
     133              : 
     134        21050 :       DO ipgf = 1, npgfa
     135              : 
     136        11828 :          nb = 0
     137              : 
     138        27026 :          DO jpgf = 1, npgfb
     139              : 
     140              :             ! *** Screening ***
     141              : 
     142        15198 :             IF (rpgfa(ipgf) + rpgfb(jpgf) < dab) THEN
     143         6888 :                DO j = nb + 1, nb + ncoset(lb_max)
     144        12801 :                   DO i = na + 1, na + ncoset(la_max)
     145         5913 :                      vab(i, j, 1) = 0.0_dp
     146         5913 :                      vab(i, j, 2) = 0.0_dp
     147         5913 :                      vab(i, j, 3) = 0.0_dp
     148         5913 :                      vab(i, j, 4) = 0.0_dp
     149         5913 :                      vab(i, j, 5) = 0.0_dp
     150         9999 :                      vab(i, j, 6) = 0.0_dp
     151              :                   END DO
     152              :                END DO
     153         2802 :                nb = nb + ncoset(lb_max)
     154         2802 :                CYCLE
     155              :             END IF
     156              : 
     157              :             ! *** Calculate some prefactors ***
     158              : 
     159        12396 :             za = zeta(ipgf)
     160        12396 :             zb = zetb(jpgf)
     161        12396 :             zet = za + zb
     162        12396 :             xhi = za*zb/zet
     163        49584 :             rap = zb*rab/zet
     164        49584 :             rbp = -za*rab/zet
     165        49584 :             rcp = -(za*rac + zb*rbc)/zet
     166        12396 :             f0 = 2.0_dp*SQRT(zet/pi)*(pi/zet)**(1.5_dp)*EXP(-xhi*rab2)
     167              : 
     168              :             ! *** Calculate the recurrence relation
     169              : 
     170        12396 :             CALL os_rr_coul(rap, la_max + 2, rbp, lb_max + 2, rcp, zet, ldrr1, ldrr2, rr)
     171              : 
     172              :             ! Translational invariance gives D_C = -(D_A + D_B).
     173              :             ! The A/B ladders differentiate the basis functions with the potential held fixed.
     174              :             ! Form its Hessian from AA, BB and both ordered AB derivatives.
     175              :             CALL apply_cartesian_operator_pair(rr(0, 1:ncoset(la_max + 2), first_b:ncoset(lb_max)), &
     176              :                                                hessian, map_ap, map_a, symmetric_components, [.TRUE., .TRUE.], [za, za], &
     177        37188 :                                                [.FALSE., .FALSE.], work(:, 1:ncol))
     178              :             CALL apply_cartesian_operator_pair(rr(0, first_a:ncoset(la_max), 1:ncoset(lb_max + 2)), &
     179              :                                                tensor(:, :, 1:6), map_bp, map_b, symmetric_components, [.TRUE., .TRUE.], [zb, zb], &
     180        37188 :                                                [.TRUE., .TRUE.], work(1:nrow, :))
     181       442044 :             hessian(:, :, :) = hessian + tensor(:, :, 1:6)
     182              :             CALL apply_cartesian_operator_pair(rr(0, 1:ncap, 1:ncbp), tensor, map_a, map_b, &
     183        37188 :                                                mixed_components, [.TRUE., .TRUE.], [za, zb], [.FALSE., .TRUE.], work(1:nrow, :))
     184        86772 :             DO icomp = 1, 6
     185        74376 :                idir = symmetric_components(1, icomp)
     186        74376 :                jdir = symmetric_components(2, icomp)
     187              :                hessian(:, :, icomp) = hessian(:, :, icomp) + &
     188       442044 :                                       tensor(:, :, idir + 3*(jdir - 1)) + tensor(:, :, jdir + 3*(idir - 1))
     189              :             END DO
     190              : 
     191              :             ! Preserve the symmetric, traceless EFG ordering: xx, xy, xz, yy, yz, zz.
     192        33442 :             DO j = 1, ncol
     193        71608 :                DO i = 1, nrow
     194        38166 :                   trace_third = (hessian(i, j, 1) + hessian(i, j, 4) + hessian(i, j, 6))/3.0_dp
     195        38166 :                   hessian(i, j, 1) = hessian(i, j, 1) - trace_third
     196        38166 :                   hessian(i, j, 4) = hessian(i, j, 4) - trace_third
     197        59212 :                   hessian(i, j, 6) = hessian(i, j, 6) - trace_third
     198              :                END DO
     199              :             END DO
     200       442044 :             vab(na + first_a:na + ncoset(la_max), nb + first_b:nb + ncoset(lb_max), 1:6) = f0*hessian
     201              : 
     202        24224 :             nb = nb + ncoset(lb_max)
     203              : 
     204              :          END DO
     205              : 
     206        21050 :          na = na + ncoset(la_max)
     207              : 
     208              :       END DO
     209              : 
     210         9222 :    END SUBROUTINE efg
     211              : 
     212              : END MODULE ai_elec_field
        

Generated by: LCOV version 2.0-1