diff --git a/ccpp/config/ccpp_prebuild_config.py b/ccpp/config/ccpp_prebuild_config.py
index af133339d..3f693f8ff 100755
--- a/ccpp/config/ccpp_prebuild_config.py
+++ b/ccpp/config/ccpp_prebuild_config.py
@@ -203,6 +203,7 @@
'ccpp/physics/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90',
'ccpp/physics/physics/PBL/SATMEDMF/satmedmfvdif.F',
'ccpp/physics/physics/PBL/SATMEDMF/satmedmfvdifq.F',
+ 'ccpp/physics/physics/PBL/SATMEDMF/canopy_driver.F',
'ccpp/physics/physics/PBL/YSU/ysuvdif.F90',
'ccpp/physics/physics/PBL/saYSU/shinhongvdif.F90',
'ccpp/physics/physics/Radiation/RRTMG/radsw_main.F90',
diff --git a/ccpp/physics b/ccpp/physics
index bdccfdd9c..135a5dda8 160000
--- a/ccpp/physics
+++ b/ccpp/physics
@@ -1 +1 @@
-Subproject commit bdccfdd9cd474e440ad668b4732d4daacb85e357
+Subproject commit 135a5dda80f383c29c9a1ac937a392c2e74c5683
diff --git a/ccpp/suites/suite_SCM_GFS_v16.xml b/ccpp/suites/suite_SCM_GFS_v16.xml
index b98d0f8ce..57c5c01fd 100644
--- a/ccpp/suites/suite_SCM_GFS_v16.xml
+++ b/ccpp/suites/suite_SCM_GFS_v16.xml
@@ -51,6 +51,7 @@
GFS_surface_generic_post
GFS_PBL_generic_pre
satmedmfvdifq
+ canopy_driver
GFS_PBL_generic_post
GFS_GWD_generic_pre
cires_ugwp
diff --git a/ccpp/suites/suite_SCM_GFS_v16_ps.xml b/ccpp/suites/suite_SCM_GFS_v16_ps.xml
index 90962bb25..6b1a1582c 100644
--- a/ccpp/suites/suite_SCM_GFS_v16_ps.xml
+++ b/ccpp/suites/suite_SCM_GFS_v16_ps.xml
@@ -32,6 +32,7 @@
GFS_suite_interstitial_2
GFS_PBL_generic_pre
satmedmfvdifq
+ canopy_driver
GFS_PBL_generic_post
GFS_GWD_generic_pre
cires_ugwp
diff --git a/ccpp/suites/suite_SCM_GFS_v17_p8.xml b/ccpp/suites/suite_SCM_GFS_v17_p8.xml
index 4501026c8..8faddb85b 100644
--- a/ccpp/suites/suite_SCM_GFS_v17_p8.xml
+++ b/ccpp/suites/suite_SCM_GFS_v17_p8.xml
@@ -52,6 +52,7 @@
GFS_surface_generic_post
GFS_PBL_generic_pre
satmedmfvdifq
+ canopy_driver
GFS_PBL_generic_post
GFS_GWD_generic_pre
unified_ugwp
diff --git a/ccpp/suites/suite_SCM_GFS_v17_p8_ps.xml b/ccpp/suites/suite_SCM_GFS_v17_p8_ps.xml
index 0f214aff6..a789c414b 100644
--- a/ccpp/suites/suite_SCM_GFS_v17_p8_ps.xml
+++ b/ccpp/suites/suite_SCM_GFS_v17_p8_ps.xml
@@ -33,6 +33,7 @@
GFS_suite_interstitial_2
GFS_PBL_generic_pre
satmedmfvdifq
+ canopy_driver
GFS_PBL_generic_post
GFS_GWD_generic_pre
unified_ugwp
diff --git a/scm/src/GFS_typedefs.F90 b/scm/src/GFS_typedefs.F90
index 2dbfe62f2..f00671fdf 100644
--- a/scm/src/GFS_typedefs.F90
+++ b/scm/src/GFS_typedefs.F90
@@ -1567,6 +1567,11 @@ module GFS_typedefs
integer :: nchem !< number of prognostic chemical species (vertically mixied)
integer :: ndvel !< number of prognostic chemical species (which are deposited, usually =nchem)
integer :: ntchm !< number of prognostic chemical tracers (advected)
+! "cplaqm" tracers
+ integer :: nto3 !< tracer index for Ozone chemical species CMAQ
+ integer :: ntno !< tracer index for NO chemical species CMAQ
+ integer :: ntno2 !< tracer index for NO2 chemical species CMAQ
+
integer :: ntchs !< tracer index for first prognostic chemical tracer
integer :: ntche !< tracer index for last prognostic chemical tracer
integer :: ntdu1 !< tracer index for dust bin1
@@ -2162,6 +2167,11 @@ module GFS_typedefs
real (kind=kind_phys), pointer :: dkt(:,:) => null() !< Eddy diffusitivity for heat
real (kind=kind_phys), pointer :: dku(:,:) => null() !< Eddy diffusitivity for momentum
+!3-LAYER CANOPY
+ !--- Extra PBL diagnostics in canopy
+ real (kind=kind_phys), pointer :: dkt_can(:,:) => null() !< Eddy diffusitivity for heat
+ real (kind=kind_phys), pointer :: dku_can(:,:) => null() !< Eddy diffusitivity for momentum
+
!
!---vay-2018 UGWP-diagnostics instantaneous
!
@@ -2266,7 +2276,6 @@ module GFS_typedefs
! Diagnostics for coupled air quality model
real (kind=kind_phys), pointer :: aod (:) => null() !< instantaneous aerosol optical depth ( n/a )
-!IVAI
! Diagnostics for coupled air quality model
real (kind=kind_phys), pointer :: coszens(:) => null() ! Cosine SZA for photolysis
real (kind=kind_phys), pointer :: jo3o1d(:) => null() ! instantaneous O3O1D photolysis rate
@@ -2276,7 +2285,6 @@ module GFS_typedefs
real (kind=kind_phys), pointer :: cfrt (:) => null() ! Forest Fraction
real (kind=kind_phys), pointer :: cclu (:) => null() ! Clumping Index
real (kind=kind_phys), pointer :: cpopu(:) => null() ! Population density
-!IVAI
! Auxiliary output arrays for debugging
real (kind=kind_phys), pointer :: aux2d(:,:) => null() !< auxiliary 2d arrays in output (for debugging)
@@ -5649,6 +5657,10 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, &
Model%dtidx = no_tracer
if(Model%ntchm>0) then
+! GFS_v16 n=9 "no2" n=10 "no" n=11 "o3" (n=8,9, 10 in PBL resp.)
+ Model%ntno2 = get_tracer_index(Model%tracer_names, 'no2') ! n=11 (index 10 "no2" in PBL scheme) GFS_v17_p8
+ Model%ntno = get_tracer_index(Model%tracer_names, 'no') ! n=12 (index 11 "no" in PBL scheme) GFS_v17_p8
+ Model%nto3 = get_tracer_index(Model%tracer_names, 'o3') ! n=13 (index 12 "o3" in PBL scheme) GFS_v17_p8
Model%ntdu1 = get_tracer_index(Model%tracer_names, 'dust1')
Model%ntdu2 = get_tracer_index(Model%tracer_names, 'dust2')
Model%ntdu3 = get_tracer_index(Model%tracer_names, 'dust3')
@@ -5723,6 +5735,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, &
endif
! More specific chemical tracer names:
+! NB. ntchs is 1st chemical tracer (not so2 tracer)
call label_dtend_tracer(Model,100+Model%ntchs,'so2','sulfur dioxide concentration','kg kg-1 s-1')
if(Model%ntchm>0) then
! Need better descriptions of these.
@@ -5772,6 +5785,11 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, &
call label_dtend_tracer(Model,100+Model%ntia,'ice_aero','number concentration of ice-friendly aerosols','kg-1 s-1')
call label_dtend_tracer(Model,100+Model%nto,'o_ion','oxygen ion concentration','kg kg-1 s-1')
call label_dtend_tracer(Model,100+Model%nto2,'o2','oxygen concentration','kg kg-1 s-1')
+! cplaqm tracers CMAQ
+ call label_dtend_tracer(Model,100+Model%ntno2,'no2_cpl','cplaqm NO2 concentration','kg kg-1 s-1')
+ call label_dtend_tracer(Model,100+Model%ntno, 'no_cpl', 'cplaqm NO concentration','kg kg-1 s-1')
+ call label_dtend_tracer(Model,100+Model%nto3, 'o3_cpl', 'cplaqm ozone concentration','kg kg-1 s-1')
+
call label_dtend_cause(Model,Model%index_of_process_pbl,'pbl','tendency due to PBL')
call label_dtend_cause(Model,Model%index_of_process_dcnv,'deepcnv','tendency due to deep convection')
call label_dtend_cause(Model,Model%index_of_process_scnv,'shalcnv','tendency due to shallow convection')
@@ -5854,6 +5872,12 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, &
enddo
endif
+! NB. In PBL scheme chemical tracers indexes are offset by 1
+! (qdiag3d) cplaqm tracers "no2", "no", "o3"
+ call fill_dtidx(Model,dtend_select,100+Model%ntno2,Model%index_of_process_pbl,have_pbl) ! ntno2= 11 (index 10 is "no2" in PBL scheme) GFS_v17_p8
+ call fill_dtidx(Model,dtend_select,100+Model%ntno ,Model%index_of_process_pbl,have_pbl) ! ntno = 12 (index 11 is "no" in PBL scheme) GFS_v17_p8
+ call fill_dtidx(Model,dtend_select,100+Model%nto3 ,Model%index_of_process_pbl,have_pbl) ! nto3 = 13 (index 12 is "o3" in PBL scheme) GFS_v17_p8
+
call fill_dtidx(Model,dtend_select,100+Model%ntoz,Model%index_of_process_pbl,have_pbl)
call fill_dtidx(Model,dtend_select,100+Model%ntoz,Model%index_of_process_prod_loss,have_oz_phys)
call fill_dtidx(Model,dtend_select,100+Model%ntoz,Model%index_of_process_ozmix,have_oz_phys)
@@ -7437,6 +7461,9 @@ subroutine control_print(Model)
print *, ' nqrimef : ', Model%nqrimef
print *, ' ntqv : ', Model%ntqv
print *, ' ntoz : ', Model%ntoz
+ print *, ' ntno2 : ', Model%ntno2 ! "no2" tracer cplaqm/CMAQ
+ print *, ' ntno : ', Model%ntno ! "no" tracer cplaqm/CMAQ
+ print *, ' nto3 : ', Model%nto3 ! "o3" tracer cplaqm/CMAQ
print *, ' ntcw : ', Model%ntcw
print *, ' ntiw : ', Model%ntiw
print *, ' ntrw : ', Model%ntrw
@@ -8373,6 +8400,12 @@ subroutine diag_create (Diag, Model)
allocate (Diag%dkt(IM,Model%levs))
allocate (Diag%dku(IM,Model%levs))
+ !--- New PBL Diagnostics in 3-layer canopy
+ if (Model%do_canopy .and. Model%cplaqm) then
+ allocate (Diag%dkt_can(IM,Model%levs))
+ allocate (Diag%dku_can(IM,Model%levs))
+ endif
+
!-- New max hourly diag.
allocate (Diag%refdmax(IM))
allocate (Diag%refdmax263k(IM))
@@ -8449,12 +8482,11 @@ subroutine diag_create (Diag, Model)
Diag%aod = zero
end if
-!IVAI:
! Air quality diagnostics
! -- initialize diagnostic variables
if (Model%cplaqm) then
-!IVAI: photdiag arrays
+! photdiag arrays
allocate (Diag%coszens(IM))
Diag%coszens= zero
@@ -8464,7 +8496,7 @@ subroutine diag_create (Diag, Model)
allocate (Diag%jno2(IM))
Diag%jno2 = zero
-!IVAI: canopy arrays read via aqm_emis_read
+! Canopy arrays read via aqm_emis_read
if (Model%do_canopy) then
allocate (Diag%claie(IM))
Diag%claie = zero
@@ -8483,7 +8515,6 @@ subroutine diag_create (Diag, Model)
end if! (Model%do_canopy)
end if ! (Model%cplaqm)
-!IVAI
! Auxiliary arrays in output for debugging
if (Model%naux2d>0) then
@@ -8751,6 +8782,12 @@ subroutine diag_phys_zero (Diag, Model, linit, iauwindow_center)
Diag%dkt = zero
Diag%dku = zero
+! Extra PBL diagnostics in 3-layer canopy
+ if (Model%do_canopy .and. Model%cplaqm ) then
+ Diag%dkt_can = zero
+ Diag%dku_can = zero
+ endif
+
! max hourly diagnostics
Diag%refl_10cm = -35.
Diag%max_hail_diam_sfc = -999.
diff --git a/scm/src/GFS_typedefs.meta b/scm/src/GFS_typedefs.meta
index b057faa1c..cf7988ed6 100644
--- a/scm/src/GFS_typedefs.meta
+++ b/scm/src/GFS_typedefs.meta
@@ -6844,6 +6844,29 @@
units = index
dimensions = ()
type = integer
+### IVAI
+[ntno2]
+ standard_name = index_for_no2_chemical_tracer_in_tracer_concentration_array
+ long_name = tracer index for coupled AQM/CMAQ NO2 chemical tracer
+ units = index
+ dimensions = ()
+ type = integer
+## active = (flag_for_air_quality_coupling .and. flag_for_canopy_option)
+[ntno]
+ standard_name = index_for_no_chemical_tracer_in_tracer_concentration_array
+ long_name = tracer index for coupled AQM/CMAQ NO chemical tracer
+ units = index
+ dimensions = ()
+ type = integer
+## active = (flag_for_air_quality_coupling .and. flag_for_canopy_option)
+[nto3]
+ standard_name = index_for_ozone_chemical_tracer_in_tracer_concentration_array
+ long_name = tracer index for coupled AQM/CMAQ ozone chemical tracer
+ units = index
+ dimensions = ()
+ type = integer
+## active = (flag_for_air_quality_coupling .and. flag_for_canopy_option)
+### IVAI
[ntcw]
standard_name = index_of_cloud_liquid_water_mixing_ratio_in_tracer_concentration_array
long_name = tracer index for cloud condensate (or liquid water)
@@ -10016,6 +10039,22 @@
dimensions = (horizontal_dimension,vertical_layer_dimension)
type = real
kind = kind_phys
+[dkt_can]
+ standard_name = atmosphere_heat_diffusivity_in_canopy
+ long_name = atmospheric heat diffusivity in canopy
+ units = m2 s-1
+ dimensions = (horizontal_dimension,vertical_layer_dimension)
+ type = real
+ kind = kind_phys
+ active = (flag_for_air_quality_coupling .and. flag_for_canopy_option)
+[dku_can]
+ standard_name = atmosphere_momentum_diffusivity_in_canopy
+ long_name = atmospheric momentum diffusivity in canopy
+ units = m2 s-1
+ dimensions = (horizontal_dimension,vertical_layer_dimension)
+ type = real
+ kind = kind_phys
+ active = (flag_for_air_quality_coupling .and. flag_for_canopy_option)
[cldfra]
standard_name = instantaneous_3d_cloud_fraction
long_name = instantaneous 3D cloud fraction for all MPs