Skip to content
Snippets Groups Projects
lima_functions.f90 9.44 KiB
Newer Older
  • Learn to ignore specific revisions
  • Gaelle TANGUY's avatar
    Gaelle TANGUY committed
    !#################################
            MODULE MODI_LIMA_FUNCTIONS
    !#################################
    !
    INTERFACE
    !
    FUNCTION COUNTJV(LTAB,I1,I2,I3) RESULT(IC)
      LOGICAL, DIMENSION(:,:,:),   INTENT(IN)           :: LTAB 
      INTEGER, DIMENSION(:),       INTENT(INOUT)        :: I1,I2,I3 
      INTEGER                                           :: IC
    END FUNCTION COUNTJV
    !
    FUNCTION MOMG (PALPHA,PNU,PP) RESULT (PMOMG)
      REAL,                        INTENT(IN)           :: PALPHA 
      REAL,                        INTENT(IN)           :: PNU    
      REAL,                        INTENT(IN)           :: PP     
      REAL                                              :: PMOMG  
    END FUNCTION MOMG
    !
    FUNCTION RECT(PA,PB,PX,PX1,PX2)  RESULT(PRECT)
      REAL,                        INTENT(IN)           :: PA
      REAL,                        INTENT(IN)           :: PB
      REAL, DIMENSION(:),          INTENT(IN)           :: PX
      REAL,                        INTENT(IN)           :: PX1
      REAL,                        INTENT(IN)           :: PX2
      REAL, DIMENSION(SIZE(PX,1))                       :: PRECT
    END FUNCTION RECT
    !
    FUNCTION DELTA(PA,PB,PX,PX1,PX2)  RESULT(PDELTA)
      REAL,                        INTENT(IN)           :: PA
      REAL,                        INTENT(IN)           :: PB
      REAL, DIMENSION(:),          INTENT(IN)           :: PX
      REAL,                        INTENT(IN)           :: PX1
      REAL,                        INTENT(IN)           :: PX2
      REAL, DIMENSION(SIZE(PX,1))                       :: PDELTA
    END FUNCTION DELTA
    !
    FUNCTION DELTA_VEC(PA,PB,PX,PX1,PX2)  RESULT(PDELTA_VEC)
      REAL,                        INTENT(IN)           :: PA
      REAL,                        INTENT(IN)           :: PB
      REAL, DIMENSION(:),          INTENT(IN)           :: PX
      REAL, DIMENSION(:),          INTENT(IN)           :: PX1
      REAL, DIMENSION(:),          INTENT(IN)           :: PX2
      REAL, DIMENSION(SIZE(PX,1))                       :: PDELTA_VEC
    END FUNCTION DELTA_VEC
    !
    SUBROUTINE GAULAG(x,w,n,alf)
      INTEGER,                     INTENT(IN)           :: n
      REAL,                        INTENT(IN)           :: alf
      REAL, DIMENSION(n),          INTENT(INOUT)        :: w, x
    END SUBROUTINE GAULAG
    !
    SUBROUTINE GAUHER(x,w,n)
      INTEGER,                     INTENT(IN)           :: n
      REAL, DIMENSION(n),          INTENT(INOUT)        :: w, x
    END SUBROUTINE GAUHER
    !
    END INTERFACE
    !
    END MODULE MODI_LIMA_FUNCTIONS
    !
    !------------------------------------------------------------------------------
    !
    !#########################################
    FUNCTION COUNTJV(LTAB,I1,I2,I3) RESULT(IC)
    !#########################################
    !
      IMPLICIT NONE
    !
      LOGICAL, DIMENSION(:,:,:) :: LTAB ! Mask
      INTEGER, DIMENSION(:) :: I1,I2,I3 ! Used to replace the COUNT and PACK
      INTEGER :: JI,JJ,JK,IC
    !
      IC = 0
      DO JK = 1,SIZE(LTAB,3)
         DO JJ = 1,SIZE(LTAB,2)
            DO JI = 1,SIZE(LTAB,1)
               IF( LTAB(JI,JJ,JK) ) THEN
                  IC = IC +1
                  I1(IC) = JI
                  I2(IC) = JJ
                  I3(IC) = JK
               END IF
            END DO
         END DO
      END DO
    !
    END FUNCTION COUNTJV
    !
    !------------------------------------------------------------------------------
    !
    !###########################################
    FUNCTION MOMG (PALPHA,PNU,PP) RESULT (PMOMG)
    !###########################################
    !
    ! auxiliary routine used to compute the Pth moment order of the generalized
    ! gamma law
    !
      USE MODI_GAMMA
    !
      IMPLICIT NONE
    !
      REAL     :: PALPHA ! first shape parameter of the dimensionnal distribution
      REAL     :: PNU    ! second shape parameter of the dimensionnal distribution
      REAL     :: PP     ! order of the moment
      REAL     :: PMOMG  ! result: moment of order ZP
    !
      PMOMG = GAMMA_X0D(PNU+PP/PALPHA)/GAMMA_X0D(PNU)
    !
    END FUNCTION MOMG
    !
    !------------------------------------------------------------------------------
    !
    !#############################################
    FUNCTION RECT(PA,PB,PX,PX1,PX2)  RESULT(PRECT)
    !#############################################
    !
    !     PRECT takes the value PA if PX1<=PX<PX2, and PB outside the [PX1;PX2[ interval
    !
      IMPLICIT NONE
    !
      REAL,                        INTENT(IN)           :: PA
      REAL,                        INTENT(IN)           :: PB
      REAL, DIMENSION(:),          INTENT(IN)           :: PX
      REAL,                        INTENT(IN)           :: PX1
      REAL,                        INTENT(IN)           :: PX2
      REAL, DIMENSION(SIZE(PX,1))                       :: PRECT
    !
      PRECT(:) = PB
      WHERE (PX(:).GE.PX1 .AND. PX(:).LT.PX2)
         PRECT(:) = PA
      END WHERE
      RETURN
    !
    END FUNCTION RECT
    !
    !-------------------------------------------------------------------------------
    !
    !###############################################
    FUNCTION DELTA(PA,PB,PX,PX1,PX2)  RESULT(PDELTA)
    !###############################################
    !
    !     PDELTA takes the value PA if PX<PX1, and PB if PX>=PX2
    !     PDELTA is a cubic interpolation between PA and PB for PX between PX1 and PX2 
    !
      IMPLICIT NONE
    !
      REAL,                        INTENT(IN)           :: PA
      REAL,                        INTENT(IN)           :: PB
      REAL, DIMENSION(:),          INTENT(IN)           :: PX
      REAL,                        INTENT(IN)           :: PX1
      REAL,                        INTENT(IN)           :: PX2
      REAL, DIMENSION(SIZE(PX,1))                       :: PDELTA
    !
    !*       local variable
    !
      REAL                                              :: ZA
    !
      ZA = 6.0*(PA-PB)/(PX2-PX1)**3
      WHERE     (PX(:).LT.PX1)
         PDELTA(:) = PA
      ELSEWHERE (PX(:).GE.PX2)
         PDELTA(:) = PB
      ELSEWHERE
         PDELTA(:) =   PA + ZA*PX1**2*(PX1/6.0 - 0.5*PX2)              &
              + ZA*PX1*PX2*                          (PX(:))    &
              - (0.5*ZA*(PX1+PX2))*                  (PX(:)**2) & 
              + (ZA/3.0)*                            (PX(:)**3)
      END WHERE
      RETURN
    !
    END FUNCTION DELTA
    !
    !-------------------------------------------------------------------------------
    !
    !#######################################################
    FUNCTION DELTA_VEC(PA,PB,PX,PX1,PX2)  RESULT(PDELTA_VEC)
    !#######################################################
    !
    !    Same as DELTA for vectorized PX1 and PX2 arguments
    !
      IMPLICIT NONE
    !
      REAL,                        INTENT(IN)           :: PA
      REAL,                        INTENT(IN)           :: PB
      REAL, DIMENSION(:),          INTENT(IN)           :: PX
      REAL, DIMENSION(:),          INTENT(IN)           :: PX1
      REAL, DIMENSION(:),          INTENT(IN)           :: PX2
      REAL, DIMENSION(SIZE(PX,1))                       :: PDELTA_VEC
    !
    !*       local variable
    !
      REAL, DIMENSION(SIZE(PX,1))                       :: ZA
    !
      ZA(:) = 0.0
      wHERE     (PX(:)<=PX1(:))
         PDELTA_VEC(:) = PA
      ELSEWHERE (PX(:)>=PX2(:))
         PDELTA_VEC(:) = PB
      ELSEWHERE
         ZA(:)         = 6.0*(PA-PB)/(PX2(:)-PX1(:))**3
         PDELTA_VEC(:) =   PA + ZA(:)*PX1(:)**2*(PX1(:)/6.0 - 0.5*PX2(:))           &
              + ZA(:)*PX1(:)*PX2(:)*                          (PX(:))    &
              - (0.5*ZA(:)*(PX1(:)+PX2(:)))*                  (PX(:)**2) & 
              + (ZA(:)/3.0)*                                  (PX(:)**3)
      END WHERE
      RETURN
    !
    END FUNCTION DELTA_VEC
    !
    !-------------------------------------------------------------------------------
    !
    !###########################
    SUBROUTINE gaulag(x,w,n,alf)
    !###########################
      INTEGER n,MAXIT
      REAL alf,w(n),x(n)
      DOUBLE PRECISION EPS
      PARAMETER (EPS=3.D-14,MAXIT=10)
      INTEGER i,its,j
      REAL ai
      DOUBLE PRECISION p1,p2,p3,pp,z,z1
    !
      REAL SUMW
    !
      do 13 i=1,n
         if(i.eq.1)then
            z=(1.+alf)*(3.+.92*alf)/(1.+2.4*n+1.8*alf)
         else if(i.eq.2)then
            z=z+(15.+6.25*alf)/(1.+.9*alf+2.5*n)
         else
            ai=i-2
            z=z+((1.+2.55*ai)/(1.9*ai)+1.26*ai*alf/(1.+3.5*ai))* &
                 (z-x(i-2))/(1.+.3*alf)
         endif
         do 12 its=1,MAXIT
            p1=1.d0
            p2=0.d0
            do 11 j=1,n
               p3=p2
               p2=p1
               p1=((2*j-1+alf-z)*p2-(j-1+alf)*p3)/j
    11      continue
            pp=(n*p1-(n+alf)*p2)/z
            z1=z
            z=z1-p1/pp
            if(abs(z-z1).le.EPS)goto 1
    12   continue
    1    x(i)=z
         w(i)=-exp(gammln(alf+n)-gammln(float(n)))/(pp*n*p2)
    13 continue
    !
    ! NORMALISATION
    !
      SUMW = 0.0
      DO 14 I=1,N
         SUMW = SUMW + W(I)
    14 CONTINUE
      DO 15 I=1,N
         W(I) = W(I)/SUMW
    15 CONTINUE
    !
      return
    END SUBROUTINE gaulag
    !
    !------------------------------------------------------------------------------
    !
    !##########################################
    SUBROUTINE gauher(x,w,n)
    !##########################################
      INTEGER n,MAXIT
      REAL w(n),x(n)
      DOUBLE PRECISION EPS,PIM4
      PARAMETER (EPS=3.D-14,PIM4=.7511255444649425D0,MAXIT=10)
      INTEGER i,its,j,m
      DOUBLE PRECISION p1,p2,p3,pp,z,z1
    !
      REAL SUMW
    !
      m=(n+1)/2
      do 13 i=1,m
         if(i.eq.1)then
            z=sqrt(float(2*n+1))-1.85575*(2*n+1)**(-.16667)
         else if(i.eq.2)then
            z=z-1.14*n**.426/z
         else if (i.eq.3)then
            z=1.86*z-.86*x(1)
         else if (i.eq.4)then
            z=1.91*z-.91*x(2)
         else
            z=2.*z-x(i-2)
         endif
         do 12 its=1,MAXIT
            p1=PIM4
            p2=0.d0
            do 11 j=1,n
               p3=p2
               p2=p1
               p1=z*sqrt(2.d0/j)*p2-sqrt(dble(j-1)/dble(j))*p3
    11      continue
            pp=sqrt(2.d0*n)*p2
            z1=z
            z=z1-p1/pp
            if(abs(z-z1).le.EPS)goto 1
    12   continue
    1    x(i)=z
         x(n+1-i)=-z
         pp=pp/PIM4 ! NORMALIZATION
         w(i)=2.0/(pp*pp)
         w(n+1-i)=w(i)
    13 continue
    !
    ! NORMALISATION
    !
      SUMW = 0.0
      DO 14 I=1,N
         SUMW = SUMW + W(I)
    14 CONTINUE
      DO 15 I=1,N
         W(I) = W(I)/SUMW
    15 CONTINUE
    !
      return
    END SUBROUTINE gauher
    !
    !------------------------------------------------------------------------------