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

Generated by: LCOV version 2.0-1