subroutine miev0 ( xx, crefin, perfct, mimcut, anyang, 1
$ numang, xmu, nmom, ipolzn, momdim, prnt,
$ qext, qsca, gqsc, pmom, sforw, sback, s1,
$ s2, tforw, tback )
c
c computes mie scattering and extinction efficiencies; asymmetry
c factor; forward- and backscatter amplitude; scattering
c amplitudes for incident polarization parallel and perpendicular
c to the plane of scattering, as functions of scattering angle;
c coefficients in the legendre polynomial expansions of either the
c unpolarized phase function or the polarized phase matrix;
c and some quantities needed in polarized radiative transfer.
c
c calls : biga, ckinmi, small1, small2, testmi, miprnt,
c lpcoef, errmsg
c
c i n t e r n a l v a r i a b l e s
c -----------------------------------
c
c an,bn mie coefficients little-a-sub-n, little-b-sub-n
c ( ref. 1, eq. 16 )
c anm1,bnm1 mie coefficients little-a-sub-(n-1),
c little-b-sub-(n-1); used in -gqsc- sum
c anp coeffs. in s+ expansion ( ref. 2, p. 1507 )
c bnp coeffs. in s- expansion ( ref. 2, p. 1507 )
c anpm coeffs. in s+ expansion ( ref. 2, p. 1507 )
c when mu is replaced by - mu
c bnpm coeffs. in s- expansion ( ref. 2, p. 1507 )
c when mu is replaced by - mu
c calcmo(k) true, calculate moments for k-th phase quantity
c (derived from -ipolzn-; used only in 'lpcoef')
c cbiga(n) bessel function ratio capital-a-sub-n (ref. 2, eq. 2)
c ( complex version )
c cior complex index of refraction with negative
c imaginary part (van de hulst convention)
c cioriv 1 / cior
c coeff ( 2n + 1 ) / ( n ( n + 1 ) )
c fn floating point version of index in loop performing
c mie series summation
c lita,litb(n) mie coefficients -an-, -bn-, saved in arrays for
c use in calculating legendre moments *pmom*
c maxtrm max. possible no. of terms in mie series
c mm + 1 and - 1, alternately.
c mim magnitude of imaginary refractive index
c mre real part of refractive index
c maxang max. possible value of input variable -numang-
c nangd2 (numang+1)/2 ( no. of angles in 0-90 deg; anyang=f )
c noabs true, sphere non-absorbing (determined by -mimcut-)
c np1dn ( n + 1 ) / n
c npquan highest-numbered phase quantity for which moments are
c to be calculated (the largest digit in -ipolzn-
c if ipolzn .ne. 0)
c ntrm no. of terms in mie series
c pass1 true on first entry, false thereafter; for self-test
c pin(j) angular function little-pi-sub-n ( ref. 2, eq. 3 )
c at j-th angle
c pinm1(j) little-pi-sub-(n-1) ( see -pin- ) at j-th angle
c psinm1 ricatti-bessel function psi-sub-(n-1), argument -xx-
c psin ricatti-bessel function psi-sub-n of argument -xx-
c ( ref. 1, p. 11 ff. )
c rbiga(n) bessel function ratio capital-a-sub-n (ref. 2, eq. 2)
c ( real version, for when imag refrac index = 0 )
c rioriv 1 / mre
c rn 1 / n
c rtmp (real) temporary variable
c sp(j) s+ for j-th angle ( ref. 2, p. 1507 )
c sm(j) s- for j-th angle ( ref. 2, p. 1507 )
c sps(j) s+ for (numang+1-j)-th angle ( anyang=false )
c sms(j) s- for (numang+1-j)-th angle ( anyang=false )
c taun angular function little-tau-sub-n ( ref. 2, eq. 4 )
c at j-th angle
c tcoef n ( n+1 ) ( 2n+1 ) (for summing tforw,tback series)
c twonp1 2n + 1
c yesang true if scattering amplitudes are to be calculated
c zetnm1 ricatti-bessel function zeta-sub-(n-1) of argument
c -xx- ( ref. 2, eq. 17 )
c zetn ricatti-bessel function zeta-sub-n of argument -xx-
c
c ----------------------------------------------------------------------
c -------- i / o specifications for subroutine miev0 -----------------
c ----------------------------------------------------------------------
implicit none
logical anyang, perfct, prnt(*)
integer ipolzn, momdim, numang, nmom
real*8 gqsc, mimcut, pmom( 0:momdim, * ), qext, qsca,
$ xmu(*), xx
complex*16 crefin, sforw, sback, s1(*), s2(*), tforw(*),
$ tback(*)
integer maxang,mxang2,maxtrm
real*8 onethr
c ----------------------------------------------------------------------
c
parameter ( maxang = 501, mxang2 = maxang/2 + 1 )
c
c ** note -- maxtrm = 10100 is neces-
c ** sary to do some of the test probs,
c ** but 1100 is sufficient for most
c ** conceivable applications
parameter ( maxtrm = 1100 )
parameter ( onethr = 1./3. )
c
logical anysav, calcmo(4), noabs, ok, pass1, persav, yesang
integer npquan
integer i,j,n,nmosav,iposav,numsav,ntrm,nangd2
real*8 mim, mimsav, mre, mm, np1dn
real*8 rioriv,xmusav,xxsav,sq,fn,rn,twonp1,tcoef, coeff
real*8 xinv,psinm1,chinm1,psin,chin,rtmp,taun
real*8 rbiga( maxtrm ), pin( maxang ), pinm1( maxang )
complex*16 an, bn, anm1, bnm1, anp, bnp, anpm, bnpm, cresav,
$ cior, cioriv, ctmp, zet, zetnm1, zetn
complex*16 cbiga( maxtrm ), lita( maxtrm ), litb( maxtrm ),
$ sp( maxang ), sm( maxang ), sps( mxang2 ), sms( mxang2 )
equivalence ( cbiga, rbiga )
save pass1
sq( ctmp ) = dble( ctmp )**2 + dimag( ctmp )**2
data pass1 / .true. /
c
c
if ( pass1 ) then
c ** save certain user input values
xxsav = xx
cresav = crefin
mimsav = mimcut
persav = perfct
anysav = anyang
nmosav = nmom
iposav = ipolzn
numsav = numang
xmusav = xmu( 1 )
c ** reset input values for test case
xx = 10.0
crefin = ( 1.5, - 0.1 )
perfct = .false.
mimcut = 0.0
anyang = .true.
numang = 1
xmu( 1 )= - 0.7660444
nmom = 1
ipolzn = - 1
c
end if
c ** check input and calculate
c ** certain variables from input
c
10 call ckinmi
( numang, maxang, xx, perfct, crefin, momdim,
$ nmom, ipolzn, anyang, xmu, calcmo, npquan )
c
if ( perfct .and. xx .le. 0.1 ) then
c ** use totally-reflecting
c ** small-particle limit
c
call small1
( xx, numang, xmu, qext, qsca, gqsc, sforw,
$ sback, s1, s2, tforw, tback, lita, litb )
ntrm = 2
go to 200
end if
c
if ( .not.perfct ) then
c
cior = crefin
if ( dimag( cior ) .gt. 0.0 ) cior = dconjg( cior )
mre = dble( cior )
mim = - dimag( cior )
noabs = mim .le. mimcut
cioriv = 1.0 / cior
rioriv = 1.0 / mre
c
if ( xx * dmax1( 1.d0, cdabs(cior) ) .le. 0.d1 ) then
c
c ** use general-refractive-index
c ** small-particle limit
c ** ( ref. 2, p. 1508 )
c
call small2
( xx, cior, .not.noabs, numang, xmu, qext,
$ qsca, gqsc, sforw, sback, s1, s2, tforw,
$ tback, lita, litb )
ntrm = 2
go to 200
end if
c
end if
c
nangd2 = ( numang + 1 ) / 2
yesang = numang .gt. 0
c ** estimate number of terms in mie series
c ** ( ref. 2, p. 1508 )
if ( xx.le.8.0 ) then
ntrm = xx + 4. * xx**onethr + 1.
else if ( xx.lt.4200. ) then
ntrm = xx + 4.05 * xx**onethr + 2.
else
ntrm = xx + 4. * xx**onethr + 2.
end if
if ( ntrm+1 .gt. maxtrm )
$ call errmsg
( 'miev0--parameter maxtrm too small', .true. )
c
c ** calculate logarithmic derivatives of
c ** j-bessel-fcn., big-a-sub-(1 to ntrm)
if ( .not.perfct )
$ call biga
( cior, xx, ntrm, noabs, yesang, rbiga, cbiga )
c
c ** initialize ricatti-bessel functions
c ** (psi,chi,zeta)-sub-(0,1) for upward
c ** recurrence ( ref. 1, eq. 19 )
xinv = 1.0 / xx
psinm1 = dsin( xx )
chinm1 = dcos( xx )
psin = psinm1 * xinv - chinm1
chin = chinm1 * xinv + psinm1
zetnm1 = dcmplx( psinm1, chinm1 )
zetn = dcmplx( psin, chin )
c ** initialize previous coeffi-
c ** cients for -gqsc- series
anm1 = ( 0.0, 0.0 )
bnm1 = ( 0.0, 0.0 )
c ** initialize angular function little-pi
c ** and sums for s+, s- ( ref. 2, p. 1507 )
if ( anyang ) then
do 60 j = 1, numang
pinm1( j ) = 0.0
pin( j ) = 1.0
sp ( j ) = ( 0.0, 0.0 )
sm ( j ) = ( 0.0, 0.0 )
60 continue
else
do 70 j = 1, nangd2
pinm1( j ) = 0.0
pin( j ) = 1.0
sp ( j ) = ( 0.0, 0.0 )
sm ( j ) = ( 0.0, 0.0 )
sps( j ) = ( 0.0, 0.0 )
sms( j ) = ( 0.0, 0.0 )
70 continue
end if
c ** initialize mie sums for efficiencies, etc.
qsca = 0.0
gqsc = 0.0
sforw = ( 0., 0. )
sback = ( 0., 0. )
tforw( 1 ) = ( 0., 0. )
tback( 1 ) = ( 0., 0. )
c
c
c --------- loop to sum mie series -----------------------------------
c
mm = + 1.0
do 100 n = 1, ntrm
c ** compute various numerical coefficients
fn = n
rn = 1.0 / fn
np1dn = 1.0 + rn
twonp1 = 2 * n + 1
coeff = twonp1 / ( fn * ( n + 1 ) )
tcoef = twonp1 * ( fn * ( n + 1 ) )
c
c ** calculate mie series coefficients
if ( perfct ) then
c ** totally-reflecting case
c
an = ( ( fn*xinv ) * psin - psinm1 ) /
$ ( ( fn*xinv ) * zetn - zetnm1 )
bn = psin / zetn
c
else if ( noabs ) then
c ** no-absorption case
c
an = ( ( rioriv*rbiga(n) + ( fn*xinv ) ) * psin - psinm1 )
$ / ( ( rioriv*rbiga(n) + ( fn*xinv ) ) * zetn - zetnm1 )
bn = ( ( mre * rbiga(n) + ( fn*xinv ) ) * psin - psinm1 )
$ / ( ( mre * rbiga(n) + ( fn*xinv ) ) * zetn - zetnm1 )
else
c ** absorptive case
c
an = ( ( cioriv * cbiga(n) + ( fn*xinv ) ) * psin - psinm1 )
$ /( ( cioriv * cbiga(n) + ( fn*xinv ) ) * zetn - zetnm1 )
bn = ( ( cior * cbiga(n) + ( fn*xinv ) ) * psin - psinm1 )
$ /( ( cior * cbiga(n) + ( fn*xinv ) ) * zetn - zetnm1 )
qsca = qsca + twonp1 * ( sq( an ) + sq( bn ) )
c
end if
c ** save mie coefficients for *pmom* calculation
lita( n ) = an
litb( n ) = bn
c ** increment mie sums for non-angle-
c ** dependent quantities
c
sforw = sforw + twonp1 * ( an + bn )
tforw( 1 ) = tforw( 1 ) + tcoef * ( an - bn )
sback = sback + ( mm * twonp1 ) * ( an - bn )
tback( 1 ) = tback( 1 ) + ( mm * tcoef ) * ( an + bn )
gqsc = gqsc + ( fn - rn ) * dble( anm1 * dconjg( an )
$ + bnm1 * dconjg( bn ) )
$ + coeff * dble( an * dconjg( bn ) )
c
if ( yesang ) then
c ** put mie coefficients in form
c ** needed for computing s+, s-
c ** ( ref. 2, p. 1507 )
anp = coeff * ( an + bn )
bnp = coeff * ( an - bn )
c ** increment mie sums for s+, s-
c ** while upward recursing
c ** angular functions little pi
c ** and little tau
if ( anyang ) then
c ** arbitrary angles
c
c ** vectorizable loop
do 80 j = 1, numang
rtmp = ( xmu( j ) * pin( j ) ) - pinm1( j )
taun = fn * rtmp - pinm1( j )
sp( j ) = sp( j ) + anp * ( pin( j ) + taun )
sm( j ) = sm( j ) + bnp * ( pin( j ) - taun )
pinm1( j ) = pin( j )
pin( j ) = ( xmu( j ) * pin( j ) ) + np1dn * rtmp
80 continue
c
else
c ** angles symmetric about 90 degrees
anpm = mm * anp
bnpm = mm * bnp
c ** vectorizable loop
do 90 j = 1, nangd2
rtmp = ( xmu( j ) * pin( j ) ) - pinm1( j )
taun = fn * rtmp - pinm1( j )
sp ( j ) = sp ( j ) + anp * ( pin( j ) + taun )
sms( j ) = sms( j ) + bnpm * ( pin( j ) + taun )
sm ( j ) = sm ( j ) + bnp * ( pin( j ) - taun )
sps( j ) = sps( j ) + anpm * ( pin( j ) - taun )
pinm1( j ) = pin( j )
pin( j ) = ( xmu( j ) * pin( j ) ) + np1dn * rtmp
90 continue
c
end if
end if
c ** update relevant quantities for next
c ** pass through loop
mm = - mm
anm1 = an
bnm1 = bn
c ** upward recurrence for ricatti-bessel
c ** functions ( ref. 1, eq. 17 )
c
zet = ( twonp1 * xinv ) * zetn - zetnm1
zetnm1 = zetn
zetn = zet
psinm1 = psin
psin = dble( zetn )
100 continue
c
c ---------- end loop to sum mie series --------------------------------
c
c
qext = 2. / xx**2 * dble( sforw )
if ( perfct .or. noabs ) then
qsca = qext
else
qsca = 2. / xx**2 * qsca
end if
c
gqsc = 4. / xx**2 * gqsc
sforw = 0.5 * sforw
sback = 0.5 * sback
tforw( 2 ) = 0.5 * ( sforw + 0.25 * tforw( 1 ) )
tforw( 1 ) = 0.5 * ( sforw - 0.25 * tforw( 1 ) )
tback( 2 ) = 0.5 * ( sback + 0.25 * tback( 1 ) )
tback( 1 ) = 0.5 * ( - sback + 0.25 * tback( 1 ) )
c
if ( yesang ) then
c ** recover scattering amplitudes
c ** from s+, s- ( ref. 1, eq. 11 )
if ( anyang ) then
c ** vectorizable loop
do 110 j = 1, numang
s1( j ) = 0.5 * ( sp( j ) + sm( j ) )
s2( j ) = 0.5 * ( sp( j ) - sm( j ) )
110 continue
c
else
c ** vectorizable loop
do 120 j = 1, nangd2
s1( j ) = 0.5 * ( sp( j ) + sm( j ) )
s2( j ) = 0.5 * ( sp( j ) - sm( j ) )
120 continue
c ** vectorizable loop
do 130 j = 1, nangd2
s1( numang+1 - j ) = 0.5 * ( sps( j ) + sms( j ) )
s2( numang+1 - j ) = 0.5 * ( sps( j ) - sms( j ) )
130 continue
end if
c
end if
c ** calculate legendre moments
200 if ( nmom.gt.0 )
$ call lpcoef
( ntrm, nmom, ipolzn, momdim, calcmo, npquan,
$ lita, litb, pmom )
c
if ( dimag(crefin) .gt. 0.0 ) then
c ** take complex conjugates
c ** of scattering amplitudes
sforw = dconjg( sforw )
sback = dconjg( sback )
do 210 i = 1, 2
tforw( i ) = dconjg( tforw(i) )
tback( i ) = dconjg( tback(i) )
210 continue
c
do 220 j = 1, numang
s1( j ) = dconjg( s1(j) )
s2( j ) = dconjg( s2(j) )
220 continue
c
end if
c
if ( pass1 ) then
c ** compare test case results with
c ** correct answers and abort if bad
c
call testmi
( qext, qsca, gqsc, sforw, sback, s1, s2,
$ tforw, tback, pmom, momdim, ok )
if ( .not. ok ) then
prnt(1) = .false.
prnt(2) = .false.
call miprnt
( prnt, xx, perfct, crefin, numang, xmu, qext,
$ qsca, gqsc, nmom, ipolzn, momdim, calcmo,
$ pmom, sforw, sback, tforw, tback, s1, s2 )
call errmsg
( 'miev0 -- self-test failed', .true. )
end if
c ** restore user input values
xx = xxsav
crefin = cresav
mimcut = mimsav
perfct = persav
anyang = anysav
nmom = nmosav
ipolzn = iposav
numang = numsav
xmu(1) = xmusav
pass1 = .false.
go to 10
c
end if
c
if ( prnt(1) .or. prnt(2) )
$ call miprnt
( prnt, xx, perfct, crefin, numang, xmu, qext,
$ qsca, gqsc, nmom, ipolzn, momdim, calcmo,
$ pmom, sforw, sback, tforw, tback, s1, s2 )
c
return
c
end
subroutine ckinmi( numang, maxang, xx, perfct, crefin, momdim, 1
$ nmom, ipolzn, anyang, xmu, calcmo, npquan )
c
c check for bad input to 'miev0' and calculate -calcmo,npquan-
c
implicit none
logical perfct, anyang, calcmo(*)
integer numang, maxang, momdim, nmom, ipolzn, npquan
real*8 xx, xmu(*)
integer i,l,j,ip
complex*16 crefin
c
character*4 string
logical inperr
c
inperr = .false.
c
if ( numang.gt.maxang ) then
call errmsg
( 'miev0--parameter maxang too small', .true. )
inperr = .true.
end if
if ( numang.lt.0 ) call wrtbad
( 'numang', inperr )
if ( xx.lt.0. ) call wrtbad
( 'xx', inperr )
if ( .not.perfct .and. dble(crefin).le.0. )then
print *,'crefin=',crefin
call wrtbad
( 'crefin', inperr )
endif
if ( momdim.lt.1 ) call wrtbad
( 'momdim', inperr )
c
if ( nmom.ne.0 ) then
if ( nmom.lt.0 .or. nmom.gt.momdim ) call wrtbad
('nmom',inperr)
if ( iabs(ipolzn).gt.4444 ) call wrtbad
( 'ipolzn', inperr )
npquan = 0
do 5 l = 1, 4
calcmo( l ) = .false.
5 continue
if ( ipolzn.ne.0 ) then
c ** parse out -ipolzn- into its digits
c ** to find which phase quantities are
c ** to have their moments calculated
c
write( string, '(i4)' ) iabs(ipolzn)
do 10 j = 1, 4
ip = ichar( string(j:j) ) - ichar( '0' )
if ( ip.ge.1 .and. ip.le.4 ) calcmo( ip ) = .true.
if ( ip.eq.0 .or. (ip.ge.5 .and. ip.le.9) )
$ call wrtbad
( 'ipolzn', inperr )
npquan = max0( npquan, ip )
10 continue
end if
end if
c
if ( anyang ) then
c ** allow for slight imperfections in
c ** computation of cosine
do 20 i = 1, numang
if ( xmu(i).lt.-1.00001 .or. xmu(i).gt.1.00001 )
$ call wrtbad
( 'xmu', inperr )
20 continue
else
do 22 i = 1, ( numang + 1 ) / 2
if ( xmu(i).lt.-0.00001 .or. xmu(i).gt.1.00001 )
$ call wrtbad
( 'xmu', inperr )
22 continue
end if
c
if ( inperr )
$ call errmsg
( 'miev0--input error(s). aborting...', .true. )
c
if ( xx.gt.20000.0 .or. dble(crefin).gt.10.0 .or.
$ dabs( dimag(crefin) ).gt.10.0 ) call errmsg
(
$ 'miev0--xx or crefin outside tested range', .false. )
c
return
end
subroutine lpcoef ( ntrm, nmom, ipolzn, momdim, calcmo, npquan, 1
$ a, b, pmom )
c
c calculate legendre polynomial expansion coefficients (also
c called moments) for phase quantities ( ref. 5 formulation )
c
c input: ntrm number terms in mie series
c nmom, ipolzn, momdim 'miev0' arguments
c calcmo flags calculated from -ipolzn-
c npquan defined in 'miev0'
c a, b mie series coefficients
c
c output: pmom legendre moments ('miev0' argument)
c
c *** notes ***
c
c (1) eqs. 2-5 are in error in dave, appl. opt. 9,
c 1888 (1970). eq. 2 refers to m1, not m2; eq. 3 refers to
c m2, not m1. in eqs. 4 and 5, the subscripts on the second
c term in square brackets should be interchanged.
c
c (2) the general-case logic in this subroutine works correctly
c in the two-term mie series case, but subroutine 'lpco2t'
c is called instead, for speed.
c
c (3) subroutine 'lpco1t', to do the one-term case, is never
c called within the context of 'miev0', but is included for
c complete generality.
c
c (4) some improvement in speed is obtainable by combining the
c 310- and 410-loops, if moments for both the third and fourth
c phase quantities are desired, because the third phase quantity
c is the real part of a complex series, while the fourth phase
c quantity is the imaginary part of that very same series. but
c most users are not interested in the fourth phase quantity,
c which is related to circular polarization, so the present
c scheme is usually more efficient.
c
implicit none
logical calcmo(*)
integer ipolzn, momdim, nmom, ntrm, npquan
real*8 pmom( 0:momdim, * )
complex*16 a(*), b(*)
c
c ** specification of local variables
c
c am(m) numerical coefficients a-sub-m-super-l
c in dave, eqs. 1-15, as simplified in ref. 5.
c
c bi(i) numerical coefficients b-sub-i-super-l
c in dave, eqs. 1-15, as simplified in ref. 5.
c
c bidel(i) 1/2 bi(i) times factor capital-del in dave
c
c cm,dm() arrays c and d in dave, eqs. 16-17 (mueller form),
c calculated using recurrence derived in ref. 5
c
c cs,ds() arrays c and d in ref. 4, eqs. a5-a6 (sekera form),
c calculated using recurrence derived in ref. 5
c
c c,d() either -cm,dm- or -cs,ds-, depending on -ipolzn-
c
c evenl true for even-numbered moments; false otherwise
c
c idel 1 + little-del in dave
c
c maxtrm max. no. of terms in mie series
c
c maxmom max. no. of non-zero moments
c
c nummom number of non-zero moments
c
c recip(k) 1 / k
c
integer maxtrm,maxmom,mxmom2,maxrcp
parameter ( maxtrm = 1102, maxmom = 2*maxtrm, mxmom2 = maxmom/2,
$ maxrcp = 4*maxtrm + 2 )
real*8 am( 0:maxtrm ), bi( 0:mxmom2 ), bidel( 0:mxmom2 ),
$ recip( maxrcp )
complex*16 cm( maxtrm ), dm( maxtrm ), cs( maxtrm ), ds( maxtrm ),
$ c( maxtrm ), d( maxtrm )
integer k,j,l,nummom,ld2,idel,m,i,mmax,imax
real*8 sum
equivalence ( c, cm ), ( d, dm )
logical pass1, evenl
save pass1, recip
data pass1 / .true. /
c
c
if ( pass1 ) then
c
do 1 k = 1, maxrcp
recip( k ) = 1.0 / k
1 continue
pass1 = .false.
c
end if
c
do 5 j = 1, max0( 1, npquan )
do 5 l = 0, nmom
pmom( l, j ) = 0.0
5 continue
c
if ( ntrm.eq.1 ) then
call lpco1t
( nmom, ipolzn, momdim, calcmo, a, b, pmom )
return
else if ( ntrm.eq.2 ) then
call lpco2t
( nmom, ipolzn, momdim, calcmo, a, b, pmom )
return
end if
c
if ( ntrm+2 .gt. maxtrm )
$ call errmsg
( 'lpcoef--parameter maxtrm too small', .true. )
c
c ** calculate mueller c, d arrays
cm( ntrm+2 ) = ( 0., 0. )
dm( ntrm+2 ) = ( 0., 0. )
cm( ntrm+1 ) = ( 1. - recip( ntrm+1 ) ) * b( ntrm )
dm( ntrm+1 ) = ( 1. - recip( ntrm+1 ) ) * a( ntrm )
cm( ntrm ) = ( recip(ntrm) + recip(ntrm+1) ) * a( ntrm )
$ + ( 1. - recip(ntrm) ) * b( ntrm-1 )
dm( ntrm ) = ( recip(ntrm) + recip(ntrm+1) ) * b( ntrm )
$ + ( 1. - recip(ntrm) ) * a( ntrm-1 )
c
do 10 k = ntrm-1, 2, -1
cm( k ) = cm( k+2 ) - ( 1. + recip(k+1) ) * b( k+1 )
$ + ( recip(k) + recip(k+1) ) * a( k )
$ + ( 1. - recip(k) ) * b( k-1 )
dm( k ) = dm( k+2 ) - ( 1. + recip(k+1) ) * a( k+1 )
$ + ( recip(k) + recip(k+1) ) * b( k )
$ + ( 1. - recip(k) ) * a( k-1 )
10 continue
cm( 1 ) = cm( 3 ) + 1.5 * ( a( 1 ) - b( 2 ) )
dm( 1 ) = dm( 3 ) + 1.5 * ( b( 1 ) - a( 2 ) )
c
if ( ipolzn.ge.0 ) then
c
do 20 k = 1, ntrm + 2
c( k ) = ( 2*k - 1 ) * cm( k )
d( k ) = ( 2*k - 1 ) * dm( k )
20 continue
c
else
c ** compute sekera c and d arrays
cs( ntrm+2 ) = ( 0., 0. )
ds( ntrm+2 ) = ( 0., 0. )
cs( ntrm+1 ) = ( 0., 0. )
ds( ntrm+1 ) = ( 0., 0. )
c
do 30 k = ntrm, 1, -1
cs( k ) = cs( k+2 ) + ( 2*k + 1 ) * ( cm( k+1 ) - b( k ) )
ds( k ) = ds( k+2 ) + ( 2*k + 1 ) * ( dm( k+1 ) - a( k ) )
30 continue
c
do 40 k = 1, ntrm + 2
c( k ) = ( 2*k - 1 ) * cs( k )
d( k ) = ( 2*k - 1 ) * ds( k )
40 continue
c
end if
c
c
if( ipolzn.lt.0 ) nummom = min0( nmom, 2*ntrm - 2 )
if( ipolzn.ge.0 ) nummom = min0( nmom, 2*ntrm )
if ( nummom .gt. maxmom )
$ call errmsg
( 'lpcoef--parameter maxtrm too small', .true. )
c
c ** loop over moments
do 500 l = 0, nummom
ld2 = l / 2
evenl = mod( l,2 ) .eq. 0
c ** calculate numerical coefficients
c ** a-sub-m and b-sub-i in dave
c ** double-sums for moments
if( l.eq.0 ) then
c
idel = 1
do 60 m = 0, ntrm
am( m ) = 2.0 * recip( 2*m + 1 )
60 continue
bi( 0 ) = 1.0
c
else if( evenl ) then
c
idel = 1
do 70 m = ld2, ntrm
am( m ) = ( 1. + recip( 2*m-l+1 ) ) * am( m )
70 continue
do 75 i = 0, ld2-1
bi( i ) = ( 1. - recip( l-2*i ) ) * bi( i )
75 continue
bi( ld2 ) = ( 2. - recip( l ) ) * bi( ld2-1 )
c
else
c
idel = 2
do 80 m = ld2, ntrm
am( m ) = ( 1. - recip( 2*m+l+2 ) ) * am( m )
80 continue
do 85 i = 0, ld2
bi( i ) = ( 1. - recip( l+2*i+1 ) ) * bi( i )
85 continue
c
end if
c ** establish upper limits for sums
c ** and incorporate factor capital-
c ** del into b-sub-i
mmax = ntrm - idel
if( ipolzn.ge.0 ) mmax = mmax + 1
imax = min0( ld2, mmax - ld2 )
if( imax.lt.0 ) go to 600
do 90 i = 0, imax
bidel( i ) = bi( i )
90 continue
if( evenl ) bidel( 0 ) = 0.5 * bidel( 0 )
c
c ** perform double sums just for
c ** phase quantities desired by user
if( ipolzn.eq.0 ) then
c
do 110 i = 0, imax
c ** vectorizable loop (cray)
sum = 0.0
do 100 m = ld2, mmax - i
sum = sum + am( m ) *
$ ( dble( c(m-i+1) * dconjg( c(m+i+idel) ) )
$ + dble( d(m-i+1) * dconjg( d(m+i+idel) ) ) )
100 continue
pmom( l,1 ) = pmom( l,1 ) + bidel( i ) * sum
110 continue
pmom( l,1 ) = 0.5 * pmom( l,1 )
go to 500
c
end if
c
if ( calcmo(1) ) then
do 160 i = 0, imax
c ** vectorizable loop (cray)
sum = 0.0
do 150 m = ld2, mmax - i
sum = sum + am( m ) *
$ dble( c(m-i+1) * dconjg( c(m+i+idel) ) )
150 continue
pmom( l,1 ) = pmom( l,1 ) + bidel( i ) * sum
160 continue
end if
c
c
if ( calcmo(2) ) then
do 210 i = 0, imax
c ** vectorizable loop (cray)
sum = 0.0
do 200 m = ld2, mmax - i
sum = sum + am( m ) *
$ dble( d(m-i+1) * dconjg( d(m+i+idel) ) )
200 continue
pmom( l,2 ) = pmom( l,2 ) + bidel( i ) * sum
210 continue
end if
c
c
if ( calcmo(3) ) then
do 310 i = 0, imax
c ** vectorizable loop (cray)
sum = 0.0
do 300 m = ld2, mmax - i
sum = sum + am( m ) *
$ ( dble( c(m-i+1) * dconjg( d(m+i+idel) ) )
$ + dble( c(m+i+idel) * dconjg( d(m-i+1) ) ) )
300 continue
pmom( l,3 ) = pmom( l,3 ) + bidel( i ) * sum
310 continue
pmom( l,3 ) = 0.5 * pmom( l,3 )
end if
c
c
if ( calcmo(4) ) then
do 410 i = 0, imax
c ** vectorizable loop (cray)
sum = 0.0
do 400 m = ld2, mmax - i
sum = sum + am( m ) *
$ ( dimag( c(m-i+1) * dconjg( d(m+i+idel) ) )
$ + dimag( c(m+i+idel) * dconjg( d(m-i+1) ) ))
400 continue
pmom( l,4 ) = pmom( l,4 ) + bidel( i ) * sum
410 continue
pmom( l,4 ) = - 0.5 * pmom( l,4 )
end if
c
500 continue
c
c
600 return
end
subroutine lpco1t ( nmom, ipolzn, momdim, calcmo, a, b, pmom ) 1
c
c calculate legendre polynomial expansion coefficients (also
c called moments) for phase quantities in special case where
c no. terms in mie series = 1
c
c input: nmom, ipolzn, momdim 'miev0' arguments
c calcmo flags calculated from -ipolzn-
c a(1), b(1) mie series coefficients
c
c output: pmom legendre moments
c
implicit none
logical calcmo(*)
integer ipolzn, momdim, nmom,nummom,l
real*8 pmom( 0:momdim, * ),sq,a1sq,b1sq
complex*16 a(*), b(*), ctmp, a1b1c
sq( ctmp ) = dble( ctmp )**2 + dimag( ctmp )**2
c
c
a1sq = sq( a(1) )
b1sq = sq( b(1) )
a1b1c = a(1) * dconjg( b(1) )
c
if( ipolzn.lt.0 ) then
c
if( calcmo(1) ) pmom( 0,1 ) = 2.25 * b1sq
if( calcmo(2) ) pmom( 0,2 ) = 2.25 * a1sq
if( calcmo(3) ) pmom( 0,3 ) = 2.25 * dble( a1b1c )
if( calcmo(4) ) pmom( 0,4 ) = 2.25 *dimag( a1b1c )
c
else
c
nummom = min0( nmom, 2 )
c ** loop over moments
do 100 l = 0, nummom
c
if( ipolzn.eq.0 ) then
if( l.eq.0 ) pmom( l,1 ) = 1.5 * ( a1sq + b1sq )
if( l.eq.1 ) pmom( l,1 ) = 1.5 * dble( a1b1c )
if( l.eq.2 ) pmom( l,1 ) = 0.15 * ( a1sq + b1sq )
go to 100
end if
c
if( calcmo(1) ) then
if( l.eq.0 ) pmom( l,1 ) = 2.25 * ( a1sq + b1sq / 3. )
if( l.eq.1 ) pmom( l,1 ) = 1.5 * dble( a1b1c )
if( l.eq.2 ) pmom( l,1 ) = 0.3 * b1sq
end if
c
if( calcmo(2) ) then
if( l.eq.0 ) pmom( l,2 ) = 2.25 * ( b1sq + a1sq / 3. )
if( l.eq.1 ) pmom( l,2 ) = 1.5 * dble( a1b1c )
if( l.eq.2 ) pmom( l,2 ) = 0.3 * a1sq
end if
c
if( calcmo(3) ) then
if( l.eq.0 ) pmom( l,3 ) = 3.0 * dble( a1b1c )
if( l.eq.1 ) pmom( l,3 ) = 0.75 * ( a1sq + b1sq )
if( l.eq.2 ) pmom( l,3 ) = 0.3 * dble( a1b1c )
end if
c
if( calcmo(4) ) then
if( l.eq.0 ) pmom( l,4 ) = - 1.5 * dimag( a1b1c )
if( l.eq.1 ) pmom( l,4 ) = 0.0
if( l.eq.2 ) pmom( l,4 ) = 0.3 * dimag( a1b1c )
end if
c
100 continue
c
end if
c
return
end
subroutine lpco2t ( nmom, ipolzn, momdim, calcmo, a, b, pmom ) 1
c
c calculate legendre polynomial expansion coefficients (also
c called moments) for phase quantities in special case where
c no. terms in mie series = 2
c
c input: nmom, ipolzn, momdim 'miev0' arguments
c calcmo flags calculated from -ipolzn-
c a(1-2), b(1-2) mie series coefficients
c
c output: pmom legendre moments
c
implicit none
logical calcmo(*)
integer ipolzn, momdim, nmom,l,nummom
real*8 pmom( 0:momdim, * ),sq,a1sq,b1sq,pm1,pm2,a2sq,b2sq
complex*16 a(*), b(*)
complex*16 a2c, b2c, ctmp, ca, cac, cat, cb, cbc, cbt, cg, ch
sq( ctmp ) = dble( ctmp )**2 + dimag( ctmp )**2
c
c
ca = 3. * a(1) - 5. * b(2)
cat= 3. * b(1) - 5. * a(2)
cac = dconjg( ca )
a2sq = sq( a(2) )
b2sq = sq( b(2) )
a2c = dconjg( a(2) )
b2c = dconjg( b(2) )
c
if( ipolzn.lt.0 ) then
c ** loop over sekera moments
nummom = min0( nmom, 2 )
do 50 l = 0, nummom
c
if( calcmo(1) ) then
if( l.eq.0 ) pmom( l,1 ) = 0.25 * ( sq(cat) +
$ (100./3.) * b2sq )
if( l.eq.1 ) pmom( l,1 ) = (5./3.) * dble( cat * b2c )
if( l.eq.2 ) pmom( l,1 ) = (10./3.) * b2sq
end if
c
if( calcmo(2) ) then
if( l.eq.0 ) pmom( l,2 ) = 0.25 * ( sq(ca) +
$ (100./3.) * a2sq )
if( l.eq.1 ) pmom( l,2 ) = (5./3.) * dble( ca * a2c )
if( l.eq.2 ) pmom( l,2 ) = (10./3.) * a2sq
end if
c
if( calcmo(3) ) then
if( l.eq.0 ) pmom( l,3 ) = 0.25 * dble( cat*cac +
$ (100./3.)*b(2)*a2c )
if( l.eq.1 ) pmom( l,3 ) = 5./6. * dble( b(2)*cac +
$ cat*a2c )
if( l.eq.2 ) pmom( l,3 ) = 10./3. * dble( b(2) * a2c )
end if
c
if( calcmo(4) ) then
if( l.eq.0 ) pmom( l,4 ) = -0.25 * dimag( cat*cac +
$ (100./3.)*b(2)*a2c )
if( l.eq.1 ) pmom( l,4 ) = -5./6. * dimag( b(2)*cac +
$ cat*a2c )
if( l.eq.2 ) pmom( l,4 ) = -10./3. * dimag( b(2) * a2c )
end if
c
50 continue
c
else
c
cb = 3. * b(1) + 5. * a(2)
cbt= 3. * a(1) + 5. * b(2)
cbc = dconjg( cb )
cg = ( cbc*cbt + 10.*( cac*a(2) + b2c*cat) ) / 3.
ch = 2.*( cbc*a(2) + b2c*cbt )
c
c ** loop over mueller moments
nummom = min0( nmom, 4 )
do 100 l = 0, nummom
c
if( ipolzn.eq.0 .or. calcmo(1) ) then
if( l.eq.0 ) pm1 = 0.25 * sq(ca) + sq(cb) / 12.
$ + (5./3.) * dble(ca*b2c) + 5.*b2sq
if( l.eq.1 ) pm1 = dble( cb * ( cac/6. + b2c ) )
if( l.eq.2 ) pm1 = sq(cb)/30. + (20./7.) * b2sq
$ + (2./3.) * dble( ca * b2c )
if( l.eq.3 ) pm1 = (2./7.) * dble( cb * b2c )
if( l.eq.4 ) pm1 = (40./63.) * b2sq
if ( calcmo(1) ) pmom( l,1 ) = pm1
end if
c
if( ipolzn.eq.0 .or. calcmo(2) ) then
if( l.eq.0 ) pm2 = 0.25*sq(cat) + sq(cbt) / 12.
$ + (5./3.) * dble(cat*a2c) + 5.*a2sq
if( l.eq.1 ) pm2 = dble( cbt * ( dconjg(cat)/6. + a2c) )
if( l.eq.2 ) pm2 = sq(cbt)/30. + (20./7.) * a2sq
$ + (2./3.) * dble( cat * a2c )
if( l.eq.3 ) pm2 = (2./7.) * dble( cbt * a2c )
if( l.eq.4 ) pm2 = (40./63.) * a2sq
if ( calcmo(2) ) pmom( l,2 ) = pm2
end if
c
if( ipolzn.eq.0 ) then
pmom( l,1 ) = 0.5 * ( pm1 + pm2 )
go to 100
end if
c
if( calcmo(3) ) then
if( l.eq.0 ) pmom( l,3 ) = 0.25 * dble( cac*cat + cg +
$ 20.*b2c*a(2) )
if( l.eq.1 ) pmom( l,3 ) = dble( cac*cbt + cbc*cat +
$ 3.*ch ) / 12.
if( l.eq.2 ) pmom( l,3 ) = 0.1 * dble( cg + (200./7.) *
$ b2c * a(2) )
if( l.eq.3 ) pmom( l,3 ) = dble( ch ) / 14.
if( l.eq.4 ) pmom( l,3 ) = 40./63. * dble( b2c * a(2) )
end if
c
if( calcmo(4) ) then
if( l.eq.0 ) pmom( l,4 ) = 0.25 * dimag( cac*cat + cg +
$ 20.*b2c*a(2) )
if( l.eq.1 ) pmom( l,4 ) = dimag( cac*cbt + cbc*cat +
$ 3.*ch ) / 12.
if( l.eq.2 ) pmom( l,4 ) = 0.1 * dimag( cg + (200./7.) *
$ b2c * a(2) )
if( l.eq.3 ) pmom( l,4 ) = dimag( ch ) / 14.
if( l.eq.4 ) pmom( l,4 ) = 40./63. * dimag( b2c * a(2) )
end if
c
100 continue
c
end if
c
return
end
subroutine biga( cior, xx, ntrm, noabs, yesang, rbiga, cbiga ) 1
c
c calculate logarithmic derivatives of j-bessel-function
c
c input : cior, xx, ntrm, noabs, yesang (defined in 'miev0')
c
c output : rbiga or cbiga (defined in 'miev0')
c
c internal variables :
c
c confra value of lentz continued fraction for -cbiga(ntrm)-,
c used to initialize downward recurrence.
c down = true, use down-recurrence. false, do not.
c f1,f2,f3 arithmetic statement functions used in determining
c whether to use up- or down-recurrence
c ( ref. 2, eqs. 6-8 )
c mre real refractive index
c mim imaginary refractive index
c rezinv 1 / ( mre * xx ); temporary variable for recurrence
c zinv 1 / ( cior * xx ); temporary variable for recurrence
c
implicit none
logical down, noabs, yesang
integer ntrm,n
real*8 mre, mim, rbiga(*), xx, rezinv, rtmp, f1,f2,f3
complex*16 cior, ctmp, confra, cbiga(*), zinv
f1( mre ) = - 8.0 + mre**2 * ( 26.22 + mre * ( - 0.4474
$ + mre**3 * ( 0.00204 - 0.000175 * mre ) ) )
f2( mre ) = 3.9 + mre * ( - 10.8 + 13.78 * mre )
f3( mre ) = - 15.04 + mre * ( 8.42 + 16.35 * mre )
c
c ** decide whether 'biga' can be
c ** calculated by up-recurrence
mre = dble( cior )
mim = dabs( dimag( cior ) )
if ( mre.lt.1.0 .or. mre.gt.10.0 .or. mim.gt.10.0 ) then
down = .true.
else if ( yesang ) then
down = .true.
if ( mim*xx .lt. f2( mre ) ) down = .false.
else
down = .true.
if ( mim*xx .lt. f1( mre ) ) down = .false.
end if
c
zinv = 1.0 / ( cior * xx )
rezinv = 1.0 / ( mre * xx )
c
if ( down ) then
c ** compute initial high-order 'biga' using
c ** lentz method ( ref. 1, pp. 17-20 )
c
ctmp = confra
( ntrm, zinv, xx )
c
c *** downward recurrence for 'biga'
c *** ( ref. 1, eq. 22 )
if ( noabs ) then
c ** no-absorption case
rbiga( ntrm ) = dble( ctmp )
do 25 n = ntrm, 2, - 1
rbiga( n-1 ) = (n*rezinv)
$ - 1.0 / ( (n*rezinv) + rbiga( n ) )
25 continue
c
else
c ** absorptive case
cbiga( ntrm ) = ctmp
do 30 n = ntrm, 2, - 1
cbiga( n-1 ) = (n*zinv) - 1.0 / ( (n*zinv) + cbiga( n ) )
30 continue
c
end if
c
else
c *** upward recurrence for 'biga'
c *** ( ref. 1, eqs. 20-21 )
if ( noabs ) then
c ** no-absorption case
rtmp = dsin( mre*xx )
rbiga( 1 ) = - rezinv
$ + rtmp / ( rtmp*rezinv - dcos( mre*xx ) )
do 40 n = 2, ntrm
rbiga( n ) = - ( n*rezinv )
$ + 1.0 / ( ( n*rezinv ) - rbiga( n-1 ) )
40 continue
c
else
c ** absorptive case
ctmp = cdexp( - dcmplx(0.d0,2.d0) * cior * xx )
cbiga( 1 ) = - zinv + (1.-ctmp) / ( zinv * (1.-ctmp) -
$ dcmplx(0.d0,1.d0)*(1.+ctmp) )
do 50 n = 2, ntrm
cbiga( n ) = - (n*zinv) + 1.0 / ((n*zinv) - cbiga( n-1 ))
50 continue
end if
c
end if
c
return
end
complex*16 function confra
( n, zinv, xx )
c
c compute bessel function ratio capital-a-sub-n from its
c continued fraction using lentz method ( ref. 1, pp. 17-20 )
c
c zinv = reciprocal of argument of capital-a
c
c i n t e r n a l v a r i a b l e s
c ------------------------------------
c
c cak term in continued fraction expansion of capital-a
c ( ref. 1, eq. 25 )
c capt factor used in lentz iteration for capital-a
c ( ref. 1, eq. 27 )
c cdenom denominator in -capt- ( ref. 1, eq. 28b )
c cnumer numerator in -capt- ( ref. 1, eq. 28a )
c cdtd product of two successive denominators of -capt-
c factors ( ref. 1, eq. 34c )
c cntn product of two successive numerators of -capt-
c factors ( ref. 1, eq. 34b )
c eps1 ill-conditioning criterion
c eps2 convergence criterion
c kk subscript k of -cak- ( ref. 1, eq. 25b )
c kount iteration counter ( used only to prevent runaway )
c maxit max. allowed no. of iterations
c mm + 1 and - 1, alternately
c
implicit none
integer n,maxit,mm,kk,kount
real*8 xx,eps1,eps2
complex*16 zinv
complex*16 cak, capt, cdenom, cdtd, cnumer, cntn
data eps1 / 1.e - 2 /, eps2 / 1.e - 8 /
data maxit / 10000 /
c
c *** ref. 1, eqs. 25a, 27
confra = ( n + 1 ) * zinv
mm = - 1
kk = 2 * n + 3
cak = ( mm * kk ) * zinv
cdenom = cak
cnumer = cdenom + 1.0 / confra
kount = 1
c
20 kount = kount + 1
if ( kount.gt.maxit )
$ call errmsg
( 'confra--iteration failed to converge$', .true.)
c
c *** ref. 2, eq. 25b
mm = - mm
kk = kk + 2
cak = ( mm * kk ) * zinv
c *** ref. 2, eq. 32
if ( cdabs( cnumer/cak ).le.eps1
$ .or. cdabs( cdenom/cak ).le.eps1 ) then
c
c ** ill-conditioned case -- stride
c ** two terms instead of one
c
c *** ref. 2, eqs. 34
cntn = cak * cnumer + 1.0
cdtd = cak * cdenom + 1.0
confra = ( cntn / cdtd ) * confra
c *** ref. 2, eq. 25b
mm = - mm
kk = kk + 2
cak = ( mm * kk ) * zinv
c *** ref. 2, eqs. 35
cnumer = cak + cnumer / cntn
cdenom = cak + cdenom / cdtd
kount = kount + 1
go to 20
c
else
c ** well-conditioned case
c
c *** ref. 2, eqs. 26, 27
capt = cnumer / cdenom
confra = capt * confra
c ** check for convergence
c ** ( ref. 2, eq. 31 )
c
if ( dabs( dble(capt) - 1.0 ).ge.eps2
$ .or. dabs( dimag(capt) ) .ge.eps2 ) then
c
c *** ref. 2, eqs. 30a-b
cnumer = cak + 1.0 / cnumer
cdenom = cak + 1.0 / cdenom
go to 20
end if
end if
c
return
c
end
subroutine miprnt( prnt, xx, perfct, crefin, numang, xmu, 2
$ qext, qsca, gqsc, nmom, ipolzn, momdim,
$ calcmo, pmom, sforw, sback, tforw, tback,
$ s1, s2 )
c
c print scattering quantities of a single particle
c
implicit none
logical perfct, prnt(*), calcmo(*)
integer ipolzn, momdim, nmom, numang,i,m,j
real*8 gqsc, pmom( 0:momdim, * ), qext, qsca, xx, xmu(*)
real*8 fi1,fi2,fnorm
complex*16 crefin, sforw, sback, tforw(*), tback(*), s1(*), s2(*)
character*22 fmt
c
c
if ( perfct ) write ( 59, '(''1'',10x,a,1p,e11.4)' )
$ 'perfectly conducting case, size parameter =', xx
if ( .not.perfct ) write ( 59, '(''1'',10x,3(a,1p,e11.4))' )
$ 'refractive index: real ', dble(crefin),
$ ' imag ', dimag(crefin), ', size parameter =', xx
c
if ( prnt(1) .and. numang.gt.0 ) then
c
write ( 59, '(/,a)' )
$ ' cos(angle) ------- s1 --------- ------- s2 ---------'//
$ ' --- s1*conjg(s2) --- i1=s1**2 i2=s2**2 (i1+i2)/2'//
$ ' deg polzn'
do 10 i = 1, numang
fi1 = dble( s1(i) ) **2 + dimag( s1(i) )**2
fi2 = dble( s2(i) ) **2 + dimag( s2(i) )**2
write( 59, '( i4, f10.6, 1p,10e11.3 )' )
$ i, xmu(i), s1(i), s2(i), s1(i)*dconjg(s2(i)),
$ fi1, fi2, 0.5*(fi1+fi2), (fi2-fi1)/(fi2+fi1)
10 continue
c
end if
c
c
if ( prnt(2) ) then
c
write ( 59, '(/,a,9x,a,17x,a,17x,a,/,(0p,f7.2, 1p,6e12.3) )' )
$ ' angle', 's-sub-1', 't-sub-1', 't-sub-2',
$ 0.0, sforw, tforw(1), tforw(2),
$ 180., sback, tback(1), tback(2)
write ( 59, '(/,4(a,1p,e11.4))' )
$ ' efficiency factors, extinction:', qext,
$ ' scattering:', qsca,
$ ' absorption:', qext-qsca,
$ ' rad. pressure:', qext-gqsc
c
if ( nmom.gt.0 ) then
c
write( 59, '(/,a)' ) ' normalized moments of :'
if ( ipolzn.eq.0 ) write ( 59, '(''+'',27x,a)' ) 'phase fcn'
if ( ipolzn.gt.0 ) write ( 59, '(''+'',33x,a)' )
$ 'm1 m2 s21 d21'
if ( ipolzn.lt.0 ) write ( 59, '(''+'',33x,a)' )
$ 'r1 r2 r3 r4'
c
fnorm = 4. / ( xx**2 * qsca )
do 20 m = 0, nmom
write ( 59, '(a,i4)' ) ' moment no.', m
do 20 j = 1, 4
if( calcmo(j) ) then
write( fmt, 98 ) 24 + (j-1)*13
write ( 59,fmt ) fnorm * pmom(m,j)
end if
20 continue
end if
c
end if
c
return
c
98 format( '( ''+'', t', i2, ', 1p,e13.4 )' )
end
subroutine small1 ( xx, numang, xmu, qext, qsca, gqsc, sforw, 1
$ sback, s1, s2, tforw, tback, a, b )
c
c small-particle limit of mie quantities in totally reflecting
c limit ( mie series truncated after 2 terms )
c
c a,b first two mie coefficients, with numerator and
c denominator expanded in powers of -xx- ( a factor
c of xx**3 is missing but is restored before return
c to calling program ) ( ref. 2, p. 1508 )
c
implicit none
integer numang,j
real*8 gqsc, qext, qsca, xx, xmu(*)
real*8 twothr,fivthr,fivnin,sq,rtmp
complex*16 a( 2 ), b( 2 ), sforw, sback, s1(*), s2(*),
$ tforw(*), tback(*)
c
parameter ( twothr = 2./3., fivthr = 5./3., fivnin = 5./9. )
complex*16 ctmp
sq( ctmp ) = dble( ctmp )**2 + dimag( ctmp )**2
c
c
a( 1 ) = dcmplx ( 0.d0, twothr * ( 1. - 0.2 * xx**2 ) )
$ / dcmplx ( 1.d0 - 0.5 * xx**2, twothr * xx**3 )
c
b( 1 ) = dcmplx ( 0.d0, - ( 1. - 0.1 * xx**2 ) / 3. )
$ / dcmplx ( 1.d0 + 0.5 * xx**2, - xx**3 / 3. )
c
a( 2 ) = dcmplx ( 0.d0, xx**2 / 30. )
b( 2 ) = dcmplx ( 0.d0, - xx**2 / 45. )
c
qsca = 6. * xx**4 * ( sq( a(1) ) + sq( b(1) )
$ + fivthr * ( sq( a(2) ) + sq( b(2) ) ) )
qext = qsca
gqsc = 6. * xx**4 * dble( a(1) * dconjg( a(2) + b(1) )
$ + ( b(1) + fivnin * a(2) ) * dconjg( b(2) ) )
c
rtmp = 1.5 * xx**3
sforw = rtmp * ( a(1) + b(1) + fivthr * ( a(2) + b(2) ) )
sback = rtmp * ( a(1) - b(1) - fivthr * ( a(2) - b(2) ) )
tforw( 1 ) = rtmp * ( b(1) + fivthr * ( 2.*b(2) - a(2) ) )
tforw( 2 ) = rtmp * ( a(1) + fivthr * ( 2.*a(2) - b(2) ) )
tback( 1 ) = rtmp * ( b(1) - fivthr * ( 2.*b(2) + a(2) ) )
tback( 2 ) = rtmp * ( a(1) - fivthr * ( 2.*a(2) + b(2) ) )
c
do 10 j = 1, numang
s1( j ) = rtmp * ( a(1) + b(1) * xmu(j) + fivthr *
$ ( a(2) * xmu(j) + b(2) * ( 2.*xmu(j)**2 - 1. )) )
s2( j ) = rtmp * ( b(1) + a(1) * xmu(j) + fivthr *
$ ( b(2) * xmu(j) + a(2) * ( 2.*xmu(j)**2 - 1. )) )
10 continue
c ** recover actual mie coefficients
a( 1 ) = xx**3 * a( 1 )
a( 2 ) = xx**3 * a( 2 )
b( 1 ) = xx**3 * b( 1 )
b( 2 ) = xx**3 * b( 2 )
c
return
end
subroutine small2 ( xx, cior, calcqe, numang, xmu, qext, qsca, 1
$ gqsc, sforw, sback, s1, s2, tforw, tback,
$ a, b )
c
c small-particle limit of mie quantities for general refractive
c index ( mie series truncated after 2 terms )
c
c a,b first two mie coefficients, with numerator and
c denominator expanded in powers of -xx- ( a factor
c of xx**3 is missing but is restored before return
c to calling program ) ( ref. 2, p. 1508 )
c
c ciorsq square of refractive index
c
implicit none
logical calcqe
integer numang,j
real*8 gqsc, qext, qsca, xx, xmu(*)
real*8 twothr,fivthr,sq,rtmp
complex*16 a( 2 ), b( 2 ), cior, sforw, sback, s1(*), s2(*),
$ tforw(*), tback(*)
c
parameter ( twothr = 2./3., fivthr = 5./3. )
complex*16 ctmp, ciorsq
sq( ctmp ) = dble( ctmp )**2 + dimag( ctmp )**2
c
c
ciorsq = cior**2
ctmp = dcmplx( 0.d0, twothr ) * ( ciorsq - 1.0 )
a(1) = ctmp * ( 1.0 - 0.1 * xx**2 + (ciorsq/350. + 1./280.)*xx**4)
$ / ( ciorsq + 2.0 + ( 1.0 - 0.7 * ciorsq ) * xx**2
$ - ( ciorsq**2/175. - 0.275 * ciorsq + 0.25 ) * xx**4
$ + xx**3 * ctmp * ( 1.0 - 0.1 * xx**2 ) )
c
b(1) = (xx**2/30.) * ctmp * ( 1.0 + (ciorsq/35. - 1./14.) *xx**2 )
$ / ( 1.0 - ( ciorsq/15. - 1./6. ) * xx**2 )
c
a(2) = ( 0.1 * xx**2 ) * ctmp * ( 1.0 - xx**2 / 14. )
$ / ( 2. * ciorsq + 3. - ( ciorsq/7. - 0.5 ) * xx**2 )
c
qsca = 6. * xx**4 * ( sq(a(1)) + sq(b(1)) + fivthr * sq(a(2)) )
gqsc = 6. * xx**4 * dble( a(1) * dconjg( a(2) + b(1) ) )
qext = qsca
if ( calcqe ) qext = 6. * xx * dble( a(1) + b(1) + fivthr * a(2) )
c
rtmp = 1.5 * xx**3
sforw = rtmp * ( a(1) + b(1) + fivthr * a(2) )
sback = rtmp * ( a(1) - b(1) - fivthr * a(2) )
tforw( 1 ) = rtmp * ( b(1) - fivthr * a(2) )
tforw( 2 ) = rtmp * ( a(1) + 2. * fivthr * a(2) )
tback( 1 ) = tforw( 1 )
tback( 2 ) = rtmp * ( a(1) - 2. * fivthr * a(2) )
c
do 10 j = 1, numang
s1( j ) = rtmp * ( a(1) + ( b(1) + fivthr * a(2) ) * xmu(j) )
s2( j ) = rtmp * ( b(1) + a(1) * xmu(j) + fivthr * a(2)
$ * ( 2. * xmu(j)**2 - 1. ) )
10 continue
c ** recover actual mie coefficients
a( 1 ) = xx**3 * a( 1 )
a( 2 ) = xx**3 * a( 2 )
b( 1 ) = xx**3 * b( 1 )
b( 2 ) = ( 0., 0. )
c
return
end
subroutine testmi ( qext, qsca, gqsc, sforw, sback, s1, s2, 1
$ tforw, tback, pmom, momdim, ok )
c
c compare mie code test case results with correct answers
c and return ok=false if even one result is inaccurate.
c
c the test case is : mie size parameter = 10
c refractive index = 1.5 - 0.1 i
c scattering angle = 140 degrees
c 1 sekera moment
c
c results for this case may be found among the test cases
c at the end of reference (1).
c
c *** note *** when running on some computers, esp. in single
c precision, the 'accur' criterion below may have to be relaxed.
c however, if 'accur' must be set larger than 10**-3 for some
c size parameters, your computer is probably not accurate
c enough to do mie computations for those size parameters.
c
implicit none
integer momdim,m,n
real*8 qext, qsca, gqsc, pmom( 0:momdim, * )
complex*16 sforw, sback, s1(*), s2(*), tforw(*), tback(*)
logical ok, wrong
c
real*8 accur, testqe, testqs, testgq, testpm( 0:1 )
complex*16 testsf, testsb,tests1,tests2,testtf(2), testtb(2)
data testqe / 2.459791 /, testqs / 1.235144 /,
$ testgq / 1.139235 /, testsf / ( 61.49476, -3.177994 ) /,
$ testsb / ( 1.493434, 0.2963657 ) /,
$ tests1 / ( -0.1548380, -1.128972) /,
$ tests2 / ( 0.05669755, 0.5425681) /,
$ testtf / ( 12.95238, -136.6436 ), ( 48.54238, 133.4656 ) /,
$ testtb / ( 41.88414, -15.57833 ), ( 43.37758, -15.28196 )/,
$ testpm / 227.1975, 183.6898 /
real*8 calc,exact
c data accur / 1.e-5 /
data accur / 1.e-4 /
wrong( calc, exact ) = dabs( (calc - exact) / exact ) .gt. accur
c
c
ok = .true.
if ( wrong( qext,testqe ) )
$ call tstbad
( 'qext', abs((qext - testqe) / testqe), ok )
if ( wrong( qsca,testqs ) )
$ call tstbad
( 'qsca', abs((qsca - testqs) / testqs), ok )
if ( wrong( gqsc,testgq ) )
$ call tstbad
( 'gqsc', abs((gqsc - testgq) / testgq), ok )
c
if ( wrong( dble(sforw), dble(testsf) ) .or.
$ wrong( dimag(sforw), dimag(testsf) ) )
$ call tstbad
( 'sforw', cdabs((sforw - testsf) / testsf), ok )
c
if ( wrong( dble(sback), dble(testsb) ) .or.
$ wrong( dimag(sback), dimag(testsb) ) )
$ call tstbad
( 'sback', cdabs((sback - testsb) / testsb), ok )
c
if ( wrong( dble(s1(1)), dble(tests1) ) .or.
$ wrong( dimag(s1(1)), dimag(tests1) ) )
$ call tstbad
( 's1', cdabs((s1(1) - tests1) / tests1), ok )
c
if ( wrong( dble(s2(1)), dble(tests2) ) .or.
$ wrong( dimag(s2(1)), dimag(tests2) ) )
$ call tstbad
( 's2', cdabs((s2(1) - tests2) / tests2), ok )
c
do 20 n = 1, 2
if ( wrong( dble(tforw(n)), dble(testtf(n)) ) .or.
$ wrong( dimag(tforw(n)), dimag(testtf(n)) ) )
$ call tstbad
( 'tforw', cdabs( (tforw(n) - testtf(n)) /
$ testtf(n) ), ok )
if ( wrong( dble(tback(n)), dble(testtb(n)) ) .or.
$ wrong( dimag(tback(n)), dimag(testtb(n)) ) )
$ call tstbad
( 'tback', cdabs( (tback(n) - testtb(n)) /
$ testtb(n) ), ok )
20 continue
c
do 30 m = 0, 1
if ( wrong( pmom(m,1), testpm(m) ) )
$ call tstbad
( 'pmom', dabs( (pmom(m,1)-testpm(m)) /
$ testpm(m) ), ok )
30 continue
c
return
c
end
subroutine errmsg( messag, fatal ) 9
c
c print out a warning or error message; abort if error
c
implicit none
logical fatal, once
character*(*) messag
integer maxmsg, nummsg
save maxmsg, nummsg, once
data nummsg / 0 /, maxmsg / 100 /, once / .false. /
c
c
if ( fatal ) then
write ( *, '(2a)' ) ' ******* error >>>>>> ', messag
stop
end if
c
nummsg = nummsg + 1
if ( nummsg.gt.maxmsg ) then
if ( .not.once ) write ( *,99 )
once = .true.
else
write ( *, '(2a)' ) ' ******* warning >>>>>> ', messag
endif
c
return
c
99 format( ///,' >>>>>> too many warning messages -- ',
$ 'they will no longer be printed <<<<<<<', /// )
end
subroutine wrtbad ( varnam, erflag ) 9
c
c write names of erroneous variables
c
c input : varnam = name of erroneous variable to be written
c ( character, any length )
c
c output : erflag = logical flag, set true by this routine
c ----------------------------------------------------------------------
implicit none
character*(*) varnam
logical erflag
integer maxmsg, nummsg
save nummsg, maxmsg
data nummsg / 0 /, maxmsg / 50 /
c
c
nummsg = nummsg + 1
write ( *, '(3a)' ) ' **** input variable ', varnam,
$ ' in error ****'
erflag = .true.
if ( nummsg.eq.maxmsg )
$ call errmsg
( 'too many input errors. aborting...$', .true. )
return
c
end
subroutine tstbad( varnam, relerr, ok ) 10
c
c write name (-varnam-) of variable failing self-test and its
c percent error from the correct value. return ok = false.
c
implicit none
character*(*) varnam
logical ok
real*8 relerr
c
c
ok = .false.
write( *, '(/,3a,1p,e11.2,a)' )
$ ' output variable ', varnam,' differed by', 100.*relerr,
$ ' per cent from correct value. self-test failed.'
return
c
end