!
!=======================================================================
!
MODULE DFUNCL_STAN_DYNAMIC
!
      USE ACCURACY_REAL
      USE ACCURACY_INTEGER
      USE MINMAX_VALUES
!
!
CONTAINS
!
!
!=======================================================================
!
!    Standard Longitudinal Dielectric Functions i.e. with:
!
!                  * no external magnetic field
!
!=======================================================================
!
      SUBROUTINE DFUNCL_DYNAMIC(X,Z,RS,T,D_FUNCL,FLAG,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * D_FUNCL  : type of longitudinal dielectric function (3D)
!       * FLAG     : current index of the omega loop calling this subroutine
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE MATERIAL_PROP,    ONLY : DMN
      USE REAL_NUMBERS,     ONLY : ZERO,INF
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL
!
      REAL (WP)             ::  X,Z,RS,T
      REAL (WP)             ::  EPSR,EPSI
!
      INTEGER               ::  FLAG
!
      IF(DMN == '3D') THEN                                          !
        CALL DFUNCL_DYNAMIC_3D(X,Z,RS,T,D_FUNCL,FLAG,EPSR,EPSI)     !
      ELSE IF(DMN == '2D') THEN                                     !
        CALL DFUNCL_DYNAMIC_2D(X,Z,RS,T,D_FUNCL,EPSR,EPSI)          !
      ELSE IF(DMN == 'BL') THEN                                     !
        CALL DFUNCL_DYNAMIC_BL(X,Z,RS,T,D_FUNCL,EPSR,EPSI)          !
      ELSE IF(DMN == 'ML') THEN                                     !
        CALL DFUNCL_DYNAMIC_ML(X,Z,RS,T,D_FUNCL,EPSR,EPSI)          !
      ELSE IF(DMN == 'Q1') THEN                                     !
        CALL DFUNCL_DYNAMIC_Q1(X,Z,D_FUNCL,EPSR,EPSI)               !
      ELSE IF(DMN == '1D') THEN                                     !
        CALL DFUNCL_DYNAMIC_1D(X,Z,RS,T,D_FUNCL,EPSR,EPSI)          !
      END IF                                                        !
!
      END SUBROUTINE DFUNCL_DYNAMIC
!
!    1) 3D case
!
!=======================================================================
!
      SUBROUTINE DFUNCL_DYNAMIC_3D(X,Z,RS,T,D_FUNCL,FLAG,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions in 3D
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * V        : dimensionless factor   --> V = hbar * omega / E_F
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * D_FUNCL  : type of longitudinal dielectric function (3D)
!                      D_FUNCL = 'ARBR' Arista-Brandt 1                     <-- T-dependent
!                      D_FUNCL = 'ATAS' Atwal-Ashcroft                      <-- T-dependent
!                      D_FUNCL = 'BLZ1' Boltzmann
!                      D_FUNCL = 'BLZ2' damped Boltzmann
!                      D_FUNCL = 'DACA' Arista-Brandt 2                     <-- T-dependent
!                      D_FUNCL = 'GOTZ' Götze memory function
!                      D_FUNCL = 'HEAP' Hertel-Appel
!                      D_FUNCL = 'HAFO' Hartree-Fock
!                      D_FUNCL = 'HUCO' Hu-O'Connell                        <-- damping
!                      D_FUNCL = 'HYDR' hydrodynamic                        <-- damping
!                      D_FUNCL = 'KLEI' Kleinman                            <-- T-dependent
!                      D_FUNCL = 'KLKD' Klimontovich-Kraeft                 <-- T-dependent
!                      D_FUNCL = 'KLKN' Klimontovich-Kraeft                 <-- T-dependent
!                      D_FUNCL = 'LAND' Landau parameters-based
!                      D_FUNCL = 'LVL1' linearized Vlasov (weak coupling)   <-- T-dependent
!                      D_FUNCL = 'LVL2' linearized Vlasov (strong coupling) <-- T-dependent
!                      D_FUNCL = 'MEM2' Two-moment memory function          <-- T-dependent
!                      D_FUNCL = 'MEM3' Three-moment memory function        <-- T-dependent
!                      D_FUNCL = 'MEM4' Four-moment memory function         <-- T-dependent
!                      D_FUNCL = 'MER1' Mermin 1                            <-- damping
!                      D_FUNCL = 'MER2' Mermin 2                            <-- T-dependent
!                      D_FUNCL = 'MER+' Mermin with Local Field Corrections <-- damping
!                      D_FUNCL = 'MSAP' mean spherical approximation
!                      D_FUNCL = 'NEV2' Nevanlinna                          <-- T-dependent
!                      D_FUNCL = 'NEV3' Nevanlinna                          <-- T-dependent
!                      D_FUNCL = 'PLPO' plasmon pole
!                      D_FUNCL = 'RDF1' Altshuler et al                     <-- damping
!                      D_FUNCL = 'RDF2' Altshuler et al                     <-- damping
!                      D_FUNCL = 'RPA1' RPA
!                      D_FUNCL = 'RPA2' RPA                                 <-- T-dependent
!                      D_FUNCL = 'RPA+' RPA + static local field corrections
!                      D_FUNCL = 'UTIC' Utsumi-Ichimaru                     <-- T-dependent
!                      D_FUNCL = 'VLFP' Vlasov-Fokker-Planck                <-- damping
!       * FLAG     : current index of the omega loop calling this subroutine
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,            ONLY : ZERO,ONE,FOURTH
!
      USE LF_VALUES,               ONLY : LANDAU
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL
!
      REAL (WP)             ::  X,Z,RS,T
      REAL (WP)             ::  D                     ! dopant concentration
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  XC,U0,W
!
      INTEGER               ::  FLAG
!
!  Computing the dielectric function
!
      IF(D_FUNCL.EQ.'ARBR') THEN                                    !
        CALL ARBR_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'ATAS') THEN                               !
        CALL ATAS_EPS_D_LG_3D(X,Z,T,RS,FLAG,EPSR,EPSI)              !
      ELSE IF(D_FUNCL.EQ.'BLZ1') THEN                               !
        CALL BLZ1_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)                     !
      ELSE IF(D_FUNCL.EQ.'BLZ2') THEN                               !
        CALL BLZ2_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)                     !
      ELSE IF(D_FUNCL.EQ.'DACA') THEN                               !
        CALL DACA_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'GOTZ') THEN                               !
        CALL GOTZ_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'HEAP') THEN                               !
        CALL HEAP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'HAFO') THEN                               !
        CALL HAFO_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)                     !
      ELSE IF(D_FUNCL.EQ.'HUCO') THEN                               !
        CALL HUCO_EPS_D_LG_3D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'HYDR') THEN                               !
        CALL HYDR_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)                     !
      ELSE IF(D_FUNCL.EQ.'KLEI') THEN                               !
        CALL KLEI_EPS_D_LG_3D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'KLKD') THEN                               !
        CALL KLKD_EPS_D_LG_3D(X,Z,T,EPSR,EPSI)                      !
      ELSE IF(D_FUNCL.EQ.'KLKN') THEN                               !
        CALL KLKN_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'LAND') THEN                               !
        CALL LAND_EPS_D_LG_3D(X,Z,XC,U0,W,D,RS,LANDAU,EPSR,EPSI)    !
      ELSE IF(D_FUNCL.EQ.'LVL1') THEN                               !
        CALL LVL1_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'LVL2') THEN                               !
        CALL LVL2_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'MEM2') THEN                               !
        CALL MEM2_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'MEM3') THEN                               !
        CALL MEM3_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'MER1') THEN                               !
        CALL MER1_EPS_D_LG_3D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'MER2') THEN                               !
        CALL MER2_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'MER+') THEN                               !
        CALL MERP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'MSAP') THEN                               !
        CALL MSAP_EPS_D_LG_3D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'NEV2') THEN                               !
        CALL NEV2_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'NEV3') THEN                               !
        CALL NEV3_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'PLPO') THEN                               !
        CALL PLPO_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'RDF1') THEN                               !
        CALL RDF1_EPS_D_LG_3D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'RDF2') THEN                               !
        CALL RDF2_EPS_D_LG_3D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'RPA1') THEN                               !
        CALL RPA1_EPS_D_LG_3D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'RPA2') THEN                               !
        CALL RPA2_EPS_D_LG_3D(X,Z,T,EPSR,EPSI)                      !
      ELSE IF(D_FUNCL.EQ.'RPA+') THEN                               !
        CALL RPAP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'UTIC') THEN                               !
        CALL UTIC_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)                   !
      ELSE IF(D_FUNCL.EQ.'VLFP') THEN                               !
        CALL VLFP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)                   !
      END IF                                                        !
!
      END SUBROUTINE DFUNCL_DYNAMIC_3D
!
!=======================================================================
!
      SUBROUTINE ARBR_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)
!
!  This subroutine computes Arista-Brandt expression
!    for the longitudinal temperature-dependent
!    dielectric function EPS(q,omega,T) in 3D systems.
!
!  References: (1) N. R. Arista and W. Brandt, Phys. Rev. A 29,
!                     1471-1480 (1984)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature (SI)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified :  5 Nov 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,FOUR,&
                                     FOURTH,EIGHTH,SMALL,INF
      USE CONSTANTS_P1,       ONLY : BOHR,K_B
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PI_ETC,             ONLY : PI
!
      USE CHEMICAL_POTENTIAL, ONLY : MU_T
      USE SPECIFIC_INT_8
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  X2,X3,Y,U
      REAL (WP)              ::  KBT,D,THETA,ETA
      REAL (WP)              ::  CHI0_2
      REAL (WP)              ::  UPX,UMX
      REAL (WP)              ::  G_UPX,G_UMX
      REAL (WP)              ::  ENU,EDE,NUM,DEN
      REAL (WP)              ::  LN
      REAL (WP)              ::  MAX_EXP,MIN_EXP
!
      REAL (WP)              ::  ABS,EXP,LOG
!
!  Computing the max and min value of the exponent of e^x
!
!
      CALL MINMAX_EXP(MAX_EXP,MIN_EXP)                              !
!
      X2 = X  * X                                                   !
      X3 = X2 * X                                                   !
      Y  = X + X                                                    ! q / k_F
      U  = X * Z                                                    ! U = omega / (q v_F)
!
      KBT   = K_B * T                                               !
      THETA = KBT / EF_SI                                           ! 1 / degeneracy
      D     = ONE / THETA                                           ! degeneracy
      ETA   = MU_T('3D',T) / KBT                                    !
!
      CHI0_2 = ONE / (PI * KF_SI *  BOHR)                           ! ref. (1) eq. (4)
!
      UPX = U + X                                                   !
      UMX = U - X                                                   !
!
      IF(ABS(UMX) <= SMALL) UMX = 0.01E0_WP                         !
!
!  Computing the integrals involved in the real part
!
      CALL INT_ARB(UPX,D,ETA,G_UPX)                                 !
      CALL INT_ARB(UMX,D,ETA,G_UMX)                                 !
!
      EPSR = ONE + FOURTH * CHI0_2 * (G_UPX - G_UMX) / X3           ! ref. (1) eq. (7)
!
!  Computing the imaginary part
!
      ENU = ETA - D * (UMX)**2                                      ! exponent of numerator
      EDE = ETA - D * (UPX)**2                                      ! exponent of denominator
!
!  Numerator of Log
!
      IF(ENU >= ZERO) THEN                                          !
        IF(ENU < MAX_EXP) THEN                                      !
          NUM = ONE + EXP(ENU)                                      !
        ELSE                                                        !
          NUM = INF                                                 !
        END IF                                                      !
      ELSE                                                          !
        IF(ENU > MIN_EXP) THEN                                      !
          NUM = ONE + EXP(ENU)                                      !
        ELSE                                                        !
          NUM = ONE                                                 !
        END IF                                                      !
      END IF                                                        !
!
!  Denominator  of Log
!
      IF(EDE >= ZERO) THEN                                          !
        IF(EDE < MAX_EXP) THEN                                      !
          DEN = ONE + EXP(EDE)                                      !
        ELSE                                                        !
          DEN = INF                                                 !
        END IF                                                      !
      ELSE                                                          !
        IF(EDE > MIN_EXP) THEN                                      !
          DEN = ONE + EXP(EDE)                                      !
        ELSE                                                        !
          DEN = ONE                                                 !
        END IF                                                      !
      END IF                                                        !
!
!  Computing the Log
!
      IF(ENU /= INF .AND. EDE /= INF) THEN                          !
        LN = LOG(NUM/DEN)                                           !
      ELSE IF(ENU /= INF .AND. EDE == INF) THEN                     !
        LN =   LOG( EXP(- EDE) + EXP(ENU - EDE) )                   !
      ELSE IF(ENU == INF .AND. EDE /= INF) THEN                     !
        LN = - LOG( EXP(- ENU) + EXP(EDE - ENU) )                   !
      ELSE IF(ENU == INF .AND. EDE == INF) THEN                     !
        LN = ENU - EDE                                              !
      END IF                                                        !
!
      EPSI = EIGHTH * PI * CHI0_2 * THETA * LN  / X3                ! ref. (1) eq. (23)
!
      END SUBROUTINE ARBR_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE ATAS_EPS_D_LG_3D(X,Z,T,RS,FLAG,EPSR,EPSI)
!
!  This subroutine computes Arkhipov et al parametrization
!    for the longitudinal temperature-dependent Atwal-Ashcroft
!    dielectric function EPS(q,omega,T) in 3D systems.
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 90, 053102 (2014)
!              (2) G. S. Atwal and N. W. Ashcroft, Phys. Rev. B 65, 115109 (2002)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * T        : temperature (SI)
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * FLAG     : current index of the omega loop calling this subroutine
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!  Warning: the subroutine is suppose to be called in a omega-loop
!           starting from omega ~ zero. During the first run of
!           the subroutine, it will store Pi_mu(q,omega=0) for further use
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,THREE,FOUR,  &
                                     HALF,FOURTH
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E,E,EPS_0,K_B
      USE FERMI_SI,           ONLY : EF_SI,KF_SI,VF_SI
      USE UTILITIES_1,        ONLY : RS_TO_N0
      USE EXT_FUNCTIONS,      ONLY : FDP1P5
      USE CHEMICAL_POTENTIAL, ONLY : MU
      USE COULOMB_K,          ONLY : COULOMB_FF
!
      USE UNITS,              ONLY : UNIT
!
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,T,RS,U,GM
      REAL (WP)             ::  D,NU,ITA,VC
      REAL (WP)             ::  Q_SI
      REAL (WP)             ::  K0,K2,K4,N0,XSI,OM
      REAL (WP)             ::  EPSR,EPSI
!
      REAL (WP)             ::  DREAL,DIMAG
!
      COMPLEX (WP)          ::  S1,S2,W
      COMPLEX (WP)          ::  G11,G12,G31,G32,G51,G52
      COMPLEX (WP)          ::  PP0,PP2,PP4
      COMPLEX (WP)          ::  PI0Q,PI2Q,PI4Q
      COMPLEX (WP)          ::  B0,B2,B4,D2,D4
      COMPLEX (WP)          ::  EQO,FQO
!
      INTEGER               ::  FLAG
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
!
      CALL COULOMB_FF('3D',UNIT,Q_SI,ZERO,VC)                       ! Coulomb pot.
!
      NU  = ONE / TAU                                               ! collision freq.
      U   = X * Z                                                   ! omega / (q * v_F)
      GM  = NU / (Q_SI * VF_SI)                                     ! gamma
      D   = EF_SI / (K_B*T)                                         !
      ITA = MU('3D',T) / (K_B*T)                                    !
!
!  Computing the electron density
!
      N0 = RS_TO_N0('3D',RS)                                        !
!
      S1 = U + X + IC * GM                                          ! sigma_1
      S2 = U - X + IC * GM                                          ! sigma_2
!
      OM  = Z * H_BAR * Q_SI * Q_SI * HALF / M_E                    ! omega in SI
      XSI = OM * NU * M_E / (N0 * Q_SI  *Q_SI)                      !
      W   = OM + IC * NU                                            !
!
!  Computing the G_l(sigma) functions
!
      G11 = G1(S1,D,ITA)                                            !
      G12 = G1(S2,D,ITA)                                            !
      G31 = G3(S1,D,ITA)                                            ! ref. 1 eq. (40)
      G32 = G3(S2,D,ITA)                                            !
      G51 = G5(S1,D,ITA)                                            !
      G52 = G5(S2,D,ITA)                                            !
!
!  Computing the polarization operators PPx
!
      K0 = THREE * M_E * N0 / (FOUR*X*H_BAR*H_BAR*KF_SI*KF_SI)      !
      K2 = M_E * N0 / (H_BAR * H_BAR)                               !
      K4 = M_E * N0 * KF_SI * KF_SI / (H_BAR * H_BAR)               !
!
      PP0 = K0 * (G11 - G12)                                        ! ref. 1 eq. (37)
!
      PP2=K2*( FOURTH*(TWO+THREE*X*(G11-G12))   -                 & !
               HALF*(THREE*(S1*G11+S2*G12))    +                  & ! ref. 1 eq. (38)
               FOURTH*(THREE*(G31-G32)/X)                         & !
             )                                                      !
!
      PP4 = K4*( TWO*(THREE*FDP1P5(ITA) / D**2.5E0_WP - TWO*X*U)+ & !
               THREE*FOURTH*(G51-G52)/X                         + & !
               THREE*HALF*(THREE*X*(G31-G32))                   - & !
               THREE*(S1*G31+S2*G32)                            + & ! ref. 1 eq. (39)
               THREE*FOURTH*X*X*X*(G11-G12)                     - & !
               THREE*X*(S1*S1*G11-S2*S2*G12)                    - & !
               THREE*X*X*(S1*G11+S2*G12)                          & !
             )                                                      !
!
!  Computing the coefficients Bs and Ds
!
      IF(FLAG == 1) THEN                                            !
        PI0Q = PP0                                                  !
        PI2Q = PP2                                                  !
        PI4Q = PP4                                                  !
      END IF                                                        !
!
      B0 = - PI0Q                                                   !
      B2 = - PI2Q                                                   !
      B4 = - PI4Q                                                   !
      D2 = (IC * NU * PI2Q - OM * B2) / W                           !
      D4 = (IC * NU * PI4Q - OM * B4) / W                           !
!
!  Computing the functions E(q,omega) and F(q,omega)
!
      EQO = - IC*NU*PP2*( (PP2*B0-PP0*B2)/(D4*B0-B2*D2) )/OM        !
      FQO =   IC*NU*( (D2*PP2-D4*PP0-IC*XSI*PP2*(PP2*B0-PP0*B2)) /& !
                  (D4*B0-B2*D2)  - ONE                            & !
                    ) / OM + IC*XSI*PP0                             !
!
!  Computing the dielectric function
!
      EPSR = ONE + VC *  REAL( (PP0 + EQO) / (ONE + FQO) )          !
      EPSI =       VC * AIMAG( (PP0 + EQO) / (ONE + FQO) )          !
!
      END SUBROUTINE ATAS_EPS_D_LG_3D
!
!=======================================================================
!
      FUNCTION G1(S,D,ETA)
!
!  This function computes Arkhipov et al G1 function
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 90, 053102 (2014)
!
!  Input parameters:
!
!       * S        : sigma
!       * D        : D
!       * ETA      : eta
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE DIMENSION_CODE,     ONLY : NZ_MAX
      USE REAL_NUMBERS,       ONLY : ONE,TWO
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE INTEGRATION,        ONLY : INTEGR_L
!
      IMPLICIT NONE
!
      REAL (WP)             ::  D,ETA
      REAL (WP)             ::  Y,Y_MAX,Y1
      REAL (WP)             ::  F(NZ_MAX),G(NZ_MAX)
      REAL (WP)             ::  SR,SI,A,B,RLN,ILN,RIN,IIN
      REAL (WP)             ::  H
!
      REAL (WP)             ::  FLOAT,REAL,AIMAG,LOG
      REAL (WP)             ::  SQRT,ATAN,EXP
!
      COMPLEX (WP)          ::  G1,S
!
      INTEGER               ::  J,ID
!
      Y_MAX = 100.0E0_WP                                            ! max of y
      H     = Y_MAX / FLOAT(NZ_MAX - 1)                             ! y-step
      ID    = 1                                                     !
!
!  Setting up the grid Y and the integrand functions
!                  F(I) and G(I)
!
!    F(I) : real part of integrand
!    G(I) : imaginary part of integrand
!
!  Here, we make use of the fact that, if z = a + i b
!
!      Ln(z) = ln|z| + r atan(b/a)
!
!  Notation:  SR = Re [ sigma ]
!             SI = Im [ sigma ]
!             A  = Re[ (sigma + y)/(sigma-y) ]
!             B  = Im[ (sigma + y)/(sigma-y) ]
!
      DO J = 1, NZ_MAX                                              !
