LCOV - code coverage report
Current view: top level - src - xc_pot_saop.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:70636b1) Lines: 42.6 % 549 234
Test Date: 2026-02-11 07:00:35 Functions: 87.5 % 8 7

            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 Calculate the saop potential
      10              : ! **************************************************************************************************
      11              : MODULE xc_pot_saop
      12              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      13              :                                               get_atomic_kind
      14              :    USE basis_set_types,                 ONLY: gto_basis_set_type
      15              :    USE cp_array_utils,                  ONLY: cp_1d_r_p_type
      16              :    USE cp_control_types,                ONLY: dft_control_type
      17              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      18              :                                               dbcsr_deallocate_matrix,&
      19              :                                               dbcsr_p_type,&
      20              :                                               dbcsr_set
      21              :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_plus_fm_fm_t,&
      22              :                                               dbcsr_allocate_matrix_set,&
      23              :                                               dbcsr_deallocate_matrix_set
      24              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      25              :                                               cp_fm_get_info,&
      26              :                                               cp_fm_get_submatrix,&
      27              :                                               cp_fm_p_type,&
      28              :                                               cp_fm_release,&
      29              :                                               cp_fm_set_all,&
      30              :                                               cp_fm_set_submatrix,&
      31              :                                               cp_fm_type
      32              :    USE input_constants,                 ONLY: do_method_gapw,&
      33              :                                               oe_gllb,&
      34              :                                               oe_lb,&
      35              :                                               oe_saop,&
      36              :                                               xc_funct_no_shortcut
      37              :    USE input_section_types,             ONLY: &
      38              :         section_vals_create, section_vals_duplicate, section_vals_get_subs_vals, &
      39              :         section_vals_release, section_vals_retain, section_vals_set_subs_vals, section_vals_type, &
      40              :         section_vals_val_get, section_vals_val_set
      41              :    USE kinds,                           ONLY: dp
      42              :    USE mathconstants,                   ONLY: pi
      43              :    USE message_passing,                 ONLY: mp_para_env_type
      44              :    USE pw_env_types,                    ONLY: pw_env_get,&
      45              :                                               pw_env_type
      46              :    USE pw_methods,                      ONLY: pw_axpy,&
      47              :                                               pw_copy,&
      48              :                                               pw_scale,&
      49              :                                               pw_zero
      50              :    USE pw_pool_types,                   ONLY: pw_pool_type
      51              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      52              :                                               pw_r3d_rs_type
      53              :    USE qs_collocate_density,            ONLY: calculate_rho_elec
      54              :    USE qs_environment_types,            ONLY: get_qs_env,&
      55              :                                               qs_environment_type
      56              :    USE qs_gapw_densities,               ONLY: prepare_gapw_den
      57              :    USE qs_grid_atom,                    ONLY: grid_atom_type
      58              :    USE qs_harmonics_atom,               ONLY: harmonics_atom_type
      59              :    USE qs_integrate_potential,          ONLY: integrate_v_rspace
      60              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      61              :                                               qs_kind_type
      62              :    USE qs_ks_atom,                      ONLY: update_ks_atom
      63              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      64              :    USE qs_local_rho_types,              ONLY: local_rho_set_create,&
      65              :                                               local_rho_set_release,&
      66              :                                               local_rho_type
      67              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      68              :                                               mo_set_type
      69              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      70              :    USE qs_oce_types,                    ONLY: oce_matrix_type
      71              :    USE qs_rho_atom_methods,             ONLY: allocate_rho_atom_internals,&
      72              :                                               calculate_rho_atom_coeff
      73              :    USE qs_rho_atom_types,               ONLY: get_rho_atom,&
      74              :                                               rho_atom_coeff,&
      75              :                                               rho_atom_type
      76              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      77              :                                               qs_rho_type
      78              :    USE qs_vxc_atom,                     ONLY: calc_rho_angular,&
      79              :                                               gaVxcgb_noGC
      80              :    USE util,                            ONLY: get_limit
      81              :    USE virial_types,                    ONLY: virial_type
      82              :    USE xc,                              ONLY: xc_vxc_pw_create
      83              :    USE xc_atom,                         ONLY: fill_rho_set,&
      84              :                                               vxc_of_r_new,&
      85              :                                               xc_rho_set_atom_update
      86              :    USE xc_derivative_set_types,         ONLY: xc_derivative_set_type,&
      87              :                                               xc_dset_create,&
      88              :                                               xc_dset_get_derivative,&
      89              :                                               xc_dset_release,&
      90              :                                               xc_dset_zero_all
      91              :    USE xc_derivative_types,             ONLY: xc_derivative_get,&
      92              :                                               xc_derivative_type
      93              :    USE xc_derivatives,                  ONLY: xc_functionals_eval
      94              :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_setall,&
      95              :                                               xc_rho_cflags_type
      96              :    USE xc_rho_set_types,                ONLY: xc_rho_set_create,&
      97              :                                               xc_rho_set_release,&
      98              :                                               xc_rho_set_type,&
      99              :                                               xc_rho_set_update
     100              :    USE xc_xbecke88,                     ONLY: xb88_lda_info,&
     101              :                                               xb88_lsd_info
     102              : #include "./base/base_uses.f90"
     103              : 
     104              :    IMPLICIT NONE
     105              : 
     106              :    PRIVATE
     107              : 
     108              :    PUBLIC :: add_saop_pot
     109              : 
     110              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xc_pot_saop'
     111              : 
     112              :    ! should be eliminated
     113              :    REAL(KIND=dp), PARAMETER :: alpha = 1.19_dp, beta = 0.01_dp, K_rho = 0.42_dp
     114              :    REAL(KIND=dp), PARAMETER :: kappa = 0.804_dp, mu = 0.21951_dp, &
     115              :                                beta_ec = 0.066725_dp, gamma_saop = 0.031091_dp
     116              : 
     117              : CONTAINS
     118              : 
     119              : ! **************************************************************************************************
     120              : !> \brief ...
     121              : !> \param ks_matrix ...
     122              : !> \param qs_env ...
     123              : !> \param oe_corr ...
     124              : ! **************************************************************************************************
     125           14 :    SUBROUTINE add_saop_pot(ks_matrix, qs_env, oe_corr)
     126              : 
     127              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ks_matrix
     128              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     129              :       INTEGER, INTENT(IN)                                :: oe_corr
     130              : 
     131              :       INTEGER                                            :: dft_method_id, homo, i, ispin, j, k, &
     132              :                                                             nspins, orb, xc_deriv_method_id, &
     133              :                                                             xc_rho_smooth_id
     134              :       INTEGER, DIMENSION(2)                              :: ncol, nrow
     135              :       INTEGER, DIMENSION(2, 3)                           :: bo
     136              :       LOGICAL                                            :: compute_virial, gapw, lsd
     137              :       REAL(KIND=dp)                                      :: density_cut, efac, gradient_cut, &
     138              :                                                             tau_cut, we_GLLB, we_LB, xc_energy
     139           14 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: coeff_col
     140              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: virial_xc_tmp
     141           14 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
     142           14 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: e_uniform
     143           14 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: single_mo_coeff
     144              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     145           28 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: orbital_density_matrix, rho_struct_ao
     146           14 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: molecular_orbitals
     147              :       TYPE(pw_c1d_gs_type)                               :: orbital_g
     148           14 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g
     149              :       TYPE(pw_env_type), POINTER                         :: pw_env
     150              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     151              :       TYPE(pw_r3d_rs_type)                               :: orbital
     152           14 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: vxc_GLLB, vxc_SAOP
     153           28 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r, rho_struct_r, tau, vxc_LB, &
     154           14 :                                                             vxc_tau, vxc_tmp
     155              :       TYPE(pw_r3d_rs_type), POINTER                      :: weights
     156              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     157              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     158              :       TYPE(section_vals_type), POINTER                   :: input, xc_fun_section_orig, &
     159              :                                                             xc_fun_section_tmp, xc_section_orig, &
     160              :                                                             xc_section_tmp
     161              :       TYPE(virial_type), POINTER                         :: virial
     162              :       TYPE(xc_derivative_set_type)                       :: deriv_set
     163              :       TYPE(xc_derivative_type), POINTER                  :: deriv
     164              :       TYPE(xc_rho_cflags_type)                           :: needs
     165              :       TYPE(xc_rho_set_type)                              :: rho_set
     166              : 
     167           14 :       NULLIFY (ks_env, pw_env, auxbas_pw_pool, input)
     168           14 :       NULLIFY (rho_g, rho_r, tau, rho_struct, e_uniform)
     169           14 :       NULLIFY (vxc_LB, vxc_tmp, vxc_tau)
     170           14 :       NULLIFY (mo_eigenvalues, deriv, rho_struct_r, rho_struct_ao)
     171           14 :       NULLIFY (orbital_density_matrix, xc_section_tmp, xc_fun_section_tmp)
     172              : 
     173              :       CALL get_qs_env(qs_env, &
     174              :                       ks_env=ks_env, &
     175              :                       rho=rho_struct, &
     176              :                       xcint_weights=weights, &
     177              :                       pw_env=pw_env, &
     178              :                       input=input, &
     179              :                       virial=virial, &
     180           14 :                       mos=molecular_orbitals)
     181           14 :       compute_virial = virial%pv_calculate .AND. (.NOT. virial%pv_numer)
     182           14 :       CALL section_vals_val_get(input, "DFT%QS%METHOD", i_val=dft_method_id)
     183           14 :       gapw = (dft_method_id == do_method_gapw)
     184              : 
     185           14 :       xc_section_orig => section_vals_get_subs_vals(input, "DFT%XC")
     186           14 :       CALL section_vals_retain(xc_section_orig)
     187           14 :       CALL section_vals_duplicate(xc_section_orig, xc_section_tmp)
     188              : 
     189              :       CALL section_vals_val_get(xc_section_orig, "DENSITY_CUTOFF", &
     190           14 :                                 r_val=density_cut)
     191              :       CALL section_vals_val_get(xc_section_orig, "GRADIENT_CUTOFF", &
     192           14 :                                 r_val=gradient_cut)
     193              :       CALL section_vals_val_get(xc_section_orig, "TAU_CUTOFF", &
     194           14 :                                 r_val=tau_cut)
     195              : 
     196           14 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     197              : 
     198           14 :       CALL section_vals_val_get(input, "DFT%LSD", l_val=lsd)
     199           14 :       IF (lsd) THEN
     200            6 :          nspins = 2
     201              :       ELSE
     202            8 :          nspins = 1
     203              :       END IF
     204              : 
     205           62 :       ALLOCATE (single_mo_coeff(nspins))
     206           14 :       CALL dbcsr_allocate_matrix_set(orbital_density_matrix, nspins)
     207           14 :       CALL qs_rho_get(rho_struct, rho_r=rho_struct_r, rho_ao=rho_struct_ao)
     208           14 :       rho_r => rho_struct_r
     209           34 :       DO ispin = 1, nspins
     210           20 :          ALLOCATE (orbital_density_matrix(ispin)%matrix)
     211              :          CALL dbcsr_copy(orbital_density_matrix(ispin)%matrix, &
     212           34 :                          rho_struct_ao(ispin)%matrix, "orbital density")
     213              :       END DO
     214          140 :       bo = rho_r(1)%pw_grid%bounds_local
     215              : 
     216              :       !---------------------------!
     217              :       ! create the density needed !
     218              :       !---------------------------!
     219              :       CALL xc_rho_set_create(rho_set, bo, &
     220              :                              density_cut, &
     221              :                              gradient_cut, &
     222           14 :                              tau_cut)
     223           14 :       CALL xc_rho_cflags_setall(needs, .FALSE.)
     224           14 :       IF (lsd) THEN
     225            6 :          CALL xb88_lsd_info(needs=needs)
     226            6 :          needs%norm_drho = .TRUE.
     227              :       ELSE
     228            8 :          CALL xb88_lda_info(needs=needs)
     229              :       END IF
     230              :       CALL section_vals_val_get(xc_section_orig, "XC_GRID%XC_DERIV", &
     231           14 :                                 i_val=xc_deriv_method_id)
     232              :       CALL section_vals_val_get(xc_section_orig, "XC_GRID%XC_SMOOTH_RHO", &
     233           14 :                                 i_val=xc_rho_smooth_id)
     234              :       CALL xc_rho_set_update(rho_set, rho_r, rho_g, tau, needs, &
     235              :                              xc_deriv_method_id, &
     236              :                              xc_rho_smooth_id, &
     237           14 :                              auxbas_pw_pool)
     238              : 
     239              :       !----------------------------------------!
     240              :       ! Construct the LB94 potential in vxc_LB !
     241              :       !----------------------------------------!
     242              :       xc_fun_section_orig => section_vals_get_subs_vals(xc_section_orig, &
     243           14 :                                                         "XC_FUNCTIONAL")
     244           14 :       CALL section_vals_create(xc_fun_section_tmp, xc_fun_section_orig%section)
     245              :       CALL section_vals_val_set(xc_fun_section_tmp, "_SECTION_PARAMETERS_", &
     246           14 :                                 i_val=xc_funct_no_shortcut)
     247              :       CALL section_vals_val_set(xc_fun_section_tmp, "XALPHA%_SECTION_PARAMETERS_", &
     248           14 :                                 l_val=.TRUE.)
     249              :       CALL section_vals_set_subs_vals(xc_section_tmp, "XC_FUNCTIONAL", &
     250           14 :                                       xc_fun_section_tmp)
     251              : 
     252           14 :       CPASSERT(.NOT. compute_virial)
     253              :       CALL xc_vxc_pw_create(vxc_tmp, vxc_tau, xc_energy, rho_r, rho_g, tau, &
     254              :                             xc_section_tmp, weights, auxbas_pw_pool, &
     255           14 :                             compute_virial=.FALSE., virial_xc=virial_xc_tmp)
     256              : 
     257              :       CALL section_vals_val_set(xc_fun_section_tmp, "XALPHA%_SECTION_PARAMETERS_", &
     258           14 :                                 l_val=.FALSE.)
     259              :       CALL section_vals_val_set(xc_fun_section_tmp, "PZ81%_SECTION_PARAMETERS_", &
     260           14 :                                 l_val=.TRUE.)
     261              : 
     262           14 :       CPASSERT(.NOT. compute_virial)
     263              :       CALL xc_vxc_pw_create(vxc_LB, vxc_tau, xc_energy, rho_r, rho_g, tau, &
     264              :                             xc_section_tmp, weights, auxbas_pw_pool, &
     265           14 :                             compute_virial=.FALSE., virial_xc=virial_xc_tmp)
     266              : 
     267           34 :       DO ispin = 1, nspins
     268           34 :          CALL pw_axpy(vxc_tmp(ispin), vxc_LB(ispin), alpha)
     269              :       END DO
     270              : 
     271           34 :       DO ispin = 1, nspins
     272           20 :          CALL add_lb_pot(vxc_tmp(ispin)%array, rho_set, lsd, ispin)
     273           34 :          CALL pw_axpy(vxc_tmp(ispin), vxc_LB(ispin), -1.0_dp)
     274              :       END DO
     275              : 
     276              :       !-----------------------------------------------------------------------------------!
     277              :       ! Construct 2 times PBE one particle density from the PZ correlation energy density !
     278              :       !-----------------------------------------------------------------------------------!
     279           14 :       CALL xc_dset_create(deriv_set, local_bounds=bo)
     280              :       CALL xc_functionals_eval(xc_fun_section_tmp, &
     281              :                                lsd=lsd, &
     282              :                                rho_set=rho_set, &
     283              :                                deriv_set=deriv_set, &
     284           14 :                                deriv_order=0)
     285              : 
     286           14 :       deriv => xc_dset_get_derivative(deriv_set, [INTEGER::])
     287           14 :       CALL xc_derivative_get(deriv, deriv_data=e_uniform)
     288              : 
     289           62 :       ALLOCATE (vxc_GLLB(nspins))
     290           34 :       DO ispin = 1, nspins
     291           34 :          CALL auxbas_pw_pool%create_pw(vxc_GLLB(ispin))
     292              :       END DO
     293              : 
     294           34 :       DO ispin = 1, nspins
     295           34 :          CALL calc_2excpbe(vxc_GLLB(ispin)%array, rho_set, e_uniform, lsd)
     296              :       END DO
     297              : 
     298           14 :       CALL xc_dset_release(deriv_set)
     299              : 
     300           14 :       CALL auxbas_pw_pool%create_pw(orbital)
     301           14 :       CALL auxbas_pw_pool%create_pw(orbital_g)
     302              : 
     303           34 :       DO ispin = 1, nspins
     304              : 
     305              :          CALL get_mo_set(molecular_orbitals(ispin), &
     306              :                          mo_coeff=mo_coeff, &
     307              :                          eigenvalues=mo_eigenvalues, &
     308           20 :                          homo=homo)
     309              :          CALL cp_fm_create(single_mo_coeff(ispin), &
     310              :                            mo_coeff%matrix_struct, &
     311           20 :                            "orbital density matrix")
     312              : 
     313              :          CALL cp_fm_get_info(single_mo_coeff(ispin), &
     314           20 :                              nrow_global=nrow(ispin), ncol_global=ncol(ispin))
     315           60 :          ALLOCATE (coeff_col(nrow(ispin), 1))
     316              : 
     317           20 :          CALL pw_zero(vxc_tmp(ispin))
     318              : 
     319           98 :          DO orb = 1, homo - 1
     320              : 
     321           78 :             efac = K_rho*SQRT(mo_eigenvalues(homo) - mo_eigenvalues(orb))
     322           78 :             IF (.NOT. lsd) efac = 2.0_dp*efac
     323              : 
     324           78 :             CALL cp_fm_set_all(single_mo_coeff(ispin), 0.0_dp)
     325              :             CALL cp_fm_get_submatrix(mo_coeff, coeff_col, &
     326           78 :                                      1, orb, nrow(ispin), 1)
     327              :             CALL cp_fm_set_submatrix(single_mo_coeff(ispin), coeff_col, &
     328           78 :                                      1, orb)
     329           78 :             CALL dbcsr_set(orbital_density_matrix(ispin)%matrix, 0.0_dp)
     330              :             CALL cp_dbcsr_plus_fm_fm_t(orbital_density_matrix(ispin)%matrix, &
     331              :                                        matrix_v=single_mo_coeff(ispin), &
     332              :                                        ncol=ncol(ispin), &
     333           78 :                                        alpha=1.0_dp)
     334           78 :             CALL pw_zero(orbital)
     335           78 :             CALL pw_zero(orbital_g)
     336              :             CALL calculate_rho_elec(matrix_p=orbital_density_matrix(ispin)%matrix, &
     337              :                                     rho=orbital, rho_gspace=orbital_g, &
     338           78 :                                     ks_env=ks_env)
     339              : 
     340           98 :             CALL pw_axpy(orbital, vxc_tmp(ispin), efac)
     341              : 
     342              :          END DO
     343           20 :          DEALLOCATE (coeff_col)
     344              : 
     345          694 :          DO k = bo(1, 3), bo(2, 3)
     346        24228 :             DO j = bo(1, 2), bo(2, 2)
     347       447395 :                DO i = bo(1, 1), bo(2, 1)
     348       446721 :                   IF (rho_r(ispin)%array(i, j, k) > density_cut) THEN
     349              :                      vxc_tmp(ispin)%array(i, j, k) = vxc_tmp(ispin)%array(i, j, k)/ &
     350       423187 :                                                      rho_r(ispin)%array(i, j, k)
     351              :                   ELSE
     352            0 :                      vxc_tmp(ispin)%array(i, j, k) = 0.0_dp
     353              :                   END IF
     354              :                END DO
     355              :             END DO
     356              :          END DO
     357              : 
     358           54 :          CALL pw_axpy(vxc_tmp(ispin), vxc_GLLB(ispin), 1.0_dp)
     359              : 
     360              :       END DO
     361              : 
     362              :       !---------------!
     363              :       ! Assemble SAOP !
     364              :       !---------------!
     365           48 :       ALLOCATE (vxc_SAOP(nspins))
     366              : 
     367           34 :       DO ispin = 1, nspins
     368              : 
     369              :          CALL get_mo_set(molecular_orbitals(ispin), &
     370              :                          mo_coeff=mo_coeff, &
     371              :                          eigenvalues=mo_eigenvalues, &
     372           20 :                          homo=homo)
     373           20 :          CALL auxbas_pw_pool%create_pw(vxc_SAOP(ispin))
     374           20 :          CALL pw_zero(vxc_SAOP(ispin))
     375              : 
     376           60 :          ALLOCATE (coeff_col(nrow(ispin), 1))
     377              : 
     378          118 :          DO orb = 1, homo
     379              : 
     380           98 :             we_LB = EXP(-2.0_dp*(mo_eigenvalues(homo) - mo_eigenvalues(orb))**2)
     381           98 :             we_GLLB = 1.0_dp - we_LB
     382           98 :             IF (.NOT. lsd) THEN
     383           32 :                we_LB = 2.0_dp*we_LB
     384           32 :                we_GLLB = 2.0_dp*we_GLLB
     385              :             END IF
     386              : 
     387              :             vxc_tmp(ispin)%array = we_LB*vxc_LB(ispin)%array + &
     388      4682538 :                                    we_GLLB*vxc_GLLB(ispin)%array
     389              : 
     390           98 :             CALL cp_fm_set_all(single_mo_coeff(ispin), 0.0_dp)
     391              :             CALL cp_fm_get_submatrix(mo_coeff, coeff_col, &
     392           98 :                                      1, orb, nrow(ispin), 1)
     393              :             CALL cp_fm_set_submatrix(single_mo_coeff(ispin), coeff_col, &
     394           98 :                                      1, orb)
     395           98 :             CALL dbcsr_set(orbital_density_matrix(ispin)%matrix, 0.0_dp)
     396              :             CALL cp_dbcsr_plus_fm_fm_t(orbital_density_matrix(ispin)%matrix, &
     397              :                                        matrix_v=single_mo_coeff(ispin), &
     398              :                                        ncol=ncol(ispin), &
     399           98 :                                        alpha=1.0_dp)
     400           98 :             CALL pw_zero(orbital)
     401           98 :             CALL pw_zero(orbital_g)
     402              :             CALL calculate_rho_elec(matrix_p=orbital_density_matrix(ispin)%matrix, &
     403              :                                     rho=orbital, rho_gspace=orbital_g, &
     404           98 :                                     ks_env=ks_env)
     405              : 
     406              :             vxc_SAOP(ispin)%array = vxc_SAOP(ispin)%array + &
     407      2341338 :                                     orbital%array*vxc_tmp(ispin)%array
     408              : 
     409              :          END DO
     410              : 
     411           20 :          CALL dbcsr_deallocate_matrix(orbital_density_matrix(ispin)%matrix)
     412              : 
     413           20 :          DEALLOCATE (coeff_col)
     414              : 
     415          728 :          DO k = bo(1, 3), bo(2, 3)
     416        24228 :             DO j = bo(1, 2), bo(2, 2)
     417       447395 :                DO i = bo(1, 1), bo(2, 1)
     418       446721 :                   IF (rho_r(ispin)%array(i, j, k) > density_cut) THEN
     419              :                      vxc_SAOP(ispin)%array(i, j, k) = vxc_SAOP(ispin)%array(i, j, k)/ &
     420       423187 :                                                       rho_r(ispin)%array(i, j, k)
     421              :                   ELSE
     422            0 :                      vxc_SAOP(ispin)%array(i, j, k) = 0.0_dp
     423              :                   END IF
     424              :                END DO
     425              :             END DO
     426              :          END DO
     427              : 
     428              :       END DO
     429              : 
     430           14 :       CALL cp_fm_release(single_mo_coeff)
     431              : 
     432           14 :       CALL xc_rho_set_release(rho_set, auxbas_pw_pool)
     433           14 :       CALL auxbas_pw_pool%give_back_pw(orbital)
     434           14 :       CALL auxbas_pw_pool%give_back_pw(orbital_g)
     435              : 
     436              :       !--------------------!
     437              :       ! Do the integration !
     438              :       !--------------------!
     439           34 :       DO ispin = 1, nspins
     440              : 
     441           20 :          IF (oe_corr == oe_lb) THEN
     442            0 :             CALL pw_copy(vxc_LB(ispin), vxc_SAOP(ispin))
     443           20 :          ELSE IF (oe_corr == oe_gllb) THEN
     444            0 :             CALL pw_copy(vxc_GLLB(ispin), vxc_SAOP(ispin))
     445              :          END IF
     446           20 :          CALL pw_scale(vxc_SAOP(ispin), vxc_SAOP(ispin)%pw_grid%dvol)
     447              : 
     448              :          CALL integrate_v_rspace(v_rspace=vxc_SAOP(ispin), pmat=rho_struct_ao(ispin), &
     449              :                                  hmat=ks_matrix(ispin), qs_env=qs_env, &
     450              :                                  calculate_forces=.FALSE., &
     451           34 :                                  gapw=gapw)
     452              : 
     453              :       END DO
     454              : 
     455           34 :       DO ispin = 1, nspins
     456           20 :          CALL auxbas_pw_pool%give_back_pw(vxc_SAOP(ispin))
     457           20 :          CALL auxbas_pw_pool%give_back_pw(vxc_GLLB(ispin))
     458           20 :          CALL vxc_LB(ispin)%release()
     459           34 :          CALL vxc_tmp(ispin)%release()
     460              :       END DO
     461           14 :       DEALLOCATE (vxc_GLLB, vxc_LB, vxc_tmp, orbital_density_matrix)
     462              : 
     463           14 :       DEALLOCATE (vxc_SAOP)
     464              : 
     465           14 :       CALL section_vals_release(xc_fun_section_tmp)
     466           14 :       CALL section_vals_release(xc_section_tmp)
     467           14 :       CALL section_vals_release(xc_section_orig)
     468              : 
     469              :       !-----------------------!
     470              :       ! Call the GAPW routine !
     471              :       !-----------------------!
     472           14 :       IF (gapw) THEN
     473            0 :          CALL gapw_add_atomic_saop_pot(qs_env, oe_corr)
     474              :       END IF
     475              : 
     476          350 :    END SUBROUTINE add_saop_pot
     477              : 
     478              : ! **************************************************************************************************
     479              : !> \brief ...
     480              : !> \param qs_env ...
     481              : !> \param oe_corr ...
     482              : ! **************************************************************************************************
     483            0 :    SUBROUTINE gapw_add_atomic_saop_pot(qs_env, oe_corr)
     484              : 
     485              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     486              :       INTEGER, INTENT(IN)                                :: oe_corr
     487              : 
     488              :       INTEGER                                            :: ia, iat, iatom, ikind, ir, ispin, na, &
     489              :                                                             natom, nr, ns, nspins, orb
     490              :       INTEGER, DIMENSION(2)                              :: bo, homo, ncol, nrow
     491              :       INTEGER, DIMENSION(2, 3)                           :: bounds
     492            0 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list
     493              :       LOGICAL                                            :: accint, lsd, paw_atom
     494            0 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: tau
     495              :       REAL(KIND=dp)                                      :: agr, alpha, density_cut, efac, exc, &
     496              :                                                             gradient_cut, tau_cut, we_GLLB, we_LB
     497            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: coeff_col, weight_h, weight_s
     498            0 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: dummy, e_uniform, rho_h, rho_s, vtau, &
     499            0 :          vxc_GLLB_h, vxc_GLLB_s, vxc_LB_h, vxc_LB_s, vxc_SAOP_h, vxc_SAOP_s, vxc_tmp_h, vxc_tmp_s
     500            0 :       REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER      :: drho_h, drho_s, vxg
     501            0 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     502            0 :       TYPE(cp_1d_r_p_type), DIMENSION(:), POINTER        :: mo_eigenvalues
     503            0 :       TYPE(cp_fm_p_type), ALLOCATABLE, DIMENSION(:)      :: mo_coeff
     504            0 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: single_mo_coeff
     505            0 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, orbital_density_matrix, &
     506            0 :                                                             rho_struct_ao
     507            0 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: ksmat, psmat
     508              :       TYPE(dft_control_type), POINTER                    :: dft_control
     509              :       TYPE(grid_atom_type), POINTER                      :: atomic_grid, grid_atom
     510              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis
     511              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
     512              :       TYPE(local_rho_type), POINTER                      :: local_rho_set
     513            0 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: molecular_orbitals
     514              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     515              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     516            0 :          POINTER                                         :: sab
     517              :       TYPE(oce_matrix_type), POINTER                     :: oce
     518            0 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     519              :       TYPE(qs_rho_type), POINTER                         :: rho_structure
     520            0 :       TYPE(rho_atom_coeff), DIMENSION(:), POINTER        :: dr_h, dr_s, int_hh, int_ss, r_h, r_s
     521            0 :       TYPE(rho_atom_coeff), DIMENSION(:, :), POINTER     :: r_h_d, r_s_d
     522            0 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom_set
     523              :       TYPE(rho_atom_type), POINTER                       :: rho_atom
     524              :       TYPE(section_vals_type), POINTER                   :: input, xc_fun_section_orig, &
     525              :                                                             xc_fun_section_tmp, xc_section_orig, &
     526              :                                                             xc_section_tmp
     527              :       TYPE(xc_derivative_set_type)                       :: deriv_set
     528              :       TYPE(xc_derivative_type), POINTER                  :: deriv
     529              :       TYPE(xc_rho_cflags_type)                           :: needs, needs_orbs
     530              :       TYPE(xc_rho_set_type)                              :: orb_rho_set_h, orb_rho_set_s, rho_set_h, &
     531              :                                                             rho_set_s
     532              : 
     533            0 :       NULLIFY (rho_h, rho_s, vxc_LB_h, vxc_LB_s, vxc_GLLB_h, vxc_GLLB_s, &
     534            0 :                vxc_tmp_h, vxc_tmp_s, vtau, dummy, e_uniform, drho_h, drho_s, vxg, atom_list, &
     535            0 :                atomic_kind_set, qs_kind_set, deriv, atomic_grid, rho_struct_ao, &
     536            0 :                harmonics, molecular_orbitals, rho_structure, r_h, r_s, dr_h, dr_s, &
     537            0 :                r_h_d, r_s_d, rho_atom_set, rho_atom, para_env, &
     538            0 :                mo_eigenvalues, local_rho_set, matrix_ks, &
     539            0 :                orbital_density_matrix, vxc_SAOP_h, vxc_SAOP_s)
     540              : 
     541              :       ! tau is needed for fill_rho_set, but should never be used
     542            0 :       NULLIFY (tau)
     543            0 :       NULLIFY (dft_control, oce, sab)
     544              : 
     545              :       CALL get_qs_env(qs_env, input=input, &
     546              :                       rho=rho_structure, &
     547              :                       mos=molecular_orbitals, &
     548              :                       atomic_kind_set=atomic_kind_set, &
     549              :                       qs_kind_set=qs_kind_set, &
     550              :                       rho_atom_set=rho_atom_set, &
     551              :                       matrix_ks=matrix_ks, &
     552              :                       dft_control=dft_control, &
     553              :                       para_env=para_env, &
     554            0 :                       oce=oce, sab_orb=sab)
     555              : 
     556            0 :       CALL qs_rho_get(rho_structure, rho_ao=rho_struct_ao)
     557              : 
     558            0 :       xc_section_orig => section_vals_get_subs_vals(input, "DFT%XC")
     559            0 :       CALL section_vals_retain(xc_section_orig)
     560            0 :       CALL section_vals_duplicate(xc_section_orig, xc_section_tmp)
     561              : 
     562            0 :       accint = dft_control%qs_control%gapw_control%accurate_xcint
     563              : 
     564              :       ! [SC] the following code can be traced back to SVN rev. 4296 (git:f97138b) that
     565              :       !      has removed the component 'nspins' from the derived type 'dft_control_type'.
     566              :       !      Is it worth to remove the code below in favour of 'dft_control%nspins'
     567              :       !      since its reintroduction? Note that in case of ROKS calculations,
     568              :       !      'lsd == .FALSE.' but 'dft_control%nspins == 2'.
     569            0 :       CALL section_vals_val_get(input, "DFT%LSD", l_val=lsd)
     570            0 :       IF (lsd) THEN
     571            0 :          nspins = 2
     572              :       ELSE
     573            0 :          nspins = 1
     574              :       END IF
     575              : 
     576              :       CALL section_vals_val_get(xc_section_orig, "DENSITY_CUTOFF", &
     577            0 :                                 r_val=density_cut)
     578              :       CALL section_vals_val_get(xc_section_orig, "GRADIENT_CUTOFF", &
     579            0 :                                 r_val=gradient_cut)
     580              :       CALL section_vals_val_get(xc_section_orig, "TAU_CUTOFF", &
     581            0 :                                 r_val=tau_cut)
     582              : 
     583              :       ! remap pointer
     584            0 :       ns = SIZE(rho_struct_ao)
     585            0 :       psmat(1:ns, 1:1) => rho_struct_ao(1:ns)
     586            0 :       CALL calculate_rho_atom_coeff(qs_env, psmat, rho_atom_set, qs_kind_set, oce, sab, para_env)
     587            0 :       CALL prepare_gapw_den(qs_env)
     588              : 
     589            0 :       ALLOCATE (mo_coeff(nspins), single_mo_coeff(nspins), mo_eigenvalues(nspins))
     590              : 
     591            0 :       CALL dbcsr_allocate_matrix_set(orbital_density_matrix, nspins)
     592              : 
     593            0 :       DO ispin = 1, nspins
     594              :          CALL get_mo_set(molecular_orbitals(ispin), &
     595              :                          mo_coeff=mo_coeff(ispin)%matrix, &
     596              :                          eigenvalues=mo_eigenvalues(ispin)%array, &
     597            0 :                          homo=homo(ispin))
     598              :          CALL cp_fm_create(single_mo_coeff(ispin), &
     599              :                            mo_coeff(ispin)%matrix%matrix_struct, &
     600            0 :                            "orbital density matrix")
     601              :          CALL cp_fm_get_info(single_mo_coeff(ispin), &
     602            0 :                              nrow_global=nrow(ispin), ncol_global=ncol(ispin))
     603            0 :          ALLOCATE (orbital_density_matrix(ispin)%matrix)
     604              :          CALL dbcsr_copy(orbital_density_matrix(ispin)%matrix, &
     605              :                          rho_struct_ao(ispin)%matrix, &
     606            0 :                          "orbital density")
     607              :       END DO
     608            0 :       CALL local_rho_set_create(local_rho_set)
     609              :       CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
     610            0 :                                        qs_kind_set, dft_control, para_env)
     611              : 
     612            0 :       DO ikind = 1, SIZE(atomic_kind_set)
     613            0 :          CALL get_atomic_kind(atomic_kind_set(ikind), atom_list=atom_list, natom=natom)
     614              : 
     615              :          CALL get_qs_kind(qs_kind_set(ikind), paw_atom=paw_atom, &
     616            0 :                           harmonics=harmonics, grid_atom=atomic_grid)
     617            0 :          IF (.NOT. paw_atom) CYCLE
     618              : 
     619            0 :          nr = atomic_grid%nr
     620            0 :          na = atomic_grid%ng_sphere
     621            0 :          bounds(1:2, 1:3) = 1
     622            0 :          bounds(2, 1) = na
     623            0 :          bounds(2, 2) = nr
     624              : 
     625            0 :          CALL xc_dset_create(deriv_set, local_bounds=bounds)
     626              : 
     627              :          CALL xc_rho_set_create(rho_set_h, bounds, density_cut, &
     628            0 :                                 gradient_cut, tau_cut)
     629              :          CALL xc_rho_set_create(rho_set_s, bounds, density_cut, &
     630            0 :                                 gradient_cut, tau_cut)
     631              :          CALL xc_rho_set_create(orb_rho_set_h, bounds, density_cut, &
     632            0 :                                 gradient_cut, tau_cut)
     633              :          CALL xc_rho_set_create(orb_rho_set_s, bounds, density_cut, &
     634            0 :                                 gradient_cut, tau_cut)
     635              : 
     636            0 :          CALL xc_rho_cflags_setall(needs, .FALSE.)
     637            0 :          IF (lsd) THEN
     638            0 :             CALL xb88_lsd_info(needs=needs)
     639            0 :             needs%norm_drho = .TRUE.
     640              :          ELSE
     641            0 :             CALL xb88_lda_info(needs=needs)
     642              :          END IF
     643            0 :          CALL xc_rho_set_atom_update(rho_set_h, needs, nspins, bounds)
     644            0 :          CALL xc_rho_set_atom_update(rho_set_s, needs, nspins, bounds)
     645            0 :          CALL xc_rho_cflags_setall(needs_orbs, .FALSE.)
     646            0 :          needs_orbs%rho = .TRUE.
     647            0 :          IF (lsd) needs_orbs%rho_spin = .TRUE.
     648            0 :          CALL xc_rho_set_atom_update(orb_rho_set_h, needs, nspins, bounds)
     649            0 :          CALL xc_rho_set_atom_update(orb_rho_set_s, needs, nspins, bounds)
     650              : 
     651            0 :          ALLOCATE (rho_h(1:na, 1:nr, 1:nspins), rho_s(1:na, 1:nr, 1:nspins))
     652            0 :          ALLOCATE (weight_h(1:na, 1:nr), weight_s(1:na, 1:nr))
     653            0 :          ALLOCATE (vxc_LB_h(1:na, 1:nr, 1:nspins), vxc_LB_s(1:na, 1:nr, 1:nspins))
     654            0 :          ALLOCATE (vxc_GLLB_h(1:na, 1:nr, 1:nspins), vxc_GLLB_s(1:na, 1:nr, 1:nspins))
     655            0 :          ALLOCATE (vxc_tmp_h(1:na, 1:nr, 1:nspins), vxc_tmp_s(1:na, 1:nr, 1:nspins))
     656            0 :          ALLOCATE (vxc_SAOP_h(1:na, 1:nr, 1:nspins), vxc_SAOP_s(1:na, 1:nr, 1:nspins))
     657            0 :          ALLOCATE (drho_h(1:4, 1:na, 1:nr, 1:nspins), drho_s(1:4, 1:na, 1:nr, 1:nspins))
     658              : 
     659              :          ! Distribute the atoms of this kind
     660            0 :          bo = get_limit(natom, para_env%num_pe, para_env%mepos)
     661              : 
     662            0 :          DO ir = 1, nr
     663            0 :             DO ia = 1, na
     664            0 :                weight_h(ia, ir) = atomic_grid%wr(ir)*atomic_grid%wa(ia)
     665              :             END DO
     666            0 :             IF (accint) THEN
     667            0 :                alpha = dft_control%qs_control%gapw_control%aw(ikind)
     668            0 :                agr = 1.0_dp - EXP(-alpha*atomic_grid%rad2(ir))
     669            0 :                DO ia = 1, na
     670            0 :                   weight_s(ia, ir) = atomic_grid%wr(ir)*atomic_grid%wa(ia)*agr
     671              :                END DO
     672              :             ELSE
     673            0 :                DO ia = 1, na
     674            0 :                   weight_s(ia, ir) = atomic_grid%wr(ir)*atomic_grid%wa(ia)
     675              :                END DO
     676              :             END IF
     677              :          END DO
     678              : 
     679            0 :          DO iat = 1, natom !bo(1),bo(2)
     680            0 :             iatom = atom_list(iat)
     681              : 
     682            0 :             rho_atom => rho_atom_set(iatom)
     683            0 :             NULLIFY (r_h, r_s, dr_h, dr_s, r_h_d, r_s_d)
     684              :             CALL get_rho_atom(rho_atom=rho_atom, rho_rad_h=r_h, &
     685              :                               rho_rad_s=r_s, drho_rad_h=dr_h, &
     686              :                               drho_rad_s=dr_s, rho_rad_h_d=r_h_d, &
     687            0 :                               rho_rad_s_d=r_s_d)
     688            0 :             rho_h = 0.0_dp
     689            0 :             rho_s = 0.0_dp
     690            0 :             drho_h = 0.0_dp
     691            0 :             drho_s = 0.0_dp
     692            0 :             DO ir = 1, nr
     693              :                CALL calc_rho_angular(atomic_grid, harmonics, nspins, .TRUE., &
     694              :                                      ir, r_h, r_s, rho_h, rho_s, &
     695            0 :                                      dr_h, dr_s, r_h_d, r_s_d, drho_h, drho_s)
     696              :             END DO
     697            0 :             DO ir = 1, nr
     698            0 :                CALL fill_rho_set(rho_set_h, lsd, nspins, needs, rho_h, drho_h, tau, na, ir)
     699            0 :                CALL fill_rho_set(rho_set_s, lsd, nspins, needs, rho_s, drho_s, tau, na, ir)
     700              :             END DO
     701              : 
     702              :             !-----------------------------!
     703              :             ! 1. Slater exchange for LB94 !
     704              :             !-----------------------------!
     705              :             xc_fun_section_orig => section_vals_get_subs_vals(xc_section_orig, &
     706            0 :                                                               "XC_FUNCTIONAL")
     707            0 :             CALL section_vals_create(xc_fun_section_tmp, xc_fun_section_orig%section)
     708              :             CALL section_vals_val_set(xc_fun_section_tmp, "_SECTION_PARAMETERS_", &
     709            0 :                                       i_val=xc_funct_no_shortcut)
     710              :             CALL section_vals_val_set(xc_fun_section_tmp, "XALPHA%_SECTION_PARAMETERS_", &
     711            0 :                                       l_val=.TRUE.)
     712              :             CALL section_vals_set_subs_vals(xc_section_tmp, "XC_FUNCTIONAL", &
     713            0 :                                             xc_fun_section_tmp)
     714              : 
     715              :             !---------------------!
     716              :             ! Both: hard and soft !
     717              :             !---------------------!
     718            0 :             CALL xc_dset_zero_all(deriv_set)
     719              :             CALL vxc_of_r_new(xc_fun_section_tmp, rho_set_h, deriv_set, 1, needs, &
     720            0 :                               weight_h, lsd, na, nr, exc, vxc_tmp_h, vxg, vtau)
     721            0 :             CALL xc_dset_zero_all(deriv_set)
     722              :             CALL vxc_of_r_new(xc_fun_section_tmp, rho_set_s, deriv_set, 1, needs, &
     723            0 :                               weight_s, lsd, na, nr, exc, vxc_tmp_s, vxg, vtau)
     724              : 
     725              :             !-------------------------------------------!
     726              :             ! 2. PZ correlation for LB94 and ec_uniform !
     727              :             !-------------------------------------------!
     728              :             CALL section_vals_val_set(xc_fun_section_tmp, "XALPHA%_SECTION_PARAMETERS_", &
     729            0 :                                       l_val=.FALSE.)
     730              :             CALL section_vals_val_set(xc_fun_section_tmp, "PZ81%_SECTION_PARAMETERS_", &
     731            0 :                                       l_val=.TRUE.)
     732              : 
     733              :             !------!
     734              :             ! Hard !
     735              :             !------!
     736            0 :             CALL xc_dset_zero_all(deriv_set)
     737              :             CALL vxc_of_r_new(xc_fun_section_tmp, rho_set_h, deriv_set, 1, needs, &
     738            0 :                               weight_h, lsd, na, nr, exc, vxc_LB_h, vxg, vtau)
     739            0 :             vxc_LB_h = vxc_LB_h + alpha*vxc_tmp_h
     740            0 :             DO ispin = 1, nspins
     741            0 :                dummy => vxc_tmp_h(:, :, ispin:ispin)
     742            0 :                CALL add_lb_pot(dummy, rho_set_h, lsd, ispin)
     743            0 :                vxc_LB_h(:, :, ispin) = vxc_LB_h(:, :, ispin) - weight_h(:, :)*vxc_tmp_h(:, :, ispin)
     744              :             END DO
     745            0 :             NULLIFY (dummy)
     746              : 
     747            0 :             vxc_GLLB_h = 0.0_dp
     748            0 :             deriv => xc_dset_get_derivative(deriv_set, [INTEGER::])
     749            0 :             CPASSERT(ASSOCIATED(deriv))
     750            0 :             CALL xc_derivative_get(deriv, deriv_data=e_uniform)
     751            0 :             DO ispin = 1, nspins
     752            0 :                dummy => vxc_GLLB_h(:, :, ispin:ispin)
     753            0 :                CALL calc_2excpbe(dummy, rho_set_h, e_uniform, lsd)
     754            0 :                vxc_GLLB_h(:, :, ispin) = vxc_GLLB_h(:, :, ispin)*weight_h(:, :)
     755              :             END DO
     756            0 :             NULLIFY (deriv, dummy, e_uniform)
     757              : 
     758              :             !------!
     759              :             ! Soft !
     760              :             !------!
     761            0 :             CALL xc_dset_zero_all(deriv_set)
     762              :             CALL vxc_of_r_new(xc_fun_section_tmp, rho_set_s, deriv_set, 1, needs, &
     763            0 :                               weight_s, lsd, na, nr, exc, vxc_LB_s, vxg, vtau)
     764              : 
     765            0 :             vxc_LB_s = vxc_LB_s + alpha*vxc_tmp_s
     766            0 :             DO ispin = 1, nspins
     767            0 :                dummy => vxc_tmp_s(:, :, ispin:ispin)
     768            0 :                CALL add_lb_pot(dummy, rho_set_s, lsd, ispin)
     769            0 :                vxc_LB_s(:, :, ispin) = vxc_LB_s(:, :, ispin) - weight_s(:, :)*vxc_tmp_s(:, :, ispin)
     770              :             END DO
     771            0 :             NULLIFY (dummy)
     772              : 
     773            0 :             vxc_GLLB_s = 0.0_dp
     774            0 :             deriv => xc_dset_get_derivative(deriv_set, [INTEGER::])
     775            0 :             CPASSERT(ASSOCIATED(deriv))
     776            0 :             CALL xc_derivative_get(deriv, deriv_data=e_uniform)
     777            0 :             DO ispin = 1, nspins
     778            0 :                dummy => vxc_GLLB_s(:, :, ispin:ispin)
     779            0 :                CALL calc_2excpbe(dummy, rho_set_s, e_uniform, lsd)
     780            0 :                vxc_GLLB_s(:, :, ispin) = vxc_GLLB_s(:, :, ispin)*weight_s(:, :)
     781              :             END DO
     782            0 :             NULLIFY (deriv, dummy, e_uniform)
     783              : 
     784              :             !------------------!
     785              :             ! Now the orbitals !
     786              :             !------------------!
     787            0 :             vxc_tmp_h = 0.0_dp; vxc_tmp_s = 0.0_dp
     788              : 
     789            0 :             DO ispin = 1, nspins
     790              : 
     791            0 :                DO orb = 1, homo(ispin) - 1
     792              : 
     793            0 :                   ALLOCATE (coeff_col(nrow(ispin), 1))
     794              : 
     795              :                   efac = K_rho*SQRT(mo_eigenvalues(ispin)%array(homo(ispin)) - &
     796            0 :                                     mo_eigenvalues(ispin)%array(orb))
     797            0 :                   IF (.NOT. lsd) efac = 2.0_dp*efac
     798              : 
     799            0 :                   CALL cp_fm_set_all(single_mo_coeff(ispin), 0.0_dp)
     800              :                   CALL cp_fm_get_submatrix(mo_coeff(ispin)%matrix, coeff_col, &
     801            0 :                                            1, orb, nrow(ispin), 1)
     802              :                   CALL cp_fm_set_submatrix(single_mo_coeff(ispin), coeff_col, &
     803            0 :                                            1, orb)
     804            0 :                   CALL dbcsr_set(orbital_density_matrix(ispin)%matrix, 0.0_dp)
     805              :                   CALL cp_dbcsr_plus_fm_fm_t(orbital_density_matrix(ispin)%matrix, &
     806              :                                              matrix_v=single_mo_coeff(ispin), &
     807              :                                              ncol=ncol(ispin), &
     808            0 :                                              alpha=1.0_dp)
     809              : 
     810            0 :                   DEALLOCATE (coeff_col)
     811              : 
     812              :                   ! This calculates the CPC and density on the grids for every atom even though
     813              :                   ! we need it only for iatom at the moment. It seems that to circumvent this,
     814              :                   ! the routines must be adapted to calculate just iatom
     815              :                   ! remap pointer
     816            0 :                   ns = SIZE(orbital_density_matrix)
     817            0 :                   psmat(1:ns, 1:1) => orbital_density_matrix(1:ns)
     818            0 :                   CALL calculate_rho_atom_coeff(qs_env, psmat, local_rho_set%rho_atom_set, qs_kind_set, oce, sab, para_env)
     819            0 :                   CALL prepare_gapw_den(qs_env, local_rho_set, .FALSE.)
     820              : 
     821            0 :                   rho_atom => local_rho_set%rho_atom_set(iatom)
     822            0 :                   NULLIFY (r_h, r_s, dr_h, dr_s, r_h_d, r_s_d)
     823            0 :                   CALL get_rho_atom(rho_atom=rho_atom, rho_rad_h=r_h, rho_rad_s=r_s)
     824            0 :                   rho_h = 0.0_dp
     825            0 :                   rho_s = 0.0_dp
     826            0 :                   drho_h = 0.0_dp
     827            0 :                   drho_s = 0.0_dp
     828            0 :                   DO ir = 1, nr
     829              :                      CALL calc_rho_angular(atomic_grid, harmonics, nspins, .FALSE., &
     830              :                                            ir, r_h, r_s, rho_h, rho_s, &
     831            0 :                                            dr_h, dr_s, r_h_d, r_s_d, drho_h, drho_s)
     832              :                   END DO
     833            0 :                   DO ir = 1, nr
     834            0 :                      CALL fill_rho_set(orb_rho_set_h, lsd, nspins, needs_orbs, rho_h, drho_h, tau, na, ir)
     835            0 :                      CALL fill_rho_set(orb_rho_set_s, lsd, nspins, needs_orbs, rho_s, drho_s, tau, na, ir)
     836              :                   END DO
     837              : 
     838            0 :                   IF (lsd) THEN
     839            0 :                      IF (ispin == 1) THEN
     840            0 :                         vxc_tmp_h(:, :, 1) = vxc_tmp_h(:, :, 1) + efac*orb_rho_set_h%rhoa(:, :, 1)
     841            0 :                         vxc_tmp_s(:, :, 1) = vxc_tmp_s(:, :, 1) + efac*orb_rho_set_s%rhoa(:, :, 1)
     842              :                      ELSE
     843            0 :                         vxc_tmp_h(:, :, 2) = vxc_tmp_h(:, :, 2) + efac*orb_rho_set_h%rhob(:, :, 1)
     844            0 :                         vxc_tmp_s(:, :, 2) = vxc_tmp_s(:, :, 2) + efac*orb_rho_set_s%rhob(:, :, 1)
     845              :                      END IF
     846              :                   ELSE
     847            0 :                      vxc_tmp_h(:, :, 1) = vxc_tmp_h(:, :, 1) + efac*orb_rho_set_h%rho(:, :, 1)
     848            0 :                      vxc_tmp_s(:, :, 1) = vxc_tmp_s(:, :, 1) + efac*orb_rho_set_s%rho(:, :, 1)
     849              :                   END IF
     850              : 
     851              :                END DO ! orb
     852              : 
     853              :             END DO ! ispin
     854              : 
     855            0 :             IF (lsd) THEN
     856            0 :                DO ir = 1, nr
     857            0 :                   DO ia = 1, na
     858            0 :                      IF (rho_set_h%rhoa(ia, ir, 1) > rho_set_h%rho_cutoff) &
     859              :                         vxc_GLLB_h(ia, ir, 1) = vxc_GLLB_h(ia, ir, 1) + &
     860            0 :                                                 weight_h(ia, ir)*vxc_tmp_h(ia, ir, 1)/rho_set_h%rhoa(ia, ir, 1)
     861            0 :                      IF (rho_set_h%rhob(ia, ir, 1) > rho_set_h%rho_cutoff) &
     862              :                         vxc_GLLB_h(ia, ir, 2) = vxc_GLLB_h(ia, ir, 2) + &
     863            0 :                                                 weight_h(ia, ir)*vxc_tmp_h(ia, ir, 2)/rho_set_h%rhob(ia, ir, 1)
     864            0 :                      IF (rho_set_s%rhoa(ia, ir, 1) > rho_set_s%rho_cutoff) &
     865              :                         vxc_GLLB_s(ia, ir, 1) = vxc_GLLB_s(ia, ir, 1) + &
     866            0 :                                                 weight_s(ia, ir)*vxc_tmp_s(ia, ir, 1)/rho_set_s%rhoa(ia, ir, 1)
     867            0 :                      IF (rho_set_s%rhob(ia, ir, 1) > rho_set_s%rho_cutoff) &
     868              :                         vxc_GLLB_s(ia, ir, 2) = vxc_GLLB_s(ia, ir, 2) + &
     869            0 :                                                 weight_s(ia, ir)*vxc_tmp_s(ia, ir, 2)/rho_set_s%rhob(ia, ir, 1)
     870              :                   END DO
     871              :                END DO
     872              :             ELSE
     873            0 :                DO ir = 1, nr
     874            0 :                   DO ia = 1, na
     875            0 :                      IF (rho_set_h%rho(ia, ir, 1) > rho_set_h%rho_cutoff) &
     876              :                         vxc_GLLB_h(ia, ir, 1) = vxc_GLLB_h(ia, ir, 1) + &
     877            0 :                                                 weight_h(ia, ir)*vxc_tmp_h(ia, ir, 1)/rho_set_h%rho(ia, ir, 1)
     878            0 :                      IF (rho_set_s%rho(ia, ir, 1) > rho_set_s%rho_cutoff) &
     879              :                         vxc_GLLB_s(ia, ir, 1) = vxc_GLLB_s(ia, ir, 1) + &
     880            0 :                                                 weight_s(ia, ir)*vxc_tmp_s(ia, ir, 1)/rho_set_s%rho(ia, ir, 1)
     881              :                   END DO
     882              :                END DO
     883              :             END IF
     884              : 
     885            0 :             vxc_SAOP_h = 0.0_dp; vxc_SAOP_s = 0.0_dp
     886              : 
     887            0 :             DO ispin = 1, nspins
     888              : 
     889            0 :                DO orb = 1, homo(ispin)
     890              : 
     891            0 :                   ALLOCATE (coeff_col(nrow(ispin), 1))
     892              : 
     893              :                   we_LB = EXP(-2.0_dp*(mo_eigenvalues(ispin)%array(homo(ispin)) - &
     894            0 :                                        mo_eigenvalues(ispin)%array(orb))**2)
     895            0 :                   we_GLLB = 1.0_dp - we_LB
     896            0 :                   IF (.NOT. lsd) THEN
     897            0 :                      we_LB = 2.0_dp*we_LB
     898            0 :                      we_GLLB = 2.0_dp*we_GLLB
     899              :                   END IF
     900              : 
     901              :                   vxc_tmp_h(:, :, ispin) = we_LB*vxc_LB_h(:, :, ispin) + &
     902            0 :                                            we_GLLB*vxc_GLLB_h(:, :, ispin)
     903              :                   vxc_tmp_s(:, :, ispin) = we_LB*vxc_LB_s(:, :, ispin) + &
     904            0 :                                            we_GLLB*vxc_GLLB_s(:, :, ispin)
     905              : 
     906            0 :                   CALL cp_fm_set_all(single_mo_coeff(ispin), 0.0_dp)
     907              :                   CALL cp_fm_get_submatrix(mo_coeff(ispin)%matrix, coeff_col, &
     908            0 :                                            1, orb, nrow(ispin), 1)
     909              :                   CALL cp_fm_set_submatrix(single_mo_coeff(ispin), coeff_col, &
     910            0 :                                            1, orb)
     911            0 :                   CALL dbcsr_set(orbital_density_matrix(ispin)%matrix, 0.0_dp)
     912              :                   CALL cp_dbcsr_plus_fm_fm_t(orbital_density_matrix(ispin)%matrix, &
     913              :                                              matrix_v=single_mo_coeff(ispin), &
     914              :                                              ncol=ncol(ispin), &
     915            0 :                                              alpha=1.0_dp)
     916              : 
     917            0 :                   DEALLOCATE (coeff_col)
     918              : 
     919              :                   ! This calculates the CPC and density on the grids for every atom even though
     920              :                   ! we need it only for iatom at the moment. It seems that to circumvent this,
     921              :                   ! the routines must be adapted to calculate just iatom
     922              :                   ! remap pointer
     923            0 :                   ns = SIZE(orbital_density_matrix)
     924            0 :                   psmat(1:ns, 1:1) => orbital_density_matrix(1:ns)
     925            0 :                   CALL calculate_rho_atom_coeff(qs_env, psmat, local_rho_set%rho_atom_set, qs_kind_set, oce, sab, para_env)
     926            0 :                   CALL prepare_gapw_den(qs_env, local_rho_set, .FALSE.)
     927              : 
     928            0 :                   rho_atom => local_rho_set%rho_atom_set(iatom)
     929            0 :                   NULLIFY (r_h, r_s, dr_h, dr_s, r_h_d, r_s_d)
     930            0 :                   CALL get_rho_atom(rho_atom=rho_atom, rho_rad_h=r_h, rho_rad_s=r_s)
     931            0 :                   rho_h = 0.0_dp
     932            0 :                   rho_s = 0.0_dp
     933            0 :                   drho_h = 0.0_dp
     934            0 :                   drho_s = 0.0_dp
     935            0 :                   DO ir = 1, nr
     936              :                      CALL calc_rho_angular(atomic_grid, harmonics, nspins, .FALSE., &
     937              :                                            ir, r_h, r_s, rho_h, rho_s, &
     938            0 :                                            dr_h, dr_s, r_h_d, r_s_d, drho_h, drho_s)
     939              :                   END DO
     940            0 :                   DO ir = 1, nr
     941            0 :                      CALL fill_rho_set(orb_rho_set_h, lsd, nspins, needs_orbs, rho_h, drho_h, tau, na, ir)
     942            0 :                      CALL fill_rho_set(orb_rho_set_s, lsd, nspins, needs_orbs, rho_s, drho_s, tau, na, ir)
     943              :                   END DO
     944              : 
     945            0 :                   IF (lsd) THEN
     946            0 :                      IF (ispin == 1) THEN
     947            0 :                         vxc_SAOP_h(:, :, 1) = vxc_SAOP_h(:, :, 1) + vxc_tmp_h(:, :, 1)*orb_rho_set_h%rhoa(:, :, 1)
     948            0 :                         vxc_SAOP_s(:, :, 1) = vxc_SAOP_s(:, :, 1) + vxc_tmp_s(:, :, 1)*orb_rho_set_s%rhoa(:, :, 1)
     949              :                      ELSE
     950            0 :                         vxc_SAOP_h(:, :, 2) = vxc_SAOP_h(:, :, 2) + vxc_tmp_h(:, :, 2)*orb_rho_set_h%rhob(:, :, 1)
     951            0 :                         vxc_SAOP_s(:, :, 2) = vxc_SAOP_s(:, :, 2) + vxc_tmp_s(:, :, 2)*orb_rho_set_s%rhob(:, :, 1)
     952              :                      END IF
     953              :                   ELSE
     954            0 :                      vxc_SAOP_h(:, :, 1) = vxc_SAOP_h(:, :, 1) + vxc_tmp_h(:, :, 1)*orb_rho_set_h%rho(:, :, 1)
     955            0 :                      vxc_SAOP_s(:, :, 1) = vxc_SAOP_s(:, :, 1) + vxc_tmp_s(:, :, 1)*orb_rho_set_s%rho(:, :, 1)
     956              :                   END IF
     957              : 
     958              :                END DO ! orb
     959              : 
     960              :             END DO ! ispin
     961              : 
     962            0 :             IF (lsd) THEN
     963            0 :                DO ir = 1, nr
     964            0 :                   DO ia = 1, na
     965            0 :                      IF (rho_set_h%rhoa(ia, ir, 1) > rho_set_h%rho_cutoff) THEN
     966            0 :                         vxc_SAOP_h(ia, ir, 1) = vxc_SAOP_h(ia, ir, 1)/rho_set_h%rhoa(ia, ir, 1)
     967              :                      ELSE
     968            0 :                         vxc_SAOP_h(ia, ir, 1) = 0.0_dp
     969              :                      END IF
     970            0 :                      IF (rho_set_h%rhob(ia, ir, 1) > rho_set_h%rho_cutoff) THEN
     971            0 :                         vxc_SAOP_h(ia, ir, 2) = vxc_SAOP_h(ia, ir, 2)/rho_set_h%rhob(ia, ir, 1)
     972              :                      ELSE
     973            0 :                         vxc_SAOP_h(ia, ir, 2) = 0.0_dp
     974              :                      END IF
     975            0 :                      IF (rho_set_s%rhoa(ia, ir, 1) > rho_set_s%rho_cutoff) THEN
     976            0 :                         vxc_SAOP_s(ia, ir, 1) = vxc_SAOP_s(ia, ir, 1)/rho_set_s%rhoa(ia, ir, 1)
     977              :                      ELSE
     978            0 :                         vxc_SAOP_s(ia, ir, 1) = 0.0_dp
     979              :                      END IF
     980            0 :                      IF (rho_set_s%rhob(ia, ir, 1) > rho_set_s%rho_cutoff) THEN
     981            0 :                         vxc_SAOP_s(ia, ir, 2) = vxc_SAOP_s(ia, ir, 2)/rho_set_s%rhob(ia, ir, 1)
     982              :                      ELSE
     983            0 :                         vxc_SAOP_s(ia, ir, 2) = 0.0_dp
     984              :                      END IF
     985              :                   END DO
     986              :                END DO
     987              :             ELSE
     988            0 :                DO ir = 1, nr
     989            0 :                   DO ia = 1, na
     990            0 :                      IF (rho_set_h%rho(ia, ir, 1) > rho_set_h%rho_cutoff) THEN
     991            0 :                         vxc_SAOP_h(ia, ir, 1) = vxc_SAOP_h(ia, ir, 1)/rho_set_h%rho(ia, ir, 1)
     992              :                      ELSE
     993            0 :                         vxc_SAOP_h(ia, ir, 1) = 0.0_dp
     994              :                      END IF
     995            0 :                      IF (rho_set_s%rho(ia, ir, 1) > rho_set_s%rho_cutoff) THEN
     996            0 :                         vxc_SAOP_s(ia, ir, 1) = vxc_SAOP_s(ia, ir, 1)/rho_set_s%rho(ia, ir, 1)
     997              :                      ELSE
     998            0 :                         vxc_SAOP_s(ia, ir, 1) = 0.0_dp
     999              :                      END IF
    1000              :                   END DO
    1001              :                END DO
    1002              :             END IF
    1003              : 
    1004            0 :             rho_atom => rho_atom_set(iatom)
    1005            0 :             CALL get_rho_atom(rho_atom=rho_atom, ga_Vlocal_gb_h=int_hh, ga_Vlocal_gb_s=int_ss)
    1006              :             CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis, &
    1007            0 :                              harmonics=harmonics, grid_atom=grid_atom)
    1008            0 :             SELECT CASE (oe_corr)
    1009              :             CASE (oe_lb)
    1010            0 :                CALL gaVxcgb_noGC(vxc_LB_h, vxc_LB_s, int_hh, int_ss, grid_atom, orb_basis, harmonics, nspins)
    1011              :             CASE (oe_gllb)
    1012            0 :                CALL gaVxcgb_noGC(vxc_GLLB_h, vxc_GLLB_s, int_hh, int_ss, grid_atom, orb_basis, harmonics, nspins)
    1013              :             CASE (oe_saop)
    1014            0 :                CALL gaVxcgb_noGC(vxc_SAOP_h, vxc_SAOP_s, int_hh, int_ss, grid_atom, orb_basis, harmonics, nspins)
    1015              :             CASE default
    1016            0 :                CPABORT("Unknown correction!")
    1017              :             END SELECT
    1018              : 
    1019              :          END DO
    1020              : 
    1021            0 :          DEALLOCATE (rho_h, rho_s, weight_h, weight_s)
    1022            0 :          DEALLOCATE (vxc_LB_h, vxc_LB_s)
    1023            0 :          DEALLOCATE (vxc_GLLB_h, vxc_GLLB_s)
    1024            0 :          DEALLOCATE (vxc_tmp_h, vxc_tmp_s)
    1025            0 :          DEALLOCATE (vxc_SAOP_h, vxc_SAOP_s)
    1026            0 :          DEALLOCATE (drho_h, drho_s)
    1027              : 
    1028            0 :          CALL xc_dset_release(deriv_set)
    1029            0 :          CALL xc_rho_set_release(rho_set_h)
    1030            0 :          CALL xc_rho_set_release(rho_set_s)
    1031            0 :          CALL xc_rho_set_release(orb_rho_set_h)
    1032            0 :          CALL xc_rho_set_release(orb_rho_set_s)
    1033              : 
    1034              :       END DO
    1035              : 
    1036              :       ! remap pointer
    1037            0 :       ns = SIZE(matrix_ks)
    1038            0 :       ksmat(1:ns, 1:1) => matrix_ks(1:ns)
    1039            0 :       ns = SIZE(rho_struct_ao)
    1040            0 :       psmat(1:ns, 1:1) => rho_struct_ao(1:ns)
    1041              : 
    1042            0 :       CALL update_ks_atom(qs_env, ksmat, psmat, forces=.FALSE.)
    1043              : 
    1044              :       !---------!
    1045              :       ! Cleanup !
    1046              :       !---------!
    1047            0 :       CALL section_vals_release(xc_fun_section_tmp)
    1048            0 :       CALL section_vals_release(xc_section_tmp)
    1049            0 :       CALL section_vals_release(xc_section_orig)
    1050              : 
    1051            0 :       CALL local_rho_set_release(local_rho_set)
    1052            0 :       CALL cp_fm_release(single_mo_coeff)
    1053            0 :       DEALLOCATE (mo_coeff, mo_eigenvalues)
    1054            0 :       CALL dbcsr_deallocate_matrix_set(orbital_density_matrix)
    1055              : 
    1056            0 :    END SUBROUTINE gapw_add_atomic_saop_pot
    1057              : 
    1058              : ! **************************************************************************************************
    1059              : !> \brief ...
    1060              : !> \param pot ...
    1061              : !> \param rho_set ...
    1062              : !> \param lsd ...
    1063              : !> \param spin ...
    1064              : ! **************************************************************************************************
    1065           20 :    SUBROUTINE add_lb_pot(pot, rho_set, lsd, spin)
    1066              : 
    1067              :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: pot
    1068              :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
    1069              :       LOGICAL, INTENT(IN)                                :: lsd
    1070              :       INTEGER, INTENT(IN)                                :: spin
    1071              : 
    1072              :       REAL(KIND=dp), PARAMETER                           :: ob3 = 1.0_dp/3.0_dp
    1073              : 
    1074              :       INTEGER                                            :: i, j, k
    1075              :       INTEGER, DIMENSION(2, 3)                           :: bo
    1076              :       REAL(KIND=dp)                                      :: n, n_13, x, x2
    1077              : 
    1078          200 :       bo = rho_set%local_bounds
    1079              : 
    1080          694 :       DO k = bo(1, 3), bo(2, 3)
    1081        24228 :          DO j = bo(1, 2), bo(2, 2)
    1082       447395 :             DO i = bo(1, 1), bo(2, 1)
    1083       446721 :                IF (.NOT. lsd) THEN
    1084        73875 :                   IF (rho_set%rho(i, j, k) > rho_set%rho_cutoff) THEN
    1085        73875 :                      n = rho_set%rho(i, j, k)/2.0_dp
    1086        73875 :                      n_13 = n**ob3
    1087        73875 :                      x = (rho_set%norm_drho(i, j, k)/2.0_dp)/(n*n_13)
    1088        73875 :                      x2 = x*x
    1089        73875 :                      pot(i, j, k) = beta*x2*n_13/(1.0_dp + 3.0_dp*beta*x*LOG(x + SQRT(x2 + 1.0_dp)))
    1090              :                   END IF
    1091              :                ELSE
    1092       349312 :                   IF (spin == 1) THEN
    1093       174656 :                      IF (rho_set%rhoa(i, j, k) > rho_set%rho_cutoff) THEN
    1094       174656 :                         n_13 = rho_set%rhoa_1_3(i, j, k)
    1095       174656 :                         x = rho_set%norm_drhoa(i, j, k)/(rho_set%rhoa(i, j, k)*n_13)
    1096       174656 :                         x2 = x*x
    1097       174656 :                         pot(i, j, k) = beta*x2*n_13/(1.0_dp + 3.0_dp*beta*x*LOG(SQRT(x2 + 1.0_dp) + x))
    1098              :                      END IF
    1099       174656 :                   ELSE IF (spin == 2) THEN
    1100       174656 :                      IF (rho_set%rhob(i, j, k) > rho_set%rho_cutoff) THEN
    1101       174656 :                         n_13 = rho_set%rhob_1_3(i, j, k)
    1102       174656 :                         x = rho_set%norm_drhob(i, j, k)/(rho_set%rhob(i, j, k)*n_13)
    1103       174656 :                         x2 = x*x
    1104       174656 :                         pot(i, j, k) = beta*x2*n_13/(1.0_dp + 3.0_dp*beta*x*LOG(SQRT(x2 + 1.0_dp) + x))
    1105              :                      END IF
    1106              :                   END IF
    1107              :                END IF
    1108              :             END DO
    1109              :          END DO
    1110              :       END DO
    1111              : 
    1112           20 :    END SUBROUTINE add_lb_pot
    1113              : 
    1114              : ! **************************************************************************************************
    1115              : !> \brief ...
    1116              : !> \param pot ...
    1117              : !> \param rho_set ...
    1118              : !> \param e_uniform ...
    1119              : !> \param lsd ...
    1120              : ! **************************************************************************************************
    1121           20 :    SUBROUTINE calc_2excpbe(pot, rho_set, e_uniform, lsd)
    1122              : 
    1123              :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: pot
    1124              :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
    1125              :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: e_uniform
    1126              :       LOGICAL, INTENT(IN)                                :: lsd
    1127              : 
    1128              :       INTEGER                                            :: i, j, k
    1129              :       INTEGER, DIMENSION(2, 3)                           :: bo
    1130              :       REAL(KIND=dp)                                      :: e_unif, rho
    1131              : 
    1132          200 :       bo = rho_set%local_bounds
    1133              : 
    1134          694 :       DO k = bo(1, 3), bo(2, 3)
    1135        24228 :          DO j = bo(1, 2), bo(2, 2)
    1136       447395 :             DO i = bo(1, 1), bo(2, 1)
    1137       446721 :                IF (.NOT. lsd) THEN
    1138        73875 :                   IF (rho_set%rho(i, j, k) > rho_set%rho_cutoff) THEN
    1139        73875 :                      e_unif = e_uniform(i, j, k)/rho_set%rho(i, j, k)
    1140              :                   ELSE
    1141            0 :                      e_unif = 0.0_dp
    1142              :                   END IF
    1143              :                   pot(i, j, k) = &
    1144              :                      2.0_dp* &
    1145              :                      calc_ecpbe_r(rho_set%rho(i, j, k), rho_set%norm_drho(i, j, k), &
    1146              :                                   e_unif, rho_set%rho_cutoff, rho_set%drho_cutoff) + &
    1147              :                      2.0_dp* &
    1148              :                      calc_expbe_r(rho_set%rho(i, j, k), rho_set%norm_drho(i, j, k), &
    1149        73875 :                                   rho_set%rho_cutoff, rho_set%drho_cutoff)
    1150              :                ELSE
    1151       349312 :                   rho = rho_set%rhoa(i, j, k) + rho_set%rhob(i, j, k)
    1152       349312 :                   IF (rho > rho_set%rho_cutoff) THEN
    1153       349312 :                      e_unif = e_uniform(i, j, k)/rho
    1154              :                   ELSE
    1155            0 :                      e_unif = 0.0_dp
    1156              :                   END IF
    1157              :                   pot(i, j, k) = &
    1158              :                      2.0_dp* &
    1159              :                      calc_ecpbe_u(rho_set%rhoa(i, j, k), rho_set%rhob(i, j, k), rho_set%norm_drho(i, j, k), &
    1160              :                                   e_unif, &
    1161              :                                   rho_set%rho_cutoff, rho_set%drho_cutoff) + &
    1162              :                      2.0_dp* &
    1163              :                      calc_expbe_u(rho_set%rhoa(i, j, k), rho_set%rhob(i, j, k), rho_set%norm_drho(i, j, k), &
    1164       349312 :                                   rho_set%rho_cutoff, rho_set%drho_cutoff)
    1165              :                END IF
    1166              :             END DO
    1167              :          END DO
    1168              :       END DO
    1169              : 
    1170           20 :    END SUBROUTINE calc_2excpbe
    1171              : 
    1172              : ! **************************************************************************************************
    1173              : !> \brief ...
    1174              : !> \param ra ...
    1175              : !> \param rb ...
    1176              : !> \param ngr ...
    1177              : !> \param ec_unif ...
    1178              : !> \param rc ...
    1179              : !> \param ngrc ...
    1180              : !> \return ...
    1181              : ! **************************************************************************************************
    1182       349312 :    FUNCTION calc_ecpbe_u(ra, rb, ngr, ec_unif, rc, ngrc) RESULT(res)
    1183              : 
    1184              :       REAL(kind=dp), INTENT(in)                          :: ra, rb, ngr, ec_unif, rc, ngrc
    1185              :       REAL(kind=dp)                                      :: res
    1186              : 
    1187              :       REAL(kind=dp), PARAMETER                           :: ob3 = 1.0_dp/3.0_dp, tb3 = 2.0_dp/3.0_dp
    1188              : 
    1189              :       REAL(kind=dp)                                      :: A, At2, H, kf, kl, ks, phi, phi3, r, t2, &
    1190              :                                                             zeta
    1191              : 
    1192       349312 :       r = ra + rb
    1193       349312 :       H = 0.0_dp
    1194       349312 :       IF (r > rc .AND. ngr > ngrc) THEN
    1195       349312 :          zeta = (ra - rb)/r
    1196       349312 :          IF (zeta > 1.0_dp) zeta = 1.0_dp ! machine precision problem
    1197       349312 :          IF (zeta < -1.0_dp) zeta = -1.0_dp ! machine precision problem
    1198       349312 :          phi = ((1.0_dp + zeta)**tb3 + (1.0_dp - zeta)**tb3)/2.0_dp
    1199       349312 :          phi3 = phi*phi*phi
    1200       349312 :          kf = (3.0_dp*r*pi*pi)**ob3
    1201       349312 :          ks = SQRT(4.0_dp*kf/pi)
    1202       349312 :          t2 = (ngr/(2.0_dp*phi*ks*r))**2
    1203       349312 :          A = beta_ec/gamma_saop/(EXP(-ec_unif/(gamma_saop*phi3)) - 1.0_dp)
    1204       349312 :          At2 = A*t2
    1205       349312 :          kl = (1.0_dp + At2)/(1.0_dp + At2 + At2*At2)
    1206       349312 :          H = gamma_saop*LOG(1.0_dp + beta_ec/gamma_saop*t2*kl)
    1207              :       END IF
    1208       349312 :       res = ec_unif + H
    1209              : 
    1210       349312 :    END FUNCTION calc_ecpbe_u
    1211              : 
    1212              : ! **************************************************************************************************
    1213              : !> \brief ...
    1214              : !> \param r ...
    1215              : !> \param ngr ...
    1216              : !> \param ec_unif ...
    1217              : !> \param rc ...
    1218              : !> \param ngrc ...
    1219              : !> \return ...
    1220              : ! **************************************************************************************************
    1221        73875 :    FUNCTION calc_ecpbe_r(r, ngr, ec_unif, rc, ngrc) RESULT(res)
    1222              : 
    1223              :       REAL(kind=dp), INTENT(in)                          :: r, ngr, ec_unif, rc, ngrc
    1224              :       REAL(kind=dp)                                      :: res
    1225              : 
    1226              :       REAL(kind=dp)                                      :: A, At2, H, kf, kl, ks, t2
    1227              : 
    1228        73875 :       H = 0.0_dp
    1229        73875 :       IF (r > rc .AND. ngr > ngrc) THEN
    1230        73875 :          kf = (3.0_dp*r*pi*pi)**(1.0_dp/3.0_dp)
    1231        73875 :          ks = SQRT(4.0_dp*kf/pi)
    1232        73875 :          t2 = (ngr/(2.0_dp*ks*r))**2
    1233        73875 :          A = beta_ec/gamma_saop/(EXP(-ec_unif/gamma_saop) - 1.0_dp)
    1234        73875 :          At2 = A*t2
    1235        73875 :          kl = (1.0_dp + At2)/(1.0_dp + At2 + At2*At2)
    1236        73875 :          H = gamma_saop*LOG(1.0_dp + beta_ec/gamma_saop*t2*kl)
    1237              :       END IF
    1238        73875 :       res = ec_unif + H
    1239              : 
    1240        73875 :    END FUNCTION calc_ecpbe_r
    1241              : 
    1242              : ! **************************************************************************************************
    1243              : !> \brief ...
    1244              : !> \param ra ...
    1245              : !> \param rb ...
    1246              : !> \param ngr ...
    1247              : !> \param rc ...
    1248              : !> \param ngrc ...
    1249              : !> \return ...
    1250              : ! **************************************************************************************************
    1251       349312 :    FUNCTION calc_expbe_u(ra, rb, ngr, rc, ngrc) RESULT(res)
    1252              : 
    1253              :       REAL(kind=dp), INTENT(in)                          :: ra, rb, ngr, rc, ngrc
    1254              :       REAL(kind=dp)                                      :: res
    1255              : 
    1256              :       REAL(kind=dp)                                      :: r
    1257              : 
    1258       349312 :       r = ra + rb
    1259       349312 :       res = calc_expbe_r(r, ngr, rc, ngrc)
    1260              : 
    1261       349312 :    END FUNCTION calc_expbe_u
    1262              : 
    1263              : ! **************************************************************************************************
    1264              : !> \brief ...
    1265              : !> \param r ...
    1266              : !> \param ngr ...
    1267              : !> \param rc ...
    1268              : !> \param ngrc ...
    1269              : !> \return ...
    1270              : ! **************************************************************************************************
    1271       423187 :    FUNCTION calc_expbe_r(r, ngr, rc, ngrc) RESULT(res)
    1272              : 
    1273              :       REAL(kind=dp), INTENT(in)                          :: r, ngr, rc, ngrc
    1274              :       REAL(kind=dp)                                      :: res
    1275              : 
    1276              :       REAL(kind=dp)                                      :: ex_unif, fx, kf, s
    1277              : 
    1278       423187 :       IF (r > rc) THEN
    1279       423187 :          kf = (3.0_dp*r*pi*pi)**(1.0_dp/3.0_dp)
    1280       423187 :          ex_unif = -3.0_dp*kf/(4.0_dp*pi)
    1281       423187 :          fx = 1.0_dp
    1282       423187 :          IF (ngr > ngrc) THEN
    1283       423187 :             s = ngr/(2.0_dp*kf*r)
    1284       423187 :             fx = fx + kappa - kappa/(1.0_dp + mu*s*s/kappa)
    1285              :          END IF
    1286       423187 :          res = ex_unif*fx
    1287              :       ELSE
    1288              :          res = 0.0_dp
    1289              :       END IF
    1290              : 
    1291       423187 :    END FUNCTION calc_expbe_r
    1292              : 
    1293              : END MODULE xc_pot_saop
        

Generated by: LCOV version 2.0-1