module radsw 2,7 !----------------------------------------------------------------------- ! ! Purpose: Solar radiation calculations. ! !----------------------------------------------------------------------- use shr_kind_mod, only: r8 => shr_kind_r8 use ppgrid, only: pcols, pver, pverp use abortutils, only: endrun use cam_history, only: outfld use scamMod, only: single_column,scm_crm_mode,have_asdir, & asdirobs, have_asdif, asdifobs, have_aldir, & aldirobs, have_aldif, aldifobs use cam_logfile, only: iulog use radconstants, only: nswbands, wavmin, wavmax implicit none private save ! Public methods public ::& radsw_init, &! initialize constants radcswmx ! driver for solar radiation code ! Private module data real(r8) :: gravit ! Acceleration of gravity real(r8) :: rga ! 1./gravit real(r8) :: sslp ! Standard sea-level pressure !=============================================================================== CONTAINS !=============================================================================== subroutine radcswmx(lchnk ,ncol , & 1,66 E_pint ,E_pmid ,E_h2ommr ,E_o3mmr , & E_o2mmr ,E_cld ,E_cicewp ,E_cliqwp ,E_rel , & E_rei ,eccf ,E_coszrs ,solin , & E_asdir ,E_asdif ,E_aldir ,E_aldif ,nmxrgn , & pmxrgn ,qrs,qrsc,fsnt ,fsntc ,fsdtoa, fsntoa, & fsutoa ,fsntoac, fsnirtoa,fsnrtoac,fsnrtoaq,fsns , & fsnsc ,fsdsc ,fsds ,sols ,soll , & solsd ,solld , fns ,fcns , & Nday ,Nnite ,IdxDay ,IdxNite, E_co2mmr, & E_aer_tau, E_aer_tau_w, E_aer_tau_w_g, E_aer_tau_w_f) !----------------------------------------------------------------------- ! ! Purpose: ! Solar radiation code ! ! Method: ! Basic method is Delta-Eddington as described in: ! ! Briegleb, Bruce P., 1992: Delta-Eddington ! Approximation for Solar Radiation in the NCAR Community Climate Model, ! Journal of Geophysical Research, Vol 97, D7, pp7603-7612). ! ! Five changes to the basic method described above are: ! (1) addition of sulfate aerosols (Kiehl and Briegleb, 1993) ! (2) the distinction between liquid and ice particle clouds ! (Kiehl et al, 1996); ! (3) provision for calculating TOA fluxes with spectral response to ! match Nimbus-7 visible/near-IR radiometers (Collins, 1998); ! (4) max-random overlap (Collins, 2001) ! (5) The near-IR absorption by H2O was updated in 2003 by Collins, ! Lee-Taylor, and Edwards for consistency with the new line data in ! Hitran 2000 and the H2O continuum version CKD 2.4. Modifications ! were optimized by reducing RMS errors in heating rates relative ! to a series of benchmark calculations for the 5 standard AFGL ! atmospheres. The benchmarks were performed using DISORT2 combined ! with GENLN3. The near-IR scattering optical depths for Rayleigh ! scattering were also adjusted, as well as the correction for ! stratospheric heating by H2O. ! ! The treatment of maximum-random overlap is described in the ! comment block "INDEX CALCULATIONS FOR MAX OVERLAP". ! ! Divides solar spectrum into 19 intervals from 0.2-5.0 micro-meters. ! solar flux fractions specified for each interval. allows for ! seasonally and diurnally varying solar input. Includes molecular, ! cloud, aerosol, and surface scattering, along with h2o,o3,co2,o2,cloud, ! and surface absorption. Computes delta-eddington reflections and ! transmissions assuming homogeneously mixed layers. Adds the layers ! assuming scattering between layers to be isotropic, and distinguishes ! direct solar beam from scattered radiation. ! ! Longitude loops are broken into 1 or 2 sections, so that only daylight ! (i.e. coszrs > 0) computations are done. ! ! Note that an extra layer above the model top layer is added. ! ! cgs units are used. ! ! Special diagnostic calculation of the clear sky surface and total column ! absorbed flux is also done for cloud forcing diagnostics. ! !----------------------------------------------------------------------- ! ! D. Parks (NEC) 09/11/03 ! Restructuring of routine to support SX vector architecture. ! ! Possible improvements: ! ! 1. Look at vectorizing index calculations for maximum overlap. ! ! 2. Consider making innermost loop in flux computations the number ! of spectral intervals. Given that NS is fixed at 19, the trade-off ! will be stride one memory accesses of length 19 versus indirect ! addressing (list vector - gather/scatter) with potential vector ! lenghts of the number of day light points. Vectorizing on the number ! of spectral intervals seems worthwhile for low resolution models (T42), ! but might be inefficient with higher resolutions. ! ! 3. Move the linearization of daylight points (compression/expansion) out ! of radcswmx and into d_p_coupling. This would eliminate the cost of ! routines CmpDayNite and ExpDayNite. ! ! 4. Look at expliciting computing all streams in upward propagation of ! radiation. There would be additional floating point operations in ! exchange for the elimination of indirect addressing. ! !----------------------------------------------------------------------- use rad_solar_var, only: get_variability use cmparray_mod, only: CmpDayNite, ExpDayNite use quicksort, only: quick_sort use phys_control, only: phys_getopts use solar_data, only: sol_tsi, do_spctrl_scaling, ref_tsi use radconstants, only: frcsol, ph2o, pco2, po2 !-----------------------Constants for new band (640-700 nm)------------- real(r8) v_raytau_35 real(r8) v_raytau_64 real(r8) v_abo3_35 real(r8) v_abo3_64 parameter( & v_raytau_35 = 0.155208_r8, & v_raytau_64 = 0.0392_r8, & v_abo3_35 = 2.4058030e+01_r8, & v_abo3_64 = 2.210e+01_r8 & ) !-------------Parameters for accelerating max-random solution------------- ! ! The solution time scales like prod(j:1->N) (1 + n_j) where ! N = number of max-overlap regions (nmxrgn) ! n_j = number of unique cloud amounts in region j ! ! Therefore the solution cost can be reduced by decreasing n_j. ! cldmin reduces n_j by treating cloud amounts < cldmin as clear sky. ! cldeps reduces n_j by treating cloud amounts identical to log(1/cldeps) ! decimal places as identical ! ! areamin reduces the cost by dropping configurations that occupy ! a surface area < areamin of the model grid box. The surface area ! for a configuration C(j,k_j), where j is the region number and k_j is the ! index for a unique cloud amount (in descending order from biggest to ! smallest clouds) in region j, is ! ! A = prod(j:1->N) [C(j,k_j) - C(j,k_j+1)] ! ! where C(j,0) = 1.0 and C(j,n_j+1) = 0.0. ! ! nconfgmax reduces the cost and improves load balancing by setting an upper ! bound on the number of cloud configurations in the solution. If the number ! of configurations exceeds nconfgmax, the nconfgmax configurations with the ! largest area are retained, and the fluxes are normalized by the total area ! of these nconfgmax configurations. For the current max/random overlap ! assumption (see subroutine cldovrlap), 30 levels, and cloud-amount ! parameterization, the mean and RMS number of configurations are ! both roughly 5. nconfgmax has been set to the mean+2*RMS number, or 15. ! ! Minimum cloud amount (as a fraction of the grid-box area) to ! distinguish from clear sky ! real(r8) cldmin parameter (cldmin = 1.0e-80_r8) ! ! Minimimum horizontal area (as a fraction of the grid-box area) to retain ! for a unique cloud configuration in the max-random solution ! real(r8) areamin parameter (areamin = 0.01_r8) ! ! Decimal precision of cloud amount (0 -> preserve full resolution; ! 10^-n -> preserve n digits of cloud amount) ! real(r8) cldeps parameter (cldeps = 0.0_r8) ! ! Maximum number of configurations to include in solution ! integer nconfgmax parameter (nconfgmax = 15) !------------------------------Commons---------------------------------- ! ! Input arguments ! integer, intent(in) :: lchnk ! chunk identifier integer, intent(in) :: ncol ! number of atmospheric columns integer,intent(in) :: Nday ! Number of daylight columns integer,intent(in) :: Nnite ! Number of night columns integer,intent(in), dimension(pcols) :: IdxDay ! Indicies of daylight coumns integer,intent(in), dimension(pcols) :: IdxNite ! Indicies of night coumns real(r8), intent(in) :: E_pmid(pcols,pver) ! Level pressure real(r8), intent(in) :: E_pint(pcols,pverp) ! Interface pressure real(r8), intent(in) :: E_h2ommr(pcols,pver) ! Specific humidity (h2o mass mix ratio) real(r8), intent(in) :: E_o3mmr(pcols,pver) ! Ozone mass mixing ratio real(r8), intent(in) :: E_o2mmr(pcols) ! oxygen mass mixing ratio ! real(r8), intent(in) :: E_cld(pcols,pver) ! Fractional cloud cover real(r8), intent(in) :: E_cicewp(pcols,pver) ! in-cloud cloud ice water path real(r8), intent(in) :: E_cliqwp(pcols,pver) ! in-cloud cloud liquid water path real(r8), intent(in) :: E_rel(pcols,pver) ! Liquid effective drop size (microns) real(r8), intent(in) :: E_rei(pcols,pver) ! Ice effective drop size (microns) ! real(r8), intent(in) :: eccf ! Eccentricity factor (1./earth-sun dist^2) real(r8), intent(in) :: E_coszrs(pcols) ! Cosine solar zenith angle real(r8), intent(in) :: E_asdir(pcols) ! 0.2-0.7 micro-meter srfc alb: direct rad real(r8), intent(in) :: E_aldir(pcols) ! 0.7-5.0 micro-meter srfc alb: direct rad real(r8), intent(in) :: E_asdif(pcols) ! 0.2-0.7 micro-meter srfc alb: diffuse rad real(r8), intent(in) :: E_aldif(pcols) ! 0.7-5.0 micro-meter srfc alb: diffuse rad real(r8), intent(in) :: E_co2mmr(pcols) ! co2 column mean mmr ! ! Aerosol radiative property arrays ! real(r8),intent(in) :: E_aer_tau (pcols,0:pver,nswbands) ! aerosol extinction optical depth real(r8),intent(in) :: E_aer_tau_w (pcols,0:pver,nswbands) ! aerosol single scattering albedo * tau real(r8),intent(in) :: E_aer_tau_w_g(pcols,0:pver,nswbands) ! aerosol assymetry parameter * w * tau real(r8),intent(in) :: E_aer_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau ! ! IN/OUT arguments ! real(r8), intent(inout) :: pmxrgn(pcols,pverp) ! Maximum values of pressure for each ! ! maximally overlapped region. ! ! 0->pmxrgn(i,1) is range of pressure for ! ! 1st region,pmxrgn(i,1)->pmxrgn(i,2) for ! ! 2nd region, etc integer, intent(inout) :: nmxrgn(pcols) ! Number of maximally overlapped regions ! ! Output arguments ! real(r8), intent(out) :: solin(pcols) ! Incident solar flux real(r8), intent(out) :: qrs (pcols,pver) ! Solar heating rate real(r8), intent(out) :: qrsc(pcols,pver) ! Clearsky solar heating rate real(r8), intent(out) :: fsns(pcols) ! Surface absorbed solar flux real(r8), intent(out) :: fsnt(pcols) ! Total column absorbed solar flux real(r8), intent(out) :: fsntoa(pcols) ! Net solar flux at TOA real(r8), intent(out) :: fsutoa(pcols) ! Upward solar flux at TOA real(r8), intent(out) :: fsds(pcols) ! Flux shortwave downwelling surface ! real(r8), intent(out) :: fsnsc(pcols) ! Clear sky surface absorbed solar flux real(r8), intent(out) :: fsdsc(pcols) ! Clear sky surface downwelling solar flux real(r8), intent(out) :: fsntc(pcols) ! Clear sky total column absorbed solar flx real(r8), intent(out) :: fsdtoa(pcols) ! Downwelling solar flux at TOA real(r8), intent(out) :: fsntoac(pcols) ! Clear sky net solar flx at TOA real(r8), intent(out) :: sols(pcols) ! Direct solar rad on surface (< 0.7) real(r8), intent(out) :: soll(pcols) ! Direct solar rad on surface (>= 0.7) real(r8), intent(out) :: solsd(pcols) ! Diffuse solar rad on surface (< 0.7) real(r8), intent(out) :: solld(pcols) ! Diffuse solar rad on surface (>= 0.7) real(r8), intent(out) :: fsnirtoa(pcols) ! Near-IR flux absorbed at toa real(r8), intent(out) :: fsnrtoac(pcols) ! Clear sky near-IR flux absorbed at toa real(r8), intent(out) :: fsnrtoaq(pcols) ! Net near-IR flux at toa >= 0.7 microns real(r8), intent(out) :: fns(pcols,pverp) ! net flux at interfaces real(r8), intent(out) :: fcns(pcols,pverp) ! net clear-sky flux at interfaces ! !---------------------------Local variables----------------------------- ! ! Local and reordered copies of the intent(in) variables ! real(r8):: aer_tau (pcols,0:pver,nswbands) ! aerosol extinction optical depth real(r8):: aer_tau_w (pcols,0:pver,nswbands) ! aerosol single scattering albedo * tau real(r8):: aer_tau_w_g(pcols,0:pver,nswbands) ! aerosol assymetry parameter * w * tau real(r8):: aer_tau_w_f(pcols,0:pver,nswbands) ! aerosol forward scattered fraction * w * tau real(r8) :: pmid(pcols,pver) ! Level pressure real(r8) :: pint(pcols,pverp) ! Interface pressure real(r8) :: h2ommr(pcols,pver) ! Specific humidity (h2o mass mix ratio) real(r8) :: o3mmr(pcols,pver) ! Ozone mass mixing ratio ! real(r8) :: cld(pcols,pver) ! Fractional cloud cover real(r8) :: cicewp(pcols,pver) ! in-cloud cloud ice water path real(r8) :: cliqwp(pcols,pver) ! in-cloud cloud liquid water path real(r8) :: rel(pcols,pver) ! Liquid effective drop size (microns) real(r8) :: rei(pcols,pver) ! Ice effective drop size (microns) ! real(r8) :: coszrs(pcols) ! Cosine solar zenith angle real(r8) :: asdir(pcols) ! 0.2-0.7 micro-meter srfc alb: direct rad real(r8) :: aldir(pcols) ! 0.7-5.0 micro-meter srfc alb: direct rad real(r8) :: asdif(pcols) ! 0.2-0.7 micro-meter srfc alb: diffuse rad real(r8) :: aldif(pcols) ! 0.7-5.0 micro-meter srfc alb: diffuse rad real(r8) :: co2mmr(pcols) ! co2 column mean mmr real(r8) :: o2mmr(pcols) ! o2 column mean mmr real(r8) :: tot_irrad ! ! Max/random overlap variables ! real(r8) asort(pverp) ! 1 - cloud amounts to be sorted for max ovrlp. real(r8) atmp ! Temporary storage for sort when nxs = 2 real(r8) cld0 ! 1 - (cld amt) used to make wstr, cstr, nstr real(r8) totwgt(pcols) ! Total of xwgts = total fractional area of ! grid-box covered by cloud configurations ! included in solution to fluxes real(r8) wgtv(nconfgmax) ! Weights for fluxes ! 1st index is configuration number real(r8) wstr(pverp,pverp) ! area weighting factors for streams ! 1st index is for stream #, ! 2nd index is for region # real(r8) xexpt ! solar direct beam trans. for layer above real(r8) xrdnd ! diffuse reflectivity for layer above real(r8) xrupd ! diffuse reflectivity for layer below real(r8) xrups ! direct-beam reflectivity for layer below real(r8) xtdnt ! total trans for layers above real(r8) xwgt ! product of cloud amounts real(r8) yexpt ! solar direct beam trans. for layer above real(r8) yrdnd ! diffuse reflectivity for layer above real(r8) yrupd ! diffuse reflectivity for layer below real(r8) ytdnd ! dif-beam transmission for layers above real(r8) ytupd ! dif-beam transmission for layers below real(r8) zexpt ! solar direct beam trans. for layer above real(r8) zrdnd ! diffuse reflectivity for layer above real(r8) zrupd ! diffuse reflectivity for layer below real(r8) zrups ! direct-beam reflectivity for layer below real(r8) ztdnt ! total trans for layers above logical new_term ! Flag for configurations to include in fluxes logical region_found ! flag for identifying regions integer ccon(nconfgmax,0:pverp,pcols) ! flags for presence of clouds ! 1st index is for level # (including ! layer above top of model and at surface) ! 2nd index is for configuration # integer cstr(0:pverp,pverp) ! flags for presence of clouds ! 1st index is for level # (including ! layer above top of model and at surface) ! 2nd index is for stream # integer icond(nconfgmax,0:pverp,pcols) ! Indices for copying rad. properties from ! one identical downward cld config. ! to another in adding method (step 2) ! 1st index is for interface # (including ! layer above top of model and at surface) ! 2nd index is for configuration # range integer iconu(nconfgmax,0:pverp,pcols) ! Indices for copying rad. properties from ! one identical upward configuration ! to another in adding method (step 2) ! 1st index is for interface # (including ! layer above top of model and at surface) ! 2nd index is for configuration # range integer iconfig ! Counter for random-ovrlap configurations integer irgn ! Index for max-overlap regions integer is0 ! Lower end of stream index range integer is1 ! Upper end of stream index range integer isn ! Stream index integer istr(pverp+1) ! index for stream #s during flux calculation integer istrtd(0:nconfgmax+1,0:pverp,pcols) ! indices into icond ! 1st index is for interface # (including ! layer above top of model and at surface) ! 2nd index is for configuration # range integer istrtu(0:nconfgmax+1,0:pverp,pcols) ! indices into iconu ! 1st index is for interface # (including ! layer above top of model and at surface) ! 2nd index is for configuration # range integer j ! Configuration index integer jj ! Configuration index integer k1 ! Level index integer k2 ! Level index integer ksort(pverp) ! Level indices of cloud amounts to be sorted integer ktmp ! Temporary storage for sort when nxs = 2 integer kx1(0:pverp) ! Level index for top of max-overlap region integer kx2(0:pverp) ! Level index for bottom of max-overlap region integer l ! Index integer l0 ! Index integer mrgn ! Counter for nrgn integer mstr ! Counter for nstr integer n0 ! Number of configurations with ccon(:,k,:)==0 integer n1 ! Number of configurations with ccon(:,k,:)==1 integer nconfig(pcols) ! Number of random-ovrlap configurations integer nconfigm ! Value of config before testing for areamin, ! nconfgmax integer npasses ! number of passes over the indexing loop integer nrgn ! Number of max overlap regions at current ! longitude integer nstr(pverp) ! Number of unique cloud configurations ! ("streams") in a max-overlapped region ! 1st index is for region # integer nuniq ! # of unique cloud configurations integer nuniqd(0:pverp,pcols) ! # of unique cloud configurations: TOA ! to level k integer nuniqu(0:pverp,pcols) ! # of unique cloud configurations: surface ! to level k integer nxs ! Number of cloudy layers between k1 and k2 integer ptr0(nconfgmax) ! Indices of configurations with ccon(:,k,:)==0 integer ptr1(nconfgmax) ! Indices of configurations with ccon(:,k,:)==1 integer ptrc(nconfgmax) ! Pointer for configurations sorted by wgtv integer, dimension(1) :: min_idx ! required for return val of func minloc ! ! Other ! integer ns ! Spectral loop index integer i ! Longitude loop index integer k ! Level loop index integer km1 ! k - 1 integer kp1 ! k + 1 integer n ! Loop index for daylight integer indxsl ! Index for cloud particle properties integer ksz ! dust size bin index integer kaer ! aerosol group index ! ! A. Slingo's data for cloud particle radiative properties (from 'A GCM ! Parameterization for the Shortwave Properties of Water Clouds' JAS ! vol. 46 may 1989 pp 1419-1427) ! real(r8), parameter :: abarl(4) = (/ 2.817e-02_r8, 2.682e-02_r8,2.264e-02_r8,1.281e-02_r8/) real(r8), parameter :: bbarl(4) = (/ 1.305_r8 , 1.346_r8 ,1.454_r8 ,1.641_r8 /) real(r8), parameter :: cbarl(4) = (/-5.62e-08_r8 ,-6.94e-06_r8 ,4.64e-04_r8 ,0.201_r8 /) real(r8), parameter :: dbarl(4) = (/ 1.63e-07_r8 , 2.35e-05_r8 ,1.24e-03_r8 ,7.56e-03_r8 /) real(r8), parameter :: ebarl(4) = (/ 0.829_r8 , 0.794_r8 ,0.754_r8 ,0.826_r8 /) real(r8), parameter :: fbarl(4) = (/ 2.482e-03_r8, 4.226e-03_r8,6.560e-03_r8,4.353e-03_r8/) real(r8) :: abarli ! A coefficient for current spectral band real(r8) :: bbarli ! B coefficient for current spectral band real(r8) :: cbarli ! C coefficient for current spectral band real(r8) :: dbarli ! D coefficient for current spectral band real(r8) :: ebarli ! E coefficient for current spectral band real(r8) :: fbarli ! F coefficient for current spectral band ! ! Caution... A. Slingo recommends no less than 4.0 micro-meters nor ! greater than 20 micro-meters ! ! ice water coefficients (Ebert and Curry,1992, JGR, 97, 3831-3836) ! real(r8), parameter :: abari(4) = (/ 3.448e-03_r8, 3.448e-03_r8,3.448e-03_r8,3.448e-03_r8/) real(r8), parameter :: bbari(4) = (/ 2.431_r8 , 2.431_r8 ,2.431_r8 ,2.431_r8 /) real(r8), parameter :: cbari(4) = (/ 1.00e-05_r8 , 1.10e-04_r8 ,1.861e-02_r8,.46658_r8 /) real(r8), parameter :: dbari(4) = (/ 0.0_r8 , 1.405e-05_r8,8.328e-04_r8,2.05e-05_r8 /) real(r8), parameter :: ebari(4) = (/ 0.7661_r8 , 0.7730_r8 ,0.794_r8 ,0.9595_r8 /) real(r8), parameter :: fbari(4) = (/ 5.851e-04_r8, 5.665e-04_r8,7.267e-04_r8,1.076e-04_r8/) real(r8) :: abarii ! A coefficient for current spectral band real(r8) :: bbarii ! B coefficient for current spectral band real(r8) :: cbarii ! C coefficient for current spectral band real(r8) :: dbarii ! D coefficient for current spectral band real(r8) :: ebarii ! E coefficient for current spectral band real(r8) :: fbarii ! F coefficient for current spectral band ! ! UPDATE TO H2O NEAR-IR: Delta optimized for Hitran 2K and CKD 2.4 ! real(r8), parameter :: delta = 0.0014257179260883_r8 ! ! END UPDATE ! real(r8) :: albdir(pcols,nswbands) ! Current spc intrvl srf alb to direct rad real(r8) :: albdif(pcols,nswbands) ! Current spc intrvl srf alb to diffuse rad ! ! Next series depends on spectral interval ! real(r8) :: wgtint ! Weight for specific spectral interval ! ! weight for 0.64 - 0.7 microns appropriate to clear skies over oceans ! real(r8), parameter :: nirwgt(nswbands) = & (/ 0.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, 0.0_r8, & 0.0_r8, 0.0_r8, 0.0_r8, 0.320518_r8, 1.0_r8, 1.0_r8, & 1.0_r8, 1.0_r8, 1.0_r8, 1.0_r8, 1.0_r8, & 1.0_r8, 1.0_r8, 1.0_r8 /) ! ! UPDATE TO H2O NEAR-IR: Rayleigh scattering optimized for Hitran 2K & CKD 2.4 ! real(r8), parameter :: raytau(nswbands) = & (/ 4.020_r8, 2.180_r8, 1.700_r8, 1.450_r8, 1.250_r8, & 1.085_r8, 0.730_r8, v_raytau_35, v_raytau_64, & 0.02899756_r8, 0.01356763_r8, 0.00537341_r8, & 0.00228515_r8, 0.00105028_r8, 0.00046631_r8, & 0.00025734_r8, & .0001_r8, .0001_r8, .0001_r8/) ! ! END UPDATE ! ! ! Absorption coefficients ! ! ! UPDATE TO H2O NEAR-IR: abh2o optimized for Hitran 2K and CKD 2.4 ! real(r8), parameter :: abh2o(nswbands) = & (/ .000_r8, .000_r8, .000_r8, .000_r8, .000_r8, & .000_r8, .000_r8, .000_r8, .000_r8, & 0.00256608_r8, 0.06310504_r8, 0.42287445_r8, 2.45397941_r8, & 11.20070807_r8, 47.66091389_r8, 240.19010243_r8, & .000_r8, .000_r8, .000_r8/) ! ! END UPDATE ! real(r8), parameter :: abo3(nswbands) = & (/5.370e+04_r8, 13.080e+04_r8, 9.292e+04_r8, 4.530e+04_r8, 1.616e+04_r8, & 4.441e+03_r8, 1.775e+02_r8, v_abo3_35, v_abo3_64, .000_r8, & .000_r8, .000_r8 , .000_r8 , .000_r8 , .000_r8, & .000_r8, .000_r8 , .000_r8 , .000_r8 /) real(r8), parameter :: abco2(nswbands) = & (/ .000_r8, .000_r8, .000_r8, .000_r8, .000_r8, & .000_r8, .000_r8, .000_r8, .000_r8, .000_r8, & .000_r8, .000_r8, .000_r8, .000_r8, .000_r8, & .000_r8, .094_r8, .196_r8, 1.963_r8/) real(r8), parameter :: abo2(nswbands) = & (/ .000_r8, .000_r8, .000_r8, .000_r8, .000_r8, & .000_r8, .000_r8, .000_r8,1.11e-05_r8,6.69e-05_r8, & .000_r8, .000_r8, .000_r8, .000_r8, .000_r8, & .000_r8, .000_r8, .000_r8, .000_r8/) ! ! Diagnostic and accumulation arrays; note that fswup, and ! fswdn are not used in the computation,but are retained for future use. ! real(r8) solflx(pcols) ! Solar flux in current interval real(r8) totfld (pcols,0:pver) ! Spectrally summed flux divergence real(r8) totfldc(pcols,0:pver) ! Spectrally summed flux divergence (clearsky) real(r8) fswup(pcols,0:pverp) ! Spectrally summed up flux real(r8) fswdn(pcols,0:pverp) ! Spectrally summed down flux ! ! Cloud radiative property arrays ! real(r8) tauxcl(pcols,0:pver) ! water cloud extinction optical depth real(r8) tauxci(pcols,0:pver) ! ice cloud extinction optical depth real(r8) wcl(pcols,0:pver) ! liquid cloud single scattering albedo real(r8) gcl(pcols,0:pver) ! liquid cloud asymmetry parameter real(r8) fcl(pcols,0:pver) ! liquid cloud forward scattered fraction real(r8) wci(pcols,0:pver) ! ice cloud single scattering albedo real(r8) gci(pcols,0:pver) ! ice cloud asymmetry parameter real(r8) fci(pcols,0:pver) ! ice cloud forward scattered fraction ! ! Various arrays and other constants: ! real(r8) pflx(pcols,0:pverp) ! Interface press, including extra layer real(r8) zenfac(pcols) ! Square root of cos solar zenith angle real(r8) sqrco2(pcols) ! Square root of the co2 mass mixg ratio real(r8) tmp1 ! Temporary constant array real(r8) tmp2 ! Temporary constant array real(r8) pdel ! Pressure difference across layer real(r8) path ! Mass path of layer real(r8) ptop ! Lower interface pressure of extra layer real(r8) ptho2 ! Used to compute mass path of o2 real(r8) ptho3 ! Used to compute mass path of o3 real(r8) pthco2 ! Used to compute mass path of co2 real(r8) pthh2o ! Used to compute mass path of h2o real(r8) h2ostr ! Inverse sq. root h2o mass mixing ratio real(r8) wavmid(nswbands) ! Spectral interval middle wavelength real(r8) trayoslp ! Rayleigh optical depth/standard pressure real(r8) tmp1l ! Temporary constant array real(r8) tmp2l ! Temporary constant array real(r8) tmp3l ! Temporary constant array real(r8) tmp1i ! Temporary constant array real(r8) tmp2i ! Temporary constant array real(r8) tmp3i ! Temporary constant array real(r8) rdenom ! Multiple scattering term real(r8) rdirexp ! layer direct ref times exp transmission real(r8) tdnmexp ! total transmission - exp transmission real(r8) psf(nswbands) ! Frac of solar flux in spect interval ! ! Layer absorber amounts; note that 0 refers to the extra layer added ! above the top model layer ! real(r8) uh2o(pcols,0:pver) ! Layer absorber amount of h2o real(r8) uo3(pcols,0:pver) ! Layer absorber amount of o3 real(r8) uco2(pcols,0:pver) ! Layer absorber amount of co2 real(r8) uo2(pcols,0:pver) ! Layer absorber amount of o2 ! ! Total column absorber amounts: ! real(r8) uth2o(pcols) ! Total column absorber amount of h2o real(r8) uto3(pcols) ! Total column absorber amount of o3 real(r8) utco2(pcols) ! Total column absorber amount of co2 real(r8) uto2(pcols) ! Total column absorber amount of o2 ! ! These arrays are defined for pver model layers; 0 refers to the extra ! layer on top: ! real(r8) rdir(nswbands,pcols,0:pver) ! Layer reflectivity to direct rad real(r8) rdif(nswbands,pcols,0:pver) ! Layer reflectivity to diffuse rad real(r8) tdir(nswbands,pcols,0:pver) ! Layer transmission to direct rad real(r8) tdif(nswbands,pcols,0:pver) ! Layer transmission to diffuse rad real(r8) explay(nswbands,pcols,0:pver) ! Solar beam exp trans. for layer real(r8) rdirc(nswbands,pcols,0:pver) ! Clear Layer reflec. to direct rad real(r8) rdifc(nswbands,pcols,0:pver) ! Clear Layer reflec. to diffuse rad real(r8) tdirc(nswbands,pcols,0:pver) ! Clear Layer trans. to direct rad real(r8) tdifc(nswbands,pcols,0:pver) ! Clear Layer trans. to diffuse rad real(r8) explayc(nswbands,pcols,0:pver) ! Solar beam exp trans. clear layer real(r8) fus(pcols,pverp) ! Upward flux (added for CRM) real(r8) fds(pcols,pverp) ! Downward flux (added for CRM) real(r8) fusc(pcols,pverp) ! Upward clear-sky flux (added for CRM) real(r8) fdsc(pcols,pverp) ! Downward clear-sky flux (added for CRM) real(r8) flxdiv ! Flux divergence for layer ! ! Temporary arrays for either clear or cloudy values. ! real(r8), dimension(nswbands) :: Trdir real(r8), dimension(nswbands) :: Trdif real(r8), dimension(nswbands) :: Ttdir real(r8), dimension(nswbands) :: Ttdif real(r8), dimension(nswbands) :: Texplay !cdir vreg(Trdir) !cdir vreg(Trdif) !cdir vreg(Ttdir) !cdir vreg(Ttdif) !cdir vreg(Texplay) ! ! ! Radiative Properties: ! ! There are 1 classes of properties: ! (1. All-sky bulk properties ! (2. Clear-sky properties ! ! The first set of properties are generated during step 2 of the solution. ! ! These arrays are defined at model interfaces; in 1st index (for level #), ! 0 is the top of the extra layer above the model top, and ! pverp is the earth surface. 2nd index is for cloud configuration ! defined over a whole column. ! real(r8) exptdn(nswbands,0:pverp,nconfgmax,pcols) ! Sol. beam trans from layers above real(r8) rdndif(nswbands,0:pverp,nconfgmax,pcols) ! Ref to dif rad for layers above real(r8) rupdif(nswbands,0:pverp,nconfgmax,pcols) ! Ref to dif rad for layers below real(r8) rupdir(nswbands,0:pverp,nconfgmax,pcols) ! Ref to dir rad for layers below real(r8) tdntot(nswbands,0:pverp,nconfgmax,pcols) ! Total trans for layers above ! ! Bulk properties used during the clear-sky calculation. ! real(r8) exptdnc(pcols,0:pverp) ! clr: Sol. beam trans from layers above real(r8) rdndifc(pcols,0:pverp) ! clr: Ref to dif rad for layers above real(r8) rupdifc(pcols,0:pverp) ! clr: Ref to dif rad for layers below real(r8) rupdirc(pcols,0:pverp) ! clr: Ref to dir rad for layers below real(r8) tdntotc(pcols,0:pverp) ! clr: Total trans for layers above real(r8) fluxup(nswbands,0:pverp,pcols) ! Up flux at model interface real(r8) fluxdn(nswbands,0:pverp,pcols) ! Down flux at model interface real(r8) wexptdn(nswbands,pcols) ! Direct solar beam trans. to surface ! ! Scalars used in vectorization ! integer :: kk ! ! Arrays used in vectorization ! real(r8) v_wgtv(nconfgmax,pcols) ! Weights for fluxes real(r8) :: rdiff, ro, rn rdiff(ro,rn) = abs((ro-rn)/merge(ro,1.0_r8,ro /= 0.0_r8)) ! solar variability factor real(r8) :: sfac(nswbands) character(len=16) :: microp_scheme ! microphysics scheme !----------------------------------------------------------------------- ! START OF CALCULATION !----------------------------------------------------------------------- call phys_getopts(microp_scheme_out=microp_scheme) ! ! Initialize output fields: ! fsds(1:ncol) = 0.0_r8 fsnirtoa(1:ncol) = 0.0_r8 fsnrtoac(1:ncol) = 0.0_r8 fsnrtoaq(1:ncol) = 0.0_r8 fsns(1:ncol) = 0.0_r8 fsnsc(1:ncol) = 0.0_r8 fsdsc(1:ncol) = 0.0_r8 fsnt(1:ncol) = 0.0_r8 fsntc(1:ncol) = 0.0_r8 fsntoa(1:ncol) = 0.0_r8 fsdtoa(1:ncol) = 0.0_r8 fsutoa(1:ncol) = 0.0_r8 fsntoac(1:ncol) = 0.0_r8 solin(1:ncol) = 0.0_r8 sols(1:ncol) = 0.0_r8 soll(1:ncol) = 0.0_r8 solsd(1:ncol) = 0.0_r8 solld(1:ncol) = 0.0_r8 qrs (1:ncol,1:pver) = 0.0_r8 qrsc(1:ncol,1:pver) = 0.0_r8 fns(1:ncol,1:pverp) = 0.0_r8 fcns(1:ncol,1:pverp) = 0.0_r8 if (single_column.and.scm_crm_mode) then fus(1:ncol,1:pverp) = 0.0_r8 fds(1:ncol,1:pverp) = 0.0_r8 fusc(:ncol,:pverp) = 0.0_r8 fdsc(:ncol,:pverp) = 0.0_r8 endif ! ! If night everywhere, return: ! if ( Nday == 0 ) then return endif ! ! Rearrange input arrays ! call CmpDayNite(E_pmid, pmid, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_pint, pint, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call CmpDayNite(E_h2ommr, h2ommr, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_o3mmr, o3mmr, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_cld, cld, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_cicewp, cicewp, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_cliqwp, cliqwp, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_rel, rel, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_rei, rei, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call CmpDayNite(E_coszrs, coszrs, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(E_asdir, asdir, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(E_aldir, aldir, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(E_asdif, asdif, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(E_aldif, aldif, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(E_co2mmr, co2mmr, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(E_o2mmr, o2mmr, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(pmxrgn, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call CmpDayNite(nmxrgn, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call CmpDayNite(E_aer_tau, aer_tau, Nday, IdxDay, Nnite, IdxNite, 1,pcols, 0,pver, 1,nswbands) call CmpDayNite(E_aer_tau_w, aer_tau_w, Nday, IdxDay, Nnite, IdxNite, 1,pcols, 0,pver, 1,nswbands) call CmpDayNite(E_aer_tau_w_g, aer_tau_w_g, Nday, IdxDay, Nnite, IdxNite, 1,pcols, 0,pver, 1,nswbands) call CmpDayNite(E_aer_tau_w_f, aer_tau_w_f, Nday, IdxDay, Nnite, IdxNite, 1,pcols, 0,pver, 1,nswbands) if (scm_crm_mode) then ! overwrite albedos for CRM if(have_asdir) asdir = asdirobs(1) if(have_asdif) asdif = asdifobs(1) if(have_aldir) aldir = aldirobs(1) if(have_aldif) aldif = aldifobs(1) endif ! ! Perform other initializations ! tmp1 = 0.5_r8/(gravit*sslp) tmp2 = delta/gravit do i = 1, Nday sqrco2(i) = sqrt(co2mmr(i)) end do if ( do_spctrl_scaling ) then call get_variability(sfac) tot_irrad = ref_tsi else tot_irrad = sol_tsi endif do k=1,pverp do i=1,Nday pflx(i,k) = pint(i,k) end do end do do i=1,Nday ! ! Define solar incident radiation and interface pressures: ! solin(i) = tot_irrad*1.e3_r8*eccf*coszrs(i) pflx(i,0) = 0._r8 ! ! Compute optical paths: ! ptop = pflx(i,1) ptho2 = o2mmr(i) * ptop / gravit ptho3 = o3mmr(i,1) * ptop / gravit pthco2 = sqrco2(i) * (ptop / gravit) h2ostr = sqrt( 1._r8 / h2ommr(i,1) ) zenfac(i) = sqrt(coszrs(i)) pthh2o = ptop**2*tmp1 + (ptop*rga)* & (h2ostr*zenfac(i)*delta) uh2o(i,0) = h2ommr(i,1)*pthh2o uco2(i,0) = zenfac(i)*pthco2 uo2 (i,0) = zenfac(i)*ptho2 uo3 (i,0) = ptho3 ! ! End do i=1,Nday ! end do do k=1,pver !cdir nodep do i=1,Nday pdel = pflx(i,k+1) - pflx(i,k) path = pdel / gravit ptho2 = o2mmr(i) * path ptho3 = o3mmr(i,k) * path pthco2 = sqrco2(i) * path h2ostr = sqrt(1.0_r8/h2ommr(i,k)) pthh2o = (pflx(i,k+1)**2 - pflx(i,k)**2)*tmp1 + pdel*h2ostr*zenfac(i)*tmp2 uh2o(i,k) = h2ommr(i,k)*pthh2o uco2(i,k) = zenfac(i)*pthco2 uo2 (i,k) = zenfac(i)*ptho2 uo3 (i,k) = ptho3 ! ! End do i=1,Nday ! end do ! ! End k=1,pver ! end do ! ! Compute column absorber amounts for the clear sky computation: ! do i=1,Nday uth2o(i) = 0.0_r8 uto3(i) = 0.0_r8 utco2(i) = 0.0_r8 uto2(i) = 0.0_r8 !cdir expand=pver do k=1,pver uth2o(i) = uth2o(i) + uh2o(i,k) uto3(i) = uto3(i) + uo3(i,k) utco2(i) = utco2(i) + uco2(i,k) uto2(i) = uto2(i) + uo2(i,k) ! ! End k=1,pver ! end do ! ! End do i=1,Nday ! end do ! ! Set cloud properties for top (0) layer; so long as tauxcl is zero, ! there is no cloud above top of model; the other cloud properties ! are arbitrary: ! do i=1,Nday tauxcl(i,0) = 0._r8 wcl(i,0) = 0.999999_r8 gcl(i,0) = 0.85_r8 fcl(i,0) = 0.725_r8 tauxci(i,0) = 0._r8 wci(i,0) = 0.999999_r8 gci(i,0) = 0.85_r8 fci(i,0) = 0.725_r8 ! ! End do i=1,Nday ! end do ! ! Begin spectral loop ! do ns=1,nswbands ! ! Set index for cloud particle properties based on the wavelength, ! according to A. Slingo (1989) equations 1-3: ! Use index 1 (0.25 to 0.69 micrometers) for visible ! Use index 2 (0.69 - 1.19 micrometers) for near-infrared ! Use index 3 (1.19 to 2.38 micrometers) for near-infrared ! Use index 4 (2.38 to 4.00 micrometers) for near-infrared ! ! Note that the minimum wavelength is encoded (with .001, .002, .003) ! in order to specify the index appropriate for the near-infrared ! cloud absorption properties ! if(wavmax(ns) <= 0.7_r8) then indxsl = 1 else if(wavmin(ns) == 0.700_r8) then indxsl = 2 else if(wavmin(ns) == 0.701_r8) then indxsl = 3 else if(wavmin(ns) == 0.702_r8 .or. wavmin(ns) > 2.38_r8) then indxsl = 4 end if ! ! Set cloud extinction optical depth, single scatter albedo, ! asymmetry parameter, and forward scattered fraction: ! abarli = abarl(indxsl) bbarli = bbarl(indxsl) cbarli = cbarl(indxsl) dbarli = dbarl(indxsl) ebarli = ebarl(indxsl) fbarli = fbarl(indxsl) ! abarii = abari(indxsl) bbarii = bbari(indxsl) cbarii = cbari(indxsl) dbarii = dbari(indxsl) ebarii = ebari(indxsl) fbarii = fbari(indxsl) ! ! adjustfraction within spectral interval to allow for the possibility of ! sub-divisions within a particular interval: ! psf(ns) = 1.0_r8 if(ph2o(ns)/=0._r8) psf(ns) = psf(ns)*ph2o(ns) if(pco2(ns)/=0._r8) psf(ns) = psf(ns)*pco2(ns) if(po2 (ns)/=0._r8) psf(ns) = psf(ns)*po2 (ns) do k=1,pver do i=1,Nday ! liquid ! note that optical properties for liquid valid only ! in range of 4.2 > rel > 16 micron (Slingo 89) if ( microp_scheme .eq. 'MG' ) then tmp2l = 1._r8 - cbarli - dbarli*min(max(4.2_r8,rel(i,k)),16._r8) tmp3l = fbarli*min(max(4.2_r8,rel(i,k)),16._r8) else tmp2l = 1._r8 - cbarli - dbarli*rel(i,k) tmp3l = fbarli*rel(i,k) endif ! ice ! note that optical properties for ice valid only ! in range of 13 > rei > 130 micron (Ebert and Curry 92) if ( microp_scheme .eq. 'MG' ) then tmp2i = 1._r8 - cbarii - dbarii*min(max(13._r8,rei(i,k)),130._r8) tmp3i = fbarii*min(max(13._r8,rei(i,k)),130._r8) else tmp2i = 1._r8 - cbarii - dbarii*rei(i,k) tmp3i = fbarii*rei(i,k) endif if (cld(i,k) >= cldmin .and. cld(i,k) >= cldeps) then ! liquid if ( microp_scheme .eq. 'MG' ) then tmp1l = abarli + bbarli/min(max(4.2_r8,rel(i,k)),16._r8) else tmp1l = abarli + bbarli/rel(i,k) endif ! ice if ( microp_scheme .eq. 'MG' ) then tmp1i = abarii + bbarii/max(13._r8,min(rei(i,k),130._r8)) else tmp1i = abarii + bbarii/rei(i,k) endif tauxcl(i,k) = cliqwp(i,k)*tmp1l tauxci(i,k) = cicewp(i,k)*tmp1i else tauxcl(i,k) = 0.0_r8 tauxci(i,k) = 0.0_r8 endif ! Do not let single scatter albedo be 1. Delta-eddington solution ! for non-conservative case has different analytic form from solution ! for conservative case, and raddedmx is written for non-conservative case. wcl(i,k) = min(tmp2l,.999999_r8) gcl(i,k) = ebarli + tmp3l fcl(i,k) = gcl(i,k)*gcl(i,k) wci(i,k) = min(tmp2i,.999999_r8) gci(i,k) = ebarii + tmp3i fci(i,k) = gci(i,k)*gci(i,k) end do ! End do i=1,Nday end do ! End do k=1,pver ! ! Set reflectivities for surface based on mid-point wavelength ! wavmid(ns) = 0.5_r8*(wavmin(ns) + wavmax(ns)) ! ! Wavelength less than 0.7 micro-meter ! if (wavmid(ns) < 0.7_r8 ) then do i=1,Nday albdir(i,ns) = asdir(i) albdif(i,ns) = asdif(i) end do ! ! Wavelength greater than 0.7 micro-meter ! else do i=1,Nday albdir(i,ns) = aldir(i) albdif(i,ns) = aldif(i) end do end if trayoslp = raytau(ns)/sslp ! ! Layer input properties now completely specified; compute the ! delta-Eddington solution reflectivities and transmissivities ! for each layer ! call raddedmx(coszrs ,Nday , & abh2o(ns),abo3(ns) ,abco2(ns),abo2(ns) , & uh2o ,uo3 ,uco2 ,uo2 , & trayoslp ,pflx ,ns , & tauxcl ,wcl ,gcl ,fcl , & tauxci ,wci ,gci ,fci , & aer_tau(:,:,ns) ,aer_tau_w(:,:,ns) ,aer_tau_w_g(:,:,ns) ,aer_tau_w_f(:,:,ns) , & rdir ,rdif ,tdir ,tdif ,explay , & rdirc ,rdifc ,tdirc ,tdifc ,explayc ) ! ! End spectral loop ! end do ! !---------------------------------------------------------------------- ! ! Solution for max/random cloud overlap. ! ! Steps: ! (1. delta-Eddington solution for each layer (called above) ! ! (2. The adding method is used to ! compute the reflectivity and transmissivity to direct and diffuse ! radiation from the top and bottom of the atmosphere for each ! cloud configuration. This calculation is based upon the ! max-random overlap assumption. ! ! (3. to solve for the fluxes, combine the ! bulk properties of the atmosphere above/below the region. ! ! Index calculations for steps 2-3 are performed outside spectral ! loop to avoid redundant calculations. Index calculations (with ! application of areamin & nconfgmax conditions) are performed ! first to identify the minimum subset of terms for the configurations ! satisfying the areamin & nconfgmax conditions. This minimum set is ! used to identify the corresponding minimum subset of terms in ! steps 2 and 3. ! do iconfig = 1, nconfgmax ccon(iconfig,0,1:Nday) = 0 ccon(iconfig,pverp,1:Nday) = 0 icond(iconfig,0,1:Nday) = iconfig iconu(iconfig,pverp,1:Nday) = iconfig end do ! ! Construction of nuniqu/d, istrtu/d, iconu/d using binary tree ! nuniqd(0,1:Nday) = 1 nuniqu(pverp,1:Nday) = 1 istrtd(1,0,1:Nday) = 1 istrtu(1,pverp,1:Nday) = 1 !CSD$ PARALLEL DO PRIVATE( npasses, kx2, mrgn, region_found, k1, k2, kx1, nxs, ksort, asort ) & !CSD$ PRIVATE ( ktmp, atmp, cstr, mstr, nstr, cld0, wstr, nrgn, nconfigm, istr, new_term, xwgt ) & !CSD$ PRIVATE ( j, ptrc, wgtv, km1, nuniq, is0, is1, n0, n1, ptr0, ptr1, kp1, i, irgn ) & !CSD$ PRIVATE ( k, l, iconfig, l0, isn ) do i=1,Nday !---------------------------------------------------------------------- ! INDEX CALCULATIONS FOR MAX OVERLAP ! ! The column is divided into sets of adjacent layers, called regions, ! in which the clouds are maximally overlapped. The clouds are ! randomly overlapped between different regions. The number of ! regions in a column is set by nmxrgn, and the range of pressures ! included in each region is set by pmxrgn. ! ! The following calculations determine the number of unique cloud ! configurations (assuming maximum overlap), called "streams", ! within each region. Each stream consists of a vector of binary ! clouds (either 0 or 100% cloud cover). Over the depth of the region, ! each stream requires a separate calculation of radiative properties. These ! properties are generated using the adding method from ! the radiative properties for each layer calculated by raddedmx. ! ! The upward and downward-propagating streams are treated ! separately. ! ! We will refer to a particular configuration of binary clouds ! within a single max-overlapped region as a "stream". We will ! refer to a particular arrangement of binary clouds over the entire column ! as a "configuration". ! ! This section of the code generates the following information: ! (1. nrgn : the true number of max-overlap regions (need not = nmxrgn) ! (2. nstr : the number of streams in a region (>=1) ! (3. cstr : flags for presence of clouds at each layer in each stream ! (4. wstr : the fractional horizontal area of a grid box covered ! by each stream ! (5. kx1,2 : level indices for top/bottom of each region ! ! The max-overlap calculation proceeds in 3 stages: ! (1. compute layer radiative properties in raddedmx. ! (2. combine these properties between layers ! (3. combine properties to compute fluxes at each interface. ! ! Most of the indexing information calculated here is used in steps 2-3 ! after the call to raddedmx. ! ! Initialize indices for layers to be max-overlapped ! ! Loop to handle fix in totwgt=0. For original overlap config ! from npasses = 0. ! npasses = 0 do !cdir novector do irgn = 0, nmxrgn(i) kx2(irgn) = 0 end do mrgn = 0 ! ! Outermost loop over regions (sets of adjacent layers) to be max overlapped ! do irgn = 1, nmxrgn(i) ! ! Calculate min/max layer indices inside region. ! region_found = .false. if (kx2(irgn-1) < pver) then k1 = kx2(irgn-1)+1 kx1(irgn) = k1 kx2(irgn) = k1-1 !cdir novector do k2 = pver, k1, -1 if (pmid(i,k2) <= pmxrgn(i,irgn)) then kx2(irgn) = k2 mrgn = mrgn+1 region_found = .true. exit end if end do else exit endif if (region_found) then ! ! Sort cloud areas and corresponding level indices. ! nxs = 0 if (cldeps > 0) then do k = k1,k2 if (cld(i,k) >= cldmin .and. cld(i,k) >= cldeps) then nxs = nxs+1 ksort(nxs) = k ! ! We need indices for clouds in order of largest to smallest, so ! sort 1-cld in ascending order ! asort(nxs) = 1.0_r8-(floor(cld(i,k)/cldeps)*cldeps) end if end do else !cdir novector do k = k1,k2 if (cld(i,k) >= cldmin) then nxs = nxs+1 ksort(nxs) = k ! ! We need indices for clouds in order of largest to smallest, so ! sort 1-cld in ascending order ! asort(nxs) = 1.0_r8-cld(i,k) end if end do endif ! ! If nxs eq 1, no need to sort. ! If nxs eq 2, sort by swapping if necessary ! If nxs ge 3, sort using local sort routine ! if (nxs == 2) then if (asort(2) < asort(1)) then ktmp = ksort(1) ksort(1) = ksort(2) ksort(2) = ktmp atmp = asort(1) asort(1) = asort(2) asort(2) = atmp endif else if (nxs >= 3) then call quick_sort(asort(1:nxs),ksort(1:nxs)) endif ! ! Construct wstr, cstr, nstr for this region ! !cdir novector cstr(k1:k2,1:nxs+1) = 0 mstr = 1 cld0 = 0.0_r8 do l = 1, nxs if (asort(l) /= cld0) then wstr(mstr,mrgn) = asort(l) - cld0 cld0 = asort(l) mstr = mstr + 1 endif !cdir novector cstr(ksort(l),mstr:nxs+1) = 1 end do nstr(mrgn) = mstr wstr(mstr,mrgn) = 1.0_r8 - cld0 ! ! End test of region_found = true ! endif ! ! End loop over regions irgn for max-overlap ! end do nrgn = mrgn ! ! Finish construction of cstr for additional top layer ! !cdir novector cstr(0,1:nstr(1)) = 0 ! ! INDEX COMPUTATIONS FOR STEP 2-3 ! This section of the code generates the following information: ! (1. totwgt step 3 total frac. area of configurations satisfying ! areamin & nconfgmax criteria ! (2. wgtv step 3 frac. area of configurations ! (3. ccon step 2 binary flag for clouds in each configuration ! (4. nconfig steps 2-3 number of configurations ! (5. nuniqu/d step 2 Number of unique cloud configurations for ! up/downwelling rad. between surface/TOA ! and level k ! (6. istrtu/d step 2 Indices into iconu/d ! (7. iconu/d step 2 Cloud configurations which are identical ! for up/downwelling rad. between surface/TOA ! and level k ! ! Number of configurations (all permutations of streams in each region) ! nconfigm = product(nstr(1: nrgn)) ! ! Construction of totwgt, wgtv, ccon, nconfig ! !cdir novector istr(1: nrgn) = 1 nconfig(i) = 0 totwgt(i) = 0.0_r8 new_term = .true. do iconfig = 1, nconfigm xwgt = 1.0_r8 !cdir novector do mrgn = 1, nrgn xwgt = xwgt * wstr(istr(mrgn),mrgn) end do if (xwgt >= areamin) then nconfig(i) = nconfig(i) + 1 if (nconfig(i) <= nconfgmax) then j = nconfig(i) ptrc(nconfig(i)) = nconfig(i) else nconfig(i) = nconfgmax if (new_term) then min_idx = minloc(wgtv) j = min_idx(1) endif if (wgtv(j) < xwgt) then totwgt(i) = totwgt(i) - wgtv(j) new_term = .true. else new_term = .false. endif endif if (new_term) then wgtv(j) = xwgt totwgt(i) = totwgt(i) + xwgt !cdir novector do mrgn = 1, nrgn !cdir novector ccon(j,kx1(mrgn):kx2(mrgn),i) = cstr(kx1(mrgn):kx2(mrgn),istr(mrgn)) end do endif endif mrgn = nrgn istr(mrgn) = istr(mrgn) + 1 do while (istr(mrgn) > nstr(mrgn) .and. mrgn > 1) istr(mrgn) = 1 mrgn = mrgn - 1 istr(mrgn) = istr(mrgn) + 1 end do ! ! End do iconfig = 1, nconfigm ! end do ! ! If totwgt(i) = 0 implement maximum overlap and make another pass ! if totwgt(i) = 0 on this second pass then terminate. ! if (totwgt(i) > 0._r8) then exit else npasses = npasses + 1 if (npasses >= 2 ) then write(iulog,*)'RADCSWMX: Maximum overlap of column ','failed' call endrun('RADCSWMX') endif nmxrgn(i)=1 pmxrgn(i,1)=1.0e30_r8 end if ! ! End npasses = 0, do ! end do ! ! Finish construction of ccon ! istrtd(2,0,i) = nconfig(i)+1 istrtu(2,pverp,i) = nconfig(i)+1 do k = 1, pverp km1 = k-1 nuniq = 0 istrtd(1,k,i) = 1 !cdir novector do l0 = 1, nuniqd(km1,i) is0 = istrtd(l0,km1,i) is1 = istrtd(l0+1,km1,i)-1 n0 = 0 n1 = 0 !cdir novector do isn = is0, is1 j = icond(isn,km1,i) if (ccon(j,k,i) == 0) then n0 = n0 + 1 ptr0(n0) = j else ! if (ccon(j,k,i) == 1) then n1 = n1 + 1 ptr1(n1) = j endif end do if (n0 > 0) then nuniq = nuniq + 1 istrtd(nuniq+1,k,i) = istrtd(nuniq,k,i)+n0 !cdir novector icond(istrtd(nuniq,k,i):istrtd(nuniq+1,k,i)-1,k,i) = ptr0(1:n0) endif if (n1 > 0) then nuniq = nuniq + 1 istrtd(nuniq+1,k,i) = istrtd(nuniq,k,i)+n1 !cdir novector icond(istrtd(nuniq,k,i):istrtd(nuniq+1,k,i)-1,k,i) = ptr1(1:n1) endif end do nuniqd(k,i) = nuniq end do ! ! Find 'transition point' in downward configurations where the number ! of 'configurations' changes from 1. This is used to optimize the ! construction of the upward configurations. ! Note: k1 == transition point ! do k = pverp,0,-1 if ( nuniqd(k,i) == 1) then k1 = k exit end if end do do k = pver, k1+1,-1 kp1 = k+1 nuniq = 0 istrtu(1,k,i) = 1 !cdir novector do l0 = 1, nuniqu(kp1,i) is0 = istrtu(l0,kp1,i) is1 = istrtu(l0+1,kp1,i)-1 n0 = 0 n1 = 0 !cdir novector do isn = is0, is1 j = iconu(isn,kp1,i) if (ccon(j,k,i) == 0) then n0 = n0 + 1 ptr0(n0) = j else ! if (ccon(j,k,i) == 1) then n1 = n1 + 1 ptr1(n1) = j endif end do if (n0 > 0) then nuniq = nuniq + 1 istrtu(nuniq+1,k,i) = istrtu(nuniq,k,i)+n0 !cdir novector iconu(istrtu(nuniq,k,i):istrtu(nuniq+1,k,i)-1,k,i) = ptr0(1:n0) endif if (n1 > 0) then nuniq = nuniq + 1 istrtu(nuniq+1,k,i) = istrtu(nuniq,k,i)+n1 !cdir novector iconu(istrtu(nuniq,k,i):istrtu(nuniq+1,k,i)-1,k,i) = ptr1(1:n1) endif end do nuniqu(k,i) = nuniq end do ! ! Copy identical configurations from 'transition point' to surface. ! k1 = min(pverp-1,k1) nuniq = nuniqu(k1+1,i) do k = k1,0,-1 nuniqu(k,i) = nuniq !cdir novector iconu(1:nuniq,k,i) = iconu(1:nuniq,k1+1,i) !cdir novector istrtu(1:nuniq+1,k,i) = istrtu(1:nuniq+1,k1+1,i) end do !cdir novector v_wgtv(1:nconfig(i),i) = wgtv(1:nconfig(i)) ! !---------------------------------------------------------------------- ! End of index calculations !---------------------------------------------------------------------- ! ! End do i=1,Nday ! end do !CSD$ END PARALLEL !---------------------------------------------------------------------- ! Start of flux calculations !---------------------------------------------------------------------- ! ! Initialize spectrally integrated totals: ! totfld (1:Nday,0:pver) = 0.0_r8 totfldc(1:Nday,0:pver) = 0.0_r8 fswup (1:Nday,0:pver) = 0.0_r8 fswdn (1:Nday,0:pver) = 0.0_r8 fswup (1:Nday,pverp) = 0.0_r8 fswdn (1:Nday,pverp) = 0.0_r8 ! ! Start spectral interval ! !old do ns = 1,nswbands !old wgtint = nirwgt(ns) do i=1,Nday !---------------------------------------------------------------------- ! STEP 2 ! ! ! Apply adding method to solve for radiative properties ! ! first initialize the bulk properties at toa ! ! nswbands, 0:pverp, nconfgmax, pcols rdndif(:,0,1:nconfig(i),i) = 0.0_r8 exptdn(:,0,1:nconfig(i),i) = 1.0_r8 tdntot(:,0,1:nconfig(i),i) = 1.0_r8 ! ! End do i=1,Nday ! end do ! ! solve for properties involving downward propagation of radiation. ! the bulk properties are: ! ! (1. exptdn sol. beam dwn. trans from layers above ! (2. rdndif ref to dif rad for layers above ! (3. tdntot total trans for layers above ! !CSD$ PARALLEL DO PRIVATE( km1, is0, is1, j, jj, Ttdif, Trdif, Trdir, Ttdir, Texplay ) & !CSD$ PRIVATE( xexpt, xrdnd, tdnmexp, ytdnd, yrdnd, rdenom, rdirexp, zexpt, zrdnd, ztdnt ) & !CSD$ PRIVATE( i, k, l0, ns, isn ) do i = 1, Nday do k = 1, pverp km1 = k - 1 !cdir nodep do l0 = 1, nuniqd(km1,i) is0 = istrtd(l0,km1,i) is1 = istrtd(l0+1,km1,i)-1 j = icond(is0,km1,i) ! ! If cloud in layer, use cloudy layer radiative properties (ccon == 1) ! If clear layer, use clear-sky layer radiative properties (ccon /= 1) ! if ( ccon(j,km1,i) == 1 ) then Ttdif(:) = tdif(:,i,km1) Trdif(:) = rdif(:,i,km1) Trdir(:) = rdir(:,i,km1) Ttdir(:) = tdir(:,i,km1) Texplay(:) = explay(:,i,km1) else Ttdif(:) = tdifc(:,i,km1) Trdif(:) = rdifc(:,i,km1) Trdir(:) = rdirc(:,i,km1) Ttdir(:) = tdirc(:,i,km1) Texplay(:) = explayc(:,i,km1) end if do ns = 1, nswbands xexpt = exptdn(ns,km1,j,i) xrdnd = rdndif(ns,km1,j,i) tdnmexp = tdntot(ns,km1,j,i) - xexpt ytdnd = Ttdif(ns) yrdnd = Trdif(ns) rdenom = 1._r8/(1._r8-yrdnd*xrdnd) rdirexp = Trdir(ns)*xexpt zexpt = xexpt * Texplay(ns) zrdnd = yrdnd + xrdnd*(ytdnd**2)*rdenom ztdnt = xexpt*Ttdir(ns) + ytdnd* & (tdnmexp + xrdnd*rdirexp)*rdenom exptdn(ns,k,j,i) = zexpt rdndif(ns,k,j,i) = zrdnd tdntot(ns,k,j,i) = ztdnt end do ! ns = 1, nswbands ! ! If 2 or more configurations share identical properties at a given level k, ! the properties (at level k) are computed once and copied to ! all the configurations for efficiency. ! do isn = is0+1, is1 jj = icond(isn,km1,i) exptdn(:,k,jj,i) = exptdn(:,k,j,i) rdndif(:,k,jj,i) = rdndif(:,k,j,i) tdntot(:,k,jj,i) = tdntot(:,k,j,i) end do ! ! end do l0 = 1, nuniqd(k,i) ! end do ! ! end do k = 1, pverp ! end do ! ! end do i = 1, Nday ! end do !CSD$ END PARALLEL ! ! Solve for properties involving upward propagation of radiation. ! The bulk properties are: ! ! (1. rupdif Ref to dif rad for layers below ! (2. rupdir Ref to dir rad for layers below ! ! Specify surface boundary conditions (surface albedos) ! ! nswbands, 0:pverp, nconfgmax, pcols rupdir = 0._r8 rupdif = 0._r8 do i = 1, Nday do ns = 1, nswbands rupdir(ns,pverp,1:nconfig(i),i) = albdir(i,ns) rupdif(ns,pverp,1:nconfig(i),i) = albdif(i,ns) end do end do do i = 1, Nday do k = pver, 0, -1 do l0 = 1, nuniqu(k,i) is0 = istrtu(l0,k,i) is1 = istrtu(l0+1,k,i)-1 j = iconu(is0,k,i) ! ! If cloud in layer, use cloudy layer radiative properties (ccon == 1) ! If clear layer, use clear-sky layer radiative properties (ccon /= 1) ! if ( ccon(j,k,i) == 1 ) then Ttdif(:) = tdif(:,i,k) Trdif(:) = rdif(:,i,k) Trdir(:) = rdir(:,i,k) Ttdir(:) = tdir(:,i,k) Texplay(:) = explay(:,i,k) else Ttdif(:) = tdifc(:,i,k) Trdif(:) = rdifc(:,i,k) Trdir(:) = rdirc(:,i,k) Ttdir(:) = tdirc(:,i,k) Texplay(:) = explayc(:,i,k) end if do ns = 1, nswbands xrupd = rupdif(ns,k+1,j,i) xrups = rupdir(ns,k+1,j,i) ! ! If cloud in layer, use cloudy layer radiative properties (ccon == 1) ! If clear layer, use clear-sky layer radiative properties (ccon /= 1) ! yexpt = Texplay(ns) yrupd = Trdif(ns) ytupd = Ttdif(ns) rdenom = 1._r8/( 1._r8 - yrupd*xrupd) tdnmexp = (Ttdir(ns)-yexpt) rdirexp = xrups*yexpt zrupd = yrupd + xrupd*(ytupd**2)*rdenom zrups = Trdir(ns) + ytupd*(rdirexp + xrupd*tdnmexp)*rdenom rupdif(ns,k,j,i) = zrupd rupdir(ns,k,j,i) = zrups end do ! ns = 1, nswbands ! ! If 2 or more configurations share identical properties at a given level k, ! the properties (at level k) are computed once and copied to ! all the configurations for efficiency. ! do isn = is0+1, is1 jj = iconu(isn,k,i) rupdif(:,k,jj,i) = rupdif(:,k,j,i) rupdir(:,k,jj,i) = rupdir(:,k,j,i) end do ! ! end do l0 = 1, nuniqu(k,i) ! end do ! ! end do k = pver,0,-1 ! end do ! ! end do i = 1, Nday ! end do ! !---------------------------------------------------------------------- ! ! STEP 3 ! ! Compute up and down fluxes for each interface k. This requires ! adding up the contributions from all possible permutations ! of streams in all max-overlap regions, weighted by the ! product of the fractional areas of the streams in each region ! (the random overlap assumption). The adding principle has been ! used in step 2 to combine the bulk radiative properties ! above and below the interface. ! ! ! Initialize the fluxes ! fluxup = 0.0_r8 fluxdn = 0.0_r8 do i = 1, Nday !cdir novector do iconfig = 1, nconfig(i) xwgt = v_wgtv(iconfig,i) !cdir collapse do k = 0, pverp do ns = 1, nswbands xexpt = exptdn(ns,k,iconfig,i) xtdnt = tdntot(ns,k,iconfig,i) xrdnd = rdndif(ns,k,iconfig,i) xrupd = rupdif(ns,k,iconfig,i) xrups = rupdir(ns,k,iconfig,i) ! ! Flux computation ! rdenom = 1._r8/(1._r8 - xrdnd * xrupd) fluxup(ns,k,i) = fluxup(ns,k,i) + xwgt * & ((xexpt * xrups + (xtdnt - xexpt) * xrupd) * rdenom) fluxdn(ns,k,i) = fluxdn(ns,k,i) + xwgt * & (xexpt + (xtdnt - xexpt + xexpt * xrups * xrdnd) * rdenom) end do ! do ns = 1, nswbands end do ! ! End do iconfig = 1, nconfig(i) ! end do ! ! End do iconfig = 1, Nday ! end do ! ! Normalize by total area covered by cloud configurations included ! in solution ! do i = 1, Nday do k = 0, pverp do ns = 1, nswbands fluxup(ns,k,i)=fluxup(ns,k,i) / totwgt(i) fluxdn(ns,k,i)=fluxdn(ns,k,i) / totwgt(i) end do ! do i = 1, nday end do ! do k = 0, pverp end do ! do i = 1, nday ! ! Initialize the direct-beam flux at surface ! wexptdn(:,1:Nday) = 0.0_r8 do ns = 1,nswbands wgtint = nirwgt(ns) do i=1,Nday do iconfig = 1, nconfig(i) ! ! Note: exptdn can be directly indexed by iconfig at k=pverp. ! wexptdn(ns,i) = wexptdn(ns,i) + v_wgtv(iconfig,i) * exptdn(ns,pverp,iconfig,i) end do end do do i=1,Nday wexptdn(ns,i) = wexptdn(ns,i) / totwgt(i) ! ! Monochromatic computation completed; accumulate in totals ! if ( do_spctrl_scaling ) then solflx(i) = solin(i)*frcsol(ns)*psf(ns)*sfac(ns) else solflx(i) = solin(i)*frcsol(ns)*psf(ns) endif fsnt(i) = fsnt(i) + solflx(i)*(fluxdn(ns,1,i) - fluxup(ns,1,i)) fsntoa(i)= fsntoa(i) + solflx(i)*(fluxdn(ns,0,i) - fluxup(ns,0,i)) fsutoa(i)= fsutoa(i) + solflx(i)*(fluxup(ns,0,i)) fsns(i) = fsns(i) + solflx(i)*(fluxdn(ns,pverp,i)-fluxup(ns,pverp,i)) fsdtoa(i) = fsdtoa(i) + solflx(i) fswup(i,0) = fswup(i,0) + solflx(i)*fluxup(ns,0,i) fswdn(i,0) = fswdn(i,0) + solflx(i)*fluxdn(ns,0,i) ! ! Down spectral fluxes need to be in mks; thus the .001 conversion factors ! if (wavmid(ns) < 0.7_r8) then sols(i) = sols(i) + wexptdn(ns,i)*solflx(i)*0.001_r8 solsd(i) = solsd(i)+(fluxdn(ns,pverp,i)-wexptdn(ns,i))*solflx(i)*0.001_r8 else soll(i) = soll(i) + wexptdn(ns,i)*solflx(i)*0.001_r8 solld(i) = solld(i)+(fluxdn(ns,pverp,i)-wexptdn(ns,i))*solflx(i)*0.001_r8 fsnrtoaq(i) = fsnrtoaq(i) + solflx(i)*(fluxdn(ns,0,i) - fluxup(ns,0,i)) end if fsnirtoa(i) = fsnirtoa(i) + wgtint*solflx(i)*(fluxdn(ns,0,i) - fluxup(ns,0,i)) ! ! End do i=1,Nday ! end do do k=0,pver do i=1,Nday ! ! Compute flux divergence in each layer using the interface up and down ! fluxes: ! kp1 = k+1 flxdiv = (fluxdn(ns,k,i) - fluxdn(ns,kp1,i)) + (fluxup(ns,kp1,i) - fluxup(ns,k,i)) totfld(i,k) = totfld(i,k) + solflx(i)*flxdiv fswdn(i,kp1) = fswdn(i,kp1) + solflx(i)*fluxdn(ns,kp1,i) fswup(i,kp1) = fswup(i,kp1) + solflx(i)*fluxup(ns,kp1,i) fns(i,kp1) = fswdn(i,kp1) - fswup(i,kp1) if (single_column.and.scm_crm_mode) then fus(i,kp1)=fswup(i,kp1) fds(i,kp1)=fswdn(i,kp1) endif end do end do ! ! Perform clear-sky calculation ! exptdnc(1:Nday,0) = 1.0_r8 rdndifc(1:Nday,0) = 0.0_r8 tdntotc(1:Nday,0) = 1.0_r8 rupdirc(1:Nday,pverp) = albdir(1:Nday,ns) rupdifc(1:Nday,pverp) = albdif(1:Nday,ns) !cdir expand=pverp do k = 1, pverp do i=1,Nday km1 = k - 1 xexpt = exptdnc(i,km1) xrdnd = rdndifc(i,km1) yrdnd = rdifc(ns,i,km1) ytdnd = tdifc(ns,i,km1) exptdnc(i,k) = xexpt*explayc(ns,i,km1) rdenom = 1._r8/(1._r8 - yrdnd*xrdnd) rdirexp = rdirc(ns,i,km1)*xexpt tdnmexp = tdntotc(i,km1) - xexpt tdntotc(i,k) = xexpt*tdirc(ns,i,km1) + ytdnd*(tdnmexp + xrdnd*rdirexp)* & rdenom rdndifc(i,k) = yrdnd + xrdnd*(ytdnd**2)*rdenom ! ! End do i=1,Nday ! end do end do do k=pver,0,-1 do i=1,Nday xrupd = rupdifc(i,k+1) yexpt = explayc(ns,i,k) yrupd = rdifc(ns,i,k) ytupd = tdifc(ns,i,k) rdenom = 1._r8/( 1._r8 - yrupd*xrupd) rupdirc(i,k) = rdirc(ns,i,k) + ytupd*(rupdirc(i,k+1)*yexpt + & xrupd*(tdirc(ns,i,k)-yexpt))*rdenom rupdifc(i,k) = yrupd + xrupd*ytupd**2*rdenom ! ! End do i=1,Nday ! end do end do do k=0,pverp do i=1,Nday rdenom = 1._r8/(1._r8 - rdndifc(i,k)*rupdifc(i,k)) fluxup(ns,k,i) = (exptdnc(i,k)*rupdirc(i,k) + (tdntotc(i,k)-exptdnc(i,k))*rupdifc(i,k))* & rdenom fluxdn(ns,k,i) = exptdnc(i,k) + & (tdntotc(i,k) - exptdnc(i,k) + exptdnc(i,k)*rupdirc(i,k)*rdndifc(i,k))* & rdenom ! ! End do i=1,Nday ! end do end do do k=0,pver do i=1,Nday ! ! Compute flux divergence in each layer using the interface up and down ! fluxes: ! kp1 = k+1 flxdiv = (fluxdn(ns,k,i) - fluxdn(ns,kp1,i)) + (fluxup(ns,kp1,i) - fluxup(ns,k,i)) totfldc(i,k) = totfldc(i,k) + solflx(i)*flxdiv end do end do do i=1,Nday fsntc(i) = fsntc(i)+solflx(i)*(fluxdn(ns,1,i)-fluxup(ns,1,i)) fsntoac(i) = fsntoac(i)+solflx(i)*(fluxdn(ns,0,i)-fluxup(ns,0,i)) fsnsc(i) = fsnsc(i)+solflx(i)*(fluxdn(ns,pverp,i)-fluxup(ns,pverp,i)) fsdsc(i) = fsdsc(i)+solflx(i)*(fluxdn(ns,pverp,i)) fsnrtoac(i) = fsnrtoac(i)+wgtint*solflx(i)*(fluxdn(ns,0,i)-fluxup(ns,0,i)) if (single_column.and.scm_crm_mode) then do k = 1,pverp fusc(i,k)=fusc(i,k) + solflx(i) * fluxup(ns,k,i) fdsc(i,k)=fdsc(i,k) + solflx(i) * fluxdn(ns,k,i) enddo endif ! ! End do i=1,Nday ! end do do k = 1,pverp do i=1,Nday fcns(i,k)=fcns(i,k) + solflx(i)*(fluxdn(ns,k,i)-fluxup(ns,k,i)) enddo enddo ! ! End of clear sky calculation ! ! ! End of spectral interval loop ! end do do i=1,Nday ! ! Compute solar heating rate (J/kg/s) ! !cdir expand=pver do k=1,pver qrs(i,k) = -1.E-4_r8*gravit*totfld(i,k)/(pint(i,k) - pint(i,k+1)) qrsc(i,k) = -1.E-4_r8*gravit*totfldc(i,k)/(pint(i,k) - pint(i,k+1)) end do ! ! Set the downwelling flux at the surface ! fsds(i) = fswdn(i,pverp) ! ! End do i=1,Nday ! end do ! ! Rearrange output arrays. ! ! intent(inout) ! call ExpDayNite(pmxrgn, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(nmxrgn, Nday, IdxDay, Nnite, IdxNite, 1, pcols) ! ! intent(out) ! call ExpDayNite(solin, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(qrs, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call ExpDayNite(qrsc, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pver) call ExpDayNite(fns, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(fcns, Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(fsns, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsnt, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsntoa, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsutoa, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsds, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsnsc, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsdsc, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsntc, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsdtoa, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsntoac, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(sols, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(soll, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(solsd, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(solld, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsnirtoa, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsnrtoac, Nday, IdxDay, Nnite, IdxNite, 1, pcols) call ExpDayNite(fsnrtoaq, Nday, IdxDay, Nnite, IdxNite, 1, pcols) ! these outfld calls don't work for spmd only outfield in scm mode (nonspmd) if (single_column.and.scm_crm_mode) then ! Following outputs added for CRM call ExpDayNite(fus,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(fds,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(fusc,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call ExpDayNite(fdsc,Nday, IdxDay, Nnite, IdxNite, 1, pcols, 1, pverp) call outfld('FUS ',fus * 1.e-3_r8 ,pcols,lchnk) call outfld('FDS ',fds * 1.e-3_r8 ,pcols,lchnk) call outfld('FUSC ',fusc,pcols,lchnk) call outfld('FDSC ',fdsc,pcols,lchnk) endif ! write(iulog, '(a, x, i3)') 'radcswmx : exiting, chunk identifier', lchnk return end subroutine radcswmx !------------------------------------------------------------------------------- subroutine raddedmx(coszrs ,ndayc ,abh2o , & 1,3 abo3 ,abco2 ,abo2 ,uh2o ,uo3 , & uco2 ,uo2 ,trayoslp,pflx ,ns , & tauxcl ,wcl ,gcl ,fcl ,tauxci , & wci ,gci ,fci ,aer_tau ,aer_tau_w, & aer_tau_w_g, aer_tau_w_f ,rdir ,rdif ,tdir , & tdif ,explay ,rdirc ,rdifc ,tdirc , & tdifc ,explayc ) !----------------------------------------------------------------------- ! ! Purpose: ! Computes layer reflectivities and transmissivities, from the top down ! to the surface using the delta-Eddington solutions for each layer ! ! Method: ! For more details , see Briegleb, Bruce P., 1992: Delta-Eddington ! Approximation for Solar Radiation in the NCAR Community Climate Model, ! Journal of Geophysical Research, Vol 97, D7, pp7603-7612). ! ! Modified for maximum/random cloud overlap by Bill Collins and John ! Truesdale ! ! Author: Bill Collins ! !----------------------------------------------------------------------- ! ! Minimum total transmission below which no layer computation are done: ! real(r8) trmin ! Minimum total transmission allowed real(r8) wray ! Rayleigh single scatter albedo real(r8) gray ! Rayleigh asymetry parameter real(r8) fray ! Rayleigh forward scattered fraction parameter (trmin = 1.e-3_r8) parameter (wray = 0.999999_r8) parameter (gray = 0.0_r8) parameter (fray = 0.1_r8) ! !------------------------------Arguments-------------------------------- ! ! Input arguments ! real(r8), intent(in) :: coszrs(pcols) ! Cosine zenith angle real(r8), intent(in) :: trayoslp ! Tray/sslp real(r8), intent(in) :: pflx(pcols,0:pverp) ! Interface pressure real(r8), intent(in) :: abh2o ! Absorption coefficiant for h2o real(r8), intent(in) :: abo3 ! Absorption coefficiant for o3 real(r8), intent(in) :: abco2 ! Absorption coefficiant for co2 real(r8), intent(in) :: abo2 ! Absorption coefficiant for o2 real(r8), intent(in) :: uh2o(pcols,0:pver) ! Layer absorber amount of h2o real(r8), intent(in) :: uo3(pcols,0:pver) ! Layer absorber amount of o3 real(r8), intent(in) :: uco2(pcols,0:pver) ! Layer absorber amount of co2 real(r8), intent(in) :: uo2(pcols,0:pver) ! Layer absorber amount of o2 real(r8), intent(in) :: tauxcl(pcols,0:pver) ! Cloud extinction optical depth (liquid) real(r8), intent(in) :: wcl(pcols,0:pver) ! Cloud single scattering albedo (liquid) real(r8), intent(in) :: gcl(pcols,0:pver) ! Cloud asymmetry parameter (liquid) real(r8), intent(in) :: fcl(pcols,0:pver) ! Cloud forward scattered fraction (liquid) real(r8), intent(in) :: tauxci(pcols,0:pver) ! Cloud extinction optical depth (ice) real(r8), intent(in) :: wci(pcols,0:pver) ! Cloud single scattering albedo (ice) real(r8), intent(in) :: gci(pcols,0:pver) ! Cloud asymmetry parameter (ice) real(r8), intent(in) :: fci(pcols,0:pver) ! Cloud forward scattered fraction (ice) real(r8), intent(inout) :: aer_tau(pcols,0:pver) ! Aerosol extinction optical depth real(r8), intent(inout) :: aer_tau_w(pcols,0:pver) ! Aerosol single scattering albedo * tau real(r8), intent(inout) :: aer_tau_w_g(pcols,0:pver) ! Aerosol asymmetry parameter * w * t real(r8), intent(inout) :: aer_tau_w_f(pcols,0:pver) ! Aerosol forward scattered fraction * w * tau integer, intent(in) :: ndayc ! Number of daylight columns integer, intent(in) :: ns ! Index of spectral interval ! ! Input/Output arguments ! ! Following variables are defined for each layer; 0 refers to extra ! layer above top of model: ! real(r8), intent(inout) :: rdir(nswbands,pcols,0:pver) ! Layer reflectivity to direct rad real(r8), intent(inout) :: rdif(nswbands,pcols,0:pver) ! Layer reflectivity to diffuse rad real(r8), intent(inout) :: tdir(nswbands,pcols,0:pver) ! Layer transmission to direct rad real(r8), intent(inout) :: tdif(nswbands,pcols,0:pver) ! Layer transmission to diffuse rad real(r8), intent(inout) :: explay(nswbands,pcols,0:pver) ! Solar beam exp transm for layer ! ! Corresponding quantities for clear-skies ! real(r8), intent(inout) :: rdirc(nswbands,pcols,0:pver) ! Clear layer reflec. to direct rad real(r8), intent(inout) :: rdifc(nswbands,pcols,0:pver) ! Clear layer reflec. to diffuse rad real(r8), intent(inout) :: tdirc(nswbands,pcols,0:pver) ! Clear layer trans. to direct rad real(r8), intent(inout) :: tdifc(nswbands,pcols,0:pver) ! Clear layer trans. to diffuse rad real(r8), intent(inout) :: explayc(nswbands,pcols,0:pver)! Solar beam exp transm clear layer ! !---------------------------Local variables----------------------------- ! integer i ! Column indices integer k ! Level index integer nn ! Index of column loops (max=ndayc) real(r8) taugab(pcols) ! Layer total gas absorption optical depth real(r8) tauray(pcols) ! Layer rayleigh optical depth real(r8) taucsc ! Layer cloud scattering optical depth real(r8) tautot ! Total layer optical depth real(r8) wtot ! Total layer single scatter albedo real(r8) gtot ! Total layer asymmetry parameter real(r8) ftot ! Total layer forward scatter fraction real(r8) wtau ! rayleigh layer scattering optical depth real(r8) wt ! layer total single scattering albedo real(r8) ts ! layer scaled extinction optical depth real(r8) ws ! layer scaled single scattering albedo real(r8) gs ! layer scaled asymmetry parameter ! !---------------------------Statement functions------------------------- ! ! Statement functions and other local variables ! real(r8) alpha ! Term in direct reflect and transmissivity real(r8) gamma ! Term in direct reflect and transmissivity real(r8) el ! Term in alpha,gamma,n,u real(r8) taus ! Scaled extinction optical depth real(r8) omgs ! Scaled single particle scattering albedo real(r8) asys ! Scaled asymmetry parameter real(r8) u ! Term in diffuse reflect and ! transmissivity real(r8) n ! Term in diffuse reflect and ! transmissivity real(r8) lm ! Temporary for el real(r8) ne ! Temporary for n real(r8) w ! Dummy argument for statement function real(r8) uu ! Dummy argument for statement function real(r8) g ! Dummy argument for statement function real(r8) e ! Dummy argument for statement function real(r8) f ! Dummy argument for statement function real(r8) t ! Dummy argument for statement function real(r8) et ! Dummy argument for statement function ! ! Intermediate terms for delta-eddington solution ! real(r8) alp ! Temporary for alpha real(r8) gam ! Temporary for gamma real(r8) ue ! Temporary for u real(r8) arg ! Exponential argument real(r8) extins ! Extinction real(r8) amg ! Alp - gam real(r8) apg ! Alp + gam ! ! ssa <=1 limit for aerosol ! real(r8) :: w_limited(pcols,0:pver) ! Aerosol ssa (limited to < 0.999999) real(r8) :: aer_g_limit(pcols,0:pver) ! Aerosol tau_w_g (limited ssa) real(r8) :: aer_f_limit(pcols,0:pver) ! Aerosol tau_w_f (limited ssa) ! alpha(w,uu,g,e) = .75_r8*w*uu*((1._r8 + g*(1._r8-w))/(1._r8 - e*e*uu*uu)) gamma(w,uu,g,e) = .50_r8*w*((3._r8*g*(1._r8-w)*uu*uu + 1._r8)/(1._r8-e*e*uu*uu)) el(w,g) = sqrt(3._r8*(1._r8-w)*(1._r8 - w*g)) taus(w,f,t) = (1._r8 - w*f)*t omgs(w,f) = (1._r8 - f)*w/(1._r8 - w*f) asys(g,f) = (g - f)/(1._r8 - f) u(w,g,e) = 1.5_r8*(1._r8 - w*g)/e n(uu,et) = ((uu+1._r8)*(uu+1._r8)/et ) - ((uu-1._r8)*(uu-1._r8)*et) ! !----------------------------------------------------------------------- ! ! Compute layer radiative properties ! ! Compute radiative properties (reflectivity and transmissivity for ! direct and diffuse radiation incident from above, under clear ! and cloudy conditions) and transmission of direct radiation ! (under clear and cloudy conditions) for each layer. ! do k=0,pver do i=1,ndayc if(aer_tau(i,k) > 0._r8) then !where(aer_tau > 0._r8) aer_g_limit(i,k) = aer_tau_w_g(i,k) / aer_tau_w(i,k) aer_f_limit(i,k) = aer_tau_w_f(i,k) / aer_tau_w(i,k) aer_tau_w(i,k) = aer_tau(i,k) * min(aer_tau_w(i,k)/aer_tau(i,k) , 0.999999_r8) else aer_tau(i,k) = 0._r8 aer_tau_w(i,k) = 0._r8 aer_g_limit(i,k) = 0. aer_f_limit(i,k) = 0. endif aer_tau_w_g(i,k) = aer_tau_w(i,k) * aer_g_limit(i,k) aer_tau_w_f(i,k) = aer_tau_w(i,k) * aer_f_limit(i,k) enddo enddo do k=0,pver do i=1,ndayc tauray(i) = trayoslp*(pflx(i,k+1)-pflx(i,k)) taugab(i) = abh2o*uh2o(i,k) + abo3*uo3(i,k) + abco2*uco2(i,k) + abo2*uo2(i,k) tautot = tauxcl(i,k) + tauxci(i,k) + tauray(i) + taugab(i) + aer_tau(i,k) taucsc = tauxcl(i,k)*wcl(i,k) + tauxci(i,k)*wci(i,k) + aer_tau_w(i,k) wtau = wray*tauray(i) wt = wtau + taucsc wtot = wt/tautot gtot = (wtau*gray + gcl(i,k)*wcl(i,k)*tauxcl(i,k) & + gci(i,k)*wci(i,k)*tauxci(i,k) + aer_tau_w_g(i,k))/wt ftot = (wtau*fray + fcl(i,k)*wcl(i,k)*tauxcl(i,k) & + fci(i,k)*wci(i,k)*tauxci(i,k) + aer_tau_w_f(i,k))/wt ts = taus(wtot,ftot,tautot) ws = omgs(wtot,ftot) gs = asys(gtot,ftot) lm = el(ws,gs) alp = alpha(ws,coszrs(i),gs,lm) gam = gamma(ws,coszrs(i),gs,lm) ue = u(ws,gs,lm) ! ! Limit argument of exponential to 25, in case lm very large: ! arg = min(lm*ts,25._r8) extins = exp(-arg) ne = n(ue,extins) rdif(ns,i,k) = (ue+1._r8)*(ue-1._r8)*(1._r8/extins - extins)/ne tdif(ns,i,k) = 4._r8*ue/ne ! ! Limit argument of exponential to 25, in case coszrs is very small: ! arg = min(ts/coszrs(i),25._r8) explay(ns,i,k) = exp(-arg) apg = alp + gam amg = alp - gam rdir(ns,i,k) = amg*(tdif(ns,i,k)*explay(ns,i,k)-1._r8) + apg*rdif(ns,i,k) tdir(ns,i,k) = apg*tdif(ns,i,k) + (amg*rdif(ns,i,k)-(apg-1._r8))*explay(ns,i,k) ! ! Under rare conditions, reflectivies and transmissivities can be ! negative; zero out any negative values ! rdir(ns,i,k) = max(rdir(ns,i,k),0.0_r8) tdir(ns,i,k) = max(tdir(ns,i,k),0.0_r8) rdif(ns,i,k) = max(rdif(ns,i,k),0.0_r8) tdif(ns,i,k) = max(tdif(ns,i,k),0.0_r8) ! ! Clear-sky calculation ! if (tauxcl(i,k) == 0.0_r8 .and. tauxci(i,k) == 0.0_r8) then rdirc(ns,i,k) = rdir(ns,i,k) tdirc(ns,i,k) = tdir(ns,i,k) rdifc(ns,i,k) = rdif(ns,i,k) tdifc(ns,i,k) = tdif(ns,i,k) explayc(ns,i,k) = explay(ns,i,k) else tautot = tauray(i) + taugab(i) + aer_tau(i,k) taucsc = aer_tau_w(i,k) ! ! wtau already computed for all-sky ! wt = wtau + taucsc wtot = wt/tautot gtot = (wtau*gray + aer_tau_w_g(i,k))/wt ftot = (wtau*fray + aer_tau_w_f(i,k))/wt ts = taus(wtot,ftot,tautot) ws = omgs(wtot,ftot) gs = asys(gtot,ftot) lm = el(ws,gs) alp = alpha(ws,coszrs(i),gs,lm) gam = gamma(ws,coszrs(i),gs,lm) ue = u(ws,gs,lm) ! ! Limit argument of exponential to 25, in case lm very large: ! arg = min(lm*ts,25._r8) extins = exp(-arg) ne = n(ue,extins) rdifc(ns,i,k) = (ue+1._r8)*(ue-1._r8)*(1._r8/extins - extins)/ne tdifc(ns,i,k) = 4._r8*ue/ne ! ! Limit argument of exponential to 25, in case coszrs is very small: ! arg = min(ts/coszrs(i),25._r8) explayc(ns,i,k) = exp(-arg) apg = alp + gam amg = alp - gam rdirc(ns,i,k) = amg*(tdifc(ns,i,k)*explayc(ns,i,k)-1._r8)+ & apg*rdifc(ns,i,k) tdirc(ns,i,k) = apg*tdifc(ns,i,k) + (amg*rdifc(ns,i,k) - (apg-1._r8))* & explayc(ns,i,k) ! ! Under rare conditions, reflectivies and transmissivities can be ! negative; zero out any negative values ! rdirc(ns,i,k) = max(rdirc(ns,i,k),0.0_r8) tdirc(ns,i,k) = max(tdirc(ns,i,k),0.0_r8) rdifc(ns,i,k) = max(rdifc(ns,i,k),0.0_r8) tdifc(ns,i,k) = max(tdifc(ns,i,k),0.0_r8) end if end do end do end subroutine raddedmx !------------------------------------------------------------------------------- subroutine radsw_init(gravx) 1 !----------------------------------------------------------------------- ! ! Purpose: ! Initialize various constants for radiation scheme; note that ! the radiation scheme uses cgs units. ! ! Author: W. Collins (H2O parameterization) and J. Kiehl ! !----------------------------------------------------------------------- ! ! Input arguments ! real(r8), intent(in) :: gravx ! Acceleration of gravity (MKS) real(r8), parameter :: ref_tsi = 1367._r8 ! value supplied by Dan Marsh -- see solvar_woods.F90 ! !----------------------------------------------------------------------- ! ! Set general radiation consts; convert to cgs units where appropriate: ! gravit = 100._r8*gravx rga = 1._r8/gravit sslp = 1.013250e6_r8 end subroutine radsw_init !------------------------------------------------------------------------------- end module radsw