!
!=======================================================================
!
MODULE Q_BOUNDS
!
!  This module provides subroutines to compute the bounds 
!    for the q-integration. 
!
!
      USE ACCURACY_REAL
!
CONTAINS
!
!=======================================================================
!
      SUBROUTINE QBOUNDS(Q_MIN,Q_MAX)
!
!  This subroutine computes the bounds for q-integration. 
!  The lower bounds is zero except when the plasmon is damped. 
!  The upper bound is given by the intersection of the plasmon 
!    dispersion curve with the electron-hole pair dispersion.
!
!  The dispersion coefficients in modules DISP_COEF_REAL,  
!    DISP_COEF_COMP and DISP_COEF_EH are in atomic units (AU)
!
!  The subroutines find the roots of the polynomial:
!
!     AR(6)*q^6 + AR(5)*q^5 + [AR(4)-AE(4)]*q^4 + 
!         [AR(3)-AE(3)]*q^3 + [AR(2)-AE(2)]*q^2 + 
!         [AR(1)-AE(1)]*q   + [AR(0)-AE(0)] = 0
!
!
!
!  Output variables :
!
!       * Q_MIN    : lower bound in SI
!       * Q_MAX    : upper bound in SI
!
!
!   Author :  D. Sébilleau
!
!                                           Last modified : 15 Sep 2020
!
!
      USE MATERIAL_PROP,         ONLY : RS,DMN
      USE FERMI_SI,              ONLY : KF_SI
      USE FERMI_AU,              ONLY : KF_AU
      USE REAL_NUMBERS,          ONLY : ZERO,ONE,TWO,THREE,FOUR,FIVE,NINE,  &
                                        THIRD,FOURTH
      USE PI_ETC,                ONLY : PI,PI_INV
      USE PLASMON_DISPERSION
      USE DISP_COEF_REAL
      USE DISP_COEF_COMP
      USE DISP_COEF_EH
      USE UTILITIES_1,           ONLY : ALFA
      USE FIND_ZERO
!
      IMPLICIT NONE
!
      INTEGER                ::  NP,NA,NO,I
      INTEGER                ::  LOGF
!
      REAL (WP), INTENT(OUT) ::  Q_MIN,Q_MAX 
!
      REAL (WP)              ::  COEF,A0KF
      REAL (WP)              ::  A,B,C
      REAL (WP)              ::  XA0,XA1,XA2,XC
      REAL (WP)              ::  ALPHA,DE
      REAL (WP)              ::  SMALL,LARGE
      REAL (WP)              ::  ROOT,MODU
      REAL (WP)              ::  OP(101),OI(101)                    ! for CPOLY
      REAL (WP)              ::  ZR(101),ZI(101)                    ! for CPOLY
      REAL (WP)              ::  OP2(101),OI2(101)                  ! for CPOLY
      REAL (WP)              ::  ZR2(101),ZI2(101)                  ! for CPOLY
!
      REAL (WP)              ::  SQRT,ABS,REAL,AIMAG,MAX,MIN
!
      LOGICAL                ::  FAIL                               ! for CPOLY
!
      SMALL = 0.0001E0_WP                                           !
      LARGE = 1.0000E9_WP                                           !
