module modal_aer_opt 3,10
#ifdef MODAL_AERO
! parameterizes aerosol coefficients using chebychev polynomial
! parameterize aerosol radiative properties in terms of
! surface mode wet radius and wet refractive index
! Ghan and Zaveri, JGR 2007.
! uses Wiscombe's (1979) mie scattering code
use shr_kind_mod
, only: r8 => shr_kind_r8
use ppgrid
, only: pcols, pver, pverp, begchunk, endchunk
use abortutils
, only: endrun
use constituents
, only: pcnst
use spmd_utils
, only: masterproc
use error_messages
, only: handle_ncerr
use modal_aero_data, only: maxd_amode, maxd_aspectype, ntot_amode, ntot_aspectype, &
nspec_amode, lspectype_amode, lmassptr_amode, numptr_amode, alnsg_amode, &
specrefndxsw, specrefndxlw, specdens_amode, &
!++xl added 11/24/2009, dust AOD
lptr_dust_a_amode, specdens_dust_amode, &
!--dust AOD
sigmag_amode, species_class, spec_class_aerosol
use physconst
, only: rhoh2o
use cam_history
, only: phys_decomp, addfld, add_default
use perf_mod
use radconstants
, only: nswbands, nlwbands
use cam_logfile
, only: iulog
implicit none
private
save
public :: modal_aer_opt_init, modal_size_parameters, modal_aero_sw, modal_aero_lw
integer nrefr,nrefi,nr,ni
integer, parameter :: prefr=7,prefi=10
integer, parameter, public :: ncoef=5
! coefficients for parameterizing aerosol radiative properties
! in terms of refractive index and wet radius
real(r8) extpsw(ncoef,prefr,prefi,maxd_amode,nswbands) ! specific extinction
real(r8) abspsw(ncoef,prefr,prefi,maxd_amode,nswbands) ! specific absorption
real(r8) asmpsw(ncoef,prefr,prefi,maxd_amode,nswbands) ! asymmetry factor
real(r8) extplw(ncoef,prefr,prefi,maxd_amode,nlwbands) ! specific extinction
real(r8) absplw(ncoef,prefr,prefi,maxd_amode,nlwbands) ! specific absorption
real(r8) asmplw(ncoef,prefr,prefi,maxd_amode,nlwbands) ! asymmetry factor
#ifdef AEROCOM
logical saveaerocom
complex crefw_aerocom(naerocom)
real(r8) extp_aerocom(ncoef,prefr,prefi,maxd_amode,naerocom)
real(r8) absp_aerocom(ncoef,prefr,prefi,maxd_amode,naerocom)
real(r8) asmp_aerocom(ncoef,prefr,prefi,maxd_amode,naerocom)
real(r8) refrtab_aerocom(prefr,naerocom),refitab_aerocom(prefi,naerocom)
#endif
integer, parameter :: pnangle=1
! specabs = absorption coeff / unit dry mass
! specscat = scattering coeff / unit dry mass
complex crefin
complex, public :: crefwsw(nswbands) ! complex refractive index for water visible
complex, public :: crefwlw(nlwbands) ! complex refractive index for water infrared
real(r8), pointer :: refrwsw(:),refiwsw(:) ! real, imaginary ref index for water visible
real(r8), pointer :: refrwlw(:),refiwlw(:) ! real, imaginary ref index for water infrared
! data refrwsw/19*1.33/
! data refiwsw/8*1.e-9,1.5e-8,7*1.e-5,6.e-2,2*1.e-2/
real(r8) pie
real(r8) rmmin,rmmax ! min, max aerosol surface mode radius treated (m)
real(r8) xrmin,xrmax
real(r8) refrmin ! minimum of real part of refractive index
real(r8) refrmax ! maximum of real part of refractive index
real(r8) refimin ! minimum of imag part of refractive index
real(r8) refimax ! maximum of imag part of refractive index
real(r8) refrtabsw(prefr,nswbands) ! table of real refractive indices for aerosols visible
real(r8) refitabsw(prefi,nswbands) ! table of imag refractive indices for aerosols visible
real(r8) refrtablw(prefr,nlwbands) ! table of real refractive indices for aerosols infrared
real(r8) refitablw(prefi,nlwbands) ! table of imag refractive indices for aerosols infrared
#if (defined BACKSCAT)
real(r8) angmin, angmax=3.14 ! minimum, maximum scattering angle
real(r8) ang(pnangle), xmu(pnangle)
#endif
!===============================================================================
CONTAINS
!===============================================================================
subroutine modal_aer_opt_init(wavminsw,wavmaxsw,wavenumber1_longwave,wavenumber2_longwave),55
use rad_constituents
, only: rad_cnst_get_clim_aer_props
use ioFileMod
, only: getfil
use filenames
, only: modal_optics
#if ( defined SPMD )
use mpishorthand
, only: mpicom, mpiint, mpir8, mpichar
#endif
implicit none
real(r8), intent(in):: wavmaxsw(nswbands)
real(r8), intent(in):: wavminsw(nswbands)
real(r8), intent(in):: wavenumber1_longwave(nlwbands) ! (cm-1)
real(r8), intent(in):: wavenumber2_longwave(nlwbands) ! (cm-1)
real(r8) wavmidsw(nswbands) ! middle wavelength of shortwave band (m)
real(r8) wavmidlw(nlwbands) ! middle wavelength of longwave band (m)
real(r8) refr,refi
integer lw_band_len
integer :: nc_id ! index to netcdf file
character*256 outfilename,infilename
logical, parameter :: calc_optics = .false.
integer :: ierr ! error codes from pio
integer ns, m, l, ltype
call rad_cnst_get_clim_aer_props
(1, &
refindex_real_water_sw=refrwsw, &
refindex_im_water_sw=refiwsw, &
refindex_real_water_lw=refrwlw, &
refindex_im_water_lw=refiwlw)
pie=4._r8*atan(1._r8)
nrefr=prefr
nrefi=prefi
rmmin=0.01e-6
rmmax=25.e-6
xrmin=log(rmmin)
xrmax=log(rmmax)
#if (defined BACKSCAT)
angmin=1.1 ! minimum scattering angle between satellite and sun
angmax=3.14 ! backscattering
ang(1)=angmax ! backscatter angle only
do i=1,pnangle
xmu(i)=cos(ang(i))
enddo
#endif
if(calc_optics)then
! wavelength loop
do 200 ns=1,nswbands
! wavelength (m)
wavmidsw(ns) = 0.5e-6*(wavminsw(ns) + wavmaxsw(ns))
! write(iulog,*)'wavelength=',wavmidsw(ns)
! first find min,max of real and imaginary parts of refractive index
! real and imaginary parts of water refractive index
crefwsw(ns)=cmplx(refrwsw(ns),refiwsw(ns))
refrmin=real(crefwsw(ns))
refrmax=real(crefwsw(ns))
refimin=aimag(crefwsw(ns))
refimax=aimag(crefwsw(ns))
! aerosol mode loop
do m=1,ntot_amode
! aerosol species loop
do l=1,nspec_amode(m)
ltype=lspectype_amode(l,m)
! real and imaginary parts of aerosol refractive index
refr=real(specrefndxsw(ns,ltype))
refi=aimag(specrefndxsw(ns,ltype))
refrmin=min(refrmin,refr)
refrmax=max(refrmax,refr)
refimin=min(refimin,refi)
refimax=max(refimax,refi)
enddo
enddo
! write(iulog,*)'sw band ',ns
! write(iulog,*)'refrmin=',refrmin
! write(iulog,*)'refrmax=',refrmax
! write(iulog,*)'refimin=',refimin
! write(iulog,*)'refimax=',refimax
if(refimin<-1.e-3)then
write(iulog,*)'negative refractive indices not allowed'
call endrun
('error in modal_aer_opt_init')
endif
call miefit
(wavmidsw(ns),refrtabsw(1,ns),refitabsw(1,ns), &
extpsw(1,1,1,1,ns),abspsw(1,1,1,1,ns),asmpsw(1,1,1,1,ns) )
200 continue
do 300 ns=1,nlwbands
! wavmidir=10.e-6 ! wavelength (m) at 10 microns
wavmidlw(ns) = 0.5e-2*(1._r8/wavenumber1_longwave(ns) + 1._r8/wavenumber1_longwave(ns))
! first find min,max of real and imaginary parts of infrared (10 micron) refractive index
! real and imaginary parts of water refractive index
! refrwir=1.179 ! Kent et al., Applied Optics, 22, 1655-1665, 1983
! refiwir=0.6777 ! Kent et al., Applied Optics, 22, 1655-1665, 1983
crefwlw(ns)=cmplx(refrwlw(ns),refiwlw(ns))
refrmin=real(crefwlw(ns))
refrmax=real(crefwlw(ns))
refimin=aimag(crefwlw(ns))
refimax=aimag(crefwlw(ns))
! aerosol mode loop
do m=1,ntot_amode
! aerosol species loop
do l=1,nspec_amode(m)
ltype=lspectype_amode(l,m)
! real and imaginary parts of aerosol refractive index
refr=real(specrefndxlw(ns,ltype))
refi=aimag(specrefndxlw(ns,ltype))
refrmin=min(refrmin,refr)
refrmax=max(refrmax,refr)
refimin=min(refimin,refi)
refimax=max(refimax,refi)
enddo
enddo
! write(iulog,*)'longwave band ',ns
! write(iulog,*)'refrmin=',refrmin
! write(iulog,*)'refrmax=',refrmax
! write(iulog,*)'refimin=',refimin
! write(iulog,*)'refimax=',refimax
call miefit
(wavmidlw(ns),refrtablw(1,ns),refitablw(1,ns), &
extplw(1,1,1,1,ns),absplw(1,1,1,1,ns),asmplw(1,1,1,1,ns) )
300 continue
outfilename='modal_optics.nc'
call write_modal_optics
(outfilename, maxd_amode, nlwbands, nswbands, &
refrtabsw, refitabsw, refrtablw, refitablw, &
prefr, prefi, sigmag_amode, ncoef, extpsw, abspsw, asmpsw, absplw )
else
infilename='modal_optics.nc'
call getfil
(modal_optics, infilename)
write(iulog,*)'modal_optics filename=',infilename
call read_modal_optics
(infilename, maxd_amode, nlwbands, nswbands, &
refrtabsw, refitabsw, refrtablw, refitablw, &
prefr, prefi, ncoef, extpsw, abspsw, asmpsw, absplw )
do ns=1,nswbands
wavmidsw(ns) = 0.5e-6*(wavminsw(ns) + wavmaxsw(ns))
crefwsw(ns)=cmplx(refrwsw(ns),refiwsw(ns))
end do
do ns=1,nlwbands
! wavmidir=10.e-6 ! wavelength (m) at 10 microns
! wavmidlw(ns) = 0.5e-6*(wavminlw(ns) + wavmaxlw(ns))
wavmidlw(ns) = 0.5e-2*(1._r8/wavenumber1_longwave(ns) + 1._r8/wavenumber1_longwave(ns))
! real and imaginary parts of water refractive index
crefwlw(ns)=cmplx(refrwlw(ns),refiwlw(ns))
end do
endif
call addfld
('EXTINCT','/m ',pver, 'A','Aerosol extinction',phys_decomp, flag_xyfill=.true.)
call addfld
('ABSORB','/m ',pver, 'A','Aerosol absorption',phys_decomp, flag_xyfill=.true.)
call addfld
('AODVIS',' ',1, 'A','Aerosol optical depth 550 nm',phys_decomp, flag_xyfill=.true.)
call addfld
('AODABS',' ',1, 'A','Aerosol absorption optical depth 550 nm',phys_decomp, flag_xyfill=.true.)
call addfld
('AODMODE1',' ',1, 'A','Aerosol optical depth 550 nm mode 1',phys_decomp, flag_xyfill=.true.)
call addfld
('AODMODE2',' ',1, 'A','Aerosol optical depth 550 nm mode 2',phys_decomp, flag_xyfill=.true.)
call addfld
('AODMODE3',' ',1, 'A','Aerosol optical depth 550 nm mode 3',phys_decomp, flag_xyfill=.true.)
call addfld
('AODMODE4',' ',1, 'A','Aerosol optical depth 550 nm mode 4',phys_decomp, flag_xyfill=.true.)
call addfld
('AODMODE5',' ',1, 'A','Aerosol optical depth 550 nm mode 5',phys_decomp, flag_xyfill=.true.)
call addfld
('AODMODE6',' ',1, 'A','Aerosol optical depth 550 nm mode 6',phys_decomp, flag_xyfill=.true.)
call addfld
('AODMODE7',' ',1, 'A','Aerosol optical depth 550 nm mode 7',phys_decomp, flag_xyfill=.true.)
!++xl added 11/24/2009, dust AOD
call addfld
('AODDUST1',' ',1, 'A','Aerosol optical depth 550 nm model 1 from dust',phys_decomp, flag_xyfill=.true.)
call addfld
('AODDUST2',' ',1, 'A','Aerosol optical depth 550 nm model 2 from dust',phys_decomp, flag_xyfill=.true.)
call addfld
('AODDUST3',' ',1, 'A','Aerosol optical depth 550 nm model 3 from dust',phys_decomp, flag_xyfill=.true.)
!--dust AOD
call addfld
('BURDEN1','kg/m2',1, 'A','Aerosol burden mode 1',phys_decomp, flag_xyfill=.true.)
call addfld
('BURDEN2','kg/m2',1, 'A','Aerosol burden mode 2',phys_decomp, flag_xyfill=.true.)
call addfld
('BURDEN3','kg/m2',1, 'A','Aerosol burden mode 3',phys_decomp, flag_xyfill=.true.)
call addfld
('BURDEN4','kg/m2',1, 'A','Aerosol burden mode 4',phys_decomp, flag_xyfill=.true.)
call addfld
('BURDEN5','kg/m2',1, 'A','Aerosol burden mode 5',phys_decomp, flag_xyfill=.true.)
call addfld
('BURDEN6','kg/m2',1, 'A','Aerosol burden mode 6',phys_decomp, flag_xyfill=.true.)
call addfld
('BURDEN7','kg/m2',1, 'A','Aerosol burden mode 7',phys_decomp, flag_xyfill=.true.)
call addfld
('SSAVIS',' ',1, 'A','Aerosol singel-scatter albedo',phys_decomp, flag_xyfill=.true.)
call add_default
('EXTINCT', 1, ' ')
call add_default
('ABSORB', 1, ' ')
call add_default
('AODVIS', 1, ' ')
call add_default
('AODABS', 1, ' ')
call add_default
('AODMODE1', 1, ' ')
call add_default
('AODMODE2', 1, ' ')
call add_default
('AODMODE3', 1, ' ')
#if (defined MODAL_AERO_7MODE)
call add_default
('AODMODE4', 1, ' ')
call add_default
('AODMODE5', 1, ' ')
call add_default
('AODMODE6', 1, ' ')
call add_default
('AODMODE7', 1, ' ')
#endif
!++xl added 11/24/2009, dust AOD
call add_default
('AODDUST1', 1, ' ')
call add_default
('AODDUST2', 1, ' ')
call add_default
('AODDUST3', 1, ' ')
!--dust AOD
call add_default
('BURDEN1', 1, ' ')
call add_default
('BURDEN2', 1, ' ')
call add_default
('BURDEN3', 1, ' ')
#if (defined MODAL_AERO_7MODE)
call add_default
('BURDEN4', 1, ' ')
call add_default
('BURDEN5', 1, ' ')
call add_default
('BURDEN6', 1, ' ')
call add_default
('BURDEN7', 1, ' ')
#endif
call add_default
('SSAVIS', 1, ' ')
end subroutine modal_aer_opt_init
subroutine modal_size_parameters(ncol, dgnumwet, radsurf, logradsurf, cheb) 1,1
use phys_buffer
, only: pbuf_size_max, pbuf_fld, pbuf_get_fld_idx
implicit none
integer, intent(in) :: ncol
real(r8), intent(in) :: dgnumwet(pcols,pver,maxd_amode) ! aerosol wet number mode diameter (m)
real(r8), intent(out) :: radsurf(pcols,pver,maxd_amode) ! aerosol surface mode radius
real(r8), intent(out) :: logradsurf(pcols,pver,maxd_amode) ! log(aerosol surface mode radius)
real(r8), intent(out) :: cheb(ncoef,maxd_amode,pcols,pver)
integer m,l,lmass,lnum,i,k,nc,ifld,lwater
real(r8) explnsigma
real(r8) xrad(pcols) ! normalized aerosol radius
do m=1,ntot_amode
explnsigma=exp(2.0_r8*alnsg_amode(m)*alnsg_amode(m))
do k=1,pver
do i=1,ncol
! convert from number mode diameter to surface area
radsurf(i,k,m)=0.5*dgnumwet(i,k,m)*explnsigma
logradsurf(i,k,m)=log(radsurf(i,k,m))
! normalize size parameter
xrad(i)=max(logradsurf(i,k,m),xrmin)
xrad(i)=min(xrad(i),xrmax)
xrad(i)=(2._r8*xrad(i)-xrmax-xrmin)/(xrmax-xrmin)
! chebyshev polynomials
cheb(1,m,i,k)=1._r8
cheb(2,m,i,k)=xrad(i)
do nc=3,ncoef
cheb(nc,m,i,k)=2._r8*xrad(i)*cheb(nc-1,m,i,k)-cheb(nc-2,m,i,k)
enddo
end do
end do
end do
end subroutine modal_size_parameters
subroutine miefit(wavmid,refrtab,refitab, extparam,absparam,asmparam) 2,4
implicit none
integer nsiz ! number of wet particle sizes
integer nlog ! number of log-normals modes to product mie fit
parameter (nsiz=200,nlog=30)
real(r8) rad(nsiz)
real(r8) wavmid
real(r8) extparam(ncoef,prefr,prefi,maxd_amode)
real(r8) absparam(ncoef,prefr,prefi,maxd_amode)
real(r8) asmparam(ncoef,prefr,prefi,maxd_amode)
real(r8) refrtab(prefr),refitab(prefi)
real(r8) size ! 2 pi radpart / waveleng = size parameter
real(r8) qext(nsiz) ! array of extinction efficiencies
real(r8) qsca(nsiz) ! array of scattering efficiencies
real(r8) qabs(nsiz) ! array of absorption efficiencies
real(r8) gqsc(nsiz) ! array of asymmetry factor * scattering efficiency
real(r8) asymm(nsiz) ! array of asymmetry factor
complex*16 sforw,sback,tforw(2),tback(2),refindx
integer :: nmom,ipolzn,momdim,numang
real(r8) pmom(0:1,1)
logical :: perfct,prnt(2)
complex*16 crefd
real(r8) :: mimcut
logical :: anyang
real(r8) xmu
complex*16 s1(1),s2(1)
real(r8) dsdlogr(nsiz),dlogr
real(r8) rmin,rmax ! min, max aerosol size bin
real(r8) xr
real(r8) drefr ! increment in real part of refractive index
real(r8) drefi ! increment in imag part of refractive index
integer m,n,nr,ni,nl
real(r8) exparg
real(r8) volwet ! sum of volume of wet aerosols
real(r8) sumabs ! sum of specific absorption coefficients
real(r8) sumsca ! sum of specific scattering coefficients
real(r8) sumg ! sum of asymmetry factors
real(r8) rs(nlog) ! surface mode radius (cm)
real(r8) specscat(nlog) ! specific scattering (m2/g)
real(r8) specabs(nlog) ! specific absorption (m2/g)
real(r8) specext(nlog) ! specfiic extinction (m2/g)
real(r8) abs(nlog) ! single scattering albedo
real(r8) asym(nlog) ! asymmetry factor
real(r8) logr(nsiz)
real(r8) bma,bpa
real(r8) sq2pi
sq2pi=2.5066283
nmom=0
ipolzn=0
momdim=1
perfct=.false.
prnt(1)=.false.
prnt(2)=.false.
mimcut=0.0_r8
anyang=.false.
numang=0
drefr=(refrmax-refrmin)/(nrefr-1)
! size bins (m)
rmin=0.001e-6
rmax=100.e-6
dlogr=log(rmax/rmin)/(nsiz-1)
logr(1)=log(rmin)
do n=2,nsiz
logr(n)=logr(n-1)+dlogr
enddo
do n=1,nsiz
rad(n)=exp(logr(n))
enddo
! calibrate parameterization with range of refractive indices
do 120 nr=1,nrefr
do 120 ni=1,nrefi
refrtab(nr)=refrmin+(nr-1)*drefr
refitab(ni)=refimax*0.3**(nrefi-ni)
if(ni.eq.1)refitab(ni)=0.
crefd=dcmplx(refrtab(nr),refitab(ni))
! write(iulog,*)'nr,ni,refr,refi=',nr,ni,refrtab(nr),refitab(ni)
! mie calculations of optical efficiencies
do n=1,nsiz
! size parameter and weighted refractive index
size=2.*pie*rad(n)/wavmid
size=min(size,400.d0)
call miev0
(size,crefd,perfct,mimcut,anyang, &
numang,xmu,nmom,ipolzn,momdim,prnt, &
qext(n),qsca(n),gqsc(n),pmom,sforw,sback,s1, &
s2,tforw,tback )
qsca(n)=min(qsca(n),qext(n))
qabs(n)=qext(n)-qsca(n)
asymm(n)=gqsc(n)/qsca(n)
! if(nr.eq.1.and.ni.eq.1)then
! write(iulog,*)'rad=',rad(n),' qsca,qabs=',qsca(n),qabs(n)
! endif
enddo
! now consider a variety of lognormal size distributions
! with surface mode radius rs (m) and log standard deviation alnsg_amode
! aerosol mode loop
do 110 m=1,ntot_amode
! size units are m
! bounds of surface mode radius
bma=0.5*log(rmmax/rmmin)
bpa=0.5*log(rmmax*rmmin)
do 100 nl=1,nlog
! pick rs to match zeroes of chebychev
xr=cos(pie*(nl-0.5)/nlog)
rs(nl)=exp(xr*bma+bpa)
! define wet size distribution
! integrate over all size bins
volwet=0
sumsca=0
sumabs=0
sumg=0
do n=1,nsiz
exparg=log(rad(n)/rs(nl))/alnsg_amode(m)
dsdlogr(n)=exp(-0.5*exparg*exparg)
volwet=volwet+4./3.*rad(n)*dsdlogr(n)*dlogr
sumabs=sumabs+qabs(n)*dsdlogr(n)*dlogr
sumsca=sumsca+qsca(n)*dsdlogr(n)*dlogr
sumg=sumg+asymm(n)*qsca(n)*dsdlogr(n)*dlogr
enddo
! coefficients wrt wet mass, using water density
specscat(nl)=sumsca/(volwet*rhoh2o)
specabs(nl)=sumabs/(volwet*rhoh2o)
! coefficients wrt wet mass
specext(nl)=specscat(nl)+specabs(nl)
asym(nl)=sumg/sumsca
!if(nr.eq.1.and.ni.eq.1)then
if(m.eq.3.and.wavmid.gt.0.45e-6.and.wavmid.lt.0.6e-6)then
! write(98,*)'rs=',rs(nl),' cref=',refrtab(nr),refitab(ni),' specext=',specext(nl)
endif
! endif
100 continue
call fitcurv
(rs,specext,extparam(1,nr,ni,m),ncoef,nlog)
call fitcurvlin
(rs,specabs,absparam(1,nr,ni,m),ncoef,nlog)
call fitcurvlin
(rs,asym,asmparam(1,nr,ni,m),ncoef,nlog)
110 continue
120 continue
! write(iulog,*)'refitab=',(refitab(ni),ni=1,nrefi)
return
end subroutine miefit
subroutine modal_aero_sw(ncol,lchnk,iswband, nnite, idxnite, tauxar,wa,ga,fa, raer, state, & 1,30
qaerwat, radsurf, logradsurf, cheb )
! calculates aerosol radiative properties
use ppgrid
use physconst
, only: rga, rair
use physics_types
, only: physics_state
use radconstants
, only: idx_sw_diag
use cam_history
, only: outfld, fillvalue
implicit none
integer, intent(in) :: ncol ! number of columns
integer, intent(in) :: lchnk ! chunk index
integer, intent(in) :: iswband ! spectral interval
integer, intent(in) :: nnite ! number of night columns
integer, intent(in) :: idxnite(nnite) ! local column indices of night columns
real(r8), intent(in) :: raer(pcols, pver, pcnst)
type(physics_state), intent(in) :: state
real(r8), intent(in) :: qaerwat(pcols,pver,maxd_amode) ! aerosol water (g/g)
real(r8), intent(in) :: radsurf(pcols,pver,maxd_amode) ! aerosol surface mode radius
real(r8), intent(in) :: logradsurf(pcols,pver,maxd_amode) ! log(aerosol surface mode radius)
real(r8), intent(in) :: cheb(ncoef,maxd_amode,pcols,pver)
real(r8), intent(out) :: tauxar(pcols,0:pver) ! layer extinction optical depth
real(r8), intent(out) :: wa(pcols,0:pver) ! layer single-scatter albedo
real(r8), intent(out) :: ga(pcols,0:pver) ! asymmetry factor
real(r8), intent(out) :: fa(pcols,0:pver) ! forward scattered fraction
integer i,k
real(r8) pext(pcols) ! parameterized specific extinction (m2/kg)
real(r8) specpext(pcols) ! specific extinction (m2/kg)
real(r8) pabs(pcols) ! parameterized specific absorption (m2/kg)
real(r8) palb(pcols) ! parameterized single scattering albedo
real(r8) pasm(pcols) ! parameterized asymmetry factor
real(r8) :: mass(pcols,pver) ! layer mass
real(r8) totmass(pcols)
real(r8) vol(pcols) ! volume concentration of aerosol specie (m3/kg)
real(r8) volsol(pcols) ! volume concentration of soluble aerosol specie (m3/kg)
real(r8) volinsol(pcols) ! volume concentration of insoluble aerosol specie (m3/kg)
real(r8) dryvol(pcols) ! volume concentration of aerosol mode (m3/kg)
real(r8) dryvolsol(pcols) ! volume concentration of soluble aerosol mode (m3/kg)
real(r8) dryvolinsol(pcols) ! volume concentration of insoluble aerosol mode (m3/kg)
real(r8) wetvol(pcols) ! volume concentration of wet mode (m3/kg)
real(r8) watervol(pcols) ! volume concentration of water in each mode (m3/kg)
real(r8) volf ! volume fraction of insoluble aerosol
real(r8) refr(pcols) ! real part of refractive index
real(r8) refi(pcols) ! imaginary part of refractive index
real(r8) :: aodvis(pcols) ! extinction optical depth
real(r8) :: aodabs(pcols) ! absorption optical depth
real(r8) :: aodmode(pcols,maxd_amode)
real(r8) :: burden(pcols,maxd_amode)
!++xl added 11/24/2009, dust AOD
real(r8) :: dustvol(pcols) ! volume concentration of dust in aerosol mode (m3/kg)
real(r8) :: dustaodmode(pcols,maxd_amode) ! dust aod in aerosol mode
!--dust AOD
real(r8) :: ssavis(pcols)
real(r8) :: extinct(pcols,pver)
real(r8) :: absorb(pcols,pver)
logical :: savaervis ! true if visible wavelength (0.55 micron)
complex crefin(pcols), crefsol(pcols), crefinsol(pcols) ! complex refractive index
complex crefinsq, crefsolsq, crefinsolsq
complex crefa, crefb
integer lmass,ltype
integer itab(pcols),jtab(pcols)
real(r8) ttab(pcols),utab(pcols)
real(r8) cext(pcols,ncoef),cabs(pcols,ncoef),casm(pcols,ncoef)
real(r8) air_density(pcols,pver) ! (kg/m3)
integer, parameter :: nerrmax_dopaer=1000
integer nerr_dopaer
save nerr_dopaer
data nerr_dopaer/0/
real(r8) dopaer(pcols) ! aerosol optical depth in layer
real(r8) third
real(r8) colext(pcols,maxd_amode)
integer m,l,nc,ns
do i=1,ncol
extinct(i,:)=0.0_r8
absorb(i,:)=0.0_r8
aodvis(i)=0.0_r8
aodmode(i,:)=0.0_r8
aodabs(i)=0.0_r8
!++xl added 11/24/2009, dust AOD
dustaodmode(i,:)=0.0_r8
!--dust AOD
ssavis(i)=0.0_r8
end do
do k=1,pver
tauxar(:ncol,k)=0._r8
wa(:ncol,k)=0._r8
ga(:ncol,k)=0._r8
fa(:ncol,k)=0._r8
mass(:ncol,k)=state%pdeldry(:ncol,k)*rga
air_density(:ncol,k)=state%pmid(:ncol,k)/(rair*state%t(:ncol,k))
enddo
burden(:ncol,:ntot_amode)=0._r8
third=1./3.
savaervis=iswband.eq.idx_sw_diag
! zero'th layer does not contain aerosol
!
tauxar(1:ncol,0) = 0._r8
wa(1:ncol,0) = 0.925_r8
ga(1:ncol,0) = 0.850_r8
fa(1:ncol,0) = 0.7225_r8
do k=1,pver
! loop over all aerosol modes
do m=1,ntot_amode
! form bulk refractive index
crefin(:ncol)=0._r8
dryvol(:ncol)=0._r8
!++xl added 11/24/2009, dust AOD
dustvol(:ncol)=0._r8
!--dust AOD
! aerosol species loop
do l=1,nspec_amode(m)
ltype=lspectype_amode(l,m)
lmass=lmassptr_amode(l,m)
do i=1,ncol
burden(i,m)=burden(i,m) + raer(i,k,lmass)*mass(i,k)
vol(i)=raer(i,k,lmass)/specdens_amode(ltype)
dryvol(i)=dryvol(i)+vol(i)
crefin(i)=crefin(i)+vol(i)*specrefndxsw(iswband,ltype)
end do
enddo
!++xl added 11/24/2009, dust AOD
do i=1,ncol
if (lptr_dust_a_amode(m)>0) then
dustvol(i)=raer(i,k,lptr_dust_a_amode(m))/specdens_dust_amode
else
dustvol(i)=0.0_r8
endif
enddo
!--dust AOD
do i=1,ncol
watervol(i)=qaerwat(i,k,m)/rhoh2o
wetvol(i)=watervol(i)+dryvol(i)
if(watervol(i)<0._r8)then
if(abs(watervol(i)).gt.1.e-1*wetvol(i))then
write(iulog,'(a,4e10.2,a)')'watervol,wetvol,dryvolsol,dryvolinsol=', &
watervol(i),wetvol(i),dryvolsol(i),dryvolinsol(i) &
,' in modal_aero_sw'
! ! call endrun()
endif
watervol(i)=0._r8
wetvol(i)=dryvol(i)
endif
! volume mixing
crefin(i)=crefin(i)+watervol(i)*crefwsw(iswband)
crefin(i)=crefin(i)/max(wetvol(i),1.e-60_r8)
refr(i)=real(crefin(i))
refi(i)=abs(aimag(crefin(i)))
end do ! ncol
! call t_startf('binterp')
! interpolate coefficients linear in refractive index
! first call calcs itab,jtab,ttab,utab
itab(:ncol)=0
call binterp
(extpsw(1,1,1,m,iswband),ncol,ncoef,nrefr,nrefi, &
refr,refi,refrtabsw(1,iswband),refitabsw(1,iswband),itab,jtab, &
ttab,utab,cext)
call binterp
(abspsw(1,1,1,m,iswband),ncol,ncoef,nrefr,nrefi, &
refr,refi,refrtabsw(1,iswband),refitabsw(1,iswband),itab,jtab, &
ttab,utab,cabs)
call binterp
(asmpsw(1,1,1,m,iswband),ncol,ncoef,nrefr,nrefi, &
refr,refi,refrtabsw(1,iswband),refitabsw(1,iswband),itab,jtab, &
ttab,utab,casm)
! call t_stopf('binterp')
! parameterized optical properties
do i=1,ncol
if(logradsurf(i,k,m).le.xrmax)then
pext(i)=0.5_r8*cext(i,1)
do nc=2,ncoef
pext(i)=pext(i)+cheb(nc,m,i,k)*cext(i,nc)
enddo
pext(i)=exp(pext(i))
else
pext(i)=1.5_r8/(radsurf(i,k,m)*rhoh2o) ! geometric optics
endif
! convert from m2/kg water to m2/kg aerosol
specpext(i)=pext(i)
pext(i)=pext(i)*wetvol(i)*rhoh2o
! write(iulog,*)'pext=',pext(i)
pabs(i)=0.5_r8*cabs(i,1)
pasm(i)=0.5_r8*casm(i,1)
do nc=2,ncoef
pabs(i)=pabs(i)+cheb(nc,m,i,k)*cabs(i,nc)
pasm(i)=pasm(i)+cheb(nc,m,i,k)*casm(i,nc)
enddo
pabs(i)=pabs(i)*wetvol(i)*rhoh2o
pabs(i)=max(0._r8,pabs(i))
pabs(i)=min(pext(i),pabs(i))
palb(i)=1._r8-pabs(i)/max(pext(i),1.e-40_r8)
palb(i)=1._r8-pabs(i)/max(pext(i),1.e-40_r8)
dopaer(i)=pext(i)*mass(i,k)
end do
! Save aerosol optical depth at longest visible wavelength
! sum over layers
if(savaervis)then
! aerosol extinction (/m)
do i=1,ncol
extinct(i,k)=extinct(i,k) + dopaer(i)*air_density(i,k)/mass(i,k)
absorb(i,k)=absorb(i,k)+pabs(i)*air_density(i,k)
aodvis(i)=aodvis(i)+dopaer(i)
aodabs(i)=aodabs(i)+pabs(i)*mass(i,k)
aodmode(i,m)=aodmode(i,m)+dopaer(i)
!++xl added 11/24/2009, dust AOD
if (wetvol(i)>1.e-40_r8) then
dustaodmode(i,m)=dustaodmode(i,m)+dopaer(i)*dustvol(i)/wetvol(i)
! else
! dustaodmode(i,m)=0.0_r8
endif
!--dust AOD
ssavis(i)=ssavis(i)+dopaer(i)*palb(i)
end do
endif
do i=1,ncol
if ((dopaer(i)>-1.e-10) .and. (dopaer(i)<30.))goto 125
write(iulog,*)'dopaer(',i,',',k,',',m,',',lchnk,')=',dopaer(i)
! write(iulog,*)'itab,jtab,ttab,utab=',itab(i),jtab(i),ttab(i),utab(i)
write(iulog,*)'k=',k,' pext=',pext(i),' specext=',specpext(i)
write(iulog,*)'wetvol=',wetvol(i),' dryvol=',dryvol(i),' watervol=',watervol(i)
! write(iulog,*)'cext=',(cext(i,l),l=1,ncoef)
! write(iulog,*)'crefin=',crefin(i)
write(iulog,*)'nspec_amode(m)=',nspec_amode(m)
! write(iulog,*)'cheb=',(cheb(nc,m,i,k),nc=2,ncoef)
do l=1,nspec_amode(m)
lmass=lmassptr_amode(l,m)
ltype=lspectype_amode(l,m)
volf=raer(i,k,lmass)/specdens_amode(ltype)
write(iulog,*)'l=',l,'vol(l)=',volf
write(iulog,*)'specrefndxsw(l)=',specrefndxsw(iswband,ltype)
write(iulog,*)'specdens_amode(ltype)=',specdens_amode(ltype)
enddo
l=numptr_amode(m)
if ((l > 0) .and. (l .le. pcnst)) then
! write(iulog,*)'number=',raer(i,k,l)
else
! write(iulog,*)'number= ????, numptr=', l
endif
! call endrun('exit from modal_aero_sw')
nerr_dopaer = nerr_dopaer + 1
if (nerr_dopaer >= nerrmax_dopaer) then
! write(iulog,*)'*** halting in modal_aero_sw after nerr_dopaer =', nerr_dopaer
! call endrun('exit from modal_aero_sw')
end if
125 continue
end do
do i=1,ncol
tauxar(i,k)=tauxar(i,k)+dopaer(i)
wa(i,k)=wa(i,k)+dopaer(i)*palb(i)
ga(i,k)=ga(i,k)+dopaer(i)*palb(i)*pasm(i)
fa(i,k)=fa(i,k)+dopaer(i)*palb(i)*pasm(i)*pasm(i)
end do
end do ! ntot_amode
end do ! pver
if(savaervis)then
do i=1,ncol
if(aodvis(i)>1.e-10)then
ssavis(i)=ssavis(i)/aodvis(i)
else
ssavis(i)=0.925_r8
endif
do m=1,ntot_amode
colext(i,m)=0.001*aodmode(i,m)/burden(i,m)
! if(aodmode(i,m).gt.1.)write(iulog,*)'m,burden,tau,ext=',m, &
! burden(i,m),aodmode(i,m),colext(i,m)
end do
end do
do i = 1, nnite
extinct(idxnite(i),:) = fillvalue
absorb(idxnite(i),:) = fillvalue
aodvis(idxnite(i)) = fillvalue
aodabs(idxnite(i)) = fillvalue
aodmode(idxnite(i),:) = fillvalue
!++xl added 11/24/2009, dust AOD
dustaodmode(idxnite(i),:) = fillvalue
!--xl
burden(idxnite(i),:) = fillvalue
ssavis(idxnite(i)) = fillvalue
end do
call outfld
('EXTINCT',extinct ,pcols,lchnk)
call outfld
('ABSORB',absorb ,pcols,lchnk)
call outfld
('AODVIS',aodvis ,pcols,lchnk)
call outfld
('AODABS',aodabs ,pcols,lchnk)
call outfld
('AODMODE1',aodmode(1,1) ,pcols,lchnk)
call outfld
('AODMODE2',aodmode(1,2) ,pcols,lchnk)
call outfld
('AODMODE3',aodmode(1,3) ,pcols,lchnk)
#if (defined MODAL_AERO_7MODE)
call outfld
('AODMODE4',aodmode(1,4) ,pcols,lchnk)
call outfld
('AODMODE5',aodmode(1,5) ,pcols,lchnk)
call outfld
('AODMODE6',aodmode(1,6) ,pcols,lchnk)
call outfld
('AODMODE7',aodmode(1,7) ,pcols,lchnk)
#endif
!++xl added 11/24/2009, dust AOD
call outfld
('AODDUST1',dustaodmode(1,1) ,pcols,lchnk)
call outfld
('AODDUST2',dustaodmode(1,2) ,pcols,lchnk)
call outfld
('AODDUST3',dustaodmode(1,3) ,pcols,lchnk)
!--xl
call outfld
('BURDEN1',burden(1,1) ,pcols,lchnk)
call outfld
('BURDEN2',burden(1,2) ,pcols,lchnk)
call outfld
('BURDEN3',burden(1,3) ,pcols,lchnk)
#if (defined MODAL_AERO_7MODE)
call outfld
('BURDEN4',burden(1,4) ,pcols,lchnk)
call outfld
('BURDEN5',burden(1,5) ,pcols,lchnk)
call outfld
('BURDEN6',burden(1,6) ,pcols,lchnk)
call outfld
('BURDEN7',burden(1,7) ,pcols,lchnk)
#endif
call outfld
('SSAVIS',ssavis ,pcols,lchnk)
endif
return
end subroutine modal_aero_sw
subroutine modal_aero_lw(ncol,lchnk, pbuf, raer, tauxar, pdeldry) 1,9
! calculates aerosol radiative properties
use ppgrid
use constituents
, only: pcnst
use physconst
, only: rga
use phys_buffer
, only: pbuf_size_max, pbuf_fld, pbuf_get_fld_idx
implicit none
integer, intent(in) :: ncol ! number of columns
integer, intent(in) :: lchnk ! chunk index
real(r8), intent(in) :: raer(pcols, pver, pcnst)
real(r8), intent(out) :: tauxar(pcols,pver,nlwbands) ! layer absorption optical depth
real(r8), intent(in) :: pdeldry(pcols,pver) ! pressure thickness (Pa)
type(pbuf_fld), intent(in), dimension(pbuf_size_max) :: pbuf
integer i,k
real(r8) pabs(pcols) ! parameterized specific absorption (m2/kg)
real(r8) :: mass(pcols,pver) ! layer mass
real(r8) totmass(pcols)
real(r8) vol(pcols) ! volume concentration of aerosol specie (m3/kg)
real(r8) dryvol(pcols) ! volume concentration of aerosol mode (m3/kg)
real(r8) wetvol(pcols) ! volume concentration of wet mode (m3/kg)
real(r8) watervol(pcols) ! volume concentration of water in each mode (m3/kg)
real(r8) volf ! volume fraction of insoluble aerosol
real(r8) refr(pcols) ! real part of refractive index
real(r8) refi(pcols) ! imaginary part of refractive index
complex crefin(pcols) ! complex refractive index
integer lmass,ltype
integer itab(pcols),jtab(pcols)
real(r8) ttab(pcols),utab(pcols)
real(r8) cext(pcols,ncoef),cabs(pcols,ncoef),casm(pcols,ncoef)
real(r8) xrad(pcols)
real(r8) cheby(ncoef,pcols,pver,maxd_amode) ! chebychef polynomials
integer, parameter :: nerrmax_dopaer=1000
integer nerr_dopaer
save nerr_dopaer
data nerr_dopaer/0/
real(r8) dopaer(pcols) ! aerosol optical depth in layer
real(r8) third
integer m,l,nc,ns,ifld
real(r8), pointer, dimension(:,:,:) :: dgnumwet ! wet number mode diameter (m)
real(r8), pointer, dimension(:,:,:) :: qaerwat ! aerosol water (g/g)
integer ilwband
ifld = pbuf_get_fld_idx
('DGNUMWET')
dgnumwet => pbuf(ifld)%fld_ptr(1,1:pcols,1:pver,lchnk,1:maxd_amode)
ifld = pbuf_get_fld_idx
( 'QAERWAT' )
if ( associated(pbuf(ifld)%fld_ptr) ) then
qaerwat => pbuf(ifld)%fld_ptr( 1, 1:pcols, 1:pver, lchnk, 1:maxd_amode )
else
call endrun
( 'pbuf for QAERWAT not allocated in modal_aer_day' )
end if
do k=1,pver
mass(:ncol,k)=pdeldry(:ncol,k)*rga !
enddo
third=1./3.
! calc size parameter for all columns
do k=1,pver
do m=1,ntot_amode
do i=1,ncol
! convert from number diameter to surface area
xrad(i)=log(0.5*dgnumwet(i,k,m))+2.0_r8*alnsg_amode(m)*alnsg_amode(m)
! normalize size parameter
xrad(i)=max(xrad(i),xrmin)
xrad(i)=min(xrad(i),xrmax)
xrad(i)=(2*xrad(i)-xrmax-xrmin)/(xrmax-xrmin)
! chebyshev polynomials
cheby(1,i,k,m)=1.0_r8
cheby(2,i,k,m)=xrad(i)
do nc=3,ncoef
cheby(nc,i,k,m)=2.0_r8*xrad(i)*cheby(nc-1,i,k,m)-cheby(nc-2,i,k,m)
enddo
enddo
enddo
enddo
do 1000 ilwband=1,nlwbands
do k=1,pver
tauxar(:ncol,k,ilwband)=0._r8
! loop over all aerosol modes
do m=1,ntot_amode
! form bulk refractive index. Use volume mixing for infrared
do i=1,ncol
crefin(i)=0._r8
dryvol(i)=0._r8
end do
! aerosol species loop
do l=1,nspec_amode(m)
ltype=lspectype_amode(l,m)
lmass=lmassptr_amode(l,m)
do i=1,ncol
vol(i)=raer(i,k,lmass)/specdens_amode(ltype)
crefin(i)=crefin(i)+vol(i)*specrefndxlw(ilwband,ltype)
dryvol(i)=dryvol(i)+vol(i)
end do
enddo
do i=1,ncol
watervol(i)=qaerwat(i,k,m)/rhoh2o
wetvol(i)=watervol(i)+dryvol(i)
if(watervol(i)<0.0_r8)then
if(abs(watervol(i)).gt.1.e-1*wetvol(i))then
write(iulog,*)'watervol,wetvol,dryvol=',watervol(i),wetvol(i),dryvol(i),' in modal_aero_lw'
! call endrun()
endif
watervol(i)=0._r8
wetvol(i)=dryvol(i)
endif
crefin(i)=crefin(i)+watervol(i)*crefwlw(ilwband)
if(wetvol(i)>1.e-40)crefin(i)=crefin(i)/wetvol(i)
refr(i)=real(crefin(i))
refi(i)=aimag(crefin(i))
end do ! ncol
! interpolate coefficients linear in refractive index
! first call calcs itab,jtab,ttab,utab
itab(:ncol)=0
call binterp
(absplw(1,1,1,m,ilwband),ncol,ncoef,nrefr,nrefi, &
refr,refi,refrtablw(1,ilwband),refitablw(1,ilwband),itab,jtab, &
ttab,utab,cabs)
! parameterized optical properties
do i=1,ncol
pabs(i)=0.5*cabs(i,1)
do nc=2,ncoef
pabs(i)=pabs(i)+cheby(nc,i,k,m)*cabs(i,nc)
enddo
pabs(i)=pabs(i)*wetvol(i)*rhoh2o
pabs(i)=max(0._r8,pabs(i))
dopaer(i)=pabs(i)*mass(i,k)
end do
do i=1,ncol
if ((dopaer(i)>-1.e-10) .and. (dopaer(i)<20.))goto 225
write(iulog,*)'dopaer(',i,',',k,',',m,',',lchnk,')=',dopaer(i)
write(iulog,*)'k=',k,' pabs=',pabs(i)
write(iulog,*)'wetvol=',wetvol(i),' dryvol=',dryvol(i), &
' watervol=',watervol(i)
write(iulog,*)'cabs=',(cabs(i,l),l=1,ncoef)
write(iulog,*)'crefin=',crefin(i)
write(iulog,*)'nspec_amode(m)=',nspec_amode(m)
do l=1,nspec_amode(m)
lmass=lmassptr_amode(l,m)
ltype=lspectype_amode(l,m)
vol=raer(i,k,lmass)/specdens_amode(ltype)
write(iulog,*)'l=',l,'vol(l)=',vol
write(iulog,*)'specrefndxlw(l)=',specrefndxlw(ilwband,ltype)
write(iulog,*)'specdens_amode(ltype)=',specdens_amode(ltype)
enddo
l=numptr_amode(m)
if ((l > 0) .and. (l .le. pcnst)) then
write(iulog,*)'number=',raer(i,k,l)
else
write(iulog,*)'number= ????, numptr=', l
endif
! call endrun()
nerr_dopaer = nerr_dopaer + 1
if (nerr_dopaer >= nerrmax_dopaer) then
write(iulog,*)'*** halting in modal_aero_lw after nerr_dopaer =', nerr_dopaer
call endrun
()
end if
225 continue
end do
do i=1,ncol
tauxar(i,k,ilwband)=tauxar(i,k,ilwband)+dopaer(i)
end do
end do ! ntot_amode
end do ! pver
1000 continue
return
end subroutine modal_aero_lw
subroutine fitcurv(rs,yin,coef,ncoef,maxm) 1,2
! fit y(x) using Chebyshev polynomials
implicit none
integer nmodes,maxm,m,ncoef
parameter (nmodes=300)
real(r8) rs(maxm) ! surface mode radius (cm)
real(r8) yin(maxm),coef(ncoef)
real(r8) x(nmodes),y(nmodes)
real(r8) xmin,xmax
if(maxm.gt.nmodes)then
write(iulog,*)'nmodes too small in fitcurv',maxm
call endrun
()
endif
xmin=1.e20
xmax=-1.e20
do 100 m=1,maxm
x(m)=log(rs(m))
xmin=min(xmin,x(m))
xmax=max(xmax,x(m))
y(m)=log(yin(m))
100 continue
do 110 m=1,maxm
x(m)=(2*x(m)-xmax-xmin)/(xmax-xmin)
110 continue
call chebft
(coef,ncoef,y,maxm)
return
end subroutine fitcurv
subroutine fitcurvlin(rs,yin,coef,ncoef,maxm) 2,2
! fit y(x) using Chebychev polynomials
! calculates ncoef coefficients coef
implicit none
integer nmodes,m,ncoef
parameter (nmodes=300)
integer,intent(in) :: maxm
real(r8),intent(in) :: rs(maxm),yin(maxm)
real(r8) x(nmodes),y(nmodes)
real(r8),intent(out) :: coef(ncoef)
real(r8) xmin,xmax
if(maxm.gt.nmodes)then
write(iulog,*)'nmodes too small in fitcurv',maxm
call endrun
endif
do 100 m=1,maxm
x(m)=log(rs(m))
y(m)=(yin(m))
100 continue
call chebft
(coef,ncoef,y,maxm)
return
end subroutine fitcurvlin
subroutine chebft(c,m,f,n) 2
! given a function f with values at zeroes x_k of Chebychef polynomial
! T_n(x), calculate coefficients c_j such that
! f(x)=sum(k=1,n) c_k t_(k-1)(y) - 0.5*c_1
! where y=(x-0.5*(xmax+xmin))/(0.5*(xmax-xmin))
! See Numerical Recipes, pp. 148-150.
implicit none
real(r8) pi
parameter (pi=3.14159265)
real(r8) c(m),f(n),fac,sum
integer n,j,k,m
fac=2./n
do j=1,m
sum=0
do k=1,n
sum=sum+f(k)*cos((pi*(j-1))*((k-0.5)/n))
enddo
c(j)=fac*sum
enddo
return
end subroutine chebft
subroutine binterp(table,ncol,km,im,jm,x,y,xtab,ytab,ix,jy,t,u,out) 4,11
! bilinear interpolation of table
!
implicit none
integer im,jm,km,ncol
real(r8) table(km,im,jm),xtab(im),ytab(jm),out(pcols,km)
integer i,ix(pcols),ip1,j,jy(pcols),jp1,k,ic
real(r8) x(pcols),dx,t(pcols),y(pcols),dy,u(pcols), &
tu(pcols),tuc(pcols),tcu(pcols),tcuc(pcols)
if(ix(1).gt.0)go to 30
if(im.gt.1)then
do ic=1,ncol
do i=1,im
if(x(ic).lt.xtab(i))go to 10
enddo
10 ix(ic)=max0(i-1,1)
ip1=min(ix(ic)+1,im)
dx=(xtab(ip1)-xtab(ix(ic)))
if(abs(dx).gt.1.e-20_r8)then
t(ic)=(x(ic)-xtab(ix(ic)))/dx
else
t(ic)=0._r8
endif
end do
else
ix(:ncol)=1
t(:ncol)=0._r8
endif
if(jm.gt.1)then
do ic=1,ncol
do j=1,jm
if(y(ic).lt.ytab(j))go to 20
enddo
20 jy(ic)=max0(j-1,1)
jp1=min(jy(ic)+1,jm)
dy=(ytab(jp1)-ytab(jy(ic)))
if(abs(dy).gt.1.e-20_r8)then
u(ic)=(y(ic)-ytab(jy(ic)))/dy
if(u(ic).lt.0._r8.or.u(ic).gt.1._r8)then
write(iulog,*)'u,y,jy,ytab,dy=',u(ic),y(ic),jy(ic),ytab(jy(ic)),dy
endif
else
u(ic)=0._r8
endif
end do
else
jy(:ncol)=1
u(:ncol)=0._r8
endif
30 continue
do ic=1,ncol
tu(ic)=t(ic)*u(ic)
tuc(ic)=t(ic)-tu(ic)
tcuc(ic)=1._r8-tuc(ic)-u(ic)
tcu(ic)=u(ic)-tu(ic)
jp1=min(jy(ic)+1,jm)
ip1=min(ix(ic)+1,im)
do k=1,km
out(ic,k)=tcuc(ic)*table(k,ix(ic),jy(ic))+tuc(ic)*table(k,ip1,jy(ic)) &
+tu(ic)*table(k,ip1,jp1)+tcu(ic)*table(k,ix(ic),jp1)
end do
enddo
return
end subroutine binterp
subroutine write_modal_optics(outfilename, modes, lw_band_len, sw_band_len, & 1
refindex_real_sw,refindex_im_sw, refindex_real_lw, refindex_im_lw, &
nrefr, nrefi, sigma_logr_aer, ncoef, extpsw, abspsw, asmpsw, absplw )
use pio, only : pio_def_var, pio_def_dim, pio_put_var, pio_clobber, pio_put_att, pio_double, &
file_desc_T, var_desc_t, pio_global, pio_enddef, pio_closefile
use cam_pio_utils
, only : cam_pio_createfile
implicit none
character*(*) outfilename
! error status return
integer ierr
! netCDF id
type(file_desc_t) :: ncid
! dimension ids
integer lw_band_dim
integer sw_band_dim
integer refindex_real_dim
integer refindex_im_dim
integer mode_dim
integer ncoef_dim
! dimension lengths
integer, intent(in) :: nrefr,nrefi ! number of refractive indices
integer, intent(in) :: ncoef ! number of coefficients in polynomial expressions
integer, intent(in) :: sw_band_len ! number of solar wavelengths
integer, intent(in) :: lw_band_len ! number of infrared wavelengths
integer, intent(in) :: modes ! number of aerosol modes
! variable ids
type(var_desc_t) :: lw_abs_id
type(var_desc_t) :: sw_asm_id
type(var_desc_t) :: sw_ext_id
type(var_desc_t) :: sw_abs_id
type(var_desc_t) :: sigma_logr_aer_id
type(var_desc_t) :: refindex_real_lw_id
type(var_desc_t) :: refindex_im_lw_id
type(var_desc_t) :: refindex_real_sw_id
type(var_desc_t) :: refindex_im_sw_id
! rank (number of dimensions) for each variable
integer lw_abs_rank
integer sw_asm_rank
integer sw_ext_rank
integer sw_abs_rank
integer sigma_logr_aer_rank
integer refindex_rank
parameter (lw_abs_rank = 5)
parameter (sw_asm_rank = 5)
parameter (sw_ext_rank = 5)
parameter (sw_abs_rank = 5)
parameter (refindex_rank=2)
parameter (sigma_logr_aer_rank = 1)
! variable shapes
integer lw_abs_dims(lw_abs_rank)
integer sw_asm_dims(sw_asm_rank)
integer sw_ext_dims(sw_ext_rank)
integer sw_abs_dims(sw_abs_rank)
integer refindex_dims(refindex_rank)
integer coef_dim
integer sigma_logr_aer_dims(sigma_logr_aer_rank)
! data variables
! coefficients for parameterizing aerosol radiative properties
! in terms of refractive index and wet radius
real(r8), intent(in) :: extpsw(ncoef,nrefr,nrefi,modes,sw_band_len) ! specific extinction
real(r8), intent(in) :: abspsw(ncoef,nrefr,nrefi,modes,sw_band_len) ! specific absorption
real(r8), intent(in) :: asmpsw(ncoef,nrefr,nrefi,modes,sw_band_len) ! asymmetry factor
real(r8), intent(in) :: absplw(ncoef,nrefr,nrefi,modes,lw_band_len) ! specific absorption
real(r8), intent(in) :: sigma_logr_aer(maxd_amode) ! geometric standard deviation of size distribution
! tables of real refractive indices for aerosols
real(r8), intent(in) :: refindex_real_sw(nrefr,sw_band_len) !
real(r8), intent(in) :: refindex_im_sw(nrefi,sw_band_len) !
real(r8), intent(in) :: refindex_real_lw(nrefr,lw_band_len) !
real(r8), intent(in) :: refindex_im_lw(nrefi,lw_band_len) !
integer lenchr
integer len
! attribute vectors
! enter define mode
call cam_pio_createfile
(ncid, outfilename, PIO_CLOBBER)
! define dimensions
ierr = pio_def_dim(ncid, 'lw_band', lw_band_len, lw_band_dim)
ierr = pio_def_dim(ncid, 'sw_band', sw_band_len, sw_band_dim)
ierr = pio_def_dim(ncid, 'refindex_real', nrefr, refindex_real_dim)
ierr = pio_def_dim(ncid, 'refindex_im', nrefi, refindex_im_dim)
ierr = pio_def_dim(ncid, 'mode', modes, mode_dim)
ierr = pio_def_dim(ncid, 'coef_number', ncoef, coef_dim)
! define variables
lw_abs_dims(5) = lw_band_dim
lw_abs_dims(4) = mode_dim
lw_abs_dims(3) = refindex_im_dim
lw_abs_dims(2) = refindex_real_dim
lw_abs_dims(1) = coef_dim
ierr = pio_def_var(ncid, 'absplw', PIO_DOUBLE, lw_abs_dims, lw_abs_id )
sw_asm_dims(5) = sw_band_dim
sw_asm_dims(4) = mode_dim
sw_asm_dims(3) = refindex_im_dim
sw_asm_dims(2) = refindex_real_dim
sw_asm_dims(1) = coef_dim
ierr = pio_def_var(ncid, 'asmpsw', PIO_DOUBLE, sw_asm_dims, sw_asm_id )
sw_ext_dims(5) = sw_band_dim
sw_ext_dims(4) = mode_dim
sw_ext_dims(3) = refindex_im_dim
sw_ext_dims(2) = refindex_real_dim
sw_ext_dims(1) = coef_dim
ierr = pio_def_var(ncid, 'extpsw', PIO_DOUBLE, sw_ext_dims, sw_ext_id )
sw_abs_dims(5) = sw_band_dim
sw_abs_dims(4) = mode_dim
sw_abs_dims(3) = refindex_im_dim
sw_abs_dims(2) = refindex_real_dim
sw_abs_dims(1) = coef_dim
ierr = pio_def_var(ncid, 'abspsw', PIO_DOUBLE, sw_abs_dims, sw_abs_id )
refindex_dims(2) = sw_band_dim
refindex_dims(1) = refindex_real_dim
ierr = pio_def_var(ncid, 'refindex_real_sw', PIO_DOUBLE, refindex_dims, &
refindex_real_sw_id)
refindex_dims(2) = sw_band_dim
refindex_dims(1) = refindex_im_dim
ierr = pio_def_var(ncid, 'refindex_im_sw', PIO_DOUBLE, refindex_dims, &
refindex_im_sw_id)
refindex_dims(2) = lw_band_dim
refindex_dims(1) = refindex_real_dim
ierr = pio_def_var(ncid, 'refindex_real_lw', PIO_DOUBLE, refindex_dims, &
refindex_real_lw_id)
refindex_dims(2) = lw_band_dim
refindex_dims(1) = refindex_im_dim
ierr = pio_def_var(ncid, 'refindex_im_lw', PIO_DOUBLE, refindex_dims, &
refindex_im_lw_id)
sigma_logr_aer_dims(1) = mode_dim
ierr = pio_def_var(ncid, 'sigma_logr_aer', PIO_DOUBLE, sigma_logr_aer_dims, &
sigma_logr_aer_id)
! assign attributes
ierr = pio_put_att(ncid, lw_abs_id, 'long_name', &
'coefficients of polynomial expression for longwave absorption')
ierr = pio_put_att(ncid, lw_abs_id, 'units', 'meter^2 kilogram^-1')
ierr = pio_put_att(ncid, sw_ext_id, 'long_name', &
'coefficients of polynomial expression for shortwave extinction')
ierr = pio_put_att(ncid, sw_ext_id, 'units', 'meter^2 kilogram^-1')
ierr = pio_put_att(ncid, sw_asm_id, 'long_name', &
'coefficients of polynomial expression for shortwave asymmetry parameter')
ierr = pio_put_att(ncid, sw_asm_id, 'units', 'fraction')
ierr = pio_put_att(ncid, sw_abs_id, 'long_name', &
'coefficients of polynomial expression for shortwave absorption')
ierr = pio_put_att(ncid, sw_abs_id, 'units', 'meter^2 kilogram^-1')
ierr = pio_put_att(ncid, refindex_real_lw_id, 'long_name', &
'real refractive index of aerosol - longwave')
ierr = pio_put_att(ncid, refindex_im_lw_id, 'long_name', &
'imaginary refractive index of aerosol - longwave')
ierr = pio_put_att(ncid, refindex_real_sw_id, 'long_name', &
'real refractive index of aerosol - shortwave')
ierr = pio_put_att(ncid, refindex_im_sw_id, 'long_name', &
'imaginary refractive index of aerosol - shortwave')
ierr = pio_put_att(ncid, sigma_logr_aer_id, 'long_name', &
'geometric standard deviation of aerosol')
ierr = pio_put_att(ncid, sigma_logr_aer_id, 'units', '-')
ierr = pio_put_att(ncid, PIO_GLOBAL, 'source', 'OPAC + miev0')
ierr = pio_put_att(ncid, PIO_GLOBAL, 'history', 'Ghan and Zaveri, JGR 2007')
! leave define mode
ierr = pio_enddef(ncid)
ierr = pio_put_var(ncid, sigma_logr_aer_id, sigma_logr_aer)
ierr = pio_put_var(ncid, refindex_real_lw_id, refindex_real_lw)
ierr = pio_put_var(ncid, refindex_im_lw_id, refindex_im_lw)
ierr = pio_put_var(ncid, refindex_real_sw_id, refindex_real_sw)
ierr = pio_put_var(ncid, refindex_im_sw_id, refindex_im_sw)
ierr = pio_put_var(ncid, lw_abs_id, absplw)
ierr = pio_put_var(ncid, sw_ext_id, extpsw)
ierr = pio_put_var(ncid, sw_abs_id, abspsw)
ierr = pio_put_var(ncid, sw_asm_id, asmpsw)
call pio_closefile(ncid)
end subroutine write_modal_optics
subroutine read_modal_optics(infilename, modes, lw_band_len, sw_band_len, & 1
refindex_real_sw,refindex_im_sw, refindex_real_lw, refindex_im_lw, &
nrefr, nrefi, ncoef, extpsw, abspsw, asmpsw, absplw )
use pio, only : pio_inq_dimlen, pio_inq_dimid, pio_get_var, pio_inq_varid, file_desc_t, var_desc_t, &
pio_nowrite, pio_closefile
use cam_pio_utils
, only : cam_pio_openfile
implicit none
character*(*), intent(in) :: infilename
! netCDF id
type(file_desc_t) :: ncid
! dimension ids
integer lw_band_dim
integer sw_band_dim
integer refindex_real_dim
integer refindex_im_dim
integer mode_dim
integer ncoef_dim
! dimension lengths
integer, intent(in) :: nrefr,nrefi ! number of refractive indices
integer, intent(in) :: ncoef ! number of coefficients in polynomial expressions
integer, intent(in) :: sw_band_len ! number of solar wavelengths
integer, intent(in) :: lw_band_len ! number of infrared wavelengths
integer, intent(in) :: modes ! number of aerosol modes
! variable ids
type(var_desc_t) :: lw_abs_id
type(var_desc_t) :: sw_asm_id
type(var_desc_t) :: sw_ext_id
type(var_desc_t) :: sw_abs_id
type(var_desc_t) :: sigma_logr_aer_id
type(var_desc_t) :: refindex_real_lw_id
type(var_desc_t) :: refindex_im_lw_id
type(var_desc_t) :: refindex_real_sw_id
type(var_desc_t) :: refindex_im_sw_id
! rank (number of dimensions) for each variable
integer lw_abs_rank
integer sw_asm_rank
integer sw_ext_rank
integer sw_abs_rank
integer sigma_logr_aer_rank
integer refindex_rank
parameter (lw_abs_rank = 5)
parameter (sw_asm_rank = 5)
parameter (sw_ext_rank = 5)
parameter (sw_abs_rank = 5)
parameter (refindex_rank=2)
parameter (sigma_logr_aer_rank = 1)
! variable shapes
integer lw_abs_dims(lw_abs_rank)
integer sw_asm_dims(sw_asm_rank)
integer sw_ext_dims(sw_ext_rank)
integer sw_abs_dims(sw_abs_rank)
integer refindex_dims(refindex_rank)
integer coef_dim
integer sigma_logr_aer_dims(sigma_logr_aer_rank)
! data variables
! coefficients for parameterizing aerosol radiative properties
! in terms of refractive index and wet radius
real(r8), intent(out) :: extpsw(ncoef,nrefr,nrefi,modes,sw_band_len) ! specific extinction
real(r8), intent(out) :: abspsw(ncoef,nrefr,nrefi,modes,sw_band_len) ! specific absorption
real(r8), intent(out) :: asmpsw(ncoef,nrefr,nrefi,modes,sw_band_len) ! asymmetry factor
real(r8), intent(out) :: absplw(ncoef,nrefr,nrefi,modes,lw_band_len) ! specific absorption
real(r8) :: sigma_logr_aer(maxd_amode) ! geometric standard deviation of size distribution
! tables of real refractive indices for aerosols
real(r8), intent(out) :: refindex_real_sw(nrefr,sw_band_len) !
real(r8), intent(out) :: refindex_im_sw(nrefi,sw_band_len) !
real(r8), intent(out) :: refindex_real_lw(nrefr,lw_band_len) !
real(r8), intent(out) :: refindex_im_lw(nrefi,lw_band_len) !
integer lenchr
integer dimread
integer start(5),count(5)
integer m, ierr
integer len
! open file
call cam_pio_openfile
(ncid, infilename, PIO_NOWRITE)
! inquire dimensions
ierr = pio_inq_dimid(ncid,'lw_band',lw_band_dim)
ierr = pio_inq_dimlen(ncid, lw_band_dim, dimread)
if(dimread.ne.lw_band_len)then
write(iulog,*)'lw_band_len=',dimread,' from ',infilename,' ne lw_band_len=',lw_band_len
call endrun
endif
ierr = pio_inq_dimid(ncid,'sw_band',sw_band_dim)
ierr = pio_inq_dimlen(ncid, sw_band_dim, dimread)
if(dimread.ne.sw_band_len)then
write(iulog,*)'sw_band_len=',dimread,' from ',infilename,' ne sw_band_len=',sw_band_len
call endrun
endif
ierr = pio_inq_dimid(ncid,'refindex_real',refindex_real_dim)
ierr = pio_inq_dimlen(ncid, refindex_real_dim, dimread)
if(dimread.ne.nrefr)then
write(iulog,*)'refindex_real=',dimread,' from ',infilename,' ne nrefr=',nrefr
call endrun
endif
ierr = pio_inq_dimid(ncid,'refindex_im',refindex_im_dim)
ierr = pio_inq_dimlen(ncid, refindex_im_dim, dimread)
if(dimread.ne.nrefi)then
write(iulog,*)'refindex_im=',dimread,' from ',infilename,' ne nrefi=',nrefi
call endrun
endif
ierr = pio_inq_dimid(ncid,'mode',mode_dim)
ierr = pio_inq_dimlen(ncid, mode_dim, dimread)
if(dimread.ne.modes)then
write(iulog,*)'mode=',dimread,' from ',infilename,' ne modes=',modes
call endrun
endif
ierr = pio_inq_dimid(ncid,'coef_number',coef_dim)
ierr = pio_inq_dimlen(ncid, coef_dim, dimread)
if(dimread.ne.ncoef)then
write(iulog,*)'coef_number=',dimread,' from ',infilename,' ne ncoef=',ncoef
call endrun
endif
! read variables
ierr = pio_inq_varid(ncid,'absplw',lw_abs_id)
ierr = pio_get_var(ncid, lw_abs_id, absplw)
ierr = pio_inq_varid(ncid,'extpsw',sw_ext_id)
ierr = pio_get_var(ncid, sw_ext_id, extpsw)
ierr = pio_inq_varid(ncid,'abspsw',sw_abs_id)
ierr = pio_get_var(ncid, sw_abs_id, abspsw)
ierr = pio_inq_varid(ncid,'asmpsw',sw_asm_id)
ierr = pio_get_var(ncid, sw_asm_id, asmpsw)
ierr = pio_inq_varid(ncid, 'refindex_real_sw', refindex_real_sw_id)
ierr = pio_get_var(ncid, refindex_real_sw_id, refindex_real_sw)
ierr = pio_inq_varid(ncid, 'refindex_im_sw', refindex_im_sw_id)
ierr = pio_get_var(ncid, refindex_im_sw_id, refindex_im_sw)
ierr = pio_inq_varid(ncid, 'refindex_real_lw', refindex_real_lw_id)
ierr = pio_get_var(ncid, refindex_real_lw_id, refindex_real_lw)
ierr = pio_inq_varid(ncid, 'refindex_im_lw', refindex_im_lw_id)
ierr = pio_get_var(ncid, refindex_im_lw_id, refindex_im_lw)
ierr = pio_inq_varid(ncid, 'sigma_logr_aer', sigma_logr_aer_id)
ierr = pio_get_var(ncid, sigma_logr_aer_id, sigma_logr_aer)
do m=1,modes
if(sigma_logr_aer(m)/sigmag_amode(m).lt.0.99.or. &
sigma_logr_aer(m)/sigmag_amode(m).gt.1.01)then
write(iulog,*)'sigma_logr_aer,sigmag_amode=',sigma_logr_aer(m),sigmag_amode(m)
call endrun
end if
end do
call pio_closefile(ncid)
end subroutine read_modal_optics
#endif
!MODAL_AERO
end module modal_aer_opt