Skip to content
Snippets Groups Projects
bhmie_bhcoat.f90 6.79 KiB
Newer Older
  • Learn to ignore specific revisions
  • !MNH_LIC Copyright 1994-2019 CNRS, Meteo-France and Universite Paul Sabatier
    
    !MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence
    
    !MNH_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
    
    !MNH_LIC for details. version 1.
    
    !-----------------------------------------------------------------
    
    !      ########################
           MODULE MODI_BHMIE_BHCOAT
    !      ########################
    !
    INTERFACE
          SUBROUTINE BHMIE_BHCOAT(PSIZE_PARAM_CORE,PSIZE_PARAM_COAT, &
                                  PPREFR_CORE,PPREFR_COAT,PQEXT,PQBAK)
    !
    REAL,                  INTENT(IN)  :: PSIZE_PARAM_CORE
    REAL,                  INTENT(IN)  :: PSIZE_PARAM_COAT
    COMPLEX,               INTENT(IN)  :: PPREFR_CORE
    COMPLEX,               INTENT(IN)  :: PPREFR_COAT
    REAL,                  INTENT(OUT) :: PQEXT,PQBAK
    !
    END SUBROUTINE BHMIE_BHCOAT
    END INTERFACE
    END MODULE MODI_BHMIE_BHCOAT 
    !
    !     ############################################################
          SUBROUTINE BHMIE_BHCOAT(PSIZE_PARAM_CORE,PSIZE_PARAM_COAT, &
                                  PPREFR_CORE,PPREFR_COAT,PQEXT,PQBAK)
    !     ############################################################
    !
    !!***********************************************************************
    !!
    !! Subroutine BHCOAT calculates Q_ext, Q_back for coated sphere.
    !! All bessel functions computed by upward recurrence.
    !! Input:
    !!        X = 2*PI*RCORE*REFMED/WAVEL
    !!        Y = 2*PI*RMANT*REFMED/WAVEL
    !!        RFREL1 = REFCOR/REFMED
    !!        RFREL2 = REFMAN/REFMED 
    !! where  REFCOR = complex refr.index of core)
    !!        REFMAN = complex refr.index of mantle)
    !!        REFMED = real refr.index of medium)
    !!        RCORE = radius of core
    !!        RMANT = radius of mantle
    !!        WAVEL = wavelength of light in ambient medium
    !!
    !! Routine BHCOAT is taken from Bohren & Huffman (1983)
    !! Obtained from C.L.Joseph
    !!
    !! History:
    !! 92/11/24 (BTD) Explicit declaration of all variables
    
    !  P. Wautelet 22/02/2019: add kind parameter for CMPLX intrinsics (if not it default to single precision)
    
    !  P. Wautelet 26/04/2019: replace non-standard FLOAT function by REAL function
    
    !!***********************************************************************
    !
    !*       0.    DECLARATIONS
    !              ------------
    !
    USE MODD_CST
    !
    IMPLICIT NONE
    !
    !*       0.1   Declarations of dummy arguments :
    !
    REAL,                  INTENT(IN)  :: PSIZE_PARAM_CORE
    REAL,                  INTENT(IN)  :: PSIZE_PARAM_COAT
    COMPLEX,               INTENT(IN)  :: PPREFR_CORE
    COMPLEX,               INTENT(IN)  :: PPREFR_COAT
    REAL,                  INTENT(OUT) :: PQEXT,PQBAK
    !
    !*       0.2   Declarations of local variables :
    !
    INTEGER :: JJ
    INTEGER :: ISTOP,IFLAG
    REAL (KIND(0.0D0))    :: ZPSIY,ZCHIY
    REAL (KIND(0.0D0))    :: ZPSI0Y,ZPSI1Y
    REAL (KIND(0.0D0))    :: ZCHI0Y,ZCHI1Y
    REAL (KIND(0.0D0))    :: ZEN,ZONE,ZSIZE_PARAM_STOP
    REAL (KIND(0.0D0))    :: ZDEL=1.0E-8
    COMPLEX (KIND(0.0D0)) :: ZZREFR_COAT_CORE
    COMPLEX (KIND(0.0D0)) :: ZZCHI0Y2,ZZCHI1Y2,ZZCHI0X2,ZZCHI1X2
    COMPLEX (KIND(0.0D0)) :: ZZCHIX2,ZZCHIPX2,ZZCHIY2,ZZCHIPY2
    COMPLEX (KIND(0.0D0)) :: ZZAN,ZZBN,ZZXIY,ZZXI0Y,ZZXI1Y
    COMPLEX (KIND(0.0D0)) :: ZZANCAP,ZZBNCAP
    COMPLEX (KIND(0.0D0)) :: ZZX1,ZZX2,ZZY2
    COMPLEX (KIND(0.0D0)) :: ZZD0X1,ZZD0X2,ZZD0Y2,ZZD1X1,ZZD1X2,ZZD1Y2
    COMPLEX (KIND(0.0D0)) :: ZZDBAR,ZZGBAR,ZZBAK
    COMPLEX (KIND(0.0D0)) :: ZZAMESS1,ZZAMESS2,ZZAMESS3,ZZAMESS4
    COMPLEX (KIND(0.0D0)) :: ZZBRACK,ZZCRACK
    !
    !***********************************************************************
    !
    !* ZDEL is the inner sphere convergence criterion
    !
    ZZX1 = PSIZE_PARAM_CORE*PPREFR_CORE
    ZZX2 = PSIZE_PARAM_CORE*PPREFR_COAT
    ZZY2 = PSIZE_PARAM_COAT*PPREFR_COAT
    ZSIZE_PARAM_STOP = PSIZE_PARAM_COAT + 4.*PSIZE_PARAM_COAT**0.3333 + 2.0
    ISTOP = INT(ZSIZE_PARAM_STOP)
    !
    ZZREFR_COAT_CORE = PPREFR_COAT/PPREFR_CORE
    !
    !         -----------------------------------------------------------
    !              series terminated after nstop terms
    !         -----------------------------------------------------------
    !
    !* Suffix 1 means CORE medium property
    !* Suffix 2 means COAT medium property
    !
    !
    !* Suffix x means CORE size
    !* Suffix y means COAT size
    !
    ZZD0X1 = COS(ZZX1)/SIN(ZZX1)
    ZZD0X2 = COS(ZZX2)/SIN(ZZX2)
    ZZD0Y2 = COS(ZZY2)/SIN(ZZY2)
    !
    ZPSI0Y = COS(PSIZE_PARAM_COAT)
    ZPSI1Y = SIN(PSIZE_PARAM_COAT)
    ZCHI0Y =-SIN(PSIZE_PARAM_COAT)
    ZCHI1Y = COS(PSIZE_PARAM_COAT)
    
    ZZXI0Y = CMPLX(ZPSI0Y,-ZCHI0Y,kind=kind(ZZXI0Y))
    ZZXI1Y = CMPLX(ZPSI1Y,-ZCHI1Y,kind=kind(ZZXI1Y))
    
    !
    ZZCHI0Y2 =-SIN(ZZY2)
    ZZCHI1Y2 = COS(ZZY2)
    ZZCHI0X2 =-SIN(ZZX2)
    ZZCHI1X2 = COS(ZZX2)
    !
    PQEXT = 0.0
    ZZBAK = (0.0,0.0)
    ZONE  = 1.0
    IFLAG = 0
    DO JJ = 1,ISTOP
    
      ZPSIY = (2.0*ZEN-1.)*ZPSI1Y/PSIZE_PARAM_COAT - ZPSI0Y
      ZCHIY = (2.0*ZEN-1.)*ZCHI1Y/PSIZE_PARAM_COAT - ZCHI0Y
    
      ZZXIY = CMPLX(ZPSIY,-ZCHIY,kind=kind(ZZXIY))
    
    !
      ZZD1Y2 = 1.0/(ZEN/ZZY2-ZZD0Y2) - ZEN/ZZY2
    !
      IF (IFLAG/=1) THEN
        ZZD1X1 = 1.0/(ZEN/ZZX1-ZZD0X1) - ZEN/ZZX1
        ZZD1X2 = 1.0/(ZEN/ZZX2-ZZD0X2) - ZEN/ZZX2
        ZZCHIX2 = (2.0*ZEN - 1.0)*ZZCHI1X2/ZZX2 - ZZCHI0X2
        ZZCHIY2 = (2.0*ZEN - 1.0)*ZZCHI1Y2/ZZY2 - ZZCHI0Y2
        ZZCHIPX2 = ZZCHI1X2 - ZEN*ZZCHIX2/ZZX2
        ZZCHIPY2 = ZZCHI1Y2 - ZEN*ZZCHIY2/ZZY2
        ZZANCAP = (ZZREFR_COAT_CORE*ZZD1X1         - ZZD1X2  )/ &
                  (ZZREFR_COAT_CORE*ZZD1X1*ZZCHIX2 - ZZCHIPX2)/ &
                          (ZZCHIX2*ZZD1X2 - ZZCHIPX2)
        ZZBRACK = ZZANCAP*(ZZCHIY2*ZZD1Y2 - ZZCHIPY2)
        ZZBNCAP = (ZZREFR_COAT_CORE*ZZD1X2   - ZZD1X1        )/ &
                  (ZZREFR_COAT_CORE*ZZCHIPX2 - ZZD1X1*ZZCHIX2)/ &
                          (ZZCHIX2*ZZD1X2 - ZZCHIPX2)
        ZZCRACK = ZZBNCAP*(ZZCHIY2*ZZD1Y2 - ZZCHIPY2)
    !
        ZZAMESS1 = ZZBRACK*ZZCHIPY2
        ZZAMESS2 = ZZBRACK*ZZCHIY2
        ZZAMESS3 = ZZCRACK*ZZCHIPY2
        ZZAMESS4 = ZZCRACK*ZZCHIY2
    !
        IF (ABS(ZZAMESS1)<ZDEL*ABS(ZZD1Y2) .OR. &
            ABS(ZZAMESS2)<ZDEL             .OR. &
            ABS(ZZAMESS3)<ZDEL*ABS(ZZD1Y2) .OR. &
            ABS(ZZAMESS4)<ZDEL                   ) THEN
          ZZBRACK = (0.,0.)
          ZZCRACK = (0.,0.)
          IFLAG   = 1
        END IF
      END IF
      ZZDBAR = (ZZD1Y2 - ZZBRACK*ZZCHIPY2)/(1.0-ZZBRACK*ZZCHIY2)
      ZZGBAR = (ZZD1Y2 - ZZCRACK*ZZCHIPY2)/(1.0-ZZCRACK*ZZCHIY2)
      ZZAN = ((ZZDBAR/PPREFR_COAT + ZEN/PSIZE_PARAM_COAT)*ZPSIY - ZPSI1Y) / &
             ((ZZDBAR/PPREFR_COAT + ZEN/PSIZE_PARAM_COAT)*ZZXIY - ZZXI1Y)
      ZZBN = ((PPREFR_COAT*ZZGBAR + ZEN/PSIZE_PARAM_COAT)*ZPSIY - ZPSI1Y) / &
             ((PPREFR_COAT*ZZGBAR + ZEN/PSIZE_PARAM_COAT)*ZZXIY - ZZXI1Y)
    !
      ZONE  = -ZONE
      ZZBAK = ZZBAK + (2.0*ZEN + 1.0)*ZONE*(ZZAN-ZZBN)
      PQEXT = PQEXT + (2.0*ZEN + 1.0)*     (REAL(ZZAN)+REAL(ZZBN))
    !
      ZPSI0Y = ZPSI1Y
      ZPSI1Y = ZPSIY
      ZCHI0Y = ZCHI1Y
      ZCHI1Y = ZCHIY
    
      ZZXI1Y = CMPLX(ZPSI1Y,-ZCHI1Y,kind=kind(ZZXI1Y))
    
    !
      ZZCHI0X2 = ZZCHI1X2
      ZZCHI1X2 = ZZCHIX2
      ZZCHI0Y2 = ZZCHI1Y2
      ZZCHI1Y2 = ZZCHIY2
    !
      ZZD0X1 = ZZD1X1
      ZZD0X2 = ZZD1X2
      ZZD0Y2 = ZZD1Y2
    END DO
    !
    PQEXT =  PQEXT*(2.0/(PSIZE_PARAM_COAT*PSIZE_PARAM_COAT))
    PQBAK = (ABS(ZZBAK)/ PSIZE_PARAM_COAT)**2
    RETURN
    END SUBROUTINE BHMIE_BHCOAT