!------------------------------------------------------------ ! ! MODULE OSS_ADDBL: contains items needed for the ! OSS Scattering Adding-Doubling Module ! !-------------------------------------------------------------- MODULE oss_addbl PRIVATE public:: scattRT !------------------------------------------------------------------------ ! Profile Parameters (should match with oss_ir_module) !------------------------------------------------------------------------ integer :: mxlay,maxcld parameter (mxlay=100,maxcld=10) !------------------------------------------------------------------------ ! Multiple Scattering Parameters !------------------------------------------------------------------------ real accur integer mxcang,maxcmu,mxang,mxang2 parameter(mxcang=64) parameter (maxcmu=2*mxcang) parameter(mxang=mxcang+1,mxang2=mxang*mxang) data accur/1.e-04/ CONTAINS SUBROUTINE scattRT(tautot,xG,btemp,tabsHydr,tscatt,gasym,emis,fBeam,vn,nLay,nObs,& sBeam,nStr,umu,umu0,lookup,delphi,iflux,flxNetMono, & rad,xkt,xkEmRf) !---Wrapper to interface oss_module with ossScat. Some calling arguments ! are placeholders. USE constants, only : MISSING_REAL !--Input/output variables REAL :: vn,emis,fBeam,umu,umu0,delphi,rad INTEGER :: nLay,nObs,nStr,iflux LOGICAL :: lookup,sbeam INTEGER,DIMENSION(:),ALLOCATABLE :: lTyp REAL, DIMENSION(:) :: xG,tautot,flxNetMono REAL, DIMENSION(:) :: tabsHydr,tscatt,gasym REAL, DIMENSION(:) :: xkt REAL :: xkEmRf !---Internal variables REAL*8 :: rvn REAL :: tau(mxlay),cldabs REAL :: albedo,btemp,gg,hl(0:maxcmu),pmom(0:maxcmu,mxlay) REAL, PARAMETER :: scatLB=1e-8 INTEGER :: l,k,ik,ikm1 LOGICAL :: lamber,plank,deltam REAL,DIMENSION(:),ALLOCATABLE :: tscattIn !---Variable intialization data lamber/.true./,deltam/.true./ plank=.false. if(vn.lt.5000.)plank=.true. if(.not.sbeam)fBeam=0. albedo=1.-emis rvn = vn xkt = MISSING_REAL xkem = MISSING_REAL allocate(lTyp(nLay),tscattIn(size(tscatt))) tscattIn = 0. pmom = 0. lTyp = 0 !---Compute optical properties of default layers: do l=1,nLay !---Absorption optical depth (water vapor, fixed gases and hydrometeor): tau(l) =tautot(l) + tabsHydr(l) if (tscatt(l).gt.scatLB) lTyp(l)=1 if (lTyp(l).gt.0.) then !---Phase function: pmom(0,l)=1. gg=gasym(l) do k=1,nstr pmom(k,l)=pmom(k-1,l)*gg end do end if end do tscattIn = tscatt call ossscat( nlay, tau, tscattIn, pmom, xG, lTyp, & rvn, nstr, nobs, umu, fBeam, umu0, delphi, lamber, albedo, hl, & btemp, deltam, plank, sbeam, lookup, rad) deallocate(lTyp,tscattIn) RETURN END SUBROUTINE SCATTRT SUBROUTINE OSSSCAT( NLAY, TAUABS, TAUSCAT, ALPHA, TEMP, LTYPIN, & VN, NSTR, LOBS, UMU, FBEAM, UMU0, DELPHI, LAMBER, ALBEDO, HL, & TSFC, DELTAM, PLANKIN, SBEAMIN, LOOKUP, RADOUT) !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! ! **** *********** VERSION 2.0 : 21 MARCH 1995 ***************** ! ! ALGORITHM: J.L. MONCET ! S.A. CLOUGH ! ! IMPLEMENTATION: J.L. MONCET ! D.A. PORTMAN ! ! ATMOSPHERIC AND ENVIRONMENTAL RESEARCH INC. ! 840 MEMORIAL DRIVE, CAMBRIDGE, MA 02139 ! !---------------------------------------------------------------------- ! ! WORK SUPPORTED BY: THE ARM PROGRAM ! OFFICE OF ENERGY RESEARCH ! DEPARTMENT OF ENERGY ! !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! REAL*8 VN REAL TAUABS(MXLAY),TAUSCAT(MXLAY) REAL ALPHA(0:2*MXCANG,MXLAY) REAL TEMP(0:MXLAY) !---- REAL UMU,UMU0,DELPHI,FBEAM,ACCUR REAL UMU,UMU0,DELPHI,FBEAM REAL ALBEDO,HL(1),TSFC,RADOUT INTEGER NLAY,NSTR,LTYPIN(MXLAY),LTYP(MXLAY),LOBS LOGICAL DELTAM,PLANKIN,PLANK,SBEAMIN,SBEAM,LOOKUP,LAMBER ! REAL TAUEXT(MXLAY),SSALB(MXLAY),F0(0:MXLAY) real alpha1(0:2*mxcang),rad(mxang) LOGICAL REFLB,REFLT ! REAL TTOP(1),TBOT(1) COMMON /LAYDAT/ RLAY(MXANG2),TLAY(MXANG2), EMPL(MXANG),EMML(MXANG) COMMON /ACMDWN/ RTOP(MXANG2),EMTOP(MXANG) COMMON /ACMUP / RBOT(MXANG2),EMBOT(MXANG) COMMON /ANGL / PTH(MXANG),GMU(MXANG),GWT(MXANG),GMU0,& YLM(0:2*MXCANG-1,MXANG),YLM0(0:2*MXCANG-1),& GMU0VEC(1) COMMON /LPAR / PLANK,SBEAM COMMON /PNLPAR/ NANG,N2ANG,NANG2 COMMON /CONSTN/ PI,CL2INV ! DATA INIT/1/ SAVE INIT ! PLANK=PLANKIN SBEAM=SBEAMIN LTYP(1:NLAY)=LTYPIN(1:NLAY) ! IF(INIT.EQ.1)THEN ! ====================================================================== ! === INITIALIZATION =================================================== ! ====================================================================== PI=ACOS(-1.) CL2INV=1./LOG(2.) ! NCANG=NSTR/2 ! !-----Generate discrete angles and associated weights for !-----Double-Gauss" quadrature (see Stamnes, 1981) ! CALL QGAUSN(NCANG,GMU,GWT) ! NANG=NCANG+1 N2ANG=2*NANG NANG2=NANG*NANG ! DO 120 I=1,NCANG 120 PTH(I)=1./GMU(I) ! INIT=0 END IF ! ! *** Insert user angle. ! GMU(NANG)=UMU PTH(NANG)=1./UMU ! ! *** Set NAZ ! NAZ=0 IF(SBEAM)THEN GMU0=UMU0 IF((1.-GMU0).GT.1.E-05.AND. (1.-GMU(NANG)).GT.1.E-05)NAZ=N2ANG-3 END IF ! ! *** Set control parameters for CHARTS run ! IF(LAMBER) THEN ISRFL=-1 IF(ALBEDO.LE.1.E-6)ISRFL=0 ELSE STOP 'OSSSCAT: This version only supports Lambertian surfaces' ENDIF ! CALL SETCTL(NLAY,LTYP,LOBS,SBEAM,PLANK,ISRFL,LOOKUP,NAZ,& NBOT0,NBOT,NTOP0,NTOP) ! N1=NTOP0 N2=NBOT0 ! ! *** Delta-M scaling ! F=0. DO I=1,NLAY IF(DELTAM)THEN F=ALPHA(N2ANG-2,I) TAUSCAT(I)=TAUSCAT(I)*(1.-F) END IF ! DO 50 L=0,N2ANG-3 ALPHA(L,I)=(2*L+1)*(ALPHA(L,I)-F)/(1.-F) 50 CONTINUE ENDDO ! DO 330 L=1,NLAY TAUEXT(L)=TAUABS(L) IF(LTYP(L).GT.0)THEN TAUEXT(L)=TAUEXT(L)+TAUSCAT(L) IF(TAUEXT(L).LE.0.)THEN SSALB(L)=0. ELSE SSALB(L)=TAUSCAT(L)/TAUEXT(L) END IF END IF 330 CONTINUE ! IF(SBEAM)THEN ! !-----Compute solar beam extinction (current version does not treat !-----specularly reflected beam) ! SUMEX=0. F0(0)=FBEAM DO 350 L=1,NLAY !-----Add scattering component to total extinction SUMEX=SUMEX+TAUEXT(L) !-----Calculate solar irradiance at top of scattering layer F0(L)=FBEAM*EXP(-SUMEX/GMU0) 350 CONTINUE END IF ! ! ===================================================================== ! === BEGIN LOOP OVER AZIMUTHAL ANGLES ================================ ! ===================================================================== KCONV=0 DO 700 MAZ=0,NAZ EMBOT=0. EMTOP=0. RTOP=0. RBOT=0. ! ! *** Generate normalized Legendre polynomials for computational angles ! *** (GMU) and for incident solar beam angle cosine (GMU0). ! CALL LEPOLY_OSS(NANG,MAZ,2*MXCANG-1,N2ANG-3,GMU,YLM) ! --Put GMU0 in vector form to prevent compiler error: GMU0VEC(1)=GMU0 IF(SBEAM)CALL LEPOLY_OSS(1,MAZ,2*MXCANG-1,N2ANG-3,GMU0VEC,YLM0) ! IF(SBEAM)CALL LEPOLY_OSS(1,MAZ,2*MXCANG-1,N2ANG-3,GMU0,YLM0) ! !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! LOOP OVER LAYERS THE ABOVE OBSERVER LEVEL - MERGE DOWN CASE + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ REFLT=.FALSE. ! DO 500 LNUM=N1,LOBS-1 ! IF(LTYP(LNUM).LE.0)THEN !----------------------------------------------------------------------- ! CLEAR LAYER CASE: !----------------------------------------------------------------------- ! *** Accumulate partial results for successive clear layers "LAYDAT". ! *** Final merge with results contained in "ACMDWN" done at the end, ! *** when (LTYP=-99 OR -100). CALL CLRLAY(TAUEXT(LNUM),TEMP(LNUM-1),& TEMP(LNUM),REFLT,LTYP(LNUM),VN) IF(LTYP(LNUM).LE.-99) CALL ADDCLR(RTOP,TTOP,EMTOP,REFLT,PLANK) ELSE !----------------------------------------------------------------------- ! CLOUDY LAYER CASE: !----------------------------------------------------------------------- ! *** Calculate reflection/transmission matrices (in RLAY and TLAY) and ! *** internal sources (EMPL-upward- and EMML-downward) for current layer ! do k=0,n2ang-2 alpha1(k)=alpha(k,lnum) end do CALL MSLAY(TAUEXT(LNUM),SSALB(LNUM),TEMP(LNUM-1),TEMP(LNUM),& F0(LNUM-1),RLAY,TLAY,EMPL,EMML,MAZ,VN,ALPHA1,0) ! ! *** Accumulate results in ACMWDN ! CALL ADDMS(RTOP,TTOP,EMTOP,REFLT) END IF 500 CONTINUE !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! LOOP OVER LAYERS BELOW THE OBSERVER LEVEL - MERGE UP CASE + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! ! *** Initialize RBOT and EMBOT ! REFLB=.FALSE. CALL SURFCE(MAZ,ISRFL,TSFC,ALBEDO,F0(NLAY),RBOT,EMBOT,REFLB,VN) ! DO 600 LNUM=N2,LOBS,-1 ! IF(LTYP(LNUM).LE.0)THEN !----------------------------------------------------------------------- ! CLEAR LAYER CASE: !----------------------------------------------------------------------- ! *** Accumulate partial results for successive clear layers "LAYDAT". ! *** Final merge with results contained in "ACMUP" done at the end, ! *** when (LTYP=-99 OR -100). CALL CLRLAY(TAUEXT(LNUM),TEMP(LNUM),TEMP(LNUM-1),REFLB,LTYP(LNUM),VN) IF(LTYP(LNUM).LE.-99) CALL ADDCLR(RBOT,TBOT,EMBOT,REFLB,PLANK) ELSE !----------------------------------------------------------------------- ! CLOUDY LAYER CASE: !----------------------------------------------------------------------- ! *** Calculate reflection/transmission matrices (in RLAY and TLAY) and ! *** internal sources (EMPL-upward- and EMML-downward) for current layer ! do k=0,n2ang-2 alpha1(k)=alpha(k,lnum) end do CALL MSLAY(TAUEXT(LNUM),SSALB(LNUM),TEMP(LNUM),TEMP(LNUM-1),& F0(LNUM-1),RLAY,TLAY,EMPL,EMML,MAZ,VN,ALPHA1,1) ! ! *** Accumulate results. ! CALL ADDMS(RBOT,TBOT,EMBOT,REFLB) END IF 600 CONTINUE !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ! DO FINAL MERGE - Output radiances in RAD + !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IF (LOOKUP) THEN CALL MRGRAD(RTOP,EMTOP,RBOT,EMBOT,REFLT,REFLB,RAD) ELSE CALL MRGRAD(RBOT,EMBOT,RTOP,EMTOP,REFLB,REFLT,RAD) END IF ! ===================================================================== ! === END OF PANEL LOOP =============================================== ! ===================================================================== IF(MAZ.EQ.0)THEN RADOUT=RAD(NANG) ! *** (Reset control parameters for MAZ >0) PLANK=.FALSE. N1=NBOT N2=NTOP ELSE ! *** Compute radiance scaling for azimuthal order MAZ AZTERM=RAD(NANG)*COS(MAZ*DELPHI*PI/180.) RADOUT=RADOUT+AZTERM ! IF(RADOUT.NE.0.)THEN AZERR=ABS(AZTERM)/ABS(RADOUT) IF(AZERR.LE.ACCUR)KCONV=KCONV+1 END IF ! IF (KCONV.GE.2) GOTO 800 ! END IF 700 CONTINUE ! ===================================================================== ! === END OF LOOP OVER AZIMUTHAL ANGLES =============================== ! ===================================================================== 800 RETURN ! END subroutine ossscat ! SUBROUTINE SETCTL(NLAY,LTYP,LOBS,SBEAM,PLANK,ISRFL,& LOOKUP,NAZ,NBOT0,NBOT,NTOP0,NTOP) !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! This subroutine adjusts LTYP for the clear layers and adjusts the ! atmospheric boundaries to avoid in many cases treating systematically ! all the input layers in the radiative transfer calculations (for ! instance, in the solar case one can ignore the uppermost layers if ! they are non-reflecting since they do not produce a diffuse radiation ! field. Similarly, in presence of a Lambertian surface, there is no ! contribution from the surface and the clear layers adjacent to the ! surface for high order azimuthal components. CHARTS calculations ! will in this case, be restricted to the portion of the atmosphere ! between the top and bottom scattering layers). This subroutine also ! resets ISBEAM, IPLANK and NAZ in order to save on the amount of ! computation in some special cases (e.g. when the observer faces a ! non-reflecting atmosphere). ! ! Values of LTYP for clear layers are modified to indicate the ! relative position of the each layer within a set of contiguous ! clear layers above and below the observer level. LTYP values ! are assigned values as follows: ! ! LTYP = -1 - first clear layer ! = 0 - middle layers ! = -99 - last clear layer ! = -100 - single clear layer ! ! The input values of LTYP for cloudy layers indicate the actual cloud ! model used for each layer. LTYP is modified in this routine to provide ! a unique index value (>1) for each cloud layer. ! ! Output variables: ! ! NBOT0= lowest atmospheric layer below observer level at which ! one should start the radiative transfer calculations for ! MAZ=0 ! NBOT = same as NBOT0 for MAZ >0 ! NTOP0= highest atmospheric layer above observer level at which ! one should start the radiative transfer calculations for ! MAZ=0 ! NTOP = same as NTOP0 for MAZ >0 ! ! REVISED: 21 MARCH 1995 !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC INTEGER LTYP(NLAY) LOGICAL PLANK,SBEAM,LOOKUP LOGICAL REFLS0,REFLS,REFLT,REFLB0,REFLB DATA REFLS0,REFLS/.FALSE.,.FALSE./ ! ! *** Surface reflectance ! IF(ISRFL.NE.0)REFLS0=.TRUE. IF(ISRFL.GT.0)REFLS=.TRUE. ! ! *** Set LTYP for clear layers above observer level (MERGE DOWN case) ! NTOP=1 REFLT=.FALSE. DO 10 I=1,LOBS-1 IF(LTYP(I).EQ.0)THEN ! IF(I.EQ.1)THEN LTYP(I)=-1 ELSE IF(LTYP(I-1).GT.0)THEN LTYP(I)=-1 END IF ! IF(I.EQ.LOBS-1)THEN LTYP(I)=-99+LTYP(I) ELSE IF(LTYP(I+1).GT.0)THEN LTYP(I)=-99+LTYP(I) END IF ! IF (.NOT.REFLT) NTOP=NTOP+1 ELSE REFLT=.TRUE. END IF 10 CONTINUE ! ! *** Set LTYP for clear layers below observer level (MERGE UP case) ! NBOT=NLAY REFLB=.FALSE. DO 20 I=NLAY,LOBS,-1 IF(LTYP(I).EQ.0)THEN ! IF(I.EQ.NLAY)THEN LTYP(I)=-1 ELSE IF(LTYP(I+1).GT.0)THEN LTYP(I)=-1 END IF ! IF(I.EQ.LOBS)THEN LTYP(I)=-99+LTYP(I) ELSE IF(LTYP(I-1).GT.0)THEN LTYP(I)=-99+LTYP(I) END IF ! IF(.NOT.REFLB)NBOT=NBOT-1 ELSE REFLB=.TRUE. END IF 20 CONTINUE ! REFLB0=REFLB.OR.REFLS0 REFLB=REFLB.OR.REFLS ! ! *** Adjust boundaries for general solar case ! NBOT0=NBOT NTOP0=NTOP IF(REFLS0)NBOT0=NLAY IF(REFLS)NBOT=NLAY ! ! *** Adjust boundaries for thermal case ! IF(PLANK)THEN NBOT0=NLAY NTOP0=1 END IF ! ! *** Special case: No forward reflection - shrink atmospheric ! *** boundaries and force SBEAM = .FALSE. (assume that observer ! *** never looks directly into the sun.) ! IF(LOOKUP.AND..NOT.REFLT)THEN SBEAM=.FALSE. NAZ=0 ! ISRFL=-99 NBOT0=LOBS-1 END IF ! IF(.NOT.LOOKUP)THEN IF(.NOT.REFLB)NAZ=0 IF(.NOT.REFLB0)THEN SBEAM=.FALSE. NTOP0=LOBS END IF END IF ! ! *** Eliminate trivial case ! ! IF ((LOOKUP.AND.LOBS.EQ.1).OR.& ! (.NOT.LOOKUP.AND..NOT.REFLB0.AND.LOBS.EQ.NLAY+1))& ! STOP 'CASE NOT TREATED' RETURN END subroutine setctl ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! OSS (Optimal Spectral Sampling) ! $Name: $ ! $Id: oss_addbl.f90,v 1.4 2006/12/15 21:04:57 raschbre Exp $ ! Copyright AER, Inc., 2002, 2003. All rights Reserved. ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SUBROUTINE SURFCE(MAZ,ISRFL,TSFC,SALB,F0,R,EM,REFLS,VN) !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! ! This subroutine initializes the reflection matrix (R) and emission ! vector (EM) for the lower atmosphere by applying boundary conditions ! at the surface. The current version treats Lambertian surfaces only. ! ! MODIFIED: 21 MARCH 1995 to implement spectral interpolation ! of surface properties within panel ! !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! REAL R(NANG,NANG),EM(NANG) REAL*8 VN LOGICAL PLNCK,SBEAM,REFLS COMMON /ANGL / PTH(MXANG),GMU(MXANG),GWT(MXANG),GMU0,& YLM(0:2*MXCANG-1,MXANG),YLM0(0:2*MXCANG-1) COMMON /CONSTN/ PI,CL2INV COMMON /LPAR / PLNCK,SBEAM COMMON /PNLPAR/ NANG,N2ANG,NANG2 ! ! REFLS=.FALSE. ! CALL VZERO(EM,NANG) ! IF(ISRFL.EQ.-99)RETURN ! IF(ISRFL.GT.0)GOTO 100 ! ! *** LAMBERTIAN SURFACE ! IF (MAZ.GT.0)RETURN ! RS=0. ! IF(ISRFL.EQ.-1)THEN ! ! *** Calculate surface reflectance across panel ! RS=SALB REFLS=.TRUE. ELSE IF (ISRFL.EQ.2)THEN STOP 'OSSCAT: Subroutine SURFCE - option not supported' END IF ! ! *** Calculate reflection matrix ! IF(REFLS)THEN DO 40 J=1,NANG-1 FAC=2.*GMU(J)*GWT(J) DO 40 I=1,NANG 40 R(J,I)=RS*FAC DO 45 I=1,NANG 45 R(NANG,I)=0. END IF ! ! *** Initialize EM by combining thermal emission and reflection of direct ! *** solar beam at the surface ! IF(PLNCK)THEN B=WNPLAN(VN,TSFC) WK=(1.-RS)*B ! DO 60 I=1,NANG 60 EM(I)=WK END IF ! IF(SBEAM.AND.REFLS)THEN FAC=GMU0/PI WK=RS*F0*FAC ! DO 75 I=1,NANG 75 EM(I)=EM(I)+WK END IF ! ! *** General case (not implemented) ! 100 RETURN ENDsubroutine surfce ! SUBROUTINE CLRLAY(TAU,TA,TB,REFLG,INIT,VN) !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! ! This subroutine does the transmission and emission calculations ! for a clear slab. The routine processes NLIM spectral points. ! Transmission and forward and backward emission for each successive ! clear layer are accumulated respectively in TLAY, EMPL and EMML. ! If no thermal emission the routine accumulates the optical depths ! in TLAY and calculates the transmission only when the last clear layer ! of a series is reached. Linear-in-tau approximation is used for the ! thermal source and it is assumed that the Planck function varies ! linearly across the spectral interval spanned by the NLIM spectral ! points. ! ! REVISED: 11 OCTOBER 1993 !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! REAL*8 VN LOGICAL REFLG,PLNCK,SBEAM ! COMMON /ANGL / PTH(MXANG),GMU(MXANG),GWT(MXANG),GMU0,& YLM(0:2*MXCANG-1,MXANG),YLM0(0:2*MXCANG-1) COMMON /CONSTN/ PI,CL2INV COMMON /LAYDAT/ RLAY(MXANG2),TLAY(MXANG2),& EMPL(MXANG),EMML(MXANG) COMMON /LPAR / PLNCK,SBEAM COMMON /PNLPAR/ NANG,N2ANG,NANG2 COMMON /LOCWK / TX(MXANG),EMP(MXANG),EMM(MXANG),WK(MXANG) ! ! Scale optical depths for all incident angles including observer ! angle. ! DO 20 I=1,NANG WK(I)=TAU*PTH(I) 20 CONTINUE ! ! *** THERMAL CASE. ! IF(PLNCK)THEN ! ! Calculate vertically averaged Planck function for the layer and ! correction term for linear-in-Tau approximation at each spectral ! point ! BA=WNPLAN(VN,TA) BB=WNPLAN(VN,TB) BAV=.5*(BB+BA) DELB=.5*(BB-BA) ! Or omit linear in tau ! bav = wnplan(vn,(ta+tb)/2.) ! delb = 0. ! ! Compute transmittance and thermal emission ! DO 50 N=1,NANG TX(N)=EXP(-WK(N)) EM0=1.-TX(N) IF(WK(N).GT.1.E-03)THEN CCI=2./WK(N) EMD=CCI*(TX(N)-1.)+(TX(N)+1.) ELSE EMD=WK(N)*WK(N)*(1.-0.5*WK(N))/6. END IF EMP(N)=EM0*BAV+EMD*DELB EMM(N)=EM0*BAV-EMD*DELB 50 CONTINUE ! ! Accumulate partial results for clear slab. ! IF(INIT.EQ.-1.OR.INIT.EQ.-100)THEN ! *** First layer CALL VCOPY(EMP,EMPL,NANG) IF(REFLG)CALL VCOPY(EMM,EMML,NANG) CALL VCOPY(TX,TLAY,NANG) ELSE ! *** Update forward and backward emission for subsequent layers CALL DMXVV(TX,EMPL,WK,NANG) CALL sVADD(WK,EMP,EMPL,NANG) IF(REFLG)THEN CALL DMXVV(TLAY,EMM,WK,NANG) CALL sVADD(WK,EMML,EMML,NANG) END IF ! *** Update transmission CALL DMXVV(TLAY,TX,TLAY,NANG) END IF ELSE ! ! *** SOLAR ONLY ! IF(INIT.EQ.-1.OR.INIT.EQ.-100)THEN CALL VCOPY(WK,TLAY,NANG) ELSE CALL sVADD(WK,TLAY,TLAY,NANG) END IF ! ! *** Compute transmittance for combined consecutive clear layers ! IF(INIT.LE.-99)THEN DO 80 N=1,NANG TLAY(N)=EXP(-TLAY(N)) 80 CONTINUE END IF END IF RETURN END subroutine clrlay ! SUBROUTINE MSLAY(TEXT,SSALB,TA,TB,F0,RLAY,TLAY,EMPL,EMML,& MAZ,VN,ALPHA,MRGUP) !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! ! This subroutine does the interpolation of the doubling results ! for a cloudy layer. The routine processes NLIM spectral points. ! Reflection, transmission and forward and backward emission are output ! respectively in RLAY, TLAY, EMPL and EMML. Linear-in-tau approximation ! is used for the thermal source and it is assumed that the Planck ! function varies linearly across the spectral interval spanned by the ! NLIM spectral points. ! ! LAST REVISED: MARCH 1995 to implement linear spectral interpolation ! of the doubling results. !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! REAL ALPHA(0:2*MXCANG) REAL RLAY(NANG2),TLAY(NANG2),EMPL(NANG),EMML(NANG) REAL EM(2*MXANG),SBM(2*MXANG) REAL*8 VN LOGICAL PLNCK,SBEAM ! COMMON /LPAR / PLNCK,SBEAM COMMON /PNLPAR/ NANG,N2ANG,NANG2 ! CALL VZERO(EMPL,NANG) CALL VZERO(EMML,NANG) ! IF (PLNCK)THEN BA=WNPLAN(VN,TA) BB=WNPLAN(VN,TB) BAV=.5*(BB+BA) DELB=.5*(BB-BA) ! Or omit linear in tau ! bav = wnplan(vn,(ta+tb)/2.) ! delb = 0. END IF ! ! Get doubling tables for current cloud layer ! !CALL GENTAB(TABS,TSCAT,ALPHA,MAZ,RLAY,TLAY,EM,SBM) CALL GENTAB(TEXT,SSALB,ALPHA,MAZ,RLAY,TLAY,EM,SBM) ! ! Compute forward and backward internal emission due to ! thermal and solar sources ! IF(PLNCK)THEN ! ! Calculate vertically averaged Planck function for the layer and ! correction term for linear-in-Tau approximation at each spectral ! point ! DO 140 N=1,NANG EMPL(N)=EM(N)*BAV+EM(NANG+N)*DELB EMML(N)=EM(N)*BAV-EM(NANG+N)*DELB 140 CONTINUE END IF ! IF(SBEAM)THEN ! ! Add solar component ! IF(MRGUP.EQ.1)THEN DO 230 N=1,NANG EMPL(N)=EMPL(N)+SBM(N)*F0 EMML(N)=EMML(N)+SBM(NANG+N)*F0 230 CONTINUE ELSE DO 240 N=1,NANG EMPL(N)=EMPL(N)+SBM(NANG+N)*F0 EMML(N)=EMML(N)+SBM(N)*F0 240 CONTINUE END IF END IF ! RETURN END subroutine mslay ! SUBROUTINE GENTAB(TEXT,SSALB,ALPHA,MAZ,R,T,EM,SBM) !CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ! ! Generate look up tables of reflexion, transmission matrices ! and source vectors by doubling calculations for the range of ! absorption optical depths specified by NMIN and NMAX. NMIN0 ! and NMAX0 indicate the range of the calculations covered in ! previous calls to GENTAB so that calculations corresponding ! to NMIN0>>>>> ', MESSAG STOP END IF NumMsg = NumMsg + 1 IF( MsgLim ) RETURN IF ( NumMsg.LE.MaxMsg ) THEN WRITE ( *, '(/,2A,/)' ) ' ******* WARNING >>>>>> ', MESSAG ELSE WRITE ( *,99 ) MsgLim = .True. ENDIF RETURN 99 FORMAT( //,' >>>>>> TOO MANY WARNING MESSAGES -- ', & 'They will no longer be printed <<<<<<<', // ) END subroutine errmsg DOUBLE PRECISION FUNCTION D1MACH(I) ! Double-precision machine constants (see R1MACH for documentation). ! By default, returns values appropriate for a computer with IEEE ! arithmetic. This is an abbreviated version of a routine widely ! used for 20+ years by numerical analysts. Most of the values in ! the original version pertain to computers which went to computer ! heaven years ago and are of little if any interest. ! ! If the values herein do not work for any reason, just look in ! your Fortran manual for the correct values (usually in the part ! discussing representations of numbers) and insert them. The exact ! values are not that important; they can be a factor of 2-3 off ! without causing any harm. ! Only I = 1,2,4 is actually used by DISORT. ! This routine is superseded in Fortran-90 by the intrinsic numeric ! inquiry functions HUGE(1.D0), TINY(1.D0), and EPSILON(1.D0). ! The original version can be found on NetLib (search by name): ! http://www.netlib.org/ ! ==================================================================== INTEGER I !EXTERNAL ERRMSG IF( I.EQ.1 ) THEN D1MACH = 2.3D-308 ! D1MACH = TINY(1.D0) ELSE IF( I.EQ.2 ) THEN D1MACH = 1.7D+308 ! D1MACH = HUGE(1.D0) ELSE IF( I.EQ.4 ) THEN D1MACH = 2.3D-16 ! D1MACH = EPSILON(1.D0) ELSE CALL ERRMSG( 'D1MACH--argument incorrect', .TRUE.) END IF RETURN END function d1mach end module oss_addbl