!
!=======================================================================
!
MODULE CALCULATORS_P
!
      USE ACCURACY_REAL
!
!  This module contains the subroutines allowing to compute
!    various properties of the electron/plasma liquids:
!
!
!          * exact plasmon dispersion   : CALC_EPD
!
!          * fluctuation potential      : CALC_FLP
!
CONTAINS
!
!=======================================================================
!
      SUBROUTINE CALC_EPD
!
!  This subroutine computes the exact plasmon dispersion
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 16 Dec 2020
!
!
      USE FERMI_SI,         ONLY : EF_SI
!
      USE PLASMON_DISP_EXACT
!
      USE PRINT_FILES,        ONLY : IO_PD
!
      IMPLICIT NONE
!
      INTEGER, PARAMETER     ::  N_ZERO = 10000 ! max number of zeros
!
      INTEGER                ::  IS,IC          ! lower and upper indices
      INTEGER                ::  IP
!
      REAL (WP)              ::  ENE_P_Q(N_ZERO)
      REAL (WP)              ::  YQ(N_ZERO)
!
      CALL PLASMON_DISP_EX(IS,IC,YQ,ENE_P_Q)
!
      DO IP = IS, IC                                                !
        WRITE(IO_PD,*) YQ(IP),ENE_P_Q(IP) / EF_SI                   !
      END DO                                                        !
!
      END SUBROUTINE CALC_EPD
!
!=======================================================================
!
      SUBROUTINE CALC_FLP
!
!  This subroutine computes the modulus of the fluctuation potential.
!  The fluctuation potential is given by
!
!               V_q = A_q e^{i q . r}
!
!     with
!
!                     |        V_C(q)          | ^{1/2}
!               A_q = | ______________________ |
!                     |                        |
!                     | d [ epsilon] / d omega | omega = omega(q)      (1)
!
!
!
!     where omega(q) is the plasmon dispersion
!
!
!
!   References: (1) B. I. Lundqvist, Phys. kondens. Materie 9, 236-248 (1969)
!
!
!
!
!  Intermediate parameters:
!
!       * RS       : Wigner-Seitz radius (in units of a_0)
!       * T        : temperature in SI
!       * DMN      : problem dimension
!
!
!  Output parameters:
!
!       * FLPR     : real part of the screened potential
!       * FLPI     : imaginary part of the screened potential
!
!
!
!  WARNING : only REAL a at present
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 11 Jun 2021
!
!
      USE DIMENSION_CODE,   ONLY : NSIZE
      USE REAL_NUMBERS,     ONLY : ZERO,TWO,THREE,TEN,  &
                                   HALF
      USE COMPLEX_NUMBERS,  ONLY : IC
      USE DF_VALUES,        ONLY : ESTDY,EPS_T,D_FUNC
      USE MATERIAL_PROP,    ONLY : RS,DMN
      USE CONSTANTS_P1,     ONLY : H_BAR,M_E,E,EPS_0
      USE ENE_CHANGE,       ONLY : EV
      USE FERMI_SI,         ONLY : EF_SI,KF_SI
      USE EXT_FIELDS,       ONLY : T
      USE SCREENING_TYPE
      USE SCREENING_VEC
!
      USE E_GRID
      USE Q_GRID
      USE R_GRID
      USE UNITS,            ONLY : UNIT
      USE OUT_VALUES_P
      USE PLASMON_DISPERSION
!
      USE COULOMB_K,          ONLY : COULOMB_FF
      USE INTERPOLATION
      USE DERIVATION
      USE PLASMON_ENE_SI
      USE PLASMON_DISP_EXACT
      USE PLASMON_DISP_REAL
      USE RE_EPS_0_TREATMENT
!
      USE CALCULATORS_1
      USE CALCULATORS_3
!
      USE OUT_VALUES_3,       ONLY : I_ZE
      USE OUT_VALUES_P,       ONLY : I_FP
      USE PRINT_FILES,        ONLY : IO_ZE,IO_FP
!
      IMPLICIT NONE
!
      CHARACTER (LEN = 4)   ::  D_FUNCL,D_FUNCT
!
      INTEGER, PARAMETER    ::  N_ZERO = 10000 ! max number of zeros
!
      INTEGER               ::  LOGF
      INTEGER               ::  IE,IQ,IR
      INTEGER               ::  NB
      INTEGER               ::  IQ_MIN,IQ_MAX
!
      REAL (WP)             ::  Y,X
      REAL (WP)             ::  ENE_P_Q(N_ZERO),ENE_P_Q1
      REAL (WP)             ::  YB(N_ZERO)
      REAL (WP)             ::  ENE_P
      REAL (WP)             ::  EPSR(NSIZE),EPSI(NSIZE),EN(NSIZE)
      REAL (WP)             ::  EPSR1(NSIZE),EPSI1(NSIZE)
      REAL (WP)             ::  REPS,IEPS,DEPSR_Q,DEPSI_Q
      REAL (WP)             ::  FLPR(NSIZE),FLPI(NSIZE),R(NSIZE)
      REAL (WP)             ::  RN,Q_SI,KS_SI,VC,A_Q
      REAL (WP)             ::  H
!
      REAL (WP)             ::  SQRT,FLOAT,COS,SIN
!
      COMPLEX (WP)          ::  DEPS
!
      LOGF = 6                                                      !
!
!  Computing the exact plasmon dispersion in SI
!
      IF(I_FP == 1) THEN                                            !
        I_ZE  = 1                                                   !
        IO_ZE = 1                                                   !
        CALL PLASMON_DISP_EX(IQ_MIN,IQ_MAX,YB,ENE_P_Q)              !
      END IF                                                        !
!
!  Computing the dielectric function from IQ_MIN to IQ_MAX
!       (plasmon dispersion bounds)
!
      DO IQ = IQ_MIN,IQ_MAX                                         ! start of q-loop
!
        Y = Q_MIN + FLOAT(IQ - 1) * Q_STEP                          ! Y = q/k_F
!
        X = HALF * Y                                                ! X = q/(2k_F)
!
        Q_SI     = Y * KF_SI                                        ! q in SI
!
!  Computing an approximate plasmon dispersion
!
        IF(I_FP == 3) THEN                                          !
          CALL PLASMON_DISP_R(X,RS,T,PL_DISP,ENE_P_Q1)              !
        END IF                                                      !
!
!  Computing the dielectric function EPS(omega) for q
!
        CALL CALC_EPS(X,EN,EPSR,EPSI)                               ! EN = E / E_F
!
!  Plasmon energy at q in units of E / E_F
!
        IF(I_FP == 1) THEN                                          !
          ENE_P = ENE_P_Q(IQ) / EF_SI                               !
        ELSE IF(I_FP == 3) THEN                                     !
          ENE_P = ENE_P_Q1 / EF_SI                                  !
        END IF                                                      !
!
!  Checking for screening vector
!
        CALL SCREENING_VECTOR(SC_TYPE,DMN,X,RS,T,KS_SI)             !
!
!  Initialisation of derivative arrays
!
        DO IE = 1, N_E                                              !
          EPSR1(IE) = ZERO                                          !
          EPSI1(IE) = ZERO                                          !
        END DO                                                      !
!
        H = EN(2) - EN(1)                                           ! step for energy derivation (E / E_F)
!
!  Computing the derivatives of EPSR and EPSI
!
        CALL DERIV_1(EPSR,N_E,5,H,EPSR1)                            !
        CALL DERIV_1(EPSI,N_E,5,H,EPSI1)                            !
!
!  Cubic spline interpolation of EPSR1(N) and EPSI1(N) at E = ENE_P
!
        DEPSR_Q = CUBIC_SPLINE_INTERP(EPSR1,EN,N_E,ENE_P)           !
        DEPSI_Q = CUBIC_SPLINE_INTERP(EPSI1,EN,N_E,ENE_P)           !
!
        DEPS = ABS(DEPSR_Q + IC * DEPSI_Q)                          !
!
!  Calculation of Fourier transform of Coulomb potential in SI
!
        CALL COULOMB_FF(DMN,UNIT,Q_SI,KS_SI,VC)                     !
!
!  Computing the amplitude of the fluctuation potential (in eV)
!
        A_Q = SQRT(ABS(VC / DEPS)) / EV                             ! ref. (1) eq. (17)
!
!  Writing the results
!
        IF(I_FP == 1) THEN                                          !  writing to
          WRITE(IO_FP,*)  Y,A_Q                                     !  file
        ELSE IF(I_FP == 2) THEN                                     !
!
!  Loop in R
!
          DO IR = 1, N_R                                            !
!
            RN = R_MIN + FLOAT(IR - 1) * R_STEP                     ! R = k_F * r
!
            FLPR(IR) = A_Q * COS(TWO * X * RN)                      !
            FLPI(IR) = A_Q * SIN(TWO * X * RN)                      !
            R(IR)    = RN                                           !
!
            WRITE(IO_FP,*)  Y,RN,FLPR(IE),FLPI(IE)                  !
!
          END DO                                                    !
        END IF                                                      !
      END DO                                                        ! end of q-loop
!
      END SUBROUTINE CALC_FLP
!
END MODULE CALCULATORS_P
