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 :
20 : use time_manager, only: get_nstep, is_first_step, is_first_restart_step, &
21 : get_curr_calday, get_step_size
22 :
23 : use rad_constituents, only: N_DIAG, rad_cnst_get_call_list, rad_cnst_get_gas, rad_cnst_out
24 :
25 : use rrtmgp_inputs, only: rrtmgp_inputs_init
26 :
27 : use radconstants, only: nradgas, gasnamelength, gaslist, nswbands, nlwbands, &
28 : nswgpts, set_wavenumber_bands
29 : use rad_solar_var, only: rad_solar_var_init, get_variability
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 226008 : 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 226008 : if (present(timestep)) then
359 226008 : nstep = timestep
360 : else
361 0 : nstep = get_nstep()
362 : end if
363 :
364 164088 : 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 164088 : .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 61920 : .or. nstep <= irad_always
373 : case default
374 226008 : call endrun('radiation_do: unknown operation:'//op)
375 : end select
376 :
377 226008 : end function radiation_do
378 :
379 : !================================================================================================
380 :
381 61920 : 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 61920 : radiation_nextsw_cday = -1._r8
396 61920 : dosw = .false.
397 61920 : nstep = get_nstep()
398 61920 : dtime = get_step_size()
399 61920 : offset = 0
400 : do while (.not. dosw)
401 102168 : nstep = nstep + 1
402 102168 : offset = offset + dtime
403 102168 : if (radiation_do('sw', nstep)) then
404 61920 : radiation_nextsw_cday = get_curr_calday(offset=offset)
405 : dosw = .true.
406 : end if
407 : end do
408 61920 : 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 61920 : if (get_nstep() >= 1) then
414 55728 : caldayp1 = get_curr_calday(offset=int(dtime))
415 55728 : if (caldayp1 /= radiation_nextsw_cday) radiation_nextsw_cday = -1._r8
416 : end if
417 :
418 61920 : 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 1536 : call rad_solar_var_init()
499 :
500 : ! The spectral band boundaries need to be set before this init is called.
501 1536 : call rrtmgp_inputs_init(ktopcam, ktoprad)
502 :
503 : ! initialize output fields for offline driver
504 1536 : call rad_data_init(pbuf2d)
505 :
506 1536 : call cloud_rad_props_init()
507 :
508 1536 : cld_idx = pbuf_get_index('CLD')
509 1536 : cldfsnow_idx = pbuf_get_index('CLDFSNOW', errcode=ierr)
510 1536 : cldfgrau_idx = pbuf_get_index('CLDFGRAU', errcode=ierr)
511 :
512 1536 : if (is_first_step()) then
513 768 : call pbuf_set_field(pbuf2d, qrl_idx, 0._r8)
514 : end if
515 :
516 : ! Set the radiation timestep for cosz calculations if requested using
517 : ! the adjusted iradsw value from radiation
518 1536 : if (use_rad_dt_cosz) then
519 0 : dtime = get_step_size()
520 0 : dt_avg = iradsw*dtime
521 : end if
522 :
523 : ! Surface components to get radiation computed today
524 1536 : if (.not. is_first_restart_step()) then
525 768 : nextsw_cday = get_curr_calday()
526 : end if
527 :
528 : call phys_getopts(history_amwg_out = history_amwg, &
529 : history_vdiag_out = history_vdiag, &
530 : history_budget_out = history_budget, &
531 1536 : history_budget_histfile_num_out = history_budget_histfile_num)
532 :
533 : ! "irad_always" is number of time steps to execute radiation continuously from
534 : ! start of initial OR restart run
535 1536 : nstep = get_nstep()
536 1536 : if (irad_always > 0) then
537 0 : irad_always = irad_always + nstep
538 : end if
539 :
540 1536 : if (docosp) call cospsimulator_intr_init()
541 :
542 4608 : allocate(cosp_cnt(begchunk:endchunk), stat=istat)
543 1536 : call handle_allocate_error(istat, sub, 'cosp_cnt')
544 1536 : if (is_first_restart_step()) then
545 3864 : cosp_cnt(begchunk:endchunk) = cosp_cnt_init
546 : else
547 3864 : cosp_cnt(begchunk:endchunk) = 0
548 : end if
549 :
550 : ! Add fields to history buffer
551 :
552 : call addfld('TOT_CLD_VISTAU', (/ 'lev' /), 'A', '1', &
553 : 'Total gbx cloud extinction visible sw optical depth', &
554 3072 : sampling_seq='rad_lwsw', flag_xyfill=.true.)
555 : call addfld('TOT_ICLD_VISTAU', (/ 'lev' /), 'A', '1', &
556 : 'Total in-cloud extinction visible sw optical depth', &
557 3072 : sampling_seq='rad_lwsw', flag_xyfill=.true.)
558 : call addfld('LIQ_ICLD_VISTAU', (/ 'lev' /), 'A', '1', &
559 : 'Liquid in-cloud extinction visible sw optical depth', &
560 3072 : sampling_seq='rad_lwsw', flag_xyfill=.true.)
561 : call addfld('ICE_ICLD_VISTAU', (/ 'lev' /), 'A', '1', &
562 : 'Ice in-cloud extinction visible sw optical depth', &
563 3072 : sampling_seq='rad_lwsw', flag_xyfill=.true.)
564 :
565 1536 : if (cldfsnow_idx > 0) then
566 : call addfld('SNOW_ICLD_VISTAU', (/ 'lev' /), 'A', '1', &
567 : 'Snow in-cloud extinction visible sw optical depth', &
568 3072 : sampling_seq='rad_lwsw', flag_xyfill=.true.)
569 : end if
570 1536 : if (cldfgrau_idx > 0 .and. graupel_in_rad) then
571 : call addfld('GRAU_ICLD_VISTAU', (/ 'lev' /), 'A', '1', &
572 : 'Graupel in-cloud extinction visible sw optical depth', &
573 0 : sampling_seq='rad_lwsw', flag_xyfill=.true.)
574 : endif
575 :
576 : ! get list of active radiation calls
577 1536 : call rad_cnst_get_call_list(active_calls)
578 :
579 : ! Add shortwave radiation fields to history master field list.
580 :
581 18432 : do icall = 0, N_DIAG
582 :
583 18432 : if (active_calls(icall)) then
584 :
585 : call addfld('SOLIN'//diag(icall), horiz_only, 'A', 'W/m2', &
586 1536 : 'Solar insolation', sampling_seq='rad_lwsw')
587 : call addfld('QRS'//diag(icall), (/ 'lev' /), 'A', 'K/s', &
588 3072 : 'Solar heating rate', sampling_seq='rad_lwsw')
589 : call addfld('QRSC'//diag(icall), (/ 'lev' /), 'A', 'K/s', &
590 3072 : 'Clearsky solar heating rate', sampling_seq='rad_lwsw')
591 : call addfld('FSNT'//diag(icall), horiz_only, 'A', 'W/m2', &
592 1536 : 'Net solar flux at top of model', sampling_seq='rad_lwsw')
593 : call addfld('FSNTC'//diag(icall), horiz_only, 'A', 'W/m2', &
594 1536 : 'Clearsky net solar flux at top of model', sampling_seq='rad_lwsw')
595 : call addfld('FSNTOA'//diag(icall), horiz_only, 'A', 'W/m2', &
596 1536 : 'Net solar flux at top of atmosphere', sampling_seq='rad_lwsw')
597 : call addfld('FSNTOAC'//diag(icall), horiz_only, 'A', 'W/m2', &
598 1536 : 'Clearsky net solar flux at top of atmosphere', sampling_seq='rad_lwsw')
599 : call addfld('SWCF'//diag(icall), horiz_only, 'A', 'W/m2', &
600 1536 : 'Shortwave cloud forcing', sampling_seq='rad_lwsw')
601 : call addfld('FSUTOA'//diag(icall), horiz_only, 'A', 'W/m2', &
602 1536 : 'Upwelling solar flux at top of atmosphere', sampling_seq='rad_lwsw')
603 : call addfld('FSNIRTOA'//diag(icall), horiz_only, 'A', 'W/m2', &
604 1536 : 'Net near-infrared flux (Nimbus-7 WFOV) at top of atmosphere', sampling_seq='rad_lwsw')
605 : call addfld('FSNRTOAC'//diag(icall), horiz_only, 'A', 'W/m2', &
606 1536 : 'Clearsky net near-infrared flux (Nimbus-7 WFOV) at top of atmosphere', sampling_seq='rad_lwsw')
607 : call addfld('FSNRTOAS'//diag(icall), horiz_only, 'A', 'W/m2', &
608 1536 : 'Net near-infrared flux (>= 0.7 microns) at top of atmosphere', sampling_seq='rad_lwsw')
609 : call addfld('FSN200'//diag(icall), horiz_only, 'A', 'W/m2', &
610 1536 : 'Net shortwave flux at 200 mb', sampling_seq='rad_lwsw')
611 : call addfld('FSN200C'//diag(icall), horiz_only, 'A', 'W/m2', &
612 1536 : 'Clearsky net shortwave flux at 200 mb', sampling_seq='rad_lwsw')
613 : call addfld('FSNR'//diag(icall), horiz_only, 'A', 'W/m2', &
614 1536 : 'Net solar flux at tropopause', sampling_seq='rad_lwsw')
615 : call addfld('SOLL'//diag(icall), horiz_only, 'A', 'W/m2', &
616 1536 : 'Solar downward near infrared direct to surface', sampling_seq='rad_lwsw')
617 : call addfld('SOLS'//diag(icall), horiz_only, 'A', 'W/m2', &
618 1536 : 'Solar downward visible direct to surface', sampling_seq='rad_lwsw')
619 : call addfld('SOLLD'//diag(icall), horiz_only, 'A', 'W/m2', &
620 1536 : 'Solar downward near infrared diffuse to surface', sampling_seq='rad_lwsw')
621 : call addfld('SOLSD'//diag(icall), horiz_only, 'A', 'W/m2', &
622 1536 : 'Solar downward visible diffuse to surface', sampling_seq='rad_lwsw')
623 : call addfld('FSNS'//diag(icall), horiz_only, 'A', 'W/m2', &
624 1536 : 'Net solar flux at surface', sampling_seq='rad_lwsw')
625 : call addfld('FSNSC'//diag(icall), horiz_only, 'A', 'W/m2', &
626 1536 : 'Clearsky net solar flux at surface', sampling_seq='rad_lwsw')
627 : call addfld('FSDS'//diag(icall), horiz_only, 'A', 'W/m2', &
628 1536 : 'Downwelling solar flux at surface', sampling_seq='rad_lwsw')
629 : call addfld('FSDSC'//diag(icall), horiz_only, 'A', 'W/m2', &
630 1536 : 'Clearsky downwelling solar flux at surface', sampling_seq='rad_lwsw')
631 :
632 : ! Fluxes on CAM grid
633 : call addfld('FUS'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
634 3072 : 'Shortwave upward flux', sampling_seq='rad_lwsw')
635 : call addfld('FDS'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
636 3072 : 'Shortwave downward flux', sampling_seq='rad_lwsw')
637 : call addfld('FUSC'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
638 3072 : 'Shortwave clear-sky upward flux', sampling_seq='rad_lwsw')
639 : call addfld('FDSC'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
640 3072 : 'Shortwave clear-sky downward flux', sampling_seq='rad_lwsw')
641 :
642 1536 : if (history_amwg) then
643 1536 : call add_default('SOLIN'//diag(icall), 1, ' ')
644 1536 : call add_default('QRS'//diag(icall), 1, ' ')
645 1536 : call add_default('FSNT'//diag(icall), 1, ' ')
646 1536 : call add_default('FSNTC'//diag(icall), 1, ' ')
647 1536 : call add_default('FSNTOA'//diag(icall), 1, ' ')
648 1536 : call add_default('FSNTOAC'//diag(icall), 1, ' ')
649 1536 : call add_default('SWCF'//diag(icall), 1, ' ')
650 1536 : call add_default('FSNS'//diag(icall), 1, ' ')
651 1536 : call add_default('FSNSC'//diag(icall), 1, ' ')
652 1536 : call add_default('FSUTOA'//diag(icall), 1, ' ')
653 1536 : call add_default('FSDSC'//diag(icall), 1, ' ')
654 1536 : call add_default('FSDS'//diag(icall), 1, ' ')
655 : endif
656 :
657 : end if
658 : end do
659 :
660 1536 : if (scm_crm_mode) then
661 0 : call add_default('FUS ', 1, ' ')
662 0 : call add_default('FUSC ', 1, ' ')
663 0 : call add_default('FDS ', 1, ' ')
664 0 : call add_default('FDSC ', 1, ' ')
665 : endif
666 :
667 : ! Add longwave radiation fields to history master field list.
668 :
669 18432 : do icall = 0, N_DIAG
670 :
671 18432 : if (active_calls(icall)) then
672 : call addfld('QRL'//diag(icall), (/ 'lev' /), 'A', 'K/s', &
673 3072 : 'Longwave heating rate', sampling_seq='rad_lwsw')
674 : call addfld('QRLC'//diag(icall), (/ 'lev' /), 'A', 'K/s', &
675 3072 : 'Clearsky longwave heating rate', sampling_seq='rad_lwsw')
676 : call addfld('FLNT'//diag(icall), horiz_only, 'A', 'W/m2', &
677 1536 : 'Net longwave flux at top of model', sampling_seq='rad_lwsw')
678 : call addfld('FLNTC'//diag(icall), horiz_only, 'A', 'W/m2', &
679 1536 : 'Clearsky net longwave flux at top of model', sampling_seq='rad_lwsw')
680 : call addfld('FLUT'//diag(icall), horiz_only, 'A', 'W/m2', &
681 1536 : 'Upwelling longwave flux at top of model', sampling_seq='rad_lwsw')
682 : call addfld('FLUTC'//diag(icall), horiz_only, 'A', 'W/m2', &
683 1536 : 'Clearsky upwelling longwave flux at top of model', sampling_seq='rad_lwsw')
684 : call addfld('LWCF'//diag(icall), horiz_only, 'A', 'W/m2', &
685 1536 : 'Longwave cloud forcing', sampling_seq='rad_lwsw')
686 : call addfld('FLN200'//diag(icall), horiz_only, 'A', 'W/m2', &
687 1536 : 'Net longwave flux at 200 mb', sampling_seq='rad_lwsw')
688 : call addfld('FLN200C'//diag(icall), horiz_only, 'A', 'W/m2', &
689 1536 : 'Clearsky net longwave flux at 200 mb', sampling_seq='rad_lwsw')
690 : call addfld('FLNR'//diag(icall), horiz_only, 'A', 'W/m2', &
691 1536 : 'Net longwave flux at tropopause', sampling_seq='rad_lwsw')
692 : call addfld('FLNS'//diag(icall), horiz_only, 'A', 'W/m2', &
693 1536 : 'Net longwave flux at surface', sampling_seq='rad_lwsw')
694 : call addfld('FLNSC'//diag(icall), horiz_only, 'A', 'W/m2', &
695 1536 : 'Clearsky net longwave flux at surface', sampling_seq='rad_lwsw')
696 : call addfld('FLDS'//diag(icall), horiz_only, 'A', 'W/m2', &
697 1536 : 'Downwelling longwave flux at surface', sampling_seq='rad_lwsw')
698 : call addfld('FLDSC'//diag(icall), horiz_only, 'A', 'W/m2', &
699 1536 : 'Clearsky Downwelling longwave flux at surface', sampling_seq='rad_lwsw')
700 :
701 : ! Fluxes on CAM grid
702 : call addfld('FUL'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
703 3072 : 'Longwave upward flux', sampling_seq='rad_lwsw')
704 : call addfld('FDL'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
705 3072 : 'Longwave downward flux', sampling_seq='rad_lwsw')
706 : call addfld('FULC'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
707 3072 : 'Longwave clear-sky upward flux', sampling_seq='rad_lwsw')
708 : call addfld('FDLC'//diag(icall), (/ 'ilev' /), 'I', 'W/m2', &
709 3072 : 'Longwave clear-sky downward flux', sampling_seq='rad_lwsw')
710 :
711 1536 : if (history_amwg) then
712 1536 : call add_default('QRL'//diag(icall), 1, ' ')
713 1536 : call add_default('FLNT'//diag(icall), 1, ' ')
714 1536 : call add_default('FLNTC'//diag(icall), 1, ' ')
715 1536 : call add_default('FLUT'//diag(icall), 1, ' ')
716 1536 : call add_default('FLUTC'//diag(icall), 1, ' ')
717 1536 : call add_default('LWCF'//diag(icall), 1, ' ')
718 1536 : call add_default('FLNS'//diag(icall), 1, ' ')
719 1536 : call add_default('FLNSC'//diag(icall), 1, ' ')
720 1536 : call add_default('FLDS'//diag(icall), 1, ' ')
721 : end if
722 :
723 : end if
724 : end do
725 :
726 3072 : call addfld('EMIS', (/ 'lev' /), 'A', '1', 'Cloud longwave emissivity')
727 :
728 1536 : if (scm_crm_mode) then
729 0 : call add_default ('FUL ', 1, ' ')
730 0 : call add_default ('FULC ', 1, ' ')
731 0 : call add_default ('FDL ', 1, ' ')
732 0 : call add_default ('FDLC ', 1, ' ')
733 : endif
734 :
735 : ! Heating rate needed for d(theta)/dt computation
736 3072 : call addfld ('HR',(/ 'lev' /), 'A','K/s','Heating rate needed for d(theta)/dt computation')
737 :
738 1536 : if ( history_budget .and. history_budget_histfile_num > 1 ) then
739 0 : call add_default ('QRL ', history_budget_histfile_num, ' ')
740 0 : call add_default ('QRS ', history_budget_histfile_num, ' ')
741 : end if
742 :
743 1536 : if (history_vdiag) then
744 0 : call add_default('FLUT', 2, ' ')
745 0 : call add_default('FLUT', 3, ' ')
746 : end if
747 :
748 3072 : end subroutine radiation_init
749 :
750 : !===============================================================================
751 :
752 1536 : subroutine radiation_define_restart(file)
753 :
754 : ! define variables to be written to restart file
755 :
756 : ! arguments
757 : type(file_desc_t), intent(inout) :: file
758 :
759 : ! local variables
760 : integer :: ierr
761 : !----------------------------------------------------------------------------
762 :
763 1536 : call pio_seterrorhandling(file, PIO_BCAST_ERROR)
764 :
765 1536 : ierr = pio_def_var(file, 'nextsw_cday', pio_double, nextsw_cday_desc)
766 1536 : ierr = pio_put_att(file, nextsw_cday_desc, 'long_name', 'future radiation calday for surface models')
767 1536 : if (docosp) then
768 0 : ierr = pio_def_var(File, 'cosp_cnt_init', pio_int, cospcnt_desc)
769 : end if
770 :
771 1536 : end subroutine radiation_define_restart
772 :
773 : !===============================================================================
774 :
775 1536 : subroutine radiation_write_restart(file)
776 :
777 : ! write variables to restart file
778 :
779 : ! arguments
780 : type(file_desc_t), intent(inout) :: file
781 :
782 : ! local variables
783 : integer :: ierr
784 : !----------------------------------------------------------------------------
785 3072 : ierr = pio_put_var(File, nextsw_cday_desc, (/ nextsw_cday /))
786 1536 : if (docosp) then
787 0 : ierr = pio_put_var(File, cospcnt_desc, (/cosp_cnt(begchunk)/))
788 : end if
789 :
790 1536 : end subroutine radiation_write_restart
791 :
792 : !===============================================================================
793 :
794 768 : subroutine radiation_read_restart(file)
795 :
796 : ! read variables from restart file
797 :
798 : ! arguments
799 : type(file_desc_t), intent(inout) :: file
800 :
801 : ! local variables
802 : integer :: ierr
803 : type(var_desc_t) :: vardesc
804 : integer :: err_handling
805 :
806 : !----------------------------------------------------------------------------
807 768 : if (docosp) then
808 0 : call pio_seterrorhandling(File, PIO_BCAST_ERROR, err_handling)
809 0 : ierr = pio_inq_varid(File, 'cosp_cnt_init', vardesc)
810 0 : call pio_seterrorhandling(File, err_handling)
811 0 : if (ierr /= PIO_NOERR) then
812 0 : cosp_cnt_init = 0
813 : else
814 0 : ierr = pio_get_var(File, vardesc, cosp_cnt_init)
815 : end if
816 : end if
817 :
818 768 : ierr = pio_inq_varid(file, 'nextsw_cday', vardesc)
819 768 : ierr = pio_get_var(file, vardesc, nextsw_cday)
820 :
821 :
822 768 : end subroutine radiation_read_restart
823 :
824 : !===============================================================================
825 :
826 2600640 : subroutine radiation_tend( &
827 : state, ptend, pbuf, cam_out, cam_in, net_flx, rd_out)
828 :
829 : !-----------------------------------------------------------------------
830 : !
831 : ! CAM driver for radiation computation.
832 : !
833 : !-----------------------------------------------------------------------
834 :
835 : ! Location/Orbital Parameters for cosine zenith angle
836 : use phys_grid, only: get_rlat_all_p, get_rlon_all_p
837 : use cam_control_mod, only: eccen, mvelpp, lambm0, obliqr
838 : use shr_orb_mod, only: shr_orb_decl, shr_orb_cosz
839 :
840 : use rrtmgp_inputs, only: rrtmgp_set_state, rrtmgp_set_gases_lw, rrtmgp_set_cloud_lw, &
841 : rrtmgp_set_aer_lw, rrtmgp_set_gases_sw, rrtmgp_set_cloud_sw, &
842 : rrtmgp_set_aer_sw
843 :
844 : ! RRTMGP drivers for flux calculations.
845 : use mo_rte_lw, only: rte_lw
846 : use mo_rte_sw, only: rte_sw
847 :
848 : use radheat, only: radheat_tend
849 :
850 : use radiation_data, only: rad_data_write
851 :
852 : use interpolate_data, only: vertinterp
853 : use tropopause, only: tropopause_find_cam, TROP_ALG_HYBSTOB, TROP_ALG_CLIMATE
854 : use cospsimulator_intr, only: docosp, cospsimulator_intr_run, cosp_nradsteps
855 :
856 :
857 : ! Arguments
858 : type(physics_state), intent(in), target :: state
859 : type(physics_ptend), intent(out) :: ptend
860 : type(physics_buffer_desc), pointer :: pbuf(:)
861 : type(cam_out_t), intent(inout) :: cam_out
862 : type(cam_in_t), intent(in) :: cam_in
863 : real(r8), intent(out) :: net_flx(pcols)
864 :
865 : type(rad_out_t), target, optional, intent(out) :: rd_out
866 :
867 :
868 : ! Local variables
869 : type(rad_out_t), pointer :: rd ! allow rd_out to be optional by allocating a local object
870 : ! if the argument is not present
871 : logical :: write_output
872 :
873 : integer :: i, k, istat
874 : integer :: lchnk, ncol
875 : logical :: dosw, dolw
876 : integer :: icall ! loop index for climate/diagnostic radiation calls
877 :
878 : real(r8) :: calday ! current calendar day
879 : real(r8) :: delta ! Solar declination angle in radians
880 : real(r8) :: eccf ! Earth orbit eccentricity factor
881 : real(r8) :: clat(pcols) ! current latitudes(radians)
882 : real(r8) :: clon(pcols) ! current longitudes(radians)
883 : real(r8) :: coszrs(pcols) ! Cosine solar zenith angle
884 :
885 : ! Gathered indices of day and night columns
886 : ! chunk_column_index = IdxDay(daylight_column_index)
887 : integer :: Nday ! Number of daylight columns
888 : integer :: Nnite ! Number of night columns
889 : integer :: IdxDay(pcols) ! chunk indices of daylight columns
890 : integer :: IdxNite(pcols) ! chunk indices of night columns
891 :
892 : integer :: itim_old
893 :
894 61920 : real(r8), pointer :: cld(:,:) ! cloud fraction
895 61920 : real(r8), pointer :: cldfsnow(:,:) ! cloud fraction of just "snow clouds"
896 61920 : real(r8), pointer :: cldfgrau(:,:) ! cloud fraction of just "graupel clouds"
897 : real(r8) :: cldfprime(pcols,pver) ! combined cloud fraction
898 61920 : real(r8), pointer :: qrs(:,:) ! shortwave radiative heating rate
899 61920 : real(r8), pointer :: qrl(:,:) ! longwave radiative heating rate
900 61920 : real(r8), pointer :: fsds(:) ! Surface solar down flux
901 61920 : real(r8), pointer :: fsns(:) ! Surface solar absorbed flux
902 61920 : real(r8), pointer :: fsnt(:) ! Net column abs solar flux at model top
903 61920 : real(r8), pointer :: flns(:) ! Srf longwave cooling (up-down) flux
904 61920 : real(r8), pointer :: flnt(:) ! Net outgoing lw flux at model top
905 :
906 : real(r8), pointer, dimension(:,:,:) :: su => NULL() ! shortwave spectral flux up
907 : real(r8), pointer, dimension(:,:,:) :: sd => NULL() ! shortwave spectral flux down
908 : real(r8), pointer, dimension(:,:,:) :: lu => NULL() ! longwave spectral flux up
909 : real(r8), pointer, dimension(:,:,:) :: ld => NULL() ! longwave spectral flux down
910 :
911 : ! tropopause diagnostic
912 : integer :: troplev(pcols)
913 : real(r8) :: p_trop(pcols)
914 :
915 : ! state data passed to radiation calc
916 61920 : real(r8), allocatable :: t_sfc(:)
917 61920 : real(r8), allocatable :: emis_sfc(:,:)
918 61920 : real(r8), allocatable :: t_rad(:,:)
919 61920 : real(r8), allocatable :: pmid_rad(:,:)
920 61920 : real(r8), allocatable :: pint_rad(:,:)
921 61920 : real(r8), allocatable :: t_day(:,:)
922 61920 : real(r8), allocatable :: pmid_day(:,:)
923 61920 : real(r8), allocatable :: pint_day(:,:)
924 61920 : real(r8), allocatable :: coszrs_day(:)
925 61920 : real(r8), allocatable :: alb_dir(:,:)
926 61920 : real(r8), allocatable :: alb_dif(:,:)
927 :
928 : ! in-cloud optical depths for COSP
929 : real(r8) :: cld_tau_cloudsim(pcols,pver) ! liq + ice
930 : real(r8) :: snow_tau_cloudsim(pcols,pver) ! snow
931 : real(r8) :: grau_tau_cloudsim(pcols,pver) ! graupel
932 : real(r8) :: cld_lw_abs_cloudsim(pcols,pver) ! liq + ice
933 : real(r8) :: snow_lw_abs_cloudsim(pcols,pver)! snow
934 : real(r8) :: grau_lw_abs_cloudsim(pcols,pver)! graupel
935 :
936 : ! Set vertical indexing in RRTMGP to be the same as CAM (top to bottom).
937 : logical, parameter :: top_at_1 = .true.
938 :
939 : ! TOA solar flux on RRTMGP g-points
940 61920 : real(r8), allocatable :: toa_flux(:,:)
941 : ! Scale factors based on spectral distribution from input irradiance dataset
942 61920 : real(r8), allocatable :: sfac(:,:)
943 :
944 : ! Planck sources for LW.
945 61920 : type(ty_source_func_lw) :: sources_lw
946 :
947 : ! Gas volume mixing ratios. Use separate objects for LW and SW because SW only does
948 : ! calculations for daylight columns.
949 : ! These objects have a final method which deallocates the internal memory when they
950 : ! go out of scope (i.e., when radiation_tend returns), so no need for explicit deallocation.
951 61920 : type(ty_gas_concs) :: gas_concs_lw
952 61920 : type(ty_gas_concs) :: gas_concs_sw
953 :
954 : ! Atmosphere optics. This object is initialized with gas optics, then is incremented
955 : ! by the aerosol optics for the clear-sky radiative flux calculations, and then
956 : ! incremented again by the cloud optics for the all-sky radiative flux calculations.
957 61920 : type(ty_optical_props_1scl) :: atm_optics_lw
958 61920 : type(ty_optical_props_2str) :: atm_optics_sw
959 :
960 : ! Cloud optical properties objects (McICA sampling of cloud optical properties).
961 61920 : type(ty_optical_props_1scl) :: cloud_lw
962 61920 : type(ty_optical_props_2str) :: cloud_sw
963 :
964 : ! Aerosol optical properties objects.
965 61920 : type(ty_optical_props_1scl) :: aer_lw
966 61920 : type(ty_optical_props_2str) :: aer_sw
967 :
968 : ! Flux objects contain all fluxes computed by RRTMGP.
969 : ! SW allsky fluxes always include spectrally resolved fluxes needed for surface models.
970 : type(ty_fluxes_byband) :: fsw
971 : ! LW allsky fluxes only need spectrally resolved fluxes when spectralflux=.true.
972 : type(ty_fluxes_byband) :: flw
973 : ! Only broadband fluxes needed for clear sky (diagnostics).
974 : type(ty_fluxes_broadband) :: fswc, flwc
975 :
976 : ! Arrays for output diagnostics on CAM grid.
977 : real(r8) :: fns(pcols,pverp) ! net shortwave flux
978 : real(r8) :: fcns(pcols,pverp) ! net clear-sky shortwave flux
979 : real(r8) :: fnl(pcols,pverp) ! net longwave flux
980 : real(r8) :: fcnl(pcols,pverp) ! net clear-sky longwave flux
981 :
982 : ! for COSP
983 : real(r8) :: emis(pcols,pver) ! Cloud longwave emissivity
984 : real(r8) :: gb_snow_tau(pcols,pver) ! grid-box mean snow_tau
985 : real(r8) :: gb_snow_lw(pcols,pver) ! grid-box mean LW snow optical depth
986 :
987 : real(r8) :: ftem(pcols,pver) ! Temporary workspace for outfld variables
988 :
989 : character(len=128) :: errmsg
990 : character(len=*), parameter :: sub = 'radiation_tend'
991 : !--------------------------------------------------------------------------------------
992 :
993 61920 : lchnk = state%lchnk
994 61920 : ncol = state%ncol
995 :
996 61920 : if (present(rd_out)) then
997 0 : rd => rd_out
998 0 : write_output = .false.
999 : else
1000 61920 : allocate(rd, stat=istat)
1001 61920 : call handle_allocate_error(istat, sub, 'rd')
1002 61920 : write_output = .true.
1003 : end if
1004 :
1005 61920 : dosw = radiation_do('sw', get_nstep()) ! do shortwave radiation calc this timestep?
1006 61920 : dolw = radiation_do('lw', get_nstep()) ! do longwave radiation calc this timestep?
1007 :
1008 : ! Cosine solar zenith angle for current time step
1009 61920 : calday = get_curr_calday()
1010 61920 : call get_rlat_all_p(lchnk, ncol, clat)
1011 61920 : call get_rlon_all_p(lchnk, ncol, clon)
1012 :
1013 : call shr_orb_decl(calday, eccen, mvelpp, lambm0, obliqr, &
1014 61920 : delta, eccf)
1015 :
1016 61920 : if (use_rad_uniform_angle) then
1017 0 : do i = 1, ncol
1018 0 : coszrs(i) = shr_orb_cosz(calday, clat(i), clon(i), delta, dt_avg, &
1019 0 : uniform_angle=rad_uniform_angle)
1020 : end do
1021 : else
1022 1033920 : do i = 1, ncol
1023 : ! if dt_avg /= 0, it triggers using avg coszrs
1024 1033920 : coszrs(i) = shr_orb_cosz(calday, clat(i), clon(i), delta, dt_avg)
1025 : end do
1026 : end if
1027 :
1028 : ! Gather night/day column indices.
1029 61920 : Nday = 0
1030 61920 : Nnite = 0
1031 1033920 : do i = 1, ncol
1032 1033920 : if ( coszrs(i) > 0.0_r8 ) then
1033 486000 : Nday = Nday + 1
1034 486000 : IdxDay(Nday) = i
1035 : else
1036 486000 : Nnite = Nnite + 1
1037 486000 : IdxNite(Nnite) = i
1038 : end if
1039 : end do
1040 :
1041 : ! Associate pointers to physics buffer fields
1042 61920 : itim_old = pbuf_old_tim_idx()
1043 61920 : nullify(cldfsnow)
1044 61920 : if (cldfsnow_idx > 0) then
1045 247680 : call pbuf_get_field(pbuf, cldfsnow_idx, cldfsnow, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
1046 : end if
1047 61920 : nullify(cldfgrau)
1048 61920 : if (cldfgrau_idx > 0 .and. graupel_in_rad) then
1049 0 : call pbuf_get_field(pbuf, cldfgrau_idx, cldfgrau, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
1050 : endif
1051 :
1052 247680 : call pbuf_get_field(pbuf, cld_idx, cld, start=(/1,1,itim_old/), kount=(/pcols,pver,1/) )
1053 :
1054 61920 : call pbuf_get_field(pbuf, qrs_idx, qrs)
1055 61920 : call pbuf_get_field(pbuf, qrl_idx, qrl)
1056 :
1057 61920 : call pbuf_get_field(pbuf, fsns_idx, fsns)
1058 61920 : call pbuf_get_field(pbuf, fsnt_idx, fsnt)
1059 61920 : call pbuf_get_field(pbuf, fsds_idx, fsds)
1060 61920 : call pbuf_get_field(pbuf, flns_idx, flns)
1061 61920 : call pbuf_get_field(pbuf, flnt_idx, flnt)
1062 :
1063 61920 : if (spectralflux) then
1064 0 : call pbuf_get_field(pbuf, su_idx, su)
1065 0 : call pbuf_get_field(pbuf, sd_idx, sd)
1066 0 : call pbuf_get_field(pbuf, lu_idx, lu)
1067 0 : call pbuf_get_field(pbuf, ld_idx, ld)
1068 : end if
1069 :
1070 : ! Allocate the flux arrays and init to zero.
1071 61920 : call initialize_rrtmgp_fluxes(nday, nlay+1, nswbands, fsw, do_direct=.true.)
1072 61920 : call initialize_rrtmgp_fluxes(nday, nlay+1, nswbands, fswc, do_direct=.true.)
1073 61920 : call initialize_rrtmgp_fluxes(ncol, nlay+1, nlwbands, flw)
1074 61920 : call initialize_rrtmgp_fluxes(ncol, nlay+1, nlwbands, flwc)
1075 :
1076 : ! For CRM, make cloud equal to input observations:
1077 61920 : if (scm_crm_mode .and. have_cld) then
1078 0 : do k = 1, pver
1079 0 : cld(:ncol,k)= cldobs(k)
1080 : end do
1081 : end if
1082 :
1083 : ! Find tropopause height if needed for diagnostic output
1084 61920 : if (hist_fld_active('FSNR') .or. hist_fld_active('FLNR')) then
1085 : !REMOVECAM - no longer need this when CAM is retired and pcols no longer exists
1086 0 : troplev(:) = 0
1087 0 : p_trop(:) = 0._r8
1088 : !REMOVECAM_END
1089 : call tropopause_find_cam(state, troplev, tropP=p_trop, primary=TROP_ALG_HYBSTOB, &
1090 0 : backup=TROP_ALG_CLIMATE)
1091 : end if
1092 :
1093 : ! Get time of next radiation calculation - albedos will need to be
1094 : ! calculated by each surface model at this time
1095 61920 : nextsw_cday = radiation_nextsw_cday()
1096 :
1097 61920 : if (dosw .or. dolw) then
1098 :
1099 : allocate( &
1100 : t_sfc(ncol), emis_sfc(nlwbands,ncol), toa_flux(nday,nswgpts), &
1101 : sfac(nday,nswgpts), &
1102 : t_rad(ncol,nlay), pmid_rad(ncol,nlay), pint_rad(ncol,nlay+1), &
1103 : t_day(nday,nlay), pmid_day(nday,nlay), pint_day(nday,nlay+1), &
1104 : coszrs_day(nday), alb_dir(nswbands,nday), alb_dif(nswbands,nday), &
1105 841288 : stat=istat)
1106 30960 : call handle_allocate_error(istat, sub, 't_sfc,..,alb_dif')
1107 :
1108 : ! Prepares state variables, daylit columns, albedos for RRTMGP
1109 : call rrtmgp_set_state( &
1110 : state, cam_in, ncol, nlay, nday, &
1111 : idxday, coszrs, kdist_sw, t_sfc, emis_sfc, &
1112 : t_rad, pmid_rad, pint_rad, t_day, pmid_day, &
1113 30960 : pint_day, coszrs_day, alb_dir, alb_dif)
1114 :
1115 : ! Output the mass per layer, and total column burdens for gas and aerosol
1116 : ! constituents in the climate list.
1117 30960 : call rad_cnst_out(0, state, pbuf)
1118 :
1119 : ! Modified cloud fraction accounts for radiatively active snow and/or graupel
1120 30960 : call modified_cloud_fraction(ncol, cld, cldfsnow, cldfgrau, cldfprime)
1121 :
1122 : !========================!
1123 : ! SHORTWAVE calculations !
1124 : !========================!
1125 :
1126 30960 : if (dosw) then
1127 :
1128 : ! Set cloud optical properties in cloud_sw object.
1129 : call rrtmgp_set_cloud_sw( &
1130 : state, pbuf, nlay, nday, idxday, &
1131 : nnite, idxnite, pmid_day, cld, cldfsnow, &
1132 : cldfgrau, cldfprime, graupel_in_rad, kdist_sw, cloud_sw, &
1133 : rd%tot_cld_vistau, rd%tot_icld_vistau, rd%liq_icld_vistau, &
1134 : rd%ice_icld_vistau, rd%snow_icld_vistau, rd%grau_icld_vistau, &
1135 30960 : cld_tau_cloudsim, snow_tau_cloudsim, grau_tau_cloudsim )
1136 :
1137 30960 : if (write_output) then
1138 30960 : call radiation_output_cld(lchnk, rd)
1139 : end if
1140 :
1141 : ! If no daylight columns, can't create empty RRTMGP objects
1142 30960 : if (nday > 0) then
1143 :
1144 : ! Initialize object for gas concentrations.
1145 16151 : errmsg = gas_concs_sw%init(gaslist_lc)
1146 16151 : call stop_on_err(errmsg, sub, 'gas_concs_sw%init')
1147 :
1148 : ! Initialize object for combined gas + aerosol + cloud optics.
1149 : ! Allocates arrays for properties represented on g-points.
1150 16151 : errmsg = atm_optics_sw%alloc_2str(nday, nlay, kdist_sw)
1151 16151 : call stop_on_err(errmsg, sub, 'atm_optics_sw%alloc_2str')
1152 :
1153 : ! Initialize object for SW aerosol optics. Allocates arrays
1154 : ! for properties represented by band.
1155 16151 : errmsg = aer_sw%alloc_2str(nday, nlay, kdist_sw%get_band_lims_wavenumber())
1156 16151 : call stop_on_err(errmsg, sub, 'aer_sw%alloc_2str')
1157 :
1158 : end if
1159 :
1160 : ! The climate (icall==0) calculation must occur last.
1161 371520 : do icall = N_DIAG, 0, -1
1162 371520 : if (active_calls(icall)) then
1163 :
1164 30960 : if (nday > 0) then
1165 :
1166 : ! Set gas volume mixing ratios for this call in gas_concs_sw.
1167 : call rrtmgp_set_gases_sw( &
1168 : icall, state, pbuf, nlay, nday, &
1169 16151 : idxday, gas_concs_sw)
1170 :
1171 : ! Compute the gas optics (stored in atm_optics_sw).
1172 : ! toa_flux is the reference solar source from RRTMGP data.
1173 : !$acc data copyin(kdist_sw,pmid_day,pint_day,t_day,gas_concs_sw) &
1174 : !$acc copy(atm_optics_sw) &
1175 : !$acc copyout(toa_flux)
1176 : errmsg = kdist_sw%gas_optics( &
1177 : pmid_day, pint_day, t_day, gas_concs_sw, atm_optics_sw, &
1178 16151 : toa_flux)
1179 : !$acc end data
1180 16151 : call stop_on_err(errmsg, sub, 'kdist_sw%gas_optics')
1181 :
1182 : ! Scale the solar source
1183 16151 : call get_variability(toa_flux, sfac)
1184 29057214 : toa_flux = toa_flux * sfac * eccf
1185 :
1186 : end if
1187 :
1188 : ! Set SW aerosol optical properties in the aer_sw object.
1189 : ! This call made even when no daylight columns because it does some
1190 : ! diagnostic aerosol output.
1191 : call rrtmgp_set_aer_sw( &
1192 30960 : icall, state, pbuf, nday, idxday, nnite, idxnite, aer_sw)
1193 :
1194 30960 : if (nday > 0) then
1195 :
1196 : ! Increment the gas optics (in atm_optics_sw) by the aerosol optics in aer_sw.
1197 : !$acc data copyin(coszrs_day, toa_flux, alb_dir, alb_dif, &
1198 : !$acc atm_optics_sw, atm_optics_sw%tau, &
1199 : !$acc atm_optics_sw%ssa, atm_optics_sw%g, &
1200 : !$acc aer_sw, aer_sw%tau, &
1201 : !$acc aer_sw%ssa, aer_sw%g, &
1202 : !$acc cloud_sw, cloud_sw%tau, &
1203 : !$acc cloud_sw%ssa, cloud_sw%g) &
1204 : !$acc copy(fswc, fswc%flux_net,fswc%flux_up,fswc%flux_dn, &
1205 : !$acc fsw, fsw%flux_net, fsw%flux_up, fsw%flux_dn)
1206 16151 : errmsg = aer_sw%increment(atm_optics_sw)
1207 16151 : call stop_on_err(errmsg, sub, 'aer_sw%increment')
1208 :
1209 : ! Compute clear-sky fluxes.
1210 : errmsg = rte_sw(&
1211 : atm_optics_sw, top_at_1, coszrs_day, toa_flux, &
1212 16151 : alb_dir, alb_dif, fswc)
1213 16151 : call stop_on_err(errmsg, sub, 'clear-sky rte_sw')
1214 :
1215 : ! Increment the aerosol+gas optics (in atm_optics_sw) by the cloud optics in cloud_sw.
1216 16151 : errmsg = cloud_sw%increment(atm_optics_sw)
1217 16151 : call stop_on_err(errmsg, sub, 'cloud_sw%increment')
1218 :
1219 : ! Compute all-sky fluxes.
1220 : errmsg = rte_sw(&
1221 : atm_optics_sw, top_at_1, coszrs_day, toa_flux, &
1222 16151 : alb_dir, alb_dif, fsw)
1223 16151 : call stop_on_err(errmsg, sub, 'all-sky rte_sw')
1224 : !$acc end data
1225 : end if
1226 :
1227 : ! Transform RRTMGP outputs to CAM outputs and compute heating rates.
1228 30960 : call set_sw_diags()
1229 :
1230 30960 : if (write_output) then
1231 30960 : call radiation_output_sw(lchnk, ncol, icall, rd, pbuf, cam_out)
1232 : end if
1233 :
1234 : end if ! (active_calls(icall))
1235 : end do ! loop over diagnostic calcs (icall)
1236 :
1237 : else
1238 : ! SW calc not done. pbuf carries Q*dp across timesteps.
1239 : ! Convert to Q before calling radheat_tend.
1240 0 : qrs(:ncol,:) = qrs(:ncol,:) / state%pdel(:ncol,:)
1241 : end if ! if (dosw)
1242 :
1243 : !=======================!
1244 : ! LONGWAVE calculations !
1245 : !=======================!
1246 :
1247 30960 : if (dolw) then
1248 :
1249 : ! Initialize object for Planck sources.
1250 30960 : errmsg = sources_lw%alloc(ncol, nlay, kdist_lw)
1251 30960 : call stop_on_err(errmsg, sub, 'sources_lw%alloc')
1252 :
1253 : ! Set cloud optical properties in cloud_lw object.
1254 : call rrtmgp_set_cloud_lw( &
1255 : state, pbuf, ncol, nlay, nlaycam, &
1256 : cld, cldfsnow, cldfgrau, cldfprime, graupel_in_rad, &
1257 30960 : kdist_lw, cloud_lw, cld_lw_abs_cloudsim, snow_lw_abs_cloudsim, grau_lw_abs_cloudsim)
1258 :
1259 : ! Initialize object for gas concentrations
1260 30960 : errmsg = gas_concs_lw%init(gaslist_lc)
1261 30960 : call stop_on_err(errmsg, sub, 'gas_concs_lw%init')
1262 :
1263 : ! Initialize object for combined gas + aerosol + cloud optics.
1264 30960 : errmsg = atm_optics_lw%alloc_1scl(ncol, nlay, kdist_lw)
1265 30960 : call stop_on_err(errmsg, sub, 'atm_optics_lw%alloc_1scl')
1266 :
1267 : ! Initialize object for LW aerosol optics.
1268 30960 : errmsg = aer_lw%alloc_1scl(ncol, nlay, kdist_lw%get_band_lims_wavenumber())
1269 30960 : call stop_on_err(errmsg, sub, 'aer_lw%alloc_1scl')
1270 :
1271 : ! The climate (icall==0) calculation must occur last.
1272 371520 : do icall = N_DIAG, 0, -1
1273 :
1274 371520 : if (active_calls(icall)) then
1275 :
1276 : ! Set gas volume mixing ratios for this call in gas_concs_lw.
1277 30960 : call rrtmgp_set_gases_lw(icall, state, pbuf, nlay, gas_concs_lw)
1278 :
1279 : ! Compute the gas optics and Planck sources.
1280 : !$acc data copyin(kdist_lw, pmid_rad, pint_rad, &
1281 : !$acc t_rad, t_sfc, gas_concs_lw) &
1282 : !$acc copy(atm_optics_lw, atm_optics_lw%tau, &
1283 : !$acc sources_lw, sources_lw%lay_source, &
1284 : !$acc sources_lw%sfc_source, sources_lw%lev_source_inc, &
1285 : !$acc sources_lw%lev_source_dec, sources_lw%sfc_source_jac)
1286 : errmsg = kdist_lw%gas_optics( &
1287 : pmid_rad, pint_rad, t_rad, t_sfc, gas_concs_lw, &
1288 30960 : atm_optics_lw, sources_lw)
1289 : !$acc end data
1290 30960 : call stop_on_err(errmsg, sub, 'kdist_lw%gas_optics')
1291 :
1292 : ! Set LW aerosol optical properties in the aer_lw object.
1293 30960 : call rrtmgp_set_aer_lw(icall, state, pbuf, aer_lw)
1294 :
1295 : ! Increment the gas optics by the aerosol optics.
1296 : !$acc data copyin(atm_optics_lw, atm_optics_lw%tau, &
1297 : !$acc aer_lw, aer_lw%tau, &
1298 : !$acc cloud_lw, cloud_lw%tau, &
1299 : !$acc sources_lw, sources_lw%lay_source, &
1300 : !$acc sources_lw%sfc_source, sources_lw%lev_source_inc, &
1301 : !$acc sources_lw%lev_source_dec, sources_lw%sfc_source_Jac, &
1302 : !$acc emis_sfc) &
1303 : !$acc copy(flwc, flwc%flux_net, flwc%flux_up, flwc%flux_dn, &
1304 : !$acc flw, flw%flux_net, flw%flux_up, flw%flux_dn)
1305 30960 : errmsg = aer_lw%increment(atm_optics_lw)
1306 30960 : call stop_on_err(errmsg, sub, 'aer_lw%increment')
1307 :
1308 : ! Compute clear-sky LW fluxes
1309 30960 : errmsg = rte_lw(atm_optics_lw, top_at_1, sources_lw, emis_sfc, flwc)
1310 30960 : call stop_on_err(errmsg, sub, 'clear-sky rte_lw')
1311 :
1312 : ! Increment the gas+aerosol optics by the cloud optics.
1313 30960 : errmsg = cloud_lw%increment(atm_optics_lw)
1314 30960 : call stop_on_err(errmsg, sub, 'cloud_lw%increment')
1315 :
1316 : ! Compute all-sky LW fluxes
1317 30960 : errmsg = rte_lw(atm_optics_lw, top_at_1, sources_lw, emis_sfc, flw)
1318 30960 : call stop_on_err(errmsg, sub, 'all-sky rte_lw')
1319 : !$acc end data
1320 :
1321 : ! Transform RRTMGP outputs to CAM outputs and compute heating rates.
1322 30960 : call set_lw_diags()
1323 :
1324 30960 : if (write_output) then
1325 30960 : call radiation_output_lw(lchnk, ncol, icall, rd, pbuf, cam_out)
1326 : end if
1327 :
1328 : end if ! (active_calls(icall))
1329 : end do ! loop over diagnostic calcs (icall)
1330 :
1331 : else
1332 : ! LW calc not done. pbuf carries Q*dp across timesteps.
1333 : ! Convert to Q before calling radheat_tend.
1334 0 : qrl(:ncol,:) = qrl(:ncol,:) / state%pdel(:ncol,:)
1335 : end if ! if (dolw)
1336 :
1337 0 : deallocate( &
1338 0 : t_sfc, emis_sfc, toa_flux, sfac, t_rad, pmid_rad, pint_rad, &
1339 30960 : t_day, pmid_day, pint_day, coszrs_day, alb_dir, alb_dif)
1340 :
1341 : !================!
1342 : ! COSP simulator !
1343 : !================!
1344 :
1345 30960 : if (docosp) then
1346 :
1347 0 : emis(:,:) = 0._r8
1348 0 : emis(:ncol,:) = 1._r8 - exp(-cld_lw_abs_cloudsim(:ncol,:))
1349 0 : call outfld('EMIS', emis, pcols, lchnk)
1350 :
1351 : ! compute grid-box mean SW and LW snow optical depth for use by COSP
1352 0 : gb_snow_tau(:,:) = 0._r8
1353 0 : gb_snow_lw(:,:) = 0._r8
1354 0 : if (cldfsnow_idx > 0) then
1355 0 : do i = 1, ncol
1356 0 : do k = 1, pver
1357 0 : if (cldfsnow(i,k) > 0._r8) then
1358 :
1359 : ! Add graupel to snow tau for cosp
1360 0 : if (cldfgrau_idx > 0 .and. graupel_in_rad) then
1361 0 : gb_snow_tau(i,k) = snow_tau_cloudsim(i,k)*cldfsnow(i,k) + &
1362 0 : grau_tau_cloudsim(i,k)*cldfgrau(i,k)
1363 : gb_snow_lw(i,k) = snow_lw_abs_cloudsim(i,k)*cldfsnow(i,k) + &
1364 0 : grau_lw_abs_cloudsim(i,k)*cldfgrau(i,k)
1365 : else
1366 0 : gb_snow_tau(i,k) = snow_tau_cloudsim(i,k)*cldfsnow(i,k)
1367 0 : gb_snow_lw(i,k) = snow_lw_abs_cloudsim(i,k)*cldfsnow(i,k)
1368 : end if
1369 : end if
1370 : end do
1371 : end do
1372 : end if
1373 :
1374 : ! advance counter for this timestep (chunk dimension required for thread safety)
1375 0 : cosp_cnt(lchnk) = cosp_cnt(lchnk) + 1
1376 :
1377 : ! if counter is the same as cosp_nradsteps, run cosp and reset counter
1378 0 : if (cosp_nradsteps .eq. cosp_cnt(lchnk)) then
1379 :
1380 : ! N.B.: For snow optical properties, the GRID-BOX MEAN shortwave and longwave
1381 : ! optical depths are passed.
1382 : call cospsimulator_intr_run( &
1383 : state, pbuf, cam_in, emis, coszrs, &
1384 : cld_swtau_in=cld_tau_cloudsim, snow_tau_in=gb_snow_tau, &
1385 0 : snow_emis_in=gb_snow_lw)
1386 0 : cosp_cnt(lchnk) = 0
1387 : end if
1388 : end if ! docosp
1389 :
1390 : else
1391 : ! Radiative flux calculations not done. The quantity Q*dp is carried by the
1392 : ! physics buffer across timesteps. It must be converted to Q (dry static energy
1393 : ! tendency) before being passed to radheat_tend.
1394 48108240 : qrs(:ncol,:) = qrs(:ncol,:) / state%pdel(:ncol,:)
1395 48108240 : qrl(:ncol,:) = qrl(:ncol,:) / state%pdel(:ncol,:)
1396 :
1397 : end if ! if (dosw .or. dolw) then
1398 :
1399 : ! Output for PORT: Parallel Offline Radiative Transport
1400 61920 : call rad_data_write(pbuf, state, cam_in, coszrs)
1401 :
1402 : ! Compute net radiative heating tendency. Note that the WACCM version
1403 : ! of radheat_tend merges upper atmosphere heating rates with those calculated
1404 : ! by RRTMGP.
1405 : call radheat_tend(state, pbuf, ptend, qrl, qrs, fsns, &
1406 61920 : fsnt, flns, flnt, cam_in%asdir, net_flx)
1407 :
1408 61920 : if (write_output) then
1409 : ! Compute heating rate for dtheta/dt
1410 5820480 : do k = 1, pver
1411 96216480 : do i = 1, ncol
1412 96154560 : ftem(i,k) = (qrs(i,k) + qrl(i,k))/cpair * (1.e5_r8/state%pmid(i,k))**cappa
1413 : end do
1414 : end do
1415 61920 : call outfld('HR', ftem, pcols, lchnk)
1416 : end if
1417 :
1418 : ! The radiative heating rates are carried in the physics buffer across timesteps
1419 : ! as Q*dp (for energy conservation).
1420 96216480 : qrs(:ncol,:) = qrs(:ncol,:) * state%pdel(:ncol,:)
1421 96216480 : qrl(:ncol,:) = qrl(:ncol,:) * state%pdel(:ncol,:)
1422 :
1423 61920 : if (.not. present(rd_out)) then
1424 61920 : deallocate(rd)
1425 : end if
1426 61920 : call free_optics_sw(atm_optics_sw)
1427 61920 : call free_optics_sw(cloud_sw)
1428 61920 : call free_optics_sw(aer_sw)
1429 61920 : call free_fluxes(fsw)
1430 61920 : call free_fluxes(fswc)
1431 :
1432 61920 : call sources_lw%finalize()
1433 61920 : call free_optics_lw(cloud_lw)
1434 61920 : call free_optics_lw(aer_lw)
1435 61920 : call free_fluxes(flw)
1436 123840 : call free_fluxes(flwc)
1437 :
1438 : !-------------------------------------------------------------------------------
1439 : contains
1440 : !-------------------------------------------------------------------------------
1441 :
1442 30960 : subroutine set_sw_diags()
1443 :
1444 : ! Transform RRTMGP output for CAM and compute heating rates.
1445 : ! SW fluxes from RRTMGP are on daylight columns only, so expand to
1446 : ! full chunks for output to CAM history.
1447 :
1448 : integer :: i
1449 : real(r8), dimension(size(fsw%bnd_flux_dn,1), &
1450 : size(fsw%bnd_flux_dn,2), &
1451 61920 : size(fsw%bnd_flux_dn,3)) :: flux_dn_diffuse
1452 : !-------------------------------------------------------------------------
1453 :
1454 : ! Initialize to provide 0.0 values for night columns.
1455 30960 : fns = 0._r8 ! net sw flux
1456 30960 : fcns = 0._r8 ! net sw clearsky flux
1457 526320 : fsds = 0._r8 ! downward sw flux at surface
1458 526320 : rd%fsdsc = 0._r8 ! downward sw clearsky flux at surface
1459 526320 : rd%fsutoa = 0._r8 ! upward sw flux at TOA
1460 526320 : rd%fsntoa = 0._r8 ! net sw at TOA
1461 526320 : rd%fsntoac = 0._r8 ! net sw clearsky flux at TOA
1462 526320 : rd%solin = 0._r8 ! solar irradiance at TOA
1463 49505040 : rd%flux_sw_up = 0._r8
1464 49505040 : rd%flux_sw_dn = 0._r8
1465 49505040 : rd%flux_sw_clr_up = 0._r8
1466 49505040 : rd%flux_sw_clr_dn = 0._r8
1467 :
1468 48978720 : qrs = 0._r8
1469 526320 : fsns = 0._r8
1470 526320 : fsnt = 0._r8
1471 48978720 : rd%qrsc = 0._r8
1472 526320 : rd%fsnsc = 0._r8
1473 526320 : rd%fsntc = 0._r8
1474 :
1475 273960 : do i = 1, nday
1476 23085000 : fns(idxday(i),ktopcam:) = fsw%flux_net(i, ktoprad:)
1477 23085000 : fcns(idxday(i),ktopcam:) = fswc%flux_net(i,ktoprad:)
1478 243000 : fsds(idxday(i)) = fsw%flux_dn(i, nlay+1)
1479 243000 : rd%fsdsc(idxday(i)) = fswc%flux_dn(i, nlay+1)
1480 243000 : rd%fsutoa(idxday(i)) = fsw%flux_up(i, 1)
1481 243000 : rd%fsntoa(idxday(i)) = fsw%flux_net(i, 1)
1482 243000 : rd%fsntoac(idxday(i)) = fswc%flux_net(i, 1)
1483 243000 : rd%solin(idxday(i)) = fswc%flux_dn(i, 1)
1484 23085000 : rd%flux_sw_up(idxday(i),ktopcam:) = fsw%flux_up(i,ktoprad:)
1485 23085000 : rd%flux_sw_dn(idxday(i),ktopcam:) = fsw%flux_dn(i,ktoprad:)
1486 23085000 : rd%flux_sw_clr_up(idxday(i),ktopcam:) = fswc%flux_up(i,ktoprad:)
1487 23115960 : rd%flux_sw_clr_dn(idxday(i),ktopcam:) = fswc%flux_dn(i,ktoprad:)
1488 : end do
1489 :
1490 : ! Compute heating rate as a dry static energy tendency.
1491 30960 : call heating_rate('SW', ncol, fns, qrs)
1492 30960 : call heating_rate('SW', ncol, fcns, rd%qrsc)
1493 :
1494 516960 : fsns(:ncol) = fns(:ncol,pverp) ! net sw flux at surface
1495 516960 : fsnt(:ncol) = fns(:ncol,ktopcam) ! net sw flux at top-of-model (w/o extra layer)
1496 547920 : rd%fsnsc(:ncol) = fcns(:ncol,pverp) ! net sw clearsky flux at surface
1497 547920 : rd%fsntc(:ncol) = fcns(:ncol,ktopcam) ! net sw clearsky flux at top
1498 :
1499 516960 : cam_out%netsw(:ncol) = fsns(:ncol)
1500 :
1501 : ! Output fluxes at 200 mb
1502 30960 : call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fns, rd%fsn200)
1503 30960 : call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fcns, rd%fsn200c)
1504 30960 : if (hist_fld_active('FSNR')) then
1505 0 : do i = 1,ncol
1506 0 : call vertinterp(1, 1, pverp, state%pint(i,:), p_trop(i), fns(i,:), rd%fsnr(i))
1507 : end do
1508 : end if
1509 :
1510 30960 : if (spectralflux) then
1511 0 : su = 0._r8
1512 0 : sd = 0._r8
1513 0 : do i = 1, nday
1514 0 : su(idxday(i),ktopcam:,:) = fsw%bnd_flux_up(i,ktoprad:,:)
1515 0 : sd(idxday(i),ktopcam:,:) = fsw%bnd_flux_dn(i,ktoprad:,:)
1516 : end do
1517 : end if
1518 :
1519 : ! Export surface fluxes
1520 : ! sols(pcols) Direct solar rad on surface (< 0.7)
1521 : ! soll(pcols) Direct solar rad on surface (>= 0.7)
1522 : ! RRTMGP: Near-IR bands (1-10), 820-16000 cm-1, 0.625-12.195 microns
1523 : ! Put half of band 10 in each of the UV/visible and near-IR values,
1524 : ! since this band straddles 0.7 microns:
1525 : ! UV/visible bands 10-13, 16000-50000 cm-1, 0.200-0.625 micron
1526 :
1527 : ! reset fluxes
1528 526320 : cam_out%sols = 0.0_r8
1529 526320 : cam_out%soll = 0.0_r8
1530 526320 : cam_out%solsd = 0.0_r8
1531 526320 : cam_out%solld = 0.0_r8
1532 :
1533 : ! Calculate diffuse flux from total and direct
1534 364831200 : flux_dn_diffuse = fsw%bnd_flux_dn - fsw%bnd_flux_dn_dir
1535 :
1536 273960 : do i = 1, nday
1537 729000 : cam_out%soll(idxday(i)) = sum(fsw%bnd_flux_dn_dir(i,nlay+1,1:9)) &
1538 3159000 : + 0.5_r8 * fsw%bnd_flux_dn_dir(i,nlay+1,10)
1539 :
1540 243000 : cam_out%sols(idxday(i)) = 0.5_r8 * fsw%bnd_flux_dn_dir(i,nlay+1,10) &
1541 1458000 : + sum(fsw%bnd_flux_dn_dir(i,nlay+1,11:14))
1542 :
1543 486000 : cam_out%solld(idxday(i)) = sum(flux_dn_diffuse(i,nlay+1,1:9)) &
1544 2916000 : + 0.5_r8 * flux_dn_diffuse(i,nlay+1,10)
1545 :
1546 243000 : cam_out%solsd(idxday(i)) = 0.5_r8 * flux_dn_diffuse(i, nlay+1, 10) &
1547 1731960 : + sum(flux_dn_diffuse(i,nlay+1,11:14))
1548 : end do
1549 :
1550 61920 : end subroutine set_sw_diags
1551 :
1552 : !-------------------------------------------------------------------------------
1553 :
1554 30960 : subroutine set_lw_diags()
1555 :
1556 : ! Set CAM LW diagnostics
1557 : !----------------------------------------------------------------------------
1558 :
1559 30960 : fnl = 0._r8
1560 30960 : fcnl = 0._r8
1561 :
1562 : ! RTE-RRTMGP convention for net is (down - up) **CAM assumes (up - down) !!
1563 48625200 : fnl(:ncol,ktopcam:) = -1._r8 * flw%flux_net( :, ktoprad:)
1564 48625200 : fcnl(:ncol,ktopcam:) = -1._r8 * flwc%flux_net( :, ktoprad:)
1565 :
1566 48625200 : rd%flux_lw_up(:ncol,ktopcam:) = flw%flux_up( :, ktoprad:)
1567 48625200 : rd%flux_lw_clr_up(:ncol,ktopcam:) = flwc%flux_up(:, ktoprad:)
1568 48625200 : rd%flux_lw_dn(:ncol,ktopcam:) = flw%flux_dn( :, ktoprad:)
1569 48625200 : rd%flux_lw_clr_dn(:ncol,ktopcam:) = flwc%flux_dn(:, ktoprad:)
1570 :
1571 30960 : call heating_rate('LW', ncol, fnl, qrl)
1572 30960 : call heating_rate('LW', ncol, fcnl, rd%qrlc)
1573 :
1574 516960 : flns(:ncol) = fnl(:ncol, pverp)
1575 516960 : flnt(:ncol) = fnl(:ncol, ktopcam)
1576 :
1577 547920 : rd%flnsc(:ncol) = fcnl(:ncol, pverp)
1578 547920 : rd%flntc(:ncol) = fcnl(:ncol, ktopcam) ! net lw flux at top-of-model
1579 :
1580 516960 : cam_out%flwds(:ncol) = flw%flux_dn(:, nlay+1)
1581 516960 : rd%fldsc(:ncol) = flwc%flux_dn(:, nlay+1)
1582 :
1583 516960 : rd%flut(:ncol) = flw%flux_up(:, ktoprad)
1584 516960 : rd%flutc(:ncol) = flwc%flux_up(:, ktoprad)
1585 :
1586 : ! Output fluxes at 200 mb
1587 30960 : call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fnl, rd%fln200)
1588 30960 : call vertinterp(ncol, pcols, pverp, state%pint, 20000._r8, fcnl, rd%fln200c)
1589 30960 : if (hist_fld_active('FLNR')) then
1590 0 : do i = 1,ncol
1591 0 : call vertinterp(1, 1, pverp, state%pint(i,:), p_trop(i), fnl(i,:), rd%flnr(i))
1592 : end do
1593 : end if
1594 :
1595 30960 : if (spectralflux) then
1596 0 : lu = 0._r8
1597 0 : ld = 0._r8
1598 0 : lu(:ncol, ktopcam:, :) = flw%bnd_flux_up(:, ktoprad:, :)
1599 0 : ld(:ncol, ktopcam:, :) = flw%bnd_flux_dn(:, ktoprad:, :)
1600 : end if
1601 :
1602 30960 : end subroutine set_lw_diags
1603 :
1604 : !-------------------------------------------------------------------------------
1605 :
1606 123840 : subroutine heating_rate(type, ncol, flux_net, hrate)
1607 :
1608 : ! Compute heating rate as a dry static energy tendency
1609 :
1610 : ! arguments
1611 : character(2), intent(in) :: type ! either LW or SW
1612 : integer, intent(in) :: ncol
1613 : real(r8), intent(in) :: flux_net(pcols,pverp) ! W/m^2
1614 : real(r8), intent(out) :: hrate(pcols,pver) ! J/kg/s
1615 :
1616 : ! local vars
1617 : integer :: k
1618 :
1619 : ! Initialize for layers where RRTMGP is not providing fluxes.
1620 123840 : hrate = 0.0_r8
1621 :
1622 61920 : select case (type)
1623 : case ('LW')
1624 :
1625 5820480 : do k = ktopcam, pver
1626 : ! (flux divergence as bottom-MINUS-top) * g/dp
1627 11517120 : hrate(:ncol,k) = (flux_net(:ncol,k+1) - flux_net(:ncol,k)) * &
1628 107733600 : gravit * state%rpdel(:ncol,k)
1629 : end do
1630 :
1631 : case ('SW')
1632 :
1633 5882400 : do k = ktopcam, pver
1634 : ! top - bottom
1635 11517120 : hrate(:ncol,k) = (flux_net(:ncol,k) - flux_net(:ncol,k+1)) * &
1636 107733600 : gravit * state%rpdel(:ncol,k)
1637 : end do
1638 :
1639 : end select
1640 :
1641 123840 : end subroutine heating_rate
1642 :
1643 : !----------------------------------------------------------------------------
1644 : ! -- end contains statement of radiation_tend --
1645 : !----------------------------------------------------------------------------
1646 : end subroutine radiation_tend
1647 :
1648 : !===============================================================================
1649 :
1650 30960 : subroutine radiation_output_sw(lchnk, ncol, icall, rd, pbuf, cam_out)
1651 :
1652 : ! Dump shortwave radiation information to history buffer.
1653 :
1654 : integer , intent(in) :: lchnk
1655 : integer, intent(in) :: ncol
1656 : integer, intent(in) :: icall
1657 : type(rad_out_t), intent(in) :: rd
1658 : type(physics_buffer_desc), pointer :: pbuf(:)
1659 : type(cam_out_t), intent(in) :: cam_out
1660 :
1661 : ! local variables
1662 30960 : real(r8), pointer :: qrs(:,:)
1663 30960 : real(r8), pointer :: fsnt(:)
1664 30960 : real(r8), pointer :: fsns(:)
1665 30960 : real(r8), pointer :: fsds(:)
1666 :
1667 : real(r8) :: ftem(pcols)
1668 : !----------------------------------------------------------------------------
1669 :
1670 30960 : call pbuf_get_field(pbuf, qrs_idx, qrs)
1671 30960 : call pbuf_get_field(pbuf, fsnt_idx, fsnt)
1672 30960 : call pbuf_get_field(pbuf, fsns_idx, fsns)
1673 30960 : call pbuf_get_field(pbuf, fsds_idx, fsds)
1674 :
1675 30960 : call outfld('SOLIN'//diag(icall), rd%solin, pcols, lchnk)
1676 :
1677 : ! QRS is output as temperature tendency.
1678 48108240 : call outfld('QRS'//diag(icall), qrs(:ncol,:)/cpair, ncol, lchnk)
1679 48108240 : call outfld('QRSC'//diag(icall), rd%qrsc(:ncol,:)/cpair, ncol, lchnk)
1680 :
1681 30960 : call outfld('FSNT'//diag(icall), fsnt, pcols, lchnk)
1682 30960 : call outfld('FSNTC'//diag(icall), rd%fsntc, pcols, lchnk)
1683 30960 : call outfld('FSNTOA'//diag(icall), rd%fsntoa, pcols, lchnk)
1684 30960 : call outfld('FSNTOAC'//diag(icall), rd%fsntoac, pcols, lchnk)
1685 :
1686 516960 : ftem(:ncol) = rd%fsntoa(:ncol) - rd%fsntoac(:ncol)
1687 30960 : call outfld('SWCF'//diag(icall), ftem, pcols, lchnk)
1688 :
1689 30960 : call outfld('FSUTOA'//diag(icall), rd%fsutoa, pcols, lchnk)
1690 :
1691 30960 : call outfld('FSNIRTOA'//diag(icall), rd%fsnirt, pcols, lchnk)
1692 30960 : call outfld('FSNRTOAC'//diag(icall), rd%fsnrtc, pcols, lchnk)
1693 30960 : call outfld('FSNRTOAS'//diag(icall), rd%fsnirtsq, pcols, lchnk)
1694 :
1695 30960 : call outfld('FSN200'//diag(icall), rd%fsn200, pcols, lchnk)
1696 30960 : call outfld('FSN200C'//diag(icall), rd%fsn200c, pcols, lchnk)
1697 :
1698 30960 : call outfld('FSNR'//diag(icall), rd%fsnr, pcols, lchnk)
1699 :
1700 30960 : call outfld('SOLS'//diag(icall), cam_out%sols, pcols, lchnk)
1701 30960 : call outfld('SOLL'//diag(icall), cam_out%soll, pcols, lchnk)
1702 30960 : call outfld('SOLSD'//diag(icall), cam_out%solsd, pcols, lchnk)
1703 30960 : call outfld('SOLLD'//diag(icall), cam_out%solld, pcols, lchnk)
1704 :
1705 30960 : call outfld('FSNS'//diag(icall), fsns, pcols, lchnk)
1706 30960 : call outfld('FSNSC'//diag(icall), rd%fsnsc, pcols, lchnk)
1707 :
1708 30960 : call outfld('FSDS'//diag(icall), fsds, pcols, lchnk)
1709 30960 : call outfld('FSDSC'//diag(icall), rd%fsdsc, pcols, lchnk)
1710 :
1711 30960 : call outfld('FUS'//diag(icall), rd%flux_sw_up, pcols, lchnk)
1712 30960 : call outfld('FUSC'//diag(icall), rd%flux_sw_clr_up, pcols, lchnk)
1713 30960 : call outfld('FDS'//diag(icall), rd%flux_sw_dn, pcols, lchnk)
1714 30960 : call outfld('FDSC'//diag(icall), rd%flux_sw_clr_dn, pcols, lchnk)
1715 :
1716 30960 : end subroutine radiation_output_sw
1717 :
1718 : !===============================================================================
1719 :
1720 30960 : subroutine radiation_output_cld(lchnk, rd)
1721 :
1722 : ! Dump shortwave cloud optics information to history buffer.
1723 :
1724 : integer , intent(in) :: lchnk
1725 : type(rad_out_t), intent(in) :: rd
1726 : !----------------------------------------------------------------------------
1727 :
1728 30960 : call outfld('TOT_CLD_VISTAU', rd%tot_cld_vistau, pcols, lchnk)
1729 30960 : call outfld('TOT_ICLD_VISTAU', rd%tot_icld_vistau, pcols, lchnk)
1730 30960 : call outfld('LIQ_ICLD_VISTAU', rd%liq_icld_vistau, pcols, lchnk)
1731 30960 : call outfld('ICE_ICLD_VISTAU', rd%ice_icld_vistau, pcols, lchnk)
1732 30960 : if (cldfsnow_idx > 0) then
1733 30960 : call outfld('SNOW_ICLD_VISTAU', rd%snow_icld_vistau, pcols, lchnk)
1734 : endif
1735 30960 : if (cldfgrau_idx > 0 .and. graupel_in_rad) then
1736 0 : call outfld('GRAU_ICLD_VISTAU', rd%grau_icld_vistau , pcols, lchnk)
1737 : endif
1738 :
1739 30960 : end subroutine radiation_output_cld
1740 :
1741 : !===============================================================================
1742 :
1743 30960 : subroutine radiation_output_lw(lchnk, ncol, icall, rd, pbuf, cam_out)
1744 :
1745 : ! Dump longwave radiation information to history buffer
1746 :
1747 : integer, intent(in) :: lchnk
1748 : integer, intent(in) :: ncol
1749 : integer, intent(in) :: icall ! icall=0 for climate diagnostics
1750 : type(rad_out_t), intent(in) :: rd
1751 : type(physics_buffer_desc), pointer :: pbuf(:)
1752 : type(cam_out_t), intent(in) :: cam_out
1753 :
1754 : ! local variables
1755 30960 : real(r8), pointer :: qrl(:,:)
1756 30960 : real(r8), pointer :: flnt(:)
1757 30960 : real(r8), pointer :: flns(:)
1758 :
1759 : real(r8) :: ftem(pcols)
1760 : !----------------------------------------------------------------------------
1761 :
1762 30960 : call pbuf_get_field(pbuf, qrl_idx, qrl)
1763 30960 : call pbuf_get_field(pbuf, flnt_idx, flnt)
1764 30960 : call pbuf_get_field(pbuf, flns_idx, flns)
1765 :
1766 48108240 : call outfld('QRL'//diag(icall), qrl(:ncol,:)/cpair, ncol, lchnk)
1767 48108240 : call outfld('QRLC'//diag(icall), rd%qrlc(:ncol,:)/cpair, ncol, lchnk)
1768 :
1769 30960 : call outfld('FLNT'//diag(icall), flnt, pcols, lchnk)
1770 30960 : call outfld('FLNTC'//diag(icall), rd%flntc, pcols, lchnk)
1771 :
1772 30960 : call outfld('FLUT'//diag(icall), rd%flut, pcols, lchnk)
1773 30960 : call outfld('FLUTC'//diag(icall), rd%flutc, pcols, lchnk)
1774 :
1775 516960 : ftem(:ncol) = rd%flutc(:ncol) - rd%flut(:ncol)
1776 30960 : call outfld('LWCF'//diag(icall), ftem, pcols, lchnk)
1777 :
1778 30960 : call outfld('FLN200'//diag(icall), rd%fln200, pcols, lchnk)
1779 30960 : call outfld('FLN200C'//diag(icall), rd%fln200c, pcols, lchnk)
1780 :
1781 30960 : call outfld('FLNR'//diag(icall), rd%flnr, pcols, lchnk)
1782 :
1783 30960 : call outfld('FLNS'//diag(icall), flns, pcols, lchnk)
1784 30960 : call outfld('FLNSC'//diag(icall), rd%flnsc, pcols, lchnk)
1785 :
1786 30960 : call outfld('FLDS'//diag(icall), cam_out%flwds, pcols, lchnk)
1787 30960 : call outfld('FLDSC'//diag(icall), rd%fldsc, pcols, lchnk)
1788 :
1789 30960 : call outfld('FDL'//diag(icall), rd%flux_lw_dn, pcols, lchnk)
1790 30960 : call outfld('FDLC'//diag(icall), rd%flux_lw_clr_dn, pcols, lchnk)
1791 30960 : call outfld('FUL'//diag(icall), rd%flux_lw_up, pcols, lchnk)
1792 30960 : call outfld('FULC'//diag(icall), rd%flux_lw_clr_up, pcols, lchnk)
1793 :
1794 30960 : end subroutine radiation_output_lw
1795 :
1796 : !===============================================================================
1797 :
1798 3072 : subroutine coefs_init(coefs_file, available_gases, kdist)
1799 :
1800 : ! Read data from coefficients file. Initialize the kdist object.
1801 : ! available_gases object provides the gas names that CAM provides.
1802 :
1803 : ! arguments
1804 : character(len=*), intent(in) :: coefs_file
1805 : class(ty_gas_concs), intent(in) :: available_gases
1806 : class(ty_gas_optics_rrtmgp), intent(out) :: kdist
1807 :
1808 : ! local variables
1809 : type(file_desc_t) :: fh ! pio file handle
1810 : character(len=cl) :: locfn ! path to file on local storage
1811 :
1812 : ! File dimensions
1813 : integer :: &
1814 : absorber, &
1815 : atmos_layer, &
1816 : bnd, &
1817 : pressure, &
1818 : temperature, &
1819 : absorber_ext, &
1820 : pressure_interp, &
1821 : mixing_fraction, &
1822 : gpt, &
1823 : temperature_Planck
1824 :
1825 : integer :: i
1826 : integer :: did, vid
1827 : integer :: ierr, istat
1828 :
1829 3072 : character(32), dimension(:), allocatable :: gas_names
1830 3072 : integer, dimension(:,:,:), allocatable :: key_species
1831 3072 : integer, dimension(:,:), allocatable :: band2gpt
1832 3072 : real(r8), dimension(:,:), allocatable :: band_lims_wavenum
1833 3072 : real(r8), dimension(:), allocatable :: press_ref, temp_ref
1834 : real(r8) :: press_ref_trop, temp_ref_t, temp_ref_p
1835 3072 : real(r8), dimension(:,:,:), allocatable :: vmr_ref
1836 3072 : real(r8), dimension(:,:,:,:), allocatable :: kmajor
1837 3072 : real(r8), dimension(:,:,:), allocatable :: kminor_lower, kminor_upper
1838 3072 : real(r8), dimension(:,:), allocatable :: totplnk
1839 3072 : real(r8), dimension(:,:,:,:), allocatable :: planck_frac
1840 3072 : real(r8), dimension(:), allocatable :: solar_src_quiet, solar_src_facular, solar_src_sunspot
1841 : real(r8) :: tsi_default
1842 3072 : real(r8), dimension(:,:,:), allocatable :: rayl_lower, rayl_upper
1843 3072 : character(len=32), dimension(:), allocatable :: gas_minor, &
1844 3072 : identifier_minor, &
1845 3072 : minor_gases_lower, &
1846 3072 : minor_gases_upper, &
1847 3072 : scaling_gas_lower, &
1848 3072 : scaling_gas_upper
1849 3072 : integer, dimension(:,:), allocatable :: minor_limits_gpt_lower, &
1850 3072 : minor_limits_gpt_upper
1851 : ! Send these to RRTMGP as logicals,
1852 : ! but they have to be read from the netCDF as integers
1853 3072 : logical, dimension(:), allocatable :: minor_scales_with_density_lower, &
1854 3072 : minor_scales_with_density_upper
1855 3072 : logical, dimension(:), allocatable :: scale_by_complement_lower, &
1856 3072 : scale_by_complement_upper
1857 3072 : integer, dimension(:), allocatable :: int2log ! use this to convert integer-to-logical.
1858 3072 : integer, dimension(:), allocatable :: kminor_start_lower, kminor_start_upper
1859 3072 : real(r8), dimension(:,:), allocatable :: optimal_angle_fit
1860 : real(r8) :: mg_default, sb_default
1861 :
1862 : integer :: pairs, &
1863 : minorabsorbers, &
1864 : minor_absorber_intervals_lower, &
1865 : minor_absorber_intervals_upper, &
1866 : contributors_lower, &
1867 : contributors_upper, &
1868 : fit_coeffs
1869 :
1870 : character(len=128) :: error_msg
1871 : character(len=*), parameter :: sub = 'coefs_init'
1872 : !----------------------------------------------------------------------------
1873 :
1874 : ! Open file
1875 3072 : call getfil(coefs_file, locfn, 0)
1876 3072 : call cam_pio_openfile(fh, locfn, PIO_NOWRITE)
1877 :
1878 3072 : call pio_seterrorhandling(fh, PIO_BCAST_ERROR)
1879 :
1880 : ! Get dimensions
1881 :
1882 3072 : ierr = pio_inq_dimid(fh, 'absorber', did)
1883 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': absorber not found')
1884 3072 : ierr = pio_inq_dimlen(fh, did, absorber)
1885 :
1886 3072 : ierr = pio_inq_dimid(fh, 'atmos_layer', did)
1887 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': atmos_layer not found')
1888 3072 : ierr = pio_inq_dimlen(fh, did, atmos_layer)
1889 :
1890 3072 : ierr = pio_inq_dimid(fh, 'bnd', did)
1891 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': bnd not found')
1892 3072 : ierr = pio_inq_dimlen(fh, did, bnd)
1893 :
1894 3072 : ierr = pio_inq_dimid(fh, 'pressure', did)
1895 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': pressure not found')
1896 3072 : ierr = pio_inq_dimlen(fh, did, pressure)
1897 :
1898 3072 : ierr = pio_inq_dimid(fh, 'temperature', did)
1899 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': temperature not found')
1900 3072 : ierr = pio_inq_dimlen(fh, did, temperature)
1901 :
1902 3072 : ierr = pio_inq_dimid(fh, 'absorber_ext', did)
1903 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': absorber_ext not found')
1904 3072 : ierr = pio_inq_dimlen(fh, did, absorber_ext)
1905 :
1906 3072 : ierr = pio_inq_dimid(fh, 'pressure_interp', did)
1907 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': pressure_interp not found')
1908 3072 : ierr = pio_inq_dimlen(fh, did, pressure_interp)
1909 :
1910 3072 : ierr = pio_inq_dimid(fh, 'mixing_fraction', did)
1911 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': mixing_fraction not found')
1912 3072 : ierr = pio_inq_dimlen(fh, did, mixing_fraction)
1913 :
1914 3072 : ierr = pio_inq_dimid(fh, 'gpt', did)
1915 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': gpt not found')
1916 3072 : ierr = pio_inq_dimlen(fh, did, gpt)
1917 :
1918 3072 : temperature_Planck = 0
1919 3072 : ierr = pio_inq_dimid(fh, 'temperature_Planck', did)
1920 3072 : if (ierr == PIO_NOERR) then
1921 1536 : ierr = pio_inq_dimlen(fh, did, temperature_Planck)
1922 : end if
1923 3072 : ierr = pio_inq_dimid(fh, 'pair', did)
1924 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': pair not found')
1925 3072 : ierr = pio_inq_dimlen(fh, did, pairs)
1926 3072 : ierr = pio_inq_dimid(fh, 'minor_absorber', did)
1927 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_absorber not found')
1928 3072 : ierr = pio_inq_dimlen(fh, did, minorabsorbers)
1929 3072 : ierr = pio_inq_dimid(fh, 'minor_absorber_intervals_lower', did)
1930 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_absorber_intervals_lower not found')
1931 3072 : ierr = pio_inq_dimlen(fh, did, minor_absorber_intervals_lower)
1932 3072 : ierr = pio_inq_dimid(fh, 'minor_absorber_intervals_upper', did)
1933 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_absorber_intervals_upper not found')
1934 3072 : ierr = pio_inq_dimlen(fh, did, minor_absorber_intervals_upper)
1935 3072 : ierr = pio_inq_dimid(fh, 'contributors_lower', did)
1936 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': contributors_lower not found')
1937 3072 : ierr = pio_inq_dimlen(fh, did, contributors_lower)
1938 3072 : ierr = pio_inq_dimid(fh, 'contributors_upper', did)
1939 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': contributors_upper not found')
1940 3072 : ierr = pio_inq_dimlen(fh, did, contributors_upper)
1941 :
1942 3072 : ierr = pio_inq_dimid(fh, 'fit_coeffs', did)
1943 3072 : if (ierr == PIO_NOERR) then
1944 1536 : ierr = pio_inq_dimlen(fh, did, fit_coeffs)
1945 : end if
1946 :
1947 : ! Get variables
1948 :
1949 : ! names of absorbing gases
1950 9216 : allocate(gas_names(absorber), stat=istat)
1951 3072 : call handle_allocate_error(istat, sub, 'gas_names')
1952 3072 : ierr = pio_inq_varid(fh, 'gas_names', vid)
1953 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': gas_names not found')
1954 3072 : ierr = pio_get_var(fh, vid, gas_names)
1955 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading gas_names')
1956 :
1957 : ! key species pair for each band
1958 12288 : allocate(key_species(2,atmos_layer,bnd), stat=istat)
1959 3072 : call handle_allocate_error(istat, sub, 'key_species')
1960 3072 : ierr = pio_inq_varid(fh, 'key_species', vid)
1961 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': key_species not found')
1962 3072 : ierr = pio_get_var(fh, vid, key_species)
1963 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading key_species')
1964 :
1965 : ! beginning and ending gpoint for each band
1966 9216 : allocate(band2gpt(2,bnd), stat=istat)
1967 3072 : call handle_allocate_error(istat, sub, 'band2gpt')
1968 3072 : ierr = pio_inq_varid(fh, 'bnd_limits_gpt', vid)
1969 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': bnd_limits_gpt not found')
1970 3072 : ierr = pio_get_var(fh, vid, band2gpt)
1971 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading bnd_limits_gpt')
1972 :
1973 : ! beginning and ending wavenumber for each band
1974 9216 : allocate(band_lims_wavenum(2,bnd), stat=istat)
1975 3072 : call handle_allocate_error(istat, sub, 'band_lims_wavenum')
1976 3072 : ierr = pio_inq_varid(fh, 'bnd_limits_wavenumber', vid)
1977 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': bnd_limits_wavenumber not found')
1978 3072 : ierr = pio_get_var(fh, vid, band_lims_wavenum)
1979 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading bnd_limits_wavenumber')
1980 :
1981 : ! pressures [hPa] for reference atmosphere; press_ref(# reference layers)
1982 9216 : allocate(press_ref(pressure), stat=istat)
1983 3072 : call handle_allocate_error(istat, sub, 'press_ref')
1984 3072 : ierr = pio_inq_varid(fh, 'press_ref', vid)
1985 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': press_ref not found')
1986 3072 : ierr = pio_get_var(fh, vid, press_ref)
1987 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading press_ref')
1988 :
1989 : ! reference pressure separating the lower and upper atmosphere
1990 3072 : ierr = pio_inq_varid(fh, 'press_ref_trop', vid)
1991 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': press_ref_trop not found')
1992 3072 : ierr = pio_get_var(fh, vid, press_ref_trop)
1993 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading press_ref_trop')
1994 :
1995 : ! temperatures [K] for reference atmosphere; temp_ref(# reference layers)
1996 9216 : allocate(temp_ref(temperature), stat=istat)
1997 3072 : call handle_allocate_error(istat, sub, 'temp_ref')
1998 3072 : ierr = pio_inq_varid(fh, 'temp_ref', vid)
1999 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': temp_ref not found')
2000 3072 : ierr = pio_get_var(fh, vid, temp_ref)
2001 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading temp_ref')
2002 :
2003 : ! standard spectroscopic reference temperature [K]
2004 3072 : ierr = pio_inq_varid(fh, 'absorption_coefficient_ref_T', vid)
2005 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': absorption_coefficient_ref_T not found')
2006 3072 : ierr = pio_get_var(fh, vid, temp_ref_t)
2007 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading absorption_coefficient_ref_T')
2008 :
2009 : ! standard spectroscopic reference pressure [hPa]
2010 3072 : ierr = pio_inq_varid(fh, 'absorption_coefficient_ref_P', vid)
2011 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': absorption_coefficient_ref_P not found')
2012 3072 : ierr = pio_get_var(fh, vid, temp_ref_p)
2013 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading absorption_coefficient_ref_P')
2014 :
2015 : ! volume mixing ratios for reference atmosphere
2016 15360 : allocate(vmr_ref(atmos_layer, absorber_ext, temperature), stat=istat)
2017 3072 : call handle_allocate_error(istat, sub, 'vmr_ref')
2018 3072 : ierr = pio_inq_varid(fh, 'vmr_ref', vid)
2019 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': vmr_ref not found')
2020 3072 : ierr = pio_get_var(fh, vid, vmr_ref)
2021 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading vmr_ref')
2022 :
2023 : ! absorption coefficients due to major absorbing gases
2024 18432 : allocate(kmajor(gpt,mixing_fraction,pressure_interp,temperature), stat=istat)
2025 3072 : call handle_allocate_error(istat, sub, 'kmajor')
2026 3072 : ierr = pio_inq_varid(fh, 'kmajor', vid)
2027 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': kmajor not found')
2028 3072 : ierr = pio_get_var(fh, vid, kmajor)
2029 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading kmajor')
2030 :
2031 : ! absorption coefficients due to minor absorbing gases in lower part of atmosphere
2032 15360 : allocate(kminor_lower(contributors_lower, mixing_fraction, temperature), stat=istat)
2033 3072 : call handle_allocate_error(istat, sub, 'kminor_lower')
2034 3072 : ierr = pio_inq_varid(fh, 'kminor_lower', vid)
2035 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': kminor_lower not found')
2036 3072 : ierr = pio_get_var(fh, vid, kminor_lower)
2037 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_lower')
2038 :
2039 : ! absorption coefficients due to minor absorbing gases in upper part of atmosphere
2040 15360 : allocate(kminor_upper(contributors_upper, mixing_fraction, temperature), stat=istat)
2041 3072 : call handle_allocate_error(istat, sub, 'kminor_upper')
2042 3072 : ierr = pio_inq_varid(fh, 'kminor_upper', vid)
2043 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': kminor_upper not found')
2044 3072 : ierr = pio_get_var(fh, vid, kminor_upper)
2045 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_upper')
2046 :
2047 : ! integrated Planck function by band
2048 3072 : ierr = pio_inq_varid(fh, 'totplnk', vid)
2049 3072 : if (ierr == PIO_NOERR) then
2050 6144 : allocate(totplnk(temperature_Planck,bnd), stat=istat)
2051 1536 : call handle_allocate_error(istat, sub, 'totplnk')
2052 1536 : ierr = pio_get_var(fh, vid, totplnk)
2053 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading totplnk')
2054 : end if
2055 :
2056 : ! Planck fractions
2057 3072 : ierr = pio_inq_varid(fh, 'plank_fraction', vid)
2058 3072 : if (ierr == PIO_NOERR) then
2059 9216 : allocate(planck_frac(gpt,mixing_fraction,pressure_interp,temperature), stat=istat)
2060 1536 : call handle_allocate_error(istat, sub, 'planck_frac')
2061 1536 : ierr = pio_get_var(fh, vid, planck_frac)
2062 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading plank_fraction')
2063 : end if
2064 :
2065 3072 : ierr = pio_inq_varid(fh, 'optimal_angle_fit', vid)
2066 3072 : if (ierr == PIO_NOERR) then
2067 6144 : allocate(optimal_angle_fit(fit_coeffs, bnd), stat=istat)
2068 1536 : call handle_allocate_error(istat, sub, 'optiman_angle_fit')
2069 1536 : ierr = pio_get_var(fh, vid, optimal_angle_fit)
2070 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading optimal_angle_fit')
2071 : end if
2072 :
2073 3072 : ierr = pio_inq_varid(fh, 'solar_source_quiet', vid)
2074 3072 : if (ierr == PIO_NOERR) then
2075 4608 : allocate(solar_src_quiet(gpt), stat=istat)
2076 1536 : call handle_allocate_error(istat, sub, 'solar_src_quiet')
2077 1536 : ierr = pio_get_var(fh, vid, solar_src_quiet)
2078 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading solar_source_quiet')
2079 : end if
2080 :
2081 3072 : ierr = pio_inq_varid(fh, 'solar_source_facular', vid)
2082 3072 : if (ierr == PIO_NOERR) then
2083 4608 : allocate(solar_src_facular(gpt), stat=istat)
2084 1536 : call handle_allocate_error(istat, sub, 'solar_src_facular')
2085 1536 : ierr = pio_get_var(fh, vid, solar_src_facular)
2086 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading solar_source_facular')
2087 : end if
2088 :
2089 3072 : ierr = pio_inq_varid(fh, 'solar_source_sunspot', vid)
2090 3072 : if (ierr == PIO_NOERR) then
2091 4608 : allocate(solar_src_sunspot(gpt), stat=istat)
2092 1536 : call handle_allocate_error(istat, sub, 'solar_src_sunspot')
2093 1536 : ierr = pio_get_var(fh, vid, solar_src_sunspot)
2094 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading solar_source_sunspot')
2095 : end if
2096 :
2097 3072 : ierr = pio_inq_varid(fh, 'tsi_default', vid)
2098 3072 : if (ierr == PIO_NOERR) then
2099 1536 : ierr = pio_get_var(fh, vid, tsi_default)
2100 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading tsi_default')
2101 : end if
2102 :
2103 3072 : ierr = pio_inq_varid(fh, 'mg_default', vid)
2104 3072 : if (ierr == PIO_NOERR) then
2105 1536 : ierr = pio_get_var(fh, vid, mg_default)
2106 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading mg_default')
2107 : end if
2108 :
2109 3072 : ierr = pio_inq_varid(fh, 'sb_default', vid)
2110 3072 : if (ierr == PIO_NOERR) then
2111 1536 : ierr = pio_get_var(fh, vid, sb_default)
2112 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading sb_default')
2113 : end if
2114 :
2115 : ! rayleigh scattering contribution in lower part of atmosphere
2116 3072 : ierr = pio_inq_varid(fh, 'rayl_lower', vid)
2117 3072 : if (ierr == PIO_NOERR) then
2118 7680 : allocate(rayl_lower(gpt,mixing_fraction,temperature), stat=istat)
2119 1536 : call handle_allocate_error(istat, sub, 'rayl_lower')
2120 1536 : ierr = pio_get_var(fh, vid, rayl_lower)
2121 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading rayl_lower')
2122 : end if
2123 :
2124 : ! rayleigh scattering contribution in upper part of atmosphere
2125 3072 : ierr = pio_inq_varid(fh, 'rayl_upper', vid)
2126 3072 : if (ierr == PIO_NOERR) then
2127 7680 : allocate(rayl_upper(gpt,mixing_fraction,temperature), stat=istat)
2128 1536 : call handle_allocate_error(istat, sub, 'rayl_upper')
2129 1536 : ierr = pio_get_var(fh, vid, rayl_upper)
2130 1536 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading rayl_upper')
2131 : end if
2132 :
2133 9216 : allocate(gas_minor(minorabsorbers), stat=istat)
2134 3072 : call handle_allocate_error(istat, sub, 'gas_minor')
2135 3072 : ierr = pio_inq_varid(fh, 'gas_minor', vid)
2136 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': gas_minor not found')
2137 3072 : ierr = pio_get_var(fh, vid, gas_minor)
2138 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading gas_minor')
2139 :
2140 9216 : allocate(identifier_minor(minorabsorbers), stat=istat)
2141 3072 : call handle_allocate_error(istat, sub, 'identifier_minor')
2142 3072 : ierr = pio_inq_varid(fh, 'identifier_minor', vid)
2143 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': identifier_minor not found')
2144 3072 : ierr = pio_get_var(fh, vid, identifier_minor)
2145 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading identifier_minor')
2146 :
2147 9216 : allocate(minor_gases_lower(minor_absorber_intervals_lower), stat=istat)
2148 3072 : call handle_allocate_error(istat, sub, 'minor_gases_lower')
2149 3072 : ierr = pio_inq_varid(fh, 'minor_gases_lower', vid)
2150 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_gases_lower not found')
2151 3072 : ierr = pio_get_var(fh, vid, minor_gases_lower)
2152 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_gases_lower')
2153 :
2154 9216 : allocate(minor_gases_upper(minor_absorber_intervals_upper), stat=istat)
2155 3072 : call handle_allocate_error(istat, sub, 'minor_gases_upper')
2156 3072 : ierr = pio_inq_varid(fh, 'minor_gases_upper', vid)
2157 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_gases_upper not found')
2158 3072 : ierr = pio_get_var(fh, vid, minor_gases_upper)
2159 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_gases_upper')
2160 :
2161 12288 : allocate(minor_limits_gpt_lower(pairs,minor_absorber_intervals_lower), stat=istat)
2162 3072 : call handle_allocate_error(istat, sub, 'minor_limits_gpt_lower')
2163 3072 : ierr = pio_inq_varid(fh, 'minor_limits_gpt_lower', vid)
2164 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_limits_gpt_lower not found')
2165 3072 : ierr = pio_get_var(fh, vid, minor_limits_gpt_lower)
2166 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_limits_gpt_lower')
2167 :
2168 12288 : allocate(minor_limits_gpt_upper(pairs,minor_absorber_intervals_upper), stat=istat)
2169 3072 : call handle_allocate_error(istat, sub, 'minor_limits_gpt_upper')
2170 3072 : ierr = pio_inq_varid(fh, 'minor_limits_gpt_upper', vid)
2171 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_limits_gpt_upper not found')
2172 3072 : ierr = pio_get_var(fh, vid, minor_limits_gpt_upper)
2173 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_limits_gpt_upper')
2174 :
2175 : ! Read as integer and convert to logical
2176 9216 : allocate(int2log(minor_absorber_intervals_lower), stat=istat)
2177 3072 : call handle_allocate_error(istat, sub, 'int2log for lower')
2178 :
2179 9216 : allocate(minor_scales_with_density_lower(minor_absorber_intervals_lower), stat=istat)
2180 3072 : call handle_allocate_error(istat, sub, 'minor_scales_with_density_lower')
2181 3072 : ierr = pio_inq_varid(fh, 'minor_scales_with_density_lower', vid)
2182 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_scales_with_density_lower not found')
2183 3072 : ierr = pio_get_var(fh, vid, int2log)
2184 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_scales_with_density_lower')
2185 147456 : do i = 1,minor_absorber_intervals_lower
2186 147456 : if (int2log(i) .eq. 0) then
2187 53760 : minor_scales_with_density_lower(i) = .false.
2188 : else
2189 90624 : minor_scales_with_density_lower(i) = .true.
2190 : end if
2191 : end do
2192 :
2193 9216 : allocate(scale_by_complement_lower(minor_absorber_intervals_lower), stat=istat)
2194 3072 : call handle_allocate_error(istat, sub, 'scale_by_complement_lower')
2195 3072 : ierr = pio_inq_varid(fh, 'scale_by_complement_lower', vid)
2196 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': scale_by_complement_lower not found')
2197 3072 : ierr = pio_get_var(fh, vid, int2log)
2198 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading scale_by_complement_lower')
2199 147456 : do i = 1,minor_absorber_intervals_lower
2200 147456 : if (int2log(i) .eq. 0) then
2201 104448 : scale_by_complement_lower(i) = .false.
2202 : else
2203 39936 : scale_by_complement_lower(i) = .true.
2204 : end if
2205 : end do
2206 :
2207 3072 : deallocate(int2log)
2208 :
2209 : ! Read as integer and convert to logical
2210 9216 : allocate(int2log(minor_absorber_intervals_upper), stat=istat)
2211 3072 : call handle_allocate_error(istat, sub, 'int2log for upper')
2212 :
2213 9216 : allocate(minor_scales_with_density_upper(minor_absorber_intervals_upper), stat=istat)
2214 3072 : call handle_allocate_error(istat, sub, 'minor_scales_with_density_upper')
2215 3072 : ierr = pio_inq_varid(fh, 'minor_scales_with_density_upper', vid)
2216 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': minor_scales_with_density_upper not found')
2217 3072 : ierr = pio_get_var(fh, vid, int2log)
2218 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading minor_scales_with_density_upper')
2219 92160 : do i = 1,minor_absorber_intervals_upper
2220 92160 : if (int2log(i) .eq. 0) then
2221 46080 : minor_scales_with_density_upper(i) = .false.
2222 : else
2223 43008 : minor_scales_with_density_upper(i) = .true.
2224 : end if
2225 : end do
2226 :
2227 9216 : allocate(scale_by_complement_upper(minor_absorber_intervals_upper), stat=istat)
2228 3072 : call handle_allocate_error(istat, sub, 'scale_by_complement_upper')
2229 3072 : ierr = pio_inq_varid(fh, 'scale_by_complement_upper', vid)
2230 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': scale_by_complement_upper not found')
2231 3072 : ierr = pio_get_var(fh, vid, int2log)
2232 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading scale_by_complement_upper')
2233 92160 : do i = 1,minor_absorber_intervals_upper
2234 92160 : if (int2log(i) .eq. 0) then
2235 70656 : scale_by_complement_upper(i) = .false.
2236 : else
2237 18432 : scale_by_complement_upper(i) = .true.
2238 : end if
2239 : end do
2240 :
2241 3072 : deallocate(int2log)
2242 :
2243 9216 : allocate(scaling_gas_lower(minor_absorber_intervals_lower), stat=istat)
2244 3072 : call handle_allocate_error(istat, sub, 'scaling_gas_lower')
2245 3072 : ierr = pio_inq_varid(fh, 'scaling_gas_lower', vid)
2246 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': scaling_gas_lower not found')
2247 3072 : ierr = pio_get_var(fh, vid, scaling_gas_lower)
2248 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading scaling_gas_lower')
2249 :
2250 9216 : allocate(scaling_gas_upper(minor_absorber_intervals_upper), stat=istat)
2251 3072 : call handle_allocate_error(istat, sub, 'scaling_gas_upper')
2252 3072 : ierr = pio_inq_varid(fh, 'scaling_gas_upper', vid)
2253 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': scaling_gas_upper not found')
2254 3072 : ierr = pio_get_var(fh, vid, scaling_gas_upper)
2255 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading scaling_gas_upper')
2256 :
2257 9216 : allocate(kminor_start_lower(minor_absorber_intervals_lower), stat=istat)
2258 3072 : call handle_allocate_error(istat, sub, 'kminor_start_lower')
2259 3072 : ierr = pio_inq_varid(fh, 'kminor_start_lower', vid)
2260 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': kminor_start_lower not found')
2261 3072 : ierr = pio_get_var(fh, vid, kminor_start_lower)
2262 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_start_lower')
2263 :
2264 9216 : allocate(kminor_start_upper(minor_absorber_intervals_upper), stat=istat)
2265 3072 : call handle_allocate_error(istat, sub, 'kminor_start_upper')
2266 3072 : ierr = pio_inq_varid(fh, 'kminor_start_upper', vid)
2267 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': kminor_start_upper not found')
2268 3072 : ierr = pio_get_var(fh, vid, kminor_start_upper)
2269 3072 : if (ierr /= PIO_NOERR) call endrun(sub//': error reading kminor_start_upper')
2270 :
2271 : ! Close file
2272 3072 : call pio_closefile(fh)
2273 :
2274 : ! Initialize the gas optics object with data. The calls are slightly different depending
2275 : ! on whether the radiation sources are internal to the atmosphere (longwave) or external (shortwave)
2276 :
2277 3072 : if (allocated(totplnk) .and. allocated(planck_frac)) then
2278 : error_msg = kdist%load( &
2279 : available_gases, gas_names, key_species, &
2280 : band2gpt, band_lims_wavenum, &
2281 : press_ref, press_ref_trop, temp_ref, &
2282 : temp_ref_p, temp_ref_t, vmr_ref, &
2283 : kmajor, kminor_lower, kminor_upper, &
2284 : gas_minor, identifier_minor, &
2285 : minor_gases_lower, minor_gases_upper, &
2286 : minor_limits_gpt_lower, minor_limits_gpt_upper, &
2287 : minor_scales_with_density_lower, &
2288 : minor_scales_with_density_upper, &
2289 : scaling_gas_lower, scaling_gas_upper, &
2290 : scale_by_complement_lower, scale_by_complement_upper, &
2291 : kminor_start_lower, kminor_start_upper, &
2292 : totplnk, planck_frac, rayl_lower, rayl_upper, &
2293 1536 : optimal_angle_fit)
2294 1536 : else if (allocated(solar_src_quiet)) then
2295 : error_msg = kdist%load( &
2296 : available_gases, gas_names, key_species, &
2297 : band2gpt, band_lims_wavenum, &
2298 : press_ref, press_ref_trop, temp_ref, &
2299 : temp_ref_p, temp_ref_t, vmr_ref, &
2300 : kmajor, kminor_lower, kminor_upper, &
2301 : gas_minor, identifier_minor, &
2302 : minor_gases_lower, minor_gases_upper, &
2303 : minor_limits_gpt_lower, minor_limits_gpt_upper, &
2304 : minor_scales_with_density_lower, &
2305 : minor_scales_with_density_upper, &
2306 : scaling_gas_lower, scaling_gas_upper, &
2307 : scale_by_complement_lower, &
2308 : scale_by_complement_upper, &
2309 : kminor_start_lower, &
2310 : kminor_start_upper, &
2311 : solar_src_quiet, solar_src_facular, solar_src_sunspot, &
2312 : tsi_default, mg_default, sb_default, &
2313 1536 : rayl_lower, rayl_upper)
2314 : else
2315 0 : error_msg = 'must supply either totplnk and planck_frac, or solar_src_[*]'
2316 : end if
2317 :
2318 3072 : call stop_on_err(error_msg, sub, 'kdist%load')
2319 :
2320 0 : deallocate( &
2321 0 : gas_names, key_species, &
2322 0 : band2gpt, band_lims_wavenum, &
2323 0 : press_ref, temp_ref, vmr_ref, &
2324 0 : kmajor, kminor_lower, kminor_upper, &
2325 0 : gas_minor, identifier_minor, &
2326 0 : minor_gases_lower, minor_gases_upper, &
2327 0 : minor_limits_gpt_lower, &
2328 0 : minor_limits_gpt_upper, &
2329 0 : minor_scales_with_density_lower, &
2330 0 : minor_scales_with_density_upper, &
2331 0 : scale_by_complement_lower, &
2332 0 : scale_by_complement_upper, &
2333 0 : scaling_gas_lower, scaling_gas_upper, &
2334 3072 : kminor_start_lower, kminor_start_upper)
2335 :
2336 3072 : if (allocated(totplnk)) deallocate(totplnk)
2337 3072 : if (allocated(planck_frac)) deallocate(planck_frac)
2338 3072 : if (allocated(optimal_angle_fit)) deallocate(optimal_angle_fit)
2339 3072 : if (allocated(solar_src_quiet)) deallocate(solar_src_quiet)
2340 3072 : if (allocated(solar_src_facular)) deallocate(solar_src_facular)
2341 3072 : if (allocated(solar_src_sunspot)) deallocate(solar_src_sunspot)
2342 3072 : if (allocated(rayl_lower)) deallocate(rayl_lower)
2343 3072 : if (allocated(rayl_upper)) deallocate(rayl_upper)
2344 :
2345 6144 : end subroutine coefs_init
2346 :
2347 : !=========================================================================================
2348 :
2349 247680 : subroutine initialize_rrtmgp_fluxes(ncol, nlevels, nbands, fluxes, do_direct)
2350 :
2351 : ! Allocate flux arrays and set values to zero.
2352 :
2353 : ! Arguments
2354 : integer, intent(in) :: ncol, nlevels, nbands
2355 : class(ty_fluxes_broadband), intent(inout) :: fluxes
2356 : logical, optional, intent(in) :: do_direct
2357 :
2358 : ! Local variables
2359 : logical :: do_direct_local
2360 : integer :: istat
2361 : character(len=*), parameter :: sub = 'initialize_rrtmgp_fluxes'
2362 : !----------------------------------------------------------------------------
2363 :
2364 247680 : if (present(do_direct)) then
2365 : do_direct_local = .true.
2366 : else
2367 123840 : do_direct_local = .false.
2368 : end if
2369 :
2370 : ! Broadband fluxes
2371 931464 : allocate(fluxes%flux_up(ncol, nlevels), stat=istat)
2372 247680 : call handle_allocate_error(istat, sub, 'fluxes%flux_up')
2373 683784 : allocate(fluxes%flux_dn(ncol, nlevels), stat=istat)
2374 247680 : call handle_allocate_error(istat, sub, 'fluxes%flux_dn')
2375 683784 : allocate(fluxes%flux_net(ncol, nlevels), stat=istat)
2376 247680 : call handle_allocate_error(istat, sub, 'fluxes%flux_net')
2377 247680 : if (do_direct_local) then
2378 312264 : allocate(fluxes%flux_dn_dir(ncol, nlevels), stat=istat)
2379 123840 : call handle_allocate_error(istat, sub, 'fluxes%flux_dn_dir')
2380 : end if
2381 :
2382 : select type (fluxes)
2383 : type is (ty_fluxes_byband)
2384 : ! Fluxes by band always needed for SW. Only allocate for LW
2385 : ! when spectralflux is true.
2386 123840 : if (nbands == nswbands .or. spectralflux) then
2387 279972 : allocate(fluxes%bnd_flux_up(ncol, nlevels, nbands), stat=istat)
2388 61920 : call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_up')
2389 218052 : allocate(fluxes%bnd_flux_dn(ncol, nlevels, nbands), stat=istat)
2390 61920 : call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_dn')
2391 218052 : allocate(fluxes%bnd_flux_net(ncol, nlevels, nbands), stat=istat)
2392 61920 : call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_net')
2393 61920 : if (do_direct_local) then
2394 218052 : allocate(fluxes%bnd_flux_dn_dir(ncol, nlevels, nbands), stat=istat)
2395 61920 : call handle_allocate_error(istat, sub, 'fluxes%bnd_flux_dn_dir')
2396 : end if
2397 : end if
2398 : end select
2399 :
2400 : ! Initialize
2401 247680 : call reset_fluxes(fluxes)
2402 :
2403 247680 : end subroutine initialize_rrtmgp_fluxes
2404 :
2405 : !=========================================================================================
2406 :
2407 247680 : subroutine reset_fluxes(fluxes)
2408 :
2409 : ! Reset flux arrays to zero.
2410 :
2411 : class(ty_fluxes_broadband), intent(inout) :: fluxes
2412 : !----------------------------------------------------------------------------
2413 :
2414 : ! Reset broadband fluxes
2415 300797280 : fluxes%flux_up(:,:) = 0._r8
2416 300797280 : fluxes%flux_dn(:,:) = 0._r8
2417 300797280 : fluxes%flux_net(:,:) = 0._r8
2418 104352480 : if (associated(fluxes%flux_dn_dir)) fluxes%flux_dn_dir(:,:) = 0._r8
2419 :
2420 : select type (fluxes)
2421 : type is (ty_fluxes_byband)
2422 : ! Reset band-by-band fluxes
2423 729662400 : if (associated(fluxes%bnd_flux_up)) fluxes%bnd_flux_up(:,:,:) = 0._r8
2424 729724320 : if (associated(fluxes%bnd_flux_dn)) fluxes%bnd_flux_dn(:,:,:) = 0._r8
2425 729724320 : if (associated(fluxes%bnd_flux_net)) fluxes%bnd_flux_net(:,:,:) = 0._r8
2426 729848160 : if (associated(fluxes%bnd_flux_dn_dir)) fluxes%bnd_flux_dn_dir(:,:,:) = 0._r8
2427 : end select
2428 :
2429 247680 : end subroutine reset_fluxes
2430 :
2431 : !=========================================================================================
2432 :
2433 185760 : subroutine free_optics_sw(optics)
2434 :
2435 : type(ty_optical_props_2str), intent(inout) :: optics
2436 :
2437 185760 : if (allocated(optics%tau)) deallocate(optics%tau)
2438 185760 : if (allocated(optics%ssa)) deallocate(optics%ssa)
2439 185760 : if (allocated(optics%g)) deallocate(optics%g)
2440 185760 : call optics%finalize()
2441 :
2442 185760 : end subroutine free_optics_sw
2443 :
2444 : !=========================================================================================
2445 :
2446 123840 : subroutine free_optics_lw(optics)
2447 :
2448 : type(ty_optical_props_1scl), intent(inout) :: optics
2449 :
2450 123840 : if (allocated(optics%tau)) deallocate(optics%tau)
2451 123840 : call optics%finalize()
2452 :
2453 123840 : end subroutine free_optics_lw
2454 :
2455 : !=========================================================================================
2456 :
2457 247680 : subroutine free_fluxes(fluxes)
2458 :
2459 : class(ty_fluxes_broadband), intent(inout) :: fluxes
2460 :
2461 247680 : if (associated(fluxes%flux_up)) deallocate(fluxes%flux_up)
2462 247680 : if (associated(fluxes%flux_dn)) deallocate(fluxes%flux_dn)
2463 247680 : if (associated(fluxes%flux_net)) deallocate(fluxes%flux_net)
2464 247680 : if (associated(fluxes%flux_dn_dir)) deallocate(fluxes%flux_dn_dir)
2465 :
2466 : select type (fluxes)
2467 : type is (ty_fluxes_byband)
2468 61920 : if (associated(fluxes%bnd_flux_up)) deallocate(fluxes%bnd_flux_up)
2469 123840 : if (associated(fluxes%bnd_flux_dn)) deallocate(fluxes%bnd_flux_dn)
2470 123840 : if (associated(fluxes%bnd_flux_net)) deallocate(fluxes%bnd_flux_net)
2471 247680 : if (associated(fluxes%bnd_flux_dn_dir)) deallocate(fluxes%bnd_flux_dn_dir)
2472 : end select
2473 :
2474 247680 : end subroutine free_fluxes
2475 :
2476 : !=========================================================================================
2477 :
2478 30960 : subroutine modified_cloud_fraction(ncol, cld, cldfsnow, cldfgrau, cldfprime)
2479 :
2480 : ! Compute modified cloud fraction, cldfprime.
2481 : ! 1. initialize as cld
2482 : ! 2. modify for snow if cldfsnow is available. use max(cld, cldfsnow)
2483 : ! 3. modify for graupel if cldfgrau is available and graupel_in_rad is true.
2484 : ! use max(cldfprime, cldfgrau)
2485 :
2486 : ! Arguments
2487 : integer, intent(in) :: ncol
2488 : real(r8), pointer :: cld(:,:) ! cloud fraction
2489 : real(r8), pointer :: cldfsnow(:,:) ! cloud fraction of just "snow clouds"
2490 : real(r8), pointer :: cldfgrau(:,:) ! cloud fraction of just "graupel clouds"
2491 : real(r8), intent(out) :: cldfprime(:,:) ! modified cloud fraction
2492 :
2493 : ! Local variables
2494 : integer :: i, k
2495 : !----------------------------------------------------------------------------
2496 :
2497 30960 : if (associated(cldfsnow)) then
2498 2910240 : do k = 1, pver
2499 48108240 : do i = 1, ncol
2500 48077280 : cldfprime(i,k) = max(cld(i,k), cldfsnow(i,k))
2501 : end do
2502 : end do
2503 : else
2504 0 : cldfprime(:ncol,:) = cld(:ncol,:)
2505 : end if
2506 :
2507 30960 : if (associated(cldfgrau) .and. graupel_in_rad) then
2508 0 : do k = 1, pver
2509 0 : do i = 1, ncol
2510 0 : cldfprime(i,k) = max(cldfprime(i,k), cldfgrau(i,k))
2511 : end do
2512 : end do
2513 : end if
2514 :
2515 30960 : end subroutine modified_cloud_fraction
2516 :
2517 : !=========================================================================================
2518 :
2519 412456 : subroutine stop_on_err(errmsg, sub, info)
2520 :
2521 : ! call endrun if RRTMGP function returns non-empty error message.
2522 :
2523 : character(len=*), intent(in) :: errmsg ! return message from RRTMGP function
2524 : character(len=*), intent(in) :: sub ! name of calling subroutine
2525 : character(len=*), intent(in) :: info ! name of called function
2526 :
2527 412456 : if (len_trim(errmsg) > 0) then
2528 0 : call endrun(trim(sub)//': ERROR: '//trim(info)//': '//trim(errmsg))
2529 : end if
2530 :
2531 412456 : end subroutine stop_on_err
2532 :
2533 : !=========================================================================================
2534 :
2535 743040 : end module radiation
2536 :
|