LCOV - code coverage report
Current view: top level - src/xc - xc_perdew_zunger.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 67.5 % 234 158
Test Date: 2026-11-04 00:58:17 Functions: 100.0 % 9 9

            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 Perdew-Zunger correlation potential and
      10              : !>      energy density and ist derivatives with respect to
      11              : !>      the spin-up and spin-down densities up to 3rd order.
      12              : !> \par History
      13              : !>      18-MAR-2002, TCH, working version
      14              : !>      fawzi (04.2004)  : adapted to the new xc interface
      15              : !> \see functionals_utilities
      16              : ! **************************************************************************************************
      17              : MODULE xc_perdew_zunger
      18              :    USE bibliography,                    ONLY: Ortiz1994,&
      19              :                                               Perdew1981,&
      20              :                                               cite_reference
      21              :    USE input_section_types,             ONLY: section_vals_type,&
      22              :                                               section_vals_val_get
      23              :    USE kinds,                           ONLY: dp
      24              :    USE xc_derivative_desc,              ONLY: deriv_rho,&
      25              :                                               deriv_rhoa,&
      26              :                                               deriv_rhob
      27              :    USE xc_derivative_set_types,         ONLY: xc_derivative_set_type,&
      28              :                                               xc_dset_get_derivative
      29              :    USE xc_derivative_types,             ONLY: xc_derivative_get,&
      30              :                                               xc_derivative_type
      31              :    USE xc_functionals_utilities,        ONLY: calc_fx,&
      32              :                                               calc_rs,&
      33              :                                               calc_z,&
      34              :                                               set_util
      35              :    USE xc_input_constants,              ONLY: pz_dmc,&
      36              :                                               pz_orig,&
      37              :                                               pz_vmc
      38              :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_type
      39              :    USE xc_rho_set_types,                ONLY: xc_rho_set_get,&
      40              :                                               xc_rho_set_type
      41              : #include "../base/base_uses.f90"
      42              : 
      43              :    IMPLICIT NONE
      44              :    PRIVATE
      45              : 
      46              :    LOGICAL :: initialized = .FALSE.
      47              :    REAL(KIND=dp), DIMENSION(0:1) :: A = 0.0_dp, B = 0.0_dp, C = 0.0_dp, D = 0.0_dp, &
      48              :                                     b1 = 0.0_dp, b2 = 0.0_dp, ga = 0.0_dp
      49              : 
      50              :    REAL(KIND=dp), PARAMETER :: epsilon = 5.E-13_dp
      51              :    REAL(KIND=dp) :: eps_rho
      52              : 
      53              :    PUBLIC :: pz_info, pz_lda_eval, pz_lsd_eval
      54              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xc_perdew_zunger'
      55              : 
      56              : CONTAINS
      57              : 
      58              : ! **************************************************************************************************
      59              : !> \brief Return some info on the functionals.
      60              : !> \param method ...
      61              : !> \param lsd ...
      62              : !> \param reference CHARACTER(*), INTENT(OUT), OPTIONAL - full reference
      63              : !> \param shortform CHARACTER(*), INTENT(OUT), OPTIONAL - short reference
      64              : !> \param needs ...
      65              : !> \param max_deriv ...
      66              : !> \par History
      67              : !>      18-MAR-2002, TCH, working version
      68              : ! **************************************************************************************************
      69           39 :    SUBROUTINE pz_info(method, lsd, reference, shortform, needs, max_deriv)
      70              :       INTEGER, INTENT(in)                                :: method
      71              :       LOGICAL, INTENT(in)                                :: lsd
      72              :       CHARACTER(LEN=*), INTENT(OUT), OPTIONAL            :: reference, shortform
      73              :       TYPE(xc_rho_cflags_type), INTENT(inout), OPTIONAL  :: needs
      74              :       INTEGER, INTENT(out), OPTIONAL                     :: max_deriv
      75              : 
      76              :       CHARACTER(len=4)                                   :: p_string
      77              : 
      78           39 :       SELECT CASE (method)
      79              :       CASE DEFAULT
      80            0 :          CPABORT("Unsupported parametrization")
      81              :       CASE (pz_orig)
      82           39 :          p_string = 'ORIG'
      83              :       CASE (pz_dmc)
      84            0 :          p_string = 'DMC'
      85              :       CASE (pz_vmc)
      86            0 :          p_string = 'VMC'
      87              :       END SELECT
      88              : 
      89           39 :       IF (PRESENT(reference)) THEN
      90              :          reference = "J. P. Perdew and Alex Zunger," &
      91              :                      //" Phys. Rev. B 23, 5048 (1981)" &
      92            1 :                      //"["//TRIM(p_string)//"]"
      93            1 :          IF (.NOT. lsd) THEN
      94            1 :             IF (LEN_TRIM(reference) + 6 < LEN(reference)) THEN
      95            1 :                reference(LEN_TRIM(reference):LEN_TRIM(reference) + 6) = ' {LDA}'
      96              :             END IF
      97              :          END IF
      98              :       END IF
      99           39 :       IF (PRESENT(shortform)) THEN
     100              :          shortform = "J. P. Perdew et al., PRB 23, 5048 (1981)" &
     101            1 :                      //"["//TRIM(p_string)//"]"
     102            1 :          IF (.NOT. lsd) THEN
     103            1 :             IF (LEN_TRIM(shortform) + 6 < LEN(shortform)) THEN
     104            1 :                shortform(LEN_TRIM(shortform):LEN_TRIM(shortform) + 6) = ' {LDA}'
     105              :             END IF
     106              :          END IF
     107              :       END IF
     108           39 :       IF (PRESENT(needs)) THEN
     109           38 :          IF (lsd) THEN
     110            6 :             needs%rho_spin = .TRUE.
     111              :          ELSE
     112           32 :             needs%rho = .TRUE.
     113              :          END IF
     114              :       END IF
     115           39 :       IF (PRESENT(max_deriv)) max_deriv = 3
     116              : 
     117           39 :    END SUBROUTINE pz_info
     118              : 
     119              : ! **************************************************************************************************
     120              : !> \brief Calculate the correlation energy and its derivatives
     121              : !>      wrt to rho (the electron density) up to 3rd order. This
     122              : !>      is the LDA version of the Perdew-Zunger correlation energy
     123              : !>      If no order argument is given, then the routine calculates
     124              : !>      just the energy.
     125              : !> \param method ...
     126              : !> \param rho_set ...
     127              : !> \param deriv_set ...
     128              : !> \param order INTEGER, OPTIONAL - maximum order of derivatives to calculate
     129              : !>        order must lie between 0 and 3.
     130              : !> \param pz_params input parameter (scaling)
     131              : !> \par History
     132              : !>     01.2007 added scaling [Manuel Guidon]
     133              : ! **************************************************************************************************
     134          654 :    SUBROUTINE pz_lda_eval(method, rho_set, deriv_set, order, pz_params)
     135              : 
     136              :       INTEGER, INTENT(in)                                :: method
     137              :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
     138              :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set
     139              :       INTEGER, INTENT(in)                                :: order
     140              :       TYPE(section_vals_type), POINTER                   :: pz_params
     141              : 
     142              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'pz_lda_eval'
     143              : 
     144              :       INTEGER                                            :: npoints, timer_handle
     145              :       INTEGER, DIMENSION(2, 3)                           :: bo
     146              :       REAL(KIND=dp)                                      :: rho_cutoff, sc
     147              :       REAL(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
     148          218 :          POINTER                                         :: dummy, e_0, e_rho, e_rho_rho, &
     149          218 :                                                             e_rho_rho_rho, rho
     150              :       TYPE(xc_derivative_type), POINTER                  :: deriv
     151              : 
     152          218 :       CALL timeset(routineN, timer_handle)
     153          218 :       NULLIFY (rho, e_0, e_rho, e_rho_rho, e_rho_rho_rho, dummy)
     154              : 
     155          218 :       CALL section_vals_val_get(pz_params, "scale_c", r_val=sc)
     156              : 
     157              :       CALL xc_rho_set_get(rho_set, rho=rho, &
     158          218 :                           local_bounds=bo, rho_cutoff=rho_cutoff)
     159          218 :       npoints = (bo(2, 1) - bo(1, 1) + 1)*(bo(2, 2) - bo(1, 2) + 1)*(bo(2, 3) - bo(1, 3) + 1)
     160              : 
     161          218 :       CALL pz_init(method, rho_cutoff)
     162              : 
     163          218 :       dummy => rho
     164              : 
     165          218 :       e_0 => dummy
     166          218 :       e_rho => dummy
     167          218 :       e_rho_rho => dummy
     168          218 :       e_rho_rho_rho => dummy
     169              : 
     170              :       deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], &
     171          218 :                                       allocate_deriv=.TRUE.)
     172          218 :       CALL xc_derivative_get(deriv, deriv_data=e_0)
     173          218 :       IF (order >= 1) THEN
     174              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rho], &
     175          212 :                                          allocate_deriv=.TRUE.)
     176          212 :          CALL xc_derivative_get(deriv, deriv_data=e_rho)
     177              :       END IF
     178          218 :       IF (order >= 2) THEN
     179              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rho, deriv_rho], &
     180            0 :                                          allocate_deriv=.TRUE.)
     181            0 :          CALL xc_derivative_get(deriv, deriv_data=e_rho_rho)
     182              :       END IF
     183          218 :       IF (order >= 3) THEN
     184              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rho, deriv_rho, deriv_rho], &
     185            0 :                                          allocate_deriv=.TRUE.)
     186            0 :          CALL xc_derivative_get(deriv, deriv_data=e_rho_rho_rho)
     187              :       END IF
     188          218 :       IF (order > 3) THEN
     189            0 :          CPABORT("derivatives bigger than 3 not implemented")
     190              :       END IF
     191              : 
     192          218 :       CALL pz_lda_calc(rho, e_0, e_rho, e_rho_rho, e_rho_rho_rho, npoints, order, sc)
     193              : 
     194          218 :       CALL timestop(timer_handle)
     195              : 
     196          218 :    END SUBROUTINE pz_lda_eval
     197              : 
     198              : ! **************************************************************************************************
     199              : !> \brief ...
     200              : !> \param rho ...
     201              : !> \param e_0 ...
     202              : !> \param e_rho ...
     203              : !> \param e_rho_rho ...
     204              : !> \param e_rho_rho_rho ...
     205              : !> \param npoints ...
     206              : !> \param order ...
     207              : !> \param sc ...
     208              : ! **************************************************************************************************
     209          218 :    SUBROUTINE pz_lda_calc(rho, e_0, e_rho, e_rho_rho, e_rho_rho_rho, npoints, order, sc)
     210              :       !FM low level calc routine
     211              :       REAL(KIND=dp), DIMENSION(*), INTENT(in)            :: rho
     212              :       REAL(KIND=dp), DIMENSION(*), INTENT(inout)         :: e_0, e_rho, e_rho_rho, e_rho_rho_rho
     213              :       INTEGER, INTENT(in)                                :: npoints, order
     214              :       REAL(KIND=dp)                                      :: sc
     215              : 
     216              :       INTEGER                                            :: k
     217              :       REAL(KIND=dp), DIMENSION(0:3)                      :: ed
     218              : 
     219              : !$OMP PARALLEL DO PRIVATE ( k, ed ) DEFAULT(NONE)&
     220          218 : !$OMP SHARED(npoints,rho,eps_rho,order,e_0,e_rho,e_rho_rho,e_rho_rho_rho,sc)
     221              :       DO k = 1, npoints
     222              : 
     223              :          IF (rho(k) > eps_rho) THEN
     224              : 
     225              :             CALL pz_lda_ed_loc(rho(k), ed, ABS(order), sc)
     226              : 
     227              :             e_0(k) = e_0(k) + rho(k)*ed(0)
     228              :             IF (order >= 1) THEN
     229              :                e_rho(k) = e_rho(k) + ed(0) + rho(k)*ed(1)
     230              :             END IF
     231              :             IF (order >= 2) THEN
     232              :                e_rho_rho(k) = e_rho_rho(k) + 2.0_dp*ed(1) + rho(k)*ed(2)
     233              :             END IF
     234              :             IF (order >= 3) THEN
     235              :                e_rho_rho_rho(k) = e_rho_rho_rho(k) + 3.0_dp*ed(2) + rho(k)*ed(3)
     236              :             END IF
     237              : 
     238              :          END IF
     239              : 
     240              :       END DO
     241              : !$OMP END PARALLEL DO
     242              : 
     243          218 :    END SUBROUTINE pz_lda_calc
     244              : 
     245              : ! **************************************************************************************************
     246              : !> \brief Calculate the correlation energy and its derivatives
     247              : !>      wrt to rho (the electron density) up to 3rd order. This
     248              : !>      is the LSD version of the Perdew-Zunger correlation energy
     249              : !>      If no order argument is given, then the routine calculates
     250              : !>      just the energy.
     251              : !> \param method ...
     252              : !> \param rho_set ...
     253              : !> \param deriv_set ...
     254              : !> \param order INTEGER, OPTIONAL - maximum order of derivatives to calculate
     255              : !>        order must lie between 0 and 3.
     256              : !> \param pz_params input parameter (scaling)
     257              : !> \par History
     258              : !>      01.2007 added scaling [Manuel Guidon]
     259              : ! **************************************************************************************************
     260           36 :    SUBROUTINE pz_lsd_eval(method, rho_set, deriv_set, order, pz_params)
     261              :       INTEGER, INTENT(in)                                :: method
     262              :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
     263              :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set
     264              :       INTEGER, INTENT(IN), OPTIONAL                      :: order
     265              :       TYPE(section_vals_type), POINTER                   :: pz_params
     266              : 
     267              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'pz_lsd_eval'
     268              : 
     269              :       INTEGER                                            :: npoints, timer_handle
     270              :       INTEGER, DIMENSION(2, 3)                           :: bo
     271              :       REAL(KIND=dp)                                      :: rho_cutoff, sc
     272              :       REAL(KIND=dp), CONTIGUOUS, DIMENSION(:, :, :), &
     273           12 :          POINTER                                         :: a, b, dummy, e_0, ea, eaa, eaaa, eaab, &
     274           12 :                                                             eab, eabb, ebb, ebbb
     275              :       TYPE(xc_derivative_type), POINTER                  :: deriv
     276              : 
     277           12 :       CALL timeset(routineN, timer_handle)
     278           12 :       NULLIFY (a, b, e_0, ea, eaa, eab, ebb, eaaa, eaab, eabb, ebbb)
     279              : 
     280           12 :       CALL section_vals_val_get(pz_params, "scale_c", r_val=sc)
     281              : 
     282              :       CALL xc_rho_set_get(rho_set, rhoa=a, rhob=b, &
     283           12 :                           local_bounds=bo, rho_cutoff=rho_cutoff)
     284           12 :       npoints = (bo(2, 1) - bo(1, 1) + 1)*(bo(2, 2) - bo(1, 2) + 1)*(bo(2, 3) - bo(1, 3) + 1)
     285              : 
     286           12 :       CALL pz_init(method, rho_cutoff)
     287              : 
     288           12 :       dummy => a
     289              : 
     290           12 :       e_0 => dummy
     291           12 :       ea => dummy
     292           12 :       eaa => dummy; eab => dummy; ebb => dummy
     293           12 :       eaaa => dummy; eaab => dummy; eabb => dummy; ebbb => dummy
     294              : 
     295              :       deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], &
     296           12 :                                       allocate_deriv=.TRUE.)
     297           12 :       CALL xc_derivative_get(deriv, deriv_data=e_0)
     298           12 :       IF (order >= 1) THEN
     299              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa], &
     300            6 :                                          allocate_deriv=.TRUE.)
     301            6 :          CALL xc_derivative_get(deriv, deriv_data=ea)
     302              :       END IF
     303           12 :       IF (order >= 2) THEN
     304              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa, deriv_rhoa], &
     305            0 :                                          allocate_deriv=.TRUE.)
     306            0 :          CALL xc_derivative_get(deriv, deriv_data=eaa)
     307              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa, deriv_rhob], &
     308            0 :                                          allocate_deriv=.TRUE.)
     309            0 :          CALL xc_derivative_get(deriv, deriv_data=eab)
     310              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob, deriv_rhob], &
     311            0 :                                          allocate_deriv=.TRUE.)
     312            0 :          CALL xc_derivative_get(deriv, deriv_data=ebb)
     313              :       END IF
     314           12 :       IF (order >= 3) THEN
     315              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa, deriv_rhoa, deriv_rhoa], &
     316            0 :                                          allocate_deriv=.TRUE.)
     317            0 :          CALL xc_derivative_get(deriv, deriv_data=eaaa)
     318              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa, deriv_rhoa, deriv_rhob], &
     319            0 :                                          allocate_deriv=.TRUE.)
     320            0 :          CALL xc_derivative_get(deriv, deriv_data=eaab)
     321              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa, deriv_rhob, deriv_rhob], &
     322            0 :                                          allocate_deriv=.TRUE.)
     323            0 :          CALL xc_derivative_get(deriv, deriv_data=eabb)
     324              :          deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob, deriv_rhob, deriv_rhob], &
     325            0 :                                          allocate_deriv=.TRUE.)
     326            0 :          CALL xc_derivative_get(deriv, deriv_data=ebbb)
     327              :       END IF
     328           12 :       IF (order > 3) THEN
     329            0 :          CPABORT("derivatives bigger than 3 not implemented")
     330              :       END IF
     331              : 
     332              :       CALL pz_lsd_calc(a, b, e_0, ea, eaa, eab, ebb, eaaa, eaab, eabb, &
     333           12 :                        ebbb, npoints, order, sc)
     334              : 
     335           12 :       CALL timestop(timer_handle)
     336              : 
     337           12 :    END SUBROUTINE pz_lsd_eval
     338              : 
     339              : ! **************************************************************************************************
     340              : !> \brief ...
     341              : !> \param a ...
     342              : !> \param b ...
     343              : !> \param e_0 ...
     344              : !> \param ea ...
     345              : !> \param eaa ...
     346              : !> \param eab ...
     347              : !> \param ebb ...
     348              : !> \param eaaa ...
     349              : !> \param eaab ...
     350              : !> \param eabb ...
     351              : !> \param ebbb ...
     352              : !> \param npoints ...
     353              : !> \param order ...
     354              : !> \param sc ...
     355              : ! **************************************************************************************************
     356           12 :    SUBROUTINE pz_lsd_calc(a, b, e_0, ea, eaa, eab, ebb, eaaa, eaab, eabb, &
     357              :                           ebbb, npoints, order, sc)
     358              :       !FM low-level computation routine
     359              :       REAL(KIND=dp), DIMENSION(*), INTENT(in)            :: a, b
     360              :       REAL(KIND=dp), DIMENSION(*), INTENT(inout)         :: e_0, ea, eaa, eab, ebb, eaaa, eaab, &
     361              :                                                             eabb, ebbb
     362              :       INTEGER, INTENT(in)                                :: npoints, order
     363              :       REAL(KIND=dp), INTENT(IN)                          :: sc
     364              : 
     365              :       INTEGER                                            :: k, order_
     366              :       REAL(KIND=dp)                                      :: rho
     367              :       REAL(KIND=dp), DIMENSION(0:9)                      :: ed
     368              : 
     369           12 :       order_ = ABS(order)
     370              : 
     371              : !$OMP PARALLEL DO PRIVATE ( k, rho, ed ) DEFAULT(NONE)&
     372           12 : !$OMP SHARED(order_,order,npoints,eps_rho,A,b,sc,e_0,ea,eaa,eab,ebb,eaaa,eaab,eabb,ebbb)
     373              :       DO k = 1, npoints
     374              : 
     375              :          rho = a(k) + b(k)
     376              : 
     377              :          IF (rho > eps_rho) THEN
     378              : 
     379              :             CALL pz_lsd_ed_loc(a(k), b(k), ed, order_, sc)
     380              : 
     381              :             e_0(k) = e_0(k) + rho*ed(0)
     382              : 
     383              :             IF (order >= 1) THEN
     384              :                ea(k) = ea(k) + ed(0) + rho*ed(1)
     385              :                ea(k) = ea(k) + ed(0) + rho*ed(2)
     386              :             END IF
     387              : 
     388              :             IF (order >= 2) THEN
     389              :                eaa(k) = eaa(k) + 2.0_dp*ed(1) + rho*ed(3)
     390              :                eab(k) = eab(k) + ed(1) + ed(2) + rho*ed(4)
     391              :                ebb(k) = ebb(k) + 2.0_dp*ed(2) + rho*ed(5)
     392              :             END IF
     393              : 
     394              :             IF (order >= 3) THEN
     395              :                eaaa(k) = eaaa(k) + 3.0_dp*ed(3) + rho*ed(6)
     396              :                eaab(k) = eaab(k) + 2.0_dp*ed(4) + ed(3) + rho*ed(7)
     397              :                eabb(k) = eabb(k) + 2.0_dp*ed(4) + ed(5) + rho*ed(8)
     398              :                ebbb(k) = ebbb(k) + 3.0_dp*ed(5) + rho*ed(9)
     399              :             END IF
     400              : 
     401              :          END IF
     402              : 
     403              :       END DO
     404              : !$OMP END PARALLEL DO
     405              : 
     406           12 :    END SUBROUTINE pz_lsd_calc
     407              : 
     408              : ! **************************************************************************************************
     409              : !> \brief Initializes the functionals
     410              : !> \param method CHARACTER(3) - name of the method used for parameters
     411              : !> \param cutoff REAL(KIND=dp) - the cutoff density
     412              : !> \par History
     413              : !>      18-MAR-2002, TCH, working version
     414              : !> \note see functionals_utilities
     415              : ! **************************************************************************************************
     416          230 :    SUBROUTINE pz_init(method, cutoff)
     417              : 
     418              :       INTEGER, INTENT(IN)                                :: method
     419              :       REAL(KIND=dp), INTENT(IN)                          :: cutoff
     420              : 
     421          230 :       CALL set_util(cutoff)
     422              : 
     423          230 :       eps_rho = cutoff
     424              : 
     425          230 :       initialized = .FALSE.
     426              : 
     427          230 :       SELECT CASE (method)
     428              : 
     429              :       CASE DEFAULT
     430            0 :          CPABORT("Unknown method")
     431              : 
     432              :       CASE (pz_orig)
     433          230 :          CALL cite_reference(Perdew1981)
     434          230 :          ga(0) = -0.1423_dp; ga(1) = -0.0843_dp
     435          230 :          b1(0) = 1.0529_dp; b1(1) = 1.3981_dp
     436          230 :          b2(0) = 0.3334_dp; b2(1) = 0.2611_dp
     437          230 :          A(0) = 0.0311_dp; A(1) = 0.01555_dp
     438          230 :          B(0) = -0.048_dp; B(1) = -0.0269_dp
     439          230 :          C(0) = +0.0020_dp; C(1) = +0.0007_dp
     440          230 :          D(0) = -0.0116_dp; D(1) = -0.0048_dp
     441              : 
     442              :       CASE (pz_dmc)
     443            0 :          CALL cite_reference(Ortiz1994)
     444            0 :          ga(0) = -0.103756_dp; ga(1) = -0.065951_dp
     445            0 :          b1(0) = 0.56371_dp; b1(1) = 1.11846_dp
     446            0 :          b2(0) = 0.27358_dp; b2(1) = 0.18797_dp
     447            0 :          A(0) = 0.031091_dp; A(1) = 0.015545_dp
     448            0 :          B(0) = -0.046644_dp; B(1) = -0.025599_dp
     449            0 :          C(0) = -0.00419_dp; C(1) = -0.00329_dp
     450            0 :          D(0) = -0.00983_dp; D(1) = -0.00300_dp
     451              : 
     452              :       CASE (pz_vmc)
     453            0 :          CALL cite_reference(Ortiz1994)
     454            0 :          ga(0) = -0.093662_dp; ga(1) = -0.055331_dp
     455            0 :          b1(0) = 0.49453_dp; b1(1) = 0.93766_dp
     456            0 :          b2(0) = 0.25534_dp; b2(1) = 0.14829_dp
     457            0 :          A(0) = 0.031091_dp; A(1) = 0.015545_dp
     458            0 :          B(0) = -0.046644_dp; B(1) = -0.025599_dp
     459            0 :          C(0) = -0.00884_dp; C(1) = -0.00677_dp
     460          230 :          D(0) = -0.00688_dp; D(1) = -0.00093_dp
     461              : 
     462              :       END SELECT
     463              : 
     464          230 :       initialized = .TRUE.
     465              : 
     466          230 :    END SUBROUTINE pz_init
     467              : 
     468              : ! **************************************************************************************************
     469              : !> \brief ...
     470              : !> \param r ...
     471              : !> \param z ...
     472              : !> \param g ...
     473              : !> \param order ...
     474              : ! **************************************************************************************************
     475     37362837 :    SUBROUTINE calc_g(r, z, g, order)
     476              : 
     477              :       REAL(KIND=dp), INTENT(IN)                          :: r
     478              :       INTEGER, INTENT(IN)                                :: z
     479              :       REAL(KIND=dp), DIMENSION(0:), INTENT(OUT)          :: g
     480              :       INTEGER, INTENT(IN)                                :: order
     481              : 
     482              :       REAL(KIND=dp)                                      :: rr, rsr, sr
     483              : 
     484     37362837 :       IF (r >= 1.0_dp) THEN
     485              : 
     486     37265424 :          sr = SQRT(r)
     487              :          ! order 0 must always be calculated
     488     37265424 :          g(0) = ga(z)/(1.0_dp + b1(z)*sr + b2(z)*r)
     489     37265424 :          IF (order >= 1) THEN
     490              :             g(1) = -ga(z)*(b1(z)/(2.0_dp*sr) + b2(z))/ &
     491     36869492 :                    (1.0_dp + b1(z)*sr + b2(z)*r)**2
     492              :          END IF
     493     37265424 :          IF (order >= 2) THEN
     494            0 :             rsr = r*sr
     495              :             g(2) = &
     496              :                2.0_dp*ga(z)*(b1(z)/(2.0_dp*sr) + b2(z))**2 &
     497              :                /(1.0_dp + b1(z)*sr + b2(z)*r)**3 &
     498              :                + ga(z)*b1(z) &
     499            0 :                /(4.0_dp*(1.0_dp + b1(z)*sr + b2(z)*r)**2*rsr)
     500              :          END IF
     501     37265424 :          IF (order >= 3) THEN
     502              :             g(3) = &
     503              :                -6.0_dp*ga(z)*(b1(z)/(2.0_dp*sr) + b2(z))**3/ &
     504              :                (1.0_dp + b1(z)*sr + b2(z)*r)**4 &
     505              :                - (3.0_dp/2.0_dp)*ga(z)*(b1(z)/(2.0_dp*sr) + b2(z))*b1(z)/ &
     506              :                ((1.0_dp + b1(z)*sr + b2(z)*r)**3*rsr) &
     507              :                - (3.0_dp/8.0_dp)*ga(z)*b1(z)/ &
     508            0 :                ((1.0_dp + b1(z)*sr + b2(z)*r)**2*r*rsr)
     509              :          END IF
     510              : 
     511              :       ELSE
     512              : 
     513              :          ! order 0 must always be calculated
     514        97413 :          g(0) = A(z)*LOG(r) + B(z) + C(z)*r*LOG(r) + D(z)*r
     515        97413 :          IF (order >= 1) THEN
     516        85783 :             g(1) = A(z)/r + C(z)*LOG(r) + C(z) + D(z)
     517              :          END IF
     518        97413 :          IF (order >= 2) THEN
     519            0 :             rr = r*r
     520            0 :             g(2) = -A(z)/rr + C(z)/r
     521              :          END IF
     522        97413 :          IF (order >= 3) THEN
     523            0 :             g(3) = 2.0_dp*A(z)/(rr*r) - C(z)/rr
     524              :          END IF
     525              : 
     526              :       END IF
     527              : 
     528     37362837 :    END SUBROUTINE calc_g
     529              : 
     530              : ! **************************************************************************************************
     531              : !> \brief ...
     532              : !> \param rho ...
     533              : !> \param ed ...
     534              : !> \param order ...
     535              : !> \param sc ...
     536              : ! **************************************************************************************************
     537     36664213 :    SUBROUTINE pz_lda_ed_loc(rho, ed, order, sc)
     538              : 
     539              :       REAL(KIND=dp), INTENT(IN)                          :: rho
     540              :       REAL(KIND=dp), DIMENSION(0:), INTENT(OUT)          :: ed
     541              :       INTEGER, INTENT(IN)                                :: order
     542              :       REAL(dp), INTENT(IN)                               :: sc
     543              : 
     544              :       INTEGER                                            :: m, order_
     545              :       LOGICAL, DIMENSION(0:3)                            :: calc
     546              :       REAL(KIND=dp), DIMENSION(0:3)                      :: e0, r
     547              : 
     548     36664213 :       calc = .FALSE.
     549              : 
     550     36664213 :       order_ = order
     551     36664213 :       IF (order_ >= 0) THEN
     552    109934389 :          calc(0:order_) = .TRUE.
     553              :       ELSE
     554            0 :          order_ = -1*order_
     555            0 :          calc(order_) = .TRUE.
     556              :       END IF
     557              : 
     558     36664213 :       CALL calc_rs(rho, r(0))
     559     36664213 :       CALL calc_g(r(0), 0, e0, order_)
     560              : 
     561     36664213 :       IF (order_ >= 1) r(1) = (-1.0_dp/3.0_dp)*r(0)/rho
     562     36664213 :       IF (order_ >= 2) r(2) = (-4.0_dp/3.0_dp)*r(1)/rho
     563     36664213 :       IF (order_ >= 3) r(3) = (-7.0_dp/3.0_dp)*r(2)/rho
     564              : 
     565     36664213 :       m = 0
     566     36664213 :       IF (calc(0)) THEN
     567     36664213 :          ed(m) = sc*e0(0)
     568     36664213 :          m = m + 1
     569              :       END IF
     570     36664213 :       IF (calc(1)) THEN
     571     36605963 :          ed(m) = sc*e0(1)*r(1)
     572     36605963 :          m = m + 1
     573              :       END IF
     574     36664213 :       IF (calc(2)) THEN
     575            0 :          ed(m) = sc*e0(2)*r(1)**2 + sc*e0(1)*r(2)
     576            0 :          m = m + 1
     577              :       END IF
     578     36664213 :       IF (calc(3)) THEN
     579            0 :          ed(m) = sc*e0(3)*r(1)**3 + sc*e0(2)*3.0_dp*r(1)*r(2) + sc*e0(1)*r(3)
     580              :       END IF
     581              : 
     582     36664213 :    END SUBROUTINE pz_lda_ed_loc
     583              : 
     584              : ! **************************************************************************************************
     585              : !> \brief ...
     586              : !> \param a ...
     587              : !> \param b ...
     588              : !> \param ed ...
     589              : !> \param order ...
     590              : !> \param sc ...
     591              : ! **************************************************************************************************
     592       349312 :    SUBROUTINE pz_lsd_ed_loc(a, b, ed, order, sc)
     593              : 
     594              :       REAL(KIND=dp), INTENT(IN)                          :: a, b
     595              :       REAL(KIND=dp), DIMENSION(0:), INTENT(OUT)          :: ed
     596              :       INTEGER, INTENT(IN), OPTIONAL                      :: order
     597              :       REAL(KIND=dp), INTENT(IN)                          :: sc
     598              : 
     599              :       INTEGER                                            :: m, order_
     600              :       LOGICAL, DIMENSION(0:3)                            :: calc
     601              :       REAL(KIND=dp)                                      :: rho, tr, trr, trrr, trrz, trz, trzz, tz, &
     602              :                                                             tzz, tzzz
     603              :       REAL(KIND=dp), DIMENSION(0:3)                      :: e0, e1, f, r
     604              :       REAL(KIND=dp), DIMENSION(0:3, 0:3)                 :: z
     605              : 
     606       349312 :       calc = .FALSE.
     607              : 
     608       349312 :       order_ = 0
     609       349312 :       IF (PRESENT(order)) order_ = order
     610              : 
     611       349312 :       IF (order_ >= 0) THEN
     612       873280 :          calc(0:order_) = .TRUE.
     613              :       ELSE
     614            0 :          order_ = -1*order_
     615            0 :          calc(order_) = .TRUE.
     616              :       END IF
     617              : 
     618       349312 :       rho = a + b
     619              : 
     620       349312 :       CALL calc_fx(a, b, f(0:order_), order_)
     621       349312 :       CALL calc_rs(rho, r(0))
     622       349312 :       CALL calc_g(r(0), 0, e0(0:order_), order_)
     623       349312 :       CALL calc_g(r(0), 1, e1(0:order_), order_)
     624       349312 :       CALL calc_z(a, b, z(:, :), order_)
     625              : 
     626              : !! calculate first partial derivatives
     627       349312 :       IF (order_ >= 1) THEN
     628       174656 :          r(1) = (-1.0_dp/3.0_dp)*r(0)/rho
     629       174656 :          tr = e0(1) + (e1(1) - e0(1))*f(0)
     630       174656 :          tz = (e1(0) - e0(0))*f(1)
     631              :       END IF
     632              : 
     633              : !! calculate second partial derivatives
     634       349312 :       IF (order_ >= 2) THEN
     635            0 :          r(2) = (-4.0_dp/3.0_dp)*r(1)/rho
     636            0 :          trr = e0(2) + (e1(2) - e0(2))*f(0)
     637            0 :          trz = (e1(1) - e0(1))*f(1)
     638            0 :          tzz = (e1(0) - e0(0))*f(2)
     639              :       END IF
     640              : 
     641              : !! calculate third derivatives
     642       349312 :       IF (order_ >= 3) THEN
     643            0 :          r(3) = (-7.0_dp/3.0_dp)*r(2)/rho
     644            0 :          trrr = e0(3) + (e1(3) - e0(3))*f(0)
     645            0 :          trrz = (e1(2) - e0(2))*f(1)
     646            0 :          trzz = (e1(1) - e0(1))*f(2)
     647            0 :          tzzz = (e1(0) - e0(0))*f(3)
     648              :       END IF
     649              : 
     650       349312 :       m = 0
     651       349312 :       IF (calc(0)) THEN
     652       349312 :          ed(m) = e0(0) + (e1(0) - e0(0))*f(0)
     653       349312 :          ed(m) = ed(m)*sc
     654       349312 :          m = m + 1
     655              :       END IF
     656              : 
     657       349312 :       IF (calc(1)) THEN
     658       174656 :          ed(m) = tr*r(1) + tz*z(1, 0)
     659       174656 :          ed(m) = ed(m)*sc
     660       174656 :          ed(m + 1) = tr*r(1) + tz*z(0, 1)
     661       174656 :          ed(m + 1) = ed(m + 1)*sc
     662       174656 :          m = m + 2
     663              :       END IF
     664              : 
     665       349312 :       IF (calc(2)) THEN
     666              :          ed(m) = trr*r(1)**2 + 2.0_dp*trz*r(1)*z(1, 0) &
     667            0 :                  + tr*r(2) + tzz*z(1, 0)**2 + tz*z(2, 0)
     668            0 :          ed(m) = ed(m)*sc
     669              :          ed(m + 1) = trr*r(1)**2 + trz*r(1)*(z(0, 1) + z(1, 0)) &
     670            0 :                      + tr*r(2) + tzz*z(1, 0)*z(0, 1) + tz*z(1, 1)
     671            0 :          ed(m + 1) = ed(m + 1)*sc
     672              :          ed(m + 2) = trr*r(1)**2 + 2.0_dp*trz*r(1)*z(0, 1) &
     673            0 :                      + tr*r(2) + tzz*z(0, 1)**2 + tz*z(0, 2)
     674            0 :          ed(m + 2) = ed(m + 2)*sc
     675            0 :          m = m + 3
     676              :       END IF
     677              : 
     678       349312 :       IF (calc(3)) THEN
     679              :          ed(m) = trrr*r(1)**3 + 3.0_dp*trrz*r(1)**2*z(1, 0) &
     680              :                  + 3.0_dp*trr*r(1)*r(2) + 3.0_dp*trz*r(2)*z(1, 0) &
     681              :                  + tr*r(3) + 3.0_dp*trzz*r(1)*z(1, 0)**2 &
     682              :                  + tzzz*z(1, 0)**3 + 3.0_dp*trz*r(1)*z(2, 0) &
     683            0 :                  + 3.0_dp*tzz*z(1, 0)*z(2, 0) + tz*z(3, 0)
     684            0 :          ed(m) = ed(m)*sc
     685              :          ed(m + 1) = trrr*r(1)**3 + trrz*r(1)**2*(2.0_dp*z(1, 0) + z(0, 1)) &
     686              :                      + 2.0_dp*trzz*r(1)*z(1, 0)*z(0, 1) &
     687              :                      + 2.0_dp*trz*(r(2)*z(1, 0) + r(1)*z(1, 1)) &
     688              :                      + 3.0_dp*trr*r(2)*r(1) + trz*r(2)*z(0, 1) + tr*r(3) &
     689              :                      + trzz*r(1)*z(1, 0)**2 + tzzz*z(1, 0)**2*z(0, 1) &
     690              :                      + 2.0_dp*tzz*z(1, 0)*z(1, 1) &
     691            0 :                      + trz*r(1)*z(2, 0) + tzz*z(2, 0)*z(0, 1) + tz*z(2, 1)
     692            0 :          ed(m + 1) = ed(m + 1)*sc
     693              :          ed(m + 2) = trrr*r(1)**3 + trrz*r(1)**2*(2.0_dp*z(0, 1) + z(1, 0)) &
     694              :                      + 2.0_dp*trzz*r(1)*z(0, 1)*z(1, 0) &
     695              :                      + 2.0_dp*trz*(r(2)*z(0, 1) + r(1)*z(1, 1)) &
     696              :                      + 3.0_dp*trr*r(2)*r(1) + trz*r(2)*z(1, 0) + tr*r(3) &
     697              :                      + trzz*r(1)*z(0, 1)**2 + tzzz*z(0, 1)**2*z(1, 0) &
     698              :                      + 2.0_dp*tzz*z(0, 1)*z(1, 1) &
     699            0 :                      + trz*r(1)*z(0, 2) + tzz*z(0, 2)*z(1, 0) + tz*z(1, 2)
     700            0 :          ed(m + 2) = ed(m + 2)*sc
     701              :          ed(m + 3) = trrr*r(1)**3 + 3.0_dp*trrz*r(1)**2*z(0, 1) &
     702              :                      + 3.0_dp*trr*r(1)*r(2) + 3.0_dp*trz*r(2)*z(0, 1) + tr*r(3) &
     703              :                      + 3.0_dp*trzz*r(1)*z(0, 1)**2 + tzzz*z(0, 1)**3 &
     704              :                      + 3.0_dp*trz*r(1)*z(0, 2) &
     705            0 :                      + 3.0_dp*tzz*z(0, 1)*z(0, 2) + tz*z(0, 3)
     706            0 :          ed(m + 3) = ed(m + 3)*sc
     707              :       END IF
     708              : 
     709       349312 :    END SUBROUTINE pz_lsd_ed_loc
     710              : 
     711              : END MODULE xc_perdew_zunger
        

Generated by: LCOV version 2.0-1