!
      COEF  = ONE / ALFA('3D')                                      ! (9 pi/4^(1/3)
      A0KF  = COEF / RS                                             ! (a_0 * k_F) --> dimensionless
      ALPHA = SQRT(FOUR * THIRD * PI_INV / A0KF)                    ! Nozières-Pines q/k_F = omega_p/V_F
!
      NA = 4                                                        ! degree of polynomial for
!                                                                   !   RPA approximation
      NP = 6                                                        ! max degree of polynomial
!
!  Initialisation
!
      DO I = 1,NP                                                   !
        ZR(I) = ZERO                                                !
        ZI(I) = ZERO                                                !
      END DO                                                        !
!
!  Checking the order of the polynomial  --> NO
!
      NO = 0                                                        !
      DO I = NP,0,-1                                                !
        MODU = ABS(AR(I) - AE(I))                                   !
        IF(MODU > SMALL) THEN                                       !
          NO = I                                                    !
          GO TO 5                                                   !
        END IF                                                      !
      END DO                                                        !
   5  CONTINUE                                                      !
!
      IF(PL_DISP /= 'DAMPED1') THEN                                 !
!
!  Plasmon not damped --> real value of q
!
        DO I = 0,NO                                                 !
          OP(NO+1-I) = AR(I) - AE(I)                                ! OP and OI ordered
          OI(NO+1-I) = ZERO                                         ! by decreasing order
        ENDDO                                                       !
!
        Q_MIN = ZERO                                                !
        Q_MAX = LARGE                                               !
!
      ELSE
!
!  Plasmon damped     --> complex value of q
!
        DO I = 0,NO                                                 !
          OP(NO+1-I) =  REAL(AC(I),KIND=WP) - AE(I)                 ! OP and OI ordered
          OI(NO+1-I) = AIMAG(AC(I))                                 ! by decreasing order
        END DO                                                      !
!
        Q_MIN = ZERO                                                !
        Q_MAX = LARGE                                               !
!
      END IF                                                        !
!
!  Computing approximation to the critical reduced momenta x = q_c/k_F 
!
!
!   1) Nozières-Pines (XA0) 
!
      XA0 = ALPHA                                                   ! 3D value
!
!   2) RPA dispersion limited to q^2 and use of hbar omega_q: 
!
!      (1 - 3/5*alpha) x^2 + 2x - 2*alpha = 0                       ! 3D value      
!
      A =   ONE - THREE / (FIVE * ALPHA)                            !
      B =   TWO                                                     !
      C = - TWO * ALPHA                                             !
!
      DE = B * B - FOUR * A * C                                     ! discriminant Delta
!
      XA1 = (- B + SQRT(DE)) / (A + A)                              !
!
!   3) RPA dispersion limited to q^2 and use of (hbar omega_q)^2:
!
!      x^4 + 4 x^3 + (4 - 12/5) x^2 _ 4 alpha^2 = 0                 ! 3D value
!
      OP2(1) = ONE                                                  !
      OP2(2 )= FOUR                                                 !
      OP2(3) = FOUR - 12.0E0_WP/ FIVE                               !
      OP2(4) = ZERO                                                 !
      OP2(5) = - FOUR * ALPHA * ALPHA                               !
      OI2(1) = ZERO                                                 !
      OI2(2) = ZERO                                                 !
      OI2(3) = ZERO                                                 !
      OI2(4) = ZERO                                                 !
      OI2(5) = ZERO                                                 !
!
      CALL CPOLY(OP2,OI2,NA,ZR2,ZI2,FAIL)                           !
!
      XA2 = MAX(ZR2(1),ZR2(2),ZR2(3),ZR2(4))                        !
!
!  Computing the true intersection between plasmons and e-h dispersions
!
      CALL CPOLY(OP,OI,NO,ZR,ZI,FAIL)                               !
!  
!  Filtering the roots to keep only the smallest of the positive ones (XC)
!
      XC = LARGE                                                    !
      DO I = 1,NO                                                   !
        ROOT = ZR(I) / KF_AU                                        !
        IF(ROOT > SMALL) THEN                                       !
          XC = MIN(ROOT,XC,LARGE)                                   !
        END IF                                                      !
      END DO                                                        !
!
!  Printing out the results
!
      WRITE(LOGF,10)                                                !
      WRITE(LOGF,20) NO                                             !
      WRITE(LOGF,30) XA0                                            !
      WRITE(LOGF,40) XA1                                            !
      WRITE(LOGF,50) XA2                                            !
      WRITE(LOGF,60) XC                                             !
!
      Q_MAX = XC * KF_SI                                            !
!
!  Formats:
!
  10  FORMAT(//,5X,'Critical value q_c/k_F of the plasmon momentum:')
  20  FORMAT(/,13X,'---> solving polynomial of order ',I1,/)
  30  FORMAT(10X,'Nozières-Pines approximation : ', F6.3)
  40  FORMAT(10X,'RPA-q^2 linear approximation : ', F6.3)
  50  FORMAT(10X,'RPA-q^2  approximation       : ', F6.3)
  60  FORMAT(10X,'Exact value                  : ', F6.3,/)
!
      RETURN
!
      END SUBROUTINE QBOUNDS
!
END MODULE Q_BOUNDS
