LCOV - code coverage report
Current view: top level - src - atom_operators.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4c33f95) Lines: 602 668 90.1 %
Date: 2025-01-30 06:53:08 Functions: 11 11 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief   Calculate the atomic operator matrices
      10             : !> \author  jgh
      11             : !> \date    03.03.2008
      12             : !> \version 1.0
      13             : !>
      14             : ! **************************************************************************************************
      15             : MODULE atom_operators
      16             :    USE ai_onecenter,                    ONLY: &
      17             :         sg_coulomb, sg_erf, sg_erfc, sg_exchange, sg_gpot, sg_kinetic, sg_kinnuc, sg_nuclear, &
      18             :         sg_overlap, sg_proj_ol, sto_kinetic, sto_nuclear, sto_overlap
      19             :    USE atom_types,                      ONLY: &
      20             :         atom_basis_gridrep, atom_basis_type, atom_compare_grids, atom_integrals, &
      21             :         atom_potential_type, atom_state, cgto_basis, ecp_pseudo, gth_pseudo, gto_basis, lmat, &
      22             :         no_pseudo, num_basis, release_atom_basis, sgp_pseudo, sto_basis, upf_pseudo
      23             :    USE atom_utils,                      ONLY: &
      24             :         atom_solve, contract2, contract2add, contract4, coulomb_potential_numeric, integrate_grid, &
      25             :         numpot_matrix, slater_density, wigner_slater_functional
      26             :    USE dkh_main,                        ONLY: dkh_atom_transformation
      27             :    USE input_constants,                 ONLY: &
      28             :         barrier_conf, do_dkh0_atom, do_dkh1_atom, do_dkh2_atom, do_dkh3_atom, do_nonrel_atom, &
      29             :         do_sczoramp_atom, do_zoramp_atom, poly_conf
      30             :    USE kinds,                           ONLY: dp
      31             :    USE mathconstants,                   ONLY: gamma1,&
      32             :                                               sqrt2
      33             :    USE mathlib,                         ONLY: jacobi
      34             :    USE periodic_table,                  ONLY: ptable
      35             :    USE physcon,                         ONLY: c_light_au
      36             :    USE qs_grid_atom,                    ONLY: grid_atom_type
      37             : #include "./base/base_uses.f90"
      38             : 
      39             :    IMPLICIT NONE
      40             : 
      41             :    PRIVATE
      42             : 
      43             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'atom_operators'
      44             : 
      45             :    PUBLIC :: atom_int_setup, atom_ppint_setup, atom_int_release, atom_ppint_release
      46             :    PUBLIC :: atom_relint_setup, atom_relint_release, atom_basis_projection_overlap
      47             :    PUBLIC :: calculate_model_potential
      48             : 
      49             : CONTAINS
      50             : 
      51             : ! **************************************************************************************************
      52             : !> \brief Set up atomic integrals.
      53             : !> \param integrals     atomic integrals
      54             : !> \param basis         atomic basis set
      55             : !> \param potential     pseudo-potential
      56             : !> \param eri_coulomb   setup one-centre Coulomb Electron Repulsion Integrals
      57             : !> \param eri_exchange  setup one-centre exchange Electron Repulsion Integrals
      58             : !> \param all_nu        compute integrals for all even integer parameters [0 .. 2*l]
      59             : !>                      REDUNDANT, AS THIS SUBROUTINE IS NEVER INVOKED WITH all_nu = .TRUE.
      60             : ! **************************************************************************************************
      61       11154 :    SUBROUTINE atom_int_setup(integrals, basis, potential, &
      62             :                              eri_coulomb, eri_exchange, all_nu)
      63             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
      64             :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
      65             :       TYPE(atom_potential_type), INTENT(IN), OPTIONAL    :: potential
      66             :       LOGICAL, INTENT(IN), OPTIONAL                      :: eri_coulomb, eri_exchange, all_nu
      67             : 
      68             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'atom_int_setup'
      69             : 
      70             :       INTEGER                                            :: handle, i, ii, info, ipiv(1000), l, l1, &
      71             :                                                             l2, ll, lwork, m, m1, m2, mm1, mm2, n, &
      72             :                                                             n1, n2, nn1, nn2, nu, nx
      73             :       REAL(KIND=dp)                                      :: om, rc, ron, sc, x
      74       11154 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cpot, w, work
      75       11154 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: omat, vmat
      76       11154 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: eri
      77             : 
      78       11154 :       CALL timeset(routineN, handle)
      79             : 
      80       11154 :       IF (integrals%status == 0) THEN
      81       78050 :          n = MAXVAL(basis%nbas)
      82       78050 :          integrals%n = basis%nbas
      83             : 
      84       11150 :          IF (PRESENT(eri_coulomb)) THEN
      85       11122 :             integrals%eri_coulomb = eri_coulomb
      86             :          ELSE
      87          28 :             integrals%eri_coulomb = .FALSE.
      88             :          END IF
      89       11150 :          IF (PRESENT(eri_exchange)) THEN
      90       11124 :             integrals%eri_exchange = eri_exchange
      91             :          ELSE
      92          26 :             integrals%eri_exchange = .FALSE.
      93             :          END IF
      94       11150 :          IF (PRESENT(all_nu)) THEN
      95           0 :             integrals%all_nu = all_nu
      96             :          ELSE
      97       11150 :             integrals%all_nu = .FALSE.
      98             :          END IF
      99             : 
     100       11150 :          NULLIFY (integrals%ovlp, integrals%kin, integrals%core, integrals%conf)
     101     1126150 :          DO ll = 1, SIZE(integrals%ceri)
     102     1126150 :             NULLIFY (integrals%ceri(ll)%int, integrals%eeri(ll)%int)
     103             :          END DO
     104             : 
     105       55738 :          ALLOCATE (integrals%ovlp(n, n, 0:lmat))
     106     2683574 :          integrals%ovlp = 0._dp
     107             : 
     108       33438 :          ALLOCATE (integrals%kin(n, n, 0:lmat))
     109     2683574 :          integrals%kin = 0._dp
     110             : 
     111       11150 :          integrals%status = 1
     112             : 
     113       11150 :          IF (PRESENT(potential)) THEN
     114       11122 :             IF (potential%confinement) THEN
     115       25744 :                ALLOCATE (integrals%conf(n, n, 0:lmat))
     116     1060456 :                integrals%conf = 0._dp
     117        8584 :                m = basis%grid%nr
     118       25752 :                ALLOCATE (cpot(1:m))
     119        8584 :                IF (potential%conf_type == poly_conf) THEN
     120        8364 :                   rc = potential%rcon
     121        8364 :                   sc = potential%scon
     122     3351132 :                   cpot(1:m) = (basis%grid%rad(1:m)/rc)**sc
     123         220 :                ELSEIF (potential%conf_type == barrier_conf) THEN
     124         220 :                   om = potential%rcon
     125         220 :                   ron = potential%scon
     126         220 :                   rc = ron + om
     127       88220 :                   DO i = 1, m
     128       88220 :                      IF (basis%grid%rad(i) < ron) THEN
     129       75228 :                         cpot(i) = 0.0_dp
     130       12772 :                      ELSEIF (basis%grid%rad(i) < rc) THEN
     131        5652 :                         x = (basis%grid%rad(i) - ron)/om
     132        5652 :                         x = 1._dp - x
     133        5652 :                         cpot(i) = -6._dp*x**5 + 15._dp*x**4 - 10._dp*x**3 + 1._dp
     134        5652 :                         x = (rc - basis%grid%rad(i))**2/om/(basis%grid%rad(i) - ron)
     135        5652 :                         cpot(i) = cpot(i)*x
     136             :                      ELSE
     137        7120 :                         cpot(i) = 1.0_dp
     138             :                      END IF
     139             :                   END DO
     140             :                ELSE
     141           0 :                   CPABORT("")
     142             :                END IF
     143        8584 :                CALL numpot_matrix(integrals%conf, cpot, basis, 0)
     144        8584 :                DEALLOCATE (cpot)
     145             :             END IF
     146             :          END IF
     147             : 
     148       11150 :          SELECT CASE (basis%basis_type)
     149             :          CASE DEFAULT
     150           0 :             CPABORT("")
     151             :          CASE (GTO_BASIS)
     152        9800 :             DO l = 0, lmat
     153        8400 :                n = integrals%n(l)
     154        8400 :                CALL sg_overlap(integrals%ovlp(1:n, 1:n, l), l, basis%am(1:n, l), basis%am(1:n, l))
     155        9800 :                CALL sg_kinetic(integrals%kin(1:n, 1:n, l), l, basis%am(1:n, l), basis%am(1:n, l))
     156             :             END DO
     157        1400 :             IF (integrals%eri_coulomb) THEN
     158          42 :                ll = 0
     159         294 :                DO l1 = 0, lmat
     160         252 :                   n1 = integrals%n(l1)
     161         252 :                   nn1 = (n1*(n1 + 1))/2
     162        1176 :                   DO l2 = 0, l1
     163         882 :                      n2 = integrals%n(l2)
     164         882 :                      nn2 = (n2*(n2 + 1))/2
     165         882 :                      IF (integrals%all_nu) THEN
     166           0 :                         nx = MIN(2*l1, 2*l2)
     167             :                      ELSE
     168             :                         nx = 0
     169             :                      END IF
     170        2016 :                      DO nu = 0, nx, 2
     171         882 :                         ll = ll + 1
     172         882 :                         CPASSERT(ll <= SIZE(integrals%ceri))
     173        3150 :                         ALLOCATE (integrals%ceri(ll)%int(nn1, nn2))
     174    42697592 :                         integrals%ceri(ll)%int = 0._dp
     175         882 :                         eri => integrals%ceri(ll)%int
     176        1764 :                         CALL sg_coulomb(eri, nu, basis%am(1:n1, l1), l1, basis%am(1:n2, l2), l2)
     177             :                      END DO
     178             :                   END DO
     179             :                END DO
     180             :             END IF
     181        1400 :             IF (integrals%eri_exchange) THEN
     182          22 :                ll = 0
     183         154 :                DO l1 = 0, lmat
     184         132 :                   n1 = integrals%n(l1)
     185         132 :                   nn1 = (n1*(n1 + 1))/2
     186         616 :                   DO l2 = 0, l1
     187         462 :                      n2 = integrals%n(l2)
     188         462 :                      nn2 = (n2*(n2 + 1))/2
     189        1826 :                      DO nu = ABS(l1 - l2), l1 + l2, 2
     190        1232 :                         ll = ll + 1
     191        1232 :                         CPASSERT(ll <= SIZE(integrals%eeri))
     192        4156 :                         ALLOCATE (integrals%eeri(ll)%int(nn1, nn2))
     193    40282236 :                         integrals%eeri(ll)%int = 0._dp
     194        1232 :                         eri => integrals%eeri(ll)%int
     195        1694 :                         CALL sg_exchange(eri, nu, basis%am(1:n1, l1), l1, basis%am(1:n2, l2), l2)
     196             :                      END DO
     197             :                   END DO
     198             :                END DO
     199             :             END IF
     200             :          CASE (CGTO_BASIS)
     201       60340 :             DO l = 0, lmat
     202       51720 :                n = integrals%n(l)
     203       51720 :                m = basis%nprim(l)
     204       60340 :                IF (n > 0 .AND. m > 0) THEN
     205       79204 :                   ALLOCATE (omat(m, m))
     206             : 
     207       19801 :                   CALL sg_overlap(omat(1:m, 1:m), l, basis%am(1:m, l), basis%am(1:m, l))
     208       19801 :                   CALL contract2(integrals%ovlp(1:n, 1:n, l), omat(1:m, 1:m), basis%cm(1:m, 1:n, l))
     209       19801 :                   CALL sg_kinetic(omat(1:m, 1:m), l, basis%am(1:m, l), basis%am(1:m, l))
     210       19801 :                   CALL contract2(integrals%kin(1:n, 1:n, l), omat(1:m, 1:m), basis%cm(1:m, 1:n, l))
     211       19801 :                   DEALLOCATE (omat)
     212             :                END IF
     213             :             END DO
     214        8620 :             IF (integrals%eri_coulomb) THEN
     215          16 :                ll = 0
     216         112 :                DO l1 = 0, lmat
     217          96 :                   n1 = integrals%n(l1)
     218          96 :                   nn1 = (n1*(n1 + 1))/2
     219          96 :                   m1 = basis%nprim(l1)
     220          96 :                   mm1 = (m1*(m1 + 1))/2
     221         448 :                   DO l2 = 0, l1
     222         336 :                      n2 = integrals%n(l2)
     223         336 :                      nn2 = (n2*(n2 + 1))/2
     224         336 :                      m2 = basis%nprim(l2)
     225         336 :                      mm2 = (m2*(m2 + 1))/2
     226         336 :                      IF (integrals%all_nu) THEN
     227           0 :                         nx = MIN(2*l1, 2*l2)
     228             :                      ELSE
     229             :                         nx = 0
     230             :                      END IF
     231         432 :                      DO nu = 0, nx, 2
     232         336 :                         ll = ll + 1
     233         336 :                         CPASSERT(ll <= SIZE(integrals%ceri))
     234         812 :                         ALLOCATE (integrals%ceri(ll)%int(nn1, nn2))
     235         946 :                         integrals%ceri(ll)%int = 0._dp
     236         812 :                         ALLOCATE (omat(mm1, mm2))
     237             : 
     238         336 :                         eri => integrals%ceri(ll)%int
     239         336 :                         CALL sg_coulomb(omat, nu, basis%am(1:m1, l1), l1, basis%am(1:m2, l2), l2)
     240         336 :                         CALL contract4(eri, omat, basis%cm(1:m1, 1:n1, l1), basis%cm(1:m2, 1:n2, l2))
     241             : 
     242         336 :                         DEALLOCATE (omat)
     243             :                      END DO
     244             :                   END DO
     245             :                END DO
     246             :             END IF
     247        8620 :             IF (integrals%eri_exchange) THEN
     248          16 :                ll = 0
     249         112 :                DO l1 = 0, lmat
     250          96 :                   n1 = integrals%n(l1)
     251          96 :                   nn1 = (n1*(n1 + 1))/2
     252          96 :                   m1 = basis%nprim(l1)
     253          96 :                   mm1 = (m1*(m1 + 1))/2
     254         448 :                   DO l2 = 0, l1
     255         336 :                      n2 = integrals%n(l2)
     256         336 :                      nn2 = (n2*(n2 + 1))/2
     257         336 :                      m2 = basis%nprim(l2)
     258         336 :                      mm2 = (m2*(m2 + 1))/2
     259         432 :                      DO nu = ABS(l1 - l2), l1 + l2, 2
     260         896 :                         ll = ll + 1
     261         896 :                         CPASSERT(ll <= SIZE(integrals%eeri))
     262        2032 :                         ALLOCATE (integrals%eeri(ll)%int(nn1, nn2))
     263        3074 :                         integrals%eeri(ll)%int = 0._dp
     264        2032 :                         ALLOCATE (omat(mm1, mm2))
     265             : 
     266         896 :                         eri => integrals%eeri(ll)%int
     267         896 :                         CALL sg_exchange(omat, nu, basis%am(1:m1, l1), l1, basis%am(1:m2, l2), l2)
     268         896 :                         CALL contract4(eri, omat, basis%cm(1:m1, 1:n1, l1), basis%cm(1:m2, 1:n2, l2))
     269             : 
     270         896 :                         DEALLOCATE (omat)
     271             :                      END DO
     272             :                   END DO
     273             :                END DO
     274             :             END IF
     275             :          CASE (STO_BASIS)
     276        7910 :             DO l = 0, lmat
     277        6780 :                n = integrals%n(l)
     278             :                CALL sto_overlap(integrals%ovlp(1:n, 1:n, l), basis%ns(1:n, l), basis%as(1:n, l), &
     279        6780 :                                 basis%ns(1:n, l), basis%as(1:n, l))
     280             :                CALL sto_kinetic(integrals%kin(1:n, 1:n, l), l, basis%ns(1:n, l), basis%as(1:n, l), &
     281        7910 :                                 basis%ns(1:n, l), basis%as(1:n, l))
     282             :             END DO
     283        1130 :             CPASSERT(.NOT. integrals%eri_coulomb)
     284        1130 :             CPASSERT(.NOT. integrals%eri_exchange)
     285             :          CASE (NUM_BASIS)
     286       11150 :             CPABORT("")
     287             :          END SELECT
     288             : 
     289             :          ! setup transformation matrix to get an orthogonal basis, remove linear dependencies
     290       11150 :          NULLIFY (integrals%utrans, integrals%uptrans)
     291       78050 :          n = MAXVAL(basis%nbas)
     292       78026 :          ALLOCATE (integrals%utrans(n, n, 0:lmat), integrals%uptrans(n, n, 0:lmat))
     293     2683574 :          integrals%utrans = 0._dp
     294     2683574 :          integrals%uptrans = 0._dp
     295       78050 :          integrals%nne = integrals%n
     296       11150 :          lwork = 10*n
     297      111464 :          ALLOCATE (omat(n, n), vmat(n, n), w(n), work(lwork))
     298       78050 :          DO l = 0, lmat
     299       66900 :             n = integrals%n(l)
     300       78050 :             IF (n > 0) THEN
     301     1716521 :                omat(1:n, 1:n) = integrals%ovlp(1:n, 1:n, l)
     302       25809 :                CALL jacobi(omat(1:n, 1:n), w(1:n), vmat(1:n, 1:n))
     303     1716521 :                omat(1:n, 1:n) = vmat(1:n, 1:n)
     304       25809 :                ii = 0
     305      124288 :                DO i = 1, n
     306      124288 :                   IF (w(i) > basis%eps_eig) THEN
     307       83449 :                      ii = ii + 1
     308     1102592 :                      integrals%utrans(1:n, ii, l) = omat(1:n, i)/SQRT(w(i))
     309             :                   END IF
     310             :                END DO
     311       25809 :                integrals%nne(l) = ii
     312       25809 :                IF (ii > 0) THEN
     313    15095552 :                   omat(1:ii, 1:ii) = MATMUL(TRANSPOSE(integrals%utrans(1:n, 1:ii, l)), integrals%utrans(1:n, 1:ii, l))
     314      109258 :                   DO i = 1, ii
     315      109258 :                      integrals%uptrans(i, i, l) = 1._dp
     316             :                   END DO
     317     1988641 :                   CALL dgesv(ii, ii, omat(1:ii, 1:ii), ii, ipiv, integrals%uptrans(1:ii, 1:ii, l), ii, info)
     318       25809 :                   CPASSERT(info == 0)
     319             :                END IF
     320             :             END IF
     321             :          END DO
     322       11150 :          DEALLOCATE (omat, vmat, w, work)
     323             :       END IF
     324             : 
     325       11154 :       CALL timestop(handle)
     326             : 
     327       22308 :    END SUBROUTINE atom_int_setup
     328             : 
     329             : ! **************************************************************************************************
     330             : !> \brief ...
     331             : !> \param integrals ...
     332             : !> \param basis ...
     333             : !> \param potential ...
     334             : ! **************************************************************************************************
     335       11484 :    SUBROUTINE atom_ppint_setup(integrals, basis, potential)
     336             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
     337             :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     338             :       TYPE(atom_potential_type), INTENT(IN)              :: potential
     339             : 
     340             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'atom_ppint_setup'
     341             : 
     342             :       INTEGER                                            :: handle, i, ii, j, k, l, m, n
     343             :       REAL(KIND=dp)                                      :: al, alpha, rc
     344       11484 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cpot, xmat
     345       11484 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: omat, spmat
     346       11484 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rad
     347             : 
     348       11484 :       CALL timeset(routineN, handle)
     349             : 
     350       11484 :       IF (integrals%ppstat == 0) THEN
     351       80360 :          n = MAXVAL(basis%nbas)
     352       80360 :          integrals%n = basis%nbas
     353             : 
     354       11480 :          NULLIFY (integrals%core, integrals%hnl)
     355             : 
     356       57388 :          ALLOCATE (integrals%hnl(n, n, 0:lmat))
     357     3441080 :          integrals%hnl = 0._dp
     358             : 
     359       34428 :          ALLOCATE (integrals%core(n, n, 0:lmat))
     360     3441080 :          integrals%core = 0._dp
     361             : 
     362       34428 :          ALLOCATE (integrals%clsd(n, n, 0:lmat))
     363     3441080 :          integrals%clsd = 0._dp
     364             : 
     365       11480 :          integrals%ppstat = 1
     366             : 
     367       11480 :          SELECT CASE (basis%basis_type)
     368             :          CASE DEFAULT
     369           0 :             CPABORT("")
     370             :          CASE (GTO_BASIS)
     371             : 
     372       10426 :             SELECT CASE (potential%ppot_type)
     373             :             CASE (no_pseudo, ecp_pseudo)
     374        1638 :                DO l = 0, lmat
     375        1404 :                   n = integrals%n(l)
     376        1638 :                   CALL sg_nuclear(integrals%core(1:n, 1:n, l), l, basis%am(1:n, l), basis%am(1:n, l))
     377             :                END DO
     378             :             CASE (gth_pseudo)
     379        1336 :                alpha = 1._dp/potential%gth_pot%rc/SQRT(2._dp)
     380        9352 :                DO l = 0, lmat
     381        8016 :                   n = integrals%n(l)
     382       37272 :                   ALLOCATE (omat(n, n), spmat(n, 5))
     383             : 
     384     1045340 :                   omat = 0._dp
     385        8016 :                   CALL sg_erf(omat(1:n, 1:n), l, alpha, basis%am(1:n, l), basis%am(1:n, l))
     386     1045340 :                   integrals%core(1:n, 1:n, l) = -potential%gth_pot%zion*omat(1:n, 1:n)
     387       18720 :                   DO i = 1, potential%gth_pot%ncl
     388     1982092 :                      omat = 0._dp
     389       10704 :                      CALL sg_gpot(omat(1:n, 1:n), i - 1, potential%gth_pot%rc, l, basis%am(1:n, l), basis%am(1:n, l))
     390             :                      integrals%core(1:n, 1:n, l) = integrals%core(1:n, 1:n, l) + &
     391     1990108 :                                                    potential%gth_pot%cl(i)*omat(1:n, 1:n)
     392             :                   END DO
     393        8016 :                   IF (potential%gth_pot%lpotextended) THEN
     394          96 :                      DO k = 1, potential%gth_pot%nexp_lpot
     395         228 :                         DO i = 1, potential%gth_pot%nct_lpot(k)
     396       36036 :                            omat = 0._dp
     397             :                            CALL sg_gpot(omat(1:n, 1:n), i - 1, potential%gth_pot%alpha_lpot(k), l, &
     398         132 :                                         basis%am(1:n, l), basis%am(1:n, l))
     399             :                            integrals%core(1:n, 1:n, l) = integrals%core(1:n, 1:n, l) + &
     400       36096 :                                                          potential%gth_pot%cval_lpot(i, k)*omat(1:n, 1:n)
     401             :                         END DO
     402             :                      END DO
     403             :                   END IF
     404        8016 :                   IF (potential%gth_pot%lsdpot) THEN
     405           0 :                      DO k = 1, potential%gth_pot%nexp_lsd
     406           0 :                         DO i = 1, potential%gth_pot%nct_lsd(k)
     407           0 :                            omat = 0._dp
     408             :                            CALL sg_gpot(omat(1:n, 1:n), i - 1, potential%gth_pot%alpha_lsd(k), l, &
     409           0 :                                         basis%am(1:n, l), basis%am(1:n, l))
     410             :                            integrals%clsd(1:n, 1:n, l) = integrals%clsd(1:n, 1:n, l) + &
     411           0 :                                                          potential%gth_pot%cval_lsd(i, k)*omat(1:n, 1:n)
     412             :                         END DO
     413             :                      END DO
     414             :                   END IF
     415             : 
     416      303096 :                   spmat = 0._dp
     417        8016 :                   m = potential%gth_pot%nl(l)
     418       13844 :                   DO i = 1, m
     419       13844 :                      CALL sg_proj_ol(spmat(1:n, i), l, basis%am(1:n, l), i - 1, potential%gth_pot%rcnl(l))
     420             :                   END DO
     421        8016 :                   integrals%hnl(1:n, 1:n, l) = MATMUL(spmat(1:n, 1:m), &
     422     2355606 :                                                       MATMUL(potential%gth_pot%hnl(1:m, 1:m, l), TRANSPOSE(spmat(1:n, 1:m))))
     423             : 
     424        9352 :                   DEALLOCATE (omat, spmat)
     425             :                END DO
     426             :             CASE (upf_pseudo)
     427           4 :                CALL upfint_setup(integrals, basis, potential)
     428             :             CASE (sgp_pseudo)
     429           0 :                CALL sgpint_setup(integrals, basis, potential)
     430             :             CASE DEFAULT
     431        1574 :                CPABORT("")
     432             :             END SELECT
     433             : 
     434             :          CASE (CGTO_BASIS)
     435             : 
     436       11090 :             SELECT CASE (potential%ppot_type)
     437             :             CASE (no_pseudo, ecp_pseudo)
     438        8288 :                DO l = 0, lmat
     439        7104 :                   n = integrals%n(l)
     440        7104 :                   m = basis%nprim(l)
     441       19596 :                   ALLOCATE (omat(m, m))
     442             : 
     443        7104 :                   CALL sg_nuclear(omat(1:m, 1:m), l, basis%am(1:m, l), basis%am(1:m, l))
     444        7104 :                   CALL contract2(integrals%core(1:n, 1:n, l), omat(1:m, 1:m), basis%cm(1:m, 1:n, l))
     445             : 
     446        8288 :                   DEALLOCATE (omat)
     447             :                END DO
     448             :             CASE (gth_pseudo)
     449        7422 :                alpha = 1._dp/potential%gth_pot%rc/SQRT(2._dp)
     450       51954 :                DO l = 0, lmat
     451       44532 :                   n = integrals%n(l)
     452       44532 :                   m = basis%nprim(l)
     453       51954 :                   IF (n > 0 .AND. m > 0) THEN
     454      136568 :                      ALLOCATE (omat(m, m), spmat(n, 5), xmat(m))
     455             : 
     456      376615 :                      omat = 0._dp
     457       17071 :                      CALL sg_erf(omat(1:m, 1:m), l, alpha, basis%am(1:m, l), basis%am(1:m, l))
     458      376615 :                      omat(1:m, 1:m) = -potential%gth_pot%zion*omat(1:m, 1:m)
     459       17071 :                      CALL contract2(integrals%core(1:n, 1:n, l), omat(1:m, 1:m), basis%cm(1:m, 1:n, l))
     460       49995 :                      DO i = 1, potential%gth_pot%ncl
     461      722396 :                         omat = 0._dp
     462       32924 :                         CALL sg_gpot(omat(1:m, 1:m), i - 1, potential%gth_pot%rc, l, basis%am(1:m, l), basis%am(1:m, l))
     463      722396 :                         omat(1:m, 1:m) = potential%gth_pot%cl(i)*omat(1:m, 1:m)
     464       49995 :                         CALL contract2add(integrals%core(1:n, 1:n, l), omat(1:m, 1:m), basis%cm(1:m, 1:n, l))
     465             :                      END DO
     466       17071 :                      IF (potential%gth_pot%lpotextended) THEN
     467          72 :                         DO k = 1, potential%gth_pot%nexp_lpot
     468         168 :                            DO i = 1, potential%gth_pot%nct_lpot(k)
     469        3128 :                               omat = 0._dp
     470             :                               CALL sg_gpot(omat(1:m, 1:m), i - 1, potential%gth_pot%alpha_lpot(k), l, &
     471          96 :                                            basis%am(1:m, l), basis%am(1:m, l))
     472        3128 :                               omat(1:m, 1:m) = potential%gth_pot%cval_lpot(i, k)*omat(1:m, 1:m)
     473         140 :                               CALL contract2add(integrals%core(1:n, 1:n, l), omat(1:m, 1:m), basis%cm(1:m, 1:n, l))
     474             :                            END DO
     475             :                         END DO
     476             :                      END IF
     477       17071 :                      IF (potential%gth_pot%lsdpot) THEN
     478           0 :                         DO k = 1, potential%gth_pot%nexp_lsd
     479           0 :                            DO i = 1, potential%gth_pot%nct_lsd(k)
     480           0 :                               omat = 0._dp
     481             :                               CALL sg_gpot(omat(1:m, 1:m), i - 1, potential%gth_pot%alpha_lsd(k), l, &
     482           0 :                                            basis%am(1:m, l), basis%am(1:m, l))
     483           0 :                               omat(1:m, 1:m) = potential%gth_pot%cval_lsd(i, k)*omat(1:m, 1:m)
     484           0 :                               CALL contract2add(integrals%clsd(1:n, 1:n, l), omat(1:m, 1:m), basis%cm(1:m, 1:n, l))
     485             :                            END DO
     486             :                         END DO
     487             :                      END IF
     488             : 
     489      243866 :                      spmat = 0._dp
     490       17071 :                      k = potential%gth_pot%nl(l)
     491       22376 :                      DO i = 1, k
     492        5305 :                         CALL sg_proj_ol(xmat(1:m), l, basis%am(1:m, l), i - 1, potential%gth_pot%rcnl(l))
     493       22376 :                         spmat(1:n, i) = MATMUL(TRANSPOSE(basis%cm(1:m, 1:n, l)), xmat(1:m))
     494             :                      END DO
     495       17071 :                      IF (k > 0) THEN
     496        4563 :                         integrals%hnl(1:n, 1:n, l) = MATMUL(spmat(1:n, 1:k), &
     497       18252 :                                                             MATMUL(potential%gth_pot%hnl(1:k, 1:k, l), &
     498      161125 :                                                                    TRANSPOSE(spmat(1:n, 1:k))))
     499             :                      END IF
     500       17071 :                      DEALLOCATE (omat, spmat, xmat)
     501             :                   END IF
     502             :                END DO
     503             :             CASE (upf_pseudo)
     504           0 :                CALL upfint_setup(integrals, basis, potential)
     505             :             CASE (sgp_pseudo)
     506          12 :                CALL sgpint_setup(integrals, basis, potential)
     507             :             CASE DEFAULT
     508        8618 :                CPABORT("")
     509             :             END SELECT
     510             : 
     511             :          CASE (STO_BASIS)
     512             : 
     513        2336 :             SELECT CASE (potential%ppot_type)
     514             :             CASE (no_pseudo, ecp_pseudo)
     515        7336 :                DO l = 0, lmat
     516        6288 :                   n = integrals%n(l)
     517             :                   CALL sto_nuclear(integrals%core(1:n, 1:n, l), basis%ns(1:n, l), basis%as(1:n, l), &
     518        7336 :                                    basis%ns(1:n, l), basis%as(1:n, l))
     519             :                END DO
     520             :             CASE (gth_pseudo)
     521         240 :                rad => basis%grid%rad
     522         240 :                m = basis%grid%nr
     523         720 :                ALLOCATE (cpot(1:m))
     524         240 :                rc = potential%gth_pot%rc
     525         240 :                alpha = 1._dp/rc/SQRT(2._dp)
     526             : 
     527             :                ! local pseudopotential, we use erf = 1/r - erfc
     528        5040 :                integrals%core = 0._dp
     529      102640 :                DO i = 1, m
     530      102640 :                   cpot(i) = potential%gth_pot%zion*erfc(alpha*rad(i))/rad(i)
     531             :                END DO
     532         720 :                DO i = 1, potential%gth_pot%ncl
     533         480 :                   ii = 2*(i - 1)
     534      205520 :                   cpot(1:m) = cpot(1:m) + potential%gth_pot%cl(i)*(rad/rc)**ii*EXP(-0.5_dp*(rad/rc)**2)
     535             :                END DO
     536         240 :                IF (potential%gth_pot%lpotextended) THEN
     537           0 :                   DO k = 1, potential%gth_pot%nexp_lpot
     538           0 :                      al = potential%gth_pot%alpha_lpot(k)
     539           0 :                      DO i = 1, potential%gth_pot%nct_lpot(k)
     540           0 :                         ii = 2*(i - 1)
     541           0 :                         cpot(1:m) = cpot(1:m) + potential%gth_pot%cval_lpot(i, k)*(rad/al)**ii*EXP(-0.5_dp*(rad/al)**2)
     542             :                      END DO
     543             :                   END DO
     544             :                END IF
     545         240 :                CALL numpot_matrix(integrals%core, cpot, basis, 0)
     546        1680 :                DO l = 0, lmat
     547        1440 :                   n = integrals%n(l)
     548        3560 :                   ALLOCATE (omat(n, n))
     549        2280 :                   omat = 0._dp
     550             :                   CALL sto_nuclear(omat(1:n, 1:n), basis%ns(1:n, l), basis%as(1:n, l), &
     551        1440 :                                    basis%ns(1:n, l), basis%as(1:n, l))
     552        2280 :                   integrals%core(1:n, 1:n, l) = integrals%core(1:n, 1:n, l) - potential%gth_pot%zion*omat(1:n, 1:n)
     553        1680 :                   DEALLOCATE (omat)
     554             :                END DO
     555             : 
     556         240 :                IF (potential%gth_pot%lsdpot) THEN
     557           0 :                   cpot = 0._dp
     558           0 :                   DO k = 1, potential%gth_pot%nexp_lsd
     559           0 :                      al = potential%gth_pot%alpha_lsd(k)
     560           0 :                      DO i = 1, potential%gth_pot%nct_lsd(k)
     561           0 :                         ii = 2*(i - 1)
     562           0 :                         cpot(:) = cpot + potential%gth_pot%cval_lsd(i, k)*(rad/al)**ii*EXP(-0.5_dp*(rad/al)**2)
     563             :                      END DO
     564             :                   END DO
     565           0 :                   CALL numpot_matrix(integrals%clsd, cpot, basis, 0)
     566             :                END IF
     567             : 
     568        1680 :                DO l = 0, lmat
     569        1440 :                   n = integrals%n(l)
     570             :                   ! non local pseudopotential
     571        3220 :                   ALLOCATE (spmat(n, 5))
     572       10440 :                   spmat = 0._dp
     573        1440 :                   k = potential%gth_pot%nl(l)
     574        1688 :                   DO i = 1, k
     575         248 :                      rc = potential%gth_pot%rcnl(l)
     576      105848 :                      cpot(:) = sqrt2/SQRT(gamma1(l + 2*i - 1))*rad**(l + 2*i - 2)*EXP(-0.5_dp*(rad/rc)**2)/rc**(l + 2*i - 0.5_dp)
     577        1872 :                      DO j = 1, basis%nbas(l)
     578         432 :                         spmat(j, i) = integrate_grid(cpot, basis%bf(:, j, l), basis%grid)
     579             :                      END DO
     580             :                   END DO
     581        1440 :                   integrals%hnl(1:n, 1:n, l) = MATMUL(spmat(1:n, 1:k), &
     582        3468 :                                                       MATMUL(potential%gth_pot%hnl(1:k, 1:k, l), &
     583        4768 :                                                              TRANSPOSE(spmat(1:n, 1:k))))
     584        1680 :                   DEALLOCATE (spmat)
     585             :                END DO
     586         240 :                DEALLOCATE (cpot)
     587             : 
     588             :             CASE (upf_pseudo)
     589           0 :                CALL upfint_setup(integrals, basis, potential)
     590             :             CASE (sgp_pseudo)
     591           0 :                CALL sgpint_setup(integrals, basis, potential)
     592             :             CASE DEFAULT
     593        1288 :                CPABORT("")
     594             :             END SELECT
     595             : 
     596             :          CASE (NUM_BASIS)
     597       11480 :             CPABORT("")
     598             :          END SELECT
     599             : 
     600             :          ! add ecp_pseudo using numerical representation of basis
     601       11480 :          IF (potential%ppot_type == ecp_pseudo) THEN
     602             :             ! scale 1/r potential
     603       10858 :             integrals%core = -potential%ecp_pot%zion*integrals%core
     604             :             ! local potential
     605          22 :             m = basis%grid%nr
     606          22 :             rad => basis%grid%rad
     607          66 :             ALLOCATE (cpot(1:m))
     608        8822 :             cpot = 0._dp
     609          76 :             DO k = 1, potential%ecp_pot%nloc
     610          54 :                n = potential%ecp_pot%nrloc(k)
     611          54 :                alpha = potential%ecp_pot%bloc(k)
     612       21676 :                cpot(:) = cpot + potential%ecp_pot%aloc(k)*rad**(n - 2)*EXP(-alpha*rad**2)
     613             :             END DO
     614          22 :             CALL numpot_matrix(integrals%core, cpot, basis, 0)
     615             :             ! non local pseudopotential
     616          44 :             DO l = 0, MIN(potential%ecp_pot%lmax, lmat)
     617        8822 :                cpot = 0._dp
     618          52 :                DO k = 1, potential%ecp_pot%npot(l)
     619          30 :                   n = potential%ecp_pot%nrpot(k, l)
     620          30 :                   alpha = potential%ecp_pot%bpot(k, l)
     621       12052 :                   cpot(:) = cpot + potential%ecp_pot%apot(k, l)*rad**(n - 2)*EXP(-alpha*rad**2)
     622             :                END DO
     623         396 :                DO i = 1, basis%nbas(l)
     624        3366 :                   DO j = i, basis%nbas(l)
     625        2992 :                      integrals%hnl(i, j, l) = integrate_grid(cpot, basis%bf(:, i, l), basis%bf(:, j, l), basis%grid)
     626        3344 :                      integrals%hnl(j, i, l) = integrals%hnl(i, j, l)
     627             :                   END DO
     628             :                END DO
     629             :             END DO
     630          22 :             DEALLOCATE (cpot)
     631             :          END IF
     632             : 
     633             :       END IF
     634             : 
     635       11484 :       CALL timestop(handle)
     636             : 
     637       22968 :    END SUBROUTINE atom_ppint_setup
     638             : 
     639             : ! **************************************************************************************************
     640             : !> \brief ...
     641             : !> \param integrals ...
     642             : !> \param basis ...
     643             : !> \param potential ...
     644             : ! **************************************************************************************************
     645           4 :    SUBROUTINE upfint_setup(integrals, basis, potential)
     646             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
     647             :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     648             :       TYPE(atom_potential_type), INTENT(IN)              :: potential
     649             : 
     650             :       CHARACTER(len=4)                                   :: ptype
     651             :       INTEGER                                            :: i, j, k1, k2, la, lb, m, n
     652           4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: spot
     653           4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: spmat
     654             :       TYPE(atom_basis_type)                              :: gbasis
     655             : 
     656             :       ! get basis representation on UPF grid
     657           4 :       CALL atom_basis_gridrep(basis, gbasis, potential%upf_pot%r, potential%upf_pot%rab)
     658             : 
     659             :       ! local pseudopotential
     660        6556 :       integrals%core = 0._dp
     661           4 :       CALL numpot_matrix(integrals%core, potential%upf_pot%vlocal, gbasis, 0)
     662             : 
     663           4 :       ptype = ADJUSTL(TRIM(potential%upf_pot%pseudo_type))
     664           4 :       IF (ptype(1:2) == "NC" .OR. ptype(1:2) == "US") THEN
     665             :          ! non local pseudopotential
     666          14 :          n = MAXVAL(integrals%n(:))
     667           2 :          m = potential%upf_pot%number_of_proj
     668           8 :          ALLOCATE (spmat(n, m))
     669          36 :          spmat = 0.0_dp
     670           4 :          DO i = 1, m
     671           2 :             la = potential%upf_pot%lbeta(i)
     672          36 :             DO j = 1, gbasis%nbas(la)
     673          34 :                spmat(j, i) = integrate_grid(potential%upf_pot%beta(:, i), gbasis%bf(:, j, la), gbasis%grid)
     674             :             END DO
     675             :          END DO
     676           4 :          DO i = 1, m
     677           2 :             la = potential%upf_pot%lbeta(i)
     678           6 :             DO j = 1, m
     679           2 :                lb = potential%upf_pot%lbeta(j)
     680           4 :                IF (la == lb) THEN
     681          34 :                   DO k1 = 1, gbasis%nbas(la)
     682         546 :                      DO k2 = 1, gbasis%nbas(la)
     683             :                         integrals%hnl(k1, k2, la) = integrals%hnl(k1, k2, la) + &
     684         544 :                                                     spmat(k1, i)*potential%upf_pot%dion(i, j)*spmat(k2, j)
     685             :                      END DO
     686             :                   END DO
     687             :                END IF
     688             :             END DO
     689             :          END DO
     690           2 :          DEALLOCATE (spmat)
     691           2 :       ELSE IF (ptype(1:2) == "SL") THEN
     692             :          ! semi local pseudopotential
     693          10 :          DO la = 0, potential%upf_pot%l_max
     694           8 :             IF (la == potential%upf_pot%l_local) CYCLE
     695           6 :             m = SIZE(potential%upf_pot%vsemi(:, la + 1))
     696          18 :             ALLOCATE (spot(m))
     697        2772 :             spot(:) = potential%upf_pot%vsemi(:, la + 1) - potential%upf_pot%vlocal(:)
     698           6 :             n = basis%nbas(la)
     699         102 :             DO i = 1, n
     700         918 :                DO j = i, n
     701             :                   integrals%core(i, j, la) = integrals%core(i, j, la) + &
     702             :                                              integrate_grid(spot(:), &
     703         816 :                                                             gbasis%bf(:, i, la), gbasis%bf(:, j, la), gbasis%grid)
     704         912 :                   integrals%core(j, i, la) = integrals%core(i, j, la)
     705             :                END DO
     706             :             END DO
     707          10 :             DEALLOCATE (spot)
     708             :          END DO
     709             :       ELSE
     710           0 :          CPABORT("Pseudopotential type: ["//ADJUSTL(TRIM(ptype))//"] not known")
     711             :       END IF
     712             : 
     713             :       ! release basis representation on UPF grid
     714           4 :       CALL release_atom_basis(gbasis)
     715             : 
     716          80 :    END SUBROUTINE upfint_setup
     717             : 
     718             : ! **************************************************************************************************
     719             : !> \brief ...
     720             : !> \param integrals ...
     721             : !> \param basis ...
     722             : !> \param potential ...
     723             : ! **************************************************************************************************
     724          12 :    SUBROUTINE sgpint_setup(integrals, basis, potential)
     725             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
     726             :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     727             :       TYPE(atom_potential_type), INTENT(IN)              :: potential
     728             : 
     729             :       INTEGER                                            :: i, ia, j, l, m, n, na
     730             :       REAL(KIND=dp)                                      :: a, c, rc, zval
     731          12 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: cpot, pgauss
     732          12 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: qmat
     733          12 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: rad
     734             : 
     735          12 :       rad => basis%grid%rad
     736          12 :       m = basis%grid%nr
     737             : 
     738             :       ! local pseudopotential
     739        1524 :       integrals%core = 0._dp
     740          36 :       ALLOCATE (cpot(m))
     741        4812 :       cpot = 0.0_dp
     742          12 :       zval = potential%sgp_pot%zion
     743        4812 :       DO i = 1, m
     744        4800 :          rc = rad(i)/potential%sgp_pot%ac_local/SQRT(2.0_dp)
     745        4812 :          cpot(i) = cpot(i) - zval/rad(i)*erf(rc)
     746             :       END DO
     747         156 :       DO i = 1, potential%sgp_pot%n_local
     748       57756 :          cpot(:) = cpot(:) + potential%sgp_pot%c_local(i)*EXP(-potential%sgp_pot%a_local(i)*rad(:)**2)
     749             :       END DO
     750          12 :       CALL numpot_matrix(integrals%core, cpot, basis, 0)
     751          12 :       DEALLOCATE (cpot)
     752             : 
     753             :       ! nonlocal pseudopotential
     754        1524 :       integrals%hnl = 0.0_dp
     755          12 :       IF (potential%sgp_pot%has_nonlocal) THEN
     756          18 :          ALLOCATE (pgauss(1:m))
     757           6 :          n = potential%sgp_pot%n_nonlocal
     758             :          !
     759          12 :          DO l = 0, potential%sgp_pot%lmax
     760           6 :             CPASSERT(l <= UBOUND(basis%nbas, 1))
     761           6 :             IF (.NOT. potential%sgp_pot%is_nonlocal(l)) CYCLE
     762             :             ! overlap (a|p)
     763           6 :             na = basis%nbas(l)
     764          24 :             ALLOCATE (qmat(na, n))
     765          54 :             DO i = 1, n
     766       19248 :                pgauss(:) = 0.0_dp
     767         432 :                DO j = 1, n
     768         384 :                   a = potential%sgp_pot%a_nonlocal(j)
     769         384 :                   c = potential%sgp_pot%c_nonlocal(j, i, l)
     770      154032 :                   pgauss(:) = pgauss(:) + c*EXP(-a*rad(:)**2)*rad(:)**l
     771             :                END DO
     772         246 :                DO ia = 1, na
     773       77040 :                   qmat(ia, i) = SUM(basis%bf(:, ia, l)*pgauss(:)*basis%grid%wr(:))
     774             :                END DO
     775             :             END DO
     776          30 :             DO i = 1, na
     777          90 :                DO j = i, na
     778         540 :                   DO ia = 1, n
     779             :                      integrals%hnl(i, j, l) = integrals%hnl(i, j, l) &
     780         540 :                                               + qmat(i, ia)*qmat(j, ia)*potential%sgp_pot%h_nonlocal(ia, l)
     781             :                   END DO
     782          84 :                   integrals%hnl(j, i, l) = integrals%hnl(i, j, l)
     783             :                END DO
     784             :             END DO
     785          12 :             DEALLOCATE (qmat)
     786             :          END DO
     787           6 :          DEALLOCATE (pgauss)
     788             :       END IF
     789             : 
     790          24 :    END SUBROUTINE sgpint_setup
     791             : 
     792             : ! **************************************************************************************************
     793             : !> \brief ...
     794             : !> \param integrals ...
     795             : !> \param basis ...
     796             : !> \param reltyp ...
     797             : !> \param zcore ...
     798             : !> \param alpha ...
     799             : ! **************************************************************************************************
     800        9908 :    SUBROUTINE atom_relint_setup(integrals, basis, reltyp, zcore, alpha)
     801             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
     802             :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     803             :       INTEGER, INTENT(IN)                                :: reltyp
     804             :       REAL(dp), INTENT(IN)                               :: zcore
     805             :       REAL(dp), INTENT(IN), OPTIONAL                     :: alpha
     806             : 
     807             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'atom_relint_setup'
     808             : 
     809             :       INTEGER                                            :: dkhorder, handle, i, k1, k2, l, m, n, nl
     810             :       REAL(dp)                                           :: ascal
     811        9908 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: cpot
     812        9908 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: modpot
     813        9908 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: ener, sps
     814        9908 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: hmat, pvp, sp, tp, vp, wfn
     815             : 
     816        9908 :       CALL timeset(routineN, handle)
     817             : 
     818        9908 :       SELECT CASE (reltyp)
     819             :       CASE DEFAULT
     820           0 :          CPABORT("")
     821             :       CASE (do_nonrel_atom, do_zoramp_atom, do_sczoramp_atom)
     822        9836 :          dkhorder = -1
     823             :       CASE (do_dkh0_atom)
     824           2 :          dkhorder = 0
     825             :       CASE (do_dkh1_atom)
     826           2 :          dkhorder = 1
     827             :       CASE (do_dkh2_atom)
     828          30 :          dkhorder = 2
     829             :       CASE (do_dkh3_atom)
     830        9908 :          dkhorder = 3
     831             :       END SELECT
     832             : 
     833           0 :       SELECT CASE (reltyp)
     834             :       CASE DEFAULT
     835           0 :          CPABORT("")
     836             :       CASE (do_nonrel_atom)
     837             :          ! nothing to do
     838        9808 :          NULLIFY (integrals%tzora, integrals%hdkh)
     839             :       CASE (do_zoramp_atom, do_sczoramp_atom)
     840             : 
     841          28 :          NULLIFY (integrals%hdkh)
     842             : 
     843          28 :          IF (integrals%zorastat == 0) THEN
     844         196 :             n = MAXVAL(basis%nbas)
     845         140 :             ALLOCATE (integrals%tzora(n, n, 0:lmat))
     846      133636 :             integrals%tzora = 0._dp
     847          28 :             m = basis%grid%nr
     848         112 :             ALLOCATE (modpot(1:m), cpot(1:m))
     849          28 :             CALL calculate_model_potential(modpot, basis%grid, zcore)
     850             :             ! Zora potential
     851       11228 :             cpot(1:m) = modpot(1:m)/(4._dp*c_light_au*c_light_au - 2._dp*modpot(1:m))
     852       11228 :             cpot(1:m) = cpot(1:m)/basis%grid%rad2(1:m)
     853          28 :             CALL numpot_matrix(integrals%tzora, cpot, basis, 0)
     854         196 :             DO l = 0, lmat
     855         168 :                nl = basis%nbas(l)
     856      123660 :                integrals%tzora(1:nl, 1:nl, l) = REAL(l*(l + 1), dp)*integrals%tzora(1:nl, 1:nl, l)
     857             :             END DO
     858       11228 :             cpot(1:m) = cpot(1:m)*basis%grid%rad2(1:m)
     859          28 :             CALL numpot_matrix(integrals%tzora, cpot, basis, 2)
     860             :             !
     861             :             ! scaled ZORA
     862          28 :             IF (reltyp == do_sczoramp_atom) THEN
     863         168 :                ALLOCATE (hmat(n, n, 0:lmat), wfn(n, n, 0:lmat), ener(n, 0:lmat), pvp(n, n, 0:lmat), sps(n, n))
     864       31946 :                hmat(:, :, :) = integrals%kin + integrals%tzora
     865             :                ! model potential
     866          14 :                CALL numpot_matrix(hmat, modpot, basis, 0)
     867             :                ! eigenvalues and eigenvectors
     868          14 :                CALL atom_solve(hmat, integrals%utrans, wfn, ener, basis%nbas, integrals%nne, lmat)
     869             :                ! relativistic kinetic energy
     870        5614 :                cpot(1:m) = c_light_au*c_light_au/(2._dp*c_light_au*c_light_au - modpot(1:m))**2
     871        5614 :                cpot(1:m) = cpot(1:m)/basis%grid%rad2(1:m)
     872       31946 :                pvp = 0.0_dp
     873          14 :                CALL numpot_matrix(pvp, cpot, basis, 0)
     874          98 :                DO l = 0, lmat
     875          84 :                   nl = basis%nbas(l)
     876       24010 :                   pvp(1:nl, 1:nl, l) = REAL(l*(l + 1), dp)*pvp(1:nl, 1:nl, l)
     877             :                END DO
     878        5614 :                cpot(1:m) = cpot(1:m)*basis%grid%rad2(1:m)
     879          14 :                CALL numpot_matrix(pvp, cpot, basis, 2)
     880             :                ! calculate psi*pvp*psi and the scaled orbital energies
     881             :                ! actually, we directly calculate the energy difference
     882          98 :                DO l = 0, lmat
     883          84 :                   nl = basis%nbas(l)
     884         578 :                   DO i = 1, integrals%nne(l)
     885         564 :                      IF (ener(i, l) < 0._dp) THEN
     886       21276 :                         ascal = SUM(wfn(1:nl, i, l)*MATMUL(pvp(1:nl, 1:nl, l), wfn(1:nl, i, l)))
     887          28 :                         ener(i, l) = ener(i, l)*ascal/(1.0_dp + ascal)
     888             :                      ELSE
     889         452 :                         ener(i, l) = 0.0_dp
     890             :                      END IF
     891             :                   END DO
     892             :                END DO
     893             :                ! correction term is calculated as a projector
     894       31946 :                hmat = 0.0_dp
     895          98 :                DO l = 0, lmat
     896          84 :                   nl = basis%nbas(l)
     897         564 :                   DO i = 1, integrals%nne(l)
     898       14238 :                      DO k1 = 1, nl
     899      494628 :                         DO k2 = 1, nl
     900      494148 :                            hmat(k1, k2, l) = hmat(k1, k2, l) + ener(i, l)*wfn(k1, i, l)*wfn(k2, i, l)
     901             :                         END DO
     902             :                      END DO
     903             :                   END DO
     904             :                   ! transform with overlap matrix
     905          84 :                   sps(1:nl, 1:nl) = MATMUL(integrals%ovlp(1:nl, 1:nl, l), &
     906      410216 :                                            MATMUL(hmat(1:nl, 1:nl, l), integrals%ovlp(1:nl, 1:nl, l)))
     907             :                   ! add scaling correction to tzora
     908       24010 :                   integrals%tzora(1:nl, 1:nl, l) = integrals%tzora(1:nl, 1:nl, l) - sps(1:nl, 1:nl)
     909             :                END DO
     910             : 
     911          14 :                DEALLOCATE (hmat, wfn, ener, pvp, sps)
     912             :             END IF
     913             :             !
     914          28 :             DEALLOCATE (modpot, cpot)
     915             : 
     916          28 :             integrals%zorastat = 1
     917             : 
     918             :          END IF
     919             : 
     920             :       CASE (do_dkh0_atom, do_dkh1_atom, do_dkh2_atom, do_dkh3_atom)
     921             : 
     922          72 :          NULLIFY (integrals%tzora)
     923             : 
     924        9908 :          IF (integrals%dkhstat == 0) THEN
     925         504 :             n = MAXVAL(basis%nbas)
     926         360 :             ALLOCATE (integrals%hdkh(n, n, 0:lmat))
     927      321120 :             integrals%hdkh = 0._dp
     928             : 
     929         504 :             m = MAXVAL(basis%nprim)
     930         792 :             ALLOCATE (tp(m, m, 0:lmat), sp(m, m, 0:lmat), vp(m, m, 0:lmat), pvp(m, m, 0:lmat))
     931      334608 :             tp = 0._dp
     932      334608 :             sp = 0._dp
     933      334608 :             vp = 0._dp
     934      334608 :             pvp = 0._dp
     935             : 
     936          72 :             SELECT CASE (basis%basis_type)
     937             :             CASE DEFAULT
     938           0 :                CPABORT("")
     939             :             CASE (GTO_BASIS, CGTO_BASIS)
     940             : 
     941         504 :                DO l = 0, lmat
     942         432 :                   m = basis%nprim(l)
     943         504 :                   IF (m > 0) THEN
     944         272 :                      CALL sg_kinetic(tp(1:m, 1:m, l), l, basis%am(1:m, l), basis%am(1:m, l))
     945         272 :                      CALL sg_overlap(sp(1:m, 1:m, l), l, basis%am(1:m, l), basis%am(1:m, l))
     946         272 :                      IF (PRESENT(alpha)) THEN
     947          36 :                         CALL sg_erfc(vp(1:m, 1:m, l), l, alpha, basis%am(1:m, l), basis%am(1:m, l))
     948             :                      ELSE
     949         236 :                         CALL sg_nuclear(vp(1:m, 1:m, l), l, basis%am(1:m, l), basis%am(1:m, l))
     950             :                      END IF
     951         272 :                      CALL sg_kinnuc(pvp(1:m, 1:m, l), l, basis%am(1:m, l), basis%am(1:m, l))
     952      223656 :                      vp(1:m, 1:m, l) = -zcore*vp(1:m, 1:m, l)
     953      223656 :                      pvp(1:m, 1:m, l) = -zcore*pvp(1:m, 1:m, l)
     954             :                   END IF
     955             :                END DO
     956             : 
     957             :             CASE (STO_BASIS)
     958           0 :                CPABORT("")
     959             :             CASE (NUM_BASIS)
     960          72 :                CPABORT("")
     961             :             END SELECT
     962             : 
     963          72 :             CALL dkh_integrals(integrals, basis, dkhorder, sp, tp, vp, pvp)
     964             : 
     965          72 :             integrals%dkhstat = 1
     966             : 
     967          72 :             DEALLOCATE (tp, sp, vp, pvp)
     968             : 
     969             :          ELSE
     970           0 :             CPASSERT(ASSOCIATED(integrals%hdkh))
     971             :          END IF
     972             : 
     973             :       END SELECT
     974             : 
     975        9908 :       CALL timestop(handle)
     976             : 
     977        9908 :    END SUBROUTINE atom_relint_setup
     978             : 
     979             : ! **************************************************************************************************
     980             : !> \brief ...
     981             : !> \param integrals ...
     982             : !> \param basis ...
     983             : !> \param order ...
     984             : !> \param sp ...
     985             : !> \param tp ...
     986             : !> \param vp ...
     987             : !> \param pvp ...
     988             : ! **************************************************************************************************
     989          72 :    SUBROUTINE dkh_integrals(integrals, basis, order, sp, tp, vp, pvp)
     990             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
     991             :       TYPE(atom_basis_type), INTENT(INOUT)               :: basis
     992             :       INTEGER, INTENT(IN)                                :: order
     993             :       REAL(dp), DIMENSION(:, :, 0:)                      :: sp, tp, vp, pvp
     994             : 
     995             :       INTEGER                                            :: l, m, n
     996          72 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: hdkh
     997             : 
     998           0 :       CPASSERT(order >= 0)
     999             : 
    1000          72 :       hdkh => integrals%hdkh
    1001             : 
    1002         504 :       DO l = 0, lmat
    1003         432 :          n = integrals%n(l)
    1004         432 :          m = basis%nprim(l)
    1005         504 :          IF (n > 0) THEN
    1006         272 :             CALL dkh_atom_transformation(sp(1:m, 1:m, l), vp(1:m, 1:m, l), tp(1:m, 1:m, l), pvp(1:m, 1:m, l), m, order)
    1007         272 :             SELECT CASE (basis%basis_type)
    1008             :             CASE DEFAULT
    1009           0 :                CPABORT("")
    1010             :             CASE (GTO_BASIS)
    1011         222 :                CPASSERT(n == m)
    1012      219890 :                integrals%hdkh(1:n, 1:n, l) = tp(1:n, 1:n, l) + vp(1:n, 1:n, l)
    1013             :             CASE (CGTO_BASIS)
    1014          50 :                CALL contract2(integrals%hdkh(1:n, 1:n, l), tp(1:m, 1:m, l), basis%cm(1:m, 1:n, l))
    1015          50 :                CALL contract2add(integrals%hdkh(1:n, 1:n, l), vp(1:m, 1:m, l), basis%cm(1:m, 1:n, l))
    1016             :             CASE (STO_BASIS)
    1017           0 :                CPABORT("")
    1018             :             CASE (NUM_BASIS)
    1019         272 :                CPABORT("")
    1020             :             END SELECT
    1021             :          ELSE
    1022         160 :             integrals%hdkh(1:n, 1:n, l) = 0._dp
    1023             :          END IF
    1024             :       END DO
    1025             : 
    1026          72 :    END SUBROUTINE dkh_integrals
    1027             : 
    1028             : ! **************************************************************************************************
    1029             : !> \brief Calculate overlap matrix between two atomic basis sets.
    1030             : !> \param ovlap    overlap matrix <chi_{a,l} | chi_{b,l}>
    1031             : !> \param basis_a  first basis set
    1032             : !> \param basis_b  second basis set
    1033             : ! **************************************************************************************************
    1034           1 :    SUBROUTINE atom_basis_projection_overlap(ovlap, basis_a, basis_b)
    1035             :       REAL(KIND=dp), DIMENSION(:, :, 0:), INTENT(OUT)    :: ovlap
    1036             :       TYPE(atom_basis_type), INTENT(IN)                  :: basis_a, basis_b
    1037             : 
    1038             :       INTEGER                                            :: i, j, l, ma, mb, na, nb
    1039             :       LOGICAL                                            :: ebas
    1040           1 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: omat
    1041             : 
    1042           1 :       ebas = (basis_a%basis_type == basis_b%basis_type)
    1043             : 
    1044         127 :       ovlap = 0.0_dp
    1045             : 
    1046           1 :       IF (ebas) THEN
    1047           0 :          SELECT CASE (basis_a%basis_type)
    1048             :          CASE DEFAULT
    1049           0 :             CPABORT("")
    1050             :          CASE (GTO_BASIS)
    1051           0 :             DO l = 0, lmat
    1052           0 :                na = basis_a%nbas(l)
    1053           0 :                nb = basis_b%nbas(l)
    1054           0 :                CALL sg_overlap(ovlap(1:na, 1:nb, l), l, basis_a%am(1:na, l), basis_b%am(1:nb, l))
    1055             :             END DO
    1056             :          CASE (CGTO_BASIS)
    1057           7 :             DO l = 0, lmat
    1058           6 :                na = basis_a%nbas(l)
    1059           6 :                nb = basis_b%nbas(l)
    1060           6 :                ma = basis_a%nprim(l)
    1061           6 :                mb = basis_b%nprim(l)
    1062          18 :                ALLOCATE (omat(ma, mb))
    1063           6 :                CALL sg_overlap(omat(1:ma, 1:mb), l, basis_a%am(1:ma, l), basis_b%am(1:mb, l))
    1064           6 :                ovlap(1:na, 1:nb, l) = MATMUL(TRANSPOSE(basis_a%cm(1:ma, 1:na, l)), &
    1065        1277 :                                              MATMUL(omat(1:ma, 1:mb), basis_b%cm(1:mb, 1:nb, l)))
    1066           7 :                DEALLOCATE (omat)
    1067             :             END DO
    1068             :          CASE (STO_BASIS)
    1069           0 :             DO l = 0, lmat
    1070           0 :                na = basis_a%nbas(l)
    1071           0 :                nb = basis_b%nbas(l)
    1072             :                CALL sto_overlap(ovlap(1:na, 1:nb, l), basis_a%ns(1:na, l), basis_b%as(1:nb, l), &
    1073           0 :                                 basis_a%ns(1:na, l), basis_b%as(1:nb, l))
    1074             :             END DO
    1075             :          CASE (NUM_BASIS)
    1076           0 :             CPASSERT(atom_compare_grids(basis_a%grid, basis_b%grid))
    1077           1 :             DO l = 0, lmat
    1078           0 :                na = basis_a%nbas(l)
    1079           0 :                nb = basis_b%nbas(l)
    1080           0 :                DO j = 1, nb
    1081           0 :                   DO i = 1, na
    1082           0 :                      ovlap(i, j, l) = integrate_grid(basis_a%bf(:, i, l), basis_b%bf(:, j, l), basis_a%grid)
    1083             :                   END DO
    1084             :                END DO
    1085             :             END DO
    1086             :          END SELECT
    1087             :       ELSE
    1088           0 :          CPASSERT(atom_compare_grids(basis_a%grid, basis_b%grid))
    1089           0 :          DO l = 0, lmat
    1090           0 :             na = basis_a%nbas(l)
    1091           0 :             nb = basis_b%nbas(l)
    1092           0 :             DO j = 1, nb
    1093           0 :                DO i = 1, na
    1094           0 :                   ovlap(i, j, l) = integrate_grid(basis_a%bf(:, i, l), basis_b%bf(:, j, l), basis_a%grid)
    1095             :                END DO
    1096             :             END DO
    1097             :          END DO
    1098             :       END IF
    1099             : 
    1100           1 :    END SUBROUTINE atom_basis_projection_overlap
    1101             : 
    1102             : ! **************************************************************************************************
    1103             : !> \brief Release memory allocated for atomic integrals (valence electrons).
    1104             : !> \param integrals  atomic integrals
    1105             : ! **************************************************************************************************
    1106       11150 :    SUBROUTINE atom_int_release(integrals)
    1107             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
    1108             : 
    1109             :       INTEGER                                            :: ll
    1110             : 
    1111       11150 :       IF (ASSOCIATED(integrals%ovlp)) THEN
    1112       11150 :          DEALLOCATE (integrals%ovlp)
    1113             :       END IF
    1114       11150 :       IF (ASSOCIATED(integrals%kin)) THEN
    1115       11150 :          DEALLOCATE (integrals%kin)
    1116             :       END IF
    1117       11150 :       IF (ASSOCIATED(integrals%conf)) THEN
    1118        8584 :          DEALLOCATE (integrals%conf)
    1119             :       END IF
    1120     1126150 :       DO ll = 1, SIZE(integrals%ceri)
    1121     1115000 :          IF (ASSOCIATED(integrals%ceri(ll)%int)) THEN
    1122        1218 :             DEALLOCATE (integrals%ceri(ll)%int)
    1123             :          END IF
    1124     1126150 :          IF (ASSOCIATED(integrals%eeri(ll)%int)) THEN
    1125        2128 :             DEALLOCATE (integrals%eeri(ll)%int)
    1126             :          END IF
    1127             :       END DO
    1128       11150 :       IF (ASSOCIATED(integrals%utrans)) THEN
    1129       11150 :          DEALLOCATE (integrals%utrans)
    1130             :       END IF
    1131       11150 :       IF (ASSOCIATED(integrals%uptrans)) THEN
    1132       11150 :          DEALLOCATE (integrals%uptrans)
    1133             :       END IF
    1134             : 
    1135       11150 :       integrals%status = 0
    1136             : 
    1137       11150 :    END SUBROUTINE atom_int_release
    1138             : 
    1139             : ! **************************************************************************************************
    1140             : !> \brief Release memory allocated for atomic integrals (core electrons).
    1141             : !> \param integrals  atomic integrals
    1142             : ! **************************************************************************************************
    1143       11480 :    SUBROUTINE atom_ppint_release(integrals)
    1144             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
    1145             : 
    1146       11480 :       IF (ASSOCIATED(integrals%hnl)) THEN
    1147       11480 :          DEALLOCATE (integrals%hnl)
    1148             :       END IF
    1149       11480 :       IF (ASSOCIATED(integrals%core)) THEN
    1150       11480 :          DEALLOCATE (integrals%core)
    1151             :       END IF
    1152       11480 :       IF (ASSOCIATED(integrals%clsd)) THEN
    1153       11480 :          DEALLOCATE (integrals%clsd)
    1154             :       END IF
    1155             : 
    1156       11480 :       integrals%ppstat = 0
    1157             : 
    1158       11480 :    END SUBROUTINE atom_ppint_release
    1159             : 
    1160             : ! **************************************************************************************************
    1161             : !> \brief  Release memory allocated for atomic integrals (relativistic effects).
    1162             : !> \param integrals atomic integrals
    1163             : ! **************************************************************************************************
    1164       11148 :    SUBROUTINE atom_relint_release(integrals)
    1165             :       TYPE(atom_integrals), INTENT(INOUT)                :: integrals
    1166             : 
    1167       11148 :       IF (ASSOCIATED(integrals%tzora)) THEN
    1168          28 :          DEALLOCATE (integrals%tzora)
    1169             :       END IF
    1170       11148 :       IF (ASSOCIATED(integrals%hdkh)) THEN
    1171          72 :          DEALLOCATE (integrals%hdkh)
    1172             :       END IF
    1173             : 
    1174       11148 :       integrals%zorastat = 0
    1175       11148 :       integrals%dkhstat = 0
    1176             : 
    1177       11148 :    END SUBROUTINE atom_relint_release
    1178             : 
    1179             : ! **************************************************************************************************
    1180             : !> \brief Calculate model potential. It is useful to guess atomic orbitals.
    1181             : !> \param modpot  model potential
    1182             : !> \param grid    atomic radial grid
    1183             : !> \param zcore   nuclear charge
    1184             : ! **************************************************************************************************
    1185          72 :    SUBROUTINE calculate_model_potential(modpot, grid, zcore)
    1186             :       REAL(dp), DIMENSION(:), INTENT(INOUT)              :: modpot
    1187             :       TYPE(grid_atom_type), INTENT(IN)                   :: grid
    1188             :       REAL(dp), INTENT(IN)                               :: zcore
    1189             : 
    1190             :       INTEGER                                            :: i, ii, l, ll, n, z
    1191          72 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: pot, rho
    1192             :       TYPE(atom_state)                                   :: state
    1193             : 
    1194          72 :       n = SIZE(modpot)
    1195         288 :       ALLOCATE (rho(n), pot(n))
    1196             : 
    1197             :       ! fill default occupation
    1198        5112 :       state%core = 0._dp
    1199        5112 :       state%occ = 0._dp
    1200          72 :       state%multiplicity = -1
    1201          72 :       z = NINT(zcore)
    1202         360 :       DO l = 0, MIN(lmat, UBOUND(ptable(z)%e_conv, 1))
    1203         360 :          IF (ptable(z)%e_conv(l) /= 0) THEN
    1204         156 :             state%maxl_occ = l
    1205         156 :             ll = 2*(2*l + 1)
    1206         360 :             DO i = 1, SIZE(state%occ, 2)
    1207         360 :                ii = ptable(z)%e_conv(l) - (i - 1)*ll
    1208         360 :                IF (ii <= ll) THEN
    1209         156 :                   state%occ(l, i) = ii
    1210         156 :                   EXIT
    1211             :                ELSE
    1212         204 :                   state%occ(l, i) = ll
    1213             :                END IF
    1214             :             END DO
    1215             :          END IF
    1216             :       END DO
    1217             : 
    1218       13410 :       modpot = -zcore/grid%rad(:)
    1219             : 
    1220             :       ! Coulomb potential
    1221          72 :       CALL slater_density(rho, pot, NINT(zcore), state, grid)
    1222          72 :       CALL coulomb_potential_numeric(pot, rho, grid)
    1223       13410 :       modpot = modpot + pot
    1224             : 
    1225             :       ! XC potential
    1226          72 :       CALL wigner_slater_functional(rho, pot)
    1227       13410 :       modpot = modpot + pot
    1228             : 
    1229          72 :       DEALLOCATE (rho, pot)
    1230             : 
    1231       26136 :    END SUBROUTINE calculate_model_potential
    1232             : 
    1233       14137 : END MODULE atom_operators

Generated by: LCOV version 1.15