!
!=======================================================================
!
MODULE RE_EPS_0_TREATMENT
!
!  This modules provides the tools to work on the file
!               Re [eps(q,omega)] = 0
!
!
      USE ACCURACY_REAL
!
CONTAINS
!
!
!=======================================================================
!
      SUBROUTINE REORDER_EPS0(NZ,Y,ZERO_1,ZERO_2)
!
!  This subroutine reorders the file Re [eps(q,omega)] = 0 to
!    separate the plasmon dispersion from the lower branch
!
!
!  Output parameters:
!
!       * NZ       : number of zeros in each branch
!       * ZERO_1   : lower branch zeros
!       * ZERO_2   : upper branch zeros
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 16 Dec 2020
!
!
      USE OUT_VALUES_3,       ONLY : I_ZE
      USE PRINT_FILES,        ONLY : IO_ZE
!
      IMPLICIT NONE
!
      INTEGER, PARAMETER     ::  N_ZERO = 10000       ! max number of zeros
!
      INTEGER, INTENT(OUT)   ::  NZ
!
      INTEGER                ::  IZ
!
      REAL (WP), INTENT(OUT) ::  Y(N_ZERO)
      REAL (WP), INTENT(OUT) ::  ZERO_1(N_ZERO),ZERO_2(N_ZERO)
!
      IF(I_ZE == 1) THEN                                            !
!
!  Separating out the two contributions
!
        REWIND IO_ZE                                                !
        NZ = 0                                                      ! zero counter
        DO IZ = 1, N_ZERO                                           !
          READ(IO_ZE,*,END=10) Y(IZ),ZERO_1(IZ)                     !
          READ(IO_ZE,*,END=10) Y(IZ),ZERO_2(IZ)                     ! plasmon
          NZ = NZ + 1                                               !
        END DO                                                      !
!
  10    REWIND IO_ZE                                                !
!
      END IF                                                        !
!
      END SUBROUTINE REORDER_EPS0
!
!=======================================================================
!
      SUBROUTINE REORDER_EPS0_PRINT
!
!  This subroutine reorders the file Re [eps(q,omega)] = 0 to
!    separate the plasmon dispersion from the other branch
!
!
!  Output parameters:
!
!       * NZ       : number of zeros in each branch
!       * ZERO_1   : lower branch zeros
!       * ZERO_2   : upper branch zeros
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 16 Dec 2020
!
!
      USE OUT_VALUES_3,       ONLY : I_ZE
      USE PRINT_FILES,        ONLY : IO_ZE
!
      IMPLICIT NONE
!
      INTEGER, PARAMETER     ::  N_ZERO = 10000       ! max number of zeros
!
      INTEGER                ::  NZ
!
      INTEGER                ::  IZ,NBZ
!
      REAL (WP)              ::  Y(N_ZERO)
      REAL (WP)              ::  ZERO_1(N_ZERO),ZERO_2(N_ZERO)
!
      IF(I_ZE == 1) THEN                                            !
!
!  Separating out the two contributions
!
        REWIND IO_ZE                                                !
        NZ = 0                                                      ! zero counter
        DO IZ = 1, N_ZERO                                           !
          READ(IO_ZE,*,END=10) Y(IZ),ZERO_1(IZ)                     !
          READ(IO_ZE,*,END=10) Y(IZ),ZERO_2(IZ)                     ! plasmon
          NZ = NZ + 1                                               !
        END DO                                                      !
!
  10    REWIND IO_ZE                                                !
!
!
!  Rewriting it with plasmon first, and then the lower branch
!    "backwards" to ensure the continuity of the curve
!
        DO IZ = 1, NZ                                               !
          WRITE(IO_ZE,*) Y(IZ),ZERO_2(IZ)                           !
        END DO                                                      !
!
        DO IZ = NZ, 1, -1                                           !
          WRITE(IO_ZE,*) Y(IZ),ZERO_1(IZ)                           !
        END DO                                                      !
!
      END IF                                                        !
!
      END SUBROUTINE REORDER_EPS0_PRINT
!
!=======================================================================
!
      SUBROUTINE SELECT_BRANCH(IB,NB,YB,ZERO_B)
!
!  This subroutine selects one of the branches of the collective
!    excitations
!
!
!  Input parameters:
!
!       * IB       : branch number (counted from E = 0)
!                       IB  = 1 --> lower branch
!                       IB  = 2 --> upper branch
!
!
!  Output parameters:
!
!       * NB       : number of zeros in the selected branch
!       * ZERO_B   : selected branch zeros
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 16 Dec 2020
!
!
      IMPLICIT NONE
!
      INTEGER, PARAMETER     ::  N_ZERO = 10000       ! max number of zeros
!
      INTEGER, INTENT(IN)    ::  IB
      INTEGER, INTENT(OUT)   ::  NB
!
      INTEGER                ::  IQ
!
      REAL (WP), INTENT(OUT) ::  YB(N_ZERO)
      REAL (WP), INTENT(OUT) ::  ZERO_B(N_ZERO)
!
      REAL (WP)              ::  Y(N_ZERO)
      REAL (WP)              ::  ZERO_1(N_ZERO),ZERO_2(N_ZERO)
!
!  Reordering the branch values
!
      CALL REORDER_EPS0(NB,Y,ZERO_1,ZERO_2)                         !
!
      DO IQ = 1, NB                                                 !
!
        IF(IB == 1) THEN                                            !
          ZERO_B(IQ) = ZERO_1(IQ)                                   !
        ELSE IF(IB == 2) THEN                                       !
          ZERO_B(IQ) = ZERO_2(IQ)                                   !
        END IF                                                      !
