Skip to content

Commit 38a5a49

Browse files
Add new Tiedtke convection scheme (ESCOMP#267)
### Originator(s): kuanchihwang ### Descriptions (include the issue title, and the keyword ['closes', 'fixes', 'resolves'] followed by the issue number): This PR adds the new Tiedtke convection scheme to the experimental convection-permitting physics suite. ### List all namelist files that were added or changed: None ### List all files eliminated and why: None ### List all files added and what they do: ``` A schemes/mmm/cu_ntiedtke_compat.F90 A schemes/mmm/cu_ntiedtke_compat.meta * Implement new Tiedtke cumulus scheme ``` ### List all existing files that have been modified, and describe the changes: ``` M schemes/mmm/bl_gwdo_compat.F90 * Factor out computation of characteristic grid length scale M schemes/mmm/bl_gwdo_compat.meta * Fix standard names and attributes * Factor out computation of characteristic grid length scale M schemes/mmm/mmm_physics * Update mmm-physics submodule M schemes/mmm/mmm_physics_compat.F90 * Factor out computation of characteristic grid length scale * Implement conversion between geopotential height at interface wrt surface and mean sea level * Implement interstitial schemes for new Tiedtke cumulus scheme M schemes/mmm/mmm_physics_compat.meta * Fix standard names and attributes * Factor out computation of characteristic grid length scale * Implement conversion between geopotential height at interface wrt surface and mean sea level * Implement interstitial schemes for new Tiedtke cumulus scheme M schemes/utilities/state_converters.F90 * Implement conversion between dry and wet cloud ice mixing ratio M schemes/utilities/state_converters.meta * Implement conversion between dry and wet cloud ice mixing ratio M test/test_suites/suite_convection_permitting.xml * Update suite definition file M test/unit-test/tests/mmm/mmm_physics_compat_tests.pf * Update unit tests ``` ### List all automated tests that failed, as well as an explanation for why they were not fixed: None ### Is this an answer-changing PR? If so, is it a new physics package, algorithm change, tuning change, etc? Answer-changing for the convection-permitting physics suite due to a newly added physics scheme. Nothing is changed for the rest. ### If yes to the above question, describe how this code was validated with the new/modified features: The convection-permitting physics suite is considered an experimental feature. There is no baseline available to validate against because it has never been implemented in CAM-SIMA as well as CAM before.
1 parent b402de4 commit 38a5a49

11 files changed

Lines changed: 1893 additions & 70 deletions

schemes/mmm/bl_gwdo_compat.F90

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@ module bl_gwdo_compat
1313
!> \section arg_table_bl_gwdo_compat_pre_init Argument Table
1414
!! \htmlinclude bl_gwdo_compat_pre_init.html
1515
pure subroutine bl_gwdo_compat_pre_init( &
16-
omega, rearth, &
17-
dxmeter, sina, cosa, &
16+
sina, cosa, &
1817
errmsg, errflg)
1918
use ccpp_kinds, only: kind_phys
2019

21-
real(kind_phys), intent(in) :: omega(:), rearth
22-
real(kind_phys), intent(out) :: dxmeter(:), sina(:), cosa(:)
20+
real(kind_phys), intent(out) :: sina(:), cosa(:)
2321
character(*), intent(out) :: errmsg
2422
integer, intent(out) :: errflg
2523

@@ -28,10 +26,6 @@ pure subroutine bl_gwdo_compat_pre_init( &
2826

2927
! These variables do not change with time. Set them just once at model initialization for better performance.
3028

31-
! The "bl_gwdo" physics scheme needs grid sizes in meters. This is trivial for models with regular grids like WRF,
32-
! but not so straightforward for models with unstructured grids like CAM-SIMA. Here, the square root of cell area is used.
33-
dxmeter(:) = sqrt(omega(:) * (rearth ** 2))
34-
3529
! The "bl_gwdo" physics scheme was originally designed to be used with regional models like WRF, where the positive X and
3630
! Y directions may not always point to the east and north, respectively. This is no longer the case for global models like
3731
! CAM-SIMA.

schemes/mmm/bl_gwdo_compat.meta

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,6 @@
55
[ccpp-arg-table]
66
name = bl_gwdo_compat_pre_init
77
type = scheme
8-
[ omega ]
9-
standard_name = cell_angular_area
10-
units = sr
11-
type = real | kind = kind_phys
12-
dimensions = (horizontal_dimension)
13-
intent = in
14-
[ rearth ]
15-
standard_name = radius_of_earth
16-
units = m
17-
type = real | kind = kind_phys
18-
dimensions = ()
19-
intent = in
20-
[ dxmeter ]
21-
standard_name = characteristic_grid_lengthscale
22-
units = m
23-
type = real | kind = kind_phys
24-
dimensions = (horizontal_dimension)
25-
intent = out
268
[ sina ]
279
standard_name = sine_of_angle_of_rotation_from_east_to_x
2810
units = 1
@@ -115,13 +97,13 @@
11597
dimensions = (horizontal_loop_extent)
11698
intent = in
11799
[ rublten ]
118-
standard_name = tendency_of_x_wind_due_to_pbl_processes
100+
standard_name = tendency_of_eastward_wind_due_to_pbl_processes
119101
units = m s-2
120102
type = real | kind = kind_phys
121103
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
122104
intent = inout
123105
[ rvblten ]
124-
standard_name = tendency_of_y_wind_due_to_pbl_processes
106+
standard_name = tendency_of_northward_wind_due_to_pbl_processes
125107
units = m s-2
126108
type = real | kind = kind_phys
127109
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
@@ -169,12 +151,11 @@
169151
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
170152
intent = in
171153
[ q1 ]
172-
standard_name = water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water
154+
standard_name = water_vapor_mixing_ratio_wrt_dry_air
173155
units = kg kg-1
174156
type = real | kind = kind_phys
175157
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
176158
intent = in
177-
advected = true
178159
[ prsi ]
179160
standard_name = air_pressure_at_interface
180161
units = Pa

schemes/mmm/cu_ntiedtke_compat.F90

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
!> This module contains interstitial schemes that are specific to new Tiedtke cumulus scheme,
2+
!> which is part of MMM physics.
3+
module cu_ntiedtke_compat
4+
implicit none
5+
6+
private
7+
public :: cu_ntiedtke_compat_pre_run
8+
public :: cu_ntiedtke_compat_init
9+
public :: cu_ntiedtke_compat_run
10+
public :: cu_ntiedtke_diagnostics_init
11+
public :: cu_ntiedtke_diagnostics_run
12+
contains
13+
!> \section arg_table_cu_ntiedtke_compat_pre_run Argument Table
14+
!! \htmlinclude cu_ntiedtke_compat_pre_run.html
15+
subroutine cu_ntiedtke_compat_pre_run( &
16+
cflx, exner, landfrac, &
17+
lhf, shf, &
18+
rthdynten, rthblten, rthratenlw, rthratensw, &
19+
rqvdynten, rqvblten, &
20+
lndj, &
21+
ptf, pqvf, hfx, evap, &
22+
errmsg, errflg)
23+
use ccpp_kinds, only: kind_phys
24+
use ccpp_scheme_utils, only: ccpp_constituent_index
25+
26+
real(kind_phys), intent(in) :: cflx(:, :), exner(:, :), landfrac(:), &
27+
lhf(:), shf(:), &
28+
rthdynten(:, :), rthblten(:, :), rthratenlw(:, :), rthratensw(:, :), &
29+
rqvdynten(:, :), rqvblten(:, :)
30+
integer, intent(out) :: lndj(:)
31+
real(kind_phys), intent(out) :: ptf(:, :), pqvf(:, :), hfx(:), evap(:)
32+
character(*), intent(out) :: errmsg
33+
integer, intent(out) :: errflg
34+
35+
integer :: water_vapor_mixing_ratio_index
36+
37+
where (landfrac >= 0.5_kind_phys)
38+
lndj = 1
39+
elsewhere
40+
lndj = 0
41+
end where
42+
43+
ptf(:, :) = (rthdynten(:, :) + rthblten(:, :) + rthratenlw(:, :) + rthratensw(:, :)) * exner(:, :)
44+
pqvf(:, :) = rqvdynten(:, :) + rqvblten(:, :)
45+
hfx(:) = lhf(:) + shf(:)
46+
evap(:) = 0.0_kind_phys
47+
48+
call ccpp_constituent_index( &
49+
'water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water', water_vapor_mixing_ratio_index, errflg, errmsg)
50+
51+
if (errflg /= 0 .or. &
52+
water_vapor_mixing_ratio_index < lbound(cflx, 2) .or. water_vapor_mixing_ratio_index > ubound(cflx, 2)) then
53+
errmsg = 'Failed to find desired constituent flux from cflx'
54+
errflg = 1
55+
56+
return
57+
end if
58+
59+
evap(:) = cflx(:, water_vapor_mixing_ratio_index)
60+
61+
errmsg = ''
62+
errflg = 0
63+
end subroutine cu_ntiedtke_compat_pre_run
64+
65+
!> \section arg_table_cu_ntiedtke_compat_init Argument Table
66+
!! \htmlinclude cu_ntiedtke_compat_init.html
67+
subroutine cu_ntiedtke_compat_init( &
68+
con_cp, con_rd, con_rv, con_xlv, con_xls, con_xlf, con_grav, &
69+
errmsg, errflg)
70+
use ccpp_kinds, only: kind_phys
71+
use cu_ntiedtke, only: cu_ntiedtke_init
72+
73+
real(kind_phys), intent(in) :: con_cp, con_rd, con_rv, con_xlv, con_xls, con_xlf, con_grav
74+
character(*), intent(out) :: errmsg
75+
integer, intent(out) :: errflg
76+
77+
call cu_ntiedtke_init( &
78+
con_cp, con_rd, con_rv, con_xlv, con_xls, con_xlf, con_grav, &
79+
errmsg, errflg)
80+
81+
errmsg = ''
82+
errflg = 0
83+
end subroutine cu_ntiedtke_compat_init
84+
85+
!> \section arg_table_cu_ntiedtke_compat_run Argument Table
86+
!! \htmlinclude cu_ntiedtke_compat_run.html
87+
subroutine cu_ntiedtke_compat_run( &
88+
pu, pv, pt, pqv, pqc, pqi, &
89+
pqvf, ptf, poz, pzz, pomg, &
90+
pap, paph, evap, hfx, zprecc, lndj, lq, km, km1, dt, dx, &
91+
exner, &
92+
rucuten, rvcuten, rthcuten, rqvcuten, rqccuten, rqicuten, &
93+
errmsg, errflg)
94+
use ccpp_kinds, only: kind_phys
95+
use cu_ntiedtke, only: cu_ntiedtke_run
96+
97+
integer, intent(in) :: lndj(:), lq, km, km1
98+
real(kind_phys), intent(in) :: pu(:, :), pv(:, :), pt(:, :), pqv(:, :), pqc(:, :), pqi(:, :), &
99+
pqvf(:, :), ptf(:, :), poz(:, :), pzz(:, :), pomg(:, :), &
100+
pap(:, :), paph(:, :), evap(:), hfx(:), &
101+
dt, dx(:), &
102+
exner(:, :)
103+
real(kind_phys), intent(out) :: zprecc(:), &
104+
rucuten(:, :), rvcuten(:, :), &
105+
rthcuten(:, :), &
106+
rqvcuten(:, :), rqccuten(:, :), rqicuten(:, :)
107+
character(*), intent(out) :: errmsg
108+
integer, intent(out) :: errflg
109+
110+
real(kind_phys), allocatable :: pu_local(:, :), pv_local(:, :), &
111+
pt_local(:, :), &
112+
pqv_local(:, :), pqc_local(:, :), pqi_local(:, :)
113+
114+
zprecc(:) = 0.0_kind_phys
115+
116+
rucuten(:, :) = 0.0_kind_phys
117+
rvcuten(:, :) = 0.0_kind_phys
118+
rthcuten(:, :) = 0.0_kind_phys
119+
rqvcuten(:, :) = 0.0_kind_phys
120+
rqccuten(:, :) = 0.0_kind_phys
121+
rqicuten(:, :) = 0.0_kind_phys
122+
123+
! The "cu_ntiedtke" physics scheme modifies model states directly, which is not ideal.
124+
! Make local copies of the model states, pass them to the physics scheme, and compute the tendencies instead.
125+
126+
allocate(pu_local, source=pu, errmsg=errmsg, stat=errflg)
127+
128+
if (errflg /= 0) then
129+
return
130+
end if
131+
132+
allocate(pv_local, source=pv, errmsg=errmsg, stat=errflg)
133+
134+
if (errflg /= 0) then
135+
return
136+
end if
137+
138+
allocate(pt_local, source=pt, errmsg=errmsg, stat=errflg)
139+
140+
if (errflg /= 0) then
141+
return
142+
end if
143+
144+
allocate(pqv_local, source=pqv, errmsg=errmsg, stat=errflg)
145+
146+
if (errflg /= 0) then
147+
return
148+
end if
149+
150+
allocate(pqc_local, source=pqc, errmsg=errmsg, stat=errflg)
151+
152+
if (errflg /= 0) then
153+
return
154+
end if
155+
156+
allocate(pqi_local, source=pqi, errmsg=errmsg, stat=errflg)
157+
158+
if (errflg /= 0) then
159+
return
160+
end if
161+
162+
call cu_ntiedtke_run( &
163+
pu_local, pv_local, pt_local, pqv_local, pqc_local, pqi_local, &
164+
pqvf, ptf, poz, pzz, pomg, &
165+
pap, paph, evap, hfx, zprecc, lndj, lq, km, km1, dt, dx, &
166+
errmsg, errflg)
167+
168+
zprecc(:) = zprecc(:) * 0.001_kind_phys ! Convert from mm to m.
169+
170+
rucuten(:, :) = (pu_local(:, :) - pu(:, :)) / dt
171+
rvcuten(:, :) = (pv_local(:, :) - pv(:, :)) / dt
172+
rthcuten(:, :) = (pt_local(:, :) - pt(:, :)) / exner(:, :) / dt
173+
rqvcuten(:, :) = (pqv_local(:, :) - pqv(:, :)) / dt
174+
rqccuten(:, :) = (pqc_local(:, :) - pqc(:, :)) / dt
175+
rqicuten(:, :) = (pqi_local(:, :) - pqi(:, :)) / dt
176+
177+
errmsg = ''
178+
errflg = 0
179+
end subroutine cu_ntiedtke_compat_run
180+
181+
!> \section arg_table_cu_ntiedtke_diagnostics_init Argument Table
182+
!! \htmlinclude cu_ntiedtke_diagnostics_init.html
183+
subroutine cu_ntiedtke_diagnostics_init( &
184+
errmsg, errflg)
185+
use cam_history, only: history_add_field
186+
use cam_history_support, only: horiz_only
187+
188+
character(*), intent(out) :: errmsg
189+
integer, intent(out) :: errflg
190+
191+
call history_add_field('cu_ntiedtke_zprecc', &
192+
'lwe_thickness_of_convective_precipitation_amount', horiz_only, 'avg', 'm')
193+
call history_add_field('cu_ntiedtke_rucuten', &
194+
'tendency_of_eastward_wind_due_to_convection', 'lev', 'avg', 'm s-2')
195+
call history_add_field('cu_ntiedtke_rvcuten', &
196+
'tendency_of_northward_wind_due_to_convection', 'lev', 'avg', 'm s-2')
197+
call history_add_field('cu_ntiedtke_rthcuten', &
198+
'tendency_of_air_potential_temperature_due_to_convection', 'lev', 'avg', 'K s-1')
199+
call history_add_field('cu_ntiedtke_rqvcuten', &
200+
'tendency_of_water_vapor_mixing_ratio_wrt_dry_air_due_to_convection', 'lev', 'avg', 'kg kg-1 s-1')
201+
call history_add_field('cu_ntiedtke_rqccuten', &
202+
'tendency_of_cloud_liquid_water_mixing_ratio_wrt_dry_air_due_to_convection', 'lev', 'avg', 'kg kg-1 s-1')
203+
call history_add_field('cu_ntiedtke_rqicuten', &
204+
'tendency_of_cloud_ice_mixing_ratio_wrt_dry_air_due_to_convection', 'lev', 'avg', 'kg kg-1 s-1')
205+
206+
errmsg = ''
207+
errflg = 0
208+
end subroutine cu_ntiedtke_diagnostics_init
209+
210+
!> \section arg_table_cu_ntiedtke_diagnostics_run Argument Table
211+
!! \htmlinclude cu_ntiedtke_diagnostics_run.html
212+
subroutine cu_ntiedtke_diagnostics_run( &
213+
zprecc, &
214+
rucuten, rvcuten, rthcuten, rqvcuten, rqccuten, rqicuten, &
215+
errmsg, errflg)
216+
use cam_history, only: history_out_field
217+
use ccpp_kinds, only: kind_phys
218+
219+
real(kind_phys), intent(in) :: zprecc(:), &
220+
rucuten(:, :), rvcuten(:, :), &
221+
rthcuten(:, :), &
222+
rqvcuten(:, :), rqccuten(:, :), rqicuten(:, :)
223+
character(*), intent(out) :: errmsg
224+
integer, intent(out) :: errflg
225+
226+
call history_out_field('cu_ntiedtke_zprecc', zprecc)
227+
call history_out_field('cu_ntiedtke_rucuten', rucuten)
228+
call history_out_field('cu_ntiedtke_rvcuten', rvcuten)
229+
call history_out_field('cu_ntiedtke_rthcuten', rthcuten)
230+
call history_out_field('cu_ntiedtke_rqvcuten', rqvcuten)
231+
call history_out_field('cu_ntiedtke_rqccuten', rqccuten)
232+
call history_out_field('cu_ntiedtke_rqicuten', rqicuten)
233+
234+
errmsg = ''
235+
errflg = 0
236+
end subroutine cu_ntiedtke_diagnostics_run
237+
end module cu_ntiedtke_compat

0 commit comments

Comments
 (0)