#include <misc.h>
#include <params.h>
subroutine radclw(lat ,lwupcgs ,tnm ,qnm ,o3vmr , 2,12
$ pmid ,pint ,pmln ,piln ,plco2 ,
$ plh2o ,n2o ,ch4 ,cfc11 ,cfc12 ,
$ cld ,tclrsf ,qrl ,flns ,flnt ,
$ flnsc ,flntc ,flwds )
C-----------------------------------------------------------------------
C
C Compute longwave radiation heating rates and boundary fluxes
C
C Uses broad band absorptivity/emissivity method to compute clear sky;
C assumes randomly overlapped clouds with variable cloud emissivity to
C include effects of clouds.
C
C Computes clear sky absorptivity/emissivity at lower frequency (in
C general) than the model radiation frequency; uses previously computed
C and stored values for efficiency
C
C Note: This subroutine contains vertical indexing which proceeds
C from bottom to top rather than the top to bottom indexing
C used in the rest of the model.
C
C---------------------------Code history--------------------------------
C
C Original version: CCM1
C Standardized: J. Rosinski, June 1992
C Reviewed: J. Kiehl, B. Briegleb, August 1992
C Reviewed: J. Kiehl, April 1996
C Reviewed: B. Briegleb, May 1996
C
C-----------------------------------------------------------------------
c
c $Id: radclw.F,v 1.1.20.3 2000/02/25 21:24:11 zender Exp $
c
#include <implicit.h>
C------------------------------Parameters-------------------------------
#include <prgrid.h>
#include <pagrid.h>
C-----------------------------------------------------------------------
integer plevp2,plevp3,plevp4
parameter (plevp2=plev+2,plevp3=plev+3,plevp4=plev+4)
C------------------------------Commons----------------------------------
#include <comlun.h>
C-----------------------------------------------------------------------
#include <comtim.h>
C-----------------------------------------------------------------------
#include <crdcon.h>
C-----------------------------------------------------------------------
#include <comctl.h>
C-----------------------------------------------------------------------
#include <coreiorad.h>
C------------------------------Arguments--------------------------------
c++csz
#ifdef CRM_SRB
#include <crmsrb.h>
#endif /* not CRM_SRB */
c--csz
C
C Input arguments
C
integer lat ! Model latitude index
real lwupcgs(plond) ! Longwave up flux in CGS units
C
C Input arguments which are only passed to other routines
C
real tnm(plond,plev) ! Level temperature
real qnm(plond,plev) ! Level moisture field
real o3vmr(plond,plev) ! ozone volume mixing ratio
real pmid(plond,plev) ! Level pressure
real pint(plond,plevp) ! Model interface pressure
real pmln(plond,plev) ! Ln(pmid)
real piln(plond,plevp) ! Ln(pint)
real plco2(plond,plevp) ! Path length co2
real plh2o(plond,plevp) ! Path length h2o
real n2o(plond,plev) ! nitrous oxide mass mixing ratio
real ch4(plond,plev) ! methane mass mixing ratio
real cfc11(plond,plev) ! cfc11 mass mixing ratio
real cfc12(plond,plev) ! cfc12 mass mixing ratio
C
C Input/Output arguments
C
real cld(plond,plevp) ! Cloud cover
real tclrsf(plond,plevp) ! Clear sky fraction
C
C Output arguments
C
real qrl(plond,plev) ! Longwave heating rate
real flns(plond) ! Surface cooling flux
real flnt(plond) ! Net outgoing flux
real flnsc(plond) ! Clear sky surface cooing
real flntc(plond) ! Net clear sky outgoing flux
real flwds(plond) ! Down longwave flux at surface
C
C---------------------------Local variables-----------------------------
C
integer i,ii ! Longitude indices
integer k ! Level index
integer k1 ! Level index
integer k2 ! Level index
integer k3 ! Level index
integer km ! Level index
integer km1 ! Level index
integer km2 ! Level index
integer km3 ! Level index
integer km4 ! Level index
C
real tmp(plond) ! Temporary workspace
real tmp1 ! Temporary 1
real absbt(plond) ! Downward emission at model top
real plol(plond,plevp) ! O3 pressure wghted path length
real plos(plond,plevp) ! O3 path length
real co2em(plond,plevp) ! Layer co2 normalized planck funct. derivative
real co2eml(plond,plev) ! Interface co2 normalized planck funct. deriv.
real delt(plond) ! Diff t**4 mid layer to top interface
real delt1(plond) ! Diff t**4 lower intrfc to mid layer
real bk1(plond) ! Absrptvty for vertical quadrature
real bk2(plond) ! Absrptvty for vertical quadrature
real ful(plond,plevp) ! Total upwards longwave flux
real fsul(plond,plevp) ! Clear sky upwards longwave flux
real fdl(plond,plevp) ! Total downwards longwave flux
real fsdl(plond,plevp) ! Clear sky downwards longwv flux
real fclb4(plond,plev) ! Sig t**4 for cld bottom interfc
real fclt4(plond,plev) ! Sig t**4 for cloud top interfc
real s(plond,plevp,plevp) ! Flx integral sum
real tplnka(plond,plevp) ! Planck fnctn temperature
real s2c(plond,plevp) ! H2o cont amount
real s2t(plond,plevp) ! H2o cont temperature
real w(plond,plevp) ! H2o path
real tplnke(plond) ! Planck fnctn temperature
real h2otr(plond,plevp) ! H2o trnmsn for o3 overlap
real co2t(plond,plevp) ! Prs wghted temperature path
real tint(plond,plevp) ! Interface temperature
real tint4(plond,plevp) ! Interface temperature**4
real tlayr(plond,plevp) ! Level temperature
real tlayr4(plond,plevp) ! Level temperature**4
real rtclrsf(plond,plevp) ! 1./tclrsf(i,k)
real gocp ! gravit/cpair
integer klov(plond) ! Cloud lowest level index
integer khiv(plond) ! Cloud highest level index
integer khivm(plond) ! khiv(i) - 1
integer indx(plond) ! index vector of gathered array values
integer npts ! number of values satisfying some criterion
integer khighest ! indx of highest level for some criterion
logical done(plond) ! some criterion has been satisfied
logical start(plond) ! begin some test
pointer (pabsems,absems)
pointer (pabsnxt,absnxt(plond,plev,4))
pointer (pabstot,abstot(plond,plevp,plevp))
pointer (pemstot,emstot(plond,plevp))
real absems(plngbuf) ! Absorbs's and emiss's in buffer
real absnxt ! Nearest layer absorptivities
real abstot ! Non-adjacent layer absorptivites
real emstot ! Total emissivity
c
c Trace gas variables
c
real ucfc11(plond,plevp) ! CFC11 path length
real ucfc12(plond,plevp) ! CFC12 path length
real un2o0(plond,plevp) ! N2O path length
real un2o1(plond,plevp) ! N2O path length (hot band)
real uch4(plond,plevp) ! CH4 path length
real uco211(plond,plevp) ! CO2 9.4 micron band path length
real uco212(plond,plevp) ! CO2 9.4 micron band path length
real uco213(plond,plevp) ! CO2 9.4 micron band path length
real uco221(plond,plevp) ! CO2 10.4 micron band path length
real uco222(plond,plevp) ! CO2 10.4 micron band path length
real uco223(plond,plevp) ! CO2 10.4 micron band path length
real bn2o0(plond,plevp) ! pressure factor for n2o
real bn2o1(plond,plevp) ! pressure factor for n2o
real bch4(plond,plevp) ! pressure factor for ch4
real uptype(plond,plevp) ! p-type continuum path length
real abplnk1(14,plond,plevp) ! non-nearest layer Plack factor
real abplnk2(14,plond,plevp) ! nearest layer factor
C
C
C------------------------------Externals--------------------------------
C
integer intmax
external intmax
C
C-----------------------------------------------------------------------
C
C Set pointer variables
C
if (incorrad) then
pabsems = loc(bigbufc(1,lat))
else
call getmem
('RADCLW ',plngbuf,pabsems)
endif
pabstot = loc(absems(1 ))
pabsnxt = loc(absems(1 + plond*plevp*plevp ))
pemstot = loc(absems(1 + plond*plevp*plevp + plond*plev*4))
C
C Initialize and recompute the tclrsf array
C
do i=1,plon
rtclrsf(i,1) = 1.0/tclrsf(i,1)
end do
C
do k=1,plev
do i=1,plon
fclb4(i,k) = 0.
fclt4(i,k) = 0.
tclrsf(i,k+1) = tclrsf(i,k)*(1. - cld(i,k+1))
rtclrsf(i,k+1) = 1./tclrsf(i,k+1)
end do
end do
C
C Calculate some temperatures needed to derive absorptivity and
C emissivity, as well as some h2o path lengths
C
call radtpl
(tnm ,lwupcgs ,qnm ,pint ,plh2o ,
$ tplnka ,s2c ,s2t ,w ,tplnke ,
$ tint ,tint4 ,tlayr ,tlayr4 ,pmln ,
$ piln )
if (doabsems) then
C
C Compute ozone path lengths at frequency of a/e calculation.
C
call radoz2
(o3vmr ,pint ,plol ,plos )
c
c Compute trace gas path lengths
c
call trcpth
(tnm ,pint ,cfc11 ,cfc12 ,n2o ,
$ ch4 ,qnm ,ucfc11 ,ucfc12 ,un2o0 ,
$ un2o1 ,uch4 ,uco211 ,uco212 ,uco213 ,
$ uco221 ,uco222 ,uco223 ,bn2o0 ,bn2o1 ,
$ bch4 ,uptype )
C
C
C Compute total emissivity:
C
call radems
(s2c ,s2t ,w ,tplnke ,plh2o ,
$ pint ,plco2 ,tint ,tint4 ,tlayr ,
$ tlayr4 ,plol ,plos ,ucfc11 ,ucfc12 ,
$ un2o0 ,un2o1 ,uch4 ,uco211 ,uco212 ,
$ uco213 ,uco221 ,uco222 ,uco223 ,uptype ,
$ bn2o0 ,bn2o1 ,bch4 ,co2em ,co2eml ,
$ co2t ,h2otr ,abplnk1 ,abplnk2 ,emstot )
C
C Compute total absorptivity:
C
call radabs
(pmid ,pint ,co2em ,co2eml ,tplnka ,
$ s2c ,s2t ,w ,h2otr ,plco2 ,
$ plh2o ,co2t ,tint ,tlayr ,plol ,
$ plos ,pmln ,piln ,ucfc11 ,ucfc12 ,
$ un2o0 ,un2o1 ,uch4 ,uco211 ,uco212 ,
$ uco213 ,uco221 ,uco222 ,uco223 ,uptype ,
$ bn2o0 ,bn2o1 ,bch4 ,abplnk1 ,abplnk2 ,
$ abstot ,absnxt )
C
C Write abs/ems info to ssd when out-of-core.
C
if (.not.incorrad) then
call writeric
(nabem ,absems(1),plngbuf ,lat )
endif
else
C
C Get total abs/ems info from ssd when out-oc-core.
C
if (.not.incorrad) then
call readric
(nabem ,absems(1),plngbuf ,lat )
endif
end if
C
C Find the lowest and highest level cloud for each grid point
C Note: Vertical indexing here proceeds from bottom to top
C
do i=1,plon
klov(i) = 0
done(i) = .false.
end do
do k=1,plev
do i=1,plon
if (.not.done(i) .and. cld(i,plevp2-k).gt.0.0) then
done(i) = .true.
klov(i) = k
end if
end do
end do
call whenne
(plon,klov,1,0,indx,npts)
do i=1,plon
khiv(i) = klov(i)
done(i) = .false.
end do
do k=plev,1,-1
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (.not.done(i) .and. cld(i,plevp2-k).gt.0.0) then
done(i) = .true.
khiv(i) = k
end if
end do
end do
do i=1,plon
khivm(i) = khiv(i) - 1
end do
C
C Note: Vertical indexing here proceeds from bottom to top
C
do ii=1,npts
i=indx(ii)
do k=klov(i),khiv(i)
fclt4(i,plevp-k) = stebol*tint4(i,plevp2-k)
fclb4(i,plevp-k) = stebol*tint4(i,plevp3-k)
end do
end do
C
C Compute sums used in integrals (all longitude points)
C
C Definition of bk1 & bk2 depends on finite differencing. for
C trapezoidal rule bk1=bk2. trapezoidal rule applied for nonadjacent
C layers only.
C
C delt=t**4 in layer above current sigma level km.
C delt1=t**4 in layer below current sigma level km.
C
do i=1,plon
delt(i) = tint4(i,plev) - tlayr4(i,plevp)
delt1(i) = tlayr4(i,plevp) - tint4(i,plevp)
s(i,plevp,plevp) = stebol*(delt1(i)*absnxt(i,plev,1) +
$ delt (i)*absnxt(i,plev,4))
s(i,plev,plevp) = stebol*(delt (i)*absnxt(i,plev,2) +
$ delt1(i)*absnxt(i,plev,3))
end do
do k=1,plev-1
do i=1,plon
bk2(i) = (abstot(i,k,plev) + abstot(i,k,plevp))*0.5
bk1(i) = bk2(i)
s(i,k,plevp) = stebol*(bk2(i)*delt(i) + bk1(i)*delt1(i))
end do
end do
C
C All k, km>1
C
do km=plev,2,-1
do i=1,plon
delt(i) = tint4(i,km-1) - tlayr4(i,km)
delt1(i) = tlayr4(i,km) - tint4(i,km)
end do
do k=plevp,1,-1
if (k.eq.km) then
do i=1,plon
bk2(i) = absnxt(i,km-1,4)
bk1(i) = absnxt(i,km-1,1)
end do
else if(k.eq.km-1) then
do i=1,plon
bk2(i) = absnxt(i,km-1,2)
bk1(i) = absnxt(i,km-1,3)
end do
else
do i=1,plon
bk2(i) = (abstot(i,k,km-1) + abstot(i,k,km))*0.5
bk1(i) = bk2(i)
end do
end if
do i=1,plon
s(i,k,km) = s(i,k,km+1) + stebol*
$ (bk2(i)*delt(i) + bk1(i)*delt1(i))
end do
end do
end do
C
C Computation of clear sky fluxes always set first level of fsul
C
do i=1,plon
fsul(i,plevp) = lwupcgs(i)
end do
C
C Downward clear sky fluxes store intermediate quantities in down flux
C Initialize fluxes to clear sky values.
C
do i=1,plon
tmp(i) = fsul(i,plevp) - stebol*tint4(i,plevp)
fsul(i,1) = fsul(i,plevp) - abstot(i,1,plevp)*tmp(i) + s(i,1,2)
fsdl(i,1) = stebol*(tplnke(i)**4)*emstot(i,1)
ful(i,1) = fsul(i,1)
fdl(i,1) = fsdl(i,1)
end do
C
C fsdl(i,plevp) assumes isothermal layer
C
do k=2,plev
do i=1,plon
fsul(i,k) = fsul(i,plevp) - abstot(i,k,plevp)*tmp(i) +
$ s(i,k,k+1)
ful(i,k) = fsul(i,k)
fsdl(i,k) = stebol*(tplnke(i)**4)*emstot(i,k) -
$ (s(i,k,2) - s(i,k,k+1))
fdl(i,k) = fsdl(i,k)
end do
end do
C
C Store the downward emission from level 1 = total gas emission * sigma
C t**4. fsdl does not yet include all terms
C
do i=1,plon
ful(i,plevp) = fsul(i,plevp)
absbt(i) = stebol*(tplnke(i)**4)*emstot(i,plevp)
fsdl(i,plevp) = absbt(i) - s(i,plevp,2)
fdl(i,plevp) = fsdl(i,plevp)
end do
C
C Modifications for clouds
C
C Further qualify longitude subset for computations. Select only those
C locations where there are clouds (total cloud fraction <= 1.e-3 treated
C as clear)
C
call whenflt
(plon,tclrsf(1,plevp),1,0.999,indx,npts)
C
C Compute downflux at level 1 for cloudy sky
C
do ii=1,npts
i=indx(ii)
C
C First clear sky flux plus flux from cloud at level 1
C
fdl(i,plevp) = fsdl(i,plevp)*tclrsf(i,plev)*
$ rtclrsf(i,plevp-khiv(i)) + fclb4(i,plev-1)*cld(i,plev)
end do
C
C Flux emitted by other layers
C Note: Vertical indexing here proceeds from bottom to top
C
khighest = khiv(intmax
(plon,khiv,1))
do km=3,khighest
km1 = plevp - km
km2 = plevp2 - km
km4 = plevp4 - km
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (km.le.khiv(i)) then
tmp1 = cld(i,km2)*tclrsf(i,plev)*rtclrsf(i,km2)
fdl(i,plevp) = fdl(i,plevp) +
$ (fclb4(i,km1) - s(i,plevp,km4))*tmp1
end if
end do
end do
C
C Note: Vertical indexing here proceeds from bottom to top
C
do k=1,khighest-1
k1 = plevp - k
k2 = plevp2 - k
k3 = plevp3 - k
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (k.ge.klov(i) .and. k.le.khivm(i)) then
ful(i,k2) = fsul(i,k2)*(tclrsf(i,plevp)*rtclrsf(i,k1))
end if
end do
do km=1,k
km1 = plevp - km
km2 = plevp2 - km
km3 = plevp3 - km
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (k.le.khivm(i) .and. km.ge.klov(i) .and.
$ km.le.khivm(i)) then
c
ful(i,k2) = ful(i,k2) +
$ (fclt4(i,km1) + s(i,k2,k3) - s(i,k2,km3))*
$ cld(i,km2)*(tclrsf(i,km1)*rtclrsf(i,k1))
end if
end do
end do ! km=1,k
end do ! k=1,khighest-1
C
do k=1,plevp
k2 = plevp2 - k
k3 = plevp3 - k
do i=1,plon
start(i) = .false.
end do
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (k.ge.khiv(i)) then
start(i) = .true.
ful(i,k2) = fsul(i,k2)*tclrsf(i,plevp)*
$ rtclrsf(i,plevp-khiv(i))
end if
end do
do km=1,khighest
km1 = plevp - km
km2 = plevp2 - km
km3 = plevp3 - km
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (start(i) .and. km.ge.klov(i) .and. km.le.khiv(i)) then
ful(i,k2) = ful(i,k2) +
$ (cld(i,km2)*tclrsf(i,km1)*rtclrsf(i,plevp-khiv(i)))*
$ (fclt4(i,km1) + s(i,k2,k3) - s(i,k2,km3))
end if
end do
end do ! km=1,khighest
end do ! k=1,plevp
C
C Computation of the downward fluxes
C
do k=2,khighest-1
k1 = plevp - k
k2 = plevp2 - k
k3 = plevp3 - k
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (k.le.khivm(i)) fdl(i,k2) = 0.
end do
do km=k+1,khighest
km1 = plevp - km
km2 = plevp2 - km
km4 = plevp4 - km
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (k.le.khiv(i) .and. km.ge.max0(k+1,klov(i)) .and.
$ km.le.khiv(i)) then
C
fdl(i,k2) = fdl(i,k2) +
$ (cld(i,km2)*tclrsf(i,k1)*rtclrsf(i,km2))*
$ (fclb4(i,km1) - s(i,k2,km4) + s(i,k2,k3))
end if
end do
end do ! km=k+1,khighest
CDIR$ IVDEP
do ii=1,npts
i=indx(ii)
if (k.le.khivm(i)) then
fdl(i,k2) = fdl(i,k2) + fsdl(i,k2)*
$ (tclrsf(i,k1)*rtclrsf(i,plevp-khiv(i)))
end if
end do
end do ! k=1,khighest-1
C
C End cloud modification loops
C
C All longitudes: store history tape quantities
C
do i=1,plon
C
C Downward longwave flux
C
flwds(i) = fdl(i,plevp)
C
C Net flux
C
flns(i) = ful(i,plevp) - fdl(i,plevp)
C
C Clear sky flux at top of atmosphere
C
c++csz
c Following line is CCM2-CCM3 definition of clear sky OLR
c This definition differs from analogous flnt definition by emission of layer 0
c This will be superseded in CCM4
flntc(i) = fsul(i,1)
c Following line defines clear sky OLR exactly analogously to all sky OLR
c This produces exact agreement between FLNT and FLNTC for clear skies
c This will be adopted in CCM4
c flntc(i) = fsul(i,1) - fsdl(i,1)
c--csz
flnsc(i) = fsul(i,plevp) - fsdl(i,plevp)
C
C Outgoing ir
C
flnt(i) = ful(i,1) - fdl(i,1)
end do
C
C Computation of longwave heating (k per sec)
C
gocp = gravit/cpair
do k=1,plev
do i=1,plon
qrl(i,k) = (ful(i,k) - fdl(i,k) - ful(i,k+1) + fdl(i,k+1))*
$ gocp/((pint(i,k) - pint(i,k+1)))
end do
end do
if (.not.incorrad) then
call freemem
(pabsems)
end if
C
c++csz
#ifdef CRM_SRB
do k=1,plevp ! NB: plevp not plev
do i=1,plon
c Vertical profile of broadband fluxes
flx_LW_dwn(i,k)=fdl(i,k)*0.001 ! [W m-2] Downwelling LW flux
flx_LW_up(i,k)=ful(i,k)*0.001 ! [W m-2] Upwelling LW flux
enddo ! end loop over i, lon
enddo ! end loop over k, lev
#endif /* not CRM_SRB */
c--csz
return
end