!
        YB(IQ) = Y(IQ)                                              !
!
      END DO                                                        !
!
  10  CONTINUE
!
      END SUBROUTINE SELECT_BRANCH
!
!=======================================================================
!
      SUBROUTINE COMPUTE_QBOUNDS_3D(NB,YB,ZERO_B,IS,IC,QS,QC)
!
!  This subroutine computes the bounds of the plasmon branch
!    in 3D
!
!
!  Input parameters:
!
!       * NB       : number of zeros in the selected branch
!       * YB       : abscissas
!       * ZERO_B   : branch zeros
!
!
!  Output parameters:
!
!       * IS       : index of lower q-bound
!       * IC       : index of upper q-bound
!       * QS       : lower q-bound
!       * QC       : upper q-bound
!
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 17 Dec 2020
!
!
      USE REAL_NUMBERS,       ONLY : ZERO,SMALL,TTINY,LARGE
!
      USE SMOOTHING
      USE DERIVATION,         ONLY : DERIV_3P
!
      IMPLICIT NONE
!
      INTEGER, PARAMETER       ::  N_ZERO = 10000       ! max number of zeros
!
      INTEGER, INTENT(IN)      ::  NB
      INTEGER, INTENT(OUT)     ::  IS,IC
!
      INTEGER                  ::  IM,JB,PTS
      INTEGER                  ::  LOGF
!
      REAL (WP), PARAMETER     ::  EPS1 = 0.01E0_WP
      REAL (WP), PARAMETER     ::  EPS2 = 0.5E0_WP
!
      REAL (WP), INTENT(IN)    ::  YB(N_ZERO)
      REAL (WP), INTENT(INOUT) ::  ZERO_B(N_ZERO)
      REAL (WP), INTENT(OUT)   ::  QS,QC
!
      REAL (WP)                ::  H
      REAL (WP)                ::  DER1(N_ZERO)
      REAL (WP)                ::  MIN_Q,MAX_Q
      REAL (WP)                ::  MAX_B
      REAL (WP)                ::  YS,YC
!
      LOGF = 6                                                      ! log file unit
!
      MIN_Q = LARGE                                                 !
      MAX_Q = TTINY                                                 !
      MAX_B = TTINY                                                 !
!
!  Number of smoothing neighbours
!
      PTS = 50                                                      !
!
!  Step
!
      H = YB(2) - YB(1)                                             !
!
!  Smoothing the branch function
!
!      CALL SMOOFT(ZERO_B,NB,PTS)                                    !
!      CALL TSAVGOL(ZERO_B,NB)
!
!  Computing the first derivative of the branch
!
      CALL DERIV_3P(ZERO_B,NB,DER1,H)                               !
!
!  Computing the maximum MAX_B of the branch
!
      DO JB = 1, NB                                                 !
        MAX_B = MAX(MAX_B,ZERO_B(JB))                               !
      END DO                                                        !
!
!  Computing the index IM corresponding to MAX_B
!
      DO JB = 1, NB                                                 !
        IF(ABS(ZERO_B(JB)-MAX_B) < EPS1) THEN                       !
          IM = JB                                                   !
          GO TO 10                                                  !
        END IF                                                      !
      END DO                                                        !
!
!  Computing the minimum of YS the derivative (up tu MAX_B)
!
  10  DO JB = 1, IM-5                                               !
        MIN_Q = MIN(MIN_Q,DER1(JB))                                 !
      END DO                                                        !
      YS = MIN_Q                                                    !
!
!  Computing the index IS of lower bound QS
!
      DO JB = 1, IM-5                                               !
        IF(ABS(DER1(JB)-YS) < EPS2) THEN                            !
          IS = JB                                                   !
          QS = YB(JB)                                               !
          GO TO 20                                                  !
        END IF                                                      !
      END DO                                                        !
!
!  Computing the maximum of the derivative (up tu MAX_B)
!
  20  DO JB = IS,IM                                                 !
        MAX_Q = MAX(MAX_Q,DER1(JB))                                 !
      END DO                                                        !
      YC = MAX_Q                                                    !
!
!  Computing the index IC of upper bound QC
!
      DO JB = IM,IS,-1                                              !
        IF(ABS(DER1(JB)-YC) < EPS2) THEN                            !
          IC = JB                                                   !
          QC = YB(JB)                                               !
          GO TO 30                                                  !
        END IF                                                      !
      END DO                                                        !
!
  30  CONTINUE
!
!  Printing the bounds
!
      WRITE(LOGF,15)
      WRITE(LOGF, 5)
      WRITE(LOGF,25)
      WRITE(LOGF,35) QS,IS
      WRITE(LOGF,45) QC,IC
      WRITE(LOGF,55)
!
!  Formats:
!
   5  FORMAT(5X,'|',10X,'q-bounds of epsilon :    ',22X,'|')
  15  FORMAT(6X,'_________________________________________________________')
  25  FORMAT(5X,'|                                                         |')
  35  FORMAT(5X,'|',15X,'q_min = ',F8.3,5X,'index = ',I4,9X,'|')
  45  FORMAT(5X,'|',15X,'q_max = ',F8.3,5X,'index = ',I4,9X,'|')
  55  FORMAT(5X,'|_________________________________________________________|',/)
!
      END SUBROUTINE COMPUTE_QBOUNDS_3D
!
END MODULE RE_EPS_0_TREATMENT
