LCOV - code coverage report
Current view: top level - physics/rrtmgp - radiation.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 950 1061 89.5 %
Date: 2024-12-17 22:39:59 Functions: 23 24 95.8 %

          Line data    Source code
       1             : module radiation
       2             : 
       3             : !---------------------------------------------------------------------------------
       4             : !
       5             : ! CAM interface to RRTMGP radiation parameterization.
       6             : !
       7             : !---------------------------------------------------------------------------------
       8             : 
       9             : use shr_kind_mod,        only: r8=>shr_kind_r8, cl=>shr_kind_cl
      10             : use spmd_utils,          only: masterproc
      11             : use ppgrid,              only: pcols, pver, pverp, begchunk, endchunk
      12             : use ref_pres,            only: pref_edge
      13             : use physics_types,       only: physics_state, physics_ptend
      14             : use phys_control,        only: phys_getopts
      15             : use physics_buffer,      only: physics_buffer_desc, pbuf_add_field, dtype_r8, pbuf_get_index, &
      16             :                                pbuf_set_field, pbuf_get_field, pbuf_old_tim_idx
      17             : use camsrfexch,          only: cam_out_t, cam_in_t
      18             : use physconst,           only: cappa, cpair, gravit
      19             : use solar_irrad_data,    only: sol_tsi
      20             : 
      21             : use time_manager,        only: get_nstep, is_first_step, is_first_restart_step, &
      22             :                                get_curr_calday, get_step_size
      23             : 
      24             : use rad_constituents,    only: N_DIAG, rad_cnst_get_call_list, rad_cnst_get_gas, rad_cnst_out
      25             : 
      26             : use rrtmgp_inputs,       only: rrtmgp_inputs_init
      27             : 
      28             : use radconstants,        only: nradgas, gasnamelength, gaslist, nswbands, nlwbands, &
      29             :                                nswgpts, set_wavenumber_bands
      30             : 
      31             : use cloud_rad_props,     only: cloud_rad_props_init
      32             : 
      33             : use cospsimulator_intr,  only: docosp, cospsimulator_intr_init, &
      34             :                                cospsimulator_intr_run, cosp_nradsteps
      35             : 
      36             : use scamMod,             only: scm_crm_mode, single_column, have_cld, cldobs
      37             : 
      38             : use cam_history,         only: addfld, add_default, horiz_only, outfld, hist_fld_active
      39             : 
      40             : use radiation_data,      only: rad_data_register, rad_data_init
      41             : 
      42             : use ioFileMod,           only: getfil
      43             : use cam_pio_utils,       only: cam_pio_openfile
      44             : use pio,                 only: file_desc_t, var_desc_t,                       &
      45             :                                pio_int, pio_double, PIO_NOERR,                &
      46             :                                pio_seterrorhandling, PIO_BCAST_ERROR,         &
      47             :                                pio_inq_dimlen, pio_inq_dimid, pio_inq_varid,  &
      48             :                                pio_def_var, pio_put_var, pio_get_var,         &
      49             :                                pio_put_att, PIO_NOWRITE, pio_closefile
      50             : 
      51             : use mo_gas_concentrations, only: ty_gas_concs
      52             : use mo_gas_optics_rrtmgp,  only: ty_gas_optics_rrtmgp
      53             : use mo_optical_props,      only: ty_optical_props_1scl, ty_optical_props_2str
      54             : use mo_source_functions,   only: ty_source_func_lw
      55             : use mo_fluxes,             only: ty_fluxes_broadband
      56             : use mo_fluxes_byband,      only: ty_fluxes_byband
      57             : 
      58             : use string_utils,        only: to_lower
      59             : use cam_abortutils,      only: endrun, handle_allocate_error
      60             : use cam_logfile,         only: iulog
      61             : 
      62             : 
      63             : implicit none
      64             : private
      65             : save
      66             : 
      67             : public :: &
      68             :    radiation_readnl,         &! read namelist variables
      69             :    radiation_register,       &! registers radiation physics buffer fields
      70             :    radiation_do,             &! query which radiation calcs are done this timestep
      71             :    radiation_init,           &! initialization
      72             :    radiation_define_restart, &! define variables for restart
      73             :    radiation_write_restart,  &! write variables to restart
      74             :    radiation_read_restart,   &! read variables from restart
      75             :    radiation_tend,           &! compute heating rates and fluxes
      76             :    rad_out_t                  ! type for diagnostic outputs
      77             : 
      78             : integer,public, allocatable :: cosp_cnt(:)       ! counter for cosp
      79             : integer,public              :: cosp_cnt_init = 0 !initial value for cosp counter
      80             : 
      81             : real(r8), public, protected :: nextsw_cday       ! future radiation calday for surface models
      82             : 
      83             : type rad_out_t
      84             :    real(r8) :: solin(pcols)         ! Solar incident flux
      85             : 
      86             :    real(r8) :: qrsc(pcols,pver)
      87             : 
      88             :    real(r8) :: fsnsc(pcols)         ! Clear sky surface abs solar flux
      89             :    real(r8) :: fsntc(pcols)         ! Clear sky total column abs solar flux
      90             :    real(r8) :: fsdsc(pcols)         ! Clear sky surface downwelling solar flux
      91             :    
      92             :    real(r8) :: fsntoa(pcols)        ! Net solar flux at TOA
      93             :    real(r8) :: fsntoac(pcols)       ! Clear sky net solar flux at TOA
      94             :    real(r8) :: fsutoa(pcols)        ! upwelling solar flux at TOA
      95             : 
      96             :    real(r8) :: fsnirt(pcols)        ! Near-IR flux absorbed at toa
      97             :    real(r8) :: fsnrtc(pcols)        ! Clear sky near-IR flux absorbed at toa
      98             :    real(r8) :: fsnirtsq(pcols)      ! Near-IR flux absorbed at toa >= 0.7 microns
      99             : 
     100             :    real(r8) :: fsn200(pcols)        ! Net SW flux interpolated to 200 mb
     101             :    real(r8) :: fsn200c(pcols)       ! Net clear-sky SW flux interpolated to 200 mb
     102             :    real(r8) :: fsnr(pcols)          ! Net SW flux interpolated to tropopause
     103             :    
     104             :    real(r8) :: flux_sw_up(pcols,pverp)     ! upward shortwave flux on interfaces
     105             :    real(r8) :: flux_sw_clr_up(pcols,pverp) ! upward shortwave clearsky flux
     106             :    real(r8) :: flux_sw_dn(pcols,pverp)     ! downward flux
     107             :    real(r8) :: flux_sw_clr_dn(pcols,pverp) ! downward clearsky flux
     108             : 
     109             :    real(r8) :: flux_lw_up(pcols,pverp)     ! upward longwave flux on interfaces
     110             :    real(r8) :: flux_lw_clr_up(pcols,pverp) ! upward longwave clearsky flux
     111             :    real(r8) :: flux_lw_dn(pcols,pverp)     ! downward flux
     112             :    real(r8) :: flux_lw_clr_dn(pcols,pverp) ! downward clearsky flux
     113             : 
     114             :    real(r8) :: qrlc(pcols,pver)
     115             : 
     116             :    real(r8) :: flntc(pcols)         ! Clear sky lw flux at model top
     117             :    real(r8) :: flut(pcols)          ! Upward flux at top of model
     118             :    real(r8) :: flutc(pcols)         ! Upward Clear Sky flux at top of model
     119             :    real(r8) :: lwcf(pcols)          ! longwave cloud forcing
     120             : 
     121             :    real(r8) :: fln200(pcols)        ! net longwave flux interpolated to 200 mb
     122             :    real(r8) :: fln200c(pcols)       ! net clearsky longwave flux interpolated to 200 mb
     123             :    real(r8) :: flnr(pcols)          ! net longwave flux interpolated to tropopause
     124             : 
     125             :    real(r8) :: flnsc(pcols)         ! Clear sky lw flux at srf (up-down)
     126             :    real(r8) :: fldsc(pcols)         ! Clear sky lw flux at srf (down)
     127             : 
     128             :    real(r8) :: tot_cld_vistau(pcols,pver)   ! gbx water+ice cloud optical depth (only during day, night = fillvalue)
     129             :    real(r8) :: tot_icld_vistau(pcols,pver)  ! in-cld water+ice cloud optical depth (only during day, night = fillvalue)
     130             :    real(r8) :: liq_icld_vistau(pcols,pver)  ! in-cld liq cloud optical depth (only during day, night = fillvalue)
     131             :    real(r8) :: ice_icld_vistau(pcols,pver)  ! in-cld ice cloud optical depth (only during day, night = fillvalue)
     132             :    real(r8) :: snow_icld_vistau(pcols,pver) ! snow in-cloud visible sw optical depth for output on history files
     133             :    real(r8) :: grau_icld_vistau(pcols,pver) ! Graupel in-cloud visible sw optical depth for output on history files
     134             : end type rad_out_t
     135             : 
     136             : ! Control variables set via namelist
     137             : character(len=cl) :: coefs_lw_file ! filepath for lw coefficients
     138             : character(len=cl) :: coefs_sw_file ! filepath for sw coefficients
     139             : 
     140             : integer :: iradsw = -1     ! freq. of shortwave radiation calc in time steps (positive)
     141             :                            ! or hours (negative).
     142             : integer :: iradlw = -1     ! frequency of longwave rad. calc. in time steps (positive)
     143             :                            ! or hours (negative).
     144             : 
     145             : integer :: irad_always = 0 ! Specifies length of time in timesteps (positive)
     146             :                            ! or hours (negative) SW/LW radiation will be
     147             :                            ! run continuously from the start of an
     148             :                            ! initial or restart run
     149             : logical :: use_rad_dt_cosz  = .false. ! if true, use radiation dt for all cosz calculations
     150             : logical :: spectralflux     = .false. ! calculate fluxes (up and down) per band.
     151             : logical :: graupel_in_rad   = .false. ! graupel in radiation code
     152             : logical :: use_rad_uniform_angle = .false. ! if true, use the namelist rad_uniform_angle for the coszrs calculation
     153             : 
     154             : ! active_calls is set by a rad_constituents method after parsing namelist input
     155             : ! for the rad_climate and rad_diag_N entries.
     156             : logical :: active_calls(0:N_DIAG)
     157             : 
     158             : ! Physics buffer indices
     159             : integer :: qrs_idx      = 0 
     160             : integer :: qrl_idx      = 0 
     161             : integer :: su_idx       = 0 
     162             : integer :: sd_idx       = 0 
     163             : integer :: lu_idx       = 0 
     164             : integer :: ld_idx       = 0 
     165             : integer :: fsds_idx     = 0
     166             : integer :: fsns_idx     = 0
     167             : integer :: fsnt_idx     = 0
     168             : integer :: flns_idx     = 0
     169             : integer :: flnt_idx     = 0
     170             : integer :: cld_idx      = 0 
     171             : integer :: cldfsnow_idx = 0 
     172             : integer :: cldfgrau_idx = 0    
     173             : 
     174             : character(len=4) :: diag(0:N_DIAG) =(/'    ','_d1 ','_d2 ','_d3 ','_d4 ','_d5 ',&
     175             :                                       '_d6 ','_d7 ','_d8 ','_d9 ','_d10'/)
     176             : 
     177             : ! averaging time interval for zenith angle
     178             : real(r8) :: dt_avg = 0._r8
     179             : real(r8) :: rad_uniform_angle = -99._r8
     180             : 
     181             : ! Number of layers in radiation calculations.
     182             : integer :: nlay
     183             : 
     184             : ! Number of CAM layers in radiation calculations.  Is either equal to nlay, or is
     185             : ! 1 less than nlay if "extra layer" is used in the radiation calculations.
     186             : integer :: nlaycam
     187             : 
     188             : ! Indices for copying data between CAM/WACCM and RRTMGP arrays.  Since RRTMGP is
     189             : ! vertical order agnostic we can send data using the top to bottom order used
     190             : ! in CAM/WACCM.  But the number of layers that RRTMGP does computations for
     191             : ! may not match the number of layers in CAM/WACCM for two reasons:
     192             : ! 1. If the CAM model top is below 1 Pa, then RRTMGP does calculations for an
     193             : !    extra layer that is added between 1 Pa and the model top.
     194             : ! 2. If the WACCM model top is above 1 Pa, then RRMTGP only does calculations
     195             : !    for those model layers that are below 1 Pa.
     196             : integer :: ktopcam ! Index in CAM arrays of top level (layer or interface) at which
     197             :                    ! RRTMGP is active.
     198             : integer :: ktoprad ! Index in RRTMGP arrays of the layer or interface corresponding
     199             :                    ! to CAM's top layer or interface.
     200             :                    ! Note: for CAM's top to bottom indexing, the index of a given layer
     201             :                    ! (midpoint) and the upper interface of that layer, are the same.
     202             : 
     203             : ! Gas optics objects contain the data read from the coefficients files.
     204             : type(ty_gas_optics_rrtmgp) :: kdist_sw
     205             : type(ty_gas_optics_rrtmgp) :: kdist_lw
     206             : 
     207             : ! lower case version of gaslist for RRTMGP
     208             : character(len=gasnamelength) :: gaslist_lc(nradgas)
     209             : 
     210             : type(var_desc_t) :: cospcnt_desc  ! cosp
     211             : type(var_desc_t) :: nextsw_cday_desc
     212             : 
     213             : !=========================================================================================
     214             : contains
     215             : !=========================================================================================
     216             : 
     217        1536 : subroutine radiation_readnl(nlfile)
     218             : 
     219             :    ! Read radiation_nl namelist group.
     220             : 
     221             :    use namelist_utils,  only: find_group_name
     222             :    use spmd_utils,      only: mpicom, mstrid=>masterprocid, mpi_integer, mpi_logical, &
     223             :                               mpi_character, mpi_real8
     224             : 
     225             :    character(len=*), intent(in) :: nlfile  ! filepath for file containing namelist input
     226             : 
     227             :    ! Local variables
     228             :    integer :: unitn, ierr
     229             :    integer :: dtime      ! timestep size
     230             :    character(len=32) :: errmsg
     231             :    character(len=*), parameter :: sub = 'radiation_readnl'
     232             : 
     233             :    character(len=cl) :: rrtmgp_coefs_lw_file, rrtmgp_coefs_sw_file
     234             : 
     235             :    namelist /radiation_nl/ &
     236             :       rrtmgp_coefs_lw_file, rrtmgp_coefs_sw_file, iradsw, iradlw,        &
     237             :       irad_always, use_rad_dt_cosz, spectralflux, use_rad_uniform_angle, &
     238             :       rad_uniform_angle, graupel_in_rad
     239             :    !-----------------------------------------------------------------------------
     240             : 
     241        1536 :    if (masterproc) then
     242           2 :       open( newunit=unitn, file=trim(nlfile), status='old' )
     243           2 :       call find_group_name(unitn, 'radiation_nl', status=ierr)
     244           2 :       if (ierr == 0) then
     245           2 :          read(unitn, radiation_nl, iostat=ierr)
     246           2 :          if (ierr /= 0) then
     247           0 :             write(errmsg,'(a,i5)') 'iostat =', ierr
     248           0 :             call endrun(sub//': ERROR reading namelist: '//trim(errmsg))
     249             :          end if
     250             :       end if
     251           2 :       close(unitn)
     252             :    end if
     253             : 
     254             :    ! Broadcast namelist variables
     255        1536 :    call mpi_bcast(rrtmgp_coefs_lw_file, cl, mpi_character, mstrid, mpicom, ierr)
     256        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: rrtmgp_coefs_lw_file")
     257        1536 :    call mpi_bcast(rrtmgp_coefs_sw_file, cl, mpi_character, mstrid, mpicom, ierr)
     258        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: rrtmgp_coefs_sw_file")
     259        1536 :    call mpi_bcast(iradsw, 1, mpi_integer, mstrid, mpicom, ierr)
     260        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: iradsw")
     261        1536 :    call mpi_bcast(iradlw, 1, mpi_integer, mstrid, mpicom, ierr)
     262        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: iradlw")
     263        1536 :    call mpi_bcast(irad_always, 1, mpi_integer, mstrid, mpicom, ierr)
     264        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: irad_always")
     265        1536 :    call mpi_bcast(use_rad_dt_cosz, 1, mpi_logical, mstrid, mpicom, ierr)
     266        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: use_rad_dt_cosz")
     267        1536 :    call mpi_bcast(spectralflux, 1, mpi_logical, mstrid, mpicom, ierr)
     268        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: spectralflux")
     269        1536 :    call mpi_bcast(use_rad_uniform_angle, 1, mpi_logical, mstrid, mpicom, ierr)
     270        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: use_rad_uniform_angle")
     271        1536 :    call mpi_bcast(rad_uniform_angle, 1, mpi_real8, mstrid, mpicom, ierr)
     272        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: rad_uniform_angle")   
     273        1536 :    call mpi_bcast(graupel_in_rad, 1, mpi_logical, mstrid, mpicom, ierr)
     274        1536 :    if (ierr /= 0) call endrun(sub//": FATAL: mpi_bcast: graupel_in_rad")
     275             : 
     276        1536 :    if (use_rad_uniform_angle .and. rad_uniform_angle == -99._r8) then
     277             :       call endrun(sub//': ERROR - use_rad_uniform_angle is set to .true,' &
     278           0 :                      //' but rad_uniform_angle is not set ')
     279             :    end if
     280             : 
     281             :    ! Set module data
     282        1536 :    coefs_lw_file   = rrtmgp_coefs_lw_file
     283        1536 :    coefs_sw_file   = rrtmgp_coefs_sw_file
     284             : 
     285             :    ! Convert iradsw, iradlw and irad_always from hours to timesteps if necessary
     286        1536 :    dtime  = get_step_size()
     287        1536 :    if (iradsw      < 0) iradsw      = nint((-iradsw     *3600._r8)/dtime)
     288        1536 :    if (iradlw      < 0) iradlw      = nint((-iradlw     *3600._r8)/dtime)
     289        1536 :    if (irad_always < 0) irad_always = nint((-irad_always*3600._r8)/dtime)
     290             : 
     291             :    !----------------------------------------------------------------------- 
     292             :    ! Print runtime options to log.
     293             :    !-----------------------------------------------------------------------
     294             : 
     295        1536 :    if (masterproc) then
     296           2 :       write(iulog,*) 'RRTMGP radiation scheme parameters:'
     297           2 :       write(iulog,10) trim(coefs_lw_file), trim(coefs_sw_file), nlwbands, nswbands, &
     298           4 :          iradsw, iradlw, irad_always, use_rad_dt_cosz, spectralflux, graupel_in_rad
     299             :    end if
     300             : 
     301             : 10 format('  LW coefficents file: ',                                a/, &
     302             :           '  SW coefficents file: ',                                a/, &
     303             :           '  Number of LW bands:                                 ',i5/, &
     304             :           '  Number of SW bands:                                 ',i5/, &
     305             :           '  Frequency (timesteps) of Shortwave Radiation calc:  ',i5/, &
     306             :           '  Frequency (timesteps) of Longwave Radiation calc:   ',i5/, &
     307             :           '  SW/LW calc done every timestep for first N steps. N=',i5/, &
     308             :           '  Use average zenith angle:                           ',l5/, &
     309             :           '  Output spectrally resolved fluxes:                  ',l5/, &
     310             :           '  Graupel in Radiation Code:                          ',l5/)
     311             : 
     312        1536 : end subroutine radiation_readnl
     313             : 
     314             : !================================================================================================
     315             : 
     316        1536 : subroutine radiation_register
     317             : 
     318             :    ! Register radiation fields in the physics buffer
     319             : 
     320        1536 :    call pbuf_add_field('QRS' , 'global',dtype_r8,(/pcols,pver/), qrs_idx) ! shortwave radiative heating rate 
     321        1536 :    call pbuf_add_field('QRL' , 'global',dtype_r8,(/pcols,pver/), qrl_idx) ! longwave  radiative heating rate 
     322             : 
     323        1536 :    call pbuf_add_field('FSDS' , 'global',dtype_r8,(/pcols/), fsds_idx) ! Surface solar downward flux
     324        1536 :    call pbuf_add_field('FSNS' , 'global',dtype_r8,(/pcols/), fsns_idx) ! Surface net shortwave flux
     325        1536 :    call pbuf_add_field('FSNT' , 'global',dtype_r8,(/pcols/), fsnt_idx) ! Top-of-model net shortwave flux
     326             : 
     327        1536 :    call pbuf_add_field('FLNS' , 'global',dtype_r8,(/pcols/), flns_idx) ! Surface net longwave flux
     328        1536 :    call pbuf_add_field('FLNT' , 'global',dtype_r8,(/pcols/), flnt_idx) ! Top-of-model net longwave flux
     329             : 
     330             :    ! If the namelist has been configured for preserving the spectral fluxes, then create
     331             :    ! physics buffer variables to store the results.  This data is accessed by CARMA.
     332        1536 :    if (spectralflux) then
     333           0 :       call pbuf_add_field('SU'  , 'global',dtype_r8,(/pcols,pverp,nswbands/), su_idx) ! shortwave upward flux (per band)
     334           0 :       call pbuf_add_field('SD'  , 'global',dtype_r8,(/pcols,pverp,nswbands/), sd_idx) ! shortwave downward flux (per band)
     335           0 :       call pbuf_add_field('LU'  , 'global',dtype_r8,(/pcols,pverp,nlwbands/), lu_idx) ! longwave upward flux (per band)
     336           0 :       call pbuf_add_field('LD'  , 'global',dtype_r8,(/pcols,pverp,nlwbands/), ld_idx) ! longwave downward flux (per band)
     337             :    end if
     338             : 
     339             :    ! Register fields for offline radiation driver.
     340        1536 :    call rad_data_register()
     341             : 
     342        1536 : end subroutine radiation_register
     343             : 
     344             : !================================================================================================
     345             : 
     346     5232240 : function radiation_do(op, timestep)
     347             : 
     348             :    ! Return true if the specified operation is done this timestep.
     349             : 
     350             :    character(len=*), intent(in) :: op             ! name of operation
     351             :    integer, intent(in), optional:: timestep
     352             :    logical                      :: radiation_do   ! return value
     353             : 
     354             :    ! Local variables
     355             :    integer :: nstep             ! current timestep number
     356             :    !-----------------------------------------------------------------------
     357             : 
     358     5232240 :    if (present(timestep)) then
     359     5232240 :       nstep = timestep
     360             :    else
     361           0 :       nstep = get_nstep()
     362             :    end if
     363             : 
     364     3739968 :    select case (op)
     365             :       case ('sw') ! do a shortwave heating calc this timestep?
     366             :          radiation_do = nstep == 0  .or.  iradsw == 1                     &
     367             :                      .or. (mod(nstep-1,iradsw) == 0  .and.  nstep /= 1)   &
     368     3739968 :                      .or. nstep <= irad_always
     369             :       case ('lw') ! do a longwave heating calc this timestep?
     370             :          radiation_do = nstep == 0  .or.  iradlw == 1                     &
     371             :                      .or. (mod(nstep-1,iradlw) == 0  .and.  nstep /= 1)   &
     372     1492272 :                      .or. nstep <= irad_always
     373             :       case default
     374     5232240 :          call endrun('radiation_do: unknown operation:'//op)
     375             :    end select
     376             : 
     377     5232240 : end function radiation_do
     378             : 
     379             : !================================================================================================
     380             : 
     381     1492272 : real(r8) function radiation_nextsw_cday()
     382             :   
     383             :    ! If a SW radiation calculation will be done on the next time-step, then return
     384             :    ! the calendar day of that time-step.  Otherwise return -1.0
     385             : 
     386             :    ! Local variables
     387             :    integer :: nstep      ! timestep counter
     388             :    logical :: dosw       ! true => do shosrtwave calc   
     389             :    integer :: offset     ! offset for calendar day calculation
     390             :    integer :: dtime      ! integer timestep size
     391             :    real(r8):: caldayp1   ! calendar day of next time-step
     392             : 
     393             :    !-----------------------------------------------------------------------
     394             : 
     395     1492272 :    radiation_nextsw_cday = -1._r8
     396     1492272 :    dosw   = .false.
     397     1492272 :    nstep  = get_nstep()
     398     1492272 :    dtime  = get_step_size()
     399     1492272 :    offset = 0
     400             :    do while (.not. dosw)
     401     2247696 :       nstep = nstep + 1
     402     2247696 :       offset = offset + dtime
     403     2247696 :       if (radiation_do('sw', nstep)) then
     404     1492272 :          radiation_nextsw_cday = get_curr_calday(offset=offset)
     405             :          dosw = .true.
     406             :       end if
     407             :    end do
     408     1492272 :    if(radiation_nextsw_cday == -1._r8) then
     409           0 :       call endrun('error in radiation_nextsw_cday')
     410             :    end if
     411             :    
     412             :    ! determine if next radiation time-step not equal to next time-step
     413     1492272 :    if (get_nstep() >= 1) then
     414     1486080 :       caldayp1 = get_curr_calday(offset=int(dtime))
     415     1486080 :       if (caldayp1 /= radiation_nextsw_cday) radiation_nextsw_cday = -1._r8
     416             :    end if    
     417             : 
     418     1492272 : end function radiation_nextsw_cday
     419             : 
     420             : !================================================================================================
     421             : 
     422        1536 : subroutine radiation_init(pbuf2d)
     423             : 
     424             :    ! Initialize the radiation and cloud optics.
     425             :    ! Add fields to the history buffer.
     426             : 
     427             :    ! arguments
     428             :    type(physics_buffer_desc), pointer :: pbuf2d(:,:)
     429             : 
     430             :    ! local variables
     431             :    character(len=128) :: errmsg
     432             : 
     433             :    ! names of gases that are available in the model 
     434             :    ! -- needed for the kdist initialization routines 
     435        1536 :    type(ty_gas_concs) :: available_gases
     436             : 
     437             :    integer :: i, icall
     438             :    integer :: nstep                       ! current timestep number
     439             :    logical :: history_amwg                ! output the variables used by the AMWG diag package
     440             :    logical :: history_vdiag               ! output the variables used by the AMWG variability diag package
     441             :    logical :: history_budget              ! output tendencies and state variables for CAM4
     442             :                                           ! temperature, water vapor, cloud ice and cloud
     443             :                                           ! liquid budgets.
     444             :    integer :: history_budget_histfile_num ! history file number for budget fields
     445             :    integer :: ierr, istat
     446             : 
     447             :    integer :: dtime
     448             : 
     449             :    character(len=*), parameter :: sub = 'radiation_init'
     450             :    !-----------------------------------------------------------------------
     451             :    
     452             :    ! Number of layers in radiation calculation is capped by the number of
     453             :    ! pressure interfaces below 1 Pa.  When the entire model atmosphere is
     454             :    ! below 1 Pa then an extra layer is added to the top of the model for
     455             :    ! the purpose of the radiation calculation.
     456             : 
     457      145920 :    nlay = count( pref_edge(:) > 1._r8 ) ! pascals (0.01 mbar)
     458             : 
     459        1536 :    if (nlay == pverp) then
     460             :       ! Top model interface is below 1 Pa.  RRTMGP is active in all model layers plus
     461             :       ! 1 extra layer between model top and 1 Pa.
     462           0 :       ktopcam = 1
     463           0 :       ktoprad = 2
     464           0 :       nlaycam = pver
     465        1536 :    else if (nlay == (pverp-1)) then
     466             :       ! Special case nlay == (pverp-1) -- topmost interface outside bounds (CAM MT config), treat as if it is ok.
     467        1536 :       ktopcam = 1
     468        1536 :       ktoprad = 2
     469        1536 :       nlaycam = pver
     470        1536 :       nlay = nlay+1 ! reassign the value so later code understands to treat this case like nlay==pverp
     471        1536 :       write(iulog,*) 'RADIATION_INIT: Special case of 1 model interface at p < 1Pa. Top layer will be INCLUDED in radiation calculation.'
     472        1536 :       write(iulog,*) 'RADIATION_INIT: nlay = ',nlay, ' same as pverp: ',nlay==pverp
     473             :    else
     474             :       ! nlay < pverp.  nlay layers are used in radiation calcs, and they are
     475             :       ! all CAM layers.
     476           0 :       ktopcam = pver - nlay + 1
     477           0 :       ktoprad = 1
     478           0 :       nlaycam = nlay
     479             :    end if
     480             :    
     481             :    ! Create lowercase version of the gaslist for RRTMGP.  The ty_gas_concs objects
     482             :    ! work with CAM's uppercase names, but other objects that get input from the gas
     483             :    ! concs objects don't work.
     484       13824 :    do i = 1, nradgas
     485       13824 :       gaslist_lc(i) = to_lower(gaslist(i))
     486             :    end do
     487             : 
     488        1536 :    errmsg = available_gases%init(gaslist_lc)
     489        1536 :    call stop_on_err(errmsg, sub, 'available_gases%init')
     490             : 
     491             :    ! Read RRTMGP coefficients files and initialize kdist objects.
     492        1536 :    call coefs_init(coefs_sw_file, available_gases, kdist_sw)
     493        1536 :    call coefs_init(coefs_lw_file, available_gases, kdist_lw)
     494             : 
     495             :    ! Set the sw/lw band boundaries in radconstants.  Also sets
     496             :    ! indicies of specific bands for diagnostic output and COSP input.
     497        1536 :    call set_wavenumber_bands(kdist_sw, kdist_lw)
     498             : 
     499             :    ! The spectral band boundaries need to be set before this init is called.
     500        1536 :    call rrtmgp_inputs_init(ktopcam, ktoprad)
     501             : 
     502             :    ! initialize output fields for offline driver
     503        1536 :    call rad_data_init(pbuf2d)
     504             : 
     505        1536 :    call cloud_rad_props_init()
     506             :   
     507        1536 :    cld_idx      = pbuf_get_index('CLD')
     508        1536 :    cldfsnow_idx = pbuf_get_index('CLDFSNOW', errcode=ierr)
     509        1536 :    cldfgrau_idx = pbuf_get_index('CLDFGRAU', errcode=ierr)
     510             : 
     511        1536 :    if (is_first_step()) then
     512         768 :       call pbuf_set_field(pbuf2d, qrl_idx, 0._r8)
     513             :    end if
     514             : 
     515             :    ! Set the radiation timestep for cosz calculations if requested using
     516             :    ! the adjusted iradsw value from radiation
     517        1536 :    if (use_rad_dt_cosz)  then
     518           0 :       dtime  = get_step_size()
     519           0 :       dt_avg = iradsw*dtime
     520             :    end if
     521             : 
     522             :    ! Surface components to get radiation computed today
     523        1536 :    if (.not. is_first_restart_step()) then
     524         768 :       nextsw_cday = get_curr_calday()
     525             :    end if
     526             : 
     527             :    call phys_getopts(history_amwg_out   = history_amwg,    &
     528             :                      history_vdiag_out  = history_vdiag,   &
     529             :                      history_budget_out = history_budget,  &
     530        1536 :                      history_budget_histfile_num_out = history_budget_histfile_num)
     531             : 
     532             :    ! "irad_always" is number of time steps to execute radiation continuously from
     533             :    ! start of initial OR restart run
     534        1536 :    nstep = get_nstep()
     535        1536 :    if (irad_always > 0) then
     536           0 :       irad_always = irad_always + nstep
     537             :    end if
     538             : 
     539        1536 :    if (docosp) call cospsimulator_intr_init()
     540             : 
     541        4608 :    allocate(cosp_cnt(begchunk:endchunk), stat=istat)
     542        1536 :    call handle_allocate_error(istat, sub, 'cosp_cnt')
     543        1536 :    if (is_first_restart_step()) then
     544        3864 :       cosp_cnt(begchunk:endchunk) = cosp_cnt_init
     545             :    else
     546        3864 :       cosp_cnt(begchunk:endchunk) = 0     
     547             :    end if
     548             : 
     549             :    ! Add fields to history buffer
     550             : 
     551             :    call addfld('TOT_CLD_VISTAU',  (/ 'lev' /), 'A',   '1',             &
     552             :                'Total gbx cloud extinction visible sw optical depth',  &
     553        3072 :                sampling_seq='rad_lwsw', flag_xyfill=.true.)
     554             :    call addfld('TOT_ICLD_VISTAU', (/ 'lev' /), 'A',  '1',              &
     555             :                'Total in-cloud extinction visible sw optical depth',   &
     556        3072 :                sampling_seq='rad_lwsw', flag_xyfill=.true.)
     557             :    call addfld('LIQ_ICLD_VISTAU', (/ 'lev' /), 'A',  '1', &
     558             :                'Liquid in-cloud extinction visible sw optical depth',  &
     559        3072 :                sampling_seq='rad_lwsw', flag_xyfill=.true.)
     560             :    call addfld('ICE_ICLD_VISTAU', (/ 'lev' /), 'A',  '1',              &
     561             :                'Ice in-cloud extinction visible sw optical depth',     &
     562        3072 :                sampling_seq='rad_lwsw', flag_xyfill=.true.)
     563             : 
     564        1536 :    if (cldfsnow_idx > 0) then
     565             :       call addfld('SNOW_ICLD_VISTAU', (/ 'lev' /), 'A', '1',           &
     566             :                   'Snow in-cloud extinction visible sw optical depth', &
     567        3072 :                   sampling_seq='rad_lwsw', flag_xyfill=.true.)
     568             :    end if
     569        1536 :    if (cldfgrau_idx > 0 .and. graupel_in_rad) then
     570             :       call addfld('GRAU_ICLD_VISTAU', (/ 'lev' /), 'A', '1',           &
     571             :                   'Graupel in-cloud extinction visible sw optical depth', &
     572           0 :                   sampling_seq='rad_lwsw', flag_xyfill=.true.)
     573             :    endif
     574             : 
     575             :    ! get list of active radiation calls
     576        1536 :    call rad_cnst_get_call_list(active_calls)
     577             : 
     578             :    ! Add shortwave radiation fields to history master field list.
     579             : 
     580       18432 :    do icall = 0, N_DIAG
     581             : 
     582       18432 :       if (active_calls(icall)) then
     583             : 
     584             :          call addfld('SOLIN'//diag(icall),    horiz_only,   'A', 'W/m2', &
     585        1536 :                      'Solar insolation', sampling_seq='rad_lwsw')
     586             :          call addfld('QRS'//diag(icall),      (/ 'lev' /),  'A', 'K/s',  &
     587        3072 :                      'Solar heating rate', sampling_seq='rad_lwsw')
     588             :          call addfld('QRSC'//diag(icall),     (/ 'lev' /),  'A', 'K/s',  &
     589        3072 :                      'Clearsky solar heating rate', sampling_seq='rad_lwsw')
     590             :          call addfld('FSNT'//diag(icall),     horiz_only,   'A', 'W/m2', &
     591        1536 :                      'Net solar flux at top of model', sampling_seq='rad_lwsw')
     592             :          call addfld('FSNTC'//diag(icall),    horiz_only,   'A', 'W/m2', &
     593        1536 :                      'Clearsky net solar flux at top of model', sampling_seq='rad_lwsw')
     594             :          call addfld('FSNTOA'//diag(icall),   horiz_only,   'A', 'W/m2', &
     595        1536 :                      'Net solar flux at top of atmosphere', sampling_seq='rad_lwsw')
     596             :          call addfld('FSNTOAC'//diag(icall),  horiz_only,   'A', 'W/m2', &
     597        1536 :                      'Clearsky net solar flux at top of atmosphere', sampling_seq='rad_lwsw')
     598             :          call addfld('SWCF'//diag(icall),     horiz_only,   'A', 'W/m2', &
     599        1536 :                      'Shortwave cloud forcing', sampling_seq='rad_lwsw')
     600             :          call addfld('FSUTOA'//diag(icall),   horiz_only,   'A', 'W/m2', &
     601        1536 :                      'Upwelling solar flux at top of atmosphere', sampling_seq='rad_lwsw')
     602             :          call addfld('FSNIRTOA'//diag(icall), horiz_only,   'A', 'W/m2', &
     603        1536 :                      'Net near-infrared flux (Nimbus-7 WFOV) at top of atmosphere', sampling_seq='rad_lwsw')
     604             :          call addfld('FSNRTOAC'//diag(icall), horiz_only,   'A', 'W/m2', &
     605        1536 :                       'Clearsky net near-infrared flux (Nimbus-7 WFOV) at top of atmosphere', sampling_seq='rad_lwsw')
     606             :          call addfld('FSNRTOAS'//diag(icall), horiz_only,   'A', 'W/m2', &
     607        1536 :                      'Net near-infrared flux (>= 0.7 microns) at top of atmosphere', sampling_seq='rad_lwsw')
     608             :          call addfld('FSN200'//diag(icall),   horiz_only,   'A', 'W/m2', &
     609        1536 :                      'Net shortwave flux at 200 mb', sampling_seq='rad_lwsw')
     610             :          call addfld('FSN200C'//diag(icall),  horiz_only,   'A', 'W/m2', &
     611        1536 :                      'Clearsky net shortwave flux at 200 mb', sampling_seq='rad_lwsw')
     612             :          call addfld('FSNR'//diag(icall),     horiz_only,   'A', 'W/m2', &
     613        1536 :                      'Net solar flux at tropopause', sampling_seq='rad_lwsw')
     614             :          call addfld('SOLL'//diag(icall),     horiz_only,   'A', 'W/m2', &
     615        1536 :                      'Solar downward near infrared direct  to surface', sampling_seq='rad_lwsw')
     616             :          call addfld('SOLS'//diag(icall),     horiz_only,   'A', 'W/m2', &
     617        1536 :                      'Solar downward visible direct  to surface', sampling_seq='rad_lwsw')
     618             :          call addfld('SOLLD'//diag(icall),    horiz_only,   'A', 'W/m2', &
     619        1536 :                      'Solar downward near infrared diffuse to surface', sampling_seq='rad_lwsw')
     620             :          call addfld('SOLSD'//diag(icall),    horiz_only,   'A', 'W/m2', &
     621        1536 :                      'Solar downward visible diffuse to surface', sampling_seq='rad_lwsw')
     622             :          call addfld('FSNS'//diag(icall),     horiz_only,   'A', 'W/m2', &
     623        1536 :                      'Net solar flux at surface', sampling_seq='rad_lwsw')
     624             :          call addfld('FSNSC'//diag(icall),    horiz_only,   'A', 'W/m2', &
     625        1536 :                      'Clearsky net solar flux at surface', sampling_seq='rad_lwsw')
     626             :          call addfld('FSDS'//diag(icall),     horiz_only,   'A', 'W/m2', &
     627        1536 :                      'Downwelling solar flux at surface', sampling_seq='rad_lwsw')
     628             :          call addfld('FSDSC'//diag(icall),    horiz_only,   'A', 'W/m2', &
     629        1536 :                      'Clearsky downwelling solar flux at surface', sampling_seq='rad_lwsw')
     630             : 
     631             :          ! Fluxes on CAM grid
     632             :          call addfld('FUS'//diag(icall),      (/ 'ilev' /), 'I', 'W/m2', &
     633        3072 :                      'Shortwave upward flux', sampling_seq='rad_lwsw')
     634             :          call addfld('FDS'//diag(icall),      (/ 'ilev' /), 'I', 'W/m2', &
     635        3072 :                      'Shortwave downward flux', sampling_seq='rad_lwsw')
     636             :          call addfld('FUSC'//diag(icall),     (/ 'ilev' /), 'I', 'W/m2', &
     637        3072 :                      'Shortwave clear-sky upward flux', sampling_seq='rad_lwsw')
     638             :          call addfld('FDSC'//diag(icall),     (/ 'ilev' /), 'I', 'W/m2', &
     639        3072 :                      'Shortwave clear-sky downward flux', sampling_seq='rad_lwsw')
     640             : 
     641        1536 :          if (history_amwg) then
     642        1536 :             call add_default('SOLIN'//diag(icall),   1, ' ')
     643        1536 :             call add_default('QRS'//diag(icall),     1, ' ')
     644        1536 :             call add_default('FSNT'//diag(icall),    1, ' ')
     645        1536 :             call add_default('FSNTC'//diag(icall),   1, ' ')
     646        1536 :             call add_default('FSNTOA'//diag(icall),  1, ' ')
     647        1536 :             call add_default('FSNTOAC'//diag(icall), 1, ' ')
     648        1536 :             call add_default('SWCF'//diag(icall),    1, ' ')
     649        1536 :             call add_default('FSNS'//diag(icall),    1, ' ')
     650        1536 :             call add_default('FSNSC'//diag(icall),   1, ' ')
     651        1536 :             call add_default('FSUTOA'//diag(icall),  1, ' ')
     652        1536 :             call add_default('FSDSC'//diag(icall),   1, ' ')
     653        1536 :             call add_default('FSDS'//diag(icall),    1, ' ')
     654             :          endif
     655             : 
     656             :       end if
     657             :    end do
     658             : 
     659        1536 :    if (scm_crm_mode) then
     660           0 :       call add_default('FUS     ', 1, ' ')
     661           0 :       call add_default('FUSC    ', 1, ' ')
     662           0 :       call add_default('FDS     ', 1, ' ')
     663           0 :       call add_default('FDSC    ', 1, ' ')
     664             :    endif
     665             : 
     666             :    ! Add longwave radiation fields to history master field list.
     667             : 
     668       18432 :    do icall = 0, N_DIAG
     669             : 
     670       18432 :       if (active_calls(icall)) then
     671             :          call addfld('QRL'//diag(icall),     (/ 'lev' /), 'A', 'K/s',  &
     672        3072 :                      'Longwave heating rate', sampling_seq='rad_lwsw')
     673             :          call addfld('QRLC'//diag(icall),    (/ 'lev' /), 'A', 'K/s',  &
     674        3072 :                      'Clearsky longwave heating rate', sampling_seq='rad_lwsw')
     675             :          call addfld('FLNT'//diag(icall),    horiz_only,  'A', 'W/m2', &
     676        1536 :                      'Net longwave flux at top of model', sampling_seq='rad_lwsw')
     677             :          call addfld('FLNTC'//diag(icall),   horiz_only,  'A', 'W/m2', &
     678        1536 :                      'Clearsky net longwave flux at top of model', sampling_seq='rad_lwsw')
     679             :          call addfld('FLUT'//diag(icall),    horiz_only,  'A', 'W/m2', &
     680        1536 :                      'Upwelling longwave flux at top of model', sampling_seq='rad_lwsw')
     681             :          call addfld('FLUTC'//diag(icall),   horiz_only,  'A', 'W/m2', &
     682        1536 :                      'Clearsky upwelling longwave flux at top of model', sampling_seq='rad_lwsw')
     683             :          call addfld('LWCF'//diag(icall),    horiz_only,  'A', 'W/m2', &
     684        1536 :                      'Longwave cloud forcing', sampling_seq='rad_lwsw')
     685             :          call addfld('FLN200'//diag(icall),  horiz_only,  'A', 'W/m2', &
     686        1536 :                      'Net longwave flux at 200 mb', sampling_seq='rad_lwsw')
     687             :          call addfld('FLN200C'//diag(icall), horiz_only,  'A', 'W/m2', &
     688        1536 :                      'Clearsky net longwave flux at 200 mb', sampling_seq='rad_lwsw')
     689             :          call addfld('FLNR'//diag(icall),    horiz_only,  'A', 'W/m2', &
     690        1536 :                      'Net longwave flux at tropopause', sampling_seq='rad_lwsw')
     691             :          call addfld('FLNS'//diag(icall),    horiz_only,  'A', 'W/m2', &
     692        1536 :                      'Net longwave flux at surface', sampling_seq='rad_lwsw')
     693             :          call addfld('FLNSC'//diag(icall),   horiz_only,  'A', 'W/m2', &
     694        1536 :                      'Clearsky net longwave flux at surface', sampling_seq='rad_lwsw')
     695             :          call addfld('FLDS'//diag(icall),    horiz_only,  'A', 'W/m2', &
     696        1536 :                      'Downwelling longwave flux at surface', sampling_seq='rad_lwsw')
     697             :          call addfld('FLDSC'//diag(icall),   horiz_only,  'A', 'W/m2', &
     698        1536 :                      'Clearsky Downwelling longwave flux at surface', sampling_seq='rad_lwsw')
     699             : 
     700             :          ! Fluxes on CAM grid
     701             :          call addfld('FUL'//diag(icall),    (/ 'ilev' /), 'I', 'W/m2', &
     702        3072 :                      'Longwave upward flux', sampling_seq='rad_lwsw')
     703             :          call addfld('FDL'//diag(icall),    (/ 'ilev' /), 'I', 'W/m2', &
     704        3072 :                      'Longwave downward flux', sampling_seq='rad_lwsw')
     705             :          call addfld('FULC'//diag(icall),   (/ 'ilev' /), 'I', 'W/m2', &
     706        3072 :                      'Longwave clear-sky upward flux', sampling_seq='rad_lwsw')
     707             :          call addfld('FDLC'//diag(icall),   (/ 'ilev' /), 'I', 'W/m2', &
     708        3072 :                      'Longwave clear-sky downward flux', sampling_seq='rad_lwsw')
     709             : 
     710        1536 :          if (history_amwg) then
     711        1536 :             call add_default('QRL'//diag(icall),   1, ' ')
     712        1536 :             call add_default('FLNT'//diag(icall),  1, ' ')
     713        1536 :             call add_default('FLNTC'//diag(icall), 1, ' ')
     714        1536 :             call add_default('FLUT'//diag(icall),  1, ' ')
     715        1536 :             call add_default('FLUTC'//diag(icall), 1, ' ')
     716        1536 :             call add_default('LWCF'//diag(icall),  1, ' ')
     717        1536 :             call add_default('FLNS'//diag(icall),  1, ' ')
     718        1536 :             call add_default('FLNSC'//diag(icall), 1, ' ')
     719        1536 :             call add_default('FLDS'//diag(icall),  1, ' ')
     720             :          end if
     721             : 
     722             :       end if
     723             :    end do
     724             : 
     725        3072 :    call addfld('EMIS', (/ 'lev' /), 'A', '1', 'Cloud longwave emissivity')
     726             : 
     727        1536 :    if (scm_crm_mode) then
     728           0 :       call add_default ('FUL     ', 1, ' ')
     729           0 :       call add_default ('FULC    ', 1, ' ')
     730           0 :       call add_default ('FDL     ', 1, ' ')
     731           0 :       call add_default ('FDLC    ', 1, ' ')
     732             :    endif
     733             : 
     734             :    ! Heating rate needed for d(theta)/dt computation
     735        3072 :    call addfld ('HR',(/ 'lev' /), 'A','K/s','Heating rate needed for d(theta)/dt computation')
     736             : 
     737        1536 :    if ( history_budget .and. history_budget_histfile_num > 1 ) then
     738           0 :       call add_default ('QRL     ', history_budget_histfile_num, ' ')
     739           0 :       call add_default ('QRS     ', history_budget_histfile_num, ' ')
     740             :    end if
     741             : 
     742        1536 :    if (history_vdiag) then
     743           0 :       call add_default('FLUT', 2, ' ')
     744           0 :       call add_default('FLUT', 3, ' ')
     745             :    end if
     746             :    
     747        3072 : end subroutine radiation_init
     748             : 
     749             : !===============================================================================
     750             : 
     751        1536 : subroutine radiation_define_restart(file)
     752             : 
     753             :    ! define variables to be written to restart file
     754             : 
     755             :    ! arguments
     756             :    type(file_desc_t), intent(inout) :: file
     757             : 
     758             :    ! local variables
     759             :    integer :: ierr
     760             :    !----------------------------------------------------------------------------
     761             : 
     762        1536 :    call pio_seterrorhandling(file, PIO_BCAST_ERROR)
     763             : 
     764        1536 :    ierr = pio_def_var(file, 'nextsw_cday', pio_double, nextsw_cday_desc)
     765        1536 :    ierr = pio_put_att(file, nextsw_cday_desc, 'long_name', 'future radiation calday for surface models')
     766        1536 :    if (docosp) then
     767           0 :       ierr = pio_def_var(File, 'cosp_cnt_init', pio_int, cospcnt_desc)
     768             :    end if
     769             : 
     770        1536 : end subroutine radiation_define_restart
     771             :   
     772             : !===============================================================================
     773             : 
     774        1536 : subroutine radiation_write_restart(file)
     775             : 
     776             :    ! write variables to restart file
     777             : 
     778             :    ! arguments
     779             :    type(file_desc_t), intent(inout) :: file
     780             : 
     781             :    ! local variables
     782             :    integer :: ierr
     783             :    !----------------------------------------------------------------------------
     784        3072 :    ierr = pio_put_var(File, nextsw_cday_desc, (/ nextsw_cday /))
     785        1536 :    if (docosp) then
     786           0 :       ierr = pio_put_var(File, cospcnt_desc, (/cosp_cnt(begchunk)/))
     787             :    end if
     788             : 
     789        1536 : end subroutine radiation_write_restart
     790             :   
     791             : !===============================================================================
     792             : 
     793         768 : subroutine radiation_read_restart(file)
     794             : 
     795             :    ! read variables from restart file
     796             : 
     797             :    ! arguments
     798             :    type(file_desc_t), intent(inout) :: file
     799             : 
     800             :    ! local variables
     801             :    integer :: ierr
     802             :    type(var_desc_t) :: vardesc
     803             :    integer :: err_handling
     804             : 
     805             :    !----------------------------------------------------------------------------
     806         768 :    if (docosp) then
     807           0 :       call pio_seterrorhandling(File, PIO_BCAST_ERROR, err_handling)
     808           0 :       ierr = pio_inq_varid(File, 'cosp_cnt_init', vardesc)
     809           0 :       call pio_seterrorhandling(File, err_handling)
     810           0 :       if (ierr /= PIO_NOERR) then
     811           0 :          cosp_cnt_init = 0
     812             :       else
     813           0 :          ierr = pio_get_var(File, vardesc, cosp_cnt_init)
     814             :       end if
     815             :    end if
     816             : 
     817         768 :    ierr = pio_inq_varid(file, 'nextsw_cday', vardesc)
     818         768 :    ierr = pio_get_var(file, vardesc, nextsw_cday)
     819             : 
     820             : 
     821         768 : end subroutine radiation_read_restart
     822             :   
     823             : !===============================================================================
     824             : 
     825    62675424 : subroutine radiation_tend( &
     826             :    state, ptend, pbuf, cam_out, cam_in, net_flx, rd_out)
     827             : 
     828             :    !----------------------------------------------------------------------- 
     829             :    ! 
     830             :    ! CAM driver for radiation computation.
     831             :    ! 
     832             :    !-----------------------------------------------------------------------
     833             : 
     834             :    ! Location/Orbital Parameters for cosine zenith angle
     835             :    use phys_grid,          only: get_rlat_all_p, get_rlon_all_p
     836             :    use cam_control_mod,    only: eccen, mvelpp, lambm0, obliqr
     837             :    use shr_orb_mod,        only: shr_orb_decl, shr_orb_cosz
     838             : 
     839             :    use rrtmgp_inputs,      only: rrtmgp_set_state, rrtmgp_set_gases_lw, rrtmgp_set_cloud_lw, &
     840             :                                  rrtmgp_set_aer_lw, rrtmgp_set_gases_sw, rrtmgp_set_cloud_sw, &
     841             :                                  rrtmgp_set_aer_sw
     842             : 
     843             :    ! RRTMGP drivers for flux calculations.
     844             :    use mo_rte_lw,          only: rte_lw
     845             :    use mo_rte_sw,          only: rte_sw
     846             : 
     847             :    use radheat,            only: radheat_tend
     848             : 
     849             :    use radiation_data,     only: rad_data_write
     850             : 
     851             :    use interpolate_data,   only: vertinterp
     852             :    use tropopause,         only: tropopause_find_cam, TROP_ALG_HYBSTOB, TROP_ALG_CLIMATE
     853             :    use cospsimulator_intr, only: docosp, cospsimulator_intr_run, cosp_nradsteps
     854             : 
     855             : 
     856             :    ! Arguments
     857             :    type(physics_state), intent(in), target :: state
     858             :    type(physics_ptend), intent(out)        :: ptend
     859             :    type(physics_buffer_desc), pointer      :: pbuf(:)
     860             :    type(cam_out_t),     intent(inout)      :: cam_out
     861             :    type(cam_in_t),      intent(in)         :: cam_in
     862             :    real(r8),            intent(out)        :: net_flx(pcols)
     863             : 
     864             :    type(rad_out_t), target, optional, intent(out) :: rd_out
     865             : 
     866             : 
     867             :    ! Local variables
     868             :    type(rad_out_t), pointer :: rd  ! allow rd_out to be optional by allocating a local object
     869             :                                    ! if the argument is not present
     870             :    logical  :: write_output
     871             :   
     872             :    integer  :: i, k, istat
     873             :    integer  :: lchnk, ncol
     874             :    logical  :: dosw, dolw
     875             :    integer  :: icall           ! loop index for climate/diagnostic radiation calls
     876             : 
     877             :    real(r8) :: calday          ! current calendar day
     878             :    real(r8) :: delta           ! Solar declination angle  in radians
     879             :    real(r8) :: eccf            ! Earth orbit eccentricity factor
     880             :    real(r8) :: clat(pcols)     ! current latitudes(radians)
     881             :    real(r8) :: clon(pcols)     ! current longitudes(radians)
     882             :    real(r8) :: coszrs(pcols)   ! Cosine solar zenith angle
     883             : 
     884             :    ! Gathered indices of day and night columns 
     885             :    !  chunk_column_index = IdxDay(daylight_column_index)
     886             :    integer :: Nday           ! Number of daylight columns
     887             :    integer :: Nnite          ! Number of night columns
     888             :    integer :: IdxDay(pcols)  ! chunk indices of daylight columns
     889             :    integer :: IdxNite(pcols) ! chunk indices of night columns
     890             : 
     891             :    integer :: itim_old
     892             : 
     893     1492272 :    real(r8), pointer :: cld(:,:)      ! cloud fraction
     894     1492272 :    real(r8), pointer :: cldfsnow(:,:) ! cloud fraction of just "snow clouds"
     895     1492272 :    real(r8), pointer :: cldfgrau(:,:) ! cloud fraction of just "graupel clouds"
     896             :    real(r8)          :: cldfprime(pcols,pver)   ! combined cloud fraction
     897     1492272 :    real(r8), pointer :: qrs(:,:) ! shortwave radiative heating rate 
     898     1492272 :    real(r8), pointer :: qrl(:,:) ! longwave  radiative heating rate 
     899     1492272 :    real(r8), pointer :: fsds(:)  ! Surface solar down flux
     900     1492272 :    real(r8), pointer :: fsns(:)  ! Surface solar absorbed flux
     901     1492272 :    real(r8), pointer :: fsnt(:)  ! Net column abs solar flux at model top
     902     1492272 :    real(r8), pointer :: flns(:)  ! Srf longwave cooling (up-down) flux
     903     1492272 :    real(r8), pointer :: flnt(:)  ! Net outgoing lw flux at model top
     904             : 
     905             :    real(r8), pointer, dimension(:,:,:) :: su => NULL()  ! shortwave spectral flux up
     906             :    real(r8), pointer, dimension(:,:,:) :: sd => NULL()  ! shortwave spectral flux down
     907             :    real(r8), pointer, dimension(:,:,:) :: lu => NULL()  ! longwave  spectral flux up
     908             :    real(r8), pointer, dimension(:,:,:) :: ld => NULL()  ! longwave  spectral flux down
     909             : 
     910             :    ! tropopause diagnostic
     911             :    integer  :: troplev(pcols)
     912             :    real(r8) :: p_trop(pcols)
     913             : 
     914             :    ! state data passed to radiation calc
     915     1492272 :    real(r8), allocatable :: t_sfc(:)
     916     1492272 :    real(r8), allocatable :: emis_sfc(:,:)
     917     1492272 :    real(r8), allocatable :: t_rad(:,:)
     918     1492272 :    real(r8), allocatable :: pmid_rad(:,:)
     919     1492272 :    real(r8), allocatable :: pint_rad(:,:)
     920     1492272 :    real(r8), allocatable :: t_day(:,:)
     921     1492272 :    real(r8), allocatable :: pmid_day(:,:)
     922     1492272 :    real(r8), allocatable :: pint_day(:,:)
     923     1492272 :    real(r8), allocatable :: coszrs_day(:)
     924     1492272 :    real(r8), allocatable :: alb_dir(:,:)
     925     1492272 :    real(r8), allocatable :: alb_dif(:,:)
     926             : 
     927             :    ! in-cloud optical depths for COSP
     928             :    real(r8) :: cld_tau_cloudsim(pcols,pver)    ! liq + ice
     929             :    real(r8) :: snow_tau_cloudsim(pcols,pver)   ! snow
     930             :    real(r8) :: grau_tau_cloudsim(pcols,pver)   ! graupel
     931             :    real(r8) :: cld_lw_abs_cloudsim(pcols,pver) ! liq + ice
     932             :    real(r8) :: snow_lw_abs_cloudsim(pcols,pver)! snow
     933             :    real(r8) :: grau_lw_abs_cloudsim(pcols,pver)! graupel
     934             : 
     935             :    ! Set vertical indexing in RRTMGP to be the same as CAM (top to bottom).
     936             :    logical, parameter :: top_at_1 = .true.
     937             : 
     938             :    ! TOA solar flux on RRTMGP g-points
     939     1492272 :    real(r8), allocatable :: toa_flux(:,:)
     940             :    ! TSI from RRTMGP data (from sum over g-point representation)
     941             :    real(r8) :: tsi_ref
     942             :    
     943             :    ! Planck sources for LW.
     944     1492272 :    type(ty_source_func_lw) :: sources_lw
     945             : 
     946             :    ! Gas volume mixing ratios.  Use separate objects for LW and SW because SW only does
     947             :    ! calculations for daylight columns.
     948             :    ! These objects have a final method which deallocates the internal memory when they
     949             :    ! go out of scope (i.e., when radiation_tend returns), so no need for explicit deallocation.
     950     1492272 :    type(ty_gas_concs) :: gas_concs_lw
     951     1492272 :    type(ty_gas_concs) :: gas_concs_sw
     952             : 
     953             :    ! Atmosphere optics.  This object is initialized with gas optics, then is incremented
     954             :    ! by the aerosol optics for the clear-sky radiative flux calculations, and then
     955             :    ! incremented again by the cloud optics for the all-sky radiative flux calculations.
     956     1492272 :    type(ty_optical_props_1scl) :: atm_optics_lw
     957     1492272 :    type(ty_optical_props_2str) :: atm_optics_sw
     958             : 
     959             :    ! Cloud optical properties objects (McICA sampling of cloud optical properties).
     960     1492272 :    type(ty_optical_props_1scl) :: cloud_lw
     961     1492272 :    type(ty_optical_props_2str) :: cloud_sw
     962             : 
     963             :    ! Aerosol optical properties objects.
     964     1492272 :    type(ty_optical_props_1scl) :: aer_lw
     965     1492272 :    type(ty_optical_props_2str) :: aer_sw
     966             : 
     967             :    ! Flux objects contain all fluxes computed by RRTMGP.
     968             :    ! SW allsky fluxes always include spectrally resolved fluxes needed for surface models.
     969             :    type(ty_fluxes_byband) :: fsw
     970             :    ! LW allsky fluxes only need spectrally resolved fluxes when spectralflux=.true.
     971             :    type(ty_fluxes_byband) :: flw
     972             :    ! Only broadband fluxes needed for clear sky (diagnostics).
     973             :    type(ty_fluxes_broadband) :: fswc, flwc
     974             : 
     975             :    ! Arrays for output diagnostics on CAM grid.
     976             :    real(r8) :: fns(pcols,pverp)     ! net shortwave flux
     977             :    real(r8) :: fcns(pcols,pverp)    ! net clear-sky shortwave flux
     978             :    real(r8) :: fnl(pcols,pverp)     ! net longwave flux
     979             :    real(r8) :: fcnl(pcols,pverp)    ! net clear-sky longwave flux
     980             : 
     981             :    ! for COSP
     982             :    real(r8) :: emis(pcols,pver)        ! Cloud longwave emissivity
     983             :    real(r8) :: gb_snow_tau(pcols,pver) ! grid-box mean snow_tau
     984             :    real(r8) :: gb_snow_lw(pcols,pver)  ! grid-box mean LW snow optical depth
     985             : 
     986             :    real(r8) :: ftem(pcols,pver)        ! Temporary workspace for outfld variables
     987             : 
     988             :    character(len=128) :: errmsg
     989             :    character(len=*), parameter :: sub = 'radiation_tend'
     990             :    !--------------------------------------------------------------------------------------
     991             : 
     992     1492272 :    lchnk = state%lchnk
     993     1492272 :    ncol = state%ncol
     994             : 
     995     1492272 :    if (present(rd_out)) then
     996           0 :       rd => rd_out
     997           0 :       write_output = .false.
     998             :    else
     999     1492272 :       allocate(rd, stat=istat)
    1000     1492272 :       call handle_allocate_error(istat, sub, 'rd')
    1001     1492272 :       write_output = .true.
    1002             :    end if
    1003             : 
    1004     1492272 :    dosw = radiation_do('sw', get_nstep())      ! do shortwave radiation calc this timestep?
    1005     1492272 :    dolw = radiation_do('lw', get_nstep())      ! do longwave radiation calc this timestep?
    1006             : 
    1007             :    ! Cosine solar zenith angle for current time step
    1008     1492272 :    calday = get_curr_calday()
    1009     1492272 :    call get_rlat_all_p(lchnk, ncol, clat)
    1010     1492272 :    call get_rlon_all_p(lchnk, ncol, clon)
    1011             : 
    1012             :    call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, &
    1013     1492272 :                      delta, eccf)
    1014             : 
    1015     1492272 :    if (use_rad_uniform_angle) then
    1016           0 :       do i = 1, ncol
    1017           0 :          coszrs(i) = shr_orb_cosz(calday, clat(i), clon(i), delta, dt_avg, &
    1018           0 :                                   uniform_angle=rad_uniform_angle)
    1019             :       end do
    1020             :    else
    1021    24917472 :       do i = 1, ncol
    1022             :          ! if dt_avg /= 0, it triggers using avg coszrs
    1023    24917472 :          coszrs(i) = shr_orb_cosz(calday, clat(i), clon(i), delta, dt_avg)
    1024             :       end do
    1025             :    end if
    1026             : 
    1027             :    ! Gather night/day column indices.
    1028     1492272 :    Nday = 0
    1029     1492272 :    Nnite = 0
    1030    24917472 :    do i = 1, ncol
    1031    24917472 :       if ( coszrs(i) > 0.0_r8 ) then
    1032    11712600 :          Nday = Nday + 1
    1033    11712600 :          IdxDay(Nday) = i
    1034             :       else
    1035    11712600 :          Nnite = Nnite + 1
    1036    11712600 :          IdxNite(Nnite) = i
    1037             :       end if
    1038             :    end do
    1039             : 
    1040             :    ! Associate pointers to physics buffer fields
    1041     1492272 :    itim_old = pbuf_old_tim_idx()
    1042     1492272 :    nullify(cldfsnow)
    1043     1492272 :    if (cldfsnow_idx > 0) then
    1044     5969088 :       call pbuf_get_field(pbuf, cldfsnow_idx, cldfsnow, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
    1045             :    end if
    1046     1492272 :    nullify(cldfgrau)
    1047     1492272 :    if (cldfgrau_idx > 0 .and. graupel_in_rad) then
    1048           0 :       call pbuf_get_field(pbuf, cldfgrau_idx, cldfgrau, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
    1049             :    endif
    1050             : 
    1051     5969088 :    call pbuf_get_field(pbuf, cld_idx, cld, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
    1052             : 
    1053     1492272 :    call pbuf_get_field(pbuf, qrs_idx, qrs)
    1054     1492272 :    call pbuf_get_field(pbuf, qrl_idx, qrl)
    1055             : 
    1056     1492272 :    call pbuf_get_field(pbuf, fsns_idx, fsns)
    1057     1492272 :    call pbuf_get_field(pbuf, fsnt_idx, fsnt)
    1058     1492272 :    call pbuf_get_field(pbuf, fsds_idx, fsds)
    1059     1492272 :    call pbuf_get_field(pbuf, flns_idx, flns)
    1060     1492272 :    call pbuf_get_field(pbuf, flnt_idx, flnt)
    1061             : 
    1062     1492272 :    if (spectralflux) then
    1063           0 :       call pbuf_get_field(pbuf, su_idx, su)
    1064           0 :       call pbuf_get_field(pbuf, sd_idx, sd)
    1065           0 :       call pbuf_get_field(pbuf, lu_idx, lu)
    1066           0 :       call pbuf_get_field(pbuf, ld_idx, ld)
    1067             :    end if
    1068             : 
    1069             :    ! Allocate the flux arrays and init to zero.
    1070     1492272 :    call initialize_rrtmgp_fluxes(nday, nlay+1, nswbands, fsw, do_direct=.true.)
    1071     1492272 :    call initialize_rrtmgp_fluxes(nday, nlay+1, nswbands, fswc, do_direct=.true.)
    1072     1492272 :    call initialize_rrtmgp_fluxes(ncol, nlay+1, nlwbands, flw)
    1073     1492272 :    call initialize_rrtmgp_fluxes(ncol, nlay+1, nlwbands, flwc)
    1074             : 
    1075             :    !  For CRM, make cloud equal to input observations:
    1076     1492272 :    if (scm_crm_mode .and. have_cld) then
    1077           0 :       do k = 1, pver
    1078           0 :          cld(:ncol,k)= cldobs(k)
    1079             :       end do
    1080             :    end if
    1081             : 
    1082             :    ! Find tropopause height if needed for diagnostic output
    1083     1492272 :    if (hist_fld_active('FSNR') .or. hist_fld_active('FLNR')) then
    1084             :       !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists
    1085           0 :       troplev(:) = 0
    1086           0 :       p_trop(:) = 0._r8
    1087             :       !REMOVECAM_END
    1088             :       call tropopause_find_cam(state, troplev, tropP=p_trop, primary=TROP_ALG_HYBSTOB, &
    1089           0 :                            backup=TROP_ALG_CLIMATE)
    1090             :    end if
    1091             : 
    1092             :    ! Get time of next radiation calculation - albedos will need to be
    1093             :    ! calculated by each surface model at this time
    1094     1492272 :    nextsw_cday = radiation_nextsw_cday()
    1095             : 
    1096     1492272 :    if (dosw .or. dolw) then
    1097             : 
    1098             :       allocate( &
    1099             :          t_sfc(ncol), emis_sfc(nlwbands,ncol), toa_flux(nday,nswgpts),     &
    1100             :          t_rad(ncol,nlay), pmid_rad(ncol,nlay), pint_rad(ncol,nlay+1),     &
    1101             :          t_day(nday,nlay), pmid_day(nday,nlay), pint_day(nday,nlay+1),     &
    1102             :          coszrs_day(nday), alb_dir(nswbands,nday), alb_dif(nswbands,nday), &
    1103    19139833 :          stat=istat)
    1104      746136 :       call handle_allocate_error(istat, sub, 't_sfc,..,alb_dif')
    1105             : 
    1106             :       ! Prepares state variables, daylit columns, albedos for RRTMGP
    1107             :       call rrtmgp_set_state( &
    1108             :          state, cam_in, ncol, nlay, nday,             &
    1109             :          idxday, coszrs, kdist_sw, t_sfc, emis_sfc,   &
    1110             :          t_rad, pmid_rad, pint_rad, t_day, pmid_day,  &
    1111      746136 :          pint_day, coszrs_day, alb_dir, alb_dif)
    1112             : 
    1113             :       ! Output the mass per layer, and total column burdens for gas and aerosol
    1114             :       ! constituents in the climate list.
    1115      746136 :       call rad_cnst_out(0, state, pbuf)
    1116             : 
    1117             :       ! Modified cloud fraction accounts for radiatively active snow and/or graupel
    1118      746136 :       call modified_cloud_fraction(ncol, cld, cldfsnow, cldfgrau, cldfprime)
    1119             : 
    1120             :       !========================!
    1121             :       ! SHORTWAVE calculations !
    1122             :       !========================!
    1123             : 
    1124      746136 :       if (dosw) then
    1125             : 
    1126             :          ! Set cloud optical properties in cloud_sw object.
    1127             :          call rrtmgp_set_cloud_sw( &
    1128             :             state, pbuf, nlay, nday, idxday,                              &
    1129             :             nnite, idxnite, pmid_day, cld, cldfsnow,                      &
    1130             :             cldfgrau, cldfprime, graupel_in_rad, kdist_sw, cloud_sw,      &
    1131             :             rd%tot_cld_vistau, rd%tot_icld_vistau, rd%liq_icld_vistau,    &
    1132             :             rd%ice_icld_vistau, rd%snow_icld_vistau, rd%grau_icld_vistau, &
    1133      746136 :             cld_tau_cloudsim, snow_tau_cloudsim, grau_tau_cloudsim )
    1134             : 
    1135      746136 :          if (write_output) then
    1136      746136 :             call radiation_output_cld(lchnk, rd)
    1137             :          end if
    1138             : 
    1139             :          ! If no daylight columns, can't create empty RRTMGP objects
    1140      746136 :          if (nday > 0) then
    1141             : 
    1142             :             ! Initialize object for gas concentrations.
    1143      389263 :             errmsg = gas_concs_sw%init(gaslist_lc)
    1144      389263 :             call stop_on_err(errmsg, sub, 'gas_concs_sw%init')
    1145             : 
    1146             :             ! Initialize object for combined gas + aerosol + cloud optics.
    1147             :             ! Allocates arrays for properties represented on g-points.
    1148      389263 :             errmsg = atm_optics_sw%alloc_2str(nday, nlay, kdist_sw)
    1149      389263 :             call stop_on_err(errmsg, sub, 'atm_optics_sw%alloc_2str')
    1150             : 
    1151             :             ! Initialize object for SW aerosol optics.  Allocates arrays 
    1152             :             ! for properties represented by band.
    1153      389263 :             errmsg = aer_sw%alloc_2str(nday, nlay, kdist_sw%get_band_lims_wavenumber()) 
    1154      389263 :             call stop_on_err(errmsg, sub, 'aer_sw%alloc_2str')
    1155             : 
    1156             :          end if
    1157             : 
    1158             :          ! The climate (icall==0) calculation must occur last.
    1159     8953632 :          do icall = N_DIAG, 0, -1
    1160     8953632 :             if (active_calls(icall)) then
    1161             : 
    1162      746136 :                if (nday > 0) then
    1163             : 
    1164             :                   ! Set gas volume mixing ratios for this call in gas_concs_sw.
    1165             :                   call rrtmgp_set_gases_sw( &
    1166             :                      icall, state, pbuf, nlay, nday, &
    1167      389263 :                      idxday, gas_concs_sw)
    1168             : 
    1169             :                   ! Compute the gas optics (stored in atm_optics_sw).
    1170             :                   ! toa_flux is the reference solar source from RRTMGP data.
    1171             :                   errmsg = kdist_sw%gas_optics( &
    1172             :                      pmid_day, pint_day, t_day, gas_concs_sw, atm_optics_sw, &
    1173      389263 :                      toa_flux)
    1174      389263 :                   call stop_on_err(errmsg, sub, 'kdist_sw%gas_optics')
    1175             : 
    1176             :                   ! Scale the solar source
    1177    43986719 :                   tsi_ref = sum(toa_flux(1,:))
    1178   699892319 :                   toa_flux = toa_flux * sol_tsi * eccf / tsi_ref
    1179             : 
    1180             :                end if
    1181             : 
    1182             :                ! Set SW aerosol optical properties in the aer_sw object.
    1183             :                ! This call made even when no daylight columns because it does some
    1184             :                ! diagnostic aerosol output.
    1185             :                call rrtmgp_set_aer_sw( &
    1186      746136 :                   icall, state, pbuf, nday, idxday, nnite, idxnite, aer_sw)
    1187             :                   
    1188      746136 :                if (nday > 0) then
    1189             : 
    1190             :                   ! Increment the gas optics (in atm_optics_sw) by the aerosol optics in aer_sw.
    1191      389263 :                   errmsg = aer_sw%increment(atm_optics_sw)
    1192      389263 :                   call stop_on_err(errmsg, sub, 'aer_sw%increment')
    1193             : 
    1194             :                   ! Compute clear-sky fluxes.
    1195             :                   errmsg = rte_sw(&
    1196             :                      atm_optics_sw, top_at_1, coszrs_day, toa_flux, &
    1197      389263 :                      alb_dir, alb_dif, fswc)
    1198      389263 :                   call stop_on_err(errmsg, sub, 'clear-sky rte_sw')
    1199             : 
    1200             :                   ! Increment the aerosol+gas optics (in atm_optics_sw) by the cloud optics in cloud_sw.
    1201      389263 :                   errmsg = cloud_sw%increment(atm_optics_sw)
    1202      389263 :                   call stop_on_err(errmsg, sub, 'cloud_sw%increment')
    1203             : 
    1204             :                   ! Compute all-sky fluxes.
    1205             :                   errmsg = rte_sw(&
    1206             :                      atm_optics_sw, top_at_1, coszrs_day, toa_flux, &
    1207      389263 :                      alb_dir, alb_dif, fsw)
    1208      389263 :                   call stop_on_err(errmsg, sub, 'all-sky rte_sw')
    1209             : 
    1210             :                end if
    1211             : 
    1212             :                ! Transform RRTMGP outputs to CAM outputs and compute heating rates.
    1213      746136 :                call set_sw_diags()
    1214             : 
    1215      746136 :                if (write_output) then
    1216      746136 :                   call radiation_output_sw(lchnk, ncol, icall, rd, pbuf, cam_out)
    1217             :                end if
    1218             : 
    1219             :             end if ! (active_calls(icall))
    1220             :          end do    ! loop over diagnostic calcs (icall)
    1221             :          
    1222             :       else
    1223             :          ! SW calc not done.  pbuf carries Q*dp across timesteps.
    1224             :          ! Convert to Q before calling radheat_tend.
    1225           0 :          qrs(:ncol,:) = qrs(:ncol,:) / state%pdel(:ncol,:)
    1226             :       end if  ! if (dosw)
    1227             : 
    1228             :       !=======================!
    1229             :       ! LONGWAVE calculations !
    1230             :       !=======================!
    1231             : 
    1232      746136 :       if (dolw) then
    1233             : 
    1234             :          ! Initialize object for Planck sources.
    1235      746136 :          errmsg = sources_lw%alloc(ncol, nlay, kdist_lw)
    1236      746136 :          call stop_on_err(errmsg, sub, 'sources_lw%alloc')
    1237             : 
    1238             :          ! Set cloud optical properties in cloud_lw object.
    1239             :          call rrtmgp_set_cloud_lw( &
    1240             :             state, pbuf, ncol, nlay, nlaycam, &
    1241             :             cld, cldfsnow, cldfgrau, cldfprime, graupel_in_rad, &
    1242      746136 :             kdist_lw, cloud_lw, cld_lw_abs_cloudsim, snow_lw_abs_cloudsim, grau_lw_abs_cloudsim)
    1243             : 
    1244             :          ! Initialize object for gas concentrations
    1245      746136 :          errmsg = gas_concs_lw%init(gaslist_lc)
    1246      746136 :          call stop_on_err(errmsg, sub, 'gas_concs_lw%init')
    1247             : 
    1248             :          ! Initialize object for combined gas + aerosol + cloud optics.
    1249      746136 :          errmsg = atm_optics_lw%alloc_1scl(ncol, nlay, kdist_lw)
    1250      746136 :          call stop_on_err(errmsg, sub, 'atm_optics_lw%alloc_1scl')
    1251             : 
    1252             :          ! Initialize object for LW aerosol optics.
    1253      746136 :          errmsg = aer_lw%alloc_1scl(ncol, nlay, kdist_lw%get_band_lims_wavenumber())
    1254      746136 :          call stop_on_err(errmsg, sub, 'aer_lw%alloc_1scl')
    1255             : 
    1256             :          ! The climate (icall==0) calculation must occur last.
    1257     8953632 :          do icall = N_DIAG, 0, -1
    1258             : 
    1259     8953632 :             if (active_calls(icall)) then
    1260             : 
    1261             :                ! Set gas volume mixing ratios for this call in gas_concs_lw.
    1262      746136 :                call rrtmgp_set_gases_lw(icall, state, pbuf, nlay, gas_concs_lw)
    1263             : 
    1264             :                ! Compute the gas optics and Planck sources.
    1265             :                errmsg = kdist_lw%gas_optics( &
    1266             :                   pmid_rad, pint_rad, t_rad, t_sfc, gas_concs_lw, &
    1267      746136 :                   atm_optics_lw, sources_lw)
    1268      746136 :                call stop_on_err(errmsg, sub, 'kdist_lw%gas_optics')
    1269             : 
    1270             :                ! Set LW aerosol optical properties in the aer_lw object.
    1271      746136 :                call rrtmgp_set_aer_lw(icall, state, pbuf, aer_lw)
    1272             :                
    1273             :                ! Increment the gas optics by the aerosol optics.
    1274      746136 :                errmsg = aer_lw%increment(atm_optics_lw)
    1275      746136 :                call stop_on_err(errmsg, sub, 'aer_lw%increment')
    1276             : 
    1277             :                ! Compute clear-sky LW fluxes
    1278      746136 :                errmsg = rte_lw(atm_optics_lw, top_at_1, sources_lw, emis_sfc, flwc)
    1279      746136 :                call stop_on_err(errmsg, sub, 'clear-sky rte_lw')
    1280             : 
    1281             :                ! Increment the gas+aerosol optics by the cloud optics.
    1282      746136 :                errmsg = cloud_lw%increment(atm_optics_lw)
    1283      746136 :                call stop_on_err(errmsg, sub, 'cloud_lw%increment')
    1284             : 
    1285             :                ! Compute all-sky LW fluxes
    1286      746136 :                errmsg = rte_lw(atm_optics_lw, top_at_1, sources_lw, emis_sfc, flw)
    1287      746136 :                call stop_on_err(errmsg, sub, 'all-sky rte_lw')
    1288             : 
    1289             :                ! Transform RRTMGP outputs to CAM outputs and compute heating rates.
    1290      746136 :                call set_lw_diags()
    1291             : 
    1292      746136 :                if (write_output) then
    1293      746136 :                   call radiation_output_lw(lchnk, ncol, icall, rd, pbuf, cam_out)
    1294             :                end if
    1295             : 
    1296             :             end if ! (active_calls(icall))
    1297             :          end do    ! loop over diagnostic calcs (icall)
    1298             : 
    1299             :       else
    1300             :          ! LW calc not done.  pbuf carries Q*dp across timesteps.
    1301             :          ! Convert to Q before calling radheat_tend.
    1302           0 :         qrl(:ncol,:) = qrl(:ncol,:) / state%pdel(:ncol,:)
    1303             :       end if  ! if (dolw)
    1304             : 
    1305           0 :       deallocate( &
    1306           0 :          t_sfc, emis_sfc, toa_flux, t_rad, pmid_rad, pint_rad,  &
    1307      746136 :          t_day, pmid_day, pint_day, coszrs_day, alb_dir, alb_dif)
    1308             : 
    1309             :       !================!
    1310             :       ! COSP simulator !
    1311             :       !================!
    1312             : 
    1313      746136 :       if (docosp) then
    1314             : 
    1315           0 :          emis(:,:) = 0._r8
    1316           0 :          emis(:ncol,:) = 1._r8 - exp(-cld_lw_abs_cloudsim(:ncol,:))
    1317           0 :          call outfld('EMIS', emis, pcols, lchnk)
    1318             : 
    1319             :          ! compute grid-box mean SW and LW snow optical depth for use by COSP
    1320           0 :          gb_snow_tau(:,:) = 0._r8
    1321           0 :          gb_snow_lw(:,:)  = 0._r8
    1322           0 :          if (cldfsnow_idx > 0) then
    1323           0 :             do i = 1, ncol
    1324           0 :                do k = 1, pver
    1325           0 :                   if (cldfsnow(i,k) > 0._r8) then
    1326             : 
    1327             :                      ! Add graupel to snow tau for cosp
    1328           0 :                      if (cldfgrau_idx > 0 .and. graupel_in_rad) then
    1329           0 :                         gb_snow_tau(i,k) = snow_tau_cloudsim(i,k)*cldfsnow(i,k) + &
    1330           0 :                                            grau_tau_cloudsim(i,k)*cldfgrau(i,k)
    1331             :                         gb_snow_lw(i,k)  = snow_lw_abs_cloudsim(i,k)*cldfsnow(i,k) + &
    1332           0 :                                            grau_lw_abs_cloudsim(i,k)*cldfgrau(i,k)
    1333             :                      else
    1334           0 :                         gb_snow_tau(i,k) = snow_tau_cloudsim(i,k)*cldfsnow(i,k)
    1335           0 :                         gb_snow_lw(i,k)  = snow_lw_abs_cloudsim(i,k)*cldfsnow(i,k)
    1336             :                      end if
    1337             :                   end if
    1338             :                end do
    1339             :             end do
    1340             :          end if
    1341             : 
    1342             :          ! advance counter for this timestep (chunk dimension required for thread safety)
    1343           0 :          cosp_cnt(lchnk) = cosp_cnt(lchnk) + 1
    1344             : 
    1345             :          ! if counter is the same as cosp_nradsteps, run cosp and reset counter
    1346           0 :          if (cosp_nradsteps .eq. cosp_cnt(lchnk)) then
    1347             : 
    1348             :             ! N.B.: For snow optical properties, the GRID-BOX MEAN shortwave and longwave
    1349             :             !       optical depths are passed.
    1350             :             call cospsimulator_intr_run( &
    1351             :                state,  pbuf, cam_in, emis, coszrs,                     &
    1352             :                cld_swtau_in=cld_tau_cloudsim, snow_tau_in=gb_snow_tau, &
    1353           0 :                snow_emis_in=gb_snow_lw)
    1354           0 :             cosp_cnt(lchnk) = 0
    1355             :          end if
    1356             :       end if   ! docosp
    1357             :       
    1358             :    else
    1359             :       ! Radiative flux calculations not done.  The quantity Q*dp is carried by the
    1360             :       ! physics buffer across timesteps.  It must be converted to Q (dry static energy
    1361             :       ! tendency) before being passed to radheat_tend.
    1362  1159408584 :       qrs(:ncol,:) = qrs(:ncol,:) / state%pdel(:ncol,:)
    1363  1159408584 :       qrl(:ncol,:) = qrl(:ncol,:) / state%pdel(:ncol,:)
    1364             : 
    1365             :    end if   ! if (dosw .or. dolw) then
    1366             : 
    1367             :    ! Output for PORT: Parallel Offline Radiative Transport
    1368     1492272 :    call rad_data_write(pbuf, state, cam_in, coszrs)
    1369             : 
    1370             :    ! Compute net radiative heating tendency.  Note that the WACCM version
    1371             :    ! of radheat_tend merges upper atmosphere heating rates with those calculated
    1372             :    ! by RRTMGP.
    1373             :    call radheat_tend(state, pbuf,  ptend, qrl, qrs, fsns, &
    1374     1492272 :                      fsnt, flns, flnt, cam_in%asdir, net_flx)
    1375             : 
    1376     1492272 :    if (write_output) then
    1377             :       ! Compute heating rate for dtheta/dt
    1378   140273568 :       do k = 1, pver
    1379  2318817168 :          do i = 1, ncol
    1380  2317324896 :             ftem(i,k) = (qrs(i,k) + qrl(i,k))/cpair * (1.e5_r8/state%pmid(i,k))**cappa
    1381             :          end do
    1382             :       end do
    1383     1492272 :       call outfld('HR', ftem, pcols, lchnk)
    1384             :    end if
    1385             : 
    1386             :    ! The radiative heating rates are carried in the physics buffer across timesteps
    1387             :    ! as Q*dp (for energy conservation).
    1388  2318817168 :    qrs(:ncol,:) = qrs(:ncol,:) * state%pdel(:ncol,:)
    1389  2318817168 :    qrl(:ncol,:) = qrl(:ncol,:) * state%pdel(:ncol,:)
    1390             : 
    1391     1492272 :    if (.not. present(rd_out)) then
    1392     1492272 :       deallocate(rd)
    1393             :    end if
    1394     1492272 :    call free_optics_sw(atm_optics_sw)
    1395     1492272 :    call free_optics_sw(cloud_sw)
    1396     1492272 :    call free_optics_sw(aer_sw)
    1397     1492272 :    call free_fluxes(fsw)
    1398     1492272 :    call free_fluxes(fswc)
    1399             : 
    1400     1492272 :    call sources_lw%finalize()
    1401     1492272 :    call free_optics_lw(cloud_lw)
    1402     1492272 :    call free_optics_lw(aer_lw)
    1403     1492272 :    call free_fluxes(flw)
    1404     2984544 :    call free_fluxes(flwc)
    1405             : 
    1406             :    !-------------------------------------------------------------------------------
    1407             :    contains
    1408             :    !-------------------------------------------------------------------------------
    1409             : 
    1410      746136 :    subroutine set_sw_diags()
    1411             : 
    1412             :       ! Transform RRTMGP output for CAM and compute heating rates.
    1413             :       ! SW fluxes from RRTMGP are on daylight columns only, so expand to
    1414             :       ! full chunks for output to CAM history.
    1415             : 
    1416             :       integer :: i
    1417             :       real(r8), dimension(size(fsw%bnd_flux_dn,1), &
    1418             :                           size(fsw%bnd_flux_dn,2), &
    1419     1492272 :                           size(fsw%bnd_flux_dn,3)) :: flux_dn_diffuse
    1420             :       !-------------------------------------------------------------------------
    1421             : 
    1422             :       ! Initialize to provide 0.0 values for night columns.
    1423      746136 :       fns               = 0._r8 ! net sw flux
    1424      746136 :       fcns              = 0._r8 ! net sw clearsky flux
    1425    12684312 :       fsds              = 0._r8 ! downward sw flux at surface
    1426    12684312 :       rd%fsdsc          = 0._r8 ! downward sw clearsky flux at surface
    1427    12684312 :       rd%fsutoa         = 0._r8 ! upward sw flux at TOA
    1428    12684312 :       rd%fsntoa         = 0._r8 ! net sw at TOA
    1429    12684312 :       rd%fsntoac        = 0._r8 ! net sw clearsky flux at TOA
    1430    12684312 :       rd%solin          = 0._r8 ! solar irradiance at TOA
    1431  1193071464 :       rd%flux_sw_up     = 0._r8
    1432  1193071464 :       rd%flux_sw_dn     = 0._r8
    1433  1193071464 :       rd%flux_sw_clr_up = 0._r8
    1434  1193071464 :       rd%flux_sw_clr_dn = 0._r8
    1435             : 
    1436  1180387152 :       qrs      = 0._r8
    1437    12684312 :       fsns     = 0._r8
    1438    12684312 :       fsnt     = 0._r8
    1439  1180387152 :       rd%qrsc  = 0._r8
    1440    12684312 :       rd%fsnsc = 0._r8
    1441    12684312 :       rd%fsntc = 0._r8
    1442             : 
    1443     6602436 :       do i = 1, nday
    1444   556348500 :          fns(idxday(i),ktopcam:)  = fsw%flux_net(i, ktoprad:)
    1445   556348500 :          fcns(idxday(i),ktopcam:) = fswc%flux_net(i,ktoprad:)
    1446     5856300 :          fsds(idxday(i))          = fsw%flux_dn(i, nlay+1)
    1447     5856300 :          rd%fsdsc(idxday(i))      = fswc%flux_dn(i, nlay+1)
    1448     5856300 :          rd%fsutoa(idxday(i))     = fsw%flux_up(i, 1)
    1449     5856300 :          rd%fsntoa(idxday(i))     = fsw%flux_net(i, 1)
    1450     5856300 :          rd%fsntoac(idxday(i))    = fswc%flux_net(i, 1)
    1451     5856300 :          rd%solin(idxday(i))      = fswc%flux_dn(i, 1)
    1452   556348500 :          rd%flux_sw_up(idxday(i),ktopcam:)     = fsw%flux_up(i,ktoprad:)
    1453   556348500 :          rd%flux_sw_dn(idxday(i),ktopcam:)     = fsw%flux_dn(i,ktoprad:)
    1454   556348500 :          rd%flux_sw_clr_up(idxday(i),ktopcam:) = fswc%flux_up(i,ktoprad:) 
    1455   557094636 :          rd%flux_sw_clr_dn(idxday(i),ktopcam:) = fswc%flux_dn(i,ktoprad:)
    1456             :       end do
    1457             : 
    1458             :       ! Compute heating rate as a dry static energy tendency.
    1459      746136 :       call heating_rate('SW', ncol, fns, qrs)
    1460      746136 :       call heating_rate('SW', ncol, fcns, rd%qrsc)
    1461             : 
    1462    12458736 :       fsns(:ncol)     = fns(:ncol,pverp)    ! net sw flux at surface
    1463    12458736 :       fsnt(:ncol)     = fns(:ncol,ktopcam)  ! net sw flux at top-of-model (w/o extra layer)
    1464    13204872 :       rd%fsnsc(:ncol) = fcns(:ncol,pverp)   ! net sw clearsky flux at surface
    1465    13204872 :       rd%fsntc(:ncol) = fcns(:ncol,ktopcam) ! net sw clearsky flux at top
    1466             : 
    1467    12458736 :       cam_out%netsw(:ncol) = fsns(:ncol)
    1468             : 
    1469             :       ! Output fluxes at 200 mb
    1470      746136 :       call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fns,  rd%fsn200)
    1471      746136 :       call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fcns, rd%fsn200c)
    1472      746136 :       if (hist_fld_active('FSNR')) then
    1473           0 :          do i = 1,ncol
    1474           0 :             call vertinterp(1, 1, pverp, state%pint(i,:), p_trop(i), fns(i,:), rd%fsnr(i))
    1475             :          end do
    1476             :       end if
    1477             : 
    1478      746136 :       if (spectralflux) then
    1479           0 :          su  = 0._r8
    1480           0 :          sd  = 0._r8
    1481           0 :          do i = 1, nday
    1482           0 :             su(idxday(i),ktopcam:,:) = fsw%bnd_flux_up(i,ktoprad:,:)
    1483           0 :             sd(idxday(i),ktopcam:,:) = fsw%bnd_flux_dn(i,ktoprad:,:)
    1484             :          end do
    1485             :       end if
    1486             : 
    1487             :       ! Export surface fluxes
    1488             :       ! sols(pcols)      Direct solar rad on surface (< 0.7)
    1489             :       ! soll(pcols)      Direct solar rad on surface (>= 0.7)
    1490             :       ! RRTMGP: Near-IR bands (1-10), 820-16000 cm-1, 0.625-12.195 microns
    1491             :       ! Put half of band 10 in each of the UV/visible and near-IR values,
    1492             :       ! since this band straddles 0.7 microns:
    1493             :       ! UV/visible bands 10-13, 16000-50000 cm-1, 0.200-0.625 micron
    1494             : 
    1495             :       ! reset fluxes
    1496    12684312 :       cam_out%sols  = 0.0_r8
    1497    12684312 :       cam_out%soll  = 0.0_r8
    1498    12684312 :       cam_out%solsd = 0.0_r8
    1499    12684312 :       cam_out%solld = 0.0_r8
    1500             : 
    1501             :       ! Calculate diffuse flux from total and direct
    1502  8792431920 :       flux_dn_diffuse = fsw%bnd_flux_dn - fsw%bnd_flux_dn_dir
    1503             : 
    1504     6602436 :       do i = 1, nday
    1505    17568900 :          cam_out%soll(idxday(i)) = sum(fsw%bnd_flux_dn_dir(i,nlay+1,1:9))      &
    1506    76131900 :                                    + 0.5_r8 * fsw%bnd_flux_dn_dir(i,nlay+1,10) 
    1507             : 
    1508     5856300 :          cam_out%sols(idxday(i)) = 0.5_r8 * fsw%bnd_flux_dn_dir(i,nlay+1,10)   &
    1509    35137800 :                                    + sum(fsw%bnd_flux_dn_dir(i,nlay+1,11:14))
    1510             : 
    1511    11712600 :          cam_out%solld(idxday(i)) = sum(flux_dn_diffuse(i,nlay+1,1:9))         &
    1512    70275600 :                                     + 0.5_r8 * flux_dn_diffuse(i,nlay+1,10)
    1513             :          
    1514     5856300 :          cam_out%solsd(idxday(i)) = 0.5_r8 * flux_dn_diffuse(i, nlay+1, 10)    &
    1515    41740236 :                                     + sum(flux_dn_diffuse(i,nlay+1,11:14))
    1516             :       end do
    1517             : 
    1518     1492272 :    end subroutine set_sw_diags
    1519             : 
    1520             :    !-------------------------------------------------------------------------------
    1521             : 
    1522      746136 :    subroutine set_lw_diags()
    1523             : 
    1524             :       ! Set CAM LW diagnostics
    1525             :       !----------------------------------------------------------------------------
    1526             :  
    1527      746136 :       fnl = 0._r8
    1528      746136 :       fcnl = 0._r8
    1529             : 
    1530             :       ! RTE-RRTMGP convention for net is (down - up) **CAM assumes (up - down) !!
    1531  1171867320 :       fnl(:ncol,ktopcam:)  = -1._r8 * flw%flux_net(    :, ktoprad:)
    1532  1171867320 :       fcnl(:ncol,ktopcam:) = -1._r8 * flwc%flux_net(   :, ktoprad:)
    1533             : 
    1534  1171867320 :       rd%flux_lw_up(:ncol,ktopcam:)     = flw%flux_up( :, ktoprad:)
    1535  1171867320 :       rd%flux_lw_clr_up(:ncol,ktopcam:) = flwc%flux_up(:, ktoprad:)
    1536  1171867320 :       rd%flux_lw_dn(:ncol,ktopcam:)     = flw%flux_dn( :, ktoprad:)
    1537  1171867320 :       rd%flux_lw_clr_dn(:ncol,ktopcam:) = flwc%flux_dn(:, ktoprad:)
    1538             : 
    1539      746136 :       call heating_rate('LW', ncol, fnl, qrl)
    1540      746136 :       call heating_rate('LW', ncol, fcnl, rd%qrlc)
    1541             : 
    1542    12458736 :       flns(:ncol) = fnl(:ncol, pverp)
    1543    12458736 :       flnt(:ncol) = fnl(:ncol, ktopcam)
    1544             : 
    1545    13204872 :       rd%flnsc(:ncol) = fcnl(:ncol, pverp)
    1546    13204872 :       rd%flntc(:ncol) = fcnl(:ncol, ktopcam)    ! net lw flux at top-of-model
    1547             : 
    1548    12458736 :       cam_out%flwds(:ncol) = flw%flux_dn(:, nlay+1)
    1549    12458736 :       rd%fldsc(:ncol)      = flwc%flux_dn(:, nlay+1)
    1550             : 
    1551    12458736 :       rd%flut(:ncol)  = flw%flux_up(:, ktoprad) 
    1552    12458736 :       rd%flutc(:ncol) = flwc%flux_up(:, ktoprad)
    1553             : 
    1554             :       ! Output fluxes at 200 mb
    1555      746136 :       call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fnl,  rd%fln200)
    1556      746136 :       call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fcnl, rd%fln200c)
    1557      746136 :       if (hist_fld_active('FLNR')) then
    1558           0 :          do i = 1,ncol
    1559           0 :             call vertinterp(1, 1, pverp, state%pint(i,:), p_trop(i), fnl(i,:), rd%flnr(i))
    1560             :          end do
    1561             :       end if
    1562             : 
    1563      746136 :       if (spectralflux) then
    1564           0 :          lu  = 0._r8
    1565           0 :          ld  = 0._r8
    1566           0 :          lu(:ncol, ktopcam:, :)  = flw%bnd_flux_up(:, ktoprad:, :)
    1567           0 :          ld(:ncol, ktopcam:, :)  = flw%bnd_flux_dn(:, ktoprad:, :)
    1568             :       end if
    1569             : 
    1570      746136 :    end subroutine set_lw_diags
    1571             : 
    1572             :    !-------------------------------------------------------------------------------
    1573             : 
    1574     2984544 :    subroutine heating_rate(type, ncol, flux_net, hrate)
    1575             : 
    1576             :       ! Compute heating rate as a dry static energy tendency
    1577             :       
    1578             :       ! arguments
    1579             :       character(2), intent(in)  :: type ! either LW or SW
    1580             :       integer,      intent(in)  :: ncol
    1581             :       real(r8),     intent(in)  :: flux_net(pcols,pverp)  ! W/m^2
    1582             :       real(r8),     intent(out) :: hrate(pcols,pver)      ! J/kg/s
    1583             : 
    1584             :       ! local vars
    1585             :       integer :: k
    1586             : 
    1587             :       ! Initialize for layers where RRTMGP is not providing fluxes.
    1588     2984544 :       hrate = 0.0_r8
    1589             : 
    1590     1492272 :       select case (type)
    1591             :       case ('LW')
    1592             : 
    1593   140273568 :          do k = ktopcam, pver
    1594             :             ! (flux divergence as bottom-MINUS-top) * g/dp
    1595   277562592 :             hrate(:ncol,k) = (flux_net(:ncol,k+1) - flux_net(:ncol,k)) * &
    1596  2596379760 :                           gravit * state%rpdel(:ncol,k)
    1597             :          end do
    1598             : 
    1599             :       case ('SW')
    1600             : 
    1601   141765840 :          do k = ktopcam, pver
    1602             :             ! top - bottom
    1603   277562592 :             hrate(:ncol,k) = (flux_net(:ncol,k) - flux_net(:ncol,k+1)) * &
    1604  2596379760 :                           gravit * state%rpdel(:ncol,k)
    1605             :          end do
    1606             : 
    1607             :       end select
    1608             : 
    1609     2984544 :    end subroutine heating_rate
    1610             : 
    1611             :    !----------------------------------------------------------------------------
    1612             :    !            -- end contains statement of radiation_tend --
    1613             :    !----------------------------------------------------------------------------
    1614             : end subroutine radiation_tend
    1615             : 
    1616             : !===============================================================================
    1617             : 
    1618      746136 : subroutine radiation_output_sw(lchnk, ncol, icall, rd, pbuf, cam_out)
    1619             : 
    1620             :    ! Dump shortwave radiation information to history buffer.
    1621             : 
    1622             :    integer ,               intent(in) :: lchnk
    1623             :    integer,                intent(in) :: ncol
    1624             :    integer,                intent(in) :: icall
    1625             :    type(rad_out_t),        intent(in) :: rd
    1626             :    type(physics_buffer_desc), pointer :: pbuf(:)
    1627             :    type(cam_out_t),        intent(in) :: cam_out
    1628             : 
    1629             :    ! local variables
    1630      746136 :    real(r8), pointer :: qrs(:,:)
    1631      746136 :    real(r8), pointer :: fsnt(:)
    1632      746136 :    real(r8), pointer :: fsns(:)
    1633      746136 :    real(r8), pointer :: fsds(:)
    1634             : 
    1635             :    real(r8) :: ftem(pcols)
    1636             :    !----------------------------------------------------------------------------
    1637             : 
    1638      746136 :    call pbuf_get_field(pbuf, qrs_idx,  qrs)
    1639      746136 :    call pbuf_get_field(pbuf, fsnt_idx, fsnt)
    1640      746136 :    call pbuf_get_field(pbuf, fsns_idx, fsns)
    1641      746136 :    call pbuf_get_field(pbuf, fsds_idx, fsds)
    1642             : 
    1643      746136 :    call outfld('SOLIN'//diag(icall),    rd%solin,      pcols, lchnk)
    1644             : 
    1645             :    ! QRS is output as temperature tendency.
    1646  1159408584 :    call outfld('QRS'//diag(icall),      qrs(:ncol,:)/cpair,     ncol, lchnk)
    1647  1159408584 :    call outfld('QRSC'//diag(icall),     rd%qrsc(:ncol,:)/cpair, ncol, lchnk)
    1648             : 
    1649      746136 :    call outfld('FSNT'//diag(icall),    fsnt,               pcols, lchnk)
    1650      746136 :    call outfld('FSNTC'//diag(icall),   rd%fsntc,           pcols, lchnk)
    1651      746136 :    call outfld('FSNTOA'//diag(icall),  rd%fsntoa,          pcols, lchnk)
    1652      746136 :    call outfld('FSNTOAC'//diag(icall), rd%fsntoac,         pcols, lchnk)
    1653             : 
    1654    12458736 :    ftem(:ncol) = rd%fsntoa(:ncol) - rd%fsntoac(:ncol)
    1655      746136 :    call outfld('SWCF'//diag(icall),     ftem,          pcols, lchnk)
    1656             : 
    1657      746136 :    call outfld('FSUTOA'//diag(icall),   rd%fsutoa,     pcols, lchnk)
    1658             : 
    1659      746136 :    call outfld('FSNIRTOA'//diag(icall), rd%fsnirt,     pcols, lchnk)
    1660      746136 :    call outfld('FSNRTOAC'//diag(icall), rd%fsnrtc,     pcols, lchnk)
    1661      746136 :    call outfld('FSNRTOAS'//diag(icall), rd%fsnirtsq,   pcols, lchnk)
    1662             : 
    1663      746136 :    call outfld('FSN200'//diag(icall),   rd%fsn200,     pcols, lchnk)
    1664      746136 :    call outfld('FSN200C'//diag(icall),  rd%fsn200c,    pcols, lchnk)
    1665             : 
    1666      746136 :    call outfld('FSNR'//diag(icall),     rd%fsnr,       pcols, lchnk)
    1667             : 
    1668      746136 :    call outfld('SOLS'//diag(icall),     cam_out%sols,  pcols, lchnk)
    1669      746136 :    call outfld('SOLL'//diag(icall),     cam_out%soll,  pcols, lchnk)
    1670      746136 :    call outfld('SOLSD'//diag(icall),    cam_out%solsd, pcols, lchnk)
    1671      746136 :    call outfld('SOLLD'//diag(icall),    cam_out%solld, pcols, lchnk)
    1672             : 
    1673      746136 :    call outfld('FSNS'//diag(icall),     fsns,          pcols, lchnk)
    1674      746136 :    call outfld('FSNSC'//diag(icall),    rd%fsnsc,      pcols, lchnk)
    1675             : 
    1676      746136 :    call outfld('FSDS'//diag(icall),     fsds,          pcols, lchnk)
    1677      746136 :    call outfld('FSDSC'//diag(icall),    rd%fsdsc,      pcols, lchnk)
    1678             : 
    1679      746136 :    call outfld('FUS'//diag(icall),  rd%flux_sw_up,     pcols, lchnk)
    1680      746136 :    call outfld('FUSC'//diag(icall), rd%flux_sw_clr_up, pcols, lchnk)
    1681      746136 :    call outfld('FDS'//diag(icall),  rd%flux_sw_dn,     pcols, lchnk)
    1682      746136 :    call outfld('FDSC'//diag(icall), rd%flux_sw_clr_dn, pcols, lchnk)
    1683             : 
    1684      746136 : end subroutine radiation_output_sw
    1685             : 
    1686             : !===============================================================================
    1687             : 
    1688      746136 : subroutine radiation_output_cld(lchnk, rd)
    1689             : 
    1690             :    ! Dump shortwave cloud optics information to history buffer.
    1691             : 
    1692             :    integer ,        intent(in) :: lchnk
    1693             :    type(rad_out_t), intent(in) :: rd
    1694             :    !----------------------------------------------------------------------------
    1695             : 
    1696      746136 :    call outfld('TOT_CLD_VISTAU',  rd%tot_cld_vistau,  pcols, lchnk)
    1697      746136 :    call outfld('TOT_ICLD_VISTAU', rd%tot_icld_vistau, pcols, lchnk)
    1698      746136 :    call outfld('LIQ_ICLD_VISTAU', rd%liq_icld_vistau, pcols, lchnk)
    1699      746136 :    call outfld('ICE_ICLD_VISTAU', rd%ice_icld_vistau, pcols, lchnk)
    1700      746136 :    if (cldfsnow_idx > 0) then
    1701      746136 :       call outfld('SNOW_ICLD_VISTAU', rd%snow_icld_vistau, pcols, lchnk)
    1702             :    endif
    1703      746136 :    if (cldfgrau_idx > 0 .and. graupel_in_rad) then
    1704           0 :       call outfld('GRAU_ICLD_VISTAU', rd%grau_icld_vistau , pcols, lchnk)
    1705             :    endif
    1706             : 
    1707      746136 : end subroutine radiation_output_cld
    1708             : 
    1709             : !===============================================================================
    1710             : 
    1711      746136 : subroutine radiation_output_lw(lchnk, ncol, icall, rd, pbuf, cam_out)
    1712             : 
    1713             :    ! Dump longwave radiation information to history buffer
    1714             : 
    1715             :    integer,                intent(in) :: lchnk
    1716             :    integer,                intent(in) :: ncol
    1717             :    integer,                intent(in) :: icall  ! icall=0 for climate diagnostics
    1718             :    type(rad_out_t),        intent(in) :: rd
    1719             :    type(physics_buffer_desc), pointer :: pbuf(:)
    1720             :    type(cam_out_t),        intent(in) :: cam_out
    1721             : 
    1722             :    ! local variables
    1723      746136 :    real(r8), pointer :: qrl(:,:)
    1724      746136 :    real(r8), pointer :: flnt(:)
    1725      746136 :    real(r8), pointer :: flns(:)
    1726             : 
    1727             :    real(r8) :: ftem(pcols)
    1728             :    !----------------------------------------------------------------------------
    1729             : 
    1730      746136 :    call pbuf_get_field(pbuf, qrl_idx,  qrl)
    1731      746136 :    call pbuf_get_field(pbuf, flnt_idx, flnt)
    1732      746136 :    call pbuf_get_field(pbuf, flns_idx, flns)
    1733             : 
    1734  1159408584 :    call outfld('QRL'//diag(icall),     qrl(:ncol,:)/cpair,     ncol, lchnk)
    1735  1159408584 :    call outfld('QRLC'//diag(icall),    rd%qrlc(:ncol,:)/cpair, ncol, lchnk)
    1736             : 
    1737      746136 :    call outfld('FLNT'//diag(icall),    flnt,          pcols, lchnk)
    1738      746136 :    call outfld('FLNTC'//diag(icall),   rd%flntc,      pcols, lchnk)
    1739             : 
    1740      746136 :    call outfld('FLUT'//diag(icall),    rd%flut,       pcols, lchnk)
    1741      746136 :    call outfld('FLUTC'//diag(icall),   rd%flutc,      pcols, lchnk)
    1742             :    
    1743    12458736 :    ftem(:ncol) = rd%flutc(:ncol) - rd%flut(:ncol)
    1744      746136 :    call outfld('LWCF'//diag(icall),    ftem,          pcols, lchnk)
    1745             : 
    1746      746136 :    call outfld('FLN200'//diag(icall),  rd%fln200,     pcols, lchnk)
    1747      746136 :    call outfld('FLN200C'//diag(icall), rd%fln200c,    pcols, lchnk)
    1748             : 
    1749      746136 :    call outfld('FLNR'//diag(icall),    rd%flnr,       pcols, lchnk)
    1750             : 
    1751      746136 :    call outfld('FLNS'//diag(icall),    flns,          pcols, lchnk)
    1752      746136 :    call outfld('FLNSC'//diag(icall),   rd%flnsc,      pcols, lchnk)
    1753             : 
    1754      746136 :    call outfld('FLDS'//diag(icall),    cam_out%flwds, pcols, lchnk)
    1755      746136 :    call outfld('FLDSC'//diag(icall),   rd%fldsc,      pcols, lchnk)
    1756             : 
    1757      746136 :    call outfld('FDL'//diag(icall),  rd%flux_lw_dn,     pcols, lchnk)
    1758      746136 :    call outfld('FDLC'//diag(icall), rd%flux_lw_clr_dn, pcols, lchnk)
    1759      746136 :    call outfld('FUL'//diag(icall),  rd%flux_lw_up,     pcols, lchnk)
    1760      746136 :    call outfld('FULC'//diag(icall), rd%flux_lw_clr_up, pcols, lchnk)
    1761             : 
    1762      746136 : end subroutine radiation_output_lw
    1763             : 
    1764             : !===============================================================================
    1765             : 
    1766        3072 : subroutine coefs_init(coefs_file, available_gases, kdist)
    1767             : 
    1768             :    ! Read data from coefficients file.  Initialize the kdist object.
    1769             :    ! available_gases object provides the gas names that CAM provides.
    1770             : 
    1771             :    ! arguments
    1772             :    character(len=*),                  intent(in)  :: coefs_file
    1773             :    class(ty_gas_concs),               intent(in)  :: available_gases
    1774             :    class(ty_gas_optics_rrtmgp),       intent(out) :: kdist
    1775             : 
    1776             :    ! local variables
    1777             :    type(file_desc_t) :: fh    ! pio file handle
    1778             :    character(len=cl) :: locfn ! path to file on local storage
    1779             : 
    1780             :    ! File dimensions
    1781             :    integer ::            &
    1782             :       absorber,          &
    1783             :       atmos_layer,       &
    1784             :       bnd,               &
    1785             :       pressure,          &
    1786             :       temperature,       &
    1787             :       absorber_ext,      &
    1788             :       pressure_interp,   &
    1789             :       mixing_fraction,   &
    1790             :       gpt,               &
    1791             :       temperature_Planck
    1792             :    
    1793             :    integer :: i
    1794             :    integer :: did, vid
    1795             :    integer :: ierr, istat
    1796             : 
    1797        3072 :    character(32), dimension(:),  allocatable :: gas_names
    1798        3072 :    integer,  dimension(:,:,:),   allocatable :: key_species
    1799        3072 :    integer,  dimension(:,:),     allocatable :: band2gpt
    1800        3072 :    real(r8), dimension(:,:),     allocatable :: band_lims_wavenum
    1801        3072 :    real(r8), dimension(:),       allocatable :: press_ref, temp_ref
    1802             :    real(r8)                                  :: press_ref_trop, temp_ref_t, temp_ref_p
    1803        3072 :    real(r8), dimension(:,:,:),   allocatable :: vmr_ref
    1804        3072 :    real(r8), dimension(:,:,:,:), allocatable :: kmajor
    1805        3072 :    real(r8), dimension(:,:,:),   allocatable :: kminor_lower, kminor_upper
    1806        3072 :    real(r8), dimension(:,:),     allocatable :: totplnk
    1807        3072 :    real(r8), dimension(:,:,:,:), allocatable :: planck_frac
    1808        3072 :    real(r8), dimension(:),       allocatable :: solar_src_quiet, solar_src_facular, solar_src_sunspot
    1809             :    real(r8)                                  :: tsi_default
    1810        3072 :    real(r8), dimension(:,:,:),   allocatable :: rayl_lower, rayl_upper
    1811        3072 :    character(len=32), dimension(:),  allocatable :: gas_minor,         &
    1812        3072 :                                                     identifier_minor,  &
    1813        3072 :                                                     minor_gases_lower, &
    1814        3072 :                                                     minor_gases_upper, &
    1815        3072 :                                                     scaling_gas_lower, &
    1816        3072 :                                                     scaling_gas_upper
    1817        3072 :    integer, dimension(:,:),          allocatable :: minor_limits_gpt_lower, &
    1818        3072 :                                                     minor_limits_gpt_upper
    1819             :    ! Send these to RRTMGP as logicals,
    1820             :    ! but they have to be read from the netCDF as integers
    1821        3072 :    logical, dimension(:),            allocatable :: minor_scales_with_density_lower, &
    1822        3072 :                                                     minor_scales_with_density_upper
    1823        3072 :    logical, dimension(:),            allocatable :: scale_by_complement_lower, &
    1824        3072 :                                                     scale_by_complement_upper
    1825        3072 :    integer, dimension(:), allocatable :: int2log   ! use this to convert integer-to-logical.
    1826        3072 :    integer, dimension(:),            allocatable :: kminor_start_lower, kminor_start_upper
    1827        3072 :    real(r8), dimension(:,:),         allocatable :: optimal_angle_fit
    1828             :    real(r8)                                      :: mg_default, sb_default
    1829             : 
    1830             :    integer :: pairs, &
    1831             :               minorabsorbers, &
    1832             :               minor_absorber_intervals_lower, &
    1833             :               minor_absorber_intervals_upper, &
    1834             :               contributors_lower, &
    1835             :               contributors_upper, &
    1836             :               fit_coeffs
    1837             : 
    1838             :    character(len=128) :: error_msg
    1839             :    character(len=*), parameter :: sub = 'coefs_init'
    1840             :    !----------------------------------------------------------------------------
    1841             : 
    1842             :    ! Open file
    1843        3072 :    call getfil(coefs_file, locfn, 0)
    1844        3072 :    call cam_pio_openfile(fh, locfn, PIO_NOWRITE)
    1845             : 
    1846        3072 :    call pio_seterrorhandling(fh, PIO_BCAST_ERROR)
    1847             : 
    1848             :    ! Get dimensions
    1849             : 
    1850        3072 :    ierr = pio_inq_dimid(fh, 'absorber', did)
    1851        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': absorber not found')
    1852        3072 :    ierr = pio_inq_dimlen(fh, did, absorber)
    1853             : 
    1854        3072 :    ierr = pio_inq_dimid(fh, 'atmos_layer', did)
    1855        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': atmos_layer not found')
    1856        3072 :    ierr = pio_inq_dimlen(fh, did, atmos_layer)
    1857             : 
    1858        3072 :    ierr = pio_inq_dimid(fh, 'bnd', did)
    1859        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': bnd not found')
    1860        3072 :    ierr = pio_inq_dimlen(fh, did, bnd)
    1861             : 
    1862        3072 :    ierr = pio_inq_dimid(fh, 'pressure', did)
    1863        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': pressure not found')
    1864        3072 :    ierr = pio_inq_dimlen(fh, did, pressure)
    1865             : 
    1866        3072 :    ierr = pio_inq_dimid(fh, 'temperature', did)
    1867        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': temperature not found')
    1868        3072 :    ierr = pio_inq_dimlen(fh, did, temperature)
    1869             : 
    1870        3072 :    ierr = pio_inq_dimid(fh, 'absorber_ext', did)
    1871        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': absorber_ext not found')
    1872        3072 :    ierr = pio_inq_dimlen(fh, did, absorber_ext)
    1873             : 
    1874        3072 :    ierr = pio_inq_dimid(fh, 'pressure_interp', did)
    1875        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': pressure_interp not found')
    1876        3072 :    ierr = pio_inq_dimlen(fh, did, pressure_interp)
    1877             : 
    1878        3072 :    ierr = pio_inq_dimid(fh, 'mixing_fraction', did)
    1879        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': mixing_fraction not found')
    1880        3072 :    ierr = pio_inq_dimlen(fh, did, mixing_fraction)
    1881             :    
    1882        3072 :    ierr = pio_inq_dimid(fh, 'gpt', did)
    1883        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': gpt not found')
    1884        3072 :    ierr = pio_inq_dimlen(fh, did, gpt)
    1885             : 
    1886        3072 :    temperature_Planck = 0
    1887        3072 :    ierr = pio_inq_dimid(fh, 'temperature_Planck', did)
    1888        3072 :    if (ierr == PIO_NOERR) then
    1889        1536 :       ierr = pio_inq_dimlen(fh, did, temperature_Planck)
    1890             :    end if
    1891        3072 :    ierr = pio_inq_dimid(fh, 'pair', did)
    1892        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': pair not found')
    1893        3072 :    ierr = pio_inq_dimlen(fh, did, pairs)
    1894        3072 :    ierr = pio_inq_dimid(fh, 'minor_absorber', did)
    1895        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_absorber not found')
    1896        3072 :    ierr = pio_inq_dimlen(fh, did, minorabsorbers)
    1897        3072 :    ierr = pio_inq_dimid(fh, 'minor_absorber_intervals_lower', did)
    1898        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_absorber_intervals_lower not found')
    1899        3072 :    ierr = pio_inq_dimlen(fh, did, minor_absorber_intervals_lower)
    1900        3072 :    ierr = pio_inq_dimid(fh, 'minor_absorber_intervals_upper', did)
    1901        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_absorber_intervals_upper not found')
    1902        3072 :    ierr = pio_inq_dimlen(fh, did, minor_absorber_intervals_upper)
    1903        3072 :    ierr = pio_inq_dimid(fh, 'contributors_lower', did)
    1904        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': contributors_lower not found')
    1905        3072 :    ierr = pio_inq_dimlen(fh, did, contributors_lower)
    1906        3072 :    ierr = pio_inq_dimid(fh, 'contributors_upper', did)
    1907        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': contributors_upper not found')
    1908        3072 :    ierr = pio_inq_dimlen(fh, did, contributors_upper)
    1909             : 
    1910        3072 :    ierr = pio_inq_dimid(fh, 'fit_coeffs', did)
    1911        3072 :    if (ierr == PIO_NOERR) then
    1912        1536 :       ierr = pio_inq_dimlen(fh, did, fit_coeffs)
    1913             :    end if
    1914             : 
    1915             :    ! Get variables
    1916             :    
    1917             :    ! names of absorbing gases
    1918        9216 :    allocate(gas_names(absorber), stat=istat)
    1919        3072 :    call handle_allocate_error(istat, sub, 'gas_names')
    1920        3072 :    ierr = pio_inq_varid(fh, 'gas_names', vid)
    1921        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': gas_names not found')
    1922        3072 :    ierr = pio_get_var(fh, vid, gas_names)
    1923        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading gas_names')
    1924             : 
    1925             :    ! key species pair for each band
    1926       12288 :    allocate(key_species(2,atmos_layer,bnd), stat=istat)
    1927        3072 :    call handle_allocate_error(istat, sub, 'key_species')
    1928        3072 :    ierr = pio_inq_varid(fh, 'key_species', vid)
    1929        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': key_species not found')
    1930        3072 :    ierr = pio_get_var(fh, vid, key_species)
    1931        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading key_species')
    1932             : 
    1933             :    ! beginning and ending gpoint for each band
    1934        9216 :    allocate(band2gpt(2,bnd), stat=istat)
    1935        3072 :    call handle_allocate_error(istat, sub, 'band2gpt')
    1936        3072 :    ierr = pio_inq_varid(fh, 'bnd_limits_gpt', vid)
    1937        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': bnd_limits_gpt not found')
    1938        3072 :    ierr = pio_get_var(fh, vid, band2gpt)
    1939        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading bnd_limits_gpt')
    1940             : 
    1941             :    ! beginning and ending wavenumber for each band
    1942        9216 :    allocate(band_lims_wavenum(2,bnd), stat=istat)
    1943        3072 :    call handle_allocate_error(istat, sub, 'band_lims_wavenum')
    1944        3072 :    ierr = pio_inq_varid(fh, 'bnd_limits_wavenumber', vid)
    1945        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': bnd_limits_wavenumber not found')
    1946        3072 :    ierr = pio_get_var(fh, vid, band_lims_wavenum)
    1947        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading bnd_limits_wavenumber')
    1948             : 
    1949             :    ! pressures [hPa] for reference atmosphere; press_ref(# reference layers)
    1950        9216 :    allocate(press_ref(pressure), stat=istat)
    1951        3072 :    call handle_allocate_error(istat, sub, 'press_ref')
    1952        3072 :    ierr = pio_inq_varid(fh, 'press_ref', vid)
    1953        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': press_ref not found')
    1954        3072 :    ierr = pio_get_var(fh, vid, press_ref)
    1955        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading press_ref')
    1956             : 
    1957             :    ! reference pressure separating the lower and upper atmosphere
    1958        3072 :    ierr = pio_inq_varid(fh, 'press_ref_trop', vid)
    1959        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': press_ref_trop not found')
    1960        3072 :    ierr = pio_get_var(fh, vid, press_ref_trop)
    1961        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading press_ref_trop')
    1962             : 
    1963             :    ! temperatures [K] for reference atmosphere; temp_ref(# reference layers)
    1964        9216 :    allocate(temp_ref(temperature), stat=istat)
    1965        3072 :    call handle_allocate_error(istat, sub, 'temp_ref')
    1966        3072 :    ierr = pio_inq_varid(fh, 'temp_ref', vid)
    1967        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': temp_ref not found')
    1968        3072 :    ierr = pio_get_var(fh, vid, temp_ref)
    1969        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading temp_ref')
    1970             : 
    1971             :    ! standard spectroscopic reference temperature [K]
    1972        3072 :    ierr = pio_inq_varid(fh, 'absorption_coefficient_ref_T', vid)
    1973        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': absorption_coefficient_ref_T not found')
    1974        3072 :    ierr = pio_get_var(fh, vid, temp_ref_t)
    1975        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading absorption_coefficient_ref_T')
    1976             : 
    1977             :    ! standard spectroscopic reference pressure [hPa]
    1978        3072 :    ierr = pio_inq_varid(fh, 'absorption_coefficient_ref_P', vid)
    1979        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': absorption_coefficient_ref_P not found')
    1980        3072 :    ierr = pio_get_var(fh, vid, temp_ref_p)
    1981        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading absorption_coefficient_ref_P')
    1982             : 
    1983             :    ! volume mixing ratios for reference atmosphere
    1984       15360 :    allocate(vmr_ref(atmos_layer, absorber_ext, temperature), stat=istat)
    1985        3072 :    call handle_allocate_error(istat, sub, 'vmr_ref')
    1986        3072 :    ierr = pio_inq_varid(fh, 'vmr_ref', vid)
    1987        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': vmr_ref not found')
    1988        3072 :    ierr = pio_get_var(fh, vid, vmr_ref)
    1989        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading vmr_ref')
    1990             : 
    1991             :    ! absorption coefficients due to major absorbing gases
    1992       18432 :    allocate(kmajor(gpt,mixing_fraction,pressure_interp,temperature), stat=istat)
    1993        3072 :    call handle_allocate_error(istat, sub, 'kmajor')
    1994        3072 :    ierr = pio_inq_varid(fh, 'kmajor', vid)
    1995        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': kmajor not found')
    1996        3072 :    ierr = pio_get_var(fh, vid, kmajor)
    1997        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading kmajor')
    1998             : 
    1999             :    ! absorption coefficients due to minor absorbing gases in lower part of atmosphere
    2000       15360 :    allocate(kminor_lower(contributors_lower, mixing_fraction, temperature), stat=istat)
    2001        3072 :    call handle_allocate_error(istat, sub, 'kminor_lower')
    2002        3072 :    ierr = pio_inq_varid(fh, 'kminor_lower', vid)
    2003        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': kminor_lower not found')
    2004        3072 :    ierr = pio_get_var(fh, vid, kminor_lower)
    2005        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_lower')
    2006             : 
    2007             :    ! absorption coefficients due to minor absorbing gases in upper part of atmosphere
    2008       15360 :    allocate(kminor_upper(contributors_upper, mixing_fraction, temperature), stat=istat)
    2009        3072 :    call handle_allocate_error(istat, sub, 'kminor_upper')
    2010        3072 :    ierr = pio_inq_varid(fh, 'kminor_upper', vid)
    2011        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': kminor_upper not found')
    2012        3072 :    ierr = pio_get_var(fh, vid, kminor_upper)
    2013        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_upper')
    2014             : 
    2015             :    ! integrated Planck function by band
    2016        3072 :    ierr = pio_inq_varid(fh, 'totplnk', vid)
    2017        3072 :    if (ierr == PIO_NOERR) then
    2018        6144 :       allocate(totplnk(temperature_Planck,bnd), stat=istat)
    2019        1536 :       call handle_allocate_error(istat, sub, 'totplnk')
    2020        1536 :       ierr = pio_get_var(fh, vid, totplnk)
    2021        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading totplnk')
    2022             :    end if
    2023             : 
    2024             :    ! Planck fractions
    2025        3072 :    ierr = pio_inq_varid(fh, 'plank_fraction', vid)
    2026        3072 :    if (ierr == PIO_NOERR) then
    2027        9216 :       allocate(planck_frac(gpt,mixing_fraction,pressure_interp,temperature), stat=istat)
    2028        1536 :       call handle_allocate_error(istat, sub, 'planck_frac')
    2029        1536 :       ierr = pio_get_var(fh, vid, planck_frac)
    2030        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading plank_fraction')
    2031             :    end if
    2032             : 
    2033        3072 :    ierr = pio_inq_varid(fh, 'optimal_angle_fit', vid)
    2034        3072 :    if (ierr == PIO_NOERR) then
    2035        6144 :       allocate(optimal_angle_fit(fit_coeffs, bnd), stat=istat)
    2036        1536 :       call handle_allocate_error(istat, sub, 'optiman_angle_fit')
    2037        1536 :       ierr = pio_get_var(fh, vid, optimal_angle_fit)
    2038        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading optimal_angle_fit')
    2039             :    end if
    2040             : 
    2041        3072 :    ierr = pio_inq_varid(fh, 'solar_source_quiet', vid)
    2042        3072 :    if (ierr == PIO_NOERR) then
    2043        4608 :       allocate(solar_src_quiet(gpt), stat=istat)
    2044        1536 :       call handle_allocate_error(istat, sub, 'solar_src_quiet')
    2045        1536 :       ierr = pio_get_var(fh, vid, solar_src_quiet)
    2046        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading solar_source_quiet')
    2047             :    end if
    2048             : 
    2049        3072 :    ierr = pio_inq_varid(fh, 'solar_source_facular', vid)
    2050        3072 :    if (ierr == PIO_NOERR) then
    2051        4608 :       allocate(solar_src_facular(gpt), stat=istat)
    2052        1536 :       call handle_allocate_error(istat, sub, 'solar_src_facular')
    2053        1536 :       ierr = pio_get_var(fh, vid, solar_src_facular)
    2054        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading solar_source_facular')
    2055             :    end if
    2056             : 
    2057        3072 :    ierr = pio_inq_varid(fh, 'solar_source_sunspot', vid)
    2058        3072 :    if (ierr == PIO_NOERR) then
    2059        4608 :       allocate(solar_src_sunspot(gpt), stat=istat)
    2060        1536 :       call handle_allocate_error(istat, sub, 'solar_src_sunspot')
    2061        1536 :       ierr = pio_get_var(fh, vid, solar_src_sunspot)
    2062        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading solar_source_sunspot')
    2063             :    end if
    2064             : 
    2065        3072 :    ierr = pio_inq_varid(fh, 'tsi_default', vid)
    2066        3072 :    if (ierr == PIO_NOERR) then
    2067        1536 :       ierr = pio_get_var(fh, vid, tsi_default)
    2068        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading tsi_default')
    2069             :    end if
    2070             : 
    2071        3072 :    ierr = pio_inq_varid(fh, 'mg_default', vid)
    2072        3072 :    if (ierr == PIO_NOERR) then
    2073        1536 :       ierr = pio_get_var(fh, vid, mg_default)
    2074        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading mg_default')
    2075             :    end if
    2076             : 
    2077        3072 :    ierr = pio_inq_varid(fh, 'sb_default', vid)
    2078        3072 :    if (ierr == PIO_NOERR) then
    2079        1536 :       ierr = pio_get_var(fh, vid, sb_default)
    2080        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading sb_default')
    2081             :    end if
    2082             : 
    2083             :    ! rayleigh scattering contribution in lower part of atmosphere
    2084        3072 :    ierr = pio_inq_varid(fh, 'rayl_lower', vid)
    2085        3072 :    if (ierr == PIO_NOERR) then
    2086        7680 :       allocate(rayl_lower(gpt,mixing_fraction,temperature), stat=istat)
    2087        1536 :       call handle_allocate_error(istat, sub, 'rayl_lower')
    2088        1536 :       ierr = pio_get_var(fh, vid, rayl_lower)
    2089        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading rayl_lower')
    2090             :    end if
    2091             : 
    2092             :    ! rayleigh scattering contribution in upper part of atmosphere
    2093        3072 :    ierr = pio_inq_varid(fh, 'rayl_upper', vid)
    2094        3072 :    if (ierr == PIO_NOERR) then
    2095        7680 :       allocate(rayl_upper(gpt,mixing_fraction,temperature), stat=istat)
    2096        1536 :       call handle_allocate_error(istat, sub, 'rayl_upper')
    2097        1536 :       ierr = pio_get_var(fh, vid, rayl_upper)
    2098        1536 :       if (ierr /= PIO_NOERR) call endrun(sub//': error reading rayl_upper')
    2099             :    end if
    2100             : 
    2101        9216 :    allocate(gas_minor(minorabsorbers), stat=istat)
    2102        3072 :    call handle_allocate_error(istat, sub, 'gas_minor')
    2103        3072 :    ierr = pio_inq_varid(fh, 'gas_minor', vid)
    2104        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': gas_minor not found')
    2105        3072 :    ierr = pio_get_var(fh, vid, gas_minor)
    2106        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading gas_minor')
    2107             : 
    2108        9216 :    allocate(identifier_minor(minorabsorbers), stat=istat)
    2109        3072 :    call handle_allocate_error(istat, sub, 'identifier_minor')
    2110        3072 :    ierr = pio_inq_varid(fh, 'identifier_minor', vid)
    2111        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': identifier_minor not found')
    2112        3072 :    ierr = pio_get_var(fh, vid, identifier_minor)
    2113        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading identifier_minor')
    2114             :    
    2115        9216 :    allocate(minor_gases_lower(minor_absorber_intervals_lower), stat=istat)
    2116        3072 :    call handle_allocate_error(istat, sub, 'minor_gases_lower')
    2117        3072 :    ierr = pio_inq_varid(fh, 'minor_gases_lower', vid)
    2118        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_gases_lower not found')
    2119        3072 :    ierr = pio_get_var(fh, vid, minor_gases_lower)
    2120        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_gases_lower')
    2121             : 
    2122        9216 :    allocate(minor_gases_upper(minor_absorber_intervals_upper), stat=istat)
    2123        3072 :    call handle_allocate_error(istat, sub, 'minor_gases_upper')
    2124        3072 :    ierr = pio_inq_varid(fh, 'minor_gases_upper', vid)
    2125        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_gases_upper not found')
    2126        3072 :    ierr = pio_get_var(fh, vid, minor_gases_upper)
    2127        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_gases_upper')
    2128             : 
    2129       12288 :    allocate(minor_limits_gpt_lower(pairs,minor_absorber_intervals_lower), stat=istat)
    2130        3072 :    call handle_allocate_error(istat, sub, 'minor_limits_gpt_lower')
    2131        3072 :    ierr = pio_inq_varid(fh, 'minor_limits_gpt_lower', vid)
    2132        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_limits_gpt_lower not found')
    2133        3072 :    ierr = pio_get_var(fh, vid, minor_limits_gpt_lower)
    2134        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_limits_gpt_lower')
    2135             : 
    2136       12288 :    allocate(minor_limits_gpt_upper(pairs,minor_absorber_intervals_upper), stat=istat)
    2137        3072 :    call handle_allocate_error(istat, sub, 'minor_limits_gpt_upper')
    2138        3072 :    ierr = pio_inq_varid(fh, 'minor_limits_gpt_upper', vid)
    2139        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_limits_gpt_upper not found')
    2140        3072 :    ierr = pio_get_var(fh, vid, minor_limits_gpt_upper)
    2141        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_limits_gpt_upper')
    2142             : 
    2143             :    ! Read as integer and convert to logical
    2144        9216 :    allocate(int2log(minor_absorber_intervals_lower), stat=istat)
    2145        3072 :    call handle_allocate_error(istat, sub, 'int2log for lower')
    2146             : 
    2147        9216 :    allocate(minor_scales_with_density_lower(minor_absorber_intervals_lower), stat=istat)
    2148        3072 :    call handle_allocate_error(istat, sub, 'minor_scales_with_density_lower')
    2149        3072 :    ierr = pio_inq_varid(fh, 'minor_scales_with_density_lower', vid)
    2150        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_scales_with_density_lower not found')
    2151        3072 :    ierr = pio_get_var(fh, vid, int2log)
    2152        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_scales_with_density_lower')
    2153      147456 :    do i = 1,minor_absorber_intervals_lower
    2154      147456 :       if (int2log(i) .eq. 0) then
    2155       53760 :          minor_scales_with_density_lower(i) = .false.
    2156             :       else
    2157       90624 :          minor_scales_with_density_lower(i) = .true.
    2158             :       end if
    2159             :    end do
    2160             : 
    2161        9216 :    allocate(scale_by_complement_lower(minor_absorber_intervals_lower), stat=istat)
    2162        3072 :    call handle_allocate_error(istat, sub, 'scale_by_complement_lower')
    2163        3072 :    ierr = pio_inq_varid(fh, 'scale_by_complement_lower', vid)
    2164        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': scale_by_complement_lower not found')
    2165        3072 :    ierr = pio_get_var(fh, vid, int2log)
    2166        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading scale_by_complement_lower')
    2167      147456 :    do i = 1,minor_absorber_intervals_lower
    2168      147456 :       if (int2log(i) .eq. 0) then
    2169      104448 :          scale_by_complement_lower(i) = .false.
    2170             :       else
    2171       39936 :          scale_by_complement_lower(i) = .true.
    2172             :       end if
    2173             :    end do
    2174             : 
    2175        3072 :    deallocate(int2log)
    2176             : 
    2177             :    ! Read as integer and convert to logical
    2178        9216 :    allocate(int2log(minor_absorber_intervals_upper), stat=istat)
    2179        3072 :    call handle_allocate_error(istat, sub, 'int2log for upper')
    2180             : 
    2181        9216 :    allocate(minor_scales_with_density_upper(minor_absorber_intervals_upper), stat=istat)
    2182        3072 :    call handle_allocate_error(istat, sub, 'minor_scales_with_density_upper')
    2183        3072 :    ierr = pio_inq_varid(fh, 'minor_scales_with_density_upper', vid)
    2184        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': minor_scales_with_density_upper not found')
    2185        3072 :    ierr = pio_get_var(fh, vid, int2log)
    2186        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_scales_with_density_upper')
    2187       92160 :    do i = 1,minor_absorber_intervals_upper
    2188       92160 :       if (int2log(i) .eq. 0) then
    2189       46080 :          minor_scales_with_density_upper(i) = .false.
    2190             :       else
    2191       43008 :          minor_scales_with_density_upper(i) = .true.
    2192             :       end if
    2193             :    end do
    2194             : 
    2195        9216 :    allocate(scale_by_complement_upper(minor_absorber_intervals_upper), stat=istat)
    2196        3072 :    call handle_allocate_error(istat, sub, 'scale_by_complement_upper')
    2197        3072 :    ierr = pio_inq_varid(fh, 'scale_by_complement_upper', vid)
    2198        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': scale_by_complement_upper not found')
    2199        3072 :    ierr = pio_get_var(fh, vid, int2log)
    2200        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading scale_by_complement_upper')
    2201       92160 :    do i = 1,minor_absorber_intervals_upper
    2202       92160 :       if (int2log(i) .eq. 0) then
    2203       70656 :          scale_by_complement_upper(i) = .false.
    2204             :       else
    2205       18432 :          scale_by_complement_upper(i) = .true.
    2206             :       end if
    2207             :    end do
    2208             : 
    2209        3072 :    deallocate(int2log)
    2210             : 
    2211        9216 :    allocate(scaling_gas_lower(minor_absorber_intervals_lower), stat=istat)
    2212        3072 :    call handle_allocate_error(istat, sub, 'scaling_gas_lower')
    2213        3072 :    ierr = pio_inq_varid(fh, 'scaling_gas_lower', vid)
    2214        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': scaling_gas_lower not found')
    2215        3072 :    ierr = pio_get_var(fh, vid, scaling_gas_lower)
    2216        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading scaling_gas_lower')
    2217             : 
    2218        9216 :    allocate(scaling_gas_upper(minor_absorber_intervals_upper), stat=istat)
    2219        3072 :    call handle_allocate_error(istat, sub, 'scaling_gas_upper')
    2220        3072 :    ierr = pio_inq_varid(fh, 'scaling_gas_upper', vid)
    2221        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': scaling_gas_upper not found')
    2222        3072 :    ierr = pio_get_var(fh, vid, scaling_gas_upper)
    2223        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading scaling_gas_upper')
    2224             : 
    2225        9216 :    allocate(kminor_start_lower(minor_absorber_intervals_lower), stat=istat)
    2226        3072 :    call handle_allocate_error(istat, sub, 'kminor_start_lower')
    2227        3072 :    ierr = pio_inq_varid(fh, 'kminor_start_lower', vid)
    2228        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': kminor_start_lower not found')
    2229        3072 :    ierr = pio_get_var(fh, vid, kminor_start_lower)
    2230        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_start_lower')
    2231             : 
    2232        9216 :    allocate(kminor_start_upper(minor_absorber_intervals_upper), stat=istat)
    2233        3072 :    call handle_allocate_error(istat, sub, 'kminor_start_upper')
    2234        3072 :    ierr = pio_inq_varid(fh, 'kminor_start_upper', vid)
    2235        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': kminor_start_upper not found')
    2236        3072 :    ierr = pio_get_var(fh, vid, kminor_start_upper)
    2237        3072 :    if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_start_upper')
    2238             : 
    2239             :    ! Close file
    2240        3072 :    call pio_closefile(fh)
    2241             : 
    2242             :    ! Initialize the gas optics object with data. The calls are slightly different depending
    2243             :    ! on whether the radiation sources are internal to the atmosphere (longwave) or external (shortwave)
    2244             : 
    2245        3072 :    if (allocated(totplnk) .and. allocated(planck_frac)) then
    2246             :       error_msg = kdist%load( &
    2247             :          available_gases, gas_names, key_species,              &
    2248             :          band2gpt, band_lims_wavenum,                          &
    2249             :          press_ref, press_ref_trop, temp_ref,                  &
    2250             :          temp_ref_p, temp_ref_t, vmr_ref,                      &
    2251             :          kmajor, kminor_lower, kminor_upper,                   &
    2252             :          gas_minor, identifier_minor,                          &
    2253             :          minor_gases_lower, minor_gases_upper,                 &
    2254             :          minor_limits_gpt_lower, minor_limits_gpt_upper,       &
    2255             :          minor_scales_with_density_lower,                      &
    2256             :          minor_scales_with_density_upper,                      &
    2257             :          scaling_gas_lower, scaling_gas_upper,                 &
    2258             :          scale_by_complement_lower, scale_by_complement_upper, &
    2259             :          kminor_start_lower, kminor_start_upper,               &
    2260             :          totplnk, planck_frac, rayl_lower, rayl_upper,         &
    2261        1536 :          optimal_angle_fit)
    2262        1536 :    else if (allocated(solar_src_quiet)) then
    2263             :       error_msg = kdist%load( &
    2264             :          available_gases, gas_names, key_species,               &
    2265             :          band2gpt, band_lims_wavenum,                           &
    2266             :          press_ref, press_ref_trop, temp_ref,                   &
    2267             :          temp_ref_p, temp_ref_t, vmr_ref,                       & 
    2268             :          kmajor, kminor_lower, kminor_upper,                    &
    2269             :          gas_minor, identifier_minor,                           &
    2270             :          minor_gases_lower, minor_gases_upper,                  &
    2271             :          minor_limits_gpt_lower, minor_limits_gpt_upper,        &
    2272             :          minor_scales_with_density_lower,                       &
    2273             :          minor_scales_with_density_upper,                       &
    2274             :          scaling_gas_lower, scaling_gas_upper,                  &
    2275             :          scale_by_complement_lower,                             &
    2276             :          scale_by_complement_upper,                             &
    2277             :          kminor_start_lower,                                    &
    2278             :          kminor_start_upper,                                    &
    2279             :          solar_src_quiet, solar_src_facular, solar_src_sunspot, &
    2280             :          tsi_default, mg_default, sb_default,                   &
    2281        1536 :          rayl_lower, rayl_upper)
    2282             :    else
    2283           0 :       error_msg = 'must supply either totplnk and planck_frac, or solar_src_[*]'
    2284             :    end if
    2285             : 
    2286        3072 :    call stop_on_err(error_msg, sub, 'kdist%load')
    2287             : 
    2288           0 :    deallocate( &
    2289           0 :       gas_names, key_species,               &
    2290           0 :       band2gpt, band_lims_wavenum,          &
    2291           0 :       press_ref, temp_ref, vmr_ref,         &
    2292           0 :       kmajor, kminor_lower, kminor_upper,   &
    2293           0 :       gas_minor, identifier_minor,          &
    2294           0 :       minor_gases_lower, minor_gases_upper, &
    2295           0 :       minor_limits_gpt_lower,               & 
    2296           0 :       minor_limits_gpt_upper,               &
    2297           0 :       minor_scales_with_density_lower,      &
    2298           0 :       minor_scales_with_density_upper,      &
    2299           0 :       scale_by_complement_lower,            & 
    2300           0 :       scale_by_complement_upper,            &
    2301           0 :       scaling_gas_lower, scaling_gas_upper, & 
    2302        3072 :       kminor_start_lower, kminor_start_upper)
    2303             : 
    2304        3072 :    if (allocated(totplnk))           deallocate(totplnk)
    2305        3072 :    if (allocated(planck_frac))       deallocate(planck_frac)
    2306        3072 :    if (allocated(optimal_angle_fit)) deallocate(optimal_angle_fit)
    2307        3072 :    if (allocated(solar_src_quiet))   deallocate(solar_src_quiet)
    2308        3072 :    if (allocated(solar_src_facular)) deallocate(solar_src_facular)
    2309        3072 :    if (allocated(solar_src_sunspot)) deallocate(solar_src_sunspot)
    2310        3072 :    if (allocated(rayl_lower))        deallocate(rayl_lower)
    2311        3072 :    if (allocated(rayl_upper))        deallocate(rayl_upper)
    2312             : 
    2313        6144 : end subroutine coefs_init
    2314             : 
    2315             : !=========================================================================================
    2316             : 
    2317     5969088 : subroutine initialize_rrtmgp_fluxes(ncol, nlevels, nbands, fluxes, do_direct)
    2318             : 
    2319             :    ! Allocate flux arrays and set values to zero.
    2320             : 
    2321             :    ! Arguments
    2322             :    integer,                    intent(in)    :: ncol, nlevels, nbands
    2323             :    class(ty_fluxes_broadband), intent(inout) :: fluxes
    2324             :    logical, optional,          intent(in)    :: do_direct
    2325             : 
    2326             :    ! Local variables
    2327             :    logical :: do_direct_local
    2328             :    integer :: istat
    2329             :    character(len=*), parameter :: sub = 'initialize_rrtmgp_fluxes'
    2330             :    !----------------------------------------------------------------------------
    2331             : 
    2332     5969088 :    if (present(do_direct)) then
    2333             :       do_direct_local = .true.
    2334             :    else
    2335     2984544 :       do_direct_local = .false.
    2336             :    end if
    2337             : 
    2338             :    ! Broadband fluxes
    2339    22448964 :    allocate(fluxes%flux_up(ncol, nlevels), stat=istat)
    2340     5969088 :    call handle_allocate_error(istat, sub, 'fluxes%flux_up')
    2341    16479876 :    allocate(fluxes%flux_dn(ncol, nlevels), stat=istat)
    2342     5969088 :    call handle_allocate_error(istat, sub, 'fluxes%flux_dn')
    2343    16479876 :    allocate(fluxes%flux_net(ncol, nlevels), stat=istat)
    2344     5969088 :    call handle_allocate_error(istat, sub, 'fluxes%flux_net')
    2345     5969088 :    if (do_direct_local) then
    2346     7526244 :       allocate(fluxes%flux_dn_dir(ncol, nlevels), stat=istat)
    2347     2984544 :       call handle_allocate_error(istat, sub, 'fluxes%flux_dn_dir')
    2348             :    end if
    2349             : 
    2350             :    select type (fluxes)
    2351             :    type is (ty_fluxes_byband)
    2352             :       ! Fluxes by band always needed for SW.  Only allocate for LW
    2353             :       ! when spectralflux is true.
    2354     2984544 :       if (nbands == nswbands .or. spectralflux) then
    2355     6747666 :          allocate(fluxes%bnd_flux_up(ncol, nlevels, nbands), stat=istat)
    2356     1492272 :          call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_up')
    2357     5255394 :          allocate(fluxes%bnd_flux_dn(ncol, nlevels, nbands), stat=istat)
    2358     1492272 :          call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_dn')
    2359     5255394 :          allocate(fluxes%bnd_flux_net(ncol, nlevels, nbands), stat=istat)
    2360     1492272 :          call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_net')
    2361     1492272 :          if (do_direct_local) then
    2362     5255394 :             allocate(fluxes%bnd_flux_dn_dir(ncol, nlevels, nbands), stat=istat)
    2363     1492272 :             call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_dn_dir')
    2364             :          end if
    2365             :       end if
    2366             :    end select
    2367             : 
    2368             :    ! Initialize
    2369     5969088 :    call reset_fluxes(fluxes)
    2370             : 
    2371     5969088 : end subroutine initialize_rrtmgp_fluxes
    2372             : 
    2373             : !=========================================================================================
    2374             : 
    2375     5969088 : subroutine reset_fluxes(fluxes)
    2376             : 
    2377             :    ! Reset flux arrays to zero.
    2378             : 
    2379             :    class(ty_fluxes_broadband), intent(inout) :: fluxes
    2380             :    !----------------------------------------------------------------------------
    2381             : 
    2382             :    ! Reset broadband fluxes
    2383  7249214448 :    fluxes%flux_up(:,:) = 0._r8
    2384  7249214448 :    fluxes%flux_dn(:,:) = 0._r8
    2385  7249214448 :    fluxes%flux_net(:,:) = 0._r8
    2386  2514894768 :    if (associated(fluxes%flux_dn_dir)) fluxes%flux_dn_dir(:,:) = 0._r8
    2387             : 
    2388             :    select type (fluxes)
    2389             :    type is (ty_fluxes_byband)
    2390             :       ! Reset band-by-band fluxes
    2391 17584863840 :       if (associated(fluxes%bnd_flux_up)) fluxes%bnd_flux_up(:,:,:) = 0._r8
    2392 17586356112 :       if (associated(fluxes%bnd_flux_dn)) fluxes%bnd_flux_dn(:,:,:) = 0._r8
    2393 17586356112 :       if (associated(fluxes%bnd_flux_net)) fluxes%bnd_flux_net(:,:,:) = 0._r8
    2394 17589340656 :       if (associated(fluxes%bnd_flux_dn_dir)) fluxes%bnd_flux_dn_dir(:,:,:) = 0._r8
    2395             :    end select
    2396             : 
    2397     5969088 : end subroutine reset_fluxes
    2398             : 
    2399             : !=========================================================================================
    2400             : 
    2401     4476816 : subroutine free_optics_sw(optics)
    2402             : 
    2403             :    type(ty_optical_props_2str), intent(inout) :: optics
    2404             : 
    2405     4476816 :    if (allocated(optics%tau)) deallocate(optics%tau)
    2406     4476816 :    if (allocated(optics%ssa)) deallocate(optics%ssa)
    2407     4476816 :    if (allocated(optics%g)) deallocate(optics%g)
    2408     4476816 :    call optics%finalize()
    2409             : 
    2410     4476816 : end subroutine free_optics_sw
    2411             : 
    2412             : !=========================================================================================
    2413             : 
    2414     2984544 : subroutine free_optics_lw(optics)
    2415             : 
    2416             :    type(ty_optical_props_1scl), intent(inout) :: optics
    2417             : 
    2418     2984544 :    if (allocated(optics%tau)) deallocate(optics%tau)
    2419     2984544 :    call optics%finalize()
    2420             : 
    2421     2984544 : end subroutine free_optics_lw
    2422             : 
    2423             : !=========================================================================================
    2424             : 
    2425     5969088 : subroutine free_fluxes(fluxes)
    2426             : 
    2427             :    class(ty_fluxes_broadband), intent(inout) :: fluxes
    2428             : 
    2429     5969088 :    if (associated(fluxes%flux_up)) deallocate(fluxes%flux_up)
    2430     5969088 :    if (associated(fluxes%flux_dn)) deallocate(fluxes%flux_dn)
    2431     5969088 :    if (associated(fluxes%flux_net)) deallocate(fluxes%flux_net)
    2432     5969088 :    if (associated(fluxes%flux_dn_dir)) deallocate(fluxes%flux_dn_dir)
    2433             : 
    2434             :    select type (fluxes)
    2435             :    type is (ty_fluxes_byband)
    2436     1492272 :       if (associated(fluxes%bnd_flux_up)) deallocate(fluxes%bnd_flux_up)
    2437     2984544 :       if (associated(fluxes%bnd_flux_dn)) deallocate(fluxes%bnd_flux_dn)
    2438     2984544 :       if (associated(fluxes%bnd_flux_net)) deallocate(fluxes%bnd_flux_net)
    2439     5969088 :       if (associated(fluxes%bnd_flux_dn_dir)) deallocate(fluxes%bnd_flux_dn_dir)
    2440             :    end select
    2441             : 
    2442     5969088 : end subroutine free_fluxes
    2443             : 
    2444             : !=========================================================================================
    2445             : 
    2446      746136 : subroutine modified_cloud_fraction(ncol, cld, cldfsnow, cldfgrau, cldfprime)
    2447             : 
    2448             :    ! Compute modified cloud fraction, cldfprime.
    2449             :    ! 1. initialize as cld
    2450             :    ! 2. modify for snow if cldfsnow is available. use max(cld, cldfsnow)
    2451             :    ! 3. modify for graupel if cldfgrau is available and graupel_in_rad is true.
    2452             :    !    use max(cldfprime, cldfgrau)
    2453             : 
    2454             :    ! Arguments
    2455             :    integer,  intent(in)  :: ncol
    2456             :    real(r8), pointer     :: cld(:,:)       ! cloud fraction
    2457             :    real(r8), pointer     :: cldfsnow(:,:)  ! cloud fraction of just "snow clouds"
    2458             :    real(r8), pointer     :: cldfgrau(:,:)  ! cloud fraction of just "graupel clouds"
    2459             :    real(r8), intent(out) :: cldfprime(:,:) ! modified cloud fraction
    2460             : 
    2461             :    ! Local variables
    2462             :    integer :: i, k
    2463             :    !----------------------------------------------------------------------------
    2464             : 
    2465      746136 :    if (associated(cldfsnow)) then
    2466    70136784 :       do k = 1, pver
    2467  1159408584 :          do i = 1, ncol
    2468  1158662448 :             cldfprime(i,k) = max(cld(i,k), cldfsnow(i,k))
    2469             :          end do
    2470             :       end do
    2471             :    else
    2472           0 :       cldfprime(:ncol,:) = cld(:ncol,:)
    2473             :    end if
    2474             : 
    2475      746136 :    if (associated(cldfgrau) .and. graupel_in_rad) then
    2476           0 :       do k = 1, pver
    2477           0 :          do i = 1, ncol
    2478           0 :             cldfprime(i,k) = max(cldfprime(i,k), cldfgrau(i,k))
    2479             :          end do
    2480             :       end do
    2481             :    end if
    2482             : 
    2483      746136 : end subroutine modified_cloud_fraction
    2484             : 
    2485             : !=========================================================================================
    2486             : 
    2487     9833936 : subroutine stop_on_err(errmsg, sub, info)
    2488             : 
    2489             : ! call endrun if RRTMGP function returns non-empty error message.
    2490             : 
    2491             :    character(len=*), intent(in) :: errmsg    ! return message from RRTMGP function
    2492             :    character(len=*), intent(in) :: sub       ! name of calling subroutine
    2493             :    character(len=*), intent(in) :: info      ! name of called function
    2494             : 
    2495     9833936 :    if (len_trim(errmsg) > 0) then
    2496           0 :       call endrun(trim(sub)//': ERROR: '//trim(info)//': '//trim(errmsg))
    2497             :    end if
    2498             : 
    2499     9833936 : end subroutine stop_on_err
    2500             : 
    2501             : !=========================================================================================
    2502             : 
    2503    17907264 : end module radiation
    2504             : 

Generated by: LCOV version 1.14