!
        Y    = FLOAT(J - 1) * Y_MAX / FLOAT(NZ_MAX - 1)             !
        Y1   = Y                                                    !
        SR   = REAL(S)                                              !
        SI   = AIMAG(S)                                             !
        A    = (SR*SR + SI*SI - Y*Y) / ((SR-Y) * (SR-Y) + SI*SI)    !
        B    = - TWO * SI * Y                                       !
        RLN  = LOG( SQRT(A * A + B * B) )                           !
        ILN  = ATAN(B / A)                                          !
        F(J) = Y1 * RLN / (EXP(D * Y * Y - ETA) + ONE)              !
        G(J) = Y1 * ILN / (EXP(D * Y * Y - ETA) + ONE)              !
!
      END DO                                                        !
!
!  Performing the integrations
!
      CALL INTEGR_L(F,H,NZ_MAX,NZ_MAX,RIN,ID)                       !
      CALL INTEGR_L(G,H,NZ_MAX,NZ_MAX,IIN,ID)                       !
!
      G1 = RIN + IC  *IIN                                           !
!
      END FUNCTION G1
!
!=======================================================================
!
      FUNCTION G3(S,D,ETA)
!
!  This function computes Arkhipov et al G3 function
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 90, 053102 (2014)
!
!  Input parameters:
!
!       * S        : sigma
!       * D        : D
!       * ETA      : eta
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE DIMENSION_CODE,     ONLY : NZ_MAX
      USE REAL_NUMBERS,       ONLY : ONE,TWO
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE INTEGRATION,        ONLY : INTEGR_L
!
      IMPLICIT NONE
!
      REAL (WP)             ::  D,ETA
      REAL (WP)             ::  Y,Y_MAX,Y3
      REAL (WP)             ::  F(NZ_MAX),G(NZ_MAX)
      REAL (WP)             ::  SR,SI,A,B,RLN,ILN,RIN,IIN
      REAL (WP)             ::  H
!
      REAL (WP)             ::  FLOAT,REAL,AIMAG,LOG
      REAL (WP)             ::  SQRT,ATAN,EXP
!
      COMPLEX (WP)          ::  G3,S
!
      INTEGER               ::  J,ID
!
      Y_MAX = 100.0E0_WP                                            ! max of y
      H     = Y_MAX / FLOAT(NZ_MAX - 1)                             ! y-step
      ID    = 1                                                     !
!
!  Setting up the grid Y and the integrand functions
!                  F(I) and G(I)
!
!    F(I) : real part of integrand
!    G(I) : imaginary part of integrand
!
!  Here, we make use of the fact that, if z = a + i b
!
!      Ln(z) = ln|z| + r atan(b/a)
!
!  Notation:  SR = Re [ sigma ]
!             SI = Im [ sigma ]
!             A  = Re[ (sigma + y)/(sigma-y) ]
!             B  = Im[ (sigma + y)/(sigma-y) ]
!
      DO J = 1, NZ_MAX                                              !
!
        Y    = FLOAT(J - 1) * Y_MAX / FLOAT(NZ_MAX - 1)             !
        Y3   = Y * Y * Y                                            !
        SR   = REAL(S)                                              !
        SI   = AIMAG(S)                                             !
        A    = (SR*SR + SI*SI - Y*Y) / ((SR-Y) * (SR-Y) + SI*SI)    !
        B    = - TWO * SI * Y                                       !
        RLN  = LOG( SQRT(A * A + B * B) )                           !
        ILN  = ATAN(B / A)                                          !
        F(J) = Y3 *RLN /(EXP(D * Y * Y - ETA) + ONE)                !
        G(J) = Y3 *ILN /(EXP(D * Y * Y - ETA) + ONE)                !
!
      END DO                                                        !
!
!  Performing the integrations
!
      CALL INTEGR_L(F,H,NZ_MAX,NZ_MAX,RIN,ID)                       !
      CALL INTEGR_L(G,H,NZ_MAX,NZ_MAX,IIN,ID)                       !
!
      G3 = RIN + IC * IIN                                           !
!
      END FUNCTION G3
!
!=======================================================================
!
      FUNCTION G5(S,D,ETA)
!
!  This function computes Arkhipov et al G5 function
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 90, 053102 (2014)
!
!  Input parameters:
!
!       * S        : sigma
!       * D        : D
!       * ETA      : eta
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Mar 2020
!
!
      USE DIMENSION_CODE,     ONLY : NZ_MAX
      USE REAL_NUMBERS,       ONLY : ONE,TWO
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE INTEGRATION,        ONLY : INTEGR_L
!
      IMPLICIT NONE
!
      REAL (WP)             ::  D,ETA
      REAL (WP)             ::  Y,Y_MAX,Y5
      REAL (WP)             ::  F(NZ_MAX),G(NZ_MAX)
      REAL (WP)             ::  SR,SI,A,B,RLN,ILN,RIN,IIN
      REAL (WP)             ::  H
!
      REAL (WP)             ::  FLOAT,REAL,AIMAG,LOG
      REAL (WP)             ::  SQRT,ATAN,EXP
!
      COMPLEX (WP)          ::  G5,S
!
      INTEGER               ::  J,ID
!
      Y_MAX = 100.0E0_WP                                            ! max of y
      H     = Y_MAX / FLOAT(NZ_MAX - 1)                             ! y-step
      ID    = 1                                                     !
!
!  Setting up the grid Y and the integrand functions
!                  F(I) and G(I)
!
!    F(I) : real part of integrand
!    G(I) : imaginary part of integrand
!
!  Here, we make use of the fact that, if z = a + i b
!
!      Ln(z) = ln|z| + r atan(b/a)
!
!  Notation:  SR = Re [ sigma ]
!             SI = Im [ sigma ]
!             A  = Re[ (sigma + y)/(sigma-y) ]
!             B  = Im[ (sigma + y)/(sigma-y) ]
!
      DO J=1,NZ_MAX                                                 !
!
        Y    = FLOAT(J - 1) * Y_MAX / FLOAT(NZ_MAX - 1)             !
        Y5   = Y * Y * Y * Y * Y                                    !
        SR   = REAL(S)                                              !
        SI   = AIMAG(S)                                             !
        A    = (SR*SR + SI*SI - Y*Y) / ((SR-Y)*(SR-Y) + SI*SI)      !
        B    = - TWO * SI * Y                                       !
        RLN  = LOG( SQRT(A * A + B * B) )                           !
        ILN  = ATAN(B / A)                                          !
        F(J) = Y5 * RLN /(EXP(D * Y * Y - ETA) + ONE)               !
        G(J) = Y5 * ILN /(EXP(D * Y * Y - ETA) + ONE)               !

      END DO                                                        !
!
!  Performing the integrations
!
      CALL INTEGR_L(F,H,NZ_MAX,NZ_MAX,RIN,ID)                       !
      CALL INTEGR_L(G,H,NZ_MAX,NZ_MAX,IIN,ID)                       !
!
      G5 = RIN + IC * IIN                                           !
!
      END FUNCTION G5
!
!=======================================================================
!
      SUBROUTINE BLZ1_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Boltzmann dynamical
!     dielectric function in 3D
!
!  References: (1) P. Halevi, Phys. Rev. B 51, 7497-7499 (1995)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified :  6 Nov 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,THREE,FOUR,  &
                                     HALF
      USE FERMI_SI,           ONLY : EF_SI
      USE PLASMON_ENE_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)              ::  U,U2,V
      REAL (WP)              ::  COEF,ENE2
!
      REAL (WP)              ::  LOG
!
      U  = X * Z                                                    ! omega / (q * v_F)
      V  = FOUR * U * X                                             ! omega / omega_F
      U2 = U * U                                                    !
!
      ENE2 = (V * EF_SI)**2                                         ! (h_bar omega)^2
      COEF = THREE * U * ENE_P_SI * ENE_P_SI / ENE2                 !
!
      EPSR = ONE + COEF * ( U + HALF * U2 * LOG(                  & !
                                ABS((U - ONE) / (U + ONE))        & !
                                               )                  & !
                          )                                         !
      EPSI = ZERO                                                   !
!
      END SUBROUTINE BLZ1_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE BLZ2_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Boltzmann dynamical
!     dielectric function in 3D
!
!  References: (1) R. Esquivel and V. B. Stetovoy, Phys. Rev. A 69, 062102 (2004)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,THREE,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE PLASMON_ENE_SI
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)              ::  U
      REAL (WP)              ::  Q_SI,O_SI
      REAL (WP)              ::  OMP,OMT
      REAL (WP)              ::  RAT
!
      REAL (WP)              ::  REAL,AIMAG
!
      COMPLEX (WP)           ::  UU,U3,COEF
      COMPLEX (WP)           ::  KK,NUM,DEN
      COMPLEX (WP)           ::  LLOG,FL
!
      U = X * Z                                                     ! omega / (q * v_F)
!
      Q_SI = TWO * X * KF_SI                                        ! q     in SI
      O_SI = U * Q_SI * VF_SI                                       ! omega in SI
      OMP  = ENE_P_SI / H_BAR                                       ! omega_p
      OMT  = ONE / TAU                                              ! omega_tau
      RAT  = OMT / O_SI                                             ! omega_tau / omega
!
      UU = Q_SI * VF_SI / (O_SI + IC * OMT)                         ! ref. (1) eq. (16)
      U3 = UU * UU * UU                                             !
!
      COEF = OMP * OMP / (O_SI * O_SI + IC * O_SI * OMT)            !
      LLOG = LOG((ONE + UU) / (ONE - UU))                           !
      KK   = THREE / U3                                             !
      NUM  = - UU + HALF * LLOG                                     !
      DEN  = ONE + IC * RAT * (ONE - HALF * LLOG / UU)              !
!
      FL = KK * NUM / DEN                                           ! ref. (1) eq. (15)
!
      EPSR = ONE - REAL(COEF * FL, KIND=WP)                         !
      EPSI = AIMAG(COEF * FL)                                       !
!
      END SUBROUTINE BLZ2_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE DACA_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes Dandrea-Ashcroft-Carlsson parametrization
!    for the longitudinal temperature-dependent Arista-Brandt
!    dielectric function EPS(q,omega,T) for 3D systems.
!
!  References: (1) R. G. Dandrea, N. W. Ashcroft and A. E. Carlsson,
!                     Phys. Rev. B 34, 2097-2111 (1986)
!              (2) N. R. Arista and W. Brandt, Phys. Rev. A 29,
!                     1471-1480 (1984)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature (SI)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 21 Jul 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,FOUR,HALF,THIRD,FOURTH
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : K_B
      USE FERMI_SI,           ONLY : EF_SI
      USE PI_ETC,             ONLY : PI_INV,SQR_PI
      USE UTILITIES_1,        ONLY : ALFA
      USE LF_VALUES,          ONLY : GQ_TYPE
      USE LOCAL_FIELD_STATIC
      USE PHI_FUNCTION
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,RS,T,U
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  ETA0,THETA,ALPHA
      REAL (WP)             ::  F10,F20,U1,U2,COEF,NUM,DEN
      REAL (WP)             ::  GQ
!
      REAL (WP)             ::  DLOG,DEXP,DREAL,DIMAG
!
      COMPLEX (WP)          ::  EPS
!
      U=X*Z                                                         ! omega / (q * v_F)
!
      THETA=K_B*T/EF_SI                                             !
      ALPHA=ALFA('3D')                                              !
      COEF=FOURTH*ALPHA*RS/(X*X*X)                                  !
!
      IF(THETA < ONE) THEN                                          !
        ETA0=EF_SI/(K_B*T)                                          !   ref. (2) eq. (A4')
      ELSE
        ETA0=DLOG(FOUR*THIRD/(SQR_PI * THETA**1.5E0_WP))            !   ref. (2) eq. (A5')
      END IF                                                        !
!
      U1=U+X                                                        !
      U2=U-X                                                        !
!
      F10=COEF*PI_INV*(PHI(U1,THETA)-PHI(U2,THETA))                 ! ref. (1) eq. (4.6)
!
      NUM=ONE+DEXP(ETA0 - U2*U2/THETA)                              !
      DEN=ONE+DEXP(ETA0 - U1*U1/THETA)                              !
      F20=-HALF*COEF*THETA*DLOG(NUM/DEN)                            ! ref. (1) eq. (4.7)
!
!  Calling the local-field correction
!
      CALL LOCAL_FIELD_STATIC_3D(X,RS,T,GQ_TYPE,GQ)                 !
!
      EPS=(ONE-F10-IC*F20)/(ONE+GQ*F10+IC*GQ*F20)                   !
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END SUBROUTINE DACA_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE GOTZ_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)
!
!  This subroutine computes the Götze memory function approach,
!    which can be considered as a generalization of the Mermin's
!    dielectric function.
!
!  References: (1) F. Yoshida and S. Takeno, Phys. Rep. 173,
!                     301-381 (1989)
!              (2) H. B. Nersiyan and A. K. Das, Phys. Rev. E 69,
!                     046404 (2004)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * T        : temperature (SI)
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!       * V        : dimensionless factor   --> V = h_bar omega / E_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  Note:  We use the eq. (10) of ref. (2): V_C chi = - COEF1 * V_C * (f_1 + i f_2)
!           to obtain CHI_ = - COEF1 * (f_1 + i f_2)
!
!         Then, the exact CHI is obtained from ref. (1):
!                     CHI = COEF2 * CHI_
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE MATERIAL_PROP,          ONLY : DMN
      USE UNITS,                  ONLY : UNIT
!
      USE REAL_NUMBERS,           ONLY : ZERO,ONE,TWO,FOUR,EIGHT,HALF
      USE COMPLEX_NUMBERS,        ONLY : ONEC,IC
      USE PI_ETC,                 ONLY : PI,PI_INV
      USE CONSTANTS_P1,           ONLY : BOHR,H_BAR
      USE FERMI_SI,               ONLY : EF_SI,KF_SI
      USE COULOMB_K,              ONLY : COULOMB_FF
!
      USE UNITS,                  ONLY : UNIT
!
      USE DF_VALUES,              ONLY : MEM_TYPE,ALPHA,BETA
      USE LF_VALUES,              ONLY : GQ_TYPE
!
      USE DFUNC_STATIC,           ONLY : RPA1_EPS_S_LG
      USE LOCAL_FIELD_STATIC
      USE DAMPING_SI
      USE DAMPING_VALUES,         ONLY : PCT
      USE MEMORY_FUNCTIONS_F
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,T,RS
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  EPS0R,EPS0I
      REAL (WP)              ::  GQ,CHI_0,CHI_Q
      REAL (WP)              ::  NUM,DEN
      REAL (WP)              ::  COEF1,COEF2
      REAL (WP)              ::  Q_SI,VC,CHI2
      REAL (WP)              ::  U,V,X2,X3
      REAL (WP)              ::  MEM
      REAL (WP)              ::  GAMMA,GAMMA2
      REAL (WP)              ::  UP,UM,UP2,UM2
      REAL (WP)              ::  Y1P,Y2P,Y1M,Y2M
      REAL (WP)              ::  F1,F2
      REAL (WP)              ::  REPSM1,IEPSM1
      REAL (WP)              ::  REPS00
!
      REAL (WP)              ::  LOG,ATAN,REAL,AIMAG
!
      COMPLEX (WP)           ::  NUMI,DENI
      COMPLEX (WP)           ::  CHI,EPS
      COMPLEX (WP)           ::  MEMO
!
      X2 = X *  X                                                   !
      X3 = X2 * X                                                   !
!
      U      = X * Z                                                ! omega / (q * v_F)
      V      = FOUR * U * X                                         ! h_bar omega / E_F
      CHI2   = PI_INV / (KF_SI * BOHR)                              !
      COEF1  = CHI2 / X2                                            !
!
!  Computation of the coefficient chi(0) / chi_0(0)
!
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
!
!  Computing the Coulomb potential VC
!
      CALL COULOMB_FF(DMN,UNIT,Q_SI,ZERO,VC)                        ! Coulomb pot.
!
!  Computing the static dielectric function and
!    the static local field correction
!
      CALL RPA1_EPS_S_LG(X,'3D',EPS0R,EPS0I)
      CALL LFIELD_STATIC(X,RS,T,GQ_TYPE,GQ)                         !
!
      CHI_0 = (ONE - EPS0R) / VC                                    !
!
      NUM   = CHI_0                                                 !
      DEN   = ONE + VC * (GQ - ONE) * CHI_0                         !
      CHI_Q = NUM / DEN                                             !
!
      COEF2 = CHI_Q / CHI_0                                         !
      coef2 = one
!
!  Computation of the memory function
!
      MEMO = MEMORY_F(V,TAU,TAU2,PCT,ALPHA,BETA,MEM_TYPE)           !
      MEM  = TWO * PI *  REAL(MEMO,KIND=WP)                         !
!
      GAMMA  = H_BAR * MEM / (FOUR * EF_SI)                         !
      GAMMA2 = GAMMA * GAMMA                                        !
!
      UP = U + X                                                    ! U_+
      UM = U - X                                                    ! U_-
!
      UP2 = UP * UP                                                 !
      UM2 = UM * UM                                                 !
!
      NUM = X2 * (UP + ONE) * (UP + ONE) + GAMMA2                   !
      DEN = X2 * (UP - ONE) * (UP - ONE) + GAMMA2                   ! ref. (2) eq. (13)
      Y1P = LOG(NUM / DEN)                                          ! Y_1(z,U_+)
!
      NUM = X2 * (UM + ONE) * (UM + ONE) + GAMMA2                   !
      DEN = X2 * (UM - ONE) * (UM - ONE) + GAMMA2                   ! ref. (2) eq. (13)
      Y1M = LOG(NUM / DEN)                                          ! Y_1(z,U_-)
!
      Y2P = ATAN(X * (UP - ONE) / GAMMA) -                        & ! ref. (2) eq. (14)
            ATAN(X * (UP + ONE) / GAMMA)                            ! Y_2(z,U_+)
      Y2M = ATAN(X * (UM - ONE) / GAMMA) -                        & ! ref. (2) eq. (14)
            ATAN(X * (UM + ONE) / GAMMA)                            ! Y_2(z,U_-)
!
      F1 = HALF + ONE / (16.0E0_WP * X3) * (                       &!
                                       ( X2 * (UM2 - ONE) - GAMMA2 &!
                                       ) * Y1M -                   &!
                                       ( X2 * (UP2 - ONE) - GAMMA2 &! ref. (2) eq. (11)
                                       ) * Y1P +                   &!
                                         FOUR * GAMMA * X *        &!
                                         (UP * Y2P - UM * Y2M)     &!
                                           )                        !
!
      F2 = ONE / (EIGHT * X3) * (                                  &!
                        GAMMA * X * (UM * Y1M - UP * Y1P) +        &!
                        X2 * ((UM2 - ONE) - GAMMA2) * Y2M -        &! ref. (2) eq. (12)
                        X2 * ((UP2 - ONE) - GAMMA2) * Y2P          &!
                                )                                   !
!
! Computation of EPS_{RPA}(x,u,Gamma) - 1
!
      REPSM1 = COEF1 * F1                                           ! ref. (2) eq. (10)
      IEPSM1 = COEF1 * F2                                           !
!
! Computation of EPS_{RPA}(x,0) - 1
!
      CALL RPA1_EPS_S_LG(X,'3D',EPS0R,EPS0I)
!
      REPS00 = EPS0R - ONE                                          !
!
      NUMI = (X * U + IC * GAMMA) * (REPSM1 + IC * IEPSM1)          !
      DENI =  X * U + IC * GAMMA  * (REPSM1 + IC * IEPSM1) / REPS00 !
!
      CHI = - COEF2 * NUMI / DENI                                   ! ref. (1) eq. (2.124)
!
      EPS = ONEC / (ONEC + VC * CHI)                                !
      EPS = ONE + NUMI / DENI                                       ! ref. (1) eq. (9)
!
      EPSR = REAL(EPS,KIND=WP)                                      !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE GOTZ_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE HEAP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Hertel-Appel dynamical
!     dielectric function in 3D
!
!  References: (1) P. Hertel and J. Appel, Phys. Rev. B 26, 5730-5742 (1982)
!
!  Note: for TAU --> infinity, we should recover the RPA values
!
!  Remark: In order to simplify the equation, we introduce
!          the quantities q_T and omega_T so that
!
!              k_B T = h_bar^2 q_T^2 / 2m = h_bar omega_T
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature (SI)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,HALF,FOURTH,TTINY
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E,E,K_B,EPS_0
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE PI_ETC,             ONLY : PI,SQR_PI
      USE MATERIAL_PROP,      ONLY : MSOM,EPS_B
      USE PLASMON_ENE_SI
      USE UTILITIES_1,        ONLY : RS_TO_N0
      USE EXT_FUNCTIONS,      ONLY : WOFZ
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)              ::  U,KBT,QT
      REAL (WP)              ::  A,C
      REAL (WP)              ::  Q_SI,OM_P,OM_Q,OM_T,OME,TOM
      REAL (WP)              ::  XR1,XR2,XI1,BR1,BI1,BR2,BI2
      REAL (WP)              ::  MASS_E
