@@ -11,9 +11,9 @@ module rrtmgp_inputs
1111! ! \htmlinclude rrtmgp_inputs_run.html
1212! !
1313 subroutine rrtmgp_inputs_run (dosw , dolw , snow_associated , graupel_associated , &
14- pmid , pint , t , nday , idxday , cldfprime , &
15- coszrs , kdist_sw , t_sfc , emis_sfc , t_rad , pmid_rad , &
16- pint_rad , t_day , pmid_day , pint_day , coszrs_day , &
14+ is_root , iulog , is_mpas , pmid , pint , t , nday , idxday , &
15+ cldfprime , coszrs , kdist_sw , t_sfc , emis_sfc , t_rad , &
16+ pmid_rad , pint_rad , t_day , pmid_day , pint_day , coszrs_day , &
1717 alb_dir , alb_dif , lwup , stebol , ncol , ktopcam , ktoprad , &
1818 nswbands , asdir , asdif , sw_low_bounds , sw_high_bounds , &
1919 aldir , aldif , nlay , pverp , pver , cld , cldfsnow , &
@@ -27,6 +27,7 @@ subroutine rrtmgp_inputs_run(dosw, dolw, snow_associated, graupel_associated, &
2727 use ccpp_gas_concentrations, only: ty_gas_concs_ccpp
2828 use ccpp_source_functions, only: ty_source_func_lw_ccpp
2929 use atmos_phys_rad_utils, only: is_visible
30+
3031 ! Inputs
3132 logical , intent (in ) :: graupel_in_rad ! Flag to include graupel in radiation calculation
3233 integer , intent (in ) :: ncol ! Number of columns
@@ -42,6 +43,9 @@ subroutine rrtmgp_inputs_run(dosw, dolw, snow_associated, graupel_associated, &
4243 logical , intent (in ) :: dolw ! Flag for performing the longwave calculation
4344 logical , intent (in ) :: snow_associated ! Flag for whether the cloud snow fraction argument should be used
4445 logical , intent (in ) :: graupel_associated ! Flag for whether the cloud graupel fraction argument should be used
46+ logical , intent (in ) :: is_root
47+ logical , intent (in ) :: is_mpas
48+ integer , intent (in ) :: iulog
4549 integer , dimension (:), intent (in ) :: idxday ! Indices of daylight columns
4650 real (kind_phys), dimension (:,:), intent (in ) :: pmid ! Air pressure at midpoint (Pa)
4751 real (kind_phys), dimension (:,:), intent (in ) :: pint ! Air pressure at interface (Pa)
@@ -89,6 +93,7 @@ subroutine rrtmgp_inputs_run(dosw, dolw, snow_associated, graupel_associated, &
8993 real (kind_phys) :: tref_min
9094 real (kind_phys) :: tref_max
9195 integer :: idx, kdx, iband
96+ logical :: ltrick_rrtmgp
9297
9398 ! Set error variables
9499 errmsg = ' '
@@ -98,6 +103,37 @@ subroutine rrtmgp_inputs_run(dosw, dolw, snow_associated, graupel_associated, &
98103 return
99104 end if
100105
106+ !- -----------------------------------------------------------------------------
107+ ! Compile logic to determine whether it is necessary AND possible to 'trick'
108+ ! rrtmgp to violate its own validity limits by hacking its vertical grid.
109+ ! Conditions:
110+ ! 1) top CAM interface (k=1) is above 1 Pa
111+ ! 2) next interface (k=2) is below 1 Pa
112+ ! 3) RRTMGP is asked to active over ALL CAM layers
113+ ! (nlay=pverp, e.g., set by spec p_top_for_equil_rad=0.)
114+ ! 4) dycore is NOT MPAS
115+ !
116+ ! These conditions are generally only satisfied in a non-MPAS MT configuration
117+ !- -----------------------------------------------------------------------------
118+ if (( .not. is_mpas ) .and. &
119+ (nlay== pverp) .and. &
120+ (minval (pint(:,1 )) < 1._kind_phys ) .and. &
121+ (minval (pint(:,2 )) > 1._kind_phys ) ) then
122+ ! we can and need to trick rrtmgp
123+ ltrick_rrtmgp = .true.
124+ else
125+ ! we cannot or don't need to trick rrtmgp
126+ ltrick_rrtmgp = .false.
127+ end if
128+
129+ if (is_root) then
130+ if (ltrick_rrtmgp) then
131+ write (iulog,* ) ' *** TRICKING RRTMGP INTO GOING AN EXTRA LEVEL ' ,nlay,pverp
132+ else
133+ write (iulog,* ) ' *** CANT or WONT trick RRTMGP ' ,nlay,pverp
134+ end if
135+ end if
136+
101137 ! RRTMGP set state
102138 t_sfc = sqrt (sqrt (lwup(:)/ stebol)) ! Surface temp set based on longwave up flux.
103139
@@ -110,16 +146,16 @@ subroutine rrtmgp_inputs_run(dosw, dolw, snow_associated, graupel_associated, &
110146
111147 !- ------------------------------------------------------------------------
112148 ! RRTMGP enforces P > 1 Pa for validity.
113- ! In radiation.F90 we count layers based on P_ref > 10 Pa to safely account
114- ! for possible situations in MPAS (z-based vert. coordinate) in which
115- ! full 3D pressure could be significanlty below min(P_ref) .
149+ ! Actual range of RRTMGP in CAM is set with namelist variable p_top_for_equil_rad.
150+ ! In rrtmg_inputs_setup.F90, active layers for RRTMGP are counted based on
151+ ! the logical P_ref > p_top_for_equil_rad. Returned as nlay .
116152 !
117153 ! If
118- ! 1) entire vertical domain has P_ref> 10Pa (e.g. CAM7 LT) then
154+ ! 1) entire vertical domain has P_ref> p_top_for_equil_rad then
119155 ! nlay = pverp
120156 ! ktoprad = 2
121157 ! ktopcam = 1
122- ! 2) min(P_ref) < 10Pa (e.g. CAM7 MT) then
158+ ! 2) min(P_ref) < p_top_for_equil_rad (e.g. MPAS MT) then
123159 ! nlay < pverp
124160 ! ktoprad = 1
125161 ! ktopcam = pver - nlay + 1
@@ -134,23 +170,31 @@ subroutine rrtmgp_inputs_run(dosw, dolw, snow_associated, graupel_associated, &
134170
135171 ! Deal with vertical grid for RRTMGP
136172 if (nlay == pverp) then
137- ! This case is the CAM7 LT situation, i.e., all model layers are
138- ! within RRTMGP's range of valid pressures - (Case 1 above)
173+ ! All model layers are within RRTMGP's range of valid pressures
174+ ! as specified by p_top_for_equil_rad - (Case 1 above)
139175 t_rad(:,1 ) = t(:,1 )
140- ! The top reference pressure from the RRTMGP coefficients datasets is 1.005183574463 Pa
141- ! Set the top of the extra layer just below that.
142- pint_rad(:,1 ) = 1.01_kind_phys
143- ! set the highest pmid (in the "extra layer") to the midpoint (guarantees > 1Pa)
144- pmid_rad(:,1 ) = pint_rad(:,1 ) + 0.5_kind_phys * (pint_rad(:,2 ) - pint_rad(:,1 ))
176+ if (ltrick_rrtmgp) then
177+ ! The top reference pressure from the RRTMGP coefficients datasets is 1.005183574463 Pa
178+ ! Set the top of the extra layer just below that.
179+ pint_rad(:,1 ) = 1.01_kind_phys
180+ pint_rad(:,2 ) = 1.02_kind_phys
181+ ! set the highest pmid (in the "extra layer") to the midpoint (guarantees > 1Pa)
182+ pmid_rad(:,1 ) = 1.015_kind_phys ! pint_rad(:,1) + 0.5_kind_phys * (pint_rad(:,2) - pint_rad(:,1))
183+ pmid_rad(:,2 ) = 0.5 * (pint_rad(:,2 ) + pint_rad(:,3 ))
184+ else
185+ ! The top reference pressure from the RRTMGP coefficients datasets is 1.005183574463 Pa
186+ ! Set the top of the extra layer just below that.
187+ pint_rad(:,1 ) = 1.01_kind_phys
188+ ! set the highest pmid (in the "extra layer") to the midpoint (guarantees > 1Pa)
189+ pmid_rad(:,1 ) = pint_rad(:,1 ) + 0.5_kind_phys * (pint_rad(:,2 ) - pint_rad(:,1 ))
190+ end if
145191 else
146192 ! nlay < pverp : model min(pref) < p_top_for_rrtmgp (Case 2 above)
147- ! min(pref) could be 9.999 or 0.0999
148- ! Assuming the top interface of this layer is at a pressure < 1 Pa, we need to adjust
149- ! so that it is within the valid pressure range of RRTMGP (otherwise RRTMGP issues
150- ! an error). Then we set the midpoint pressure halfway between the interfaces.
193+ ! Not sure why is this needed since pint_rad should have been specified
194+ ! at RRTMGP valid values above. But this is the way it was done in
195+ ! original RRTMG implementation.
151196 pint_rad(:,1 ) = 1.01_kind_phys
152197 ! The following *should* work since pint_rad is all in valid range.
153- ! Need to think about possible edge cases ... (jtb 07/31/25)
154198 pmid_rad(:,1 ) = 0.5_kind_phys * (pint_rad(:,1 ) + pint_rad(:,2 ))
155199 end if
156200
0 commit comments