LCOV - code coverage report
Current view: top level - src - qs_vxc_atom_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 95.3 % 408 389
Test Date: 2026-09-24 01:27:39 Functions: 84.6 % 13 11

            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 Support routines for integrals of the Vxc/Fxc/Gxc potentials calculated
      10              : !>      for the atomic density in the basis set of spherical primitives
      11              : ! **************************************************************************************************
      12              : MODULE qs_vxc_atom_utils
      13              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      14              :                                               gto_basis_set_type
      15              :    USE external_potential_types,        ONLY: get_potential,&
      16              :                                               gth_potential_type,&
      17              :                                               sgp_potential_type
      18              :    USE kinds,                           ONLY: dp
      19              :    USE mathconstants,                   ONLY: fac
      20              :    USE orbital_pointers,                ONLY: indso,&
      21              :                                               nsoset
      22              :    USE paw_basis_types,                 ONLY: get_paw_basis_info
      23              :    USE qs_grid_atom,                    ONLY: grid_atom_type
      24              :    USE qs_harmonics_atom,               ONLY: get_none0_cg_list,&
      25              :                                               harmonics_atom_type
      26              :    USE qs_kind_types,                   ONLY: has_nlcc
      27              :    USE qs_rho_atom_types,               ONLY: rho_atom_coeff,&
      28              :                                               rho_atom_type
      29              : #include "./base/base_uses.f90"
      30              : 
      31              :    IMPLICIT NONE
      32              : 
      33              :    PRIVATE
      34              : 
      35              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_vxc_atom_utils'
      36              : 
      37              :    TYPE tau_basis_cache_type
      38              :       INTEGER                                            :: maxso = 0, na = 0, nr = 0, nsatbas = 0, &
      39              :                                                             nset = 0
      40              :       INTEGER, DIMENSION(:), POINTER                     :: lmax => NULL(), lmin => NULL(), &
      41              :                                                             n2oindex => NULL(), npgf => NULL(), &
      42              :                                                             o2nindex => NULL()
      43              :       REAL(dp), DIMENSION(:, :), POINTER                 :: zet => NULL()
      44              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: grad
      45              :    END TYPE tau_basis_cache_type
      46              : 
      47              :    PUBLIC :: evaluate_nlcc_primitive_fields, gapw_atom_grid_support_radius, &
      48              :              create_tau_basis_cache, release_tau_basis_cache, &
      49              :              calc_rho_angular, calc_tau_atom, calc_rho_nlcc, &
      50              :              gaVxcgb_noGC, gaVxcgb_GC, dgaVtaudgb
      51              :    PUBLIC :: tau_basis_cache_type
      52              :    PUBLIC :: calc_weight_function
      53              : 
      54              : ! **************************************************************************************************
      55              : 
      56              : CONTAINS
      57              : 
      58              : ! **************************************************************************************************
      59              : !> \brief Evaluate an NLCC density and its first two Cartesian derivatives.
      60              : !> \param point evaluation point
      61              : !> \param center pseudopotential center
      62              : !> \param gth_potential optional GTH potential
      63              : !> \param sgp_potential optional separable Gaussian potential
      64              : !> \param rho core density
      65              : !> \param gradient Cartesian density gradient
      66              : !> \param hessian Cartesian density Hessian
      67              : ! **************************************************************************************************
      68       112500 :    SUBROUTINE evaluate_nlcc_primitive_fields(point, center, gth_potential, sgp_potential, &
      69              :                                              rho, gradient, hessian)
      70              :       REAL(dp), DIMENSION(3), INTENT(IN)                 :: point, center
      71              :       TYPE(gth_potential_type), INTENT(IN), POINTER      :: gth_potential
      72              :       TYPE(sgp_potential_type), INTENT(IN), POINTER      :: sgp_potential
      73              :       REAL(dp), INTENT(OUT)                              :: rho
      74              :       REAL(dp), DIMENSION(3), INTENT(OUT)                :: gradient
      75              :       REAL(dp), DIMENSION(3, 3), INTENT(OUT)             :: hessian
      76              : 
      77              :       INTEGER                                            :: ic, idir, iexp, jdir, n_nlcc, nexp_nlcc, &
      78              :                                                             power
      79       112500 :       INTEGER, DIMENSION(:), POINTER                     :: nct_nlcc
      80              :       LOGICAL                                            :: has_sgp_nlcc, nlcc_present
      81              :       REAL(dp)                                           :: alpha, beta, d2poly, dpoly, exponential, &
      82              :                                                             poly, r2, rho_x, rho_xx, scaled_r2
      83              :       REAL(dp), DIMENSION(3)                             :: displacement
      84       112500 :       REAL(dp), DIMENSION(:), POINTER                    :: a_nlcc, alpha_nlcc, c_nlcc
      85       112500 :       REAL(dp), DIMENSION(:, :), POINTER                 :: cval_nlcc
      86              : 
      87       112500 :       NULLIFY (a_nlcc, alpha_nlcc, c_nlcc, cval_nlcc, nct_nlcc)
      88       112500 :       rho = 0.0_dp
      89       112500 :       rho_x = 0.0_dp
      90       112500 :       rho_xx = 0.0_dp
      91       450000 :       displacement = point - center
      92       450000 :       r2 = DOT_PRODUCT(displacement, displacement)
      93              : 
      94       112500 :       IF (ASSOCIATED(gth_potential)) THEN
      95              :          CALL get_potential(gth_potential, nlcc_present=nlcc_present, &
      96              :                             nexp_nlcc=nexp_nlcc, alpha_nlcc=alpha_nlcc, &
      97       112500 :                             nct_nlcc=nct_nlcc, cval_nlcc=cval_nlcc)
      98       112500 :          IF (nlcc_present) THEN
      99       105000 :             DO iexp = 1, nexp_nlcc
     100        52500 :                alpha = alpha_nlcc(iexp)
     101        52500 :                beta = 0.5_dp/(alpha*alpha)
     102        52500 :                scaled_r2 = r2/(alpha*alpha)
     103        52500 :                exponential = EXP(-0.5_dp*scaled_r2)
     104       157500 :                DO ic = 1, nct_nlcc(iexp)
     105        52500 :                   power = ic - 1
     106        52500 :                   poly = cval_nlcc(ic, iexp)*scaled_r2**power
     107        52500 :                   dpoly = 0.0_dp
     108        52500 :                   IF (power > 0) THEN
     109              :                      dpoly = cval_nlcc(ic, iexp)*REAL(power, dp)* &
     110            0 :                              scaled_r2**(power - 1)/(alpha*alpha)
     111              :                   END IF
     112            0 :                   d2poly = 0.0_dp
     113            0 :                   IF (power > 1) THEN
     114              :                      d2poly = cval_nlcc(ic, iexp)*REAL(power*(power - 1), dp)* &
     115            0 :                               scaled_r2**(power - 2)/(alpha**4)
     116              :                   END IF
     117        52500 :                   rho = rho + exponential*poly
     118        52500 :                   rho_x = rho_x + exponential*(dpoly - beta*poly)
     119       105000 :                   rho_xx = rho_xx + exponential*(d2poly - 2.0_dp*beta*dpoly + beta*beta*poly)
     120              :                END DO
     121              :             END DO
     122              :          END IF
     123            0 :       ELSE IF (ASSOCIATED(sgp_potential)) THEN
     124              :          CALL get_potential(sgp_potential, has_nlcc=has_sgp_nlcc, n_nlcc=n_nlcc, &
     125            0 :                             a_nlcc=a_nlcc, c_nlcc=c_nlcc)
     126            0 :          IF (has_sgp_nlcc) THEN
     127            0 :             DO iexp = 1, n_nlcc
     128            0 :                exponential = EXP(-a_nlcc(iexp)*r2)
     129            0 :                rho = rho + c_nlcc(iexp)*exponential
     130            0 :                rho_x = rho_x - a_nlcc(iexp)*c_nlcc(iexp)*exponential
     131            0 :                rho_xx = rho_xx + a_nlcc(iexp)**2*c_nlcc(iexp)*exponential
     132              :             END DO
     133              :          END IF
     134              :       END IF
     135              : 
     136       450000 :       gradient = 2.0_dp*rho_x*displacement
     137       450000 :       DO idir = 1, 3
     138      1350000 :          DO jdir = 1, 3
     139      1350000 :             hessian(idir, jdir) = 4.0_dp*rho_xx*displacement(idir)*displacement(jdir)
     140              :          END DO
     141       450000 :          hessian(idir, idir) = hessian(idir, idir) + 2.0_dp*rho_x
     142              :       END DO
     143       112500 :    END SUBROUTINE evaluate_nlcc_primitive_fields
     144              : 
     145              : ! **************************************************************************************************
     146              : !> \brief Compact support radius of one hard-minus-soft atom-grid field.
     147              : !> \param grid_atom radial and angular source grid
     148              : !> \param rho_h hard one-center density values
     149              : !> \param rho_s soft one-center density values
     150              : !> \param drho_h hard one-center density-gradient values
     151              : !> \param drho_s soft one-center density-gradient values
     152              : !> \param tau_h hard one-center kinetic-energy-density values
     153              : !> \param tau_s soft one-center kinetic-energy-density values
     154              : !> \return outermost radius required by any primitive hard-minus-soft field
     155              : ! **************************************************************************************************
     156          574 :    FUNCTION gapw_atom_grid_support_radius( &
     157          574 :       grid_atom, rho_h, rho_s, drho_h, drho_s, tau_h, tau_s) RESULT(cutoff)
     158              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
     159              :       REAL(dp), DIMENSION(:, :, :), INTENT(IN)           :: rho_h, rho_s
     160              :       REAL(dp), DIMENSION(:, :, :, :), INTENT(IN)        :: drho_h, drho_s
     161              :       REAL(dp), DIMENSION(:, :, :), INTENT(IN)           :: tau_h, tau_s
     162              :       REAL(dp)                                           :: cutoff
     163              : 
     164              :       INTEGER                                            :: ir, support_ir
     165              :       LOGICAL                                            :: descending
     166              :       REAL(dp)                                           :: amplitude
     167              : 
     168          574 :       cutoff = 0.0_dp
     169          574 :       descending = grid_atom%rad(1) > grid_atom%rad(grid_atom%nr)
     170          574 :       IF (descending) THEN
     171         8232 :          DO ir = 1, grid_atom%nr
     172              :             amplitude = MAX( &
     173              :                         MAXVAL(ABS(rho_h(:, ir, :) - rho_s(:, ir, :))), &
     174              :                         MAXVAL(ABS(drho_h(1:3, :, ir, :) - drho_s(1:3, :, ir, :))), &
     175      1562832 :                         MAXVAL(ABS(tau_h(:, ir, :) - tau_s(:, ir, :))))
     176         8232 :             IF (amplitude > 1.0E-12_dp) THEN
     177          514 :                support_ir = MAX(1, ir - 2)
     178          514 :                cutoff = grid_atom%rad(support_ir)
     179          514 :                RETURN
     180              :             END IF
     181              :          END DO
     182              :       ELSE
     183            0 :          DO ir = grid_atom%nr, 1, -1
     184              :             amplitude = MAX( &
     185              :                         MAXVAL(ABS(rho_h(:, ir, :) - rho_s(:, ir, :))), &
     186              :                         MAXVAL(ABS(drho_h(1:3, :, ir, :) - drho_s(1:3, :, ir, :))), &
     187            0 :                         MAXVAL(ABS(tau_h(:, ir, :) - tau_s(:, ir, :))))
     188            0 :             IF (amplitude > 1.0E-12_dp) THEN
     189            0 :                support_ir = MIN(grid_atom%nr, ir + 2)
     190            0 :                cutoff = grid_atom%rad(support_ir)
     191            0 :                RETURN
     192              :             END IF
     193              :          END DO
     194              :       END IF
     195              : 
     196              :    END FUNCTION gapw_atom_grid_support_radius
     197              : 
     198              : ! **************************************************************************************************
     199              : !> \brief ...
     200              : !> \param grid_atom ...
     201              : !> \param harmonics ...
     202              : !> \param nspins ...
     203              : !> \param grad_func ...
     204              : !> \param ir ...
     205              : !> \param r_h ...
     206              : !> \param r_s ...
     207              : !> \param rho_h ...
     208              : !> \param rho_s ...
     209              : !> \param dr_h ...
     210              : !> \param dr_s ...
     211              : !> \param r_h_d ...
     212              : !> \param r_s_d ...
     213              : !> \param drho_h ...
     214              : !> \param drho_s ...
     215              : ! **************************************************************************************************
     216      3079270 :    SUBROUTINE calc_rho_angular(grid_atom, harmonics, nspins, grad_func, &
     217              :                                ir, r_h, r_s, rho_h, rho_s, &
     218              :                                dr_h, dr_s, r_h_d, r_s_d, drho_h, drho_s)
     219              : 
     220              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
     221              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
     222              :       INTEGER, INTENT(IN)                                :: nspins
     223              :       LOGICAL, INTENT(IN)                                :: grad_func
     224              :       INTEGER, INTENT(IN)                                :: ir
     225              :       TYPE(rho_atom_coeff), DIMENSION(:), POINTER        :: r_h, r_s
     226              :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: rho_h, rho_s
     227              :       TYPE(rho_atom_coeff), DIMENSION(:), POINTER        :: dr_h, dr_s
     228              :       TYPE(rho_atom_coeff), DIMENSION(:, :), POINTER     :: r_h_d, r_s_d
     229              :       REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER      :: drho_h, drho_s
     230              : 
     231              :       INTEGER                                            :: ia, iso, ispin, na
     232              :       REAL(KIND=dp)                                      :: rad, urad
     233              : 
     234      3079270 :       CPASSERT(ASSOCIATED(r_h))
     235      3079270 :       CPASSERT(ASSOCIATED(r_s))
     236      3079270 :       CPASSERT(ASSOCIATED(rho_h))
     237      3079270 :       CPASSERT(ASSOCIATED(rho_s))
     238      3079270 :       IF (grad_func) THEN
     239      1962520 :          CPASSERT(ASSOCIATED(dr_h))
     240      1962520 :          CPASSERT(ASSOCIATED(dr_s))
     241      1962520 :          CPASSERT(ASSOCIATED(r_h_d))
     242      1962520 :          CPASSERT(ASSOCIATED(r_s_d))
     243      1962520 :          CPASSERT(ASSOCIATED(drho_h))
     244      1962520 :          CPASSERT(ASSOCIATED(drho_s))
     245              :       END IF
     246              : 
     247      3079270 :       na = grid_atom%ng_sphere
     248      3079270 :       rad = grid_atom%rad(ir)
     249      3079270 :       urad = grid_atom%oorad2l(ir, 1)
     250      6536680 :       DO ispin = 1, nspins
     251     51864490 :          DO iso = 1, harmonics%max_iso_not0
     252   2315124600 :             DO ia = 1, na
     253              :                rho_h(ia, ir, ispin) = rho_h(ia, ir, ispin) + &
     254   2266339380 :                                       r_h(ispin)%r_coef(ir, iso)*harmonics%slm(ia, iso)
     255              :                rho_s(ia, ir, ispin) = rho_s(ia, ir, ispin) + &
     256   2311667190 :                                       r_s(ispin)%r_coef(ir, iso)*harmonics%slm(ia, iso)
     257              :             END DO ! ia
     258              :          END DO ! iso
     259              :       END DO ! ispin
     260              : 
     261      3079270 :       IF (grad_func) THEN
     262      4141630 :          DO ispin = 1, nspins
     263     31537820 :             DO iso = 1, harmonics%max_iso_not0
     264   1499422200 :                DO ia = 1, na
     265              : 
     266              :                   ! components of the gradient of rho1 hard
     267              :                   drho_h(1, ia, ir, ispin) = drho_h(1, ia, ir, ispin) + &
     268              :                                              dr_h(ispin)%r_coef(ir, iso)* &
     269              :                                              harmonics%a(1, ia)*harmonics%slm(ia, iso) + &
     270              :                                              r_h_d(1, ispin)%r_coef(ir, iso)* &
     271   1467884380 :                                              harmonics%slm(ia, iso)
     272              : 
     273              :                   drho_h(2, ia, ir, ispin) = drho_h(2, ia, ir, ispin) + &
     274              :                                              dr_h(ispin)%r_coef(ir, iso)* &
     275              :                                              harmonics%a(2, ia)*harmonics%slm(ia, iso) + &
     276              :                                              r_h_d(2, ispin)%r_coef(ir, iso)* &
     277   1467884380 :                                              harmonics%slm(ia, iso)
     278              : 
     279              :                   drho_h(3, ia, ir, ispin) = drho_h(3, ia, ir, ispin) + &
     280              :                                              dr_h(ispin)%r_coef(ir, iso)* &
     281              :                                              harmonics%a(3, ia)*harmonics%slm(ia, iso) + &
     282              :                                              r_h_d(3, ispin)%r_coef(ir, iso)* &
     283   1467884380 :                                              harmonics%slm(ia, iso)
     284              : 
     285              :                   ! components of the gradient of rho1 soft
     286              :                   drho_s(1, ia, ir, ispin) = drho_s(1, ia, ir, ispin) + &
     287              :                                              dr_s(ispin)%r_coef(ir, iso)* &
     288              :                                              harmonics%a(1, ia)*harmonics%slm(ia, iso) + &
     289              :                                              r_s_d(1, ispin)%r_coef(ir, iso)* &
     290   1467884380 :                                              harmonics%slm(ia, iso)
     291              : 
     292              :                   drho_s(2, ia, ir, ispin) = drho_s(2, ia, ir, ispin) + &
     293              :                                              dr_s(ispin)%r_coef(ir, iso)* &
     294              :                                              harmonics%a(2, ia)*harmonics%slm(ia, iso) + &
     295              :                                              r_s_d(2, ispin)%r_coef(ir, iso)* &
     296   1467884380 :                                              harmonics%slm(ia, iso)
     297              : 
     298              :                   drho_s(3, ia, ir, ispin) = drho_s(3, ia, ir, ispin) + &
     299              :                                              dr_s(ispin)%r_coef(ir, iso)* &
     300              :                                              harmonics%a(3, ia)*harmonics%slm(ia, iso) + &
     301              :                                              r_s_d(3, ispin)%r_coef(ir, iso)* &
     302   1497243090 :                                              harmonics%slm(ia, iso)
     303              : 
     304              :                END DO ! ia
     305              :             END DO ! iso
     306    112827130 :             DO ia = 1, na
     307              :                drho_h(4, ia, ir, ispin) = SQRT( &
     308              :                                           drho_h(1, ia, ir, ispin)*drho_h(1, ia, ir, ispin) + &
     309              :                                           drho_h(2, ia, ir, ispin)*drho_h(2, ia, ir, ispin) + &
     310    108685500 :                                           drho_h(3, ia, ir, ispin)*drho_h(3, ia, ir, ispin))
     311              : 
     312              :                drho_s(4, ia, ir, ispin) = SQRT( &
     313              :                                           drho_s(1, ia, ir, ispin)*drho_s(1, ia, ir, ispin) + &
     314              :                                           drho_s(2, ia, ir, ispin)*drho_s(2, ia, ir, ispin) + &
     315    110864610 :                                           drho_s(3, ia, ir, ispin)*drho_s(3, ia, ir, ispin))
     316              :             END DO ! ia
     317              :          END DO ! ispin
     318              :       END IF
     319              : 
     320      3079270 :    END SUBROUTINE calc_rho_angular
     321              : 
     322              : ! **************************************************************************************************
     323              : !> \brief Precompute radial and angular factors for GAPW meta-GGA tau contractions
     324              : !> \param tau_cache precomputed compact one-center gradient basis
     325              : !> \param grid_atom atom-centered integration grid
     326              : !> \param basis_1c GAPW one-center basis
     327              : !> \param harmonics spherical harmonics on the atom-centered grid
     328              : ! **************************************************************************************************
     329         1700 :    SUBROUTINE create_tau_basis_cache(tau_cache, grid_atom, basis_1c, harmonics)
     330              : 
     331              :       TYPE(tau_basis_cache_type), INTENT(INOUT)          :: tau_cache
     332              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
     333              :       TYPE(gto_basis_set_type), POINTER                  :: basis_1c
     334              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
     335              : 
     336              :       INTEGER                                            :: dir, ia, igrid, ip, ipgf, ir, iset, iso, &
     337              :                                                             l, starti
     338         1700 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: a1, a2, gexp, r1, r2
     339         1700 :       REAL(dp), DIMENSION(:, :), POINTER                 :: slm
     340         1700 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: dslm_dxyz
     341              : 
     342         1700 :       NULLIFY (slm, dslm_dxyz)
     343              : 
     344         1700 :       CALL release_tau_basis_cache(tau_cache)
     345              : 
     346              :       CALL get_gto_basis_set(gto_basis_set=basis_1c, lmax=tau_cache%lmax, &
     347              :                              lmin=tau_cache%lmin, maxso=tau_cache%maxso, &
     348              :                              npgf=tau_cache%npgf, nset=tau_cache%nset, &
     349         1700 :                              zet=tau_cache%zet)
     350              :       CALL get_paw_basis_info(basis_1c, o2nindex=tau_cache%o2nindex, &
     351              :                               n2oindex=tau_cache%n2oindex, &
     352         1700 :                               nsatbas=tau_cache%nsatbas)
     353              : 
     354         1700 :       tau_cache%nr = grid_atom%nr
     355         1700 :       tau_cache%na = grid_atom%ng_sphere
     356         1700 :       slm => harmonics%slm
     357         1700 :       dslm_dxyz => harmonics%dslm_dxyz
     358              : 
     359         8500 :       ALLOCATE (tau_cache%grad(tau_cache%na*tau_cache%nr, tau_cache%nsatbas, 3))
     360              :       ALLOCATE (a1(tau_cache%na), a2(tau_cache%na), gexp(tau_cache%nr), &
     361        13600 :                 r1(tau_cache%nr), r2(tau_cache%nr))
     362    283398830 :       tau_cache%grad = 0.0_dp
     363              : 
     364         6142 :       DO iset = 1, tau_cache%nset
     365        19874 :          DO ipgf = 1, tau_cache%npgf(iset)
     366              :             starti = (iset - 1)*tau_cache%maxso + &
     367        13732 :                      (ipgf - 1)*nsoset(tau_cache%lmax(iset))
     368              :             gexp(1:tau_cache%nr) = EXP(-tau_cache%zet(ipgf, iset)* &
     369       663772 :                                        grid_atom%rad2(1:tau_cache%nr))
     370        56704 :             DO iso = nsoset(tau_cache%lmin(iset) - 1) + 1, nsoset(tau_cache%lmax(iset))
     371        38530 :                ip = tau_cache%o2nindex(starti + iso)
     372        38530 :                IF (ip == 0) CYCLE
     373        38530 :                l = indso(1, iso)
     374              : 
     375      1915750 :                r1(1:tau_cache%nr) = grid_atom%rad(1:tau_cache%nr)**(l - 1)*gexp(1:tau_cache%nr)
     376              :                r2(1:tau_cache%nr) = -2.0_dp*tau_cache%zet(ipgf, iset)* &
     377      1915750 :                                     grid_atom%rad2(1:tau_cache%nr)*r1(1:tau_cache%nr)
     378              : 
     379       167852 :                DO dir = 1, 3
     380      5665266 :                   a1(1:tau_cache%na) = dslm_dxyz(dir, 1:tau_cache%na, iso)
     381      5665266 :                   a2(1:tau_cache%na) = harmonics%a(dir, 1:tau_cache%na)*slm(1:tau_cache%na, iso)
     382      5785780 :                   DO ir = 1, tau_cache%nr
     383    289023690 :                      DO ia = 1, tau_cache%na
     384    283276440 :                         igrid = ia + (ir - 1)*tau_cache%na
     385    288908100 :                         tau_cache%grad(igrid, ip, dir) = r1(ir)*a1(ia) + r2(ir)*a2(ia)
     386              :                      END DO
     387              :                   END DO
     388              :                END DO
     389              :             END DO
     390              :          END DO
     391              :       END DO
     392              : 
     393         1700 :       DEALLOCATE (a1, a2, gexp, r1, r2)
     394              : 
     395         1700 :    END SUBROUTINE create_tau_basis_cache
     396              : 
     397              : ! **************************************************************************************************
     398              : !> \brief Release precomputed GAPW meta-GGA tau factors
     399              : !> \param tau_cache precomputed compact one-center gradient basis
     400              : ! **************************************************************************************************
     401         3400 :    SUBROUTINE release_tau_basis_cache(tau_cache)
     402              : 
     403              :       TYPE(tau_basis_cache_type), INTENT(INOUT)          :: tau_cache
     404              : 
     405         3400 :       IF (ALLOCATED(tau_cache%grad)) DEALLOCATE (tau_cache%grad)
     406         3400 :       IF (ASSOCIATED(tau_cache%n2oindex)) DEALLOCATE (tau_cache%n2oindex)
     407         3400 :       IF (ASSOCIATED(tau_cache%o2nindex)) DEALLOCATE (tau_cache%o2nindex)
     408         3400 :       NULLIFY (tau_cache%lmax, tau_cache%lmin, tau_cache%n2oindex, tau_cache%npgf, &
     409         3400 :                tau_cache%zet, tau_cache%o2nindex)
     410         3400 :       tau_cache%maxso = 0
     411         3400 :       tau_cache%na = 0
     412         3400 :       tau_cache%nr = 0
     413         3400 :       tau_cache%nsatbas = 0
     414         3400 :       tau_cache%nset = 0
     415              : 
     416         3400 :    END SUBROUTINE release_tau_basis_cache
     417              : 
     418              : ! **************************************************************************************************
     419              : !> \brief Computes tau hard and soft on the atomic grids for meta-GGA calculations
     420              : !> \param tau_h the hard part of tau
     421              : !> \param tau_s the soft part of tau
     422              : !> \param rho_atom atom-centered density matrices
     423              : !> \param tau_cache precomputed compact one-center gradient basis
     424              : !> \param nspins number of spin channels
     425              : !> \note This is a rewrite to correct a meta-GGA GAPW bug. This is more brute force than the original,
     426              : !>       which was done along in qs_rho_atom_methods.F, but makes sure that no corner is cut in
     427              : !>       terms of accuracy (A. Bussy)
     428              : ! **************************************************************************************************
     429         1512 :    SUBROUTINE calc_tau_atom(tau_h, tau_s, rho_atom, tau_cache, nspins)
     430              : 
     431              :       REAL(dp), DIMENSION(:, :, :), INTENT(INOUT)        :: tau_h, tau_s
     432              :       TYPE(rho_atom_type), POINTER                       :: rho_atom
     433              :       TYPE(tau_basis_cache_type), INTENT(IN)             :: tau_cache
     434              :       INTEGER, INTENT(IN)                                :: nspins
     435              : 
     436              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'calc_tau_atom'
     437              : 
     438              :       INTEGER                                            :: dir, handle, ia, ibas, igrid, ir, ispin, &
     439              :                                                             na, nbas, ngrid, nr
     440              :       REAL(dp)                                           :: tau_sum
     441         1512 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: work
     442              : 
     443         1512 :       CALL timeset(routineN, handle)
     444              : 
     445         1512 :       CPASSERT(ALLOCATED(tau_cache%grad))
     446              : 
     447              :       !zeroing tau, assuming it is already allocated
     448      2949932 :       tau_h = 0.0_dp
     449      2949932 :       tau_s = 0.0_dp
     450              : 
     451         1512 :       nr = tau_cache%nr
     452         1512 :       na = tau_cache%na
     453         1512 :       nbas = tau_cache%nsatbas
     454         1512 :       ngrid = na*nr
     455         6048 :       ALLOCATE (work(ngrid, nbas))
     456              : 
     457         3032 :       DO ispin = 1, nspins
     458         7592 :          DO dir = 1, 3
     459              :             CALL dgemm('N', 'T', ngrid, nbas, nbas, 0.5_dp, tau_cache%grad(:, :, dir), &
     460         4560 :                        ngrid, rho_atom%cpc_h(ispin)%r_coef, nbas, 0.0_dp, work, ngrid)
     461              : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) SCHEDULE(STATIC) &
     462              : !$OMP SHARED(dir, ispin, na, nbas, nr, tau_cache, tau_h, work) &
     463         4560 : !$OMP PRIVATE(ia, ibas, igrid, ir, tau_sum)
     464              :             DO ir = 1, nr
     465              :                DO ia = 1, na
     466              :                   igrid = ia + (ir - 1)*na
     467              :                   tau_sum = 0.0_dp
     468              :                   DO ibas = 1, nbas
     469              :                      tau_sum = tau_sum + tau_cache%grad(igrid, ibas, dir)*work(igrid, ibas)
     470              :                   END DO
     471              :                   tau_h(ia, ir, ispin) = tau_h(ia, ir, ispin) + tau_sum
     472              :                END DO
     473              :             END DO
     474              : !$OMP END PARALLEL DO
     475              : 
     476              :             CALL dgemm('N', 'T', ngrid, nbas, nbas, 0.5_dp, tau_cache%grad(:, :, dir), &
     477         4560 :                        ngrid, rho_atom%cpc_s(ispin)%r_coef, nbas, 0.0_dp, work, ngrid)
     478              : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) SCHEDULE(STATIC) &
     479              : !$OMP SHARED(dir, ispin, na, nbas, nr, tau_cache, tau_s, work) &
     480         6080 : !$OMP PRIVATE(ia, ibas, igrid, ir, tau_sum)
     481              :             DO ir = 1, nr
     482              :                DO ia = 1, na
     483              :                   igrid = ia + (ir - 1)*na
     484              :                   tau_sum = 0.0_dp
     485              :                   DO ibas = 1, nbas
     486              :                      tau_sum = tau_sum + tau_cache%grad(igrid, ibas, dir)*work(igrid, ibas)
     487              :                   END DO
     488              :                   tau_s(ia, ir, ispin) = tau_s(ia, ir, ispin) + tau_sum
     489              :                END DO
     490              :             END DO
     491              : !$OMP END PARALLEL DO
     492              :          END DO
     493              :       END DO
     494              : 
     495         1512 :       DEALLOCATE (work)
     496              : 
     497         1512 :       CALL timestop(handle)
     498              : 
     499         3024 :    END SUBROUTINE calc_tau_atom
     500              : 
     501              : ! **************************************************************************************************
     502              : !> \brief ...
     503              : !> \param grid_atom ...
     504              : !> \param nspins ...
     505              : !> \param grad_func ...
     506              : !> \param ir ...
     507              : !> \param rho_nlcc ...
     508              : !> \param rho_h ...
     509              : !> \param rho_s ...
     510              : !> \param drho_nlcc ...
     511              : !> \param drho_h ...
     512              : !> \param drho_s ...
     513              : ! **************************************************************************************************
     514        19750 :    SUBROUTINE calc_rho_nlcc(grid_atom, nspins, grad_func, &
     515        19750 :                             ir, rho_nlcc, rho_h, rho_s, drho_nlcc, drho_h, drho_s)
     516              : 
     517              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
     518              :       INTEGER, INTENT(IN)                                :: nspins
     519              :       LOGICAL, INTENT(IN)                                :: grad_func
     520              :       INTEGER, INTENT(IN)                                :: ir
     521              :       REAL(KIND=dp), DIMENSION(:)                        :: rho_nlcc
     522              :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: rho_h, rho_s
     523              :       REAL(KIND=dp), DIMENSION(:)                        :: drho_nlcc
     524              :       REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER      :: drho_h, drho_s
     525              : 
     526              :       INTEGER                                            :: ia, ispin, na
     527              :       REAL(KIND=dp)                                      :: drho, dx, dy, dz, rad, rho, urad, xsp
     528              : 
     529        19750 :       CPASSERT(ASSOCIATED(rho_h))
     530        19750 :       CPASSERT(ASSOCIATED(rho_s))
     531        19750 :       IF (grad_func) THEN
     532        10450 :          CPASSERT(ASSOCIATED(drho_h))
     533        10450 :          CPASSERT(ASSOCIATED(drho_s))
     534              :       END IF
     535              : 
     536        19750 :       na = grid_atom%ng_sphere
     537        19750 :       rad = grid_atom%rad(ir)
     538        19750 :       urad = grid_atom%oorad2l(ir, 1)
     539              : 
     540        19750 :       xsp = REAL(nspins, KIND=dp)
     541        19750 :       rho = rho_nlcc(ir)/xsp
     542        39500 :       DO ispin = 1, nspins
     543      1007250 :          rho_h(1:na, ir, ispin) = rho_h(1:na, ir, ispin) + rho
     544      1027000 :          rho_s(1:na, ir, ispin) = rho_s(1:na, ir, ispin) + rho
     545              :       END DO ! ispin
     546              : 
     547        19750 :       IF (grad_func) THEN
     548        10450 :          drho = drho_nlcc(ir)/xsp
     549        20900 :          DO ispin = 1, nspins
     550       543400 :             DO ia = 1, na
     551       522500 :                IF (grid_atom%azi(ia) == 0.0_dp) THEN
     552              :                   dx = 0.0_dp
     553              :                   dy = 0.0_dp
     554              :                ELSE
     555       470250 :                   dx = grid_atom%sin_pol(ia)*grid_atom%sin_azi(ia)
     556       470250 :                   dy = grid_atom%sin_pol(ia)*grid_atom%cos_azi(ia)
     557              :                END IF
     558       522500 :                dz = grid_atom%cos_pol(ia)
     559              :                ! components of the gradient of rho1 hard
     560       522500 :                drho_h(1, ia, ir, ispin) = drho_h(1, ia, ir, ispin) + drho*dx
     561       522500 :                drho_h(2, ia, ir, ispin) = drho_h(2, ia, ir, ispin) + drho*dy
     562       522500 :                drho_h(3, ia, ir, ispin) = drho_h(3, ia, ir, ispin) + drho*dz
     563              :                ! components of the gradient of rho1 soft
     564       522500 :                drho_s(1, ia, ir, ispin) = drho_s(1, ia, ir, ispin) + drho*dx
     565       522500 :                drho_s(2, ia, ir, ispin) = drho_s(2, ia, ir, ispin) + drho*dy
     566       522500 :                drho_s(3, ia, ir, ispin) = drho_s(3, ia, ir, ispin) + drho*dz
     567              :                ! norm of gradient
     568              :                drho_h(4, ia, ir, ispin) = SQRT( &
     569              :                                           drho_h(1, ia, ir, ispin)*drho_h(1, ia, ir, ispin) + &
     570              :                                           drho_h(2, ia, ir, ispin)*drho_h(2, ia, ir, ispin) + &
     571       522500 :                                           drho_h(3, ia, ir, ispin)*drho_h(3, ia, ir, ispin))
     572              : 
     573              :                drho_s(4, ia, ir, ispin) = SQRT( &
     574              :                                           drho_s(1, ia, ir, ispin)*drho_s(1, ia, ir, ispin) + &
     575              :                                           drho_s(2, ia, ir, ispin)*drho_s(2, ia, ir, ispin) + &
     576       532950 :                                           drho_s(3, ia, ir, ispin)*drho_s(3, ia, ir, ispin))
     577              :             END DO ! ia
     578              :          END DO ! ispin
     579              :       END IF
     580              : 
     581        19750 :    END SUBROUTINE calc_rho_nlcc
     582              : 
     583              : ! **************************************************************************************************
     584              : !> \brief ...
     585              : !> \param vxc_h ...
     586              : !> \param vxc_s ...
     587              : !> \param int_hh ...
     588              : !> \param int_ss ...
     589              : !> \param grid_atom ...
     590              : !> \param basis_1c ...
     591              : !> \param harmonics ...
     592              : !> \param nspins ...
     593              : ! **************************************************************************************************
     594        16817 :    SUBROUTINE gaVxcgb_noGC(vxc_h, vxc_s, int_hh, int_ss, grid_atom, basis_1c, harmonics, nspins)
     595              : 
     596              :       REAL(dp), DIMENSION(:, :, :), POINTER              :: vxc_h, vxc_s
     597              :       TYPE(rho_atom_coeff), DIMENSION(:), POINTER        :: int_hh, int_ss
     598              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
     599              :       TYPE(gto_basis_set_type), POINTER                  :: basis_1c
     600              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
     601              :       INTEGER, INTENT(IN)                                :: nspins
     602              : 
     603              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'gaVxcgb_noGC'
     604              : 
     605              :       INTEGER :: handle, ia, ic, icg, ipgf1, ipgf2, ir, iset1, iset2, iso, iso1, iso2, ispin, l, &
     606              :          ld, lmax12, lmax_expansion, lmin12, m1, m2, max_iso_not0, max_iso_not0_local, max_s_harm, &
     607              :          maxl, maxso, n1, n2, na, ngau1, ngau2, nngau1, nr, nset, size1
     608              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: cg_n_list
     609              :       INTEGER, ALLOCATABLE, DIMENSION(:, :, :)           :: cg_list
     610        16817 :       INTEGER, DIMENSION(:), POINTER                     :: lmax, lmin, npgf
     611        16817 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: g1, g2
     612        16817 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: gg, gVg_h, gVg_s, matso_h, matso_s, vx
     613        16817 :       REAL(dp), DIMENSION(:, :), POINTER                 :: zet
     614              :       REAL(dp), DIMENSION(:, :, :), POINTER              :: my_CG
     615              : 
     616        16817 :       CALL timeset(routineN, handle)
     617              : 
     618        16817 :       NULLIFY (lmin, lmax, npgf, zet, my_CG)
     619              : 
     620              :       CALL get_gto_basis_set(gto_basis_set=basis_1c, lmax=lmax, lmin=lmin, &
     621              :                              maxso=maxso, maxl=maxl, npgf=npgf, &
     622        16817 :                              nset=nset, zet=zet)
     623              : 
     624        16817 :       nr = grid_atom%nr
     625        16817 :       na = grid_atom%ng_sphere
     626        16817 :       my_CG => harmonics%my_CG
     627        16817 :       max_iso_not0 = harmonics%max_iso_not0
     628        16817 :       lmax_expansion = indso(1, max_iso_not0)
     629        16817 :       max_s_harm = harmonics%max_s_harm
     630              : 
     631       117719 :       ALLOCATE (g1(nr), g2(nr), gg(nr, 0:2*maxl))
     632       100902 :       ALLOCATE (gVg_h(na, 0:2*maxl), gVg_s(na, 0:2*maxl))
     633              :       ALLOCATE (matso_h(nsoset(maxl), nsoset(maxl)), &
     634       100902 :                 matso_s(nsoset(maxl), nsoset(maxl)))
     635        67268 :       ALLOCATE (vx(na, nr))
     636       100902 :       ALLOCATE (cg_list(2, nsoset(maxl)**2, max_s_harm), cg_n_list(max_s_harm))
     637              : 
     638        16817 :       g1 = 0.0_dp
     639        16817 :       g2 = 0.0_dp
     640        16817 :       m1 = 0
     641        56701 :       DO iset1 = 1, nset
     642        39884 :          n1 = nsoset(lmax(iset1))
     643        39884 :          m2 = 0
     644       163658 :          DO iset2 = 1, nset
     645              :             CALL get_none0_cg_list(my_CG, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
     646       123774 :                                    max_s_harm, lmax_expansion, cg_list, cg_n_list, max_iso_not0_local)
     647       123774 :             CPASSERT(max_iso_not0_local <= max_iso_not0)
     648              : 
     649       123774 :             n2 = nsoset(lmax(iset2))
     650       450171 :             DO ipgf1 = 1, npgf(iset1)
     651       326397 :                ngau1 = n1*(ipgf1 - 1) + m1
     652       326397 :                size1 = nsoset(lmax(iset1)) - nsoset(lmin(iset1) - 1)
     653       326397 :                nngau1 = nsoset(lmin(iset1) - 1) + ngau1
     654              : 
     655     18755607 :                g1(1:nr) = EXP(-zet(ipgf1, iset1)*grid_atom%rad2(1:nr))
     656      1500527 :                DO ipgf2 = 1, npgf(iset2)
     657      1050356 :                   ngau2 = n2*(ipgf2 - 1) + m2
     658              : 
     659     60010016 :                   g2(1:nr) = EXP(-zet(ipgf2, iset2)*grid_atom%rad2(1:nr))
     660      1050356 :                   lmin12 = lmin(iset1) + lmin(iset2)
     661      1050356 :                   lmax12 = lmax(iset1) + lmax(iset2)
     662              : 
     663              :                   ! reduce expansion local densities
     664      1376753 :                   IF (lmin12 <= lmax_expansion) THEN
     665              : 
     666      1049411 :                      gg = 0.0_dp
     667      1049411 :                      IF (lmin12 == 0) THEN
     668     33829782 :                         gg(1:nr, lmin12) = g1(1:nr)*g2(1:nr)
     669              :                      ELSE
     670     26132039 :                         gg(1:nr, lmin12) = grid_atom%rad2l(1:nr, lmin12)*g1(1:nr)*g2(1:nr)
     671              :                      END IF
     672              : 
     673              :                      ! limit the expansion of the local densities to a max L
     674      1049411 :                      IF (lmax12 > lmax_expansion) lmax12 = lmax_expansion
     675              : 
     676      1522423 :                      DO l = lmin12 + 1, lmax12
     677     29661823 :                         gg(1:nr, l) = grid_atom%rad(1:nr)*gg(:, l - 1)
     678              :                      END DO
     679              : 
     680      2275012 :                      DO ispin = 1, nspins
     681      1225601 :                         ld = lmax12 + 1
     682     73959811 :                         DO ir = 1, nr
     683   3709498151 :                            vx(1:na, ir) = vxc_h(1:na, ir, ispin)
     684              :                         END DO
     685              :                         CALL dgemm('N', 'N', na, ld, nr, 1.0_dp, vx(1:na, 1:nr), na, &
     686      1225601 :                                    gg(1:nr, 0:lmax12), nr, 0.0_dp, gVg_h(1:na, 0:lmax12), na)
     687     73959811 :                         DO ir = 1, nr
     688   3709498151 :                            vx(1:na, ir) = vxc_s(1:na, ir, ispin)
     689              :                         END DO
     690              :                         CALL dgemm('N', 'N', na, ld, nr, 1.0_dp, vx(1:na, 1:nr), na, &
     691      1225601 :                                    gg(1:nr, 0:lmax12), nr, 0.0_dp, gVg_s(1:na, 0:lmax12), na)
     692              : 
     693      1225601 :                         matso_h = 0.0_dp
     694      1225601 :                         matso_s = 0.0_dp
     695      9503890 :                         DO iso = 1, max_iso_not0_local
     696     25997818 :                            DO icg = 1, cg_n_list(iso)
     697     16493928 :                               iso1 = cg_list(1, icg, iso)
     698     16493928 :                               iso2 = cg_list(2, icg, iso)
     699     16493928 :                               l = indso(1, iso1) + indso(1, iso2)
     700              : 
     701     16493928 :                               CPASSERT(l <= lmax_expansion)
     702    849160529 :                               DO ia = 1, na
     703              :                                  matso_h(iso1, iso2) = matso_h(iso1, iso2) + &
     704              :                                                        gVg_h(ia, l)* &
     705              :                                                        my_CG(iso1, iso2, iso)* &
     706    824388312 :                                                        harmonics%slm(ia, iso)
     707              :                                  matso_s(iso1, iso2) = matso_s(iso1, iso2) + &
     708              :                                                        gVg_s(ia, l)* &
     709              :                                                        my_CG(iso1, iso2, iso)* &
     710    840882240 :                                                        harmonics%slm(ia, iso)
     711              :                               END DO
     712              :                            END DO
     713              :                         END DO
     714              : 
     715              :                         ! Write in the global matrix
     716      5449457 :                         DO ic = nsoset(lmin(iset2) - 1) + 1, nsoset(lmax(iset2))
     717      3174445 :                            iso1 = nsoset(lmin(iset1) - 1) + 1
     718      3174445 :                            iso2 = ngau2 + ic
     719              :                            CALL daxpy(size1, 1.0_dp, matso_h(iso1, ic), 1, &
     720      3174445 :                                       int_hh(ispin)%r_coef(nngau1 + 1, iso2), 1)
     721              :                            CALL daxpy(size1, 1.0_dp, matso_s(iso1, ic), 1, &
     722      4400046 :                                       int_ss(ispin)%r_coef(nngau1 + 1, iso2), 1)
     723              :                         END DO
     724              : 
     725              :                      END DO ! ispin
     726              : 
     727              :                   END IF ! lmax_expansion
     728              : 
     729              :                END DO ! ipfg2
     730              :             END DO ! ipfg1
     731       287432 :             m2 = m2 + maxso
     732              :          END DO ! iset2
     733        56701 :          m1 = m1 + maxso
     734              :       END DO ! iset1
     735              : 
     736        16817 :       DEALLOCATE (g1, g2, gg, matso_h, matso_s, gVg_s, gVg_h, vx)
     737              : 
     738        16817 :       DEALLOCATE (cg_list, cg_n_list)
     739              : 
     740        16817 :       CALL timestop(handle)
     741              : 
     742        16817 :    END SUBROUTINE gaVxcgb_noGC
     743              : 
     744              : ! **************************************************************************************************
     745              : !> \brief ...
     746              : !> \param vxc_h ...
     747              : !> \param vxc_s ...
     748              : !> \param vxg_h ...
     749              : !> \param vxg_s ...
     750              : !> \param int_hh ...
     751              : !> \param int_ss ...
     752              : !> \param grid_atom ...
     753              : !> \param basis_1c ...
     754              : !> \param harmonics ...
     755              : !> \param nspins ...
     756              : ! **************************************************************************************************
     757        31341 :    SUBROUTINE gaVxcgb_GC(vxc_h, vxc_s, vxg_h, vxg_s, int_hh, int_ss, &
     758              :                          grid_atom, basis_1c, harmonics, nspins)
     759              : 
     760              :       REAL(dp), DIMENSION(:, :, :), POINTER              :: vxc_h, vxc_s
     761              :       REAL(dp), DIMENSION(:, :, :, :), POINTER           :: vxg_h, vxg_s
     762              :       TYPE(rho_atom_coeff), DIMENSION(:), POINTER        :: int_hh, int_ss
     763              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
     764              :       TYPE(gto_basis_set_type), POINTER                  :: basis_1c
     765              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
     766              :       INTEGER, INTENT(IN)                                :: nspins
     767              : 
     768              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'gaVxcgb_GC'
     769              : 
     770              :       INTEGER :: dmax_iso_not0_local, handle, ia, ic, icg, ipgf1, ipgf2, ir, iset1, iset2, iso, &
     771              :          iso1, iso2, ispin, l, lmax12, lmax_expansion, lmin12, m1, m2, max_iso_not0, &
     772              :          max_iso_not0_local, max_s_harm, maxl, maxso, n1, n2, na, ngau1, ngau2, nngau1, nr, nset, &
     773              :          size1
     774              :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: cg_n_list, dcg_n_list
     775              :       INTEGER, ALLOCATABLE, DIMENSION(:, :, :)           :: cg_list, dcg_list
     776        31341 :       INTEGER, DIMENSION(:), POINTER                     :: lmax, lmin, npgf
     777              :       REAL(dp)                                           :: urad
     778        31341 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: g1, g2
     779        31341 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: dgg, gg, gVXCg_h, gVXCg_s, matso_h, &
     780        31341 :                                                             matso_s
     781        31341 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: gVXGg_h, gVXGg_s
     782        31341 :       REAL(dp), DIMENSION(:, :), POINTER                 :: zet
     783              :       REAL(dp), DIMENSION(:, :, :), POINTER              :: my_CG
     784              :       REAL(dp), DIMENSION(:, :, :, :), POINTER           :: my_CG_dxyz
     785              : 
     786        31341 :       CALL timeset(routineN, handle)
     787              : 
     788        31341 :       NULLIFY (lmin, lmax, npgf, zet, my_CG, my_CG_dxyz)
     789              : 
     790              :       CALL get_gto_basis_set(gto_basis_set=basis_1c, lmax=lmax, lmin=lmin, &
     791              :                              maxso=maxso, maxl=maxl, npgf=npgf, &
     792        31341 :                              nset=nset, zet=zet)
     793              : 
     794        31341 :       nr = grid_atom%nr
     795        31341 :       na = grid_atom%ng_sphere
     796        31341 :       my_CG => harmonics%my_CG
     797        31341 :       my_CG_dxyz => harmonics%my_CG_dxyz
     798        31341 :       max_iso_not0 = harmonics%max_iso_not0
     799        31341 :       lmax_expansion = indso(1, max_iso_not0)
     800        31341 :       max_s_harm = harmonics%max_s_harm
     801              : 
     802       282069 :       ALLOCATE (g1(nr), g2(nr), gg(nr, 0:2*maxl), dgg(nr, 0:2*maxl))
     803       188046 :       ALLOCATE (gVXCg_h(na, 0:2*maxl), gVXCg_s(na, 0:2*maxl))
     804       188046 :       ALLOCATE (gVXGg_h(3, na, 0:2*maxl), gVXGg_s(3, na, 0:2*maxl))
     805              :       ALLOCATE (cg_list(2, nsoset(maxl)**2, max_s_harm), cg_n_list(max_s_harm), &
     806       282069 :                 dcg_list(2, nsoset(maxl)**2, max_s_harm), dcg_n_list(max_s_harm))
     807              : 
     808              :       ALLOCATE (matso_h(nsoset(maxl), nsoset(maxl)), &
     809       188046 :                 matso_s(nsoset(maxl), nsoset(maxl)))
     810              : 
     811        66113 :       DO ispin = 1, nspins
     812              : 
     813        34772 :          g1 = 0.0_dp
     814        34772 :          g2 = 0.0_dp
     815        34772 :          m1 = 0
     816       153754 :          DO iset1 = 1, nset
     817        87641 :             n1 = nsoset(lmax(iset1))
     818        87641 :             m2 = 0
     819       386316 :             DO iset2 = 1, nset
     820              :                CALL get_none0_cg_list(my_CG, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
     821       298675 :                                       max_s_harm, lmax_expansion, cg_list, cg_n_list, max_iso_not0_local)
     822       298675 :                CPASSERT(max_iso_not0_local <= max_iso_not0)
     823              :                CALL get_none0_cg_list(my_CG_dxyz, lmin(iset1), lmax(iset1), lmin(iset2), lmax(iset2), &
     824       298675 :                                       max_s_harm, lmax_expansion, dcg_list, dcg_n_list, dmax_iso_not0_local)
     825              : 
     826       298675 :                n2 = nsoset(lmax(iset2))
     827       963645 :                DO ipgf1 = 1, npgf(iset1)
     828       664970 :                   ngau1 = n1*(ipgf1 - 1) + m1
     829       664970 :                   size1 = nsoset(lmax(iset1)) - nsoset(lmin(iset1) - 1)
     830       664970 :                   nngau1 = nsoset(lmin(iset1) - 1) + ngau1
     831              : 
     832     34605270 :                   g1(1:nr) = EXP(-zet(ipgf1, iset1)*grid_atom%rad2(1:nr))
     833      2638136 :                   DO ipgf2 = 1, npgf(iset2)
     834      1674491 :                      ngau2 = n2*(ipgf2 - 1) + m2
     835              : 
     836     87328041 :                      g2(1:nr) = EXP(-zet(ipgf2, iset2)*grid_atom%rad2(1:nr))
     837      1674491 :                      lmin12 = lmin(iset1) + lmin(iset2)
     838      1674491 :                      lmax12 = lmax(iset1) + lmax(iset2)
     839              : 
     840              :                      !test reduce expansion local densities
     841      1674491 :                      IF (lmin12 <= lmax_expansion) THEN
     842              : 
     843      1673891 :                         gg = 0.0_dp
     844      1673891 :                         dgg = 0.0_dp
     845              : 
     846      1673891 :                         IF (lmin12 == 0) THEN
     847     52703349 :                            gg(1:nr, lmin12) = g1(1:nr)*g2(1:nr)
     848              :                         ELSE
     849     34594092 :                            gg(1:nr, lmin12) = grid_atom%rad2l(1:nr, lmin12)*g1(1:nr)*g2(1:nr)
     850              :                         END IF
     851              : 
     852              :                         !test reduce expansion local densities
     853      1673891 :                         IF (lmax12 > lmax_expansion) lmax12 = lmax_expansion
     854              : 
     855      2602413 :                         DO l = lmin12 + 1, lmax12
     856     48789422 :                            gg(1:nr, l) = grid_atom%rad(1:nr)*gg(:, l - 1)
     857              :                            dgg(1:nr, l - 1) = dgg(1:nr, l - 1) - 2.0_dp*(zet(ipgf1, iset1) + &
     858     50463313 :                                                                          zet(ipgf2, iset2))*gg(1:nr, l)
     859              :                         END DO
     860              :                         dgg(1:nr, lmax12) = dgg(1:nr, lmax12) - 2.0_dp*(zet(ipgf1, iset1) + &
     861              :                                                                         zet(ipgf2, iset2))*grid_atom%rad(1:nr)* &
     862     87297441 :                                             gg(1:nr, lmax12)
     863              : 
     864      1673891 :                         gVXCg_h = 0.0_dp
     865      1673891 :                         gVXCg_s = 0.0_dp
     866      1673891 :                         gVXGg_h = 0.0_dp
     867      1673891 :                         gVXGg_s = 0.0_dp
     868              : 
     869              :                         ! Cross Term
     870      4276304 :                         DO l = lmin12, lmax12
     871    134202170 :                            DO ia = 1, na
     872   6807372859 :                               DO ir = 1, nr
     873              :                                  gVXCg_h(ia, l) = gVXCg_h(ia, l) + &
     874              :                                                   gg(ir, l)*vxc_h(ia, ir, ispin) + &
     875              :                                                   dgg(ir, l)* &
     876              :                                                   (vxg_h(1, ia, ir, ispin)*harmonics%a(1, ia) + &
     877              :                                                    vxg_h(2, ia, ir, ispin)*harmonics%a(2, ia) + &
     878   6674844580 :                                                    vxg_h(3, ia, ir, ispin)*harmonics%a(3, ia))
     879              : 
     880              :                                  gVXCg_s(ia, l) = gVXCg_s(ia, l) + &
     881              :                                                   gg(ir, l)*vxc_s(ia, ir, ispin) + &
     882              :                                                   dgg(ir, l)* &
     883              :                                                   (vxg_s(1, ia, ir, ispin)*harmonics%a(1, ia) + &
     884              :                                                    vxg_s(2, ia, ir, ispin)*harmonics%a(2, ia) + &
     885   6674844580 :                                                    vxg_s(3, ia, ir, ispin)*harmonics%a(3, ia))
     886              : 
     887   6674844580 :                                  urad = grid_atom%oorad2l(ir, 1)
     888              : 
     889              :                                  gVXGg_h(1, ia, l) = gVXGg_h(1, ia, l) + &
     890              :                                                      vxg_h(1, ia, ir, ispin)* &
     891   6674844580 :                                                      gg(ir, l)*urad
     892              : 
     893              :                                  gVXGg_h(2, ia, l) = gVXGg_h(2, ia, l) + &
     894              :                                                      vxg_h(2, ia, ir, ispin)* &
     895   6674844580 :                                                      gg(ir, l)*urad
     896              : 
     897              :                                  gVXGg_h(3, ia, l) = gVXGg_h(3, ia, l) + &
     898              :                                                      vxg_h(3, ia, ir, ispin)* &
     899   6674844580 :                                                      gg(ir, l)*urad
     900              : 
     901              :                                  gVXGg_s(1, ia, l) = gVXGg_s(1, ia, l) + &
     902              :                                                      vxg_s(1, ia, ir, ispin)* &
     903   6674844580 :                                                      gg(ir, l)*urad
     904              : 
     905              :                                  gVXGg_s(2, ia, l) = gVXGg_s(2, ia, l) + &
     906              :                                                      vxg_s(2, ia, ir, ispin)* &
     907   6674844580 :                                                      gg(ir, l)*urad
     908              : 
     909              :                                  gVXGg_s(3, ia, l) = gVXGg_s(3, ia, l) + &
     910              :                                                      vxg_s(3, ia, ir, ispin)* &
     911   6804770446 :                                                      gg(ir, l)*urad
     912              : 
     913              :                               END DO ! ir
     914              :                            END DO ! ia
     915              :                         END DO ! l
     916              : 
     917      1673891 :                         matso_h = 0.0_dp
     918      1673891 :                         matso_s = 0.0_dp
     919     12190332 :                         DO iso = 1, max_iso_not0_local
     920     35011831 :                            DO icg = 1, cg_n_list(iso)
     921     22821499 :                               iso1 = cg_list(1, icg, iso)
     922     22821499 :                               iso2 = cg_list(2, icg, iso)
     923              : 
     924     22821499 :                               l = indso(1, iso1) + indso(1, iso2)
     925              : 
     926              :                               !test reduce expansion local densities
     927     22821499 :                               CPASSERT(l <= lmax_expansion)
     928   1173548374 :                               DO ia = 1, na
     929              :                                  matso_h(iso1, iso2) = matso_h(iso1, iso2) + &
     930              :                                                        gVXCg_h(ia, l)* &
     931              :                                                        harmonics%slm(ia, iso)* &
     932   1140210434 :                                                        my_CG(iso1, iso2, iso)
     933              :                                  matso_s(iso1, iso2) = matso_s(iso1, iso2) + &
     934              :                                                        gVXCg_s(ia, l)* &
     935              :                                                        harmonics%slm(ia, iso)* &
     936   1163031933 :                                                        my_CG(iso1, iso2, iso)
     937              :                               END DO ! ia
     938              : 
     939              :                               !test reduce expansion local densities
     940              : 
     941              :                            END DO
     942              : 
     943              :                         END DO ! iso
     944              : 
     945      6510409 :                         DO iso = 1, dmax_iso_not0_local
     946     43747572 :                            DO icg = 1, dcg_n_list(iso)
     947     37237163 :                               iso1 = dcg_list(1, icg, iso)
     948     37237163 :                               iso2 = dcg_list(2, icg, iso)
     949              : 
     950     37237163 :                               l = indso(1, iso1) + indso(1, iso2)
     951              :                               !test reduce expansion local densities
     952     37237163 :                               CPASSERT(l <= lmax_expansion)
     953   1902023363 :                               DO ia = 1, na
     954              :                                  matso_h(iso1, iso2) = matso_h(iso1, iso2) + &
     955              :                                                        (gVXGg_h(1, ia, l)*my_CG_dxyz(1, iso1, iso2, iso) + &
     956              :                                                         gVXGg_h(2, ia, l)*my_CG_dxyz(2, iso1, iso2, iso) + &
     957              :                                                         gVXGg_h(3, ia, l)*my_CG_dxyz(3, iso1, iso2, iso))* &
     958   1859949682 :                                                        harmonics%slm(ia, iso)
     959              : 
     960              :                                  matso_s(iso1, iso2) = matso_s(iso1, iso2) + &
     961              :                                                        (gVXGg_s(1, ia, l)*my_CG_dxyz(1, iso1, iso2, iso) + &
     962              :                                                         gVXGg_s(2, ia, l)*my_CG_dxyz(2, iso1, iso2, iso) + &
     963              :                                                         gVXGg_s(3, ia, l)*my_CG_dxyz(3, iso1, iso2, iso))* &
     964   1897186845 :                                                        harmonics%slm(ia, iso)
     965              : 
     966              :                               END DO ! ia
     967              : 
     968              :                               !test reduce expansion local densities
     969              : 
     970              :                            END DO ! icg
     971              :                         END DO ! iso
     972              :                         !test reduce expansion local densities
     973              :                      END IF ! lmax_expansion
     974              : 
     975              :                      !  Write in the global matrix
     976      6650865 :                      DO ic = nsoset(lmin(iset2) - 1) + 1, nsoset(lmax(iset2))
     977      4311404 :                         iso1 = nsoset(lmin(iset1) - 1) + 1
     978      4311404 :                         iso2 = ngau2 + ic
     979              :                         CALL daxpy(size1, 1.0_dp, matso_h(iso1, ic), 1, &
     980      4311404 :                                    int_hh(ispin)%r_coef(nngau1 + 1, iso2), 1)
     981              :                         CALL daxpy(size1, 1.0_dp, matso_s(iso1, ic), 1, &
     982      5985895 :                                    int_ss(ispin)%r_coef(nngau1 + 1, iso2), 1)
     983              :                      END DO
     984              : 
     985              :                   END DO ! ipfg2
     986              :                END DO ! ipfg1
     987       983666 :                m2 = m2 + maxso
     988              :             END DO ! iset2
     989       122413 :             m1 = m1 + maxso
     990              :          END DO ! iset1
     991              :       END DO ! ispin
     992              : 
     993        31341 :       DEALLOCATE (g1, g2, gg, dgg, matso_h, matso_s, gVXCg_h, gVXCg_s, gVXGg_h, gVXGg_s)
     994        31341 :       DEALLOCATE (cg_list, cg_n_list, dcg_list, dcg_n_list)
     995              : 
     996        31341 :       CALL timestop(handle)
     997              : 
     998        31341 :    END SUBROUTINE gaVxcgb_GC
     999              : 
    1000              : ! **************************************************************************************************
    1001              : !> \brief Integrates 0.5 * grad_ga .dot. (V_tau * grad_gb) on the atomic grid for meta-GGA
    1002              : !> \param vtau_h the hard tau potential
    1003              : !> \param vtau_s the soft tau potential
    1004              : !> \param int_hh hard one-center matrix contribution
    1005              : !> \param int_ss soft one-center matrix contribution
    1006              : !> \param tau_cache precomputed compact one-center gradient basis
    1007              : !> \param nspins number of spin channels
    1008              : !> \note This is a rewrite to correct meta-GGA GAPW bug. This is more brute force than the original
    1009              : !>       but makes sure that no corner is cut in terms of accuracy (A. Bussy)
    1010              : ! **************************************************************************************************
    1011         1064 :    SUBROUTINE dgaVtaudgb(vtau_h, vtau_s, int_hh, int_ss, tau_cache, nspins)
    1012              : 
    1013              :       REAL(dp), DIMENSION(:, :, :), POINTER              :: vtau_h, vtau_s
    1014              :       TYPE(rho_atom_coeff), DIMENSION(:), POINTER        :: int_hh, int_ss
    1015              :       TYPE(tau_basis_cache_type), INTENT(IN)             :: tau_cache
    1016              :       INTEGER, INTENT(IN)                                :: nspins
    1017              : 
    1018              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dgaVtaudgb'
    1019              : 
    1020              :       INTEGER                                            :: dir, handle, ia, ibas, igrid, iold, ir, &
    1021              :                                                             ispin, jbas, jold, max_old_basis, na, &
    1022              :                                                             nbas, ngrid, nr
    1023         1064 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: int_h, int_s, weighted_grad
    1024              : 
    1025         1064 :       CALL timeset(routineN, handle)
    1026              : 
    1027         1064 :       CPASSERT(ALLOCATED(tau_cache%grad))
    1028         1064 :       CPASSERT(ASSOCIATED(tau_cache%n2oindex))
    1029              : 
    1030         1064 :       nr = tau_cache%nr
    1031         1064 :       na = tau_cache%na
    1032         1064 :       nbas = tau_cache%nsatbas
    1033         1064 :       ngrid = na*nr
    1034        64808 :       max_old_basis = MAXVAL(tau_cache%n2oindex)
    1035         9576 :       ALLOCATE (int_h(nbas, nbas), int_s(nbas, nbas), weighted_grad(ngrid, nbas))
    1036              : 
    1037         2136 :       DO ispin = 1, nspins
    1038         1072 :          CPASSERT(SIZE(int_hh(ispin)%r_coef, 1) >= max_old_basis)
    1039         1072 :          CPASSERT(SIZE(int_hh(ispin)%r_coef, 2) >= max_old_basis)
    1040         1072 :          CPASSERT(SIZE(int_ss(ispin)%r_coef, 1) >= max_old_basis)
    1041         1072 :          CPASSERT(SIZE(int_ss(ispin)%r_coef, 2) >= max_old_basis)
    1042         1072 :          int_h = 0.0_dp
    1043         1072 :          int_s = 0.0_dp
    1044         4288 :          DO dir = 1, 3
    1045              : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(3) SCHEDULE(STATIC) &
    1046              : !$OMP SHARED(dir, ispin, na, nbas, nr, tau_cache, vtau_h, weighted_grad) &
    1047         3216 : !$OMP PRIVATE(ia, ibas, igrid, ir)
    1048              :             DO ibas = 1, nbas
    1049              :                DO ir = 1, nr
    1050              :                   DO ia = 1, na
    1051              :                      igrid = ia + (ir - 1)*na
    1052              :                      weighted_grad(igrid, ibas) = vtau_h(ia, ir, ispin)* &
    1053              :                                                   tau_cache%grad(igrid, ibas, dir)
    1054              :                   END DO
    1055              :                END DO
    1056              :             END DO
    1057              : !$OMP END PARALLEL DO
    1058              :             CALL dgemm('T', 'N', nbas, nbas, ngrid, 0.5_dp, tau_cache%grad(:, :, dir), &
    1059         3216 :                        ngrid, weighted_grad, ngrid, 1.0_dp, int_h, nbas)
    1060              : 
    1061              : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(3) SCHEDULE(STATIC) &
    1062              : !$OMP SHARED(dir, ispin, na, nbas, nr, tau_cache, vtau_s, weighted_grad) &
    1063         3216 : !$OMP PRIVATE(ia, ibas, igrid, ir)
    1064              :             DO ibas = 1, nbas
    1065              :                DO ir = 1, nr
    1066              :                   DO ia = 1, na
    1067              :                      igrid = ia + (ir - 1)*na
    1068              :                      weighted_grad(igrid, ibas) = vtau_s(ia, ir, ispin)* &
    1069              :                                                   tau_cache%grad(igrid, ibas, dir)
    1070              :                   END DO
    1071              :                END DO
    1072              :             END DO
    1073              : !$OMP END PARALLEL DO
    1074              :             CALL dgemm('T', 'N', nbas, nbas, ngrid, 0.5_dp, tau_cache%grad(:, :, dir), &
    1075         4288 :                        ngrid, weighted_grad, ngrid, 1.0_dp, int_s, nbas)
    1076              :          END DO
    1077              : 
    1078              : !$OMP PARALLEL DO DEFAULT(NONE) COLLAPSE(2) SCHEDULE(STATIC) &
    1079              : !$OMP SHARED(int_h, int_hh, int_s, int_ss, ispin, nbas, tau_cache) &
    1080         2136 : !$OMP PRIVATE(ibas, iold, jbas, jold)
    1081              :          DO jbas = 1, nbas
    1082              :             DO ibas = 1, nbas
    1083              :                jold = tau_cache%n2oindex(jbas)
    1084              :                iold = tau_cache%n2oindex(ibas)
    1085              :                int_hh(ispin)%r_coef(iold, jold) = int_hh(ispin)%r_coef(iold, jold) + &
    1086              :                                                   int_h(ibas, jbas)
    1087              :                int_ss(ispin)%r_coef(iold, jold) = int_ss(ispin)%r_coef(iold, jold) + &
    1088              :                                                   int_s(ibas, jbas)
    1089              :             END DO
    1090              :          END DO
    1091              : !$OMP END PARALLEL DO
    1092              :       END DO
    1093              : 
    1094         1064 :       DEALLOCATE (int_h, int_s, weighted_grad)
    1095              : 
    1096         1064 :       CALL timestop(handle)
    1097              : 
    1098         2128 :    END SUBROUTINE dgaVtaudgb
    1099              : 
    1100              : ! **************************************************************************************************
    1101              : !> \brief Calculates the radial weight function for accurate XC integration
    1102              : !> \param fun  The weight function
    1103              : !> \param r2   Radial values of the grid (squared)
    1104              : !> \param order  Polynomila order (2n)
    1105              : !> \param alpha  Gaussian exponent
    1106              : ! **************************************************************************************************
    1107          536 :    SUBROUTINE calc_weight_function(fun, r2, order, alpha)
    1108              : 
    1109              :       REAL(dp), DIMENSION(:), INTENT(INOUT)              :: fun
    1110              :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: r2
    1111              :       INTEGER, INTENT(IN)                                :: order
    1112              :       REAL(dp), INTENT(IN)                               :: alpha
    1113              : 
    1114              :       INTEGER                                            :: i
    1115              :       REAL(dp)                                           :: pval
    1116              : 
    1117          536 :       CPASSERT(SIZE(fun) == SIZE(r2))
    1118              : 
    1119        27156 :       fun(:) = 1.0_dp
    1120          540 :       DO i = 1, order
    1121            4 :          pval = alpha**i/fac(i)
    1122          740 :          fun(:) = fun(:) + pval*r2**i
    1123              :       END DO
    1124        27156 :       fun(:) = fun(:)*EXP(-alpha*r2(:))
    1125              : 
    1126          536 :    END SUBROUTINE calc_weight_function
    1127              : 
    1128              : ! **************************************************************************************************
    1129              : 
    1130            0 : END MODULE qs_vxc_atom_utils
        

Generated by: LCOV version 2.0-1