diff --git a/ccpp/config/ccpp_prebuild_config.py b/ccpp/config/ccpp_prebuild_config.py
index 52f576eda..2698259f8 100755
--- a/ccpp/config/ccpp_prebuild_config.py
+++ b/ccpp/config/ccpp_prebuild_config.py
@@ -148,9 +148,9 @@
'ccpp/physics/physics/CONV/Chikira_Sugiyama/cs_conv.F90',
'ccpp/physics/physics/CONV/Chikira_Sugiyama/cs_conv_post.F90',
'ccpp/physics/physics/CONV/Chikira_Sugiyama/cs_conv_aw_adj.F90',
- 'ccpp/physics/physics/CONV/nTiedtke/cu_ntiedtke_pre.F90',
- 'ccpp/physics/physics/CONV/nTiedtke/cu_ntiedtke.F90',
- 'ccpp/physics/physics/CONV/nTiedtke/cu_ntiedtke_post.F90',
+ 'ccpp/physics/physics/CONV/nTiedtke/ufs_cu_ntiedtke_pre.F90',
+ 'ccpp/physics/physics/CONV/nTiedtke/ufs_cu_ntiedtke.F90',
+ 'ccpp/physics/physics/CONV/nTiedtke/ufs_cu_ntiedtke_post.F90',
'ccpp/physics/physics/CONV/SAMF/samfdeepcnv.f',
'ccpp/physics/physics/CONV/SAMF/samfshalcnv.f',
'ccpp/physics/physics/CONV/SAS/sascnvn.F',
@@ -229,9 +229,9 @@
'ccpp/physics/physics/tools/get_phi_fv3.F90',
# CNU_NTIEDTKE
- 'ccpp/physics/physics/mmm_physics/mmm_cu_ntiedtke.F90' ,
- 'ccpp/physics/physics/CONV/nTiedtke/mmm_cu_ntiedtke_pre.F90' ,
- 'ccpp/physics/physics/CONV/nTiedtke/mmm_cu_ntiedtke_post.F90' ,
+ 'ccpp/physics/physics/CONV/nTiedtke/gfs_mmm_cu_ntiedtke_pre.F90' ,
+ 'ccpp/physics/physics/mmm_physics/cu_ntiedtke.F90' ,
+ 'ccpp/physics/physics/CONV/nTiedtke/gfs_mmm_cu_ntiedtke_post.F90' ,
# NCAR MMM
# 'ccpp/physics/physics/mmm_physics/sfclayrev_pre.F90' ,
diff --git a/ccpp/physics b/ccpp/physics
index 5e80ddaab..9ea413cd1 160000
--- a/ccpp/physics
+++ b/ccpp/physics
@@ -1 +1 @@
-Subproject commit 5e80ddaabe23d2bf91030d9c4108332afb380d86
+Subproject commit 9ea413cd1c204da26667ed084406c4fe2c3db7d7
diff --git a/ccpp/physics_namelists/input_RAP_ntiedtke.nml b/ccpp/physics_namelists/input_RAP_ntiedtke.nml
index 8559dc662..2b0b09aaa 100644
--- a/ccpp/physics_namelists/input_RAP_ntiedtke.nml
+++ b/ccpp/physics_namelists/input_RAP_ntiedtke.nml
@@ -50,8 +50,8 @@
random_clds = .false.
trans_trac = .true.
cnvcld = .true.
- imfshalcnv = 3
- imfdeepcnv = 3
+ imfshalcnv = 6
+ imfdeepcnv = 6
ras = .false.
cdmbgwd = 0.14,1.8,1.0,1.0
do_mynnsfclay= .true.
diff --git a/ccpp/physics_namelists/input_RAP_ufs_ntiedtke.nml b/ccpp/physics_namelists/input_RAP_ufs_ntiedtke.nml
new file mode 100644
index 000000000..02de606f7
--- /dev/null
+++ b/ccpp/physics_namelists/input_RAP_ufs_ntiedtke.nml
@@ -0,0 +1,132 @@
+&gfs_physics_nml
+ fhzero = 6
+ h2o_phys = .true.
+ ldiag3d = .true.
+ qdiag3d = .true.
+ print_diff_pgr = .false.
+ fhcyc = 24
+ use_ufo = .true.
+ pre_rad = .false.
+ imp_physics = 8
+ ltaerosol = .true.
+ lradar = .true.
+ sedi_semi = .true.
+ decfl = 10
+ nssl_cccn = 0.6e9
+ nssl_alphah = 0.0
+ nssl_alphahl = 1.0
+ nssl_hail_on = .false.
+ nssl_ccn_on = .true.
+ nssl_invertccn = .true.
+ dt_inner = 60
+ ttendlim = -999
+ pdfcld = .false.
+ fhswr = 1200.
+ fhlwr = 1200.
+ ialb = 2
+ iems = 2
+ iaer = 5111
+ icliq_sw = 1
+ iovr = 1
+ icloud = 0
+ ico2 = 2
+ isubc_sw = 2
+ isubc_lw = 2
+ isol = 2
+ lwhtr = .true.
+ swhtr = .true.
+ cnvgwd = .true.
+ do_deep = .true.
+ shal_cnv = .true.
+ cal_pre = .false.
+ redrag = .true.
+ dspheat = .true.
+ hybedmf = .false.
+ satmedmf = .false.
+ isatmedmf = 0
+ do_mynnedmf = .true.
+ lheatstrg = .false.
+ lseaspray = .false.
+ random_clds = .false.
+ trans_trac = .true.
+ cnvcld = .true.
+ imfshalcnv = 4
+ imfdeepcnv = 4
+ ras = .false.
+ cdmbgwd = 0.14,1.8,1.0,1.0
+ do_mynnsfclay= .true.
+ prslrd0 = 0.
+ ivegsrc = 1
+ isot = 1
+ lsm = 3
+ lsoil = 4
+ lsoil_lsm = 9
+ kice = 9
+ iopt_dveg = 4
+ iopt_crs = 2
+ iopt_btr = 1
+ iopt_run = 1
+ iopt_sfc = 3
+ iopt_frz = 1
+ iopt_inf = 1
+ iopt_rad = 3
+ iopt_alb = 1
+ iopt_snf = 4
+ iopt_tbot = 2
+ iopt_stc = 3
+ iopt_trs = 2
+ debug = .false.
+ oz_phys = .false.
+ oz_phys_2015 = .true.
+ nstf_name = 2,0,0,0,0
+ nst_anl = .true.
+ lkm = 0
+ psautco = 0.0008,0.0005
+ prautco = 0.00015,0.00015
+ lgfdlmprad = .true.
+ cplchm = .false.
+ cplwav = .false.
+ cplwav2atm = .false.
+ effr_in = .true.
+ ldiag_ugwp = .false.
+ do_ugwp = .false.
+ do_tofd = .false.
+ gwd_opt = 3
+ ldiag_ugwp = .false.
+ do_ugwp_v0 = .false.
+ do_ugwp_v0_orog_only = .false.
+ do_gsl_drag_ls_bl = .true.
+ do_gsl_drag_ss = .true.
+ do_gsl_drag_tofd = .true.
+ do_ugwp_v1 = .false.
+ do_ugwp_v1_orog_only = .false.
+ do_sppt = .false.
+ do_shum = .false.
+ do_skeb = .false.
+ do_ysu = .true.
+ lndp_type = 0
+ n_var_lndp = 0
+ fscav_aero = "'*:0.0'"
+ icloud_bl = 1
+ bl_mynn_tkeadvect = .true.
+ bl_mynn_edmf = 1
+ bl_mynn_edmf_mom = 1
+ do_RRTMGP = .false.
+ doGP_cldoptics_LUT = .false.
+ doGP_lwscat = .false.
+/
+
+&cires_ugwp_nml
+ knob_ugwp_solver = 2
+ knob_ugwp_source = 1,1,0,0
+ knob_ugwp_wvspec = 1,25,25,25
+ knob_ugwp_azdir = 2,4,4,4
+ knob_ugwp_stoch = 0,0,0,0
+ knob_ugwp_effac = 1,1,1,1
+ knob_ugwp_doaxyz = 1
+ knob_ugwp_doheat = 1
+ knob_ugwp_dokdis = 1
+ knob_ugwp_ndx4lh = 1
+ knob_ugwp_version = 0
+ launch_level = 54
+/
diff --git a/ccpp/suites/suite_SCM_RAP_ntiedtke.xml b/ccpp/suites/suite_SCM_RAP_ntiedtke.xml
index 3a9c464a1..30128a092 100644
--- a/ccpp/suites/suite_SCM_RAP_ntiedtke.xml
+++ b/ccpp/suites/suite_SCM_RAP_ntiedtke.xml
@@ -19,7 +19,6 @@
rad_sw_pre
rrtmg_sw
rrtmg_sw_post
-
rrtmg_lw
sgscloud_radpost
rrtmg_lw_post
@@ -59,29 +58,25 @@
drag_suite
GFS_GWD_generic_post
GFS_suite_stateout_update
-
h2ophys
get_phi_fv3
GFS_suite_interstitial_3
GFS_DCNV_generic_pre
- cu_gf_driver_pre
- cu_gf_driver
+ gfs_mmm_cu_ntiedtke_pre
+ cu_ntiedtke
+ gfs_mmm_cu_ntiedtke_post
GFS_DCNV_generic_post
GFS_SCNV_generic_pre
GFS_SCNV_generic_post
GFS_suite_interstitial_4
cnvc90
GFS_MP_generic_pre
-
-
-
- mmm_cu_ntiedtke_pre
- mmm_cu_ntiedtke
- mmm_cu_ntiedtke_post
+ mp_thompson_pre
+ mp_thompson
+ mp_thompson_post
GFS_MP_generic_post
- cu_gf_driver_post
maximum_hourly_diagnostics
- GFS_physics_post
+ GFS_physics_post
diff --git a/ccpp/suites/suite_SCM_RAP_ufs_ntiedtke.xml b/ccpp/suites/suite_SCM_RAP_ufs_ntiedtke.xml
new file mode 100644
index 000000000..8c0363acf
--- /dev/null
+++ b/ccpp/suites/suite_SCM_RAP_ufs_ntiedtke.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+ GFS_time_vary_pre
+ GFS_rrtmg_setup
+ GFS_rad_time_vary
+ GFS_phys_time_vary
+
+
+
+
+ GFS_suite_interstitial_rad_reset
+ sgscloud_radpre
+ GFS_rrtmg_pre
+ GFS_radiation_surface
+ rad_sw_pre
+ rrtmg_sw
+ rrtmg_sw_post
+ rrtmg_lw
+ sgscloud_radpost
+ rrtmg_lw_post
+ GFS_rrtmg_post
+
+
+
+
+ GFS_suite_interstitial_phys_reset
+ GFS_suite_stateout_reset
+ get_prs_fv3
+ GFS_suite_interstitial_1
+ GFS_surface_generic_pre
+ GFS_surface_composites_pre
+ dcyc2t3
+ GFS_surface_composites_inter
+ GFS_suite_interstitial_2
+
+
+
+ mynnsfc_wrapper
+ GFS_surface_loop_control_part1
+ sfc_nst_pre
+ sfc_nst
+ sfc_nst_post
+ lsm_ruc
+ GFS_surface_loop_control_part2
+
+
+
+ GFS_surface_composites_post
+ sfc_diag
+ sfc_diag_post
+ GFS_surface_generic_post
+ mynnedmf_wrapper
+ GFS_GWD_generic_pre
+ drag_suite
+ GFS_GWD_generic_post
+ GFS_suite_stateout_update
+ h2ophys
+ get_phi_fv3
+ GFS_suite_interstitial_3
+ GFS_DCNV_generic_pre
+ ufs_cu_ntiedtke_pre
+ ufs_cu_ntiedtke
+ ufs_cu_ntiedtke_post
+ GFS_DCNV_generic_post
+ GFS_SCNV_generic_pre
+ GFS_SCNV_generic_post
+ GFS_suite_interstitial_4
+ cnvc90
+ GFS_MP_generic_pre
+ mp_thompson_pre
+ mp_thompson
+ mp_thompson_post
+ GFS_MP_generic_post
+ maximum_hourly_diagnostics
+ GFS_physics_post
+
+
+
+
diff --git a/scm/src/CCPP_typedefs.F90 b/scm/src/CCPP_typedefs.F90
index 437fb37ce..707694327 100644
--- a/scm/src/CCPP_typedefs.F90
+++ b/scm/src/CCPP_typedefs.F90
@@ -252,6 +252,8 @@ module CCPP_typedefs
real (kind=kind_phys), pointer :: rainmp(:) => null() !<
real (kind=kind_phys), pointer :: raincd(:) => null() !<
real (kind=kind_phys), pointer :: raincs(:) => null() !<
+ real (kind=kind_phys), pointer :: raincd_mm(:) => null() !<
+ real (kind=kind_phys), pointer :: raincs_mm(:) => null() !<
real (kind=kind_phys), pointer :: rainmcadj(:) => null() !<
real (kind=kind_phys), pointer :: rainp(:,:) => null() !<
real (kind=kind_phys), pointer :: rb(:) => null() !<
@@ -356,6 +358,7 @@ module CCPP_typedefs
real (kind=kind_phys), pointer :: tv_lay(:,:) => null() !<
real (kind=kind_phys), pointer :: qs_lay(:,:) => null() !<
real (kind=kind_phys), pointer :: q_lay(:,:) => null() !<
+ real (kind=kind_phys), pointer :: dqvdt_nonphy(:,:) => null() !<
real (kind=kind_phys), pointer :: deltaZ(:,:) => null() !<
real (kind=kind_phys), pointer :: deltaZc(:,:) => null() !<
real (kind=kind_phys), pointer :: deltaP(:,:) => null() !<
@@ -420,6 +423,8 @@ module CCPP_typedefs
real (kind=kind_phys), pointer :: xland(:) => null()
real (kind=kind_phys), pointer :: qcx(:,:) => null()
real (kind=kind_phys), pointer :: qix(:,:) => null()
+ real (kind=kind_phys), pointer :: geoph(:,:) => null()
+ real (kind=kind_phys), pointer :: geophi(:,:) => null()
real (kind=kind_phys), pointer :: hfx(:) => null()
real (kind=kind_phys), pointer :: qfx(:) => null()
real (kind=kind_phys), pointer :: qgh(:) => null()
@@ -661,6 +666,8 @@ subroutine gfs_interstitial_create (Interstitial, IM, Model)
allocate (Interstitial%qss_water (IM))
allocate (Interstitial%raincd (IM))
allocate (Interstitial%raincs (IM))
+ allocate (Interstitial%raincd_mm (IM))
+ allocate (Interstitial%raincs_mm (IM))
allocate (Interstitial%rainmcadj (IM))
allocate (Interstitial%rainp (IM,Model%levs))
allocate (Interstitial%rb (IM))
@@ -856,9 +863,13 @@ subroutine gfs_interstitial_create (Interstitial, IM, Model)
end if
! RRTMGP and NCAR MMM physics
- if (Model%do_ysu .or. Model%do_RRTMGP .or. Model%do_mmm_sfclayrev) then
+ if (Model%do_ysu .or. Model%do_RRTMGP .or. Model%do_mmm_sfclayrev .or. Model%imfdeepcnv .eq. Model%imfdeepcnv_mmm_ntiedtke &
+ .or. Model%imfshalcnv .eq. Model%imfshalcnv_mmm_ntiedtke) then
allocate (Interstitial%q_lay (IM, Model%levs))
allocate (Interstitial%deltaZ (IM, Model%levs))
+ allocate (Interstitial%dqvdt_nonphy (IM, Model%levs))
+ allocate (Interstitial%geoph (IM, Model%levs))
+ allocate (Interstitial%geophi (IM, Model%levs))
end if
! NCAR MMM physics
@@ -876,7 +887,8 @@ subroutine gfs_interstitial_create (Interstitial, IM, Model)
Interstitial%scm_force_flux = .false. ! If MMM surface scheme used, fluxes are not prescribed
endif
- if (Model%do_ysu .or. Model%do_mmm_sfclayrev) then
+ if (Model%do_ysu .or. Model%do_mmm_sfclayrev .or. Model%imfdeepcnv .eq. Model%imfdeepcnv_mmm_ntiedtke &
+ .or. Model%imfshalcnv .eq. Model%imfshalcnv_mmm_ntiedtke) then
allocate (Interstitial%xland (IM))
allocate (Interstitial%hfx (IM))
allocate (Interstitial%qfx (IM))
@@ -1404,6 +1416,8 @@ subroutine gfs_interstitial_phys_reset (Interstitial, Model)
Interstitial%qss_water = Model%huge
Interstitial%raincd = clear_val
Interstitial%raincs = clear_val
+ Interstitial%raincd_mm = clear_val
+ Interstitial%raincs_mm = clear_val
Interstitial%rainmcadj = clear_val
Interstitial%rainp = clear_val
Interstitial%rb = clear_val
@@ -1491,9 +1505,13 @@ subroutine gfs_interstitial_phys_reset (Interstitial, Model)
end if
! RRTMGP and NCAR MMM physics
- if (Model%do_ysu .or. Model%do_RRTMGP .or. Model%do_mmm_sfclayrev) then
+ if (Model%do_ysu .or. Model%do_RRTMGP .or. Model%do_mmm_sfclayrev .or. Model%imfdeepcnv .eq. Model%imfdeepcnv_mmm_ntiedtke &
+ .or. Model%imfshalcnv .eq. Model%imfshalcnv_mmm_ntiedtke) then
Interstitial%q_lay = clear_val
Interstitial%deltaZ = clear_val
+ Interstitial%dqvdt_nonphy = clear_val
+ Interstitial%geoph = clear_val
+ Interstitial%geophi = clear_val
endif
! NCAR MMM physics
@@ -1517,7 +1535,8 @@ subroutine gfs_interstitial_phys_reset (Interstitial, Model)
Interstitial%its = 0
Interstitial%ite = 0
endif
- if (Model%do_ysu .or. Model%do_mmm_sfclayrev) then
+ if (Model%do_ysu .or. Model%do_mmm_sfclayrev .or. Model%imfdeepcnv .eq. Model%imfdeepcnv_mmm_ntiedtke &
+ .or. Model%imfshalcnv .eq. Model%imfshalcnv_mmm_ntiedtke) then
Interstitial%xland = 0
Interstitial%hfx = clear_val
Interstitial%qfx = clear_val
diff --git a/scm/src/CCPP_typedefs.meta b/scm/src/CCPP_typedefs.meta
index 3477cd9da..7914a2331 100644
--- a/scm/src/CCPP_typedefs.meta
+++ b/scm/src/CCPP_typedefs.meta
@@ -380,6 +380,14 @@
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
+[dqvdt_nonphy]
+ standard_name = tendendy_of_water_vapor_mixing_ratio_due_to_nonphysics
+ long_name = moisture tendency due to dynamics only
+ units = kg kg-1 s-1
+ dimensions = (horizontal_loop_extent,vertical_layer_dimension)
+ type = real
+ kind = kind_phys
+ active = (control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_mmm_new_tiedtke_shallow_convection)
[cnv_dqldt]
standard_name = tendency_of_cloud_water_due_to_convective_microphysics
long_name = tendency of cloud water due to convective microphysics
@@ -1726,6 +1734,20 @@
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
+[raincd_mm]
+ standard_name = lwe_thickness_of_deep_convective_precipitation_amount_in_mm
+ long_name = deep convective rainfall amount on physics timestep in mm
+ units = mm
+ dimensions = (horizontal_loop_extent)
+ type = real
+ kind = kind_phys
+[raincs_mm]
+ standard_name = lwe_thickness_of_shallow_convective_precipitation_amount_in_mm
+ long_name = shallow convective rainfall amount on physics timestep in mm
+ units = mm
+ dimensions = (horizontal_loop_extent)
+ type = real
+ kind = kind_phys
[rainmcadj]
standard_name = lwe_thickness_of_moist_convective_adj_precipitation_amount
long_name = adjusted moist convective rainfall amount on physics timestep
@@ -2858,7 +2880,22 @@
dimensions = (horizontal_loop_extent,vertical_layer_dimension)
type = real
kind = kind_phys
- active = (flag_for_rrtmgp_radiation_scheme .or. flag_for_ysu_pbl_scheme)
+ active = (flag_for_rrtmgp_radiation_scheme .or. flag_for_ysu_pbl_scheme .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_mmm_new_tiedtke_shallow_convection)
+[geoph]
+ standard_name = geopotential_height
+ long_name = geopotential height at model layer centers
+ units = m
+ dimensions = (horizontal_loop_extent,vertical_layer_dimension)
+ type = real
+ active = (control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_mmm_new_tiedtke_shallow_convection)
+[geophi]
+ standard_name = geopotential_height_at_interface
+ long_name = geopotential height at model layer interfaces
+ units = m
+ dimensions = (horizontal_loop_extent,vertical_interface_dimension)
+ type = real
+ kind = kind_phys
+ active = (control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_mmm_new_tiedtke_shallow_convection)
[deltaZ]
standard_name = layer_thickness
long_name = layer_thickness
@@ -2897,7 +2934,7 @@
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
- active = (flag_for_ysu_pbl_scheme .or. flag_for_mmm_sfclayrev_scheme)
+ active = (flag_for_ysu_pbl_scheme .or. flag_for_mmm_sfclayrev_scheme .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_mmm_new_tiedtke_shallow_convection)
[znt]
standard_name = surface_roughness_length_in_m
long_name = surface roughness length in meter
@@ -2953,7 +2990,7 @@
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
- active = (flag_for_ysu_pbl_scheme .or. flag_for_mmm_sfclayrev_scheme)
+ active = (flag_for_ysu_pbl_scheme .or. flag_for_mmm_sfclayrev_scheme .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_mmm_new_tiedtke_shallow_convection)
[qfx]
standard_name = kinematic_surface_upward_latent_heat_flux
long_name = kinematic surface upward latent heat flux
@@ -2961,7 +2998,7 @@
dimensions = (horizontal_loop_extent)
type = real
kind = kind_phys
- active = (flag_for_ysu_pbl_scheme .or. flag_for_mmm_sfclayrev_scheme)
+ active = (flag_for_ysu_pbl_scheme .or. flag_for_mmm_sfclayrev_scheme .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_mmm_new_tiedtke_shallow_convection)
[qgh]
standard_name = saturation_mixing_ratio_at_lowest_model_level
long_name = saturation water vapor mixing ratio at lowest model level
diff --git a/scm/src/GFS_typedefs.F90 b/scm/src/GFS_typedefs.F90
index 91757f3e3..bd0d7f050 100644
--- a/scm/src/GFS_typedefs.F90
+++ b/scm/src/GFS_typedefs.F90
@@ -1192,6 +1192,7 @@ module GFS_typedefs
integer :: imfshalcnv_gf = 3 !< flag for scale- & aerosol-aware Grell-Freitas scheme (GSD)
integer :: imfshalcnv_ntiedtke = 4 !< flag for new Tiedtke scheme (CAPS)
integer :: imfshalcnv_c3 = 5 !< flag for the Community Convective Cloud (C3) scheme
+ integer :: imfshalcnv_mmm_ntiedtke = 6 !< flag for MMM's new Tiedtke scheme (CAPS)
logical :: hwrf_samfdeep !< flag for HWRF SAMF deepcnv scheme (HWRF)
logical :: progsigma !< flag for prognostic area fraction in samf ddepcnv scheme (GFS)
integer :: imfdeepcnv !< flag for mass-flux deep convection scheme
@@ -1206,6 +1207,7 @@ module GFS_typedefs
integer :: imfdeepcnv_gf = 3 !< flag for scale- & aerosol-aware Grell-Freitas scheme (GSD)
integer :: imfdeepcnv_ntiedtke = 4 !< flag for new Tiedtke scheme (CAPS)
integer :: imfdeepcnv_c3 = 5 !< flag for the Community Convective Cloud (C3) scheme
+ integer :: imfdeepcnv_mmm_ntiedtke = 6 !< flag for MMM new Tiedtke scheme (CAPS)
logical :: hwrf_samfshal !< flag for HWRF SAMF shalcnv scheme (HWRF)
integer :: isatmedmf !< flag for scale-aware TKE-based moist edmf scheme
!< 0: initial version of satmedmf (Nov. 2018)
@@ -5964,6 +5966,12 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, &
error stop
end if
+ if ( (Model%imfdeepcnv == Model%imfdeepcnv_mmm_ntiedtke .or. Model%imfshalcnv == Model%imfshalcnv_mmm_ntiedtke) .and. &
+ .not. (Model%imfdeepcnv == Model%imfdeepcnv_mmm_ntiedtke .and. Model%imfshalcnv == Model%imfshalcnv_mmm_ntiedtke) ) then
+ write(0,*) "Logic error: if NTDK deep convection is used, must also use NTDK shallow convection (and vice versa)"
+ error stop
+ end if
+
if (.not. Model%cscnv) then
if (Model%ras) then
print *,' RAS Convection scheme used with ccwf=',Model%ccwf
@@ -5979,6 +5987,8 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, &
print *,' Grell-Freitas scale & aerosol-aware mass-flux deep conv scheme'
elseif(Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke) then
print *,' New Tiedtke cumulus scheme'
+ elseif(Model%imfdeepcnv == Model%imfdeepcnv_mmm_ntiedtke) then
+ print *,' MMM New Tiedtke cumulus scheme'
elseif(Model%imfdeepcnv == Model%imfdeepcnv_c3) then
print *,' New unified cumulus convection scheme'
endif
@@ -6026,6 +6036,8 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, &
print *,' Grell-Freitas scale- & aerosol-aware mass-flux shallow conv scheme (2013)'
elseif (Model%imfshalcnv == Model%imfshalcnv_ntiedtke) then
print *,' New Tiedtke cumulus scheme'
+ elseif (Model%imfshalcnv == Model%imfshalcnv_mmm_ntiedtke) then
+ print *,' MMM New Tiedtke cumulus scheme'
elseif (Model%imfshalcnv == Model%imfshalcnv_c3) then
print *,' New unified cumulus scheme'
else
@@ -6340,6 +6352,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, &
Model%lmfdeep2 = (Model%imfdeepcnv == Model%imfdeepcnv_samf &
.or. Model%imfdeepcnv == Model%imfdeepcnv_gf &
.or. Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke &
+ .or. Model%imfdeepcnv == Model%imfdeepcnv_mmm_ntiedtke &
.or. Model%imfdeepcnv == Model%imfdeepcnv_c3)
!--- END CODE FROM GLOOPR
@@ -7350,7 +7363,7 @@ subroutine tbd_create (Tbd, IM, Model)
allocate (Tbd%hpbl (IM))
Tbd%hpbl = clear_val
- if (Model%imfdeepcnv == Model%imfdeepcnv_gf .or. Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke .or. Model%imfdeepcnv == Model%imfdeepcnv_samf .or. Model%imfshalcnv == Model%imfshalcnv_samf .or. Model%imfdeepcnv == Model%imfdeepcnv_c3 .or. Model%imfshalcnv == Model%imfshalcnv_c3) then
+ if (Model%imfdeepcnv == Model%imfdeepcnv_gf .or. Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke .or. Model%imfdeepcnv == Model%imfdeepcnv_mmm_ntiedtke .or. Model%imfdeepcnv == Model%imfdeepcnv_samf .or. Model%imfshalcnv == Model%imfshalcnv_samf .or. Model%imfdeepcnv == Model%imfdeepcnv_c3 .or. Model%imfshalcnv == Model%imfshalcnv_c3) then
allocate(Tbd%prevsq(IM, Model%levs))
Tbd%prevsq = clear_val
endif
@@ -7360,7 +7373,7 @@ subroutine tbd_create (Tbd, IM, Model)
Tbd%ud_mf = zero
endif
- if (Model%imfdeepcnv == Model%imfdeepcnv_gf .or. Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke .or. Model%imfdeepcnv == Model%imfdeepcnv_c3) then
+ if (Model%imfdeepcnv == Model%imfdeepcnv_gf .or. Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke .or. Model%imfdeepcnv == Model%imfdeepcnv_mmm_ntiedtke .or. Model%imfdeepcnv == Model%imfdeepcnv_c3 .or. Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke .or. Model%imfshalcnv == Model%imfshalcnv_ntiedtke) then
allocate(Tbd%forcet(IM, Model%levs))
allocate(Tbd%forceq(IM, Model%levs))
allocate(Tbd%prevst(IM, Model%levs))
diff --git a/scm/src/GFS_typedefs.meta b/scm/src/GFS_typedefs.meta
index 1805bbea8..2804273ff 100644
--- a/scm/src/GFS_typedefs.meta
+++ b/scm/src/GFS_typedefs.meta
@@ -5563,6 +5563,12 @@
units = flag
dimensions = ()
type = integer
+[imfshalcnv_mmm_ntiedtke]
+ standard_name = identifier_for_mmm_new_tiedtke_shallow_convection
+ long_name = flag for MMM new Tiedtke shallow convection scheme
+ units = flag
+ dimensions = ()
+ type = integer
[imfdeepcnv]
standard_name = control_for_deep_convection_scheme
long_name = flag for mass-flux deep convection scheme
@@ -5599,6 +5605,12 @@
units = flag
dimensions = ()
type = integer
+[imfdeepcnv_mmm_ntiedtke]
+ standard_name = identifier_for_mmm_new_tiedtke_deep_convection
+ long_name = flag for MMM new Tiedtke deep convection scheme
+ units = flag
+ dimensions = ()
+ type = integer
[ichoice]
standard_name = identifier_for_c3_or_gf_deep_convection_closure
long_name = flag for C3 or GF deep convection closure
@@ -8255,7 +8267,7 @@
dimensions = (horizontal_loop_extent,vertical_layer_dimension)
type = real
kind = kind_phys
- active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection)
+ active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection)
[forceq]
standard_name = tendendy_of_specific_humidity_due_to_nonphysics
long_name = moisture tendency due to dynamics only
@@ -8263,7 +8275,7 @@
dimensions = (horizontal_loop_extent,vertical_layer_dimension)
type = real
kind = kind_phys
- active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection)
+ active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection)
[prevst]
standard_name = air_temperature_on_previous_timestep
long_name = temperature from previous time step
@@ -8271,7 +8283,7 @@
dimensions = (horizontal_loop_extent,vertical_layer_dimension)
type = real
kind = kind_phys
- active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection)
+ active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection)
[prevsq]
standard_name = specific_humidity_on_previous_timestep
long_name = moisture from previous time step
@@ -8279,7 +8291,7 @@
dimensions = (horizontal_loop_extent,vertical_layer_dimension)
type = real
kind = kind_phys
- active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection .or. control_for_deep_convection_scheme == identifer_for_scale_aware_mass_flux_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_scale_aware_mass_flux_shallow_convection)
+ active = (control_for_deep_convection_scheme == identifier_for_grell_freitas_deep_convection .or. control_for_deep_convection_scheme == identifier_for_c3_deep_convection .or. control_for_deep_convection_scheme == identifier_for_new_tiedtke_deep_convection .or. control_for_deep_convection_scheme == identifer_for_scale_aware_mass_flux_deep_convection .or. control_for_shallow_convection_scheme == identifier_for_scale_aware_mass_flux_shallow_convection .or. control_for_deep_convection_scheme == identifier_for_mmm_new_tiedtke_deep_convection)
[cactiv]
standard_name = counter_for_grell_freitas_convection
long_name = convective activity memory
diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py
index c14938fe0..926fb68ba 100755
--- a/scm/src/run_scm.py
+++ b/scm/src/run_scm.py
@@ -3,7 +3,6 @@
import argparse
import f90nml
import logging
-import numpy as np
import os
import re
import shutil
@@ -32,10 +31,6 @@
# Path to default bin directory (relative to scm_root)
DEFAULT_BIN_DIR = 'scm/bin'
-# Default command string to run MPI apps (number of processes should be 1 since SCM is not set up to use more than 1 yet)
-DEFAULT_MPI_COMMAND = 'mpirun -np 1'
-
-
# Copy executable to run directory if true (otherwise it will be linked)
COPY_EXECUTABLE = False
@@ -122,10 +117,8 @@
parser.add_argument('--n_itt_out', help='period of instantaneous output (number of timesteps)', required=False, type=int)
parser.add_argument('--n_itt_diag', help='period of diagnostic output (number of timesteps)', required=False, type=int)
parser.add_argument('-dt', '--timestep', help='timestep (s)', required=False, type=float)
-parser.add_argument('--stop_on_error', help='when running multiple SCM runs, stop on first error', required=False, action='store_true')
parser.add_argument('-v', '--verbose', help='set logging level to debug and write log to file', action='count', default=0)
parser.add_argument('-f', '--file', help='name of file where SCM runs are defined')
-parser.add_argument('--mpi_command', help='command used to invoke the executable via MPI (including options)', required=False)
###############################################################################
# Functions and subroutines #
@@ -157,17 +150,17 @@ def execute(cmd, ignore_error = False):
stderr = subprocess.PIPE, shell = True)
(stdout, stderr) = p.communicate()
status = p.returncode
- message = 'Execution of "{0}" returned with exit code {1}\n'.format(cmd, status)
- message += ' stdout: "{0}"\n'.format(stdout.decode(encoding='ascii', errors='ignore').rstrip('\n'))
- message += ' stderr: "{0}"'.format(stderr.decode(encoding='ascii', errors='ignore').rstrip('\n'))
-
if status == 0:
+ message = 'Execution of "{0}" returned with exit code {1}\n'.format(cmd, status)
+ message += ' stdout: "{0}"\n'.format(stdout.decode(encoding='ascii', errors='ignore').rstrip('\n'))
+ message += ' stderr: "{0}"'.format(stderr.decode(encoding='ascii', errors='ignore').rstrip('\n'))
logging.debug(message)
elif not ignore_error:
+ message = 'Execution of command "{0}" failed, exit code {1}\n'.format(cmd, status)
+ message += ' stdout: "{0}"\n'.format(stdout.decode(encoding='ascii', errors='ignore').rstrip('\n'))
+ message += ' stderr: "{0}"'.format(stderr.decode(encoding='ascii', errors='ignore').rstrip('\n'))
logging.critical(message)
raise Exception('Execution of command "{0}" failed, exit code {1}\n'.format(cmd, status))
- else:
- logging.error(message)
return (status, stdout.decode(encoding='ascii', errors='ignore').rstrip('\n'), stderr.decode(encoding='ascii', errors='ignore').rstrip('\n'))
def parse_arguments():
@@ -192,18 +185,13 @@ def parse_arguments():
run_dir = args.run_dir
bin_dir = args.bin_dir
timestep = args.timestep
- mpi_command = args.mpi_command
- stop_on_error = args.stop_on_error
-
- if not case and not file:
- parser.error('Either "--case" or "--file" must be specified. Use "--help" for more information.')
-
+
if not sdf:
sdf = DEFAULT_SUITE
-
+
return (file, case, sdf, namelist, tracers, gdb, runtime, runtime_mult, docker, \
verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \
- n_itt_diag, run_dir, bin_dir, timestep, mpi_command, stop_on_error)
+ n_itt_diag, run_dir, bin_dir, timestep)
def find_gdb():
"""Detect gdb, abort if not found"""
@@ -224,28 +212,28 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co
"""Initialize experiment. This routine does most of the work,
including setting and checking the experiment configuration
(namelist)."""
-
+
self._case = case
self._suite_obj = suite
self._suite = suite._name
self._name = case + '_' + self._suite
-
+
self._physics_namelist = suite.namelist
-
+
#check to see that the physics namelists exists in the right dir
if not os.path.isfile(os.path.join(SCM_ROOT, PHYSICS_NAMELIST_DIR, self._physics_namelist)):
message = 'The physics namelist {0} was not found'.format(os.path.join(SCM_ROOT, PHYSICS_NAMELIST_DIR, self._physics_namelist))
logging.critical(message)
raise Exception(message)
-
+
self._tracers = suite.tracers
-
+
#check to see that the tracers exists in the right dir
if not os.path.isfile(os.path.join(SCM_ROOT, TRACERS_DIR, self._tracers)):
message = 'The tracer configuration {0} was not found'.format(os.path.join(TRACERS_DIR, self._tracers))
logging.critical(message)
raise Exception(message)
-
+
#check to see if the case namelists exists in the right dir
self._namelist = os.path.join(SCM_ROOT, CASE_NAMELIST_DIR, self._case + '.nml')
if not os.path.isfile(self._namelist):
@@ -261,14 +249,14 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co
self._runtime = None
message = 'Namelist runtime adjustment {0} IS NOT applied'.format(self._runtime)
logging.debug(message)
-
+
if runtime_mult:
self._runtime_mult = runtime_mult
- message = 'Existing case namelist or DEPHY runtime multiplied by {0}'.format(self._runtime_mult)
+ message = 'Existing case namelist runtime multiplied by {0}'.format(self._runtime_mult)
logging.debug(message)
else:
self._runtime_mult = None
-
+
if levels:
self._levels = levels
message = 'The number of vertical levels is set to {0}'.format(self._levels)
@@ -277,7 +265,7 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co
self._levels = None
message = 'The number of vertical levels contained in the case configuration file is used if present, otherwise the default value in scm_input.F90 is used.'
logging.debug(message)
-
+
if npz_type:
self._npz_type = npz_type
message = 'The npz_type of vertical levels is set to {0}'.format(self._npz_type)
@@ -301,7 +289,7 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co
self._vert_coord_file = None
message = 'The npz_type contained in the case configuration file is used if present, otherwise the default value in scm_input.F90 is used.'
logging.debug(message)
-
+
if case_data_dir:
self._case_data_dir = case_data_dir
else:
@@ -311,12 +299,12 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co
message = 'The case data directory {0} was not found'.format(self._case_data_dir)
logging.critical(message)
raise Exception(message)
-
+
if n_itt_out:
self._n_itt_out = n_itt_out
else:
self._n_itt_out = DEFAULT_OUTPUT_PERIOD
-
+
if n_itt_diag:
self._n_itt_diag = n_itt_diag
else:
@@ -326,7 +314,7 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co
self._timestep = timestep
else:
self._timestep = suite.timestep
-
+
@property
def name(self):
"""Get the name of the experiment."""
@@ -346,27 +334,27 @@ def namelist(self):
def namelist(self, value):
"""Set the case namelist of the experiment."""
self._namelist = value
-
+
@property
def case(self):
"""Get the case of the experiment."""
return self._case
-
+
@name.setter
def case(self, value):
"""Set the case of the experiment."""
self._case = value
-
+
@property
def suite(self):
"""Get the suite of the experiment."""
return self._suite
-
+
@suite.setter
def suite(self, value):
"""Set the suite of the experiment."""
self._suite = value
-
+
@property
def physics_namelist(self):
"""Get the physics namelist of the experiment."""
@@ -376,7 +364,7 @@ def physics_namelist(self):
def physics_namelist(self, value):
"""Set the physics namelist of the experiment."""
self._physics_namelist = value
-
+
@property
def tracers(self):
"""Get the tracer file for the experiment."""
@@ -386,7 +374,7 @@ def tracers(self):
def tracers(self, value):
"""Set the tracer file for the experiment."""
self._tracers = value
-
+
@property
def levels(self):
"""Get the number of vertical levels for the experiment."""
@@ -396,7 +384,7 @@ def levels(self):
def levels(self, value):
"""Set the number of vertical levels for the experiment."""
self._levels = value
-
+
@property
def npz_type(self):
"""Get the vertical level type for the experiment."""
@@ -406,7 +394,7 @@ def npz_type(self):
def npz_type(self, value):
"""Set the vertical level type for the experiment."""
self._npz_type = value
-
+
@property
def vert_coord_file(self):
"""Get the file containing vertical levels for the experiment."""
@@ -416,7 +404,7 @@ def vert_coord_file(self):
def vert_coord_file(self, value):
"""Set the file containing vertical levels for the experiment."""
self._vert_coord_file = value
-
+
@property
def case_data_dir(self):
"""Get the case data directory for the experiment."""
@@ -426,7 +414,7 @@ def case_data_dir(self):
def case_data_dir(self, value):
"""Set the case data directory for the experiment."""
self._case_data_dir = value
-
+
@property
def n_itt_out(self):
"""Get the output period (in timesteps) for the experiment."""
@@ -436,7 +424,7 @@ def n_itt_out(self):
def n_itt_out(self, value):
"""Set the output period (in timesteps) for the experiment."""
self._n_itt_out = value
-
+
@property
def n_itt_diag(self):
"""Get the diagnostic period (in timesteps) for the experiment."""
@@ -446,10 +434,10 @@ def n_itt_diag(self):
def n_itt_diag(self, value):
"""Set the diagnostic period (in timesteps) for the experiment."""
self._n_itt_diag = value
-
+
def setup_rundir(self):
"""Set up run directory for this experiment."""
-
+
# Parse case configuration namelist and extract
# - output directory
# - surface_flux_spec
@@ -463,9 +451,11 @@ def setup_rundir(self):
message = 'The --runtime_mult argument must be greater than 0 ({0} was entered)'.format(self._runtime_mult)
logging.critical(message)
raise Exception(message)
- else:
- case_nml['case_config']['runtime_mult'] = self._runtime_mult
-
+ try:
+ old_runtime = case_nml['case_config']['runtime']
+ case_nml['case_config']['runtime'] = old_runtime*self._runtime_mult
+ except KeyError:
+ logging.info('The runtime multiplier argument was set, but the runtime is not set in {0} '.format(self._namelist))
# If the number of levels is specified, set the namelist value
if self._levels:
case_nml['case_config']['n_levels'] = self._levels
@@ -480,7 +470,7 @@ def setup_rundir(self):
case_nml['case_config']['n_itt_diag'] = self._n_itt_diag
if self._timestep:
case_nml['case_config']['dt'] = self._timestep
- # look for the output_dir variable in the case configuration namelist and use it if it does;
+ # look for the output_dir variable in the case configuration namelist and use it if it does;
# if it doesn't exist, create a default output directory name (from the case and suite names) and create a namelist patch
try:
output_dir = case_nml['case_config']['output_dir']
@@ -493,7 +483,7 @@ def setup_rundir(self):
output_dir = 'output_' + self._case + '_' + self._suite + '_' + os.path.splitext(self._physics_namelist)[0]
output_dir_patch_nml = {'case_config':{'output_dir':output_dir}}
custom_output_dir = False
-
+
#if using the DEPHY format, need to also check the case data file for the surfaceForcing global attribute for 'Flux' or 'surfaceFlux', which denotes prescribed surface fluxes
try:
input_type = case_nml['case_config']['input_type']
@@ -503,7 +493,7 @@ def setup_rundir(self):
nc_fid = Dataset(os.path.join(SCM_ROOT, self._case_data_dir) + '/' + self._case + '_SCM_driver.nc' , 'r')
surfaceForcing = nc_fid.getncattr('surface_forcing_temp')
nc_fid.close()
- if (surfaceForcing.lower() == 'kinematic' or surfaceForcing.lower() == 'surface_flux'):
+ if (surfaceForcing.lower() == 'flux' or surfaceForcing.lower() == 'surface_flux'):
surface_flux_spec = True
except KeyError:
# if not using DEPHY format, check to see if surface fluxes are specified in the case configuration file (default is False)
@@ -511,34 +501,34 @@ def setup_rundir(self):
surface_flux_spec = case_nml['case_config']['sfc_flux_spec']
except KeyError:
surface_flux_spec = False
-
+
# If surface fluxes are specified for this case, use the SDF modified to use them
if surface_flux_spec:
logging.info('Specified surface fluxes are used for case {0}. Switching to SDF {1} from {2}'.format(self._case,'suite_' + self._suite + '_ps' + '.xml','suite_' + self._suite + '.xml'))
self._suite = self._suite + '_ps'
-
+
# Create physics_config namelist for experiment configuration file
physics_config = {"physics_suite":self._suite,
"physics_nml":self._physics_namelist,}
physics_config_dict = {"physics_config":physics_config}
physics_config_nml = f90nml.namelist.Namelist(physics_config_dict)
-
+
# Create STANDARD_EXPERIMENT_NAMELIST in the run directory with the case configuration and physics configuration namelists
logging.info('Creating experiment configuration namelist {0} in the run directory from {1} using {2} and {3} '.format(STANDARD_EXPERIMENT_NAMELIST,self._namelist,self._suite,self._physics_namelist))
-
+
with open(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), "w+") as nml_file:
case_nml.write(nml_file)
-
+
with open(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), "a") as nml_file:
physics_config_nml.write(nml_file)
-
+
# if using the default output dir name created in this script, patch the experiment namelist with the new output_dir variable
if(not custom_output_dir):
# GJF TODO: this implementation is clunky; newer versions of f90nml can handle this better, but this works with v0.19 so no need to require newer version
f90nml.patch(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), output_dir_patch_nml, 'temp.nml')
cmd = "mv {0} {1}".format('temp.nml', os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST))
execute(cmd)
-
+
# Link physics namelist to run directory with its original name
logging.debug('Linking physics namelist {0} to run directory'.format(self._physics_namelist))
if os.path.isfile(os.path.join(SCM_RUN, self._physics_namelist)):
@@ -555,7 +545,7 @@ def setup_rundir(self):
logging.info('Found optional prescribed surface physics namelist {0}; linking it to run directory'.format(opt_ps_nml_filename))
cmd = "ln -sf {0} {1}".format(opt_ps_nml_filename, os.path.join(SCM_RUN, self._physics_namelist))
execute(cmd)
-
+
# Link tracer configuration to run directory with standard name
logging.debug('Linking tracer configuration {0} to run directory'.format(self._tracers))
if os.path.isfile(os.path.join(SCM_RUN, self._tracers)):
@@ -566,7 +556,7 @@ def setup_rundir(self):
raise Exception(message)
cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, TRACERS_DIR, self._tracers), os.path.join(SCM_RUN, TRACERS_LINK))
execute(cmd)
-
+
# Link case data file to run directory with original name
try:
input_type = case_nml['case_config']['input_type']
@@ -585,7 +575,7 @@ def setup_rundir(self):
raise Exception(message)
cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, self._case_data_dir, case_data_netcdf_file), os.path.join(SCM_RUN, case_data_netcdf_file))
execute(cmd)
-
+
# Link vertical coordinate file to run directory with its original name
if (self._npz_type == 'input'):
logging.debug('Linking vertical coordinate file {0} to run directory'.format(self._vert_coord_file))
@@ -597,7 +587,7 @@ def setup_rundir(self):
raise Exception(message)
cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, VERT_COORD_DATA_DIR, self._vert_coord_file), os.path.join(SCM_RUN, self._vert_coord_file))
execute(cmd)
-
+
# Link physics SDF to run directory
physics_suite = 'suite_' + self._suite + '.xml'
logging.debug('Linking physics suite {0} to run directory'.format(physics_suite))
@@ -609,7 +599,7 @@ def setup_rundir(self):
raise Exception(message)
cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, PHYSICS_SUITE_DIR, physics_suite), os.path.join(SCM_RUN, physics_suite))
execute(cmd)
-
+
# Link physics data needed for schemes to run directory
logging.debug('Linking physics input data from {0} into run directory'.format(os.path.join(SCM_ROOT, PHYSICS_DATA_DIR)))
for entry in os.listdir(os.path.join(SCM_ROOT, PHYSICS_DATA_DIR)):
@@ -618,7 +608,7 @@ def setup_rundir(self):
logging.debug('Linking file {0}'.format(entry))
cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, PHYSICS_DATA_DIR, entry), os.path.join(SCM_RUN, entry))
execute(cmd)
-
+
# Link reference profile data to run directory
logging.debug('Linking reference profile data from {0} into run directory'.format(os.path.join(SCM_ROOT, REFERENCE_PROFILE_DIR)))
for entry in REFERENCE_PROFILE_FILE_LIST:
@@ -627,7 +617,7 @@ def setup_rundir(self):
logging.debug('Linking file {0}'.format(entry))
cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, REFERENCE_PROFILE_DIR, entry), os.path.join(SCM_RUN, entry))
execute(cmd)
-
+
# Parse physics namelist and extract
# - oz_phys
# - oz_phys_2015
@@ -648,7 +638,7 @@ def setup_rundir(self):
message = 'Logic error, both oz_phys and oz_phys_2015 are set to true in the physics namelist'
logging.critical(message)
raise Exception(message)
-
+
# Link input data for oz_phys or oz_phys_2015
if os.path.exists(os.path.join(SCM_RUN, OZ_PHYS_LINK)):
os.remove(os.path.join(SCM_RUN, OZ_PHYS_LINK))
@@ -660,13 +650,13 @@ def setup_rundir(self):
logging.debug('Linking input data for oz_phys_2015')
cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_RUN, OZ_PHYS_2015_TARGET), os.path.join(SCM_RUN, OZ_PHYS_LINK))
execute(cmd)
-
+
# Look for do_ugwp_v1
try:
do_ugwp_v1 = nml['gfs_physics_nml']['do_ugwp_v1']
except KeyError:
do_ugwp_v1 = DEFAULT_DO_UGWP_V1
-
+
# Link the tau file if do_ugwp_v1
if do_ugwp_v1:
if os.path.exists(os.path.join(SCM_RUN, TAU_LINK)):
@@ -674,7 +664,7 @@ def setup_rundir(self):
logging.debug('Linking input data for UGWP_v1')
cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_RUN, TAU_TARGET), os.path.join(SCM_RUN, TAU_LINK))
execute(cmd)
-
+
# Link scripts needed to run SCM analysis
logging.debug('Linking analysis scripts from {0} into run directory'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_SCRIPT_DIR)))
analysis_script_files = ['scm_analysis.py','configspec.ini']
@@ -684,7 +674,7 @@ def setup_rundir(self):
logging.debug('Linking file {0}'.format(entry))
cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_SCRIPT_DIR, entry), os.path.join(SCM_RUN, entry))
execute(cmd)
-
+
# Link plot configuration files needed to run SCM analysis
logging.debug('Linking plot configuration files from {0} into run directory'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_CONFIG_DIR)))
for entry in os.listdir(os.path.join(SCM_ROOT, SCM_ANALYSIS_CONFIG_DIR)):
@@ -693,18 +683,18 @@ def setup_rundir(self):
logging.debug('Linking file {0}'.format(entry))
cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_CONFIG_DIR, entry), os.path.join(SCM_RUN, entry))
execute(cmd)
-
+
# Create output directory (delete existing directory)
logging.debug('Creating output directory {0} in run directory'.format(output_dir))
if os.path.isdir(os.path.join(SCM_RUN, output_dir)):
shutil.rmtree(os.path.join(SCM_RUN, output_dir))
os.makedirs(os.path.join(SCM_RUN, output_dir))
-
+
# Write experiment configuration file to output directory
logging.debug('Writing experiment configuration {0}.nml to output directory'.format(self._name))
cmd = 'cp {0} {1}'.format(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), os.path.join(SCM_RUN, output_dir,self._name + '.nml'))
execute(cmd)
-
+
# Move executable to run dir
if COPY_EXECUTABLE:
logging.debug('Copying executable to run directory')
@@ -714,7 +704,7 @@ def setup_rundir(self):
logging.debug('Linking executable to run directory')
cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, SCM_BIN, EXECUTABLE_NAME), os.path.join(SCM_RUN, EXECUTABLE_NAME))
execute(cmd)
-
+
#Inform user of timestep and output intervals
if self._timestep:
logging.info('Using {0}s as the timestep with an instantaneous output period of {1}s and a diagnostic output period of {2}s'.format(
@@ -722,19 +712,15 @@ def setup_rundir(self):
else:
logging.info('Using the default timestep in src/scm_input.F90 with an instantaneous output period of {0}*dt and a diagnostic output period of {1}*dt'.format(
case_nml['case_config']['n_itt_out'],case_nml['case_config']['n_itt_diag']))
-
+
return os.path.join(SCM_RUN, output_dir)
-def launch_executable(use_gdb, gdb, mpi_command, ignore_error = False):
+def launch_executable(use_gdb, gdb, ignore_error = False):
"""Configure model run command and pass control to shell/gdb"""
if use_gdb:
- if not mpi_command:
- mpi_command = DEFAULT_MPI_COMMAND + ' xterm -e '
- cmd = '(cd {scm_run} && {mpi_command} {gdb} {executable})'.format(scm_run=SCM_RUN, mpi_command=mpi_command, gdb=gdb, executable=EXECUTABLE)
+ cmd = '(cd {scm_run} && {gdb} {executable})'.format(scm_run=SCM_RUN, gdb=gdb, executable=EXECUTABLE)
else:
- if not mpi_command:
- mpi_command = DEFAULT_MPI_COMMAND
- cmd = '(cd {scm_run} && time {mpi_command} {executable})'.format(scm_run=SCM_RUN, mpi_command=mpi_command, executable=EXECUTABLE)
+ cmd = '(cd {scm_run} && time {executable})'.format(scm_run=SCM_RUN, executable=EXECUTABLE)
logging.info('Passing control to "{0}"'.format(cmd))
time.sleep(1)
# This will abort in 'execute' in the event of an error if ignore_error = False
@@ -758,7 +744,7 @@ def launch_executable(use_gdb, gdb, mpi_command, ignore_error = False):
else:
time_elapsed = int(minutes)*60 + float(seconds)
return (status, time_elapsed)
-
+
def copy_outdir(exp_dir):
"""Copy output directory to /home for this experiment."""
dir_name = os.path.basename(exp_dir)
@@ -767,79 +753,11 @@ def copy_outdir(exp_dir):
shutil.rmtree(home_output_dir)
shutil.copytree(exp_dir, home_output_dir)
-
-def print_report_line(case_s, suite, namelist, max_str_lens):
- case_l = max_str_lens.case
- suite_l = max_str_lens.suite
- namelist_l = max_str_lens.namelist
- logging.info(f"| {case_s:<{case_l}} | {suite:<{suite_l}} | {namelist:<{namelist_l}} |")
-
-
-def print_report(logs, total_count, max_str_lens,
- passing=False, failing=False):
- case_l = max_str_lens.case
- suite_l = max_str_lens.suite
- namelist_l = max_str_lens.namelist
- status_l = max_str_lens.status
- header_printed = False
- column_width = (case_l + suite_l + namelist_l + status_l + 13)
-
- # print formatted summary
- print("")
- if (passing):
- print("Passing Summary:")
- if (failing):
- print("Failure Summary:")
- print("-" * column_width)
- for log in logs:
- case_s, suite, namelist, status = log
- print(f"| {case_s:<{case_l}} | {suite:<{suite_l}} | {namelist:<{namelist_l}} | {status:<{status_l}} |")
- if not header_printed:
- print("-" * column_width)
- header_printed = True
-
- print("-" * column_width)
- if (passing):
- # error_log contains header, subtracting 1 from error
- passing_count = logs.shape[0] - 1
- print(f"[{passing_count}/{total_count}] passing cases")
- if (failing):
- error_count = logs.shape[0] - 1
- print(f"[{error_count}/{total_count}] failed cases")
-
-
-class MaxStrLengths:
- def __init__(self, max_case_len, max_suite_len,
- max_namelist_len, max_status_len):
- self.case = max_case_len
- self.suite = max_suite_len
- self.namelist = max_namelist_len
- self.status = max_status_len
-
-
-def find_max_str_lengths(run_list):
- max_case_len = 0
- max_suite_len = 0
- max_status_len = len('status')
-
- # Loop through the list of dictionaries to find the longest lengths
- for item in run_list:
- max_case_len = max(max_case_len, len(item['case']))
- max_suite_len = max(max_suite_len, len(item['suite']))
-
- # add 6, e.g. diff between len('SCM_HRRR_gf') and len('input_HRRR_gf.nml')
- max_namelist_len = max_suite_len + 6
- max_str_lens = MaxStrLengths(max_case_len, max_suite_len,
- max_namelist_len, max_status_len)
- return max_str_lens
-
-
def main():
(file, case, sdf, namelist, tracers, use_gdb, runtime, runtime_mult, docker, \
verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \
- n_itt_diag, run_dir, bin_dir, timestep, mpi_command, stop_on_error \
- ) = parse_arguments()
-
+ n_itt_diag, run_dir, bin_dir, timestep) = parse_arguments()
+
setup_logging(verbose)
global SCM_ROOT
@@ -855,7 +773,7 @@ def main():
SCM_BIN = bin_dir
else:
SCM_BIN = os.path.join(SCM_ROOT, DEFAULT_BIN_DIR)
-
+
global SCM_RUN
if run_dir:
SCM_RUN = run_dir
@@ -863,10 +781,10 @@ def main():
SCM_RUN = os.path.join(SCM_ROOT, DEFAULT_RUN_DIR)
if not os.path.isdir(SCM_RUN):
os.makedirs(SCM_RUN)
-
+
global EXECUTABLE
EXECUTABLE = os.path.join(SCM_RUN, EXECUTABLE_NAME)
-
+
# Debugger
if use_gdb:
gdb = find_gdb()
@@ -891,20 +809,13 @@ def main():
if (namelist != None): run_list[0]["namelist"] = namelist
if (tracers != None): run_list[0]["tracers"] = tracers
-
- # setup variables
- error_logs = [["Failed Case", "Suite", "Namelist", "Status"]]
- pass_logs = [["Passing Case", "Suite", "Namelist", "Status"]]
- max_str_lens = find_max_str_lengths(run_list)
- failed_case = False
- irun = 0
-
# Loop through all input "run dictionaires"
+ irun = 0
for run in run_list:
#
# Is this a "supported" SCM configuration?
- # (e.g Do we have default namelist and tracer files for this suite?)
+ # (e.g Do we have defualt namelist and tracer files for this suite?)
# If supported, copy default configuration, modify below if necessary.
#
active_suite = None
@@ -924,9 +835,9 @@ def main():
logging.info('Using provided namelist for suite={0}'.format(run["suite"]))
except:
logging.info('Using default namelist for suite={0}'.format(run["suite"]))
-
+
# If tracer file provided, use. Otherwise use default tracer file for this suite
- try:
+ try:
active_suite.tracers = run["tracers"]
logging.info('Using provided tracer file for suite={0}'.format(run["suite"]))
except:
@@ -939,7 +850,7 @@ def main():
# If namelist and tracer file provided, use. Otherwise error.
if ("namelist" in run) and ("tracers" in run):
irun = irun + 1
- if timestep:
+ if timestep:
active_suite = suite(run["suite"], run["tracers"], run["namelist"], timestep, -1, False)
else:
active_suite = suite(run["suite"], run["tracers"], run["namelist"], -1, -1, False)
@@ -951,7 +862,6 @@ def main():
#
# Run the SCM case
#
- print_report_line(run["case"], run["suite"], active_suite.namelist, max_str_lens)
logging.info('Executing process {0} of {1}: case={2}, suite={3}, namelist={4}'.format(
irun, len(run_list), run["case"], run["suite"], active_suite.namelist))
#
@@ -963,36 +873,19 @@ def main():
l_ignore_error = MULTIRUN_IGNORE_ERROR
else:
l_ignore_error = False
- if stop_on_error:
- l_ignore_error = False
-
- (status, time_elapsed) = launch_executable(use_gdb, gdb, mpi_command, ignore_error = l_ignore_error)
+ (status, time_elapsed) = launch_executable(use_gdb, gdb, ignore_error = l_ignore_error)
#
if status == 0:
logging.info('Process "(case={0}, suite={1}, namelist={2}" completed successfully'. \
format(run["case"], run["suite"], active_suite.namelist))
- pass_logs = np.append(pass_logs,
- [[run["case"], run["suite"], active_suite.namelist, status]],
- axis=0)
else:
- failed_case = True
- error_str = 'Process "(case={0}, suite={1}, namelist={2}" exited with code {3}'. \
- format( run["case"], run["suite"], active_suite.namelist, status)
- logging.warning(error_str)
- error_logs = np.append(error_logs,
- [[run["case"], run["suite"], active_suite.namelist, status]],
- axis=0)
+ logging.warning('Process "(case={0}, suite={1}, namelist={2}" exited with code {3}'. \
+ format( run["case"], run["suite"], active_suite.namelist, status))
#
if time_elapsed:
logging.info(' Elapsed time: {0}s'.format(time_elapsed))
if docker:
copy_outdir(exp_dir)
- print_report(pass_logs, len(run_list), max_str_lens, passing=True)
- if (failed_case):
- print_report(error_logs, len(run_list), max_str_lens, failing=True)
- sys.exit(1)
-
-
if __name__ == '__main__':
main()
diff --git a/scm/src/scm_physical_constants.F90 b/scm/src/scm_physical_constants.F90
index c500330c4..0680e8083 100644
--- a/scm/src/scm_physical_constants.F90
+++ b/scm/src/scm_physical_constants.F90
@@ -24,7 +24,7 @@ module scm_physical_constants
real(kind=dp),parameter:: con_cvap =1.8460e+3
real(kind=dp),parameter:: con_hvap =2.5000e+6 !< latent heat of vaporization of water at 0C
real(kind=dp),parameter:: con_hfus =3.3358e+5 !< latent heat of fusion of water at 0C
- real(kind=dp),parameter:: con_xls =2.85e+6 !< latent heat of sublimation of water at 0C
+ real(kind=dp),parameter:: con_xls =2.8440E06 !< latent heat of sublimation of snow/ice at 0C
real(kind=dp),parameter:: con_psat =6.1078e+2_dp !< pres at H2O 3pt (\f$Pa\f$)
real(kind=dp),parameter:: con_t0c =2.7315e+2
real(kind=dp),parameter:: con_ttp =2.7316e+2
diff --git a/scm/src/scm_physical_constants.meta b/scm/src/scm_physical_constants.meta
index 75dab5678..1b29ed9de 100644
--- a/scm/src/scm_physical_constants.meta
+++ b/scm/src/scm_physical_constants.meta
@@ -119,8 +119,8 @@
type = real
kind = kind_phys
[con_xls]
- standard_name = latent_heat_of_sublimation_of_water_at_0C
- long_name = latent heat of sublimation of water at 0C
+ standard_name = latent_heat_of_sublimation_of_ice_snow_at_0C
+ long_name = latent heat of sublimation of snow/ice at 0C
units = J kg-1
dimensions = ()
type = real
@@ -299,4 +299,4 @@
units = K
dimensions = ()
type = real
- kind = kind_phys
\ No newline at end of file
+ kind = kind_phys
diff --git a/scm/src/suite_info.py b/scm/src/suite_info.py
index f74fee7cd..811cdd433 100755
--- a/scm/src/suite_info.py
+++ b/scm/src/suite_info.py
@@ -61,6 +61,7 @@ def timestep(self, value):
suite_list.append(suite('SCM_RAP_mmm', 'tracers_RAP.txt', 'input_RAP_mmm.nml', 600.0, 600.0 , False))
suite_list.append(suite('SCM_RAP_mmm_YSU', 'tracers_RAP.txt', 'input_RAP_mmm_YSU.nml', 600.0, 600.0 , False))
suite_list.append(suite('SCM_RAP_ntiedtke', 'tracers_RAP.txt', 'input_RAP_ntiedtke.nml', 600.0, 600.0 , False))
+suite_list.append(suite('SCM_RAP_ufs_ntiedtke', 'tracers_RAP.txt', 'input_RAP_ufs_ntiedtke.nml', 600.0, 600.0 , False))
suite_list.append(suite('SCM_RAP_sfclayrev', 'tracers_RAP.txt', 'input_RAP_sfclayrev.nml', 600.0, 600.0 , False))
suite_list.append(suite('SCM_GFS_v17_p8_mmm', 'tracers_GFS_v17_p8.txt', 'input_GFS_v17_p8_mmm.nml', 600.0, 600.0, False))
suite_list.append(suite('SCM_GFS_v17_p8_YSU', 'tracers_GFS_v17_p8.txt', 'input_GFS_v17_p8_YSU.nml', 600.0, 600.0, False))