Skip to content

Commit addb421

Browse files
cacraigucarpeverwheeJulioTBacmeister
authored
RRTMGP mods for MT configurations (ESCOMP#266)
Originator(s): JulioTBacmeister peverwhee cacraigucar Description (include issue title and the keyword ['closes', 'fixes', 'resolves'] and issue number): No issue here, but in ESCOMP/CAM ESCOMP/CAM#1279: RRTMGP error with mpas and L93 mid-top configuration List all namelist files that were added or changed: - Added p_top_for_rrtmgp which is supplied by the host model's radiation namelist List all files eliminated and why: N/A List all files added and what they do: A to_be_ccppized/nlte_fomichev.F90 - Copied from ESCOMP/CAM - List all existing files that have been modified, and describe the changes: (Helpful git command: `git diff --name-status development...<your_branch_name>`) M schemes/rrtmgp/utils/calculate_net_heating.F90 - modifications to fix the MT configuration List all automated tests that failed, as well as an explanation for why they weren't fixed: N/A Is this an answer-changing PR? If so, is it a new physics package, algorithm change, tuning change, etc? - Answer changing for MT only in ESCOMP/CAM If yes to the above question, describe how this code was validated with the new/modified features: @JulioTBacmeister made scientific runs --------- Co-authored-by: peverwhee <courtneyp@ucar.edu> Co-authored-by: Julio Bacmeister <juliob@ucar.edu>
1 parent 178c183 commit addb421

3 files changed

Lines changed: 2600 additions & 32 deletions

File tree

schemes/rrtmgp/rrtmgp_inputs.F90

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ module rrtmgp_inputs
1313
subroutine rrtmgp_inputs_init(ktopcam, ktoprad, nlaycam, sw_low_bounds, sw_high_bounds, nswbands, &
1414
pref_edge, nlay, pver, pverp, kdist_sw, kdist_lw, qrl, is_first_step, use_rad_dt_cosz, &
1515
timestep_size, nstep, iradsw, dt_avg, irad_always, is_first_restart_step, is_root, &
16-
nlwbands, nradgas, gasnamelength, iulog, idx_sw_diag, idx_nir_diag, idx_uv_diag, &
16+
p_top_for_rrtmgp, &
17+
nlwbands, nradgas, gasnamelength, idx_sw_diag, idx_nir_diag, idx_uv_diag, &
1718
idx_sw_cloudsim, idx_lw_diag, idx_lw_cloudsim, nswgpts, nlwgpts, nlayp, &
1819
nextsw_cday, current_cal_day, band2gpt_sw, errmsg, errflg)
1920
use ccpp_kinds, only: kind_phys
@@ -26,10 +27,10 @@ subroutine rrtmgp_inputs_init(ktopcam, ktoprad, nlaycam, sw_low_bounds, sw_high_
2627
integer, intent(in) :: nradgas ! Number of radiatively active gases
2728
integer, intent(in) :: pverp ! Number of vertical interfaces
2829
integer, intent(in) :: pver ! Number of vertical layers
29-
integer, intent(in) :: iradsw ! Freq. of shortwave radiation calc in time steps (positive) or hours (negative).
30+
integer, intent(in) :: iradsw ! Freq. of shortwave radiation calc in time steps
31+
! (positive) or hours (negative).
3032
integer, intent(in) :: timestep_size ! Timestep size (s)
3133
integer, intent(in) :: nstep ! Current timestep number
32-
integer, intent(in) :: iulog ! Logging unit
3334
integer, intent(in) :: gasnamelength ! Length of all of the gas_list entries
3435
real(kind_phys), intent(in) :: current_cal_day ! Current calendar day
3536
real(kind_phys), dimension(:), intent(in) :: pref_edge ! Reference pressures (interfaces) (Pa)
@@ -39,6 +40,7 @@ subroutine rrtmgp_inputs_init(ktopcam, ktoprad, nlaycam, sw_low_bounds, sw_high_
3940
logical, intent(in) :: is_first_restart_step ! Flag for whether this is the first restart step (.true. = yes)
4041
logical, intent(in) :: use_rad_dt_cosz ! Use adjusted radiation timestep for cosz calculation
4142
logical, intent(in) :: is_root ! Flag for whether this is the root task
43+
real(kind_phys), intent(in) :: p_top_for_rrtmgp ! Top pressure to use for RRTMGP
4244

4345
! Outputs
4446
integer, intent(out) :: ktopcam ! Index in CAM arrays of top level (layer or interface) at which RRTMGP is active
@@ -81,7 +83,7 @@ subroutine rrtmgp_inputs_init(ktopcam, ktoprad, nlaycam, sw_low_bounds, sw_high_
8183
! pressure interfaces below 1 Pa. When the entire model atmosphere is
8284
! below 1 Pa then an extra layer is added to the top of the model for
8385
! the purpose of the radiation calculation.
84-
nlay = count( pref_edge(:) > 1._kind_phys ) ! pascals (0.01 mbar)
86+
nlay = count( pref_edge(:) > p_top_for_rrtmgp )
8587
nlayp = nlay + 1
8688

8789
if (nlay == pverp) then
@@ -90,16 +92,6 @@ subroutine rrtmgp_inputs_init(ktopcam, ktoprad, nlaycam, sw_low_bounds, sw_high_
9092
ktopcam = 1
9193
ktoprad = 2
9294
nlaycam = pver
93-
else if (nlay == (pverp-1)) then
94-
! Special case nlay == (pverp-1) -- topmost interface outside bounds (CAM MT config), treat as if it is ok.
95-
ktopcam = 1
96-
ktoprad = 2
97-
nlaycam = pver
98-
nlay = nlay+1 ! reassign the value so later code understands to treat this case like nlay==pverp
99-
if (is_root) then
100-
write(iulog,*) 'RADIATION_INIT: Special case of 1 model interface at p < 1Pa. Top layer will be INCLUDED in radiation calculation.'
101-
write(iulog,*) 'RADIATION_INIT: nlay = ',nlay, ' same as pverp: ',nlay==pverp
102-
end if
10395
else
10496
! nlay < pverp. nlay layers are used in radiation calcs, and they are
10597
! all CAM layers.
@@ -254,33 +246,49 @@ subroutine rrtmgp_inputs_run(dosw, dolw, snow_associated, graupel_associated, &
254246
! to be consistent with t_sfc.
255247
emis_sfc(:,:) = 1._kind_phys
256248

249+
!-------------------------------------------------------------------------
250+
! RRTMGP enforces P > 1 Pa for validity.
251+
! In radiation.F90 we count layers based on P_ref > 10 Pa to safely account
252+
! for possible situations in MPAS (z-based vert. coordinate) in which
253+
! full 3D pressure could be significanlty below min(P_ref).
254+
!
255+
! If
256+
! 1) entire vertical domain has P_ref> 10Pa (e.g. CAM7 LT) then
257+
! nlay = pverp
258+
! ktoprad = 2
259+
! ktopcam = 1
260+
! 2) min(P_ref) < 10Pa (e.g. CAM7 MT) then
261+
! nlay < pverp
262+
! ktoprad = 1
263+
! ktopcam = pver - nlay + 1
264+
!
257265
! Level ordering is the same for both CAM and RRTMGP (top to bottom)
266+
! Note in Case 2, tops of {t,pint,pmid}_rad start at a 'valid' level,
267+
! i.e. pref > p_top_for_rrtmgp
268+
!-------------------------------------------------------
258269
t_rad(:,ktoprad:) = t(:,ktopcam:)
259270
pmid_rad(:,ktoprad:) = pmid(:,ktopcam:)
260271
pint_rad(:,ktoprad:) = pint(:,ktopcam:)
261272

262-
! Add extra layer values if needed.
273+
! Deal with vertical grid for RRTMGP
263274
if (nlay == pverp) then
264-
t_rad(:,1) = t(:,1)
275+
! This case is the CAM7 LT situation, i.e., all model layers are
276+
! within RRTMGP's range of valid pressures - (Case 1 above)
277+
t_rad(:,1) = t(:,1)
265278
! The top reference pressure from the RRTMGP coefficients datasets is 1.005183574463 Pa
266279
! Set the top of the extra layer just below that.
267280
pint_rad(:,1) = 1.01_kind_phys
268-
269-
! next interface down in LT will always be > 1Pa
270-
! but in MT we apply adjustment to have it be 1.02 Pa if it was too high
271-
where (pint_rad(:,2) <= pint_rad(:,1)) pint_rad(:,2) = pint_rad(:,1)+0.01_kind_phys
272-
273-
! set the highest pmid (in the "extra layer") to the midpoint (guarantees > 1Pa)
281+
! set the highest pmid (in the "extra layer") to the midpoint (guarantees > 1Pa)
274282
pmid_rad(:,1) = pint_rad(:,1) + 0.5_kind_phys * (pint_rad(:,2) - pint_rad(:,1))
275-
276-
! For case of CAM MT, also ensure pint_rad(:,2) > pint_rad(:,1) & pmid_rad(:,2) > max(pmid_rad(:,1), min_pressure)
277-
where (pmid_rad(:,2) <= kdist_sw%gas_props%get_press_min()) pmid_rad(:,2) = pint_rad(:,2) + 0.01_kind_phys
278283
else
279-
! nlay < pverp, thus the 1 Pa level is within a CAM layer. Assuming the top interface of
280-
! this layer is at a pressure < 1 Pa, we need to adjust the top of this layer so that it
281-
! is within the valid pressure range of RRTMGP (otherwise RRTMGP issues an error). Then
282-
! set the midpoint pressure halfway between the interfaces.
284+
! nlay < pverp : model min(pref) < p_top_for_rrtmgp (Case 2 above)
285+
! min(pref) could be 9.999 or 0.0999
286+
! Assuming the top interface of this layer is at a pressure < 1 Pa, we need to adjust
287+
! so that it is within the valid pressure range of RRTMGP (otherwise RRTMGP issues
288+
! an error). Then we set the midpoint pressure halfway between the interfaces.
283289
pint_rad(:,1) = 1.01_kind_phys
290+
! The following *should* work since pint_rad is all in valid range.
291+
! Need to think about possible edge cases ... (jtb 07/31/25)
284292
pmid_rad(:,1) = 0.5_kind_phys * (pint_rad(:,1) + pint_rad(:,2))
285293
end if
286294

schemes/rrtmgp/utils/calculate_net_heating.F90

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ module calculate_net_heating
2323
!> \section arg_table_calculate_net_heating_run Argument Table
2424
!! \htmlinclude calculate_net_heating_run.html
2525
!!
26-
subroutine calculate_net_heating_run(ncol, rad_heat, qrl_prime, qrs_prime, fsns, fsnt, &
27-
flns, flnt, is_offline_dyn, net_flx, errmsg, errflg)
26+
subroutine calculate_net_heating_run(ncol, rad_heat, qrl_prime, qrs_prime, &
27+
is_offline_dyn, fsns, fsnt, flns, flnt, net_flx, &
28+
errmsg, errflg)
2829
!-----------------------------------------------------------------------
2930
! Compute net radiative heating from qrs and qrl, and the associated net
3031
! boundary flux.
@@ -52,6 +53,7 @@ subroutine calculate_net_heating_run(ncol, rad_heat, qrl_prime, qrs_prime, fsns,
5253
! Set error variables
5354
errmsg = ''
5455
errflg = 0
56+
5557
if (.not. is_offline_dyn) then
5658
rad_heat(:,:) = (qrs_prime(:,:) + qrl_prime(:,:))
5759
end if
@@ -62,5 +64,4 @@ subroutine calculate_net_heating_run(ncol, rad_heat, qrl_prime, qrs_prime, fsns,
6264

6365
end subroutine calculate_net_heating_run
6466

65-
!================================================================================================
6667
end module calculate_net_heating

0 commit comments

Comments
 (0)