LCOV - code coverage report
Current view: top level - src/xc - xc_perdew_zunger.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 160 236 67.8 %
Date: 2024-11-21 06:45:46 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.15