-
WAUTELET Philippe authoredWAUTELET Philippe authored
bhmie_bhcoat.f90 6.79 KiB
!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
ZEN = REAL(JJ)
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