LCOV - code coverage report
Current view: top level - src/xc - xc_xbeef.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 45.8 % 142 65
Test Date: 2026-11-04 00:58:17 Functions: 50.0 % 6 3

            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 calculates the Exchange contribution in the BEEF-vdW functional
      10              : !         (Norskov Group)
      11              : !> \par History
      12              : !>      02.2014 created based on xc_xbecke88.F [rkoitz]
      13              : !> \author rkoitz
      14              : ! **************************************************************************************************
      15              : MODULE xc_xbeef
      16              : 
      17              :    USE bibliography,                    ONLY: Wellendorff2012,&
      18              :                                               cite_reference
      19              :    USE cp_array_utils,                  ONLY: cp_3d_r_cp_type
      20              :    USE input_section_types,             ONLY: section_vals_type,&
      21              :                                               section_vals_val_get
      22              :    USE kinds,                           ONLY: dp
      23              :    USE mathconstants,                   ONLY: pi
      24              :    USE xc_derivative_desc,              ONLY: deriv_norm_drho,&
      25              :                                               deriv_norm_drhoa,&
      26              :                                               deriv_norm_drhob,&
      27              :                                               deriv_rho,&
      28              :                                               deriv_rhoa,&
      29              :                                               deriv_rhob
      30              :    USE xc_derivative_set_types,         ONLY: xc_derivative_set_type,&
      31              :                                               xc_dset_get_derivative
      32              :    USE xc_derivative_types,             ONLY: xc_derivative_get,&
      33              :                                               xc_derivative_type
      34              :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_type
      35              :    USE xc_rho_set_types,                ONLY: xc_rho_set_get,&
      36              :                                               xc_rho_set_type
      37              : #include "../base/base_uses.f90"
      38              : 
      39              :    IMPLICIT NONE
      40              :    PRIVATE
      41              : 
      42              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      43              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xc_xbeef'
      44              : 
      45              :    PUBLIC :: xbeef_lda_info, xbeef_lsd_info, xbeef_lda_eval, xbeef_lsd_eval
      46              : 
      47              :    !for beef functional pulled out of GPAW source, Feb 2014
      48              :    REAL(kind=dp), PARAMETER :: a(0:29) = [1.516501714304992365356_dp, 0.441353209874497942611_dp, -0.091821352411060291887_dp, &
      49              :                                           -0.023527543314744041314_dp, 0.034188284548603550816_dp, 0.002411870075717384172_dp, &
      50              :                                           -0.014163813515916020766_dp, 0.000697589558149178113_dp, 0.009859205136982565273_dp, &
      51              :                                           -0.006737855050935187551_dp, -0.001573330824338589097_dp, 0.005036146253345903309_dp, &
      52              :                                           -0.002569472452841069059_dp, -0.000987495397608761146_dp, 0.002033722894696920677_dp, &
      53              :                                           -0.000801871884834044583_dp, -0.000668807872347525591_dp, 0.001030936331268264214_dp, &
      54              :                                           -0.000367383865990214423_dp, -0.000421363539352619543_dp, 0.000576160799160517858_dp, &
      55              :                                           -0.000083465037349510408_dp, -0.000445844758523195788_dp, 0.000460129009232047457_dp, &
      56              :                                           -0.000005231775398304339_dp, -0.000423957047149510404_dp, 0.000375019067938866537_dp, &
      57              :                                           0.000021149381251344578_dp, -0.000190491156503997170_dp, 0.000073843624209823442_dp]
      58              : CONTAINS
      59              : 
      60              : ! **************************************************************************************************
      61              : !> \brief return various information on the functional
      62              : !> \param reference string with the reference of the actual functional
      63              : !> \param shortform string with the shortform of the functional name
      64              : !> \param needs the components needed by this functional are set to
      65              : !>        true (does not set the unneeded components to false)
      66              : !> \param max_deriv ...
      67              : !> \par History
      68              : !>      02.2014 created
      69              : !> \author rkoitz
      70              : ! **************************************************************************************************
      71              : 
      72           23 :    SUBROUTINE xbeef_lda_info(reference, shortform, needs, max_deriv)
      73              :       CHARACTER(LEN=*), INTENT(OUT), OPTIONAL            :: reference, shortform
      74              :       TYPE(xc_rho_cflags_type), INTENT(inout), OPTIONAL  :: needs
      75              :       INTEGER, INTENT(out), OPTIONAL                     :: max_deriv
      76              : 
      77           23 :       IF (PRESENT(reference)) THEN
      78            1 :          reference = "Wellendorff, J. et al., Phys. Rev. B 85, 235149 (2012) {LDA}"
      79              :       END IF
      80           23 :       IF (PRESENT(shortform)) THEN
      81            1 :          shortform = "Exchange Contribution to BEEF-vdW Functional (Wellendorff, 2012) {LDA}"
      82              :       END IF
      83           23 :       IF (PRESENT(needs)) THEN
      84           22 :          needs%rho = .TRUE.
      85           22 :          needs%rho_1_3 = .TRUE.
      86           22 :          needs%norm_drho = .TRUE.
      87              :       END IF
      88           23 :       IF (PRESENT(max_deriv)) max_deriv = 1
      89              : 
      90           23 :    END SUBROUTINE xbeef_lda_info
      91              : 
      92              : ! **************************************************************************************************
      93              : !> \brief return various information on the functional
      94              : !> \param reference string with the reference of the actual functional
      95              : !> \param shortform string with the shortform of the functional name
      96              : !> \param needs the components needed by this functional are set to
      97              : !>        true (does not set the unneeded components to false)
      98              : !> \param max_deriv ...
      99              : !> \par History
     100              : !>      02.2014 created
     101              : !> \author rkoitz
     102              : ! **************************************************************************************************
     103            0 :    SUBROUTINE xbeef_lsd_info(reference, shortform, needs, max_deriv)
     104              :       CHARACTER(LEN=*), INTENT(OUT), OPTIONAL            :: reference, shortform
     105              :       TYPE(xc_rho_cflags_type), INTENT(inout), OPTIONAL  :: needs
     106              :       INTEGER, INTENT(out), OPTIONAL                     :: max_deriv
     107              : 
     108            0 :       IF (PRESENT(reference)) THEN
     109            0 :          reference = "Wellendorff, J. et al., Phys. Rev. B 85, 235149 (2012) {LSD}"
     110              :       END IF
     111            0 :       IF (PRESENT(shortform)) THEN
     112            0 :          shortform = "Exchange Contribution to BEEF-vdW Functional (Wellendorff, 2012) {LSD}"
     113              :       END IF
     114            0 :       IF (PRESENT(needs)) THEN
     115            0 :          needs%rho_spin = .TRUE.
     116            0 :          needs%rho_spin_1_3 = .TRUE.
     117            0 :          needs%norm_drho_spin = .TRUE.
     118              :       END IF
     119            0 :       IF (PRESENT(max_deriv)) max_deriv = 1
     120              : 
     121            0 :    END SUBROUTINE xbeef_lsd_info
     122              : 
     123              : ! **************************************************************************************************
     124              : !> \brief evaluates the beef exchange functional for lda
     125              : !> \param rho_set the density where you want to evaluate the functional
     126              : !> \param deriv_set place where to store the functional derivatives (they are
     127              : !>        added to the derivatives)
     128              : !> \param grad_deriv maximum degree of the derivative that should be evaluated
     129              : !> \param xbeef_params input parameters (scaling)
     130              : !> \par History
     131              : !>      02.2014 created
     132              : !> \author rkoitz
     133              : ! **************************************************************************************************
     134           54 :    SUBROUTINE xbeef_lda_eval(rho_set, deriv_set, grad_deriv, xbeef_params)
     135              :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
     136              :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set
     137              :       INTEGER, INTENT(in)                                :: grad_deriv
     138              :       TYPE(section_vals_type), POINTER                   :: xbeef_params
     139              : 
     140              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xbeef_lda_eval'
     141              : 
     142              :       INTEGER                                            :: handle, npoints
     143              :       INTEGER, DIMENSION(2, 3)                           :: bo
     144              :       REAL(kind=dp)                                      :: epsilon_rho, sx
     145              :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :, :), &
     146           18 :          POINTER                                         :: dummy, e_0, e_ndrho, e_rho, norm_drho, &
     147           18 :                                                             rho, rho_1_3
     148              :       TYPE(xc_derivative_type), POINTER                  :: deriv
     149              : 
     150           18 :       CALL timeset(routineN, handle)
     151              : 
     152           18 :       CALL section_vals_val_get(xbeef_params, "scale_x", r_val=sx)
     153              : 
     154           18 :       CALL cite_reference(Wellendorff2012)
     155              : 
     156              :       CALL xc_rho_set_get(rho_set, rho_1_3=rho_1_3, rho=rho, &
     157           18 :                           norm_drho=norm_drho, local_bounds=bo, rho_cutoff=epsilon_rho)
     158           18 :       npoints = (bo(2, 1) - bo(1, 1) + 1)*(bo(2, 2) - bo(1, 2) + 1)*(bo(2, 3) - bo(1, 3) + 1)
     159              : 
     160           18 :       dummy => rho
     161              : 
     162           18 :       e_0 => dummy
     163           18 :       e_rho => dummy
     164           18 :       e_ndrho => dummy
     165              : 
     166              :       deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], &
     167           18 :                                       allocate_deriv=.TRUE.)
     168           18 :       CALL xc_derivative_get(deriv, deriv_data=e_0)
     169           18 :       IF (grad_deriv >= 1) THEN
     170              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rho], &
     171           18 :                                          allocate_deriv=.TRUE.)
     172           18 :          CALL xc_derivative_get(deriv, deriv_data=e_rho)
     173              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho], &
     174           18 :                                          allocate_deriv=.TRUE.)
     175           18 :          CALL xc_derivative_get(deriv, deriv_data=e_ndrho)
     176              :       END IF
     177           18 :       IF (grad_deriv > 1) THEN
     178            0 :          CPABORT("derivatives greater than 1 not implemented")
     179              :       END IF
     180              : 
     181              : !$OMP     PARALLEL DEFAULT(NONE) &
     182              : !$OMP              SHARED(rho, rho_1_3, norm_drho, e_0, e_rho) &
     183              : !$OMP              SHARED(e_ndrho) &
     184              : !$OMP              SHARED( grad_deriv, npoints) &
     185           18 : !$OMP              SHARED(epsilon_rho,sx)
     186              :       CALL xbeef_lda_calc(rho=rho, rho_1_3=rho_1_3, norm_drho=norm_drho, &
     187              :                           e_0=e_0, e_rho=e_rho, e_ndrho=e_ndrho, &
     188              :                           grad_deriv=grad_deriv, &
     189              :                           npoints=npoints, epsilon_rho=epsilon_rho, sx=sx)
     190              : !$OMP     END PARALLEL
     191              : 
     192           18 :       CALL timestop(handle)
     193           18 :    END SUBROUTINE xbeef_lda_eval
     194              : 
     195              : ! **************************************************************************************************
     196              : !> \brief evaluates the beef exchange functional for lda
     197              : !> \param rho the density where you want to evaluate the functional
     198              : !> \param rho_1_3 ...
     199              : !> \param norm_drho ...
     200              : !> \param e_0 ...
     201              : !> \param e_rho ...
     202              : !> \param e_ndrho ...
     203              : !> \param grad_deriv maximum degree of the derivative that should be evaluated
     204              : !> \param npoints ...
     205              : !> \param epsilon_rho ...
     206              : !> \param sx scaling-parameter for exchange
     207              : !> \par History
     208              : !>      02.2014 created based on xc_xbecke88
     209              : !> \author rkoitz
     210              : ! **************************************************************************************************
     211           18 :    SUBROUTINE xbeef_lda_calc(rho, rho_1_3, norm_drho, &
     212           18 :                              e_0, e_rho, e_ndrho, &
     213              :                              grad_deriv, npoints, epsilon_rho, sx)
     214              :       INTEGER, INTENT(in)                                :: npoints, grad_deriv
     215              :       REAL(kind=dp), DIMENSION(1:npoints), INTENT(inout) :: e_ndrho, e_rho, e_0
     216              :       REAL(kind=dp), DIMENSION(1:npoints), INTENT(in)    :: norm_drho, rho_1_3, rho
     217              :       REAL(kind=dp), INTENT(in)                          :: epsilon_rho, sx
     218              : 
     219              :       INTEGER, PARAMETER                                 :: m = 30
     220              : 
     221              :       INTEGER                                            :: i, ii
     222              :       REAL(kind=dp)                                      :: ds_ndrho, ds_rho, dt, e_ueg, e_ueg_drho, &
     223              :                                                             epsilon_rho43, k_lda, kf, my_rho, &
     224              :                                                             my_rho_1_3, s, s2, t, t3
     225              :       REAL(kind=dp), DIMENSION(0:29)                     :: de_leg, e_leg
     226              : 
     227              : !energies, first and second derivatives from legendre pol
     228              : 
     229           18 :       kf = (3.0_dp*pi**2)**(1.0_dp/3.0_dp) !only constants, without n^1/3
     230           18 :       k_lda = -(2.0_dp/(2.0_dp**(4._dp/3._dp)))*(3.0_dp/2.0_dp)*(3.0_dp/(4.0_dp*pi))**(1.0_dp/3.0_dp)
     231              :       !exchange energy density of the uniform electron gas, non spin-polarized
     232              : 
     233           18 :       epsilon_rho43 = epsilon_rho**(4._dp/3._dp)
     234              : 
     235              : !$OMP     DO
     236              :       DO ii = 1, npoints
     237              : 
     238      1417176 :          my_rho = rho(ii)
     239              : 
     240      1417176 :          IF (my_rho > epsilon_rho) THEN
     241      1417176 :             my_rho_1_3 = rho_1_3(ii)
     242              : 
     243      1417176 :             e_ueg = k_lda*my_rho*my_rho_1_3
     244      1417176 :             e_ueg_drho = (4.0_dp/3.0_dp)*k_lda*my_rho_1_3
     245              : 
     246      1417176 :             t3 = my_rho_1_3*my_rho*2*kf !reduced gradient, denominator
     247              : 
     248      1417176 :             s = norm_drho(ii)/MAX(t3, epsilon_rho43) !reduced gradient finally
     249      1417176 :             s2 = s**2
     250      1417176 :             t = 2.0_dp*s2/(4.0_dp + s2) - 1.0_dp
     251              : 
     252      1417176 :             e_leg(0) = 1 !first legendre pol
     253      1417176 :             e_leg(1) = t !second legendre pol
     254              : 
     255      1417176 :             IF ((grad_deriv >= 1)) THEN !asking for first derivative or higher
     256      1417176 :                de_leg(0) = 0
     257      1417176 :                de_leg(1) = 1
     258      1417176 :                dt = 4.0_dp*s/(4.0_dp + s2) - 4.0_dp*s*s2/(4.0_dp + s2)**2
     259      1417176 :                ds_rho = -(4.0_dp*s)/(3.0_dp*MAX(my_rho, epsilon_rho))
     260      1417176 :                ds_ndrho = 1.0_dp/(MAX(t3, epsilon_rho43))
     261              :             END IF
     262              : 
     263     41098104 :             DO i = 2, m - 1 !LEGENDRE PART
     264     39680928 :                e_leg(i) = 2._dp*(t)*e_leg(i - 1) - e_leg(i - 2) - ((t)*e_leg(i - 1) - e_leg(i - 2))/(REAL(i, KIND=dp))
     265              :                !taken from quantum espresso beef library.
     266              : 
     267     41098104 :                IF (grad_deriv >= 1) THEN !first derivative
     268              :                   !the zero-derivatives need to be available for the first deriv.
     269     39680928 :                   de_leg(i) = e_leg(i - 1)*i + de_leg(i - 1)*(t)
     270              :                END IF
     271              :             END DO
     272              : 
     273              :             !add the scaled legendre linear combination to e_0
     274     43932456 :             e_0(ii) = e_0(ii) + SUM(e_leg*a)*e_ueg*sx
     275              : 
     276              :             !FIRST DERIVATIVE
     277      1417176 :             IF ((grad_deriv >= 1)) THEN !asking for first derivative or higher
     278     86447736 :                e_rho(ii) = e_rho(ii) + (SUM(e_leg*a)*e_ueg_drho + SUM(de_leg*a)*dt*ds_rho*e_ueg)*sx
     279     43932456 :                e_ndrho(ii) = e_ndrho(ii) + (SUM(de_leg*a)*dt*ds_ndrho*e_ueg)*sx
     280              :             END IF
     281              : 
     282              :          END IF
     283              :       END DO
     284              : 
     285              : !$OMP    END DO
     286              : 
     287           18 :    END SUBROUTINE xbeef_lda_calc
     288              : 
     289              : ! **************************************************************************************************
     290              : !> \brief evaluates the beef 88 exchange functional for lsd
     291              : !> \param rho_set ...
     292              : !> \param deriv_set ...
     293              : !> \param grad_deriv ...
     294              : !> \param xbeef_params ...
     295              : !> \par History
     296              : !>         2/2014 rkoitz [created based on Becke 88]
     297              : !> \author rkoitz
     298              : ! **************************************************************************************************
     299            0 :    SUBROUTINE xbeef_lsd_eval(rho_set, deriv_set, grad_deriv, xbeef_params)
     300              :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
     301              :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set
     302              :       INTEGER, INTENT(in)                                :: grad_deriv
     303              :       TYPE(section_vals_type), POINTER                   :: xbeef_params
     304              : 
     305              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xbeef_lsd_eval'
     306              : 
     307              :       INTEGER                                            :: handle, i, ispin, npoints
     308              :       INTEGER, DIMENSION(2, 3)                           :: bo
     309              :       REAL(kind=dp)                                      :: epsilon_rho, sx
     310              :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :, :), &
     311            0 :          POINTER                                         :: dummy, e_0
     312            0 :       TYPE(cp_3d_r_cp_type), DIMENSION(2)                :: e_ndrho, e_rho, norm_drho, rho, rho_1_3
     313              :       TYPE(xc_derivative_type), POINTER                  :: deriv
     314              : 
     315            0 :       CALL timeset(routineN, handle)
     316              : 
     317            0 :       CALL cite_reference(Wellendorff2012)
     318              : 
     319            0 :       NULLIFY (deriv)
     320            0 :       DO i = 1, 2
     321            0 :          NULLIFY (norm_drho(i)%array, rho(i)%array, rho_1_3(i)%array)
     322              :       END DO
     323              : 
     324            0 :       CALL section_vals_val_get(xbeef_params, "scale_x", r_val=sx)
     325              :       CALL xc_rho_set_get(rho_set, rhoa_1_3=rho_1_3(1)%array, &
     326              :                           rhob_1_3=rho_1_3(2)%array, rhoa=rho(1)%array, &
     327              :                           rhob=rho(2)%array, norm_drhoa=norm_drho(1)%array, &
     328              :                           norm_drhob=norm_drho(2)%array, rho_cutoff=epsilon_rho, &
     329            0 :                           local_bounds=bo)
     330            0 :       npoints = (bo(2, 1) - bo(1, 1) + 1)*(bo(2, 2) - bo(1, 2) + 1)*(bo(2, 3) - bo(1, 3) + 1)
     331              : 
     332            0 :       dummy => rho(1)%array
     333              : 
     334            0 :       e_0 => dummy
     335            0 :       DO i = 1, 2
     336            0 :          e_rho(i)%array => dummy
     337            0 :          e_ndrho(i)%array => dummy
     338              :       END DO
     339              : 
     340              :       deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], &
     341            0 :                                       allocate_deriv=.TRUE.)
     342            0 :       CALL xc_derivative_get(deriv, deriv_data=e_0)
     343            0 :       IF (grad_deriv >= 1) THEN
     344              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa], &
     345            0 :                                          allocate_deriv=.TRUE.)
     346            0 :          CALL xc_derivative_get(deriv, deriv_data=e_rho(1)%array)
     347              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob], &
     348            0 :                                          allocate_deriv=.TRUE.)
     349            0 :          CALL xc_derivative_get(deriv, deriv_data=e_rho(2)%array)
     350              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa], &
     351            0 :                                          allocate_deriv=.TRUE.)
     352            0 :          CALL xc_derivative_get(deriv, deriv_data=e_ndrho(1)%array)
     353              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob], &
     354            0 :                                          allocate_deriv=.TRUE.)
     355            0 :          CALL xc_derivative_get(deriv, deriv_data=e_ndrho(2)%array)
     356              :       END IF
     357            0 :       IF (grad_deriv > 1) THEN
     358            0 :          CPABORT("derivatives greater than 1 not implemented")
     359              :       END IF
     360              : 
     361            0 :       DO ispin = 1, 2
     362              : 
     363              : !$OMP        PARALLEL DEFAULT(NONE) &
     364              : !$OMP                 SHARED(rho, ispin, rho_1_3, norm_drho, e_0) &
     365              : !$OMP                 SHARED(e_rho, e_ndrho) &
     366              : !$OMP                 SHARED(grad_deriv, npoints) &
     367            0 : !$OMP                 SHARED(epsilon_rho, sx)
     368              : 
     369              :          CALL xbeef_lsd_calc( &
     370              :             rho_spin=rho(ispin)%array, &
     371              :             rho_1_3_spin=rho_1_3(ispin)%array, &
     372              :             norm_drho_spin=norm_drho(ispin)%array, &
     373              :             e_0=e_0, e_rho_spin=e_rho(ispin)%array, &
     374              :             e_ndrho_spin=e_ndrho(ispin)%array, &
     375              :             grad_deriv=grad_deriv, npoints=npoints, &
     376              :             epsilon_rho=epsilon_rho, sx=sx)
     377              : 
     378              : !$OMP        END PARALLEL
     379              : 
     380              :       END DO
     381              : 
     382            0 :       CALL timestop(handle)
     383              : 
     384            0 :    END SUBROUTINE xbeef_lsd_eval
     385              : ! **************************************************************************************************
     386              : !> \brief low level calculation of the beef exchange functional for lsd
     387              : !> \param rho_spin alpha or beta spin density
     388              : !> \param rho_1_3_spin rho_spin**(1./3.)
     389              : !> \param norm_drho_spin || grad rho_spin ||
     390              : !> \param e_0 adds to it the local value of the functional
     391              : !> \param e_rho_spin e_*_spin: derivative of the functional wrt. to the variables
     392              : !>        named where the * is. Everything wrt. to the spin of the arguments.
     393              : !> \param e_ndrho_spin ...
     394              : !> \param grad_deriv ...
     395              : !> \param npoints ...
     396              : !> \param epsilon_rho ...
     397              : !> \param sx scaling-parameter for exchange
     398              : !> \par History
     399              : !>      02.2014 created based on Becke88
     400              : !> \author rkoitz
     401              : ! **************************************************************************************************
     402            0 :    SUBROUTINE xbeef_lsd_calc(rho_spin, rho_1_3_spin, norm_drho_spin, e_0, &
     403              :                              e_rho_spin, e_ndrho_spin, grad_deriv, npoints, epsilon_rho, sx)
     404              :       REAL(kind=dp), DIMENSION(*), INTENT(in)            :: rho_spin, rho_1_3_spin, norm_drho_spin
     405              :       REAL(kind=dp), DIMENSION(*), INTENT(inout)         :: e_0, e_rho_spin, e_ndrho_spin
     406              :       INTEGER, INTENT(in)                                :: grad_deriv, npoints
     407              :       REAL(kind=dp), INTENT(in)                          :: epsilon_rho, sx
     408              : 
     409              :       INTEGER, PARAMETER                                 :: m = 30
     410              : 
     411              :       INTEGER                                            :: i, ii
     412              :       REAL(kind=dp)                                      :: ds_ndrho, ds_rho, dt, e_ueg, e_ueg_drho, &
     413              :                                                             epsilon_rho43, k_lsd, kf, &
     414              :                                                             my_epsilon_rho, my_rho, my_rho_1_3, s, &
     415              :                                                             s2, t, t3
     416              :       REAL(kind=dp), DIMENSION(0:29)                     :: de_leg, e_leg
     417              : 
     418              : !energies and first derivatives from legendre pol
     419              : 
     420            0 :       kf = (3.0_dp*pi**2)**(1.0_dp/3.0_dp) !only constants, without n^1/3
     421            0 :       k_lsd = (3.0_dp/2.0_dp)*(3.0_dp/(4.0_dp*pi))**(1.0_dp/3.0_dp)
     422              :       !exchange energy density of the uniform electron gas, spin-polarized
     423              : 
     424            0 :       my_epsilon_rho = 0.5_dp*epsilon_rho
     425            0 :       epsilon_rho43 = my_epsilon_rho**(4._dp/3._dp)
     426              : 
     427            0 : !$OMP     DO
     428              :       DO ii = 1, npoints
     429            0 :          my_rho = rho_spin(ii)
     430              : 
     431            0 :          IF (my_rho > epsilon_rho) THEN
     432            0 :             my_rho_1_3 = rho_1_3_spin(ii)
     433              : 
     434            0 :             e_ueg = k_lsd*my_rho*my_rho_1_3
     435            0 :             e_ueg_drho = (4.0_dp/3.0_dp)*k_lsd*my_rho_1_3
     436              : 
     437            0 :             t3 = my_rho_1_3*my_rho*2*kf !reduced gradient, denominator
     438              : 
     439            0 :             s = norm_drho_spin(ii)/MAX(t3, epsilon_rho43) !reduced gradient finally
     440            0 :             s2 = s**2
     441            0 :             t = 2.0_dp*s**2/(4.0_dp + s**2) - 1.0_dp
     442              : 
     443            0 :             e_leg(0) = 1 !first legendre pol
     444            0 :             e_leg(1) = t !second legendre pol
     445              : 
     446            0 :             IF ((grad_deriv >= 1)) THEN !asking for first derivative or higher
     447            0 :                de_leg(0) = 0
     448            0 :                de_leg(1) = 1
     449            0 :                dt = 4.0_dp*s/(4.0_dp + s2) - 4.0_dp*s*s2/(4.0_dp + s2)**2
     450            0 :                ds_rho = -(4.0_dp*s)/(3.0_dp*MAX(my_rho, epsilon_rho))
     451            0 :                ds_ndrho = 1.0_dp/(MAX(t3, epsilon_rho43))
     452              :             END IF
     453              : 
     454            0 :             DO i = 2, m - 1 !LEGENDRE PART
     455            0 :                e_leg(i) = 2._dp*(t)*e_leg(i - 1) - e_leg(i - 2) - ((t)*e_leg(i - 1) - e_leg(i - 2))/(REAL(i, KIND=dp))
     456              :                !taken from quantum espresso beef library.
     457              : 
     458            0 :                IF (grad_deriv >= 1) THEN !first derivative
     459              :                   !the zero-derivatives need to be available for the first deriv.
     460            0 :                   de_leg(i) = e_leg(i - 1)*i + de_leg(i - 1)*(t)
     461              :                END IF
     462              : 
     463              :             END DO
     464              : 
     465              :             !NO DERIVATIVE
     466              :             !add the scaled legendre linear combination to e_0
     467            0 :             e_0(ii) = e_0(ii) + SUM(e_leg*a)*e_ueg*sx
     468              : 
     469              :             !FIRST DERIVATIVE
     470            0 :             IF ((grad_deriv >= 1)) THEN !asking for first derivative or higher
     471            0 :                e_rho_spin(ii) = e_rho_spin(ii) + (SUM(e_leg*a)*e_ueg_drho + SUM(de_leg*a)*dt*ds_rho*e_ueg)*sx
     472            0 :                e_ndrho_spin(ii) = e_ndrho_spin(ii) + (SUM(de_leg*a)*dt*ds_ndrho*e_ueg)*sx
     473              :             END IF
     474              :          END IF
     475              :       END DO
     476              : !$OMP   END DO
     477              : 
     478            0 :    END SUBROUTINE xbeef_lsd_calc
     479              : 
     480              : END MODULE xc_xbeef
     481              : 
        

Generated by: LCOV version 2.0-1