!
      REAL (WP)              ::  SQRT,REAL,AIMAG
!
      LOGICAL                ::  FLAG
!
      COMPLEX (WP)           ::  BQOT,BQ0I,Z12,Z22
      COMPLEX (WP)           ::  NUM,DEN,EPS
!
      U = X * Z                                                     ! omega / (q * v_F)
!
      MASS_E = M_E * MSOM                                           ! effective mass
      KBT    = K_B * T                                              !
!
      Q_SI = TWO * X * KF_SI                                        ! q  in SI
      QT     = SQRT(TWO * MASS_E * KBT) / H_BAR                     !
!
      OM_P = ENE_P_SI / H_BAR                                       ! omega_p
      OM_Q = HALF * H_BAR * Q_SI * Q_SI / MASS_E                    ! omega_q
      OM_T = HALF * H_BAR * QT   * QT   / MASS_E                    ! omega_T
!
      OME = U * Q_SI * VF_SI                                        ! omega
      TOM = TAU * OME                                               ! tau * omega
!
      KBT    = K_B * T                                              !
!
      C = FOURTH * OM_P * OM_P / (OM_Q * OM_T * SQR_PI)             ! see notes
!
      XR1 = (U + X) * KF_SI / QT                                    ! \
      XR2 = (U - X) * KF_SI / QT                                    !  > see notes
      XI1 = MASS_E / (H_BAR * Q_SI * QT * TAU)                      ! /
!
! Computing B(q,omega,tau)
!
!  Calling Faddeeva function W(z) = exp(-z^2) * [ 1 - erf(-iz) ]
!
!  Here, from ref. (1) eq. (28): w(z) = exp(-z^2) - W(z)
!
      CALL WOFZ(XR1,XI1,BR1,BI1,FLAG)                               !
      CALL WOFZ(XR2,XI1,BR2,BI2,FLAG)                               !
!
      Z12 = (XR1 + IC * XI1) * (XR1 + IC * XI1)                     !
      Z22 = (XR2 + IC * XI1) * (XR2 + IC * XI1)                     !
!
!  w(z1) - w(z2) = W(z2) - W(z1) + exp(-z1^2) - exp(-z2^2)
!
!
      BQOT = - IC * PI * C * ( BR2 + IC * BI2 - BR1 - IC * BR1 +  & ! ref. (1) eq. (27)
                               EXP(- Z12) - EXP(- Z22) )            !
!
!  Computing B(q,0,inf)
!
      XR1 = X * KF_SI / QT
      XR2 = - XR1
      XI1 = ZERO
!
      CALL WOFZ(XR1,XI1,BR1,BI1,FLAG)                               !
      CALL WOFZ(XR2,XI1,BR2,BI2,FLAG)                               !
!
      Z12 = (XR1 + IC * XI1) * (XR1 + IC * XI1)                     ! z1^2
      Z22 = (XR2 + IC * XI1) * (XR2 + IC * XI1)                     ! z2^2
!
!  w(z1) - w(z2) = W(z2) - W(z1) + exp(-z1^2) - exp(-z2^2)
!
      BQ0I = - IC * PI * C * ( BR2 + IC * BI2 - BR1 - IC * BR1 +  & ! ref. (1) eq. (27)
                               EXP(- Z12) - EXP(- Z22) )            !
!
      NUM = (ONE + IC / TOM) * BQOT                                 !
      DEN = ONE + IC * BQOT / (TOM * BQ0I)                          !
!
      EPS = ONE + NUM / DEN                                         ! ref. (1) eq. (21)
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE HEAP_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE HAFO_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    Hartree-Fock dielectric function
!
!  References: (1) V. D. Gorobchenko, V. N. Kohn and E. G. Maksimov,
!                    in "Modern Problems in Condensed Matter" Vol. 24,
!                    L. V. Keldysh, D. A. Kirzhnitz and A. A. Maradudin ed.
!                    pp. 87-219 (North-Holland, 1989)
!
!  Notation: hbar omega_q = hbar^2 q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  Note: in ref. (1), omega is in unit of E_F/h_bar and q in unit of k_F
!
!        Therefore: omega/q in ref. (1) is given in SI by 2 * omega / (q * v_F)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE PI_ETC,             ONLY : PI_INV
      USE UTILITIES_1,        ONLY : ALFA
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Y,Z,RS,Y2,U
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q0R,Q0I,ALPHA,Z1,Z2
      REAL (WP)             ::  COEF,LN1,LN2
!
      REAL (WP)             ::  DLOG,DABS,DREAL,DIMAG
!
      COMPLEX (WP)          ::  EPS
!
      ALPHA=ALFA('3D')                                              !
!
      Y=X+X                                                         ! Y = q / k_F
      Y2=Y*Y                                                        !
!
      U=X*Z                                                         ! omega / (q * v_F)
!
      Z1=X+U                                                        !
      Z2=X-U                                                        !
      COEF=TWO*PI_INV*ALPHA*RS                                      !
      LN1=DLOG(DABS(ONE+Z1)/(ONE-Z1))                               !
      LN2=DLOG(DABS(ONE+Z2)/(ONE-Z2))                               !
!
      Q0R=COEF*(ONE + HALF*(ONE-Z1*Z1)*LN1/Y +                    & ! ref. (1) eq. (3.2)
                      HALF*(ONE-Z2*Z2)*LN2/Y)                       !
!
      IF(U < (ONE-X)) THEN                                          !
!
        Q0I=TWO*ALPHA*RS*U/Y2                                       ! ref. (1) eq. (3.3)
!
      ELSE                                                          !
!
         IF( (U <= (ONE+U)) .AND. (U >= DABS(ONE-U)) ) THEN         !
           Q0I=ALPHA*RS*(ONE - (X-U)**2)/(Y2*Y)                     ! ref. (1) eq. (3.3)
         ELSE                                                       !
           Q0I=ZERO                                                 ! ref. (1) eq. (3.3)
         END IF                                                     !
!
      END IF                                                        !
!
      EPS=ONE/(ONE-Q0R-IC*Q0I)                                      ! ref. (1) eq. (3.1)
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END SUBROUTINE HAFO_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE HUCO_EPS_D_LG_3D(X,Z,EPSR,EPSI)
!
! This subroutine computes the Hu-O'Connell dielectric function that
!  including damping effect through electron-electron and electron-impurity
!  fluctuation, leading to a diffusion coefficient D, for 3D systems
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = hbar omega / E_F
!
!
!  Output variables :
!
!       * EPSR     : real part of the dielectric function at q
!       * EPSI     : imaginary part of the dielectric function at q
!
!   Reference :  (1) G. Y. Hu and R. F. O'Connell, Phys. Rev. B 40, 3600-3604 (1989)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 13 Nov 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,EIGHT,  &
                                     HALF,FOURTH,EIGHTH
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E
      USE FERMI_SI,           ONLY : KF_SI
      USE SCREENING_VEC,      ONLY : THOMAS_FERMI_VECTOR
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)              ::  Q_SI,KTF_SI
      REAL (WP)              ::  K2Q2
      REAL (WP)              ::  COEF,KOEF
      REAL (WP)              ::  U,B,NUP,NUM
      REAL (WP)              ::  NP2,NM2
      REAL (WP)              ::  BX,B2X2
      REAL (WP)              ::  OPNP,OMNP
      REAL (WP)              ::  OPNM,OMNM
      REAL (WP)              ::  OBXP,OBXM
      REAL (WP)              ::  LOGP,LOGM
      REAL (WP)              ::  TOPP,TOMP
      REAL (WP)              ::  TOPM,TOMM
!
      REAL (WP)              ::  LOG,ATAN
!
      U    = X * Z                                                  ! omega / (q * v_F)
      Q_SI = TWO * KF_SI * X                                        ! q in SI
!
!  Computing the Thomas-Fermi vector
!
      CALL THOMAS_FERMI_VECTOR('3D',KTF_SI)                         !
!
      K2Q2 = KTF_SI * KTF_SI / (Q_SI * Q_SI)                        !
!
      COEF = HALF * K2Q2                                            ! coeff. of real part
      KOEF = K2Q2 / (EIGHT * X)                                     ! coeff. of imag part
!
!  Setting the Hu-O'Connell parameters
!
      B   = TWO * M_E * DIF / H_BAR                                 ! \
      NUP = X + U                                                   !  > ref. (1) eq. (8)
      NUM = X - U                                                   ! /
!
      NP2 = NUP * NUP                                               !
      NM2 = NUM * NUM                                               !
!
      OPNP = ONE + NUP                                              !
      OMNP = ONE - NUP                                              !
      OPNM = ONE + NUM                                              !
      OMNM = ONE - NUM                                              !
!
      BX   = B * X                                                  !
      B2X2 = BX * BX                                                !
!
      LOGP = LOG( ABS( (OPNP**2 + B2X2) / (OMNP**2 + B2X2) ) )      !
      LOGM = LOG( ABS( (OPNM**2 + B2X2) / (OMNM**2 + B2X2) ) )      !
!
      OBXP = ONE + B2X2 - NP2                                       !
      OBXM = ONE + B2X2 - NM2                                       !
!
      TOPP = OPNP / BX                                              ! \
      TOMP = OMNP / BX                                              !  | arguments of
      TOPM = OPNM / BX                                              !  |  arctan[ ]
      TOMM = OMNM / BX                                              ! /
!
!  Real part of epsilon
!
      EPSR = ONE + COEF * ( ONE + EIGHTH / X * (                  & !
                                OBXP * LOGP + OBXM * LOGM         & !
                                               )                  & !
                            - HALF * B * (                        & ! ref. (1) es. (7)
                                NUP * ( ATAN(TOMP) + ATAN(TOPP) ) & !
                              + NUM * ( ATAN(TOMM) + ATAN(TOPM) ) & !
                                         )                        & !
                          )                                         !
!
!  Imaginary part of epsilon
!
      EPSI= KOEF * (                                              & !
                       OBXM * ( ATAN(TOMM) + ATAN(TOPM) )         & !
                     - OBXP * ( ATAN(TOMP) + ATAN(TOPP) )         & !
                     + BX * (                                     & ! ref. (1) es. (9)
                            NUM * LOGM - NUP * LOGP               & !
                            )                                     & !
                   )                                                !
!
      END SUBROUTINE HUCO_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE HYDR_EPS_D_LG_3D(X,Z,RS,EPSR,EPSI)
!
!  This subroutine computes the longitudinal hydrodynamic dynamical
!     dielectric function in 3D
!
!  References: (1) R. Esquivel-Sirvent and G. C. Schatz,
!                     J. Phys. Chem. C 116, 420-424 (2011)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,THIRD
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE PLASMON_ENE_SI
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,RS,U
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q_SI,O_SI
      REAL (WP)             ::  O_PL,GAMMA
!
      REAL (WP)             ::  REAL,AIMAG
!
      COMPLEX (WP)          ::  EPS,BETA2,NUM,DEN
!
      U = X * Z                                                     ! omega / (q * v_F)
!
      Q_SI = TWO * X * KF_SI                                        ! q       in SI
      O_SI = U * Q_SI * VF_SI                                       ! omega   in SI
      O_PL = ENE_P_SI / H_BAR                                       ! omega_p in SI
!
      GAMMA = ONE / TAU                                             !
!
      NUM   = 0.20E0_WP * THIRD * O_SI + IC * THIRD * GAMMA         !
      DEN   = O_SI + IC * GAMMA                                     !
      BETA2 = VF_SI * VF_SI * NUM / DEN                             !
!
      EPS = ONE - O_PL * O_PL / (O_SI * DEN - BETA2 * Q_SI * Q_SI)  ! ref. (1) eq. (6)
!
      EPSR = REAL(EPS,KIND=WP)                                      !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE HYDR_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE KLEI_EPS_D_LG_3D(X,Z,EPSR,EPSI)
!
!  This subroutine computes Kleinman longitudinal
!    dielectric function EPS(q,omega,T) in 3D systems.
!
!  References: (1) P. R. Antoniewicz and L. Kleinman, Phys. Rev. B2,
!                     2808-2811 (1970)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!  Warning: there is an inhomogeneity in Kleinman's equation. His Delta (D)
!           is an energy shift and should be proportional to an energy and it
!           is in fact proportional to a momentum ...
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified :  5 Oct 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,EIGHT,  &
                                     HALF,THIRD
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E
      USE FERMI_SI,           ONLY : KF_SI
      USE PI_ETC,             ONLY : PI_INV
      USE SCREENING_VEC2,     ONLY : KLEINMAN_VECTOR
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  A,B,D,AL,KS_A,KS_B,Q_SI,Q2,OM
      REAL (WP)             ::  NUM,DEN,DEN_A,DEN_B,KK,K2,K3,AA
      REAL (WP)             ::  A1,A2,A3
      REAL (WP)             ::  CHI1P,CHI1M,CHI2P,CHI2M
!
      REAL (WP)             ::  EXP,LOG,ABS
!
      COMPLEX (WP)          ::  EPS,CHIP,CHIM,G1,G2,G3
!
      COMPLEX (WP)          ::  CONJG
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
      OM   = Z * H_BAR * Q_SI * Q_SI * HALF / M_E                   ! omega in SI
!
      Q2 = Q_SI * Q_SI                                              !
      K2 = KF_SI * KF_SI                                            !
      K3 = K2 * KF_SI                                               !
!
      AL = HALF * (ONE + EXP(-X))                                   ! ref. 1 eq. (21)
!
!  Computation of the screening vectors KS
!
      CALL KLEINMAN_VECTOR('3D',X,1,KS_A)                           ! for coef A
      CALL KLEINMAN_VECTOR('3D',X,2,KS_B)                           ! for coef B
!
      NUM   = Q2                                                    !
      DEN_A = TWO * AL * KF_SI * KF_SI + KS_A * KS_A                !
      DEN_B = TWO * AL * KF_SI * KF_SI + KS_B * KS_B + Q2           !
      A     = HALF * NUM / DEN_A                                    ! ref. 1 eq. (2)
      B     = HALF * NUM / DEN_B                                    ! ref. 1 eq. (3)
      D     = EIGHT * THIRD * PI_INV * K3 * (A - B) / Q2            ! ref. 1 eq. (7)
!
      KK = TWO / (Q2 * Q_SI)                                        !
!
!  Chi(q,+omega)
!
      AA  = Q2 + D + OM                                             !
      NUM = AA + TWO * Q_SI * KF_SI                                 !
      DEN = AA - TWO * Q_SI * KF_SI                                 !
!
      CHI1P = KK * PI_INV * ( (K2 - (HALF * AA / Q_SI)**2) *      & ! real part
                              LOG(ABS(NUM / DEN)) +               & !
                              KF_SI * AA / Q_SI                   & ! ref. 1 eq. (5)
                            )                                       !
!
      A1 = - (Q2 + TWO * Q_SI * KF_SI)                              !
      A2 = OM + D                                                   !
      A3 = TWO * Q_SI * KF_SI * Q2                                  !
!
      IF( (A1 < A2) .AND. (A2 < A3) ) THEN                          !
        CHI2P = KK * (K2 - (HALF * AA / Q_SI)**2)                   ! imaginary part
      ELSE                                                          !
        CHI2P = ZERO                                                ! ref. 1 eq. (5)
      END IF                                                        !
!
!  Chi(q,-omega)
!
      AA  = Q2 + D - OM                                             !
      NUM = AA + TWO * Q_SI * KF_SI                                 !
      DEN = AA - TWO * Q_SI * KF_SI                                 !
!
      CHI1M = KK * PI_INV *( (K2 - (HALF * AA / Q_SI)**2) *       & ! real part
                             LOG(ABS(NUM / DEN)) +                & !
                             KF_SI * AA / Q_SI                    & ! ref. 1 eq. (5)
                           )                                        !
!
      A2 = - OM + D                                                 !
!
      IF( (A1 < A2) .AND. (A2 < A3) ) THEN                          !
        CHI2M = KK * (K2 - (HALF * AA / Q_SI)**2)                   ! imaginary part
      ELSE                                                          !
        CHI2M = ZERO                                                !
      END IF                                                        !
!
      CHIP = CHI1P - IC * CHI2P                                     ! ref. 1 eq. (4)
      CHIM = CHI1M - IC * CHI2M                                     ! ref. 1 eq. (4)
!
!  Computing the dielectric function
!
      G1 = CHIP + CONJG(CHIM)                                       !
      G2 = CHIP * CHIP + CONJG(CHIM) * CONJG(CHIM)                  !
      G3 = CHIP * CONJG(CHIM)                                       !
!
      EPS = ONE + HALF * G1 / ( ONE - HALF *                      & !
                                (A * G2 + TWO * B * G3) / G1      & ! ref. 1 eq. (1)
                              )                                     !
!
      EPSR = REAL(EPS,KIND=WP)                                      !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE KLEI_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE KLKD_EPS_D_LG_3D(X,Z,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Klimontovich-Kraeft
!    dynamical dielectric function in 3D
!
!  This result is valid in the highly degenerate case
!
!  References: (1) W.-D. Kraeft, D. Kremp, W. Ebeling and G. Röpke,
!                     "Quantum Statistics of Charged Particle Systems",
!                     (Plenum Press, 1986)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * T        : temperature (SI)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  Note: We rewrite  m*omega/q  +/- h_bar*q/2 as
!
!                    m*v_F * ( U +/- X)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified :  5 Oct 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,FOUR,HALF
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E,K_B
      USE FERMI_SI,           ONLY : EF_SI,KF_SI,VF_SI
      USE PI_ETC,             ONLY : PI,PI2
      USE COULOMB_K,          ONLY : COULOMB_FF
!
      USE UNITS,              ONLY : UNIT
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,X2,Z,T,U,U2
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  BETA,VC,Q_SI,TF,O_SI
      REAL (WP)             ::  CR,CI,C2,PIR,PII
      REAL (WP)             ::  A,BP,BM
!
      REAL (WP)             ::  DLOG,DEXP
!
      X2=X*X                                                        !
!
      U=X*Z                                                         ! omega / (q * v_F)
      U2=U*U                                                        !
!
      BETA=ONE/(K_B*T)                                              !
!
      Q_SI=TWO*X*KF_SI                                              ! q in SI
      O_SI=U*Q_SI*VF_SI                                             ! omega in SI
!
      CALL COULOMB_FF('3D',UNIT,Q_SI,ZERO,VC)                       ! Coulomb potential
!
      TF=EF_SI/K_B                                                  ! Fermi temperature
!
      CR=M_E*KF_SI/(FOUR*PI2*H_BAR*H_BAR*X)                         !
      CI=M_E*M_E/(TWO*PI*H_BAR*H_BAR*H_BAR*H_BAR*BETA*Q_SI)         !
      C2=CI*O_SI*BETA                                               !
!
      A=PI2 * (T/TF) /(BETA*12.0E0_WP)                              !
      BP=EF_SI*(U+X)*(U+X) - EF_SI                                  !
      BM=EF_SI*(U-X)*(U-X) - EF_SI                                  !
!
      PIR=CR * ( TWO*X - HALF*(ONE-X2-U2)*                         &!
                        DLOG(((ONE-X)**2 - U2)/((ONE+X)**2 - U2)) +&!
                    X*U*DLOG(((ONE-X)**2 - X2)/((ONE+X)**2 - X2)) +&!
                   HALF*PI* (T/TF)**2 * (                          &! ref. (1) eq. (4.91)
                   HALF*DLOG(((ONE-X)**2 - U2)/((ONE+X)**2 - U2)) +&!
                   (ONE+X)/((ONE+X)**2 - U2) -                     &!
                   (ONE-X)/((ONE-X)**2 - U2)                       &!
                                        )                          &!
               )                                                    !
!
      IF(U > (ONE+X)) THEN                                          !
        PII=CI*DEXP(-BETA*A)*( DEXP(-BETA*BP) - DEXP(-BETA*BM) )    ! ref. (1) eq. (4.92)
      ELSE IF(U < (ONE-X)) THEN                                     !
        PII=CI*DEXP(BETA*A)*( DEXP(BETA*BP) - DEXP(-BETA*BM) ) - C2 ! ref. (1) eq. (4.92)
      ELSE                                                          !
        PII=CI*BETA*(BM+A) + CI* (                                 &!
                     DEXP(-BETA*(A+BP)) -  DEXP(BETA*(A+BM))       &! ref. (1) eq. (4.92)
                                 )                                  !
      END IF                                                        !
!
      EPSR=ONE-VC*PIR                                               !
      EPSI=PII                                                      !
!
      END SUBROUTINE KLKD_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE KLKN_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Klimontovich-Kraeft
!    dynamical dielectric function in 3D
!
!  This result is valid in the nondegenerate case
!
!  References: (1) W.-D. Kraeft, D. Kremp, W. Ebeling and G. Röpke,
!                     "Quantum Statistics of Charged Particle Systems",
!                     (Plenum Press, 1986)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature (SI)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  Note: we rewrite  m*omega/q  +/- h_bar*q/2 as
!
!                    m*v_F * ( U +/- X)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 19 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO
      USE COMPLEX_NUMBERS,    ONLY : ONEC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E,K_B
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE PI_ETC,             ONLY : PI
      USE UTILITIES_1,        ONLY : RS_TO_N0
      USE EXT_FUNCTIONS,      ONLY : CONHYP
      USE COULOMB_K,          ONLY : COULOMB_FF
!
      USE UNITS,              ONLY : UNIT
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,T,U
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  BETA,COEF,GAMMA,VC,Q_SI
      REAL (WP)             ::  AP,AM,CR,CI
      REAL (WP)             ::  ZZRP,ZZRM
      REAL (WP)             ::  RS,N0
!
      REAL (WP)             ::  DSQRT,DREAL
!
      COMPLEX (WP)          ::  A,B,ZZCP,ZZCM
      COMPLEX (WP)          ::  PIR,PII
!
      COMPLEX (WP)          ::  DCMPLX
!
      U=X*Z                                                         ! omega / (q * v_F)
!
      BETA=ONE/(K_B*T)                                              !
      COEF=TWO*M_E*K_B*T                                            !
      GAMMA=TWO*PI*H_BAR/DSQRT(PI*COEF)                             !
!
      Q_SI=TWO*X*KF_SI                                              ! q in SI
!
      N0=RS_TO_N0('3D',RS)                                          !
!
      CALL COULOMB_FF('3D',UNIT,Q_SI,ZERO,VC)                       ! Coulomb potential
!
      AP=M_E*VF_SI*( U + X )                                        !
      AM=M_E*VF_SI*( U - X )                                        !
!
      CR=N0*BETA/(H_BAR*Q_SI)                                       ! coef. of real part
      CI=N0*M_E*GAMMA/(TWO*H_BAR*H_BAR*Q_SI)                        ! coef. of imaginary
!
      A=ONEC                                                        ! parameters of
      B=(1.5E0_WP,0.0E0_WP)                                         !  1F1(a,b;z)
!
      ZZRP=-AP*AP/COEF                                              !
      ZZRM=-AM*AM/COEF                                              ! arguments of
      ZZCP=DCMPLX(ZZRP)                                             !  1F1(a,b;z)
      ZZCM=DCMPLX(ZZRM)                                             !
!
      PIR=CR*( AP*CONHYP(A,B,ZZCP,0,0) -                          & ! ref. (1) eq. (4.71)
               AM*CONHYP(A,B,ZZCM,0,0)                            & !
             )                                                      !
      PII=CI*( CDEXP(ZZCP) - CDEXP(ZZCM) )                          ! ref. (1) eq. (4.72)
!
      EPSR=ONE-VC*DREAL(PIR)                                        !
      EPSI=DREAL(PII)                                               !
!
      END SUBROUTINE KLKN_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE LAND_EPS_D_LG_3D(X,Z,XC,U0,W,D,RS,LANDAU,EPSR,EPSI)
!
!  This subroutine computes the dielectric function EPS(q,omega)
!    in 3D systems in terms of Landau's parameters.
!
!  References: (1) E. Lipparini, "Modern Many-Particle Physics - Atomic Gases,
!                   Quantum Dots and Quantum Fluids", World Scientific (2003)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * XC       : dimensionless cut-off  --> XC = q_c  / (2 * k_F)
!       * U0 / A   : bare interaction constant / hard sphere radius (in SI)
!       * W        : half bandwidth for bare particle
!       * D        : filling (dopant concentration)
!       * RS       : dimensionless factor
!       * LANDAU   : model chosen for the calculation of the parameters
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,THREE, &
                                     HALF,THIRD
      USE COMPLEX_NUMBERS,    ONLY : ONEC,IC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E,E,EPS_0
      USE FERMI_SI,           ONLY : KF_SI
      USE PI_ETC,             ONLY : PI,PI2
      USE LANDAU_PARAM
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  LANDAU
!
      REAL (WP)             ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q_SI,XC,U0,W,D,RS
      REAL (WP)             ::  U,NU0,TH,V_C
      REAL (WP)             ::  F0S,F0A,F1S,F1A,F2S,F2A
!
      REAL (WP)             ::  DLOG,DABS,DREAL,DIMAG
!
      COMPLEX (WP)          ::  EPS,CHIS,OM00,OM20,OM22
      COMPLEX (WP)          ::  NUM,DEN,NU1,DE1
!
      COMPLEX (WP)          ::  DCMPLX
!
      U=X*Z                                                         ! omega / (q * v_F)
      Q_SI=TWO*X*KF_SI                                              ! q in SI
      NU0=M_E*KF_SI/(PI2*H_BAR*H_BAR)                               ! DoS at Fermi level
!
!  Computing the Coulomb potential
!
      V_C=E*E/(EPS_0*Q_SI*Q_SI)                                     !
!
!  Computing Landau's parameters
!
      CALL LANDAU_PARAMETERS_3D(X,XC,U0,W,D,RS,LANDAU,         &    !
                                F0S,F0A,F1S,F1A,F2S,F2A)            !
!
!  Computing the Omega_{l,l} parameters
!
      IF(ONE.GT.U) THEN                                             !
        TH=HALF*PI*U                                                !
      ELSE                                                          !
        TH=ZERO                                                     !
      ENDIF                                                         !
      OM00=ONE + HALF*U*DLOG(DABS((U-ONE)/(U+ONE))) + IC*TH         !
      OM20=HALF + HALF*(THREE*U*U-ONE)*OM00                         ! ref. 1 eq. (8.14)
      OM22=0.20E0_WP+HALF*(THREE*U*U-ONE)*OM20                      !
!
!  Computation of the density-density response function
!
      NU1=TWO*(ONE+THIRD*F1S)*(ONE+0.2E0_WP*F2S)*OM20               !
      DE1=THREE*(OM00+F2S*(OM22*OM00-OM20*OM20))                    !
      NUM=DCMPLX(THIRD*NU0*(ONE+THIRD*F1S))                         !
      DEN=U*U - THIRD*(ONE+THIRD*F1S)*(ONE+F0S) - NU1/DE1           !
      CHIS=NUM/DEN                                                  ! ref. 1 eq. (8.23)
!
      EPS=ONE/(ONE+V_C*CHIS)                                        !
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END SUBROUTINE LAND_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE LVL1_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)
!
!  This subroutine computes the longitudinal linearized Vlasov dynamical
!     dielectric function in 3D for a weakly coupled plasma
!
!  References: (1) S. Ichimaru, Rev. Mod. Phys. 54, 1017-1059 (1982)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * T        : temperature (SI)
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO
      USE CONSTANTS_P1,       ONLY : M_E,K_B
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE SCREENING_VEC,      ONLY : DEBYE_VECTOR
      USE EXT_FUNCTIONS,      ONLY : W
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,T,RS,U
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  ZZ,Q_SI
      REAL (WP)             ::  KD_SI
!
      REAL (WP)             ::  DSQRT,DREAL,DIMAG
!
      U=X*Z                                                         ! omega / (q * v_F)
      Q_SI=TWO*X*KF_SI                                              ! q
!
!  Computation of the Debye screening vector
!
      CALL DEBYE_VECTOR('3D',T,RS,KD_SI)                            !
!
      ZZ=U*VF_SI/DSQRT(K_B*T/M_E)                                   ! argument of PDF W(zz)
!
      EPSR=ONE + (KD_SI/Q_SI)**2 * DREAL(W(ZZ))                     ! ref. (1) eq. (2.112)
      EPSI=(KD_SI/Q_SI)**2 * DIMAG(W(ZZ))                           !
!
      END SUBROUTINE LVL1_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE LVL2_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)
!
!  This subroutine computes the longitudinal linearized Vlasov dynamical
!     dielectric function in 3D for a strongly coupled plasma
!
!  References: (1) S. Ichimaru, Rev. Mod. Phys. 54, 1017-1059 (1982)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * T        : temperature (SI)
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 23 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO
      USE CONSTANTS_P1,       ONLY : M_E,K_B
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE LF_VALUES,          ONLY : GQ_TYPE
      USE SF_VALUES,          ONLY : SQ_TYPE
      USE EXT_FUNCTIONS,      ONLY : W
      USE SCREENING_VEC,      ONLY : DEBYE_VECTOR
      USE LOCAL_FIELD_STATIC
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,T,RS,U
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  ZZ,Q_SI,FR
      REAL (WP)             ::  GQ,KD_SI
!
      REAL (WP)             ::  DSQRT,DREAL,DIMAG
!
      COMPLEX (WP)          ::  NUM,DEN
!
      U=X*Z                                                         ! omega / (q * v_F)
      Q_SI=TWO*X*KF_SI                                              ! q
!
!  Computation of the Debye screening vector
!
      CALL DEBYE_VECTOR('3D',T,RS,KD_SI)                            !
!
      ZZ=U*VF_SI/DSQRT(K_B*T/M_E)                                   ! argument of PDF W(zz)
      FR=(KD_SI/Q_SI)**2                                            ! (k_D/q)^2
!
!  Computing the static local-field correction
!
      CALL LOCAL_FIELD_STATIC_3D(X,RS,T,GQ_TYPE,GQ)                 !
!
      NUM=FR*W(ZZ)                                                  !ref. (1) eq. (2.114)
      DEN=ONE-NUM*GQ                                                !
!
      EPSR=ONE + DREAL(NUM/DEN)                                     !
      EPSI=DIMAG(NUM/DEN)                                           !
!
      END SUBROUTINE LVL2_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE MEM2_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the dielectric function following
!    the Nevanlinna formula of the classical Hamburger theory of moments
!
!  It makes use of the moments:
!
!       Cn(q) = 1/pi int_{-inf}^{+inf} omega^n L(q,omega) d omega
!
!    with the loss function given by
!
!       L(q,omega) = -1/omega * Im[ 1/epsilon(q,omega) ]
!
!
!  ---> This is the two-moment version
!
!
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 76,  026403 (2007)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!
!  Intermediate parameters:
!
!       * C0       : 0-th order moment of the loss function
!       * C2       : 2-th order moment of the loss function
!
!  Output parameters:
!
!       * EPS      : value of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,         ONLY : TWO,FOUR
      USE COMPLEX_NUMBERS,      ONLY : ONEC,IC
      USE PI_ETC,               ONLY : PI
      USE FERMI_SI,             ONLY : KF_SI,VF_SI
      USE LOSS_MOMENTS
      USE DF_VALUES,            ONLY : MEM_TYPE,ALPHA,BETA
      USE MEMORY_FUNCTIONS_F
      USE DAMPING_SI
      USE DAMPING_VALUES,         ONLY : PCT
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  Q_SI,U,V
      REAL (WP)              ::  OM,OM2,OMP
      REAL (WP)              ::  C0,C2,C4
      REAL (WP)              ::  OM12
!
      REAL (WP)              ::  REAL,AIMAG
!
      COMPLEX (WP)           ::  EEE,EPS
      COMPLEX (WP)           ::  NUM,DEN
      COMPLEX (WP)           ::  MEMO,MEM
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
      U    = X * Z                                                  ! omega / (q * v_F)
      V    = FOUR * U * X                                           ! h_bar omega / E_F
      OM   = U * Q_SI * VF_SI                                       ! omega in SI
      OM2  = OM * OM                                                !
!
!  Computing the moments of the loss function
!
      CALL LOSS_MOMENTS_AN(X,C0,C2,C4)
!
      OM12 = C2 / C0                                                !
!
!  Choice of the memory function MEM
!
      MEMO = MEMORY_F(V,TAU,TAU2,PCT,ALPHA,BETA,MEM_TYPE)           !
      MEM  = TWO * PI * IC * MEMO                                   !
!
!  Nevanlinna's formula
!
      NUM = OM12                                                    !
      DEN = OM2 - OM12 + OM * MEM                                   !
!
      EEE = ONEC + NUM / DEN                                        !
!
      EPS = ONEC / EEE                                              ! ref. (1)  eq. (5)
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE MEM2_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE MEM3_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the dielectric function following
!    the Nevanlinna formula of the classical Hamburger theory of moments
!
!  It makes use of the moments:
!
!       Cn(q) = 1/pi int_{-inf}^{+inf} omega^n L(q,omega) d omega
!
!    with the loss function given by
!
!       L(q,omega) = -1/omega * Im[ 1/epsilon(q,omega) ]
!
!
!  ---> This is the three-moment version
!
!
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 76,  026403 (2007)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!
!
!  Intermediate parameters:
!
!       * C0       : 0-th order moment of the loss function
!       * C2       : 2-th order moment of the loss function
!       * C4       : 4-th order moment of the loss function
!
!  Output parameters:
!
!       * EPS      : value of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE DF_VALUES,            ONLY : MEM_TYPE,ALPHA,BETA
!
      USE REAL_NUMBERS,         ONLY : ONE,TWO,FOUR
      USE COMPLEX_NUMBERS,      ONLY : ZEROC,IC
      USE PI_ETC,               ONLY : PI
      USE CONSTANTS_P1,         ONLY : H_BAR
      USE FERMI_SI,             ONLY : KF_SI,VF_SI
      USE PLASMON_ENE_SI
      USE LOSS_MOMENTS
      USE DF_VALUES,            ONLY : MEM_TYPE,ALPHA,BETA
      USE MEMORY_FUNCTIONS_F
      USE DAMPING_SI
      USE DAMPING_VALUES,       ONLY : PCT
!
      IMPLICIT NONE
!
      INTEGER                ::  EXPN,EXPD
!
      INTEGER                ::  EXPONENT
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  Q_SI,U,V
      REAL (WP)              ::  OM,OMP
      REAL (WP)              ::  C0,C2,C4
      REAL (WP)              ::  OM12,OM22
      REAL (WP)              ::  REN,RED,IMN,IMD
!
      REAL (WP)              ::  REAL,AIMAG
!
      COMPLEX (WP)           ::  OMB,OM2
      COMPLEX (WP)           ::  EPS
      COMPLEX (WP)           ::  NUM,DEN
      COMPLEX (WP)           ::  MEMO,MEM
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
      U    = X * Z                                                  ! omega / (q * v_F)
      V    = FOUR * U * X                                           ! h_bar omega / E_F
      OM   = U * Q_SI * VF_SI                                       ! omega in SI
      OMB  = OM + IC / TAU                                          !
      OM2  = OMB * OMB                                              !
      OMP  = ENE_P_SI / H_BAR                                       ! omega_p
!
!  Computing the moments of the loss function
!
      CALL LOSS_MOMENTS_AN(X,C0,C2,C4)
!
      OM12 = C2 / C0                                                !
      OM22 = C4 / C2                                                !
!
!  Choice of the memory function MEM
!
      MEMO = MEMORY_F(V,TAU,TAU2,PCT,ALPHA,BETA,MEM_TYPE)           !
      MEM  = TWO * PI * IC * MEMO                                   !
!
!  Memory function formula
!
      NUM = OMP * OMP * (OMB + MEM)                                 !
      DEN = OMB * (OM2 - OM22) + MEM * (OM2 - OM12)                 !
!
!  Real and imaginary part of NUM and DEN
!
      REN =  REAL(NUM,KIND=WP)                                      !
      RED =  REAL(DEN,KIND=WP)                                      !
      IMN = AIMAG(NUM)                                              !
      IMD = AIMAG(DEN)                                              !
!
!  Checking the real/imaginary parts when infinitesimal
!
!
      EXPN = EXPONENT(IMN)                                          !
      EXPD = EXPONENT(IMD)                                          !
!
      IF(EXPN < -100) THEN                                          !
        NUM = REN + ZEROC                                           !
      END IF                                                        !
      IF(EXPD < -100) THEN                                          !
        DEN = RED + ZEROC                                           !
      END IF                                                        !
!
!  EPS = DEN / (NUM + DEN)
!
      EPS = DEN / (NUM + DEN)
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE MEM3_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE MER1_EPS_D_LG_3D(X,Z,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Mermin dynamical
!     dielectric function in 3D
!
!  References: (1) H. B. Nersiyan and A. K. Das, Phys. Rev. E 69, 046404 (2004)
!              (2) H. B. Nersiyan , A. K. Das, and H. H. Matevosyan,
!                        Phys. Rev. E 66, 046415 (2002)
!
!  Note: for TAU --> infinity, we recover the RPA values
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!       * TAU      : relaxation time (used for damping)  in SI
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!  Note: in order to be more general, we use EPS_B (background
!        dielectric constant) instead of 1 (vacuum case)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 10 Aug 2021
!
!
      USE MATERIAL_PROP,      ONLY : EPS_B
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR,EIGHT,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : BOHR,H_BAR
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PI_ETC,             ONLY : PI_INV
!
      USE DFUNC_STATIC,       ONLY : RPA1_EPS_S_LG
      USE DAMPING_SI,         ONLY : TAU
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN) ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  U,X2,X3
      REAL (WP)             ::  CHI2,COEF
      REAL (WP)             ::  REPSM1,IEPSM1
      REAL (WP)             ::  REPS00
      REAL (WP)             ::  EPS0R,EPS0I
      REAL (WP)             ::  GAMMA,GAMMA2
      REAL (WP)             ::  UP,UM,UP2,UM2
      REAL (WP)             ::  NUM,DEN
      REAL (WP)             ::  Y1P,Y2P,Y1M,Y2M
      REAL (WP)             ::  F1,F2
!
      REAL (WP)             ::  LOG,ATAN,REAL,AIMAG
!
      COMPLEX (WP)          ::  NUMI,DENI,EPS
!
      X2 = X *  X                                                   !
      X3 = X2 * X                                                   !
!
      U      = X * Z                                                ! omega / (q * v_F)
      CHI2   = PI_INV / (KF_SI * BOHR)                              !
      GAMMA  = H_BAR / (FOUR * EF_SI * TAU)                         !
      GAMMA2 = GAMMA * GAMMA                                        !
!
      COEF = CHI2 / X2                                              !
!
      UP = U + X                                                    ! U_+
      UM = U - X                                                    ! U_-
!
      UP2 = UP * UP                                                 !
      UM2 = UM * UM                                                 !
!
      NUM = X2 * (UP + ONE) * (UP + ONE) + GAMMA2                   !
      DEN = X2 * (UP - ONE) * (UP - ONE) + GAMMA2                   ! ref. (1) eq. (13)
      Y1P = LOG(NUM / DEN)                                          ! Y_1(z,U_+)
!
      NUM = X2 * (UM + ONE) * (UM + ONE) + GAMMA2                   !
      DEN = X2 * (UM - ONE) * (UM - ONE) + GAMMA2                   ! ref. (1) eq. (13)
      Y1M = LOG(NUM / DEN)                                          ! Y_1(z,U_-)
!
      Y2P = ATAN(X * (UP - ONE) / GAMMA) -                        & ! ref. (1) eq. (14)
            ATAN(X * (UP + ONE) / GAMMA)                            ! Y_2(z,U_+)
      Y2M = ATAN(X * (UM - ONE) / GAMMA) -                        & ! ref. (1) eq. (14)
            ATAN(X * (UM + ONE) / GAMMA)                            ! Y_2(z,U_-)
!
      F1 = HALF + ONE / (16.0E0_WP * X3) * (                       &!
                                       ( X2 * (UM2 - ONE) - GAMMA2 &!
                                       ) * Y1M -                   &!
                                       ( X2 * (UP2 - ONE) - GAMMA2 &! ref. (1) eq. (11)
                                       ) * Y1P +                   &!
                                         FOUR * GAMMA * X *        &!
                                         (UP * Y2P - UM * Y2M)     &!
                                           )                        !
!
      F2 = ONE / (EIGHT * X3) * (                                  &!
                        GAMMA * X * (UM * Y1M - UP * Y1P) +        &!
                        X2 * ((UM2 - ONE) - GAMMA2) * Y2M -        &! ref. (1) eq. (12)
                        X2 * ((UP2 - ONE) - GAMMA2) * Y2P          &!
                                )                                   !
!
! Computation of EPS_{RPA}(x,u,Gamma) - 1
!
      REPSM1 = COEF * F1                                            ! ref. (1) eq. (10)
      IEPSM1 = COEF * F2                                            !
!
! Computation of EPS_{RPA}(x,0) - EPS_B
!
      CALL RPA1_EPS_S_LG(X,'3D',EPS0R,EPS0I)                        !
!
      REPS00 = EPS0R - EPS_B                                        !
!
      NUMI = (X * U + IC * GAMMA) * (REPSM1 + IC * IEPSM1)          !
      DENI =  X * U + IC * GAMMA  * (REPSM1 + IC * IEPSM1) / REPS00 !
!
      EPS = EPS_B + NUMI / DENI                                     ! ref. (1) eq. (9)
!
      EPSR = REAL(EPS,KIND=WP)                                      !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE MER1_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE MER2_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Lindhard-Mermin dynamical
!     dielectric function in 3D
!
!  References: (1) P.-O. Chapuis et al, Phys. Rev. B 77, 035441 (2008)
!
!  Note: for TAU --> infinity, we should recover the RPA values
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * TAU      : relaxation time (used for damping)  in SI
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified :  6 Aug 2021
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,THREE,FOUR,EIGHT,  &
                                     HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE MATERIAL_PROP,      ONLY : EPS_B
      USE PLASMON_ENE_SI
      USE DAMPING_SI,         ONLY : TAU
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,U,RS,T
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q_SI,O_SI
!
      REAL (WP)             ::  ABS,REAL,AIMAG
!
      COMPLEX (WP)          ::  UU,FL_U,FL_0
      COMPLEX (WP)          ::  ZPU,ZMU
      COMPLEX (WP)          ::  OB,COEF
      COMPLEX (WP)          ::  NUM,DEN,EPS
!
      U    = X * Z                                                  ! omega / (q * v_F)
      Q_SI = TWO * X * KF_SI                                        ! q     in SI
      O_SI = U * Q_SI * VF_SI                                       ! omega in SI
      OB   = O_SI + IC / TAU                                        !
!
      COEF = THREE * ENE_P_SI * ENE_P_SI / (H_BAR * H_BAR * OB)     !
!
      UU  = OB / (Q_SI * VF_SI)                                     ! u
      ZPU = X + UU                                                  ! z + u
      ZMU = X - UU                                                  ! z - u
!
      FL_0 = HALF + (ONE - X * X) * LOG( ABS((X + ONE) /          & !
                                             (X - ONE))           & ! ref (1) eq. (13)
                                       ) / (FOUR * X)               !
      FL_U = HALF + (ONE - ZMU * ZMU) * LOG( (ZMU + ONE) /        & !
                                             (ZMU - ONE)          & !
                                           ) / (EIGHT * X) +      & ! ref (1) eq. (11)
                    (ONE - ZPU * ZPU) * LOG( (ZPU + ONE) /        & !
                                             (ZPU - ONE)          & !
                                           ) / (EIGHT * X)          !
!
      NUM = UU * UU * FL_U
      DEN = O_SI + IC * FL_U / (TAU * FL_0)                         !
      EPS = EPS_B + COEF * NUM / DEN                                !
!
      EPSR = REAL(EPS,KIND=WP)                                      ! ref (1) eq. (9)
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE MER2_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE MERP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Mermin dynamical
!     dielectric function in 3D, with local field corrections
!
!  References: (1) H. B. Nersiyan and A. K. Das, Phys. Rev. E 69, 046404 (2004)
!
!  Note: for TAU --> infinity, we recover the RPA values
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * TAU      : relaxation time (used for damping)  in SI
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   --> This version uses RPA + LFC instead of RPA
!
!
!  Note: in order to be more general, we use EPS_B (background
!        dielectric constant) instead of 1 (vacuum case)
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 10 Aug 2021
!
!
      USE MATERIAL_PROP,      ONLY : EPS_B
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR,EIGHT,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : BOHR,H_BAR
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PI_ETC,             ONLY : PI_INV
!
      USE LF_VALUES,          ONLY : GQ_TYPE
!
      USE DFUNC_STATIC,       ONLY : RPA1_EPS_S_LG
      USE LOCAL_FIELD_STATIC
      USE DAMPING_SI,         ONLY : TAU
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN) ::  X,Z,RS,T
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  U,X2,X3
      REAL (WP)             ::  CHI2,COEF
      REAL (WP)             ::  REPSM1,IEPSM1
      REAL (WP)             ::  REPS00
      REAL (WP)             ::  EPS0R,EPS0I
      REAL (WP)             ::  GAMMA,GAMMA2
      REAL (WP)             ::  UP,UM,UP2,UM2
      REAL (WP)             ::  NUM,DEN
      REAL (WP)             ::  Y1P,Y2P,Y1M,Y2M
      REAL (WP)             ::  F1,F2
      REAL (WP)             ::  GQ
!
      REAL (WP)             ::  LOG,ATAN,REAL,AIMAG
!
      COMPLEX (WP)          ::  ERL,NUML,DENL,NUMI,DENI,EPS
!
      X2 = X *  X                                                   !
      X3 = X2 * X                                                   !

!
      U      = X * Z                                                ! omega / (q * v_F)
      CHI2   = PI_INV / (KF_SI * BOHR)                              !
      GAMMA  = H_BAR / (FOUR * EF_SI * TAU)                         !
      GAMMA2 = GAMMA * GAMMA                                        !
!
      COEF = CHI2 / X2                                              !
!
      UP = U + X                                                    ! U_+
      UM = U - X                                                    ! U_-
!
!  Computing the static local field correction GQ
!
      CALL LFIELD_STATIC(X,RS,T,GQ_TYPE,GQ)                         !
!
!  Computation of EPS_{RPA+LFC}(x,0) - EPS_B
!
      CALL RPA1_EPS_S_LG(X,'3D',EPS0R,EPS0I)                        ! EPS_{RPA}(x,0)
      REPS00 = (EPS0R - EPS_B) / (ONE - GQ *   (EPS0R - ONE))       ! EPS_{RPA+LFC}(x,0) - EPS_B
!
!  Computation of F1 and F2
!
      UP2 = UP * UP                                                 !
      UM2 = UM * UM                                                 !
!
      NUM = X2 * (UP + ONE) * (UP + ONE) + GAMMA2                   !
      DEN = X2 * (UP - ONE) * (UP - ONE) + GAMMA2                   ! ref. (1) eq. (13)
      Y1P = LOG(NUM / DEN)                                          ! Y_1(z,U_+)
!
      NUM = X2 * (UM + ONE) * (UM + ONE) + GAMMA2                   !
      DEN = X2 * (UM - ONE) * (UM - ONE) + GAMMA2                   ! ref. (1) eq. (13)
      Y1M = LOG(NUM / DEN)                                          ! Y_1(z,U_-)
!
      Y2P = ATAN(X * (UP - ONE) / GAMMA) -                        & ! ref. (1) eq. (14)
            ATAN(X * (UP + ONE) / GAMMA)                            ! Y_2(z,U_+)
      Y2M = ATAN(X * (UM - ONE) / GAMMA) -                        & ! ref. (1) eq. (14)
            ATAN(X * (UM + ONE) / GAMMA)                            ! Y_2(z,U_-)
!
      F1 = HALF + ONE / (16.0E0_WP * X3) * (                       &!
                                       ( X2 * (UM2 - ONE) - GAMMA2 &!
                                       ) * Y1M -                   &!
                                       ( X2 * (UP2 - ONE) - GAMMA2 &! ref. (1) eq. (11)
                                       ) * Y1P +                   &!
                                         FOUR * GAMMA * X *        &!
                                         (UP * Y2P - UM * Y2M)     &!
                                           )                        !
!
      F2 = ONE / (EIGHT * X3) * (                                  &!
                        GAMMA * X * (UM * Y1M - UP * Y1P) +        &!
                        X2 * ((UM2 - ONE) - GAMMA2) * Y2M -        &! ref. (1) eq. (12)
                        X2 * ((UP2 - ONE) - GAMMA2) * Y2P          &!
                                )                                   !
!
      REPSM1 = COEF * F1                                            ! ref. (1) eq. (10)
      IEPSM1 = COEF * F2                                            !
!
! Computation of EPS_{RPA+LFC}(x,u,Gamma) - 1 = ERL
!
      NUML = (REPSM1 + IC * IEPSM1)                                 !
      DENL = ONE - GQ * NUML                                        !
      ERL  = NUML / DENL                                            !
!
      NUMI = (X * U + IC * GAMMA) * ERL                             !
      DENI =  X * U + IC * GAMMA  * ERL / REPS00                    !
!
      EPS  = EPS_B + NUMI / DENI                                    ! ref. (1) eq. (9)
!
      EPSR = REAL(EPS,KIND=WP)                                      !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE MERP_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE MSAP_EPS_D_LG_3D(X,Y,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    mean spherical approximation dielectric function
!
!  References: (1) N. Iwamoto, E. Krotscheck and D. Pines,
!                     Phys. Rev. B 29, 3936-3951 (1984)
!              (2) B. Tanatar and N. Mutulay, Eur. Phys. J. B 1,
!                     409-417 (1998)
!
!  Notation: hbar omega_q = hbar^2 q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Y        : dimensionless factor   --> Y = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE REAL_NUMBERS,             ONLY : ZERO,ONE,TWO,SIX
      USE CONSTANTS_P1,             ONLY : BOHR
      USE FERMI_SI,                 ONLY : KF_SI
      USE PI_ETC,                   ONLY : PI
      USE STRUCTURE_FACTOR_STATIC,  ONLY : HFA_SF
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Y
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q_SI,A0Q,S0
!
      Q_SI=TWO*KF_SI                                                ! q in SI
      A0Q=BOHR*Q_SI                                                 ! a_0 * q (dimensionless)
      S0=HFA_SF(X)                                                  ! HF structure factor
!
      EPSR=ONE - ( ONE/(SIX*PI) * ONE/(X*X*X) * ONE/A0Q *         & !
                   ONE/(Y*Y - ONE/(S0*S0))                        & !
                 )                                                  !
      EPSI=ZERO                                                     !
!
      END SUBROUTINE MSAP_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE NEV2_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the dielectric function following
!    the Nevanlinna formula of the classical Hamburger theory of moments
!
!  It makes use of the moments:
!
!       Cn(q) = 1/pi int_{-inf}^{+inf} omega^n L(q,omega) d omega
!
!    with the loss function given by
!
!       L(q,omega) = -1/omega * Im[ 1/epsilon(q,omega) ]
!
!
!  ---> This is the two-moment version
!
!
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 76,  026403 (2007)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!
!  Intermediate parameters:
!
!       * GQ_TYPE  : local-field correction type (3D)
!       * EC_TYPE  : type of correlation energy functional
!       * SQ_TYPE  : static structure factor approximation (3D)
!       * PL_TYPE  : type of plasma considered
!                      PL_TYPE  = 'OCP' --> one-component plasma (~ electron gas)
!                      PL_TYPE  = 'DCP' --> two-component plasma
!       * NEV_TYPE : type of Nevalinna function used
!                      NEV_TYPE  = 'NONE' --> no function
!                      NEV_TYPE  = 'STA2' --> static value h(q)
!
!  Intermediate parameters:
!
!       * C0       : 0-th order moment of the loss function
!       * C2       : 2-th order moment of the loss function
!
!  Output parameters:
!
!       * EPS      : value of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,         ONLY : TWO
      USE COMPLEX_NUMBERS,      ONLY : ONEC
      USE FERMI_SI,             ONLY : KF_SI,VF_SI
      USE LOSS_MOMENTS
      USE DF_VALUES,            ONLY : NEV_TYPE
      USE NEVALINNA_FUNCTIONS
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  Q_SI,U,OM,OM2,OMP
      REAL (WP)              ::  C0,C2,C4
      REAL (WP)              ::  OM12
!
      REAL (WP)              ::  REAL,AIMAG
!
      COMPLEX (WP)           ::  EEE,EPS
      COMPLEX (WP)           ::  QN,NUM,DEN
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
      U    = X * Z                                                  ! omega / (q * v_F)
      OM   = U * Q_SI * VF_SI                                       ! omega in SI
      OM2  = OM * OM                                                !
!
!  Computing the moments of the loss function
!
      CALL LOSS_MOMENTS_AN(X,C0,C2,C4)
!
      OM12 = C2 / C0                                                !
!
!  Choice of the Nevanlinna function Q(X,V) = QN
!
      QN = NEVAN2(X,Z,RS,T,TAU,NEV_TYPE)                            !
!
!  Nevanlinna's formula
!
      NUM = OM12                                                    !
      DEN = OM2 - OM12 + OM * QN                                    !
!
      EEE = ONEC + NUM / DEN                                        !
!
      EPS = ONEC / EEE                                              ! ref. (1)  eq. (5)
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE NEV2_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE NEV3_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the dielectric function following
!    the Nevanlinna formula of the classical Hamburger theory of moments
!
!  It makes use of the moments:
!
!       Cn(q) = 1/pi int_{-inf}^{+inf} omega^n L(q,omega) d omega
!
!    with the loss function given by
!
!       L(q,omega) = -1/omega * Im[ 1/epsilon(q,omega) ]
!
!
!  ---> This is the three-moment version
!
!
!
!  References: (1) Yu. V. Arkhipov et al, Phys. Rev. E 76,  026403 (2007)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!
!  Intermediate parameters:
!
!       * GQ_TYPE  : local-field correction type (3D)
!       * EC_TYPE  : type of correlation energy functional
!       * SQ_TYPE  : static structure factor approximation (3D)
!       * PL_TYPE  : type of plasma considered
!                      PL_TYPE  = 'OCP' --> one-component plasma (~ electron gas)
!                      PL_TYPE  = 'DCP' --> two-component plasma
!       * NEV_TYPE : type of Nevalinna function used
!                      NEV_TYPE  = 'NONE' --> no function
!                      NEV_TYPE  = 'STA1' --> static value h(q)
!                      NEV_TYPE  = 'STA2' --> static value h(q)
!                      NEV_TYPE  = 'CLCO' --> Classical Coulomb OCP
!                      NEV_TYPE  = 'AMTA' -->
!                      NEV_TYPE  = 'PEEL' --> Perel'-Eliashberg function
!                      NEV_TYPE  = 'PE76' -->
!
!  Intermediate parameters:
!
!       * C0       : 0-th order moment of the loss function
!       * C2       : 2-th order moment of the loss function
!       * C4       : 4-th order moment of the loss function
!
!  Output parameters:
!
!       * EPS      : value of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,         ONLY : TWO
      USE COMPLEX_NUMBERS,      ONLY : ONEC
      USE CONSTANTS_P1,         ONLY : H_BAR
      USE FERMI_SI,             ONLY : KF_SI,VF_SI
      USE PLASMON_ENE_SI
      USE LOSS_MOMENTS
      USE DF_VALUES,            ONLY : NEV_TYPE
      USE NEVALINNA_FUNCTIONS
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  Q_SI,U,OM,OM2,OMP
      REAL (WP)              ::  C0,C2,C4
      REAL (WP)              ::  OM12,OM22
!
      REAL (WP)              ::  REAL,AIMAG
!
      COMPLEX (WP)           ::  EEE,EPS
      COMPLEX (WP)           ::  QN,NUM,DEN
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
      U    = X * Z                                                  ! omega / (q * v_F)
      OM   = U * Q_SI * VF_SI                                       ! omega in SI
      OM2  = OM * OM                                                !
      OMP  = ENE_P_SI / H_BAR                                       ! omega_p
!
!  Computing the moments of the loss function
!
      CALL LOSS_MOMENTS_AN(X,C0,C2,C4)
!
      OM12 = C2 / C0                                                !
      OM22 = C4 / C2                                                !
!
!  Choice of the Nevanlinna function Q(X,V) = QN
!
      QN = NEVAN2(X,Z,RS,T,TAU,NEV_TYPE)                            !
!
!  Nevanlinna's formula
!
      NUM = OMP * OMP * (OM + QN)                                   !
      DEN = OM * (OM2 - OM22) + QN * (OM2 - OM12)                   !
!
      EEE = ONEC + NUM / DEN                                        !
!
      EPS = ONEC / EEE                                              ! ref. (1)  eq. (5)
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE NEV3_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE PLPO_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic plasmon pole
!    dielectric function for 3D systems
!
!  References: (1) L. Hedin, J. Michiels and J. Inglesfield,
!                     Phys. Rev. B 8, 15565-582 (1998)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!
!  Intermediate parameters:
!
!       * PL_DISP  : type of analytical plasmon dispersion
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 10 Nov 2020
!
!
      USE REAL_NUMBERS,       ONLY : TWO,FOUR
      USE COMPLEX_NUMBERS,    ONLY : ONEC
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PLASMON_DISP_REAL
      USE PLASMON_ENE_SI
      USE PLASMON_DISPERSION
!
      IMPLICIT NONE
!
      REAL (WP),INTENT(IN)  ::  X,Z,RS,T
      REAL (WP),INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)             ::  ENE_SI,ENE_QR,ENE_P_Q
!
      REAL (WP)             ::  REAL,AIMAG
!
      COMPLEX (WP)          ::  NUM,DEN
      COMPLEX (WP)          ::  EPS,ENE_Q_SI
!
      COMPLEX (WP)          ::  CMPLX
!
      ENE_SI = FOUR * X * X * Z * EF_SI                             !
!
!  Calculation of the analytical plasmon dispersion
!
      CALL PLASMON_DISP_3D(X,RS,T,PL_DISP,ENE_P_Q)                  !
!
      ENE_Q_SI = CMPLX(ENE_P_Q)                                     !
!
      NUM = ENE_P_SI * ENE_P_SI                                     !
      DEN = ENE_SI * ENE_SI + NUM - ENE_Q_SI * ENE_Q_SI             !
!
      EPS = ONEC - NUM / DEN                                        !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE PLPO_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE RDF1_EPS_D_LG_3D(X,Z,EPSR,EPSI)
!
!  This subroutine computes random delta-function electron-impurity
!    interaction form of the dielectric function for disordered 3D
!    conductors
!
!  Reference: (1) B. L. Altshuler, A. G. Aronov, D.E. Khmelnitskii and
!                 A. I. Larkin, in "Quantum Theory of Solids",
!                 I. M. Lifschits editor, MIR (1982), pp. 129-236
!             (2) D. V. Livanov, M. Yu. Reizer and A. V. Sergeev,
!                       Sov. Phys. JETP 72, 760-764 (1991) -->  for sign
!                                                               correction
!
!  Note: this version valid for omega*tau << 1 and q*l << 1
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : BOHR,H_BAR,E,M_E
      USE PI_ETC,             ONLY : PI_INV
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE UTILITIES_1,        ONLY : D
      USE SCREENING_VEC,      ONLY : THOMAS_FERMI_VECTOR
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)              ::  U,Q,Q2,OM,DC,K3
      REAL (WP)              ::  NUM
!
      REAL (WP)              ::  REAL,AIMAG
!
      COMPLEX (WP)           ::  EPS,DEN
!
      U  = X * Z                                                    ! omega / q v_F
      Q  = TWO * X * KF_SI                                          ! q in SI
      Q2 = Q * Q                                                    !
      OM = U * Q * VF_SI                                            ! omega in SI
!
      DC = VF_SI * VF_SI * LFT / D('3D')                            ! diffusion coefficient
!
      K3 = FOUR * PI_INV * KF_SI / BOHR                             !
!
      NUM = K3 * DC                                                 ! ref. 1 eq. (3.4.18)
      DEN = DC * Q2 - IC * OM                                       !
!
      EPS = ONE - NUM / DEN                                         !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE RDF1_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE RDF2_EPS_D_LG_3D(X,Z,EPSR,EPSI)
!
!  This subroutine computes random delta-function electron-impurity
!    interaction form of the dielectric function for disordered 3D
!    conductors
!
!  Reference: (1) B. L. Altshuler, A. G. Aronov, D.E. Khmelnitskii and
!                 A. I. Larkin, in "Quantum Theory of Solids",
!                 I. M. Lifschits editor, MIR (1982), pp. 129-236
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE UTILITIES_1,        ONLY : D,DOS_EF
      USE COULOMB_K,          ONLY : COULOMB_FF
      USE DAMPING_SI
!
      USE UNITS,              ONLY : UNIT
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,VC
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q,OM,DC,N0,L,QL
!
      REAL (WP)             ::  SQRT,REAL,AIMAG
!
      COMPLEX (WP)          ::  EPS,ZETA,PI0
      COMPLEX (WP)          ::  NUM,DEN
!
      Q  = TWO * X * KF_SI                                          ! q in SI
      OM = Z * H_BAR * Q * Q * HALF / M_E                           ! omega in SI
!
      CALL COULOMB_FF('3D',UNIT,Q,ZERO,VC)                          ! Coulomb potential
!
      DC = VF_SI * VF_SI * LFT / D('3D')                            ! diffusion coefficient
      L  = SQRT(DC * LFT * D('3D'))                                 ! elastic MFP
      QL = Q * L                                                    !
!
!  Computing the density of states at Fermi level
!
      N0=DOS_EF('3D')                                               !
!
      NUM  = ONE - IC * (OM * LFT + QL)                             !
      DEN  = ONE - IC * (OM * LFT - QL)                             !
      ZETA = IC * HALF * CDLOG(NUM / DEN) / QL                      ! ref. (1), above
!
      PI0 = N0 * (ONE + IC * OM * LFT * (ZETA / (ONE - ZETA)))      !
!
      EPS = ONE - VC * PI0                                          !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE RDF2_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE RPA1_EPS_D_LG_3D(X,Z,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    RPA dielectric function for 3D systems
!
!  References: (1) J. Solyom, "Fundamental of the Physics of Solids",
!                              Vol3, Chap. 29, p. 61-138, Springer
!
!  Notation: hbar omega_q = hbar^2 q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  In the RPA case, we have
!
!                  EPS(RPA) = 1 - V_C * Pi_0   Pi_0 : RPA polarisability
!
!    which we will write as
!
!                  EPS(RPA) = 1 + ZZ * L       ZZ : (q_{TF}/q)^2
!                                              L  : Lindhard function
!
!    where q_{TF} is the Thomas-Fermi screening vector, and  EPS(TF) = 1 + ZZ
!    is the Thomas-Fermi dieclectric function.
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 18 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR
      USE CONSTANTS_P1,       ONLY : BOHR
      USE FERMI_SI,           ONLY : KF_SI
      USE PI_ETC,             ONLY : PI
      USE LINDHARD_FUNCTION,  ONLY : LINDHARD_D
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)              ::  LR,LI
      REAL (WP)              ::  Q_SI,ZZ
!
      Q_SI = TWO * X * KF_SI                                        !
!
!  Coefficient Z: (q_{TF}/q)^2   --> dimension-dependent
!
!
      ZZ = FOUR * KF_SI / (PI * BOHR * Q_SI * Q_SI)                 !
!
!  Calling the dynamic Lindhard function
!
      CALL LINDHARD_D(X,Z,'3D',LR,LI)                               !
!
!  Calculation of the RPA dielectric function
!
      EPSR = ONE + ZZ * LR                                          !
      EPSI = ZZ * LI                                                ! EPS(RPA) =  1 + ZZ * L
!
      END SUBROUTINE RPA1_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE RPA2_EPS_D_LG_3D(X,Z,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal temperature-dependent
!    RPA dielectric function EPS(q,omega,T) for 3D systems.
!
!  References: (1) M. Barriga-Carrasco, Phys. Rev. E 76, 016405 (2007)
!
!  Notation: hbar omega_q = hbar^2 q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * T        : temperature (SI)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Sep 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR,EIGHT,  &
                                     HALF,THIRD
      USE CONSTANTS_P1,       ONLY : BOHR,K_B
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PI_ETC,             ONLY : PI
      USE CHEMICAL_POTENTIAL, ONLY : MU
      USE EXT_FUNCTIONS,      ONLY : PDF
      USE INTEGRATION,        ONLY : INTEGR_L
!
      IMPLICIT NONE
!
      INTEGER               ::  IY
      INTEGER               ::  ID
      INTEGER, PARAMETER    ::  N_Y = 100
!
      REAL (WP)             ::  X,Z,T,U
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  BETA,D,KFA0,COEFR,COEFI
      REAL (WP)             ::  SMALL,LARGE,Z3
      REAL (WP)             ::  G1,G2,NUM,DEN
      REAL (WP)             ::  X1,X2,X12,X22
      REAL (WP)             ::  BMU
      REAL (WP)             ::  F1(N_Y),F2(N_Y)
      REAL (WP)             ::  Y,Y_STEP
!
      REAL (WP), PARAMETER  ::  Y_MAX = EIGHT
!
      REAL (WP)             ::  LOG,ABS,SQRT,REAL,EXP
!
      SMALL = 1.0E-1_WP                                             !
      LARGE = 1.0E+1_WP                                             !
!
      ID = 2                                                        !
!
      U  = X * Z                                                    ! omega / (q * v_F)
      Z3 = Z * Z * Z                                                !
!
      BETA  = ONE / (K_B * T)                                       !
      KFA0  = KF_SI * BOHR                                          ! dimensionless parameter
      D     = EF_SI * BETA                                          ! plasma degeneracy parameter
      COEFR = ONE / (FOUR * PI * Z3 * KFA0)                         !
      COEFI = ONE / (EIGHT * Z3 * KFA0)                              !
!
      BMU = BETA * MU('3D',T)                                       !
!
      X1  = U + Z                                                   !
      X2  = U - Z                                                   !
      X12 = X1 * X1                                                 !
      X22 = X2 * X2                                                 !
!
!  Calculation of G1 = g(u+z) and G2 = g(u-z)
!
      IF(D <= SMALL) THEN                                           ! ref. (1) eq. (8)
        G1 = X1 + HALF * (ONE - X12) *                            & ! g(u+z)
                  LOG(ABS((ONE + X1) / (ONE - X1)))                 !
        G2 = X2 + HALF * (ONE - X22) *                            & ! g(u-z)
                  LOG(ABS((ONE + X2) / (ONE - X2)))                 !
      ELSE IF(D >= LARGE) THEN                                      !
        G1 = TWO * THIRD * SQRT(D) * REAL(PDF(SQRT(D)*X1),KIND=WP)  ! ref. (1) eq. (9)
        G2 = TWO * THIRD * SQRT(D) * REAL(PDF(SQRT(D)*X2),KIND=WP)  ! ref. (1) eq. (9)
      ELSE                                                          !
        DO IY = 1, N_Y                                              !
          Y_STEP = Y_MAX / FLOAT(N_Y - 1)                           !
          Y      = FLOAT(IY - 1) * Y_STEP                           ! integration step
          F1(IY)  = Y * LOG(ABS((X1 + Y) / (X1 - Y))) /           & !
                       EXP(D * Y * Y - BMU)                         ! ref. (1) eq. (7)
          F2(IY)  = Y * LOG(ABS((X2 + Y) / (X2 - Y))) /           & !
                       EXP(D * Y * Y - BMU)                         !
        END DO                                                      !
        CALL INTEGR_L(F1,Y_STEP,N_Y,N_Y,G1,ID)                      !  g(u+z)
        CALL INTEGR_L(F2,Y_STEP,N_Y,N_Y,G2,ID)                      !  g(u-z)
      END IF                                                        !
!
      NUM = ONE + EXP(BMU - D * X22)                                !
      DEN = ONE + EXP(BMU - D * X12)                                !
!
      EPSR = ONE + COEFR * (G1 - G2)                                ! ref. (1) eq. (6)
      EPSI = COEFI * LOG(NUM / DEN) / D                             ! ref. (1) eq. (11)
!
      END SUBROUTINE RPA2_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE RPAP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    RPA dielectric function + STATIC local field corrections
!    for 3D systems
!
!  Notation: hbar omega_q = hbar^2 q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature (SI)
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 26 Apr 2021
!
!
      USE LF_VALUES
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR
      USE COMPLEX_NUMBERS,    ONLY : ONEC,IC
      USE CONSTANTS_P1,       ONLY : BOHR
      USE FERMI_SI,           ONLY : KF_SI
      USE PI_ETC,             ONLY : PI
      USE LINDHARD_FUNCTION,  ONLY : LINDHARD_D
      USE LOCAL_FIELD_STATIC
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
      REAL (WP)              ::  LR,LI
      REAL (WP)              ::  Q_SI,ZZ
      REAL (WP)              ::  GR
!
      COMPLEX (WP)           ::  GQ
      COMPLEX (WP)           ::  NUM,DEN
      COMPLEX (WP)           ::  EPS,EPS0
!
      Q_SI = TWO * X * KF_SI                                        !
!
!  Coefficient Z: (q_{TF}/q)^2   --> dimension-dependent
!
!
      ZZ = FOUR * KF_SI / (PI * BOHR * Q_SI * Q_SI)                 !
!
!  Calling the dynamic Lindhard function
!
      CALL LINDHARD_D(X,Z,'3D',LR,LI)                               !
!
!  Calling the local-field calculation
!
      CALL LOCAL_FIELD_STATIC_3D(X,RS,T,GQ_TYPE,GR)                 !
      GQ = CMPLX(GR)                                                !
!
!  Calculation of the RPA dielectric function
!
      EPSR = ONE + ZZ * LR                                          !
      EPSI = ZZ * LI                                                ! EPS(RPA) =  1 + ZZ * L
!
      EPS0 = EPSR + IC * EPSI                                       !
!
!  Computing the LFC dielectric function
!
      NUM = ONEC - EPS0                                             ! V_C * Pi_{RPA}
      DEN = ONEC + GQ * NUM                                         ! 1 + V_C * G * Pi_{RPA}
!
      EPS = ONEC - NUM / DEN                                        !
!
      EPSR =  REAL(EPS, KIND = WP)                                  !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE RPAP_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE UTIC_EPS_D_LG_3D(X,Z,T,RS,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions in 3D in the Utsumi-Ichimaru approximation
!
!  Reference: (1) K. Utsumi and S. Ichimaru,
!                    Phys. Rev. B 22, 1522-1533 (1980)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * T        : temperature in SI
!       * RS       : Wigner-Seitz radius (in units of a_0)
!
!  Intermediate parameters:
!
!       * SQ_TYPE  : static structure factor approximation (3D)
!       * GQ_TYPE  : local-field correction type (3D)
!       * IQ_TYPE  : type of approximation for I(q)
!                       IQ_TYPE  = 'IKP' Iwamoto-Krotscheck-Pines parametrization
!                       IQ_TYPE  = 'KU1'
!                       IQ_TYPE  = 'KU2'
!                       IQ_TYPE  = 'TWA'
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 23 Jun 2020
!
!
      USE REAL_NUMBERS,            ONLY : ZERO,ONE,TWO,FOUR,  &
                                          HALF
      USE COMPLEX_NUMBERS,         ONLY : IC
      USE CONSTANTS_P1,            ONLY : H_BAR,M_E
      USE FERMI_SI,                ONLY : KF_SI
      USE PI_ETC,                  ONLY : PI_INV
      USE UTILITIES_1,             ONLY : RS_TO_N0
      USE LF_VALUES,               ONLY : GQ_TYPE
      USE ENERGIES,                ONLY : EC_TYPE
      USE SF_VALUES,               ONLY : SQ_TYPE
      USE EXT_FUNCTIONS,           ONLY : PDF
      USE RELAXATION_TIME_STATIC,  ONLY : UTIC_RT_3D
      USE CALC_ENERGIES,           ONLY : ENERGIES_3D
      USE COULOMB_K,               ONLY : COULOMB_FF
      USE UTIC_PARAMETERS,         ONLY : UTIC_PARAM
      USE LOCAL_FIELD_STATIC
      USE DFUNC_STATIC
!
      USE UNITS,                   ONLY : UNIT
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Y,T,Y2,Z,V,RS
      REAL (WP)             ::  EPSR,EPSI,EPS0R,EPS0I
      REAL (WP)             ::  OMEGA,Q_SI,OMG0,VC,N0,COEF
      REAL (WP)             ::  GQ,TAU_Q,Q1,Q3,OM0,OMQ,OO
      REAL (WP)             ::  E_0,E_X,E_X_HF,E_C,E_XC
      REAL (WP)             ::  E_HF,E_GS,E_KIN,E_POT
!
      REAL (WP)             ::  DSQRT,DREAL,DIMAG
!
      COMPLEX (WP)          ::  EPS,OMB,OOB,NUM,DEN,QQO,QQ0
!
      Y=X+X                                                         ! Y = q / k_F
      Y2=Y*Y                                                        !
      V=Z*Y2                                                        ! omega / omega_{k_F}
!
      OMEGA=V*HALF*H_BAR*KF_SI*KF_SI/M_E                            ! omega
!
      Q_SI=Y*KF_SI                                                  !
      OMG0=HALF*H_BAR*Q_SI*Q_SI/M_E                                 ! ref. 1 eq. (2.6)
!
!  Computing the Coulomb potential
!
      CALL COULOMB_FF('3D',UNIT,Q_SI,ZERO,VC)                       !
!
!  Computing electron density
!
      N0=RS_TO_N0('3D',RS)                                          !
!
!  Computing the local-field correction
!
      CALL LOCAL_FIELD_STATIC_3D(X,RS,T,GQ_TYPE,GQ)                 !
!
!  Computing the UTIC relaxation time
!
      TAU_Q=UTIC_RT_3D(X,RS,T,SQ_TYPE,GQ_TYPE)                      !
!
!  Computing the UTIC parameters OMEGA(q) and OMEGA(0)
!
      CALL UTIC_PARAM(X,RS,T,OMQ,OM0)                               !
!
      OO=OMEGA/OMQ                                                  !
!
!  Coefficient \bar{omega}
!
      OMB=OMEGA+DSQRT(TWO*PI_INV)*(PDF(OO)-ONE) /(OO*TAU_Q)         ! ref. 1 eq. (3.13)
!
      OOB=OMB/OMEGA                                                 !
!
!  Computing the averaged kinetic energy per electron
!
      CALL ENERGIES_3D(X,EC_TYPE,RS,T,0,ZERO,E_0,E_X,E_X_HF,E_C,  & !
                       E_XC,E_HF,E_GS,E_KIN,E_POT)                  !
!
!  Coefficients Q1 and Q3
!
      Q1=N0*Q_SI*Q_SI/M_E                                           !
      Q3=Q1*(FOUR*E_KIN*OMG0/H_BAR + OMG0*OMG0)                     !
!
!  Susceptibility function Q(q,omega)
!
      QQO=Q1/(OMB*OMB) + Q3/(OMB*OMB*OMB*OMB)                       ! ref. 1 eq. (3.17)
!
!  Computing the RPA susceptibility Q(q,0)
!
      CALL DFUNCL_STATIC(X,'LRPA',EPS0R,EPS0I)                      !
      QQ0=ONE-(EPS0R+IC*EPS0I)/VC                                   ! ref. 1 eq. (3.15)
!
!  Computing eps(q,omega)
!
      NUM=VC*OOB*QQO                                                !
      DEN=ONE + (VC*OOB*GQ + (OOB-ONE)/QQ0)*QQO                     !
      EPS=ONE - NUM/DEN                                             ! ref. 1 eq. (3.12)
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END SUBROUTINE UTIC_EPS_D_LG_3D
!
!=======================================================================
!
      SUBROUTINE VLFP_EPS_D_LG_3D(X,Z,RS,T,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Vlasov-Fokker-Planck
!    dynamical dielectric function in 3D
!
!  References: (1) A. Selchow and K. Morawetz, Phys. Rev. E 59, 1015-1023 (1999)
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Y = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : system temperature in SI
!
!  Alternatively, the diffusion coefficient D can be used, with the
!    relation:
!                    TAU * D = K_B * T / M_E
!
!  Note:             lambda = 1 / tau                               ! ref. (1) eq. (7)
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,            ONLY : TWO
      USE COMPLEX_NUMBERS,         ONLY : ONEC,IC
      USE CONSTANTS_P1,            ONLY : M_E,K_B
      USE FERMI_SI,                ONLY : KF_SI,VF_SI
      USE SCREENING_VEC,           ONLY : DEBYE_VECTOR
      USE EXT_FUNCTIONS,           ONLY : CONHYP
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  U
      REAL (WP)              ::  Q_SI,OMG
      REAL (WP)              ::  KD_SI
      REAL (WP)              ::  AA,BB,Q2,RAT
!
      REAL (WP)              ::  REAL,IMAG
!
      COMPLEX (WP)           ::  EPS
      COMPLEX (WP)           ::  A,B,ZZ,COEF
!
      COMPLEX (WP)           ::  CMPLX
!
      U    = X * Z                                                  ! omega / (q * v_F)
      Q_SI = TWO * X * KF_SI                                        ! q     in SI
      OMG  = U * Q_SI * VF_SI                                       ! omega in SI
!
      Q2   = Q_SI * Q_SI                                            !
!
      CALL DEBYE_VECTOR('3D',T,RS,KD_SI)                            !
!
      RAT  = KD_SI * KD_SI / Q2
      AA   = K_B * T * TAU / M_E                                    ! k_B * T / (m * lambda)
      BB   = AA * Q2                                                !
      COEF = IC * OMG / (BB - IC * OMG)                             !
!
!  Parameters/arguments of 1F1
!
      A  = ONEC                                                     !
      B  = ONEC + CMPLX( (BB - IC * OMG) * TAU)                     !
      ZZ = CMPLX(BB * TAU)                                          !
!
      EPS = ONEC + RAT * (ONEC + COEF * CONHYP(A,B,ZZ,0,10))        ! ref. (1) eq. (27)
!
      EPSR = REAL(EPS,KIND=WP)                                      !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE VLFP_EPS_D_LG_3D
!
!=======================================================================
!
!    2) BL case (bilayer)
!
!=======================================================================
!
      SUBROUTINE DFUNCL_DYNAMIC_BL(X,Z,RS,T,D_FUNCL,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions in a bilayer
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * D_FUNCL  : type of longitudinal dielectric function (2D)
!
!
!  Intermediate parameters:
!
!       * DL       : distance between the two layers (SI)
!
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,TWO
      USE FERMI_SI,           ONLY : KF_SI
      USE MULTILAYER,         ONLY : DL
      USE UTILITIES_3,        ONLY : EPS_TO_PI
      USE COULOMB_K,          ONLY : COULOMB_FF
!
      USE UNITS,              ONLY : UNIT
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL
!
      REAL (WP)             ::  X,Z,RS,T,D
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  REPS,IEPS
      REAL (WP)             ::  PIR,PII
      REAL (WP)             ::  Q_SI,VC
!
      Q_SI = TWO * X * KF_SI                                        ! q
!
!  Computing the single layer dielectric function
!
      CALL DFUNCL_DYNAMIC_2D(X,Z,RS,T,D_FUNCL,REPS,IEPS)            !
!
!  Computing the single layer polarisability
!
      CALL COULOMB_FF('2D',UNIT,Q_SI,ZERO,VC)                       !
      CALL EPS_TO_PI(EPSR,EPSI,VC,PIR,PII)                          !
!
!  Computing the bilayer dielectric function
!
      CALL BILA_EPS_D_LG_2D(X,DL,PIR,PII,EPSR,EPSI)                 !
!
      END SUBROUTINE DFUNCL_DYNAMIC_BL
!
!=======================================================================
!
      SUBROUTINE BILA_EPS_D_LG_2D(X,DL,PIR,PII,EPSR,EPSI)
!
!  This subroutine computes the dielectric function of a bilayer system
!    It assumes that the two layers are identical
!
!  Reference: (1) S. Das Sarma and A. Madhukar, Phys. Rev. B 23,
!                    805-815 (1981)
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * DL       : distance between the two layers (SI)
!       * PIR      : real part of polarization of one layer
!       * PII      : imaginary part of polarization of one layer
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 19 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : E
      USE FERMI_SI,           ONLY : KF_SI
      USE MULTILAYER,         ONLY : EPS_1
      USE CONFINEMENT_FF
!
      IMPLICIT NONE
!
      REAL (WP)             :: X,DL,VC,PIR,PII
      REAL (WP)             :: EPSR,EPSI
      REAL (WP)             :: Q_SI
!
      REAL (WP)             :: DEXP,DREAL,DIMAG
!
      COMPLEX (WP)          :: PI,EPS
!
      Q_SI=TWO*X*KF_SI                                              ! q
!
!  Computing the intralayer Coulomb potential
!
      VC=E*E*CONFIN_FF(X)/(Q_SI*EPS_1)                              !
!
      PI=PIR+IC*PII                                                 !
!
      EPS=ONE - TWO*VC*PI + VC*PI*VC*PI*(ONE-DEXP(-TWO*Q_SI*DL))    ! ref. (1) eq. (12)
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END SUBROUTINE BILA_EPS_D_LG_2D
!
!=======================================================================
!
!    3) ML case (multilayers)
!
!=======================================================================
!
      SUBROUTINE DFUNCL_DYNAMIC_ML(X,Z,RS,T,D_FUNCL,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions in an infinite stacking of
!    (identical) layers
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * D_FUNCL  : type of longitudinal dielectric function (2D)
!
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : TWO
      USE CONSTANTS_P1,       ONLY : E
      USE FERMI_SI,           ONLY : KF_SI
      USE MULTILAYER,         ONLY : H_TYPE,D1,EPS_1
      USE UTILITIES_3,        ONLY : EPS_TO_PI
      USE CONFINEMENT_FF
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL
!
      REAL (WP)             ::  X,Z,RS,T
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  REPS,IEPS
      REAL (WP)             ::  PIR,PII
      REAL (WP)             ::  Q_SI,VC
!
      Q_SI=TWO*X*KF_SI                                              ! q
!
!  Computing the single layer dielectric function
!
      CALL DFUNCL_DYNAMIC_2D(X,Z,RS,T,D_FUNCL,REPS,IEPS)            !
!
!  Computing the intralayer Coulomb potential
!
      VC=E*E*CONFIN_FF(X)/(Q_SI*EPS_1)                              !
!
!  Computing the single layer polarisability
!
      CALL EPS_TO_PI(EPSR,EPSI,VC,PIR,PII)                          !
!
!  Computing the multilayer dielectric function
!
      IF(H_TYPE == 'MLA1') THEN                                     !
        CALL MLA1_EPS_D_LG_2D(X,PIR,PII,EPSR,EPSI)                  !
      ELSE IF (H_TYPE == 'MLA2') THEN                               !
        CALL MLA2_EPS_D_LG_2D(X,PIR,PII,EPSR,EPSI)                  !
      END IF                                                        !
!
      END SUBROUTINE DFUNCL_DYNAMIC_ML
!
!=======================================================================
!
      SUBROUTINE MLA1_EPS_D_LG_2D(X,PIR,PII,EPSR,EPSI)
!
!  This subroutine computes the dielectric function of a infinite
!    stacking of layers with one layer per unit cell.
!    It assumes that all layers are identical
!
!  Reference: (1) A. C. Sharma, Solid State Comm. 70, 1171-1174 (1989)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * PIR      : real part of polarization of one layer
!       * PII      : imaginary part of polarization of one layer
!
!  Intermediate parameters:
!
!       * DL       : size of stacking unit cell
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 16 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : E
      USE FERMI_SI,           ONLY : KF_SI
      USE MULTILAYER,         ONLY : DL,EPS_1
      USE CONFINEMENT_FF
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,VC,PIR,PII
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q_SI,SGN
!
      REAL (WP)             ::  DSINH,DCOSH,DREAL,DIMAG
!
      COMPLEX (WP)          ::  PI,EPS,AQ
!
      Q_SI=TWO*X*KF_SI                                              ! q in SI
!
!  Computing the intralayer Coulomb potential
!
      VC=E*E*CONFIN_FF(X)/(Q_SI*EPS_1)                              !
!
      PI=PIR+IC*PII                                                 !
!
      AQ=VC*PI*DSINH(Q_SI*DL) - DCOSH(Q_SI*DL)                      ! ref. 1 eq. (12)
!
      IF(DREAL(AQ) >= ZERO) THEN                                    !
        SGN=ONE                                                     !
      ELSE                                                          ! sign of Re [ AQ ]
        SGN=-ONE                                                    !
      END IF                                                        !
!
      EPS=CDSQRT(AQ*AQ-ONE) / (SGN*DSINH(Q_SI*DL))                  ! ref. 1 eq. (11)
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END SUBROUTINE MLA1_EPS_D_LG_2D
!
!=======================================================================
!
      SUBROUTINE MLA2_EPS_D_LG_2D(X,PIR,PII,EPSR,EPSI)
!
!  This subroutine computes the dielectric function of a infinite
!    stacking of layers with two layers per unit cell.
!    It assumes that all layers are identical
!
!  Reference: (1) A. C. Sharma, N. Chatuverdi and Y. M. Gupta,
!                    Physica C 209, 507-512 (1993)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * PIR      : real part of polarization of one layer
!       * PII      : imaginary part of polarization of one layer
!
!  Intermediate parameters:
!
!       * DL       : size of stacking unit cell
!       * D1       : distance between the two layers in the unit cell (SI)
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : E
      USE FERMI_SI,           ONLY : KF_SI
      USE MULTILAYER,         ONLY : DL,D1,EPS_1
      USE CONFINEMENT_FF
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,VC,PIR,PII
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q,DPR,FQ,SGN
!
      REAL (WP)             ::  DSINH,DCOSH,DREAL,DIMAG
!
      COMPLEX (WP)          ::  PI,EPS,HQ
!
      Q=TWO*X*KF_SI                                                 ! q in SI
!
!  Computing the intralayer Coulomb potential
!
      VC=E*E*CONFIN_FF(X)/(Q*EPS_1)                                 !
!
      DPR=TWO*D1-DL                                                 ! d'
      FQ=(DCOSH(Q*DL)-DCOSH(Q*DPR)) / DSINH(Q*DL)                   ! ref. (1) eq. (10)
!
      PI=PIR+IC*PII                                                 !
!
      HQ=DCOSH(Q*DL) - DSINH(Q*DL)*(TWO-VC*PI*FQ)*VC*PI             ! ref. (1) eq. (14)
!
      IF(DREAL(HQ) >= ZERO) THEN                                    !
        SGN=ONE                                                     !
      ELSE                                                          ! sign of Re [ HQ ]
        SGN=-ONE                                                    !
      END IF                                                        !
!
      EPS=CDSQRT(HQ*HQ-ONE) / (SGN*DSINH(Q*DL)*(ONE-VC*PI*FQ))      ! ref. 1 eq. (12)
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END
!
!=======================================================================
!
!    4) 2D case
!
!=======================================================================
!
      SUBROUTINE DFUNCL_DYNAMIC_2D(X,Z,RS,T,D_FUNCL,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions in 2D
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * D_FUNCL  : type of longitudinal dielectric function (2D)
!                      D_FUNCL = 'LAND' Landau parameter formulation
!                      D_FUNCL = 'PLPO' plasmon pole approximation
!                      D_FUNCL = 'RPA1' random phase approximation
!                      D_FUNCL = 'MER1' Mermin 1                     <-- damping
!                      D_FUNCL = 'HUCO' Hu-O'Connell                 <-- with loss
!                      D_FUNCL = 'NEVA' Nevalinna                    <-- with loss
!                      D_FUNCL = 'RDF1' Altshuler et al              <-- with loss
!                      D_FUNCL = 'RDF2' Sharma-Ashraf                <-- with loss
!
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 10 Aug 2021
!
!
      USE LF_VALUES,            ONLY : LANDAU
      USE PLASMON_DISPERSION
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL
!
      REAL (WP)             ::  X,Z,RS,T
      REAL (WP)             ::  EPSR,EPSI
!
      IF(D_FUNCL == 'LAND') THEN                                    !
        CALL LAND_EPS_D_LG_2D(X,Z,RS,LANDAU,EPSR,EPSI)              !
      ELSE IF(D_FUNCL == 'PLPO') THEN                               !
        CALL PLPO_EPS_D_LG_2D(X,Z,RS,T,PL_DISP,EPSR,EPSI)           !
      ELSE IF(D_FUNCL == 'RPA1') THEN                               !
        CALL RPA1_EPS_D_LG_2D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL == 'MER1') THEN                               !
        CALL MER1_EPS_D_LG_2D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL == 'HUCO') THEN                               !
        CALL HUCO_EPS_D_LG_2D(X,Z,RS,EPSR,EPSI)                     !
      ELSE IF(D_FUNCL == 'NEVA') THEN                               !
        CONTINUE                                                    !
      ELSE IF(D_FUNCL == 'RDF1') THEN                               !
        CALL RDF1_EPS_D_LG_2D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL == 'RDF2') THEN                               !
        CALL RDF2_EPS_D_LG_2D(X,Z,EPSR,EPSI)                        !
      END IF                                                        !
!
      END SUBROUTINE DFUNCL_DYNAMIC_2D
!
!=======================================================================
!
      SUBROUTINE LAND_EPS_D_LG_2D(X,Z,RS,LANDAU,EPSR,EPSI)
!
!  This subroutine computes the dielectric function EPS(q,omega)
!    in 2D systems in terms of Landau's parameters.
!
!  References: (1) E. Lipparini, "Modern Many-Particle Physics - Atomic Gases,
!                   Quantum Dots and Quantum Fluids", World Scientific (2003)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : dimensionless factor
!       * LANDAU   : model chosen for the calculation of the parameters
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!
!                                           Last modified : 17 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,HALF,THIRD,FOURTH
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : E,EPS_0
      USE FERMI_SI,           ONLY : KF_SI
      USE UTILITIES_1,        ONLY : DOS_EF
      USE CHEMICAL_POTENTIAL, ONLY : MU_RS
      USE ENERGIES,           ONLY : EC_TYPE
      USE LANDAU_PARAM
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  LANDAU
!
      REAL (WP)             ::  X,Z,RS
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q_SI
      REAL (WP)             ::  U,NU0,MU,V_C
      REAL (WP)             ::  F0S,F0A,F1S,F1A,F2S,F2A
!
      REAL (WP)             ::  DSQRT,DREAL,DIMAG
!
      COMPLEX (WP)          ::  EPS,CHIS,G00,G20,G22
      COMPLEX (WP)          ::  NUM,DEN,NU1,DE1
!
      U=X*Z                                                         ! omega / (q * v_F)
      Q_SI=TWO*X*KF_SI                                              ! q in SI
      NU0=DOS_EF('2D')                                              ! DoS at Fermi level
!
!  Computing the Coulomb potential
!
      V_C=HALF*E*E/(EPS_0*Q_SI)                                     !
!
!  Computing the chemical potential
!
      MU=MU_RS(RS,EC_TYPE)                                          !
!
!  Computing the Landau parameters using chemical potential
!
      CALL LANDAU_PARAMETERS_2D(RS,LANDAU,MU,1,                 &   !
                                F0S,F0A,F1S,F1A,F2S,F2A)            !
!
!  Calculation of the coefficients Gamma_{l,l'}
!
      IF(U <= ONE) THEN                                             !
        G00=ONE + IC*U/DSQRT(ONE-U*U)                               !
      ELSE                                                          ! ref. 1 eq. (8.53)
        G00=ONE   -  U/DSQRT(U*U-ONE)                               !
      END IF                                                        !
!
      G20=ONE + (TWO*U*U-ONE)*G00                                   !
      G22=HALF+ (TWO*U*U-ONE)*G20                                   ! ref. 1 eq. (8.54)
!
      NU1=(ONE+HALF*F1S)*(ONE+FOURTH*F2S)*G20                       !
      DE1=TWO*(G00 + HALF*F2S*(G22*G00-G20*G20))                    !
      NUM=HALF*NU0*(ONE+HALF*F1S)                                   !
      DEN=U*U - HALF*(ONE+HALF*F1S)*(ONE+F0S) - NU1/DE1             !
!
      CHIS=NUM/DEN                                                  ! ref. 1 eq. (8.60)
!
      EPS=ONE/(ONE+V_C*CHIS)                                        !
!
      EPSR=DREAL(EPS)                                               !
      EPSI=DIMAG(EPS)                                               !
!
      END SUBROUTINE LAND_EPS_D_LG_2D
!
!=======================================================================
!
      SUBROUTINE PLPO_EPS_D_LG_2D(X,Z,RS,T,PL_DISP,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic plasmon pole
!    dielectric function for 2D systems
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * PL_DISP  : type of analytical plasmon dispersion
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Nov 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,FOUR
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PLASMON_DISP_REAL
      USE PLASMON_ENE_SI
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 7)    ::  PL_DISP
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS,T
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  ENE_SI,ENE_P_Q
      REAL (WP)              ::  Q_SI
      REAL (WP)              ::  NUM,DEN,EPS
!
      ENE_SI = FOUR * X * X * Z * EF_SI                             ! hbar omega
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
!
!  Calculation of the analytical plasmon dispersion
!
      CALL PLASMON_DISP_2D(X,RS,T,PL_DISP,ENE_P_Q)                  ! hbar omega(q)
!
      NUM = ENE_P_SI * ENE_P_SI * Q_SI                              !
      DEN = ENE_SI * ENE_SI + NUM - ENE_P_Q * ENE_P_Q               !
!
      EPS = ONE - NUM / DEN                                         !
!
      EPSR = EPS                                                    !
      EPSI = ZERO                                                   !
!
      END SUBROUTINE PLPO_EPS_D_LG_2D
!
!=======================================================================
!
      SUBROUTINE RPA1_EPS_D_LG_2D(X,Z,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    RPA dielectric function for 2D systems
!
!  References: (1) J. Solyom, "Fundamental of the Physics of Solids",
!                        Vol3, Chap. 29, p. 61-138, Springer
!
!  Notation: hbar omega_q = hbar^2 q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  In the RPA case, we have
!
!                  EPS(RPA) = 1 - V_C * Pi_0   Pi_0 : RPA polarisability
!
!    which we will write as
!
!                  EPS(RPA) = 1 + ZZ * L       ZZ: q_{TF} / q
!                                              L : Lindhard function
!
!    where q_{TF} is the Thomas-Fermi screening vector, and  EPS(TF) = 1 + ZZ
!    is the Thomas-Fermi dieclectric function.
!
!
!  Note: There is a misprint in eq. (29.5.2) of ref. (1) :
!
!        4 pi e^2 / q^2 should be replaced by 2 pi e^2 / q
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 16 Oct 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,EIGHT
      USE CONSTANTS_P1,       ONLY : BOHR
      USE FERMI_SI,           ONLY : KF_SI
      USE SCREENING_VEC,      ONLY : THOMAS_FERMI_VECTOR
      USE LINDHARD_FUNCTION,  ONLY : LINDHARD_D
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  LR,LI
      REAL (WP)             ::  Q_SI,K_TF_SI,ZZ
!
      Q_SI = TWO * X * KF_SI                                        !
!
!  Coefficient ZZ: (q_{TF}/q)^2   --> dimension-dependent
!
      CALL THOMAS_FERMI_VECTOR('2D',K_TF_SI)                        !
      ZZ = K_TF_SI / Q_SI                                           !
!
!  Calling the dynamic Lindhard function
!
      CALL LINDHARD_D(X,Z,'2D',LR,LI)                               !
!
!  Calculation of the RPA dielectric function
!
      EPSR = ONE + ZZ * LR                                          !
      EPSI = ZZ * LI                                                ! EPS(RPA) =  1 + ZZ * L
!
      END SUBROUTINE RPA1_EPS_D_LG_2D
!
!=======================================================================
!
      SUBROUTINE MER1_EPS_D_LG_2D(X,Z,EPSR,EPSI)
!
!  This subroutine computes the longitudinal Mermin dynamical
!     dielectric function in 2D
!
!  References: (1) H. B. Nersiyan and A. K. Das, Phys. Rev. E 80, 016402 (2009)
!
!  Note: for TAU --> infinity, we recover the RPA values
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Intermediate parameters:
!
!       * U        : dimensionless factor   --> U = omega / q v_F
!       * TAU      : relaxation time (used for damping)  in SI
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!  Note: in order to be more general, we use EPS_B (background
!        dielectric constant) instead of 1 (vacuum case)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 10 Aug 2021
!
!
      USE MATERIAL_PROP,      ONLY : EPS_B
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE SQUARE_ROOTS,       ONLY : SQR2
      USE CONSTANTS_P1,       ONLY : BOHR,H_BAR
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
!
      USE DFUNC_STATIC,       ONLY : RPA1_EPS_S_LG
      USE DAMPING_SI,         ONLY : TAU
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN) ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  U,X2
      REAL (WP)             ::  CHI2,COEF,KOEF
      REAL (WP)             ::  REPSM1,IEPSM1
      REAL (WP)             ::  REPS00
      REAL (WP)             ::  EPS0R,EPS0I
      REAL (WP)             ::  GAMMA,GAMMA2
      REAL (WP)             ::  UP,UM,UP2,UM2
      REAL (WP)             ::  NU1,NU2,DEN
      REAL (WP)             ::  YPP,YPM,YMP,YMM
      REAL (WP)             ::  F1,F2
!
      REAL (WP)             ::  SQRT,REAL,AIMAG
!
      COMPLEX (WP)          ::  NUMI,DENI,EPS
!
      X2 = X *  X                                                   !
!
      U      = X * Z                                                ! omega / (q * v_F)
      CHI2   = ONE / (KF_SI * BOHR)                                 !
      GAMMA  = H_BAR / (FOUR * EF_SI * TAU)                         !
      GAMMA2 = GAMMA * GAMMA                                        !
!
      COEF = HALF * CHI2 / X2                                       !
      KOEF = HALF * SQR2                                            ! 1 / sqrt(2)
!
      UP = U + X                                                    ! U_+
      UM = U - X                                                    ! U_-
!
      UP2 = UP * UP                                                 !
      UM2 = UM * UM                                                 !
!
      NU1 = X2 * (UP + ONE) * (UP + ONE) + GAMMA2                   !
      NU2 = X2 * (UP2 - ONE) +  GAMMA2                              ! ref. (1) eq. (5)
      DEN = X2 * (UP - ONE) * (UP - ONE) + GAMMA2                   !
!
      YPP = KOEF * SQRT( SQRT(NU1 / DEN) + NU2 / DEN )              ! Y_+(z,U_+)
      YMP = KOEF * SQRT( SQRT(NU1 / DEN) - NU2 / DEN )              ! Y_-(z,U_+)
!
      NU1 = X2 * (UM + ONE) * (UM + ONE) + GAMMA2                   !
      NU2 = X2 * (UM2 - ONE) +  GAMMA2                              ! ref. (1) eq. (5)
      DEN = X2 * (UM - ONE) * (UM - ONE) + GAMMA2                   !
!
      YPM = KOEF * SQRT( SQRT(NU1 / DEN) + NU2 / DEN )              ! Y_+(z,U_-)
      YMM = KOEF * SQRT( SQRT(NU1 / DEN) - NU2 / DEN )              ! Y_-(z,U_-)
!
      F1 = TWO * X + GAMMA * (YMM - YMP) / X +                    & ! ref. (1) eq. (3)
                     (UM - ONE) * YPM -                           & !
                     (UP - ONE) * YPP                               !
!
      F2 = GAMMA * (YPM - YPP) / X +                              & ! ref. (1) eq. (4)
           (UP - ONE) * YMP -                                     & !
           (UM - ONE) * YMM                                         !
!
! Computation of EPS_{RPA}(x,u,Gamma) - 1
!
      REPSM1 = COEF * F1                                            ! ref. (1) eq. (2)
      IEPSM1 = COEF * F2                                            !
!
! Computation of EPS_{RPA}(x,0) - EPS_B
!
      CALL RPA1_EPS_S_LG(X,'2D',EPS0R,EPS0I)                        ! EPS_{RPA}(x,0)
!
      REPS00 = EPS0R - EPS_B                                        ! EPS_{RPA}(x,0) - EPS_B
!
      NUMI = (X * U + IC * GAMMA) * (REPSM1 + IC * IEPSM1)          !
      DENI =  X * U + IC * GAMMA  * (REPSM1 + IC * IEPSM1) / REPS00 !
!
      EPS = EPS_B + NUMI / DENI                                     ! ref. (1) eq. (1)
!
      EPSR = REAL(EPS,KIND=WP)                                      !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE MER1_EPS_D_LG_2D
!
!=======================================================================
!
      SUBROUTINE HUCO_EPS_D_LG_2D(X,Z,RS,EPSR,EPSI)
!
! This subroutine computes the Hu-O'Connell dielectric function that
!  including damping effect through electron-electron and electron-impurity
!  fluctuation, leading to a diffusion coefficient D, for 2D systems
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = hbar omega / E_F
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * D        : diffusion coefficient                        (in SI)
!
!
!  Output variables :
!
!       * EPSR     : real part of the dielectric function at q
!       * EPSI     : imaginary part of the dielectric function at q
!
!   Reference :  (1) G. Y. Hu and R. F. O'Connell,
!                        J. Phys. C: Solid State Phys. 21, 4325-4331 (1988)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,FOUR,FOURTH
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E
      USE SQUARE_ROOTS,       ONLY : SQR2
      USE FERMI_SI,           ONLY : KF_SI
      USE SCREENING_VEC,      ONLY : THOMAS_FERMI_VECTOR
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP), INTENT(IN)  ::  X,Z,RS
      REAL (WP), INTENT(OUT) ::  EPSR,EPSI
!
      REAL (WP)              ::  U
      REAL (WP)              ::  Q_SI,KTF_SI
      REAL (WP)              ::  FF
      REAL (WP)              ::  KOQ
      REAL (WP)              ::  COEF,KOEF
      REAL (WP)              ::  B,NUP,NUM
      REAL (WP)              ::  NP2,NM2
      REAL (WP)              ::  SIP,SIM
      REAL (WP)              ::  SP2,SM2
      REAL (WP)              ::  BX,B2X2
      REAL (WP)              ::  OBXP,OBXM
      REAL (WP)              ::  FBNP,FBNM
      REAL (WP)              ::  SQP1,SQM1
      REAL (WP)              ::  SQP2,SQM2
!
      REAL (WP)              ::  SIGN,SQRT
!
      U    = X * Z                                                  ! omega / (q * v_F)
      Q_SI = TWO * KF_SI * X                                        ! q in SI
!
      FF = ONE                                                      !
!
!  Computing the Thomas-Fermi vector
!
      CALL THOMAS_FERMI_VECTOR('3D',KTF_SI)                         !
!
      KOQ = KTF_SI  / Q_SI                                          !
!
      COEF = FF * KOQ                                               !
      KOEF = FF * KOQ / (TWO * SQR2 * X)                            !
!
!  Setting the Hu-O'Connell parameters
!
      B   = TWO * M_E * DIF / H_BAR                                 ! \
      NUP = X + U                                                   !  > ref. (1) eq. (8)
      NUM = X - U                                                   ! /
!
      NP2 = NUP * NUP                                               !
      NM2 = NUM * NUM                                               !
!
      SIP = SIGN(ONE,NUP)                                           !
      SIM = SIGN(ONE,NUM)                                           !
!
      SP2 = SIP / (TWO * SQR2 * X)                                  !
      SM2 = SIM / (TWO * SQR2 * X)                                  !
!
      BX   = B * X                                                  !
      B2X2 = BX * BX                                                !
!
      OBXP = ONE + B2X2 - NP2                                       !
      OBXM = ONE + B2X2 - NM2                                       !
!
      FBNP = FOUR * B2X2 * NP2                                      !
      FBNM = FOUR * B2X2 * NM2                                      !
!
      SQP1 = SQRT( SQRT(OBXP**2 + FBNP) - OBXP )                    !
      SQM1 = SQRT( SQRT(OBXM**2 + FBNM) - OBXM )                    !
      SQP2 = SQRT( SQRT(OBXP**2 + FBNP) + OBXP )                    !
      SQM2 = SQRT( SQRT(OBXM**2 + FBNM) + OBXM )                    !
!
!  Real part of epsilon
!
      EPSR = ONE + COEF * ( ONE -  SM2 * SQM1 -  SP2 * SQP1  )      !
!
!  Imaginary part of epsilon
!
!
      EPSI = KOEF * ( SQM2 - SQP2 )                                 !
!
      END SUBROUTINE HUCO_EPS_D_LG_2D
!
!=======================================================================
!
      SUBROUTINE RDF1_EPS_D_LG_2D(X,Z,EPSR,EPSI)
!
!  This subroutine computes random delta-function electron-impurity
!    interaction form of the dielectric function for disordered 2D
!    conductors
!
!  Reference: (1) B. L. Altshuler, A. G. Aronov, D.E. Khmelnitskii and
!                 A. I. Larkin, in "Quantum Theory of Solids",
!                 I. M. Lifschits editor, MIR (1982), pp. 129-236
!             (2) D. V. Livanov, M. Yu. Reizer and A. V. Sergeev,
!                       Sov. Phys. JETP 72, 760-764 (1991) -->  for sign
!                                                               correction
!
!  Note: this version valid for omega*tau << 1 and q*l << 1
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE SCREENING_VEC,      ONLY : THOMAS_FERMI_VECTOR
      USE UTILITIES_1,        ONLY : D
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q,Q2,OM,DC
      REAL (WP)             ::  K_TF,NUM
!
      REAL (WP)             ::  REAL,AIMAG
!
      COMPLEX (WP)          ::  EPS,DEN
!
      Q  = TWO * X * KF_SI                                          ! q in SI
      Q2 = Q * Q                                                    !
      OM = Z * H_BAR * Q * Q * HALF / M_E                           ! omega in SI
!
      DC = VF_SI * VF_SI * LFT / D('2D')                            ! diffusion coefficient
!
!  Computing the Thomas-Fermi screening vector                      !
!
      CALL THOMAS_FERMI_VECTOR('2D',K_TF)                           !
!
      NUM = DC * Q * K_TF                                           ! ref. 1 eq. (3.4.19)
      DEN = DC * Q2 - IC * OM                                       !
!
      EPS = ONE + NUM / DEN                                         !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE RDF1_EPS_D_LG_2D
!
!=======================================================================
!
      SUBROUTINE RDF2_EPS_D_LG_2D(X,Z,EPSR,EPSI)
!
!  This subroutine computes random delta-function electron-impurity
!    interaction form of the dielectric function for disordered 2D
!    conductors
!
!  Reference: (1) A. C. Sharma and S. S. Z. Ashraf,
!                    J. Phys.: Condens. Matter 16, 3117 (2004)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,HALF
      USE COMPLEX_NUMBERS,    ONLY : IC
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E
      USE FERMI_SI,           ONLY : KF_SI,VF_SI
      USE UTILITIES_1,        ONLY : D,DOS_EF
      USE COULOMB_K,          ONLY : COULOMB_FF
!
      USE UNITS,              ONLY : UNIT
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,VC
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q,OM,DC,N0,L,QL
!
      REAL (WP)             ::  SQRT,REAL,AIMAG
!
      COMPLEX (WP)          ::  EPS,ZETA,PI0
!
      COMPLEX (WP)          ::  CDSQRT
!
      Q  = TWO * X * KF_SI                                          ! q in SI
      OM = Z * H_BAR * Q * Q * HALF / M_E                           ! omega in SI
!
      CALL COULOMB_FF('2D',UNIT,Q,ZERO,VC)                          !
!
      DC = VF_SI * VF_SI * LFT / D('2D')                            ! diffusion coefficient
      L  = SQRT(DC * LFT * D('2D'))                                 ! elastic MFP
      QL = Q * L                                                    !
!
!  Computing the density of states at Fermi level
!
      N0 = DOS_EF('2D')                                             !
!
      ZETA = ONE / CDSQRT((ONE - IC * OM * LFT)**2 + QL * QL)       !  eq. (3.4.11a)
!
      PI0 = N0 * (ONE + IC * OM * LFT * (ZETA / (ONE - ZETA)))      !
!
      EPS = ONE - VC * PI0                                          !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE RDF2_EPS_D_LG_2D
!
!=======================================================================
!
!    5) Q1D case
!
!=======================================================================
!
      SUBROUTINE DFUNCL_DYNAMIC_Q1(X,Z,D_FUNCL,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions in Q1D
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * D_FUNCL  : type of longitudinal dielectric function (1D)
!                      D_FUNCL = 'HUCO'  Hu-O'Connell
!
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE PLASMON_DISPERSION
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL
!
      REAL (WP)             ::  X,Z,RS,T
      REAL (WP)             ::  EPSR,EPSI
!
      IF(D_FUNCL.EQ.'HUCO') THEN                                    !
        CALL HUCO_EPS_D_LG_Q1(X,Z,EPSR,EPSI)                        !
      END IF                                                        !
!
      END SUBROUTINE DFUNCL_DYNAMIC_Q1
!
!=======================================================================
!
      SUBROUTINE HUCO_EPS_D_LG_Q1(X,Z,EPSR,EPSI)
!
! This subroutine computes the Hu-O'Connell dielectric function that
!  including damping effect through electron-electron and electron-impurity
!  fluctuation, leading to a diffusion coefficient D, for Q1D systems
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = hbar omega / E_F
!       * D        : diffusion coefficient                        (in SI)
!
!
!  Output variables :
!
!       * EPSR     : real part of the dielectric function at q
!       * EPSI     : imaginary part of the dielectric function at q
!
!   Reference :  (1) G. Y. Hu and R. F. O'Connell, J. Phys. C: Condens.
!                       Matter 2, 9381-9397 (1990)
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE MATERIAL_PROP,      ONLY : MSOM
      USE CONFIN_VAL,         ONLY : OM0,CONFIN
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,HALF
      USE CONSTANTS_P1,       ONLY : H_BAR,M_E
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PI_ETC,             ONLY : PI
      USE COULOMB_K
!
      USE UNITS,              ONLY : UNIT
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  A,B,XX,Y,B1,B2
      REAL (WP)             ::  NU_P(0:1),NU_M(0:1)
      REAL (WP)             ::  Q_SI,MS
      REAL (WP)             ::  COEF,V_C
!
      REAL (WP)             ::  DSQRT,DREAL,DIMAG
!
      COMPLEX (WP)          ::  IC
      COMPLEX (WP)          ::  NUM,DEN,CHI,EPS
!
      Q_SI = TWO * X * KF_SI                                        ! q in SI
      MS   = MSOM * M_E                                             ! m*
!
      COEF = - MS / (PI * Q_SI)                                     !
!
!  Computing the Coulomb potential
!
      CALL COULOMB_FF('Q1',UNIT,Q_SI,ZERO,V_C)                      !
!
!  Setting the Hu-O'Connell parameters
!
      B  = SQRT( H_BAR / (MS * OM0) )                               !
      A  = TWO * MSOM * MS * DIF / H_BAR                            !    ref. (1) eq. (3.3)
      XX = B * Q_SI                                                 !  \ ref. (1) eq. (3.4)
      Y  = Z * EF_SI / H_BAR                                        !  /
!
      NU_P(0) =         Y / XX + HALF * X                           ! \
      NU_P(1) = (Y - ONE) / XX + HALF * X                           !  \
      NU_M(0) =          Y/ XX - HALF * X                           !  / ref. (1) eq. (3.4)
      NU_M(1) = (Y - ONE) / XX - HALF * X                           ! /
!
      B1 = B * SQRT(TWO * MS * (EF_SI - H_BAR * OM0)) / H_BAR       ! \ ref. (1) eq. (3.3)
      B2 = B * SQRT(TWO * MS * (EF_SI - ONE * H_BAR * OM0)) / H_BAR ! /
!
      IF(CONFIN == 'HC-1111') THEN                                  !
        NUM = (B1 - NU_M(0) - IC * HALF * A * XX) *              &  !
              (B1 + NU_P(0) + IC * HALF * A * XX)                   !
        DEN = (B1 + NU_M(0) + IC * HALF * A  *XX) *              &  !
              (B1 - NU_P(0) - IC * HALF * A * XX)                   !
        CHI = COEF * CDLOG(NUM / DEN)                               !
        EPS = ONE - CHI * V_C                                       !
      ELSE IF(CONFIN == 'HC-1122') THEN                             !
        NUM = (B1 - NU_M(0) - IC * HALF * A * XX) *              &  !
              (B1 + NU_P(0) + IC * HALF * A * XX)                   !
        DEN = (B1 + NU_M(0) + IC * HALF * A * XX) *              &  !
              (B1 - NU_P(0) - IC * HALF * A * XX)                   !
        CHI = COEF * CDLOG(NUM / DEN)                               !
        EPS = - CHI * V_C                                           !
      ELSE IF(CONFIN == 'HC-1221') THEN                             !
        NUM = (B1 - NU_M(1) - IC * HALF * A * XX) *              &  !
              (B2 + NU_P(1) + IC * HALF * A * XX)                   !
        DEN = (B1 + NU_M(1) + IC * HALF * A * XX) *              &  !
              (B2 - NU_P(1) - IC * HALF * A * XX)                   !
        CHI = COEF * CDLOG(NUM / DEN)                               !
        EPS = -CHI * V_C                                            !
      ELSE IF(CONFIN == 'HC-2222') THEN                             !
        NUM = (B2 - NU_M(0) - IC * HALF * A * XX) *              &  !
              (B2 + NU_P(0) + IC * HALF * A * XX)                   !
        DEN = (B2 + NU_M(0) + IC * HALF * A * XX) *              &  !
              (B2 - NU_P(0) - IC * HALF * A * XX)                   !
        CHI = COEF * CDLOG(NUM / DEN)                               !
        EPS = ONE - CHI * V_C                                       !
      END IF                                                        !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE HUCO_EPS_D_LG_Q1
!
!=======================================================================
!
!    6) 1D case
!
!=======================================================================
!
      SUBROUTINE DFUNCL_DYNAMIC_1D(X,Z,RS,T,D_FUNCL,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    dielectric functions in 1D
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * D_FUNCL  : type of longitudinal dielectric function (1D)
!                      D_FUNCL = 'RPA1' random phase approximation
!                      D_FUNCL = 'PLPO' plamson pole approximation
!                      D_FUNCL = 'RDF1'  Altshuler et al model
!                      D_FUNCL = 'RDF2'  Sharma-Ashraf model
!
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE PLASMON_DISPERSION
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL
!
      REAL (WP)             ::  X,Z,RS,T
      REAL (WP)             ::  EPSR,EPSI
!
      IF(D_FUNCL == 'RPA1') THEN                                    !
        CALL RPA1_EPS_D_LG_1D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL == 'PLPO') THEN                               !
        CALL PLPO_EPS_D_LG_1D(X,Z,RS,T,PL_DISP,EPSR,EPSI)           !
      ELSE IF(D_FUNCL.EQ.'RDF1') THEN                               !
        CALL RDF1_EPS_D_LG_1D(X,Z,EPSR,EPSI)                        !
      ELSE IF(D_FUNCL.EQ.'RDF2') THEN                               !
        CALL RDF2_EPS_D_LG_1D(X,Z,EPSR,EPSI)                        !
      END IF                                                        !
!
      END SUBROUTINE DFUNCL_DYNAMIC_1D
!
!=======================================================================
!
      SUBROUTINE RPA1_EPS_D_LG_1D(X,Z,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic
!    RPA dielectric function for 1D systems
!
!  References: (1) J. Solyom, "Fundamental of the Physics of Solids",
!                        Vol3, Chap. 29, p. 61-138, Springer
!
!  Notation: hbar omega_q = hbar^2 q^2 / 2m
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  In the RPA case, we have
!
!                  EPS(RPA) = 1 - V_C * Pi_0   Pi_0 : RPA polarisability
!
!    which we will write as
!
!                  EPS(RPA) = 1 + ZZ * L       ZZ: (q_{TF}/q)^2
!                                              L : Lindhard function
!
!    where q_{TF} is the Thomas-Fermi screening vector, and  EPS(TF) = 1 + ZZ
!    is the Thomas-Fermi dieclectric function.
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Jun 2020
!
!
      USE REAL_NUMBERS,       ONLY : ONE,TWO,EIGHT
      USE CONSTANTS_P1,       ONLY : BOHR
      USE FERMI_SI,           ONLY : KF_SI
      USE SCREENING_VEC,      ONLY : THOMAS_FERMI_VECTOR
      USE LINDHARD_FUNCTION,  ONLY : LINDHARD_D
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  LR,LI
      REAL (WP)             ::  Q_SI,K_TF_SI,ZZ
!
      Q_SI = TWO * X * KF_SI                                        !
!
!  Coefficient ZZ: (q_{TF}/q)^2   --> dimension-dependent
!
      CALL THOMAS_FERMI_VECTOR('1D',K_TF_SI)                        !
      ZZ = (K_TF_SI/Q_SI)**2                                        !
!
!  Calling the dynamic Lindhard function
!
      CALL LINDHARD_D(X,Z,'1D',LR,LI)                               !
!
!  Calculation of the RPA dielectric function
!
      EPSR = ONE + ZZ * LR                                          !
      EPSI = ZZ * LI                                                ! EPS(RPA) =  1 + ZZ * L
!
      END SUBROUTINE RPA1_EPS_D_LG_1D
!
!=======================================================================
!
      SUBROUTINE PLPO_EPS_D_LG_1D(X,Z,RS,T,PL_DISP,EPSR,EPSI)
!
!  This subroutine computes the longitudinal dynamic plasmon pole
!    dielectric function for 1D systems
!
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * PL_DISP  : type of analytical plasmon dispersion
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!  Notation: hbar omega_q = hbar q^2 / 2m
!
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 22 Jul 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,ONE,TWO,FOUR
      USE FERMI_SI,           ONLY : EF_SI,KF_SI
      USE PLASMON_DISP_REAL,  ONLY : PLASMON_DISP_1D
      USE PLASMON_ENE_SI
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 7)   ::  PL_DISP
!
      REAL (WP)             ::  X,Z,RS,T
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  ENE_SI,ENE_P_Q,EPS
!
      ENE_SI=FOUR*X*X*Z*EF_SI                                       ! hbar omega
!
!  Calculation of the analytical plasmon dispersion
!
      CALL PLASMON_DISP_1D(X,RS,T,PL_DISP,ENE_P_Q)                  ! hbar omega(q)
!
      EPS=ONE-ENE_P_SI*ENE_P_SI/(ENE_SI*ENE_SI+ENE_P_SI*ENE_P_SI - &!
                                 ENE_P_Q*ENE_P_Q)                   !
!
      EPSR=EPS                                                      !
      EPSI=ZERO                                                     !
!
      END SUBROUTINE PLPO_EPS_D_LG_1D
!
!=======================================================================
!
      SUBROUTINE RDF1_EPS_D_LG_1D(X,Z,EPSR,EPSI)
!
!  This subroutine computes random delta-function electron-impurity
!    interaction form of the dielectric function for disordered 1D
!    conductors
!
!  Reference: (1) B. L. Altshuler, A. G. Aronov, D.E. Khmelnitskii and
!                 A. I. Larkin, in "Quantum Theory of Solids",
!                 I. M. Lifschits editor, MIR (1982), pp. 129-236
!             (2) D. V. Livanov, M. Yu. Reizer and A. V. Sergeev,
!                       Sov. Phys. JETP 72, 760-764 (1991) -->  for sign
!                                                               correction
!
!  Note: this version valid for omega*tau << 1 and q*l << 1
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,     ONLY : ONE,TWO,HALF
      USE COMPLEX_NUMBERS,  ONLY : IC
      USE CONSTANTS_P1,     ONLY : H_BAR,M_E,E,COULOMB
      USE FERMI_SI,         ONLY : KF_SI,VF_SI
      USE UTILITIES_1,      ONLY : D,DOS_EF
      USE SCREENING_VEC,    ONLY : THOMAS_FERMI_VECTOR
      USE CONFIN_VAL,       ONLY : R0
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q,Q2,OM,DC,N0
      REAL (WP)             ::  K_TF,NUM
!
      REAL (WP)             ::  LOG,REAL,AIMAG
!
      COMPLEX (WP)          ::  EPS,DEN
!
      Q  = TWO * X * KF_SI                                          ! q in SI
      Q2 = Q * Q                                                    !
      OM = Z * H_BAR * Q2 * HALF / M_E                              ! omega in SI
!
      DC = VF_SI * VF_SI * LFT / D('3D')                            ! diffusion coefficient
!
!  Computing the density of states at Fermi level
!
      N0 = DOS_EF('3D')                                             !
!
!  Computing the Thomas-Fermi screening vector                      !
!
      CALL THOMAS_FERMI_VECTOR('3D',K_TF)                           !
!
      NUM = DC * Q2 * N0 * E * E * COULOMB * LOG(ONE / (Q2 * R0*R0))! ref. 2 eq. (26)
      DEN = DC * Q2 - IC * OM                                       !
!
      EPS = ONE + NUM / DEN                                         !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE RDF1_EPS_D_LG_1D
!
!=======================================================================
!
      SUBROUTINE RDF2_EPS_D_LG_1D(X,Z,EPSR,EPSI)
!
!  This subroutine computes random delta-function electron-impurity
!    interaction form of the dielectric function for disordered 1D
!    conductors
!
!  Reference: (1) A. C. Sharma and S. S. Z. Ashraf,
!                    J. Phys.: Condens. Matter 16, 3117 (2004)
!
!  Input parameters:
!
!       * X        : dimensionless factor   --> X = q / (2 * k_F)
!       * Z        : dimensionless factor   --> Z = omega / omega_q
!
!  Output parameters:
!
!       * EPSR     : real part of the dielectric function
!       * EPSI     : imaginary part of the dielectric function
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 30 Apr 2021
!
!
      USE REAL_NUMBERS,     ONLY : ZERO,ONE,TWO,FOUR,HALF
      USE COMPLEX_NUMBERS,  ONLY : IC
      USE CONSTANTS_P1,     ONLY : H_BAR,M_E
      USE FERMI_SI,         ONLY : EF_SI,KF_SI
      USE UTILITIES_1,      ONLY : DOS_EF
      USE COULOMB_K,        ONLY : COULOMB_FF
!
      USE UNITS,            ONLY : UNIT
      USE DAMPING_SI
!
      IMPLICIT NONE
!
      REAL (WP)             ::  X,Z,VC
      REAL (WP)             ::  EPSR,EPSI
      REAL (WP)             ::  Q,OM,N0
!
      REAL (WP)             ::  REAL,AIMAG
!
      COMPLEX (WP)          ::  EPS,ZETA,PI0
      COMPLEX (WP)          ::  NUM,DEN,PHI,PSI
!
      Q  = TWO * X  *KF_SI                                          ! q in SI
      OM = Z * H_BAR * Q * Q * HALF / M_E                           ! omega in SI
!
      CALL COULOMB_FF('1D',UNIT,Q,ZERO,VC)                          !
!
!  Computing the density of states at Fermi level
!
      N0 = DOS_EF('1D')                                             !
!
      PHI  = CDSQRT(ONE + IC * HALF / (LFT * EF_SI))                ! ref. 1 eq. (27)
      PSI  = CDSQRT(ONE - (OM + IC * HALF / LFT) / EF_SI)           ! ref. 1 eq. (28)
      NUM  = IC * (PHI - PSI)                                       !
      DEN  = LFT * EF_SI * ( PHI*PSI *( (PHI-PSI)**2 - FOUR*X*X ) ) !
      ZETA = NUM / DEN                                              ! ref. 1 eq. (26)
!
      PI0 = N0 * (ONE + IC * OM * LFT * (ZETA / (ONE - ZETA)))      !
!
      EPS = ONE - VC * PI0                                          !
!
      EPSR =  REAL(EPS,KIND=WP)                                     !
      EPSI = AIMAG(EPS)                                             !
!
      END SUBROUTINE RDF2_EPS_D_LG_1D
!
END MODULE DFUNCL_STAN_DYNAMIC
