LCOV - code coverage report
Current view: top level - src - qs_vxc.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:70636b1) Lines: 88.0 % 299 263
Test Date: 2026-02-11 07:00:35 Functions: 100.0 % 2 2

            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
      10              : !>
      11              : !>
      12              : !> \par History
      13              : !>     refactoring 03-2011 [MI]
      14              : !> \author MI
      15              : ! **************************************************************************************************
      16              : MODULE qs_vxc
      17              : 
      18              :    USE cell_types,                      ONLY: cell_type
      19              :    USE cp_control_types,                ONLY: dft_control_type
      20              :    USE input_constants,                 ONLY: sic_ad,&
      21              :                                               sic_eo,&
      22              :                                               sic_mauri_spz,&
      23              :                                               sic_mauri_us,&
      24              :                                               sic_none,&
      25              :                                               xc_none,&
      26              :                                               xc_vdw_fun_nonloc
      27              :    USE input_section_types,             ONLY: section_vals_type,&
      28              :                                               section_vals_val_get
      29              :    USE kinds,                           ONLY: dp
      30              :    USE message_passing,                 ONLY: mp_para_env_type
      31              :    USE pw_env_types,                    ONLY: pw_env_get,&
      32              :                                               pw_env_type
      33              :    USE pw_grids,                        ONLY: pw_grid_compare
      34              :    USE pw_methods,                      ONLY: pw_axpy,&
      35              :                                               pw_copy,&
      36              :                                               pw_multiply,&
      37              :                                               pw_scale,&
      38              :                                               pw_transfer,&
      39              :                                               pw_zero
      40              :    USE pw_pool_types,                   ONLY: pw_pool_type
      41              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      42              :                                               pw_r3d_rs_type
      43              :    USE qs_dispersion_nonloc,            ONLY: calculate_dispersion_nonloc
      44              :    USE qs_dispersion_types,             ONLY: qs_dispersion_type
      45              :    USE qs_ks_types,                     ONLY: get_ks_env,&
      46              :                                               qs_ks_env_type
      47              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      48              :                                               qs_rho_type
      49              :    USE virial_types,                    ONLY: virial_type
      50              :    USE xc,                              ONLY: calc_xc_density,&
      51              :                                               xc_exc_calc,&
      52              :                                               xc_vxc_pw_create
      53              : #include "./base/base_uses.f90"
      54              : 
      55              :    IMPLICIT NONE
      56              : 
      57              :    PRIVATE
      58              : 
      59              :    ! *** Public subroutines ***
      60              :    PUBLIC :: qs_vxc_create, qs_xc_density
      61              : 
      62              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_vxc'
      63              : 
      64              : CONTAINS
      65              : 
      66              : ! **************************************************************************************************
      67              : !> \brief calculates and allocates the xc potential, already reducing it to
      68              : !>      the dependence on rho and the one on tau
      69              : !> \param ks_env to get all the needed things
      70              : !> \param rho_struct density for which v_xc is calculated
      71              : !> \param xc_section ...
      72              : !> \param vxc_rho will contain the v_xc part that depend on rho
      73              : !>        (if one of the chosen xc functionals has it it is allocated and you
      74              : !>        are responsible for it)
      75              : !> \param vxc_tau will contain the kinetic tau part of v_xc
      76              : !>        (if one of the chosen xc functionals has it it is allocated and you
      77              : !>        are responsible for it)
      78              : !> \param exc ...
      79              : !> \param just_energy if true calculates just the energy, and does not
      80              : !>        allocate v_*_rspace
      81              : !> \param edisp ...
      82              : !> \param dispersion_env ...
      83              : !> \param adiabatic_rescale_factor ...
      84              : !> \param pw_env_external    external plane wave environment
      85              : !> \par History
      86              : !>      - 05.2002 modified to use the mp_allgather function each pe
      87              : !>        computes only part of the grid and this is broadcasted to all
      88              : !>        instead of summed.
      89              : !>        This scales significantly better (e.g. factor 3 on 12 cpus
      90              : !>        32 H2O) [Joost VdV]
      91              : !>      - moved to qs_ks_methods [fawzi]
      92              : !>      - sic alterations [Joost VandeVondele]
      93              : !> \author Fawzi Mohamed
      94              : ! **************************************************************************************************
      95       570636 :    SUBROUTINE qs_vxc_create(ks_env, rho_struct, xc_section, vxc_rho, vxc_tau, exc, &
      96              :                             just_energy, edisp, dispersion_env, adiabatic_rescale_factor, &
      97              :                             pw_env_external)
      98              : 
      99              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     100              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     101              :       TYPE(section_vals_type), POINTER                   :: xc_section
     102              :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: vxc_rho, vxc_tau
     103              :       REAL(KIND=dp), INTENT(out)                         :: exc
     104              :       LOGICAL, INTENT(in), OPTIONAL                      :: just_energy
     105              :       REAL(KIND=dp), INTENT(out), OPTIONAL               :: edisp
     106              :       TYPE(qs_dispersion_type), OPTIONAL, POINTER        :: dispersion_env
     107              :       REAL(KIND=dp), INTENT(in), OPTIONAL                :: adiabatic_rescale_factor
     108              :       TYPE(pw_env_type), OPTIONAL, POINTER               :: pw_env_external
     109              : 
     110              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_vxc_create'
     111              : 
     112              :       INTEGER                                            :: handle, ispin, mspin, myfun, &
     113              :                                                             nelec_spin(2), vdw
     114              :       LOGICAL :: compute_virial, do_adiabatic_rescaling, my_just_energy, rho_g_valid, &
     115              :          sic_scaling_b_zero, tau_r_valid, uf_grid, vdW_nl
     116              :       REAL(KIND=dp)                                      :: exc_m, factor, &
     117              :                                                             my_adiabatic_rescale_factor, &
     118              :                                                             my_scaling, nelec_s_inv
     119              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: virial_xc_tmp
     120              :       TYPE(cell_type), POINTER                           :: cell
     121              :       TYPE(dft_control_type), POINTER                    :: dft_control
     122              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     123       142659 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g, rho_m_gspace, rho_struct_g
     124              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho_nlcc_g, tmp_g, tmp_g2
     125              :       TYPE(pw_env_type), POINTER                         :: pw_env
     126              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool, vdw_pw_pool, xc_pw_pool
     127       142659 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: my_vxc_rho, my_vxc_tau, rho_m_rspace, &
     128       142659 :                                                             rho_r, rho_struct_r, tau, tau_struct_r
     129              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho_nlcc, tmp_pw, weights
     130              :       TYPE(virial_type), POINTER                         :: virial
     131              : 
     132       142659 :       CALL timeset(routineN, handle)
     133              : 
     134       142659 :       CPASSERT(.NOT. ASSOCIATED(vxc_rho))
     135       142659 :       CPASSERT(.NOT. ASSOCIATED(vxc_tau))
     136       142659 :       NULLIFY (dft_control, pw_env, auxbas_pw_pool, xc_pw_pool, vdw_pw_pool, cell, my_vxc_rho, &
     137       142659 :                tmp_pw, tmp_g, tmp_g2, my_vxc_tau, rho_g, rho_r, tau, rho_m_rspace, &
     138       142659 :                rho_m_gspace, rho_nlcc, rho_nlcc_g, rho_struct_r, rho_struct_g, tau_struct_r)
     139              : 
     140       142659 :       exc = 0.0_dp
     141       142659 :       my_just_energy = .FALSE.
     142       142659 :       IF (PRESENT(just_energy)) my_just_energy = just_energy
     143       142659 :       my_adiabatic_rescale_factor = 1.0_dp
     144       142659 :       do_adiabatic_rescaling = .FALSE.
     145       142659 :       IF (PRESENT(adiabatic_rescale_factor)) THEN
     146           44 :          my_adiabatic_rescale_factor = adiabatic_rescale_factor
     147           44 :          do_adiabatic_rescaling = .TRUE.
     148              :       END IF
     149              : 
     150              :       CALL get_ks_env(ks_env, &
     151              :                       dft_control=dft_control, &
     152              :                       pw_env=pw_env, &
     153              :                       cell=cell, &
     154              :                       xcint_weights=weights, &
     155              :                       virial=virial, &
     156              :                       rho_nlcc=rho_nlcc, &
     157       142659 :                       rho_nlcc_g=rho_nlcc_g)
     158              : 
     159              :       CALL qs_rho_get(rho_struct, &
     160              :                       tau_r_valid=tau_r_valid, &
     161              :                       rho_g_valid=rho_g_valid, &
     162              :                       rho_r=rho_struct_r, &
     163              :                       rho_g=rho_struct_g, &
     164       142659 :                       tau_r=tau_struct_r)
     165              : 
     166       142659 :       compute_virial = virial%pv_calculate .AND. (.NOT. virial%pv_numer)
     167       142659 :       IF (compute_virial) THEN
     168        35958 :          virial%pv_xc = 0.0_dp
     169              :       END IF
     170              : 
     171              :       CALL section_vals_val_get(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", &
     172       142659 :                                 i_val=myfun)
     173              :       CALL section_vals_val_get(xc_section, "VDW_POTENTIAL%POTENTIAL_TYPE", &
     174       142659 :                                 i_val=vdw)
     175              : 
     176       142659 :       vdW_nl = (vdw == xc_vdw_fun_nonloc)
     177              :       ! this combination has not been investigated
     178       142659 :       CPASSERT(.NOT. (do_adiabatic_rescaling .AND. vdW_nl))
     179              :       ! are the necessary inputs available
     180       142659 :       IF (.NOT. (PRESENT(dispersion_env) .AND. PRESENT(edisp))) THEN
     181              :          vdW_nl = .FALSE.
     182              :       END IF
     183       142659 :       IF (PRESENT(edisp)) edisp = 0.0_dp
     184              : 
     185       142659 :       IF (myfun /= xc_none .OR. vdW_nl) THEN
     186              : 
     187              :          ! test if the real space density is available
     188       128105 :          CPASSERT(ASSOCIATED(rho_struct))
     189       128105 :          IF (dft_control%nspins /= 1 .AND. dft_control%nspins /= 2) &
     190            0 :             CPABORT("nspins must be 1 or 2")
     191       128105 :          mspin = SIZE(rho_struct_r)
     192       128105 :          IF (dft_control%nspins == 2 .AND. mspin == 1) &
     193            0 :             CPABORT("Spin count mismatch")
     194              : 
     195              :          ! there are some options related to SIC here.
     196              :          ! Normal DFT computes E(rho_alpha,rho_beta) (or its variant E(2*rho_alpha) for non-LSD)
     197              :          ! SIC can             E(rho_alpha,rho_beta)-b*(E(rho_alpha,rho_beta)-E(rho_beta,rho_beta))
     198              :          ! or compute          E(rho_alpha,rho_beta)-b*E(rho_alpha-rho_beta,0)
     199              : 
     200              :          ! my_scaling is the scaling needed of the standard E(rho_alpha,rho_beta) term
     201       128105 :          my_scaling = 1.0_dp
     202       128309 :          SELECT CASE (dft_control%sic_method_id)
     203              :          CASE (sic_none)
     204              :             ! all fine
     205              :          CASE (sic_mauri_spz, sic_ad)
     206              :             ! no idea yet what to do here in that case
     207          204 :             CPASSERT(.NOT. tau_r_valid)
     208              :          CASE (sic_mauri_us)
     209           92 :             my_scaling = 1.0_dp - dft_control%sic_scaling_b
     210              :             ! no idea yet what to do here in that case
     211           92 :             CPASSERT(.NOT. tau_r_valid)
     212              :          CASE (sic_eo)
     213              :             ! NOTHING TO BE DONE
     214              :          CASE DEFAULT
     215              :             ! this case has not yet been treated here
     216       128105 :             CPABORT("NYI")
     217              :          END SELECT
     218              : 
     219       128105 :          IF (dft_control%sic_scaling_b == 0.0_dp) THEN
     220              :             sic_scaling_b_zero = .TRUE.
     221              :          ELSE
     222       128005 :             sic_scaling_b_zero = .FALSE.
     223              :          END IF
     224              : 
     225       128105 :          IF (PRESENT(pw_env_external)) &
     226            0 :             pw_env => pw_env_external
     227       128105 :          CALL pw_env_get(pw_env, xc_pw_pool=xc_pw_pool, auxbas_pw_pool=auxbas_pw_pool)
     228       128105 :          uf_grid = .NOT. pw_grid_compare(auxbas_pw_pool%pw_grid, xc_pw_pool%pw_grid)
     229              : 
     230       128105 :          IF (.NOT. uf_grid) THEN
     231       128091 :             rho_r => rho_struct_r
     232              : 
     233       128091 :             IF (tau_r_valid) THEN
     234         3220 :                tau => tau_struct_r
     235              :             END IF
     236              : 
     237              :             ! for gradient corrected functional the density in g space might
     238              :             ! be useful so if we have it, we pass it in
     239       128091 :             IF (rho_g_valid) THEN
     240       128071 :                rho_g => rho_struct_g
     241              :             END IF
     242              :          ELSE
     243           14 :             CPASSERT(rho_g_valid)
     244           56 :             ALLOCATE (rho_r(mspin))
     245           56 :             ALLOCATE (rho_g(mspin))
     246           28 :             DO ispin = 1, mspin
     247           14 :                CALL xc_pw_pool%create_pw(rho_g(ispin))
     248           28 :                CALL pw_transfer(rho_struct_g(ispin), rho_g(ispin))
     249              :             END DO
     250           28 :             DO ispin = 1, mspin
     251           14 :                CALL xc_pw_pool%create_pw(rho_r(ispin))
     252           28 :                CALL pw_transfer(rho_g(ispin), rho_r(ispin))
     253              :             END DO
     254           14 :             IF (tau_r_valid) THEN
     255              :                ! tau with finer grids is not implemented (at least not correctly), which this asserts
     256            0 :                CPABORT("Tau (MGGA) with finer grids not implemented")
     257              :             END IF
     258           14 :             IF (ASSOCIATED(weights)) THEN
     259            0 :                CPABORT("Accurate integration with finer grids not implemented")
     260              :             END IF
     261              :          END IF
     262              : 
     263              :          ! add the nlcc densities
     264       128105 :          IF (ASSOCIATED(rho_nlcc)) THEN
     265          566 :             factor = 1.0_dp
     266         1132 :             DO ispin = 1, mspin
     267          566 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     268         1132 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     269              :             END DO
     270              :          END IF
     271              : 
     272              :          !
     273              :          ! here the rho_r, rho_g, tau is what it should be
     274              :          ! we get back the right my_vxc_rho and my_vxc_tau as required
     275              :          !
     276       128105 :          IF (my_just_energy) THEN
     277              :             exc = xc_exc_calc(rho_r=rho_r, tau=tau, &
     278              :                               rho_g=rho_g, xc_section=xc_section, &
     279        10406 :                               weights=weights, pw_pool=xc_pw_pool)
     280              : 
     281              :          ELSE
     282              :             CALL xc_vxc_pw_create(vxc_rho=my_vxc_rho, vxc_tau=my_vxc_tau, rho_r=rho_r, &
     283              :                                   rho_g=rho_g, tau=tau, exc=exc, &
     284              :                                   xc_section=xc_section, &
     285              :                                   weights=weights, pw_pool=xc_pw_pool, &
     286              :                                   compute_virial=compute_virial, &
     287       117699 :                                   virial_xc=virial%pv_xc)
     288              :          END IF
     289              : 
     290              :          ! remove the nlcc densities (keep stuff in original state)
     291       128105 :          IF (ASSOCIATED(rho_nlcc)) THEN
     292          566 :             factor = -1.0_dp
     293         1132 :             DO ispin = 1, mspin
     294          566 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     295         1132 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     296              :             END DO
     297              :          END IF
     298              : 
     299              :          ! calclulate non-local vdW functional
     300              :          ! only if this XC_SECTION has it
     301              :          ! if yes, we use the dispersion_env from ks_env
     302              :          ! this is dangerous, as it assumes a special connection xc_section -> qs_env
     303       128105 :          IF (vdW_nl) THEN
     304          388 :             CALL get_ks_env(ks_env=ks_env, para_env=para_env)
     305              :             ! no SIC functionals allowed
     306          388 :             CPASSERT(dft_control%sic_method_id == sic_none)
     307              :             !
     308          388 :             CALL pw_env_get(pw_env, vdw_pw_pool=vdw_pw_pool)
     309          388 :             IF (my_just_energy) THEN
     310              :                CALL calculate_dispersion_nonloc(my_vxc_rho, rho_r, rho_g, edisp, dispersion_env, &
     311            6 :                                                 my_just_energy, vdw_pw_pool, xc_pw_pool, para_env)
     312              :             ELSE
     313              :                CALL calculate_dispersion_nonloc(my_vxc_rho, rho_r, rho_g, edisp, dispersion_env, &
     314          382 :                                                 my_just_energy, vdw_pw_pool, xc_pw_pool, para_env, virial=virial)
     315              :             END IF
     316              :          END IF
     317              : 
     318              :          !! Apply rescaling to the potential if requested
     319       128105 :          IF (.NOT. my_just_energy) THEN
     320       117699 :             IF (do_adiabatic_rescaling) THEN
     321           24 :                IF (ASSOCIATED(my_vxc_rho)) THEN
     322           62 :                   DO ispin = 1, SIZE(my_vxc_rho)
     323           62 :                      CALL pw_scale(my_vxc_rho(ispin), my_adiabatic_rescale_factor)
     324              :                   END DO
     325              :                END IF
     326              :             END IF
     327              :          END IF
     328              : 
     329       128105 :          IF (my_scaling /= 1.0_dp) THEN
     330           92 :             exc = exc*my_scaling
     331           92 :             IF (ASSOCIATED(my_vxc_rho)) THEN
     332          180 :                DO ispin = 1, SIZE(my_vxc_rho)
     333          180 :                   CALL pw_scale(my_vxc_rho(ispin), my_scaling)
     334              :                END DO
     335              :             END IF
     336           92 :             IF (ASSOCIATED(my_vxc_tau)) THEN
     337            0 :                DO ispin = 1, SIZE(my_vxc_tau)
     338            0 :                   CALL pw_scale(my_vxc_tau(ispin), my_scaling)
     339              :                END DO
     340              :             END IF
     341              :          END IF
     342              : 
     343              :          ! we have pw data for the xc, qs_ks requests coeff structure, here we transfer
     344              :          ! pw -> coeff
     345       128105 :          IF (ASSOCIATED(my_vxc_rho)) THEN
     346       117699 :             vxc_rho => my_vxc_rho
     347       117699 :             NULLIFY (my_vxc_rho)
     348              :          END IF
     349       128105 :          IF (ASSOCIATED(my_vxc_tau)) THEN
     350         2176 :             vxc_tau => my_vxc_tau
     351         2176 :             NULLIFY (my_vxc_tau)
     352              :          END IF
     353       128105 :          IF (uf_grid) THEN
     354           28 :             DO ispin = 1, SIZE(rho_r)
     355           28 :                CALL xc_pw_pool%give_back_pw(rho_r(ispin))
     356              :             END DO
     357           14 :             DEALLOCATE (rho_r)
     358           14 :             IF (ASSOCIATED(rho_g)) THEN
     359           28 :                DO ispin = 1, SIZE(rho_g)
     360           28 :                   CALL xc_pw_pool%give_back_pw(rho_g(ispin))
     361              :                END DO
     362           14 :                DEALLOCATE (rho_g)
     363              :             END IF
     364              :          END IF
     365              : 
     366              :          ! compute again the xc but now for Exc(m,o) and the opposite sign
     367       128105 :          IF (dft_control%sic_method_id == sic_mauri_spz .AND. .NOT. sic_scaling_b_zero) THEN
     368          390 :             ALLOCATE (rho_m_rspace(2), rho_m_gspace(2))
     369           78 :             CALL xc_pw_pool%create_pw(rho_m_gspace(1))
     370           78 :             CALL xc_pw_pool%create_pw(rho_m_rspace(1))
     371           78 :             CALL pw_copy(rho_struct_r(1), rho_m_rspace(1))
     372           78 :             CALL pw_axpy(rho_struct_r(2), rho_m_rspace(1), alpha=-1._dp)
     373           78 :             CALL pw_copy(rho_struct_g(1), rho_m_gspace(1))
     374           78 :             CALL pw_axpy(rho_struct_g(2), rho_m_gspace(1), alpha=-1._dp)
     375              :             ! bit sad, these will be just zero...
     376           78 :             CALL xc_pw_pool%create_pw(rho_m_gspace(2))
     377           78 :             CALL xc_pw_pool%create_pw(rho_m_rspace(2))
     378           78 :             CALL pw_zero(rho_m_rspace(2))
     379           78 :             CALL pw_zero(rho_m_gspace(2))
     380              : 
     381           78 :             IF (my_just_energy) THEN
     382              :                exc_m = xc_exc_calc(rho_r=rho_m_rspace, tau=tau, &
     383              :                                    rho_g=rho_m_gspace, xc_section=xc_section, &
     384           24 :                                    weights=weights, pw_pool=xc_pw_pool)
     385              :             ELSE
     386              :                ! virial untested
     387           54 :                CPASSERT(.NOT. compute_virial)
     388              :                CALL xc_vxc_pw_create(vxc_rho=my_vxc_rho, vxc_tau=my_vxc_tau, rho_r=rho_m_rspace, &
     389              :                                      rho_g=rho_m_gspace, tau=tau, exc=exc_m, &
     390              :                                      xc_section=xc_section, &
     391              :                                      weights=weights, pw_pool=xc_pw_pool, &
     392              :                                      compute_virial=.FALSE., &
     393           54 :                                      virial_xc=virial_xc_tmp)
     394              :             END IF
     395              : 
     396           78 :             exc = exc - dft_control%sic_scaling_b*exc_m
     397              : 
     398              :             ! and take care of the potential only vxc_rho is taken into account
     399           78 :             IF (.NOT. my_just_energy) THEN
     400           54 :                CALL pw_axpy(my_vxc_rho(1), vxc_rho(1), -dft_control%sic_scaling_b)
     401           54 :                CALL pw_axpy(my_vxc_rho(1), vxc_rho(2), dft_control%sic_scaling_b)
     402           54 :                CALL my_vxc_rho(1)%release()
     403           54 :                CALL my_vxc_rho(2)%release()
     404           54 :                DEALLOCATE (my_vxc_rho)
     405              :             END IF
     406              : 
     407          234 :             DO ispin = 1, 2
     408          156 :                CALL xc_pw_pool%give_back_pw(rho_m_rspace(ispin))
     409          234 :                CALL xc_pw_pool%give_back_pw(rho_m_gspace(ispin))
     410              :             END DO
     411           78 :             DEALLOCATE (rho_m_rspace)
     412           78 :             DEALLOCATE (rho_m_gspace)
     413              : 
     414              :          END IF
     415              : 
     416              :          ! now we have - sum_s N_s * Exc(rho_s/N_s,0)
     417       128105 :          IF (dft_control%sic_method_id == sic_ad .AND. .NOT. sic_scaling_b_zero) THEN
     418              : 
     419              :             ! find out how many elecs we have
     420           26 :             CALL get_ks_env(ks_env, nelectron_spin=nelec_spin)
     421              : 
     422          130 :             ALLOCATE (rho_m_rspace(2), rho_m_gspace(2))
     423           78 :             DO ispin = 1, 2
     424           52 :                CALL xc_pw_pool%create_pw(rho_m_gspace(ispin))
     425           78 :                CALL xc_pw_pool%create_pw(rho_m_rspace(ispin))
     426              :             END DO
     427              : 
     428           78 :             DO ispin = 1, 2
     429           52 :                IF (nelec_spin(ispin) > 0.0_dp) THEN
     430           52 :                   nelec_s_inv = 1.0_dp/nelec_spin(ispin)
     431              :                ELSE
     432              :                   ! does it matter if there are no electrons with this spin (H) ?
     433            0 :                   nelec_s_inv = 0.0_dp
     434              :                END IF
     435           52 :                CALL pw_copy(rho_struct_r(ispin), rho_m_rspace(1))
     436           52 :                CALL pw_copy(rho_struct_g(ispin), rho_m_gspace(1))
     437           52 :                CALL pw_scale(rho_m_rspace(1), nelec_s_inv)
     438           52 :                CALL pw_scale(rho_m_gspace(1), nelec_s_inv)
     439           52 :                CALL pw_zero(rho_m_rspace(2))
     440           52 :                CALL pw_zero(rho_m_gspace(2))
     441              : 
     442           52 :                IF (my_just_energy) THEN
     443              :                   exc_m = xc_exc_calc(rho_r=rho_m_rspace, tau=tau, &
     444              :                                       rho_g=rho_m_gspace, xc_section=xc_section, &
     445           12 :                                       weights=weights, pw_pool=xc_pw_pool)
     446              :                ELSE
     447              :                   ! virial untested
     448           40 :                   CPASSERT(.NOT. compute_virial)
     449              :                   CALL xc_vxc_pw_create(vxc_rho=my_vxc_rho, vxc_tau=my_vxc_tau, rho_r=rho_m_rspace, &
     450              :                                         rho_g=rho_m_gspace, tau=tau, exc=exc_m, &
     451              :                                         xc_section=xc_section, &
     452              :                                         weights=weights, pw_pool=xc_pw_pool, &
     453              :                                         compute_virial=.FALSE., &
     454           40 :                                         virial_xc=virial_xc_tmp)
     455              :                END IF
     456              : 
     457           52 :                exc = exc - dft_control%sic_scaling_b*nelec_spin(ispin)*exc_m
     458              : 
     459              :                ! and take care of the potential only vxc_rho is taken into account
     460           78 :                IF (.NOT. my_just_energy) THEN
     461           40 :                   CALL pw_axpy(my_vxc_rho(1), vxc_rho(ispin), -dft_control%sic_scaling_b)
     462           40 :                   CALL my_vxc_rho(1)%release()
     463           40 :                   CALL my_vxc_rho(2)%release()
     464           40 :                   DEALLOCATE (my_vxc_rho)
     465              :                END IF
     466              :             END DO
     467              : 
     468           78 :             DO ispin = 1, 2
     469           52 :                CALL xc_pw_pool%give_back_pw(rho_m_rspace(ispin))
     470           78 :                CALL xc_pw_pool%give_back_pw(rho_m_gspace(ispin))
     471              :             END DO
     472           26 :             DEALLOCATE (rho_m_rspace)
     473           26 :             DEALLOCATE (rho_m_gspace)
     474              : 
     475              :          END IF
     476              : 
     477              :          ! compute again the xc but now for Exc(n_down,n_down)
     478       128105 :          IF (dft_control%sic_method_id == sic_mauri_us .AND. .NOT. sic_scaling_b_zero) THEN
     479          276 :             ALLOCATE (rho_r(2))
     480           92 :             rho_r(1) = rho_struct_r(2)
     481           92 :             rho_r(2) = rho_struct_r(2)
     482           92 :             IF (rho_g_valid) THEN
     483          276 :                ALLOCATE (rho_g(2))
     484           92 :                rho_g(1) = rho_struct_g(2)
     485           92 :                rho_g(2) = rho_struct_g(2)
     486              :             END IF
     487              : 
     488           92 :             IF (my_just_energy) THEN
     489              :                exc_m = xc_exc_calc(rho_r=rho_r, tau=tau, &
     490              :                                    rho_g=rho_g, xc_section=xc_section, &
     491           32 :                                    weights=weights, pw_pool=xc_pw_pool)
     492              :             ELSE
     493              :                ! virial untested
     494           60 :                CPASSERT(.NOT. compute_virial)
     495              :                CALL xc_vxc_pw_create(vxc_rho=my_vxc_rho, vxc_tau=my_vxc_tau, rho_r=rho_r, &
     496              :                                      rho_g=rho_g, tau=tau, exc=exc_m, &
     497              :                                      xc_section=xc_section, &
     498              :                                      weights=weights, pw_pool=xc_pw_pool, &
     499              :                                      compute_virial=.FALSE., &
     500           60 :                                      virial_xc=virial_xc_tmp)
     501              :             END IF
     502              : 
     503           92 :             exc = exc + dft_control%sic_scaling_b*exc_m
     504              : 
     505              :             ! and take care of the potential
     506           92 :             IF (.NOT. my_just_energy) THEN
     507              :                ! both go to minority spin
     508           60 :                CALL pw_axpy(my_vxc_rho(1), vxc_rho(2), 2.0_dp*dft_control%sic_scaling_b)
     509           60 :                CALL my_vxc_rho(1)%release()
     510           60 :                CALL my_vxc_rho(2)%release()
     511           60 :                DEALLOCATE (my_vxc_rho)
     512              :             END IF
     513           92 :             DEALLOCATE (rho_r, rho_g)
     514              : 
     515              :          END IF
     516              : 
     517              :          !
     518              :          ! cleanups
     519              :          !
     520       128105 :          IF (uf_grid .AND. (ASSOCIATED(vxc_rho) .OR. ASSOCIATED(vxc_tau))) THEN
     521              :             BLOCK
     522              :                TYPE(pw_r3d_rs_type) :: tmp_pw
     523              :                TYPE(pw_c1d_gs_type) :: tmp_g, tmp_g2
     524           14 :                CALL xc_pw_pool%create_pw(tmp_g)
     525           14 :                CALL auxbas_pw_pool%create_pw(tmp_g2)
     526           14 :                IF (ASSOCIATED(vxc_rho)) THEN
     527           28 :                   DO ispin = 1, SIZE(vxc_rho)
     528           14 :                      CALL auxbas_pw_pool%create_pw(tmp_pw)
     529           14 :                      CALL pw_transfer(vxc_rho(ispin), tmp_g)
     530           14 :                      CALL pw_transfer(tmp_g, tmp_g2)
     531           14 :                      CALL pw_transfer(tmp_g2, tmp_pw)
     532           14 :                      CALL xc_pw_pool%give_back_pw(vxc_rho(ispin))
     533           28 :                      vxc_rho(ispin) = tmp_pw
     534              :                   END DO
     535              :                END IF
     536           14 :                IF (ASSOCIATED(vxc_tau)) THEN
     537            0 :                   DO ispin = 1, SIZE(vxc_tau)
     538            0 :                      CALL auxbas_pw_pool%create_pw(tmp_pw)
     539            0 :                      CALL pw_transfer(vxc_tau(ispin), tmp_g)
     540            0 :                      CALL pw_transfer(tmp_g, tmp_g2)
     541            0 :                      CALL pw_transfer(tmp_g2, tmp_pw)
     542            0 :                      CALL xc_pw_pool%give_back_pw(vxc_tau(ispin))
     543            0 :                      vxc_tau(ispin) = tmp_pw
     544              :                   END DO
     545              :                END IF
     546           14 :                CALL auxbas_pw_pool%give_back_pw(tmp_g2)
     547           28 :                CALL xc_pw_pool%give_back_pw(tmp_g)
     548              :             END BLOCK
     549              :          END IF
     550       128105 :          IF (ASSOCIATED(tau) .AND. uf_grid) THEN
     551            0 :             DO ispin = 1, SIZE(tau)
     552            0 :                CALL xc_pw_pool%give_back_pw(tau(ispin))
     553              :             END DO
     554            0 :             DEALLOCATE (tau)
     555              :          END IF
     556              : 
     557              :       END IF
     558              : 
     559       142659 :       CALL timestop(handle)
     560              : 
     561       142659 :    END SUBROUTINE qs_vxc_create
     562              : 
     563              : ! **************************************************************************************************
     564              : !> \brief calculates the XC density: E_xc(r) - V_xc(r)*rho(r)  or  E_xc(r)/rho(r)
     565              : !> \param ks_env to get all the needed things
     566              : !> \param rho_struct density
     567              : !> \param xc_section ...
     568              : !> \param dispersion_env ...
     569              : !> \param xc_ener will contain the xc energy density E_xc(r) - V_xc(r)*rho(r)
     570              : !> \param xc_den will contain the xc energy density E_xc(r)/rho(r)
     571              : !> \param exc will contain the xc energy density E_xc(r)
     572              : !> \param vxc ...
     573              : !> \param vtau ...
     574              : !> \author JGH
     575              : ! **************************************************************************************************
     576          490 :    SUBROUTINE qs_xc_density(ks_env, rho_struct, xc_section, dispersion_env, &
     577           98 :                             xc_ener, xc_den, exc, vxc, vtau)
     578              : 
     579              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     580              :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     581              :       TYPE(section_vals_type), POINTER                   :: xc_section
     582              :       TYPE(qs_dispersion_type), OPTIONAL, POINTER        :: dispersion_env
     583              :       TYPE(pw_r3d_rs_type), INTENT(INOUT), OPTIONAL      :: xc_ener, xc_den
     584              :       TYPE(pw_r3d_rs_type), OPTIONAL                     :: exc
     585              :       TYPE(pw_r3d_rs_type), DIMENSION(:), OPTIONAL       :: vxc, vtau
     586              : 
     587              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qs_xc_density'
     588              : 
     589              :       INTEGER                                            :: handle, ispin, myfun, nspins, vdw
     590              :       LOGICAL                                            :: rho_g_valid, tau_r_valid, uf_grid, vdW_nl
     591              :       REAL(KIND=dp)                                      :: edisp, excint, factor, rho_cutoff
     592              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: vdum
     593              :       TYPE(cell_type), POINTER                           :: cell
     594              :       TYPE(dft_control_type), POINTER                    :: dft_control
     595              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     596           98 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g
     597              :       TYPE(pw_c1d_gs_type), POINTER                      :: rho_nlcc_g
     598              :       TYPE(pw_env_type), POINTER                         :: pw_env
     599              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool, vdw_pw_pool, xc_pw_pool
     600              :       TYPE(pw_r3d_rs_type)                               :: exc_r
     601           98 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r, tau_r, vxc_rho, vxc_tau
     602              :       TYPE(pw_r3d_rs_type), POINTER                      :: rho_nlcc, weights
     603              : 
     604           98 :       CALL timeset(routineN, handle)
     605              : 
     606              :       CALL get_ks_env(ks_env, &
     607              :                       dft_control=dft_control, &
     608              :                       pw_env=pw_env, &
     609              :                       cell=cell, &
     610              :                       xcint_weights=weights, &
     611              :                       rho_nlcc=rho_nlcc, &
     612           98 :                       rho_nlcc_g=rho_nlcc_g)
     613              : 
     614              :       CALL qs_rho_get(rho_struct, &
     615              :                       tau_r_valid=tau_r_valid, &
     616              :                       rho_g_valid=rho_g_valid, &
     617              :                       rho_r=rho_r, &
     618              :                       rho_g=rho_g, &
     619           98 :                       tau_r=tau_r)
     620           98 :       nspins = dft_control%nspins
     621              : 
     622           98 :       CALL section_vals_val_get(xc_section, "XC_FUNCTIONAL%_SECTION_PARAMETERS_", i_val=myfun)
     623           98 :       CALL section_vals_val_get(xc_section, "VDW_POTENTIAL%POTENTIAL_TYPE", i_val=vdw)
     624           98 :       vdW_nl = (vdw == xc_vdw_fun_nonloc)
     625           98 :       IF (PRESENT(xc_ener)) THEN
     626           32 :          IF (tau_r_valid) THEN
     627            0 :             CALL cp_warn(__LOCATION__, "Tau contribution will not be correctly handled")
     628              :          END IF
     629              :       END IF
     630           98 :       IF (vdW_nl) THEN
     631            0 :          CALL cp_warn(__LOCATION__, "vdW functional contribution will be ignored")
     632              :       END IF
     633              : 
     634           98 :       CALL pw_env_get(pw_env, xc_pw_pool=xc_pw_pool, auxbas_pw_pool=auxbas_pw_pool)
     635           98 :       uf_grid = .NOT. pw_grid_compare(auxbas_pw_pool%pw_grid, xc_pw_pool%pw_grid)
     636           98 :       IF (uf_grid) THEN
     637            0 :          CALL cp_warn(__LOCATION__, "Fine grid option not possible with local energy")
     638            0 :          CPABORT("Fine Grid in Local Energy")
     639              :       END IF
     640              : 
     641           98 :       IF (PRESENT(xc_ener)) THEN
     642           32 :          CALL pw_zero(xc_ener)
     643              :       END IF
     644           98 :       IF (PRESENT(xc_den)) THEN
     645           66 :          CALL pw_zero(xc_den)
     646              :       END IF
     647           98 :       IF (PRESENT(exc)) THEN
     648            0 :          CALL pw_zero(exc)
     649              :       END IF
     650           98 :       IF (PRESENT(vxc)) THEN
     651          138 :          DO ispin = 1, nspins
     652          138 :             CALL pw_zero(vxc(ispin))
     653              :          END DO
     654              :       END IF
     655           98 :       IF (PRESENT(vtau)) THEN
     656           40 :          DO ispin = 1, nspins
     657           40 :             CALL pw_zero(vtau(ispin))
     658              :          END DO
     659              :       END IF
     660              : 
     661           98 :       IF (myfun /= xc_none) THEN
     662              : 
     663           96 :          CPASSERT(ASSOCIATED(rho_struct))
     664           96 :          CPASSERT(dft_control%sic_method_id == sic_none)
     665              : 
     666              :          ! add the nlcc densities
     667           96 :          IF (ASSOCIATED(rho_nlcc)) THEN
     668            0 :             factor = 1.0_dp
     669            0 :             DO ispin = 1, nspins
     670            0 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     671            0 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     672              :             END DO
     673              :          END IF
     674           96 :          NULLIFY (vxc_rho, vxc_tau)
     675              :          CALL xc_vxc_pw_create(vxc_rho=vxc_rho, vxc_tau=vxc_tau, rho_r=rho_r, &
     676              :                                rho_g=rho_g, tau=tau_r, exc=excint, &
     677              :                                xc_section=xc_section, &
     678              :                                weights=weights, pw_pool=xc_pw_pool, &
     679              :                                compute_virial=.FALSE., &
     680              :                                virial_xc=vdum, &
     681           96 :                                exc_r=exc_r)
     682              :          ! calclulate non-local vdW functional
     683              :          ! only if this XC_SECTION has it
     684              :          ! if yes, we use the dispersion_env from ks_env
     685              :          ! this is dangerous, as it assumes a special connection xc_section -> qs_env
     686           96 :          IF (vdW_nl) THEN
     687            0 :             CALL get_ks_env(ks_env=ks_env, para_env=para_env)
     688              :             ! no SIC functionals allowed
     689            0 :             CPASSERT(dft_control%sic_method_id == sic_none)
     690              :             !
     691            0 :             CALL pw_env_get(pw_env, vdw_pw_pool=vdw_pw_pool)
     692              :             CALL calculate_dispersion_nonloc(vxc_rho, rho_r, rho_g, edisp, dispersion_env, &
     693            0 :                                              .FALSE., vdw_pw_pool, xc_pw_pool, para_env)
     694              :          END IF
     695              : 
     696              :          ! remove the nlcc densities (keep stuff in original state)
     697           96 :          IF (ASSOCIATED(rho_nlcc)) THEN
     698            0 :             factor = -1.0_dp
     699            0 :             DO ispin = 1, dft_control%nspins
     700            0 :                CALL pw_axpy(rho_nlcc, rho_r(ispin), factor)
     701            0 :                CALL pw_axpy(rho_nlcc_g, rho_g(ispin), factor)
     702              :             END DO
     703              :          END IF
     704              :          !
     705           96 :          IF (PRESENT(xc_den)) THEN
     706           64 :             CALL pw_copy(exc_r, xc_den)
     707           64 :             rho_cutoff = 1.E-14_dp
     708           64 :             CALL calc_xc_density(xc_den, rho_r, rho_cutoff)
     709              :          END IF
     710           96 :          IF (PRESENT(xc_ener)) THEN
     711           32 :             CALL pw_copy(exc_r, xc_ener)
     712           64 :             DO ispin = 1, nspins
     713           64 :                CALL pw_multiply(xc_ener, vxc_rho(ispin), rho_r(ispin), alpha=-1.0_dp)
     714              :             END DO
     715              :          END IF
     716           96 :          IF (PRESENT(exc)) THEN
     717            0 :             CALL pw_copy(exc_r, exc)
     718              :          END IF
     719           96 :          IF (PRESENT(vxc)) THEN
     720          134 :             DO ispin = 1, nspins
     721          134 :                CALL pw_copy(vxc_rho(ispin), vxc(ispin))
     722              :             END DO
     723              :          END IF
     724           96 :          IF (PRESENT(vtau)) THEN
     725           40 :             DO ispin = 1, nspins
     726           40 :                CALL pw_copy(vxc_tau(ispin), vtau(ispin))
     727              :             END DO
     728              :          END IF
     729              :          ! remove arrays
     730           96 :          IF (ASSOCIATED(vxc_rho)) THEN
     731          198 :             DO ispin = 1, nspins
     732          198 :                CALL vxc_rho(ispin)%release()
     733              :             END DO
     734           96 :             DEALLOCATE (vxc_rho)
     735              :          END IF
     736           96 :          IF (ASSOCIATED(vxc_tau)) THEN
     737           40 :             DO ispin = 1, nspins
     738           40 :                CALL vxc_tau(ispin)%release()
     739              :             END DO
     740           20 :             DEALLOCATE (vxc_tau)
     741              :          END IF
     742           96 :          CALL exc_r%release()
     743              :          !
     744              :       END IF
     745              : 
     746           98 :       CALL timestop(handle)
     747              : 
     748           98 :    END SUBROUTINE qs_xc_density
     749              : 
     750              : END MODULE qs_vxc
        

Generated by: LCOV version 2.0-1