From 214c18213c4d2e005199a5a018ce72f2bdbffb63 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Wed, 4 Feb 2026 18:14:01 +0000 Subject: [PATCH 01/10] initial connection of tempo version 3 --- .gitmodules | 3 +++ .../Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 | 13 ++++--------- .../UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta | 7 ------- physics/MP/TEMPO/tempo_v3 | 1 + 4 files changed, 8 insertions(+), 16 deletions(-) create mode 160000 physics/MP/TEMPO/tempo_v3 diff --git a/.gitmodules b/.gitmodules index d098a48b7..172e437ba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,6 @@ path = physics/MP/TEMPO/TEMPO url = https://github.com/NCAR/TEMPO branch = main +[submodule "physics/MP/TEMPO/tempo_v3"] + path = physics/MP/TEMPO/tempo_v3 + url = https://github.com/NCAR/TEMPO.git diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 index 754fe12bb..f11c23360 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 @@ -47,7 +47,7 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& gasvmr_ccl4, gasvmr_cfc113, aerodp,ext550, clouds6, clouds7, clouds8, & clouds9, cldsa, cldfra, cldfra2d, lwp_ex,iwp_ex, lwp_fc,iwp_fc, & faersw1, faersw2, faersw3, faerlw1, faerlw2, faerlw3, alpha, rrfs_sd, & - aero_dir_fdb, fdb_coef, spp_wts_rad, spp_rad, ico2, ozphys, tempo_cfg, & + aero_dir_fdb, fdb_coef, spp_wts_rad, spp_rad, ico2, ozphys, & errmsg, errflg) use machine, only: kind_phys @@ -89,7 +89,6 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& make_RainNumber_thompson => make_RainNumber use module_mp_tempo_params, only: & - ty_tempo_cfg, & Nt_c_l_tempo => Nt_c_l, & Nt_c_o_tempo => Nt_c_o, & re_qc_min_tempo => re_qc_min, & @@ -260,9 +259,6 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& real (kind=kind_phys), dimension(lm) :: cldfra1d, qv1d, & & qc1d, qi1d, qs1d, dz1d, p1d, t1d - ! For TEMPO MP - type(ty_tempo_cfg), intent(in) :: tempo_cfg - ! for F-A MP real(kind=kind_phys), dimension(im,lm+LTP+1) :: tem2db, hz @@ -960,10 +956,9 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& effri(i,lmk) = re_qi_min_thompson*1.e6 effrs(i,lmk) = re_qs_min_thompson*1.e6 else - call calc_effectRad_tempo(t1d=tlyr(i,:), p1d=plyr(i,:)*100., qv1d=qv_mp(i,:), qc1d=qc_mp(i,:), & - nc1d=nc_mp(i,:), qi1d=qi_mp(i,:), ni1d=ni_mp(i,:), qs1d=qs_mp(i,:), & - re_qc1d=effrl(i,:), re_qi1d=effri(i,:), re_qs1d=effrs(i,:), kts=1, kte=lm, & - lsml=islmsk, configs=tempo_cfg) + call calc_effectRad_thompson(tlyr(i,:), plyr(i,:)*100., qv_mp(i,:), qc_mp(i,:), & + nc_mp(i,:), qi_mp(i,:), ni_mp(i,:), qs_mp(i,:), & + effrl(i,:), effri(i,:), effrs(i,:), islmsk, 1, lm ) ! Scale Thompson's effective radii from meter to micron do k=1,lm effrl(i,k) = MAX(re_qc_min_tempo, MIN(effrl(i,k), re_qc_max_tempo))*1.e6 diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta index 697aadfb5..fa81230ab 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta @@ -267,13 +267,6 @@ dimensions = () type = ty_ozphys intent = in -[tempo_cfg] - standard_name = configuration_for_TEMPO_microphysics - long_name = configuration information for TEMPO microphysics - units = mixed - dimensions = () - type = ty_tempo_cfg - intent = in [iaermdl] standard_name = control_for_aerosol_radiation_scheme long_name = control of aerosol scheme in radiation diff --git a/physics/MP/TEMPO/tempo_v3 b/physics/MP/TEMPO/tempo_v3 new file mode 160000 index 000000000..b29fb2da3 --- /dev/null +++ b/physics/MP/TEMPO/tempo_v3 @@ -0,0 +1 @@ +Subproject commit b29fb2da35f342f18b384b37a3091901c7a86381 From 07b895cd46e4e9defdeb57e630554500ed93ad74 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Wed, 4 Feb 2026 19:10:25 +0000 Subject: [PATCH 02/10] Add comments to radiation for tempo MP and to differentiate tempo from Thompson --- .../Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 | 10 +++++----- .../UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 | 8 ++++---- physics/Radiation/radiation_clouds.f | 2 ++ 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 index f11c23360..eaf66490c 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 @@ -790,13 +790,13 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& if(nint(slmsk(i)) == 1) then if (imp_physics == imp_physics_thompson) then nc_mp (i,k) = Nt_c_l_thompson*orho(i,k) - else + else ! tempo nc_mp (i,k) = Nt_c_l_tempo*orho(i,k) endif else if (imp_physics == imp_physics_thompson) then nc_mp (i,k) = Nt_c_o_thompson*orho(i,k) - else + else ! tempo nc_mp (i,k) = Nt_c_o_tempo*orho(i,k) endif endif @@ -921,14 +921,14 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& if ((ltaerosol .or. mraerosol) .and. qc_mp(i,k)>1.e-12 .and. nc_mp(i,k)<100.) then if (imp_physics == imp_physics_thompson) then nc_mp(i,k) = make_DropletNumber_thompson(qc_mp(i,k)*rho(i,k), nwfa(i,k)*rho(i,k)) * orho(i,k) - else + else ! tempo nc_mp(i,k) = make_DropletNumber_tempo(qc_mp(i,k)*rho(i,k), nwfa(i,k)*rho(i,k)) * orho(i,k) endif endif if (qi_mp(i,k)>1.e-12 .and. ni_mp(i,k)<100.) then if (imp_physics == imp_physics_thompson) then ni_mp(i,k) = make_IceNumber_thompson(qi_mp(i,k)*rho(i,k), tlyr(i,k)) * orho(i,k) - else + else ! tempo ni_mp(i,k) = make_IceNumber_tempo(qi_mp(i,k)*rho(i,k), tlyr(i,k)) * orho(i,k) endif endif @@ -955,7 +955,7 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& effrl(i,lmk) = re_qc_min_thompson*1.e6 effri(i,lmk) = re_qi_min_thompson*1.e6 effrs(i,lmk) = re_qs_min_thompson*1.e6 - else + else ! tempo call calc_effectRad_thompson(tlyr(i,:), plyr(i,:)*100., qv_mp(i,:), qc_mp(i,:), & nc_mp(i,:), qi_mp(i,:), ni_mp(i,:), qs_mp(i,:), & effrl(i,:), effri(i,:), effrs(i,:), islmsk, 1, lm ) diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 index f9a2b76ea..0a808aa10 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 @@ -234,7 +234,7 @@ subroutine GFS_suite_interstitial_4_run (im, levs, ltaerosol, tracers_total, ntr nc_mp(i,k) = gq0(i,k,ntlnc) / (one-spechum(i,k)) if (imp_physics == imp_physics_thompson) then nc_mp(i,k) = max(zero, nc_mp(i,k) + make_DropletNumber_thompson(qc_mp(i,k) * rho, nwfa(i,k)*rho) * orho) - else + else ! tempo nc_mp(i,k) = max(zero, nc_mp(i,k) + make_DropletNumber_tempo(qc_mp(i,k) * rho, nwfa(i,k)*rho) * orho) endif !> - Convert number concentrations from dry to moist @@ -247,7 +247,7 @@ subroutine GFS_suite_interstitial_4_run (im, levs, ltaerosol, tracers_total, ntr ni_mp(i,k) = gq0(i,k,ntinc) / (one-spechum(i,k)) if (imp_physics == imp_physics_thompson) then ni_mp(i,k) = max(zero, ni_mp(i,k) + make_IceNumber_thompson(qi_mp(i,k) * rho, save_tcp(i,k)) * orho) - else + else ! tempo ni_mp(i,k) = max(zero, ni_mp(i,k) + make_IceNumber_tempo(qi_mp(i,k) * rho, save_tcp(i,k)) * orho) endif !> - Convert number concentrations from dry to moist @@ -267,7 +267,7 @@ subroutine GFS_suite_interstitial_4_run (im, levs, ltaerosol, tracers_total, ntr !> - Update cloud water number concentration if (imp_physics == imp_physics_thompson) then gq0(i,k,ntlnc) = max(zero, gq0(i,k,ntlnc) + make_DropletNumber_thompson(qc_mp(i,k) * rho, nwfa(i,k)*rho) * orho) - else + else ! tempo gq0(i,k,ntlnc) = max(zero, gq0(i,k,ntlnc) + make_DropletNumber_tempo(qc_mp(i,k) * rho, nwfa(i,k)*rho) * orho) endif endif @@ -277,7 +277,7 @@ subroutine GFS_suite_interstitial_4_run (im, levs, ltaerosol, tracers_total, ntr !> - Update cloud ice number concentration if (imp_physics == imp_physics_thompson) then gq0(i,k,ntinc) = max(zero, gq0(i,k,ntinc) + make_IceNumber_thompson(qi_mp(i,k) * rho, save_tcp(i,k)) * orho) - else + else ! tempo gq0(i,k,ntinc) = max(zero, gq0(i,k,ntinc) + make_IceNumber_tempo(qi_mp(i,k) * rho, save_tcp(i,k)) * orho) endif endif diff --git a/physics/Radiation/radiation_clouds.f b/physics/Radiation/radiation_clouds.f index d779d56c2..714d0e52f 100644 --- a/physics/Radiation/radiation_clouds.f +++ b/physics/Radiation/radiation_clouds.f @@ -28,6 +28,7 @@ ! ntrac, ntcw, ntiw, ntrw, ntsw, ntgl, ntclamt, ! ! imp_physics, imp_physics_nssl, imp_physics_fer_hires, ! ! imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6, ! +! imp_physics_tempo, ! ! imp_physics_zhao_carr, imp_physics_zhao_carr_pdf, ! ! imp_physics_mg, iovr, iovr_rand, iovr_maxrand, iovr_max, ! ! iovr_dcorr, iovr_exp, iovr_exprand, idcor, idcor_con, ! @@ -436,6 +437,7 @@ subroutine radiation_clouds_prop & ! imp_physics_fer_hires : Ferrier-Aligo microphysics scheme ! ! imp_physics_gfdl : GFDL microphysics scheme ! ! imp_physics_thompson : Thompson microphysics scheme ! +! imp_physics_tempo : Tempo microphysics scheme ! ! imp_physics_wsm6 : WSMG microphysics scheme ! ! imp_physics_zhao_carr : Zhao-Carr microphysics scheme ! ! imp_physics_zhao_carr_pdf : Zhao-Carr microphysics scheme with PDF clouds From 13c04f6c83ab696846a49b3a8458dd58e431b186 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Wed, 4 Feb 2026 20:40:10 +0000 Subject: [PATCH 03/10] Connects TEMPO to GFS PBL generic --- .../GFS_PBL_generic_common.F90 | 17 ++++++- .../UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 | 45 +++++++++++++++++-- .../UFS_SCM_NEPTUNE/GFS_PBL_generic_post.meta | 14 ++++++ .../UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 | 42 ++++++++++++++++- .../UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.meta | 14 ++++++ 5 files changed, 125 insertions(+), 7 deletions(-) diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_common.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_common.F90 index 1ae654edf..2d2a5dd90 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_common.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_common.F90 @@ -13,6 +13,7 @@ module GFS_PBL_generic_common subroutine set_aerosol_tracer_index(imp_physics, imp_physics_wsm6, & imp_physics_thompson, ltaerosol,mraerosol, & + imp_physics_tempo, lthailaware, & imp_physics_mg, ntgl, imp_physics_gfdl, & imp_physics_zhao_carr, imp_physics_nssl,& nssl_hail_on, nssl_ccn_on, nssl_3moment, kk, & @@ -20,10 +21,10 @@ subroutine set_aerosol_tracer_index(imp_physics, imp_physics_wsm6, & implicit none ! integer, intent(in ) :: imp_physics, imp_physics_wsm6, & - imp_physics_thompson, & + imp_physics_thompson, imp_physics_tempo,& imp_physics_mg, ntgl, imp_physics_gfdl, & imp_physics_zhao_carr,imp_physics_nssl - logical, intent(in ) :: ltaerosol, mraerosol, nssl_hail_on, nssl_ccn_on, nssl_3moment + logical, intent(in ) :: ltaerosol, mraerosol, nssl_hail_on, nssl_ccn_on, nssl_3moment, lthailaware integer, intent(out) :: kk character(len=*), intent(out) :: errmsg integer, intent(out) :: errflg @@ -43,6 +44,18 @@ subroutine set_aerosol_tracer_index(imp_physics, imp_physics_wsm6, & else kk = 9 endif + elseif (imp_physics == imp_physics_tempo) then +! Tempo (Note: why are we setting tracer indices manually?) +! I'll assume that kk = 9 includes qv, qc, qr, qi, qs, qg, ni, nr +! when ltaerosol = true: nc, nwfa, and nifa are added (+3) +! when lthail = true: ng and volg are added (+2) + kk = 9 + if(ltaerosol) then + kk = kk + 3 + endif + if(lthailaware) then + kk = kk + 2 + endif ! MG elseif (imp_physics == imp_physics_mg) then if (ntgl > 0) then diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 index 01033f4d6..d30d91be7 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 @@ -12,6 +12,7 @@ subroutine GFS_PBL_generic_post_run (im, levs, nvdiff, ntrac, ntqv, ntcw, ntiw, ntrw, ntsw, ntlnc, ntinc, ntrnc, ntsnc, ntgnc, ntwa, ntia, ntgl, ntoz, ntke, ntkev,nqrimef, & trans_aero, ntchs, ntchm, ntccn, nthl, nthnc, ntgv, nthv, ntrz, ntgz, nthz, & imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6, imp_physics_zhao_carr, imp_physics_mg, & + impo_physics_tempo, lthailaware, & imp_physics_fer_hires, imp_physics_nssl, nssl_ccn_on, ltaerosol, mraerosol, nssl_hail_on, nssl_3moment, & cplflx, cplaqm, cplchm, lssav, flag_for_pbl_generic_tend, ldiag3d, lsidea, hybedmf, do_shoc, satmedmf, & shinhong, do_ysu, dvdftra, dusfc1, dvsfc1, dtsfc1, dqsfc1, dtf, dudt, dvdt, dtdt, htrsw, htrlw, xmu, & @@ -32,11 +33,11 @@ subroutine GFS_PBL_generic_post_run (im, levs, nvdiff, ntrac, integer, intent(in) :: ntqv, ntcw, ntiw, ntrw, ntsw, ntlnc, ntinc, ntrnc, ntsnc, ntgnc, ntwa, ntia, ntgl, ntoz, ntke, ntkev, nqrimef integer, intent(in) :: ntccn, nthl, nthnc, ntgv, nthv, ntrz, ntgz, nthz logical, intent(in) :: trans_aero - integer, intent(in) :: imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6 + integer, intent(in) :: imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6, imp_physics_tempo integer, intent(in) :: imp_physics_zhao_carr, imp_physics_mg, imp_physics_fer_hires integer, intent(in) :: imp_physics_nssl logical, intent(in) :: nssl_ccn_on, nssl_hail_on, nssl_3moment - logical, intent(in) :: ltaerosol, cplflx, cplaqm, cplchm, lssav, ldiag3d, lsidea, use_med_flux, mraerosol + logical, intent(in) :: ltaerosol, cplflx, cplaqm, cplchm, lssav, ldiag3d, lsidea, use_med_flux, mraerosol, lthailaware logical, intent(in) :: hybedmf, do_shoc, satmedmf, shinhong, do_ysu logical, intent(in) :: flag_for_pbl_generic_tend @@ -107,7 +108,8 @@ subroutine GFS_PBL_generic_post_run (im, levs, nvdiff, ntrac, if (trans_aero) then ! Set kk if chemistry-aerosol tracers are diffused call set_aerosol_tracer_index(imp_physics, imp_physics_wsm6, & - imp_physics_thompson, ltaerosol,mraerosol, & + imp_physics_thompson, ltaerosol,mraerosol, & + imp_physics_tempo, lthailaware, & imp_physics_mg, ntgl, imp_physics_gfdl, & imp_physics_zhao_carr, imp_physics_nssl,& nssl_hail_on, nssl_ccn_on, nssl_3moment, kk, & @@ -198,6 +200,43 @@ subroutine GFS_PBL_generic_post_run (im, levs, nvdiff, ntrac, enddo enddo endif + elseif (imp_physics == imp_physics_tempo) then + ! Tempo + do k=1,levs + do i=1,im + dqdt(i,k,ntqv) = dvdftra(i,k,1) + dqdt(i,k,ntcw) = dvdftra(i,k,2) + dqdt(i,k,ntiw) = dvdftra(i,k,3) + dqdt(i,k,ntrw) = dvdftra(i,k,4) + dqdt(i,k,ntsw) = dvdftra(i,k,5) + dqdt(i,k,ntgl) = dvdftra(i,k,6) + dqdt(i,k,ntinc) = dvdftra(i,k,7) + dqdt(i,k,ntrnc) = dvdftra(i,k,8) + dqdt(i,k,ntoz) = dvdftra(i,k,9) + enddo + enddo + + n = 10 + if (ltaerosol) then + do k=1,levs + do i=1,im + dqdt(i,k,ntlnc) = dvdftra(i,k,n) + dqdt(i,k,ntwa) = dvdftra(i,k,n+1) + dqdt(i,k,ntia) = dvdftra(i,k,n+2) + enddo + enddo + n = 13 + endif + + if (lthailaware) then + do k=1,levs + do i=1,im + dqdt(i,k,ntgnc) = dvdftra(i,k,n) + dqdt(i,k,ntgv) = dvdftra(i,k,n+1) + enddo + enddo + endif + elseif (imp_physics == imp_physics_mg) then ! MG3/2 if (ntgl > 0) then ! MG do k=1,levs diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.meta b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.meta index 057d061a4..f2e711e11 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.meta +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.meta @@ -253,6 +253,13 @@ dimensions = () type = integer intent = in +[imp_physics_tempo] + standard_name = identifier_for_tempo_microphysics_scheme + long_name = choice of Tempo microphysics scheme + units = flag + dimensions = () + type = integer + intent = in [imp_physics_wsm6] standard_name = identifier_for_wsm6_microphysics_scheme long_name = choice of WSM6 microphysics scheme @@ -295,6 +302,13 @@ dimensions = () type = logical intent = in +[lthailaware] + standard_name = flag_for_hail_physics + long_name = flag for hail physics + units = flag + dimensions = () + type = logical + intent = in [mraerosol] standard_name = do_merra2_aerosol_awareness long_name = flag for merra2 aerosol-aware physics for example the thompson microphysics diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 index eab767147..e5bb9b0cb 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 @@ -14,6 +14,7 @@ subroutine GFS_PBL_generic_pre_run (im, levs, nvdiff, ntrac, rtg_ozone_index, ntwa, ntia, ntgl, ntoz, ntke, ntkev, nqrimef, trans_aero, ntchs, ntchm, & ntccn, nthl, nthnc, ntgv, nthv, ntrz, ntgz, nthz, & imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6, & + imp_physics_tempo, lthailaware, & imp_physics_zhao_carr, imp_physics_mg, imp_physics_fer_hires, imp_physics_nssl, & ltaerosol, mraerosol, nssl_ccn_on, nssl_hail_on, nssl_3moment, & hybedmf, do_shoc, satmedmf, qgrs, vdftra, save_u, save_v, save_t, save_q, & @@ -31,9 +32,9 @@ subroutine GFS_PBL_generic_pre_run (im, levs, nvdiff, ntrac, rtg_ozone_index, integer, intent(in) :: ntwa, ntia, ntgl, ntoz, ntke, ntkev, nqrimef,ntchs, ntchm integer, intent(in) :: ntccn, nthl, nthnc, ntgv, nthv, ntrz, ntgz, nthz logical, intent(in) :: trans_aero, ldiag3d, qdiag3d, lssav - integer, intent(in) :: imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6 + integer, intent(in) :: imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6, imp_physics_tempo integer, intent(in) :: imp_physics_zhao_carr, imp_physics_mg, imp_physics_fer_hires - logical, intent(in) :: ltaerosol, hybedmf, do_shoc, satmedmf, flag_for_pbl_generic_tend, mraerosol + logical, intent(in) :: ltaerosol, hybedmf, do_shoc, satmedmf, flag_for_pbl_generic_tend, mraerosol, lthailaware integer, intent(in) :: imp_physics_nssl logical, intent(in) :: nssl_hail_on, nssl_ccn_on, nssl_3moment @@ -140,6 +141,43 @@ subroutine GFS_PBL_generic_pre_run (im, levs, nvdiff, ntrac, rtg_ozone_index, enddo rtg_ozone_index = 9 endif + elseif (imp_physics == imp_physics_tempo) then + ! Tempo + do k=1,levs + do i=1,im + vdftra(i,k,1) = qgrs(i,k,ntqv) + vdftra(i,k,2) = qgrs(i,k,ntcw) + vdftra(i,k,3) = qgrs(i,k,ntiw) + vdftra(i,k,4) = qgrs(i,k,ntrw) + vdftra(i,k,5) = qgrs(i,k,ntsw) + vdftra(i,k,6) = qgrs(i,k,ntgl) + vdftra(i,k,7) = qgrs(i,k,ntinc) + vdftra(i,k,8) = qgrs(i,k,ntrnc) + vdftra(i,k,9) = qgrs(i,k,ntoz) + enddo + enddo + rtg_ozone_index = 9 + n = 10 + + if (ltaerosol) then + do k=1,levs + do i=1,im + vdftra(i,k,n) = qgrs(i,k,ntlnc) + vdftra(i,k,n+1) = qgrs(i,k,ntwa) + vdftra(i,k,n+2) = qgrs(i,k,ntia) + enddo + enddo + n = 13 + endif + + if (lthailaware) then + do k=1,levs + do i=1,im + vdftra(i,k,n) = qgrs(i,k,ntgnc) + vdftra(i,k,n+1) = qgrs(i,k,ntgv) + enddo + enddo + endif ! MG elseif (imp_physics == imp_physics_mg) then ! MG3/2 if (ntgl > 0) then ! MG3 diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.meta b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.meta index 7a8e72bba..259e61a54 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.meta +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.meta @@ -259,6 +259,13 @@ dimensions = () type = integer intent = in +[imp_physics_tempo] + standard_name = identifier_for_tempo_microphysics_scheme + long_name = choice of Tempo microphysics scheme + units = flag + dimensions = () + type = integer + intent = in [imp_physics_wsm6] standard_name = identifier_for_wsm6_microphysics_scheme long_name = choice of WSM6 microphysics scheme @@ -301,6 +308,13 @@ dimensions = () type = logical intent = in +[lthailaware] + standard_name = flag_for_hail_physics + long_name = flag for hail physics + units = flag + dimensions = () + type = logical + intent = in [mraerosol] standard_name = do_merra2_aerosol_awareness long_name = flag for merra2 aerosol-aware physics for example the thompson microphysics From fc03db5e235c5977b23437954bd5577445f49e60 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Fri, 6 Feb 2026 18:18:02 +0000 Subject: [PATCH 04/10] fix type and add tempo to aerosol index procedure --- physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 | 2 +- physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 index d30d91be7..9756055ec 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 @@ -12,7 +12,7 @@ subroutine GFS_PBL_generic_post_run (im, levs, nvdiff, ntrac, ntqv, ntcw, ntiw, ntrw, ntsw, ntlnc, ntinc, ntrnc, ntsnc, ntgnc, ntwa, ntia, ntgl, ntoz, ntke, ntkev,nqrimef, & trans_aero, ntchs, ntchm, ntccn, nthl, nthnc, ntgv, nthv, ntrz, ntgz, nthz, & imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_wsm6, imp_physics_zhao_carr, imp_physics_mg, & - impo_physics_tempo, lthailaware, & + imp_physics_tempo, lthailaware, & imp_physics_fer_hires, imp_physics_nssl, nssl_ccn_on, ltaerosol, mraerosol, nssl_hail_on, nssl_3moment, & cplflx, cplaqm, cplchm, lssav, flag_for_pbl_generic_tend, ldiag3d, lsidea, hybedmf, do_shoc, satmedmf, & shinhong, do_ysu, dvdftra, dusfc1, dvsfc1, dtsfc1, dqsfc1, dtf, dudt, dvdt, dtdt, htrsw, htrlw, xmu, & diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 index e5bb9b0cb..630de1824 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 @@ -312,6 +312,7 @@ subroutine GFS_PBL_generic_pre_run (im, levs, nvdiff, ntrac, rtg_ozone_index, if (trans_aero) then call set_aerosol_tracer_index(imp_physics, imp_physics_wsm6, & imp_physics_thompson, ltaerosol,mraerosol, & + imp_physics_tempo, lthailaware, & imp_physics_mg, ntgl, imp_physics_gfdl, & imp_physics_zhao_carr, imp_physics_nssl,& nssl_hail_on, nssl_ccn_on, nssl_3moment, kk, & From e29c7faec2baecb6f59ff1a250da7d74fb56da62 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Fri, 13 Feb 2026 14:14:32 +0000 Subject: [PATCH 05/10] simplify tempo driver and add condensation routine --- .gitmodules | 2 +- physics/MP/TEMPO/mp_tempo.F90 | 943 +++----------------- physics/MP/TEMPO/mp_tempo.meta | 729 ++++----------- physics/MP/TEMPO/mp_tempo_condensation.F90 | 186 ++++ physics/MP/TEMPO/mp_tempo_condensation.meta | 252 ++++++ physics/MP/TEMPO/tempo_v3 | 2 +- 6 files changed, 727 insertions(+), 1387 deletions(-) create mode 100644 physics/MP/TEMPO/mp_tempo_condensation.F90 create mode 100644 physics/MP/TEMPO/mp_tempo_condensation.meta diff --git a/.gitmodules b/.gitmodules index 172e437ba..c103d06f2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,4 +8,4 @@ branch = main [submodule "physics/MP/TEMPO/tempo_v3"] path = physics/MP/TEMPO/tempo_v3 - url = https://github.com/NCAR/TEMPO.git + url = https://github.com/AndersJensen-NOAA/TEMPO.git diff --git a/physics/MP/TEMPO/mp_tempo.F90 b/physics/MP/TEMPO/mp_tempo.F90 index 174eaac2e..eda4943ae 100644 --- a/physics/MP/TEMPO/mp_tempo.F90 +++ b/physics/MP/TEMPO/mp_tempo.F90 @@ -10,8 +10,8 @@ module mp_tempo use machine, only : kind_phys use module_mp_tempo_params - use module_mp_tempo_utils, only : make_IceNumber, make_RainNumber, make_DropletNumber - use module_mp_tempo, only : tempo_init, tempo_3d_to_1d_driver, tempo_finalize + use module_mp_tempo_cfgs, only : ty_tempo_cfgs + use module_mp_tempo_driver, only : tempo_init, tempo_run, ty_tempo_driver_diags implicit none @@ -19,91 +19,62 @@ module mp_tempo private - integer, parameter :: ext_ndiag3d = 37 - contains !> This subroutine is a wrapper around the actual tempo_init(). !! \section arg_table_mp_tempo_init Argument Table !! \htmlinclude mp_tempo_init.html !! - subroutine mp_tempo_init(ncol, nlev, con_pi, con_t0c, con_rv, & - con_cp, con_rgas, con_boltz, con_amd, & - con_amw, con_avgd, con_hvap, con_hfus, & - con_g, con_rd, con_eps, & - restart, imp_physics, & - imp_physics_tempo, convert_dry_rho, & - spechum, qc, qr, qi, qs, qg, ni, nr, & - chw, vh, & - is_aerosol_aware, merra2_aerosol_aware, & - is_hail_aware, & - nc, nwfa2d, nifa2d, & - nwfa, nifa, tgrs, prsl, phil, area, & - aerfld, mpicomm, mpirank, mpiroot, & - threads, ext_diag, diag3d, & - is_initialized, errmsg, errflg) + subroutine mp_tempo_init(ncol, nlev, & + imp_physics, imp_physics_tempo, & + mpicomm, mpirank, mpiroot, & + tgrs, prsl, phil, con_g, con_rd, con_eps, & + restart, convert_dry_rho, is_aerosol_aware, & + is_hail_aware, do_sat_adj, semi_sedi, & + spechum, nwfa, nifa, nwfa2d, nifa2d, & + tempo_cfgs, is_initialized, errmsg, errflg) - implicit none - ! Interface variables integer, intent(in ) :: ncol integer, intent(in ) :: nlev - real(kind_phys), intent(in ) :: con_pi, con_t0c, con_rv, con_cp, con_rgas, & - con_boltz, con_amd, con_amw, con_avgd, & - con_hvap, con_hfus, con_g, con_rd, con_eps logical, intent(in ) :: restart logical, intent(inout) :: is_initialized integer, intent(in ) :: imp_physics integer, intent(in ) :: imp_physics_tempo - ! Hydrometeors + logical, intent(in ) :: do_sat_adj + logical, intent(in ) :: semi_sedi logical, intent(in ) :: convert_dry_rho - real(kind_phys), intent(inout) :: spechum(:,:) - real(kind_phys), intent(inout) :: qc(:,:) - real(kind_phys), intent(inout) :: qr(:,:) - real(kind_phys), intent(inout) :: qi(:,:) - real(kind_phys), intent(inout) :: qs(:,:) - real(kind_phys), intent(inout) :: qg(:,:) - real(kind_phys), intent(inout) :: ni(:,:) - real(kind_phys), intent(inout) :: nr(:,:) - real(kind_phys), intent(inout), optional :: chw(:,:), vh(:,:) - ! Aerosols logical, intent(in ) :: is_aerosol_aware - logical, intent(in ) :: merra2_aerosol_aware logical, intent(in ) :: is_hail_aware - real(kind_phys), intent(inout), optional :: nc(:,:) + real(kind_phys), intent(in ) :: con_g, con_rd, con_eps + ! Hydrometeors + real(kind_phys), intent(inout) :: spechum(:,:) + ! Aerosols real(kind_phys), intent(inout), optional :: nwfa(:,:) real(kind_phys), intent(inout), optional :: nifa(:,:) real(kind_phys), intent(inout), optional :: nwfa2d(:) real(kind_phys), intent(inout), optional :: nifa2d(:) - real(kind_phys), intent(in) :: aerfld(:,:,:) + ! State variables real(kind_phys), intent(in ) :: tgrs(:,:) real(kind_phys), intent(in ) :: prsl(:,:) real(kind_phys), intent(in ) :: phil(:,:) - real(kind_phys), intent(in ) :: area(:) ! MPI information type(MPI_Comm), intent(in ) :: mpicomm integer, intent(in ) :: mpirank integer, intent(in ) :: mpiroot - ! Threading/blocking information - integer, intent(in ) :: threads - ! Extended diagnostics - logical, intent(in ) :: ext_diag - real(kind_phys), intent(in ), optional :: diag3d(:,:,:) ! CCPP error handling character(len=*), intent( out) :: errmsg integer, intent( out) :: errflg - - ! + type(ty_tempo_cfgs), intent(inout) :: tempo_cfgs + real(kind_phys) :: qv(1:ncol,1:nlev) ! kg kg-1 (water vapor mixing ratio) real(kind_phys) :: hgt(1:ncol,1:nlev) ! m real(kind_phys) :: rho(1:ncol,1:nlev) ! kg m-3 real(kind_phys) :: orho(1:ncol,1:nlev) ! m3 kg-1 - real(kind_phys) :: nc_local(1:ncol,1:nlev) ! needed because nc is only allocated if is_aerosol_aware is true - ! real (kind=kind_phys) :: h_01, z1, niIN3, niCCN3 integer :: i, k - + ! Initialize the CCPP error handling variables errmsg = '' errflg = 0 @@ -112,33 +83,19 @@ subroutine mp_tempo_init(ncol, nlev, con_pi, con_t0c, con_rv, & ! Consistency checks if (imp_physics/=imp_physics_tempo) then - write(errmsg,'(*(a))') "Logic error: namelist choice of microphysics is different from TEMPO MP" + write(errmsg,'(*(a))') "Logic error: namelist choice of microphysics is different from Tempo MP" errflg = 1 return end if - if (ext_diag) then - if (size(diag3d,dim=3) /= ext_ndiag3d) then - write(errmsg,'(*(a))') "Logic error: number of diagnostic 3d arrays from model does not match requirements" - errflg = 1 - return - end if - end if + ! Call tempo init (also sets initial default values of physical constants) + if (mpirank==mpiroot) write(*,*) 'Calling tempo_init()' - if (is_aerosol_aware .and. merra2_aerosol_aware) then - write(errmsg,'(*(a))') "Logic error: Only one TEMPO aerosol option can be true, either is_aerosol_aware or merra2_aerosol_aware)" - errflg = 1 - return - end if + ! Main call to tempo_init() + call tempo_init(aerosolaware_flag=.false., hailaware_flag=.false., & + semi_sedi_flag=semi_sedi, cloud_condensation_flag=(.not. do_sat_adj), & + tempo_cfgs=tempo_cfgs) - ! Call TEMPO init (also sets initial default values of physical constants) - if (mpirank==mpiroot) write(*,*) 'Calling tempo_init() with is_aerosol_aware = ', is_aerosol_aware - - call tempo_init(is_aerosol_aware_in=is_aerosol_aware, & - merra2_aerosol_aware_in=merra2_aerosol_aware, & - is_hail_aware_in=is_hail_aware, & - mpicomm=mpicomm, mpirank=mpirank, mpiroot=mpiroot, & - threads=threads, errmsg=errmsg, errflg=errflg) if (errflg /= 0) return ! For restart runs, the init is done here @@ -147,108 +104,27 @@ subroutine mp_tempo_init(ncol, nlev, con_pi, con_t0c, con_rv, & return end if - ! Set local TEMPO MP module constants from host model and overwrite derived constants calculated in module_mp_tempo_params/mp_tempo_params_init() - PI = con_pi - lvap0 = con_hvap - lfus = con_hfus - lsub = lvap0 + lfus - olfus = 1./lfus - - Rv = con_Rv - R = con_rd - RoverRv = con_eps - Cp2 = con_cp - T_0 = con_t0c - R_uni = con_rgas - k_b = con_boltz - N_avo = con_avgd - - oRv = 1.0 / Rv - am_r = PI * rho_w2 / 6.0 - am_i = PI * rho_i / 6.0 - am_g = (/PI*rho_g(1)/6.0, & - PI*rho_g(2)/6.0, & - PI*rho_g(3)/6.0, & - PI*rho_g(4)/6.0, & - PI*rho_g(5)/6.0, & - PI*rho_g(6)/6.0, & - PI*rho_g(7)/6.0, & - PI*rho_g(8)/6.0, & - PI*rho_g(9)/6.0/) - - M_w = con_amw*1.0E-3 !module_mp_tempo expects kg/mol - M_a = con_amd*1.0E-3 !module_mp_tempo expects kg/mol - ma_w = M_w/N_avo - - ar_volume = 4.0 / 3.0 * PI * (2.5e-6)**3 - - ! Geopotential height in m2 s-2 to height in m - hgt = phil/con_g - - ! Ensure non-negative mass mixing ratios of all water variables - where(spechum<0) spechum = 1.0E-10 ! COMMENT, gthompsn, spechum should *never* be identically zero. - where(qc<0) qc = 0.0 - where(qr<0) qr = 0.0 - where(qi<0) qi = 0.0 - where(qs<0) qs = 0.0 - where(qg<0) qg = 0.0 - - !> - Convert specific humidity to water vapor mixing ratio. - !> - Also, hydrometeor variables are mass or number mixing ratio - !> - either kg of species per kg of dry air, or per kg of (dry + vapor). - if (merra2_aerosol_aware) then - call get_niwfa(aerfld, nifa, nwfa, ncol, nlev) - end if - - - qv = spechum/(1.0_kind_phys-spechum) - if (convert_dry_rho) then - qc = qc/(1.0_kind_phys-spechum) - qr = qr/(1.0_kind_phys-spechum) - qi = qi/(1.0_kind_phys-spechum) - qs = qs/(1.0_kind_phys-spechum) - qg = qg/(1.0_kind_phys-spechum) - - ni = ni/(1.0_kind_phys-spechum) - nr = nr/(1.0_kind_phys-spechum) - if (is_hail_aware) then - chw = chw/(1.0_kind_phys-spechum) - vh = vh/(1.0_kind_phys-spechum) - endif - if (is_aerosol_aware .or. merra2_aerosol_aware) then - nc = nc/(1.0_kind_phys-spechum) + if (is_aerosol_aware) then nwfa = nwfa/(1.0_kind_phys-spechum) nifa = nifa/(1.0_kind_phys-spechum) end if end if + ! Geopotential height in m2 s-2 to height in m + hgt = phil/con_g + ! Density of moist air in kg m-3 and inverse density of air rho = con_eps*prsl/(con_rd*tgrs*(qv+con_eps)) orho = 1.0/rho - ! Ensure we have 1st guess ice number where mass non-zero but no number. - where(qi .LE. 0.0) ni=0.0 - where(qi .GT. 0 .and. ni .LE. 0.0) ni = make_IceNumber(qi*rho, tgrs) * orho - where(qi .EQ. 0.0 .and. ni .GT. 0.0) ni=0.0 - - ! Ensure we have 1st guess rain number where mass non-zero but no number. - where(qr .LE. 0.0) nr=0.0 - where(qr .GT. 0 .and. nr .LE. 0.0) nr = make_RainNumber(qr*rho, tgrs) * orho - where(qr .EQ. 0.0 .and. nr .GT. 0.0) nr=0.0 - - if (is_hail_aware) then - where(qg .LE. 0.0) chw=0.0 - where(qg .LE. 0.0) vh=0.0 - endif - - !..Check for existing aerosol data, both CCN and IN aerosols. If missing - !.. fill in just a basic vertical profile, somewhat boundary-layer following. + ! Check for existing aerosol data, both CCN and IN aerosols. If missing + ! fill in just a basic vertical profile, somewhat boundary-layer following. if (is_aerosol_aware) then ! Potential cloud condensation nuclei (CCN) if (MAXVAL(nwfa) .lt. eps) then - if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial CCN aerosols.' + if (mpirank==mpiroot) write(*,*) ' There are no initial CCN aerosols. A basic vertical profile will be created.' do i = 1, ncol if (hgt(i,1).le.1000.0) then h_01 = 0.8 @@ -266,30 +142,28 @@ subroutine mp_tempo_init(ncol, nlev, con_pi, con_t0c, con_rv, & enddo enddo else - if (mpirank==mpiroot) write(*,*) ' Apparently initial CCN aerosols are present.' + if (mpirank==mpiroot) write(*,*) ' Initial CCN aerosols are present.' if (MAXVAL(nwfa2d) .lt. eps) then !+---+-----------------------------------------------------------------+ !..Scale the lowest level aerosol data into an emissions rate. This is !.. very far from ideal, but need higher emissions where larger amount !.. of (climo) existing and lesser emissions where there exists fewer to !.. begin as a first-order simplistic approach. Later, proper connection to - !.. emission inventory would be better, but, for now, scale like this: - !.. where: Nwfa=50 per cc, emit 0.875E4 aerosols per second per grid box unit - !.. that was tested as ~(20kmx20kmx50m = 2.E10 m**-3) + !.. emission inventory would be better. !+---+-----------------------------------------------------------------+ - if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial CCN aerosol surface emission rates.' + if (mpirank==mpiroot) write(*,*) ' There are no initial CCN aerosol surface emission rates. Rates will be created from surface values.' do i = 1, ncol z1 = hgt(i,2)-hgt(i,1) - nwfa2d(i) = nwfa(i,1) * 0.000196 * (50./z1) + nwfa2d(i) = nwfa(i,1) * 0.000196 * (5./z1) enddo else - if (mpirank==mpiroot) write(*,*) ' Apparently initial CCN aerosol surface emission rates are present.' + if (mpirank==mpiroot) write(*,*) ' Initial CCN aerosol surface emission rates are present.' endif endif ! Potential ice nuclei (IN) if (MAXVAL(nifa) .lt. eps) then - if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial IN aerosols.' + if (mpirank==mpiroot) write(*,*) ' There are no initial IN aerosols. A basic vertical profile will be created.' do i = 1, ncol if (hgt(i,1).le.1000.0) then h_01 = 0.8 @@ -306,58 +180,23 @@ subroutine mp_tempo_init(ncol, nlev, con_pi, con_t0c, con_rv, & enddo enddo else - if (mpirank==mpiroot) write(*,*) ' Apparently initial IN aerosols are present.' + if (mpirank==mpiroot) write(*,*) ' Initial IN aerosols are present.' if (MAXVAL(nifa2d) .lt. eps) then - if (mpirank==mpiroot) write(*,*) ' Apparently there are no initial IN aerosol surface emission rates, set to zero.' + if (mpirank==mpiroot) write(*,*) ' There are no initial IN aerosol surface emission rates. Rates will be set to zero.' ! calculate IN surface flux here, right now just set to zero nifa2d = 0. else - if (mpirank==mpiroot) write(*,*) ' Apparently initial IN aerosol surface emission rates are present.' + if (mpirank==mpiroot) write(*,*) ' Initial IN aerosol surface emission rates are present.' endif endif - ! Ensure we have 1st guess cloud droplet number where mass non-zero but no number. - where(qc .LE. 0.0) nc=0.0 - where(qc .GT. 0 .and. nc .LE. 0.0) nc = make_DropletNumber(qc*rho, nwfa*rho) * orho - where(qc .EQ. 0.0 .and. nc .GT. 0.0) nc = 0.0 - ! Ensure non-negative aerosol number concentrations. where(nwfa .LE. 0.0) nwfa = 1.1E6 where(nifa .LE. 0.0) nifa = naIN1*0.01 - - ! Copy to local array for calculating cloud effective radii below - nc_local = nc - - else if (merra2_aerosol_aware) then - - ! Ensure we have 1st guess cloud droplet number where mass non-zero but no number. - where(qc .LE. 0.0) nc=0.0 - where(qc .GT. 0 .and. nc .LE. 0.0) nc = make_DropletNumber(qc*rho, nwfa*rho) * orho - where(qc .EQ. 0.0 .and. nc .GT. 0.0) nc = 0.0 - - else - - ! Constant droplet concentration for single moment cloud water as in - ! module_mp_thompson.F90, only needed for effective radii calculation - nc_local = Nt_c_l/rho - end if if (convert_dry_rho) then - !qc = qc/(1.0_kind_phys+qv) - !qr = qr/(1.0_kind_phys+qv) - !qi = qi/(1.0_kind_phys+qv) - !qs = qs/(1.0_kind_phys+qv) - !qg = qg/(1.0_kind_phys+qv) - - ni = ni/(1.0_kind_phys+qv) - nr = nr/(1.0_kind_phys+qv) - if (is_hail_aware) then - chw = chw/(1.0_kind_phys+qv) - vh = vh/(1.0_kind_phys+qv) - endif - if (is_aerosol_aware .or. merra2_aerosol_aware) then - nc = nc/(1.0_kind_phys+qv) + if (is_aerosol_aware) then nwfa = nwfa/(1.0_kind_phys+qv) nifa = nifa/(1.0_kind_phys+qv) end if @@ -372,35 +211,21 @@ end subroutine mp_tempo_init !! \htmlinclude mp_tempo_run.html !! !>\ingroup aatempo -!>\section gen_tempo_hrrr TEMPO MP General Algorithm -!>@{ - subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & - con_eps, convert_dry_rho, & - spechum, qc, qr, qi, qs, qg, ni, nr, & - chw, vh, & - is_aerosol_aware, is_hail_aware, & - merra2_aerosol_aware, nc, nwfa, nifa,& - nwfa2d, nifa2d, aero_ind_fdb, & - tgrs, prsl, phii, omega, & - sedi_semi, decfl, islmsk, dtp, & - dt_inner, & - first_time_step, istep, nsteps, & - prcp, rain, graupel, ice, snow, sr, & - refl_10cm, fullradar_diag, & - max_hail_diam_sfc, & - do_radar_ref, aerfld, & - mpicomm, mpirank, mpiroot, blkno, & - ext_diag, diag3d, reset_diag3d, & - spp_wts_mp, spp_mp, n_var_spp, & - spp_prt_list, spp_var_list, & - spp_stddev_cutoff, & - cplchm, pfi_lsan, pfl_lsan, & - is_initialized, errmsg, errflg) +!>\section gen_tempo TEMPO MP General Algorithm + subroutine mp_tempo_run(ncol, nlev, & + mpicomm, mpirank, mpiroot, blkno, & + convert_dry_rho, dtp, dt_inner, & + spechum, qc, qr, qi, qs, qg, ni, nr, & + nc, nwfa, nifa, nwfa2d, nifa2d, ng, volg, & + con_g, con_rd, con_eps, & + tgrs, prsl, phii, omega, & + is_aerosol_aware, is_hail_aware, & + is_initialized, tempo_cfgs, errmsg, errflg) - implicit none ! Interface variables - logical, intent(inout) :: is_initialized + logical, intent(in ) :: is_initialized + logical, intent(in ) :: convert_dry_rho ! Dimensions and constants integer, intent(in ) :: ncol integer, intent(in ) :: nlev @@ -408,7 +233,6 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & real(kind_phys), intent(in ) :: con_rd real(kind_phys), intent(in ) :: con_eps ! Hydrometeors - logical, intent(in ) :: convert_dry_rho real(kind_phys), intent(inout) :: spechum(:,:) real(kind_phys), intent(inout) :: qc(:,:) real(kind_phys), intent(inout) :: qr(:,:) @@ -417,72 +241,39 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & real(kind_phys), intent(inout) :: qg(:,:) real(kind_phys), intent(inout) :: ni(:,:) real(kind_phys), intent(inout) :: nr(:,:) - real(kind_phys), optional, intent(inout) :: chw(:,:), vh(:,:) - ! Aerosols - logical, intent(in) :: is_aerosol_aware, fullradar_diag - logical, intent(in) :: merra2_aerosol_aware, is_hail_aware real(kind_phys), optional, intent(inout) :: nc(:,:) real(kind_phys), optional, intent(inout) :: nwfa(:,:) real(kind_phys), optional, intent(inout) :: nifa(:,:) real(kind_phys), optional, intent(in ) :: nwfa2d(:) real(kind_phys), optional, intent(in ) :: nifa2d(:) - real(kind_phys), intent(in) :: aerfld(:,:,:) - logical, optional, intent(in ) :: aero_ind_fdb + real(kind_phys), optional, intent(inout) :: ng(:,:) + real(kind_phys), optional, intent(inout) :: volg(:,:) + logical, intent(in) :: is_aerosol_aware + logical, intent(in) :: is_hail_aware ! State variables and timestep information real(kind_phys), intent(inout) :: tgrs(:,:) real(kind_phys), intent(in ) :: prsl(:,:) real(kind_phys), intent(in ) :: phii(:,:) real(kind_phys), intent(in ) :: omega(:,:) - integer, intent(in ) :: islmsk(:) real(kind_phys), intent(in ) :: dtp - logical, intent(in ) :: first_time_step - integer, intent(in ) :: istep, nsteps real, intent(in ) :: dt_inner - ! Precip/rain/snow/graupel fall amounts and fraction of frozen precip - real(kind_phys), intent(inout) :: prcp(:) - real(kind_phys), intent(inout), optional :: rain(:) - real(kind_phys), intent(inout), optional :: graupel(:) - real(kind_phys), intent(inout), optional :: ice(:) - real(kind_phys), intent(inout), optional :: snow(:) - real(kind_phys), intent( out) :: sr(:) - ! Radar reflectivity - real(kind_phys), intent(inout) :: refl_10cm(:,:) - real(kind_phys), intent(inout) :: max_hail_diam_sfc(:) - logical, intent(in ) :: do_radar_ref - logical, intent(in) :: sedi_semi - integer, intent(in) :: decfl + ! logical, intent(in ) :: first_time_step ! MPI and block information integer, intent(in) :: blkno type(MPI_Comm), intent(in) :: mpicomm integer, intent(in) :: mpirank integer, intent(in) :: mpiroot - ! Extended diagnostic output - logical, intent(in) :: ext_diag - real(kind_phys), target, intent(inout), optional :: diag3d(:,:,:) - logical, intent(in) :: reset_diag3d - ! CCPP error handling character(len=*), intent( out) :: errmsg integer, intent( out) :: errflg - - ! SPP - integer, intent(in) :: spp_mp - integer, intent(in) :: n_var_spp - real(kind_phys), intent(in), optional :: spp_wts_mp(:,:) - real(kind_phys), intent(in), optional :: spp_prt_list(:) - character(len=10), intent(in), optional :: spp_var_list(:) - real(kind_phys), intent(in), optional :: spp_stddev_cutoff(:) - - logical, intent (in) :: cplchm - ! ice and liquid water 3d precipitation fluxes - only allocated if cplchm is .true. - real(kind=kind_phys), intent(inout), dimension(:,:), optional :: pfi_lsan - real(kind=kind_phys), intent(inout), dimension(:,:), optional :: pfl_lsan + type(ty_tempo_cfgs), intent(in) :: tempo_cfgs + type(ty_tempo_driver_diags) :: tempo_driver_diags ! Local variables - ! Reduced time step if subcycling is used - real(kind_phys) :: dtstep - integer :: ndt + ! ! Reduced time step if subcycling is used + ! real(kind_phys) :: dtstep + ! integer :: ndt ! Air density real(kind_phys) :: rho(1:ncol,1:nlev) !< kg m-3 ! Water vapor mixing ratio (instead of specific humidity) @@ -490,151 +281,70 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & ! Vertical velocity and level width real(kind_phys) :: w(1:ncol,1:nlev) !< m s-1 real(kind_phys) :: dz(1:ncol,1:nlev) !< m - ! Rain/snow/graupel fall amounts - real(kind_phys) :: rain_mp(1:ncol) ! mm, dummy, not used - real(kind_phys) :: graupel_mp(1:ncol) ! mm, dummy, not used - real(kind_phys) :: ice_mp(1:ncol) ! mm, dummy, not used - real(kind_phys) :: snow_mp(1:ncol) ! mm, dummy, not used - real(kind_phys) :: delta_rain_mp(1:ncol) ! mm - real(kind_phys) :: delta_graupel_mp(1:ncol) ! mm - real(kind_phys) :: delta_ice_mp(1:ncol) ! mm - real(kind_phys) :: delta_snow_mp(1:ncol) ! mm - real(kind_phys) :: pfils(1:ncol,1:nlev,1) - real(kind_phys) :: pflls(1:ncol,1:nlev,1) - ! Radar reflectivity - logical :: diagflag ! must be true if do_radar_ref is true, not used otherwise - integer :: do_radar_ref_mp ! integer instead of logical do_radar_ref - ! Effective cloud radii - turned off in CCPP (taken care off in radiation) - logical, parameter :: do_effective_radii = .false. - integer, parameter :: has_reqc = 0 - integer, parameter :: has_reqi = 0 - integer, parameter :: has_reqs = 0 - integer, parameter :: kme_stoch = 1 - integer :: spp_mp_opt - ! Dimensions used in mp_gt_driver + ! Dimensions integer :: ids,ide, jds,jde, kds,kde, & ims,ime, jms,jme, kms,kme, & its,ite, jts,jte, kts,kte - ! Pointer arrays for extended diagnostics - !real(kind_phys), dimension(:,:,:), pointer :: vts1 => null() - !real(kind_phys), dimension(:,:,:), pointer :: txri => null() - !real(kind_phys), dimension(:,:,:), pointer :: txrc => null() - real(kind_phys), dimension(:,:,:), pointer :: prw_vcdc => null() - real(kind_phys), dimension(:,:,:), pointer :: prw_vcde => null() - real(kind_phys), dimension(:,:,:), pointer :: tpri_inu => null() - real(kind_phys), dimension(:,:,:), pointer :: tpri_ide_d => null() - real(kind_phys), dimension(:,:,:), pointer :: tpri_ide_s => null() - real(kind_phys), dimension(:,:,:), pointer :: tprs_ide => null() - real(kind_phys), dimension(:,:,:), pointer :: tprs_sde_d => null() - real(kind_phys), dimension(:,:,:), pointer :: tprs_sde_s => null() - real(kind_phys), dimension(:,:,:), pointer :: tprg_gde_d => null() - real(kind_phys), dimension(:,:,:), pointer :: tprg_gde_s => null() - real(kind_phys), dimension(:,:,:), pointer :: tpri_iha => null() - real(kind_phys), dimension(:,:,:), pointer :: tpri_wfz => null() - real(kind_phys), dimension(:,:,:), pointer :: tpri_rfz => null() - real(kind_phys), dimension(:,:,:), pointer :: tprg_rfz => null() - real(kind_phys), dimension(:,:,:), pointer :: tprs_scw => null() - real(kind_phys), dimension(:,:,:), pointer :: tprg_scw => null() - real(kind_phys), dimension(:,:,:), pointer :: tprg_rcs => null() - real(kind_phys), dimension(:,:,:), pointer :: tprs_rcs => null() - real(kind_phys), dimension(:,:,:), pointer :: tprr_rci => null() - real(kind_phys), dimension(:,:,:), pointer :: tprg_rcg => null() - real(kind_phys), dimension(:,:,:), pointer :: tprw_vcd_c => null() - real(kind_phys), dimension(:,:,:), pointer :: tprw_vcd_e => null() - real(kind_phys), dimension(:,:,:), pointer :: tprr_sml => null() - real(kind_phys), dimension(:,:,:), pointer :: tprr_gml => null() - real(kind_phys), dimension(:,:,:), pointer :: tprr_rcg => null() - real(kind_phys), dimension(:,:,:), pointer :: tprr_rcs => null() - real(kind_phys), dimension(:,:,:), pointer :: tprv_rev => null() - real(kind_phys), dimension(:,:,:), pointer :: tten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: qvten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: qrten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: qsten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: qgten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: qiten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: niten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: nrten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: ncten3 => null() - real(kind_phys), dimension(:,:,:), pointer :: qcten3 => null() - + integer :: itimestep = 1 + ! Initialize the CCPP error handling variables errmsg = '' errflg = 0 - if (is_hail_aware .and. sedi_semi) then - write(errmsg, fmt='((a))') 'Cannot use hail-aware TEMPO with sedi_semi... plese set sedi_semi=.false.' - errflg = 1 - return - endif - - if (first_time_step .and. istep==1 .and. blkno==1) then - ! Check initialization state - if (.not.is_initialized) then - write(errmsg, fmt='((a))') 'mp_tempo_run called before mp_tempo_init' - errflg = 1 - return - end if - ! Check forr optional arguments of aerosol-aware microphysics - if (is_aerosol_aware .and. .not. (present(nc) .and. & - present(nwfa) .and. & - present(nifa) .and. & - present(nwfa2d) .and. & - present(nifa2d) )) then - write(errmsg,fmt='(*(a))') 'Logic error in mp_tempo_run:', & - ' aerosol-aware microphysics require all of the', & - ' following optional arguments:', & - ' nc, nwfa, nifa, nwfa2d, nifa2d' - errflg = 1 - return - else if (merra2_aerosol_aware .and. .not. (present(nc) .and. & - present(nwfa) .and. & - present(nifa) )) then - write(errmsg,fmt='(*(a))') 'Logic error in mp_tempo_run:', & - ' merra2 aerosol-aware microphysics require the', & - ' following optional arguments: nc, nwfa, nifa' - errflg = 1 - return - end if - ! Consistency cheecks - subcycling and inner loop at the same time are not supported - if (nsteps>1 .and. dt_inner < dtp) then - write(errmsg,'(*(a))') "Logic error: Subcycling and inner loop cannot be used at the same time" - errflg = 1 - return - else if (mpirank==mpiroot .and. nsteps>1) then - write(*,'(a,i0,a,a,f6.2,a)') 'TEMPO MP is using ', nsteps, ' substep(s) per time step with an ', & - 'effective time step of ', dtp/real(nsteps, kind=kind_phys), ' seconds' - else if (mpirank==mpiroot .and. dt_inner < dtp) then - ndt = max(nint(dtp/dt_inner),1) - write(*,'(a,i0,a,a,f6.2,a)') 'TEMPO MP is using ', ndt, ' inner loops per time step with an ', & - 'effective time step of ', dtp/real(ndt, kind=kind_phys), ' seconds' - end if - end if - - ! Set stochastic physics selection to apply all perturbations - if ( spp_mp==7 ) then - spp_mp_opt=7 - else - spp_mp_opt=0 - endif + ! if (first_time_step .and. istep==1 .and. blkno==1) then + ! ! Check initialization state + ! if (.not.is_initialized) then + ! write(errmsg, fmt='((a))') 'mp_tempo_run called before mp_tempo_init' + ! errflg = 1 + ! return + ! end if + ! ! Check forr optional arguments of aerosol-aware microphysics + ! if (is_aerosol_aware .and. .not. (present(nc) .and. & + ! present(nwfa) .and. & + ! present(nifa) .and. & + ! present(nwfa2d) .and. & + ! present(nifa2d) )) then + ! write(errmsg,fmt='(*(a))') 'Logic error in mp_tempo_run:', & + ! ' aerosol-aware microphysics require all of the', & + ! ' following optional arguments:', & + ! ' nc, nwfa, nifa, nwfa2d, nifa2d' + ! errflg = 1 + ! return + ! else if (merra2_aerosol_aware .and. .not. (present(nc) .and. & + ! present(nwfa) .and. & + ! present(nifa) )) then + ! write(errmsg,fmt='(*(a))') 'Logic error in mp_tempo_run:', & + ! ' merra2 aerosol-aware microphysics require the', & + ! ' following optional arguments: nc, nwfa, nifa' + ! errflg = 1 + ! return + ! end if + ! ! Consistency cheecks - subcycling and inner loop at the same time are not supported + ! if (nsteps>1 .and. dt_inner < dtp) then + ! write(errmsg,'(*(a))') "Logic error: Subcycling and inner loop cannot be used at the same time" + ! errflg = 1 + ! return + ! else if (mpirank==mpiroot .and. nsteps>1) then + ! write(*,'(a,i0,a,a,f6.2,a)') 'TEMPO MP is using ', nsteps, ' substep(s) per time step with an ', & + ! 'effective time step of ', dtp/real(nsteps, kind=kind_phys), ' seconds' + ! else if (mpirank==mpiroot .and. dt_inner < dtp) then + ! ndt = max(nint(dtp/dt_inner),1) + ! write(*,'(a,i0,a,a,f6.2,a)') 'TEMPO MP is using ', ndt, ' inner loops per time step with an ', & + ! 'effective time step of ', dtp/real(ndt, kind=kind_phys), ' seconds' + ! end if + ! end if ! Set reduced time step if subcycling is used - if (nsteps>1) then - dtstep = dtp/real(nsteps, kind=kind_phys) - else - dtstep = dtp - end if - if (merra2_aerosol_aware) then - call get_niwfa(aerfld, nifa, nwfa, ncol, nlev) - end if +! if (nsteps>1) then +! dtstep = dtp/real(nsteps, kind=kind_phys) +! else +! dtstep = dtp +! end if !> - Convert specific humidity to water vapor mixing ratio. !> - Also, hydrometeor variables are mass or number mixing ratio !> - either kg of species per kg of dry air, or per kg of (dry + vapor). - - ! DH* - do this only if istep == 1? Would be ok if it was - ! guaranteed that nothing else in the same subcycle group - ! was using these arrays, but it is somewhat dangerous. qv = spechum/(1.0_kind_phys-spechum) if (convert_dry_rho) then @@ -643,20 +353,18 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & qi = qi/(1.0_kind_phys-spechum) qs = qs/(1.0_kind_phys-spechum) qg = qg/(1.0_kind_phys-spechum) - ni = ni/(1.0_kind_phys-spechum) nr = nr/(1.0_kind_phys-spechum) if (is_hail_aware) then - chw = chw/(1.0_kind_phys-spechum) - vh = vh/(1.0_kind_phys-spechum) + ng = ng/(1.0_kind_phys-spechum) + volg = volg/(1.0_kind_phys-spechum) endif - if (is_aerosol_aware .or. merra2_aerosol_aware) then + if (is_aerosol_aware) then nc = nc/(1.0_kind_phys-spechum) nwfa = nwfa/(1.0_kind_phys-spechum) nifa = nifa/(1.0_kind_phys-spechum) end if end if - ! *DH !> - Density of air in kg m-3 rho = con_eps*prsl/(con_rd*tgrs*(qv+con_eps)) @@ -667,26 +375,6 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & !> - Layer width in m from geopotential in m2 s-2 dz = (phii(:,2:nlev+1) - phii(:,1:nlev)) / con_g - ! Accumulated values inside Thompson scheme, not used; - ! only use delta and add to inout variables (different units) - rain_mp = 0 - graupel_mp = 0 - ice_mp = 0 - snow_mp = 0 - delta_rain_mp = 0 - delta_graupel_mp = 0 - delta_ice_mp = 0 - delta_snow_mp = 0 - - ! Flags for calculating radar reflectivity; diagflag is redundant - if (do_radar_ref) then - diagflag = .true. - do_radar_ref_mp = 1 - else - diagflag = .false. - do_radar_ref_mp = 0 - end if - ! Set internal dimensions ids = 1 ims = 1 @@ -706,261 +394,23 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & kde = nlev kme = nlev kte = nlev - if(cplchm) then - pfi_lsan = 0.0 - pfl_lsan = 0.0 - end if - ! Set pointers for extended diagnostics - set_extended_diagnostic_pointers: if (ext_diag) then - if (reset_diag3d) then - diag3d = 0.0 - end if - !vts1 => diag3d(:,:,X:X) - !txri => diag3d(:,:,X:X) - !txrc => diag3d(:,:,X:X) - prw_vcdc => diag3d(:,:,1:1) - prw_vcde => diag3d(:,:,2:2) - tpri_inu => diag3d(:,:,3:3) - tpri_ide_d => diag3d(:,:,4:4) - tpri_ide_s => diag3d(:,:,5:5) - tprs_ide => diag3d(:,:,6:6) - tprs_sde_d => diag3d(:,:,7:7) - tprs_sde_s => diag3d(:,:,8:8) - tprg_gde_d => diag3d(:,:,9:9) - tprg_gde_s => diag3d(:,:,10:10) - tpri_iha => diag3d(:,:,11:11) - tpri_wfz => diag3d(:,:,12:12) - tpri_rfz => diag3d(:,:,13:13) - tprg_rfz => diag3d(:,:,14:14) - tprs_scw => diag3d(:,:,15:15) - tprg_scw => diag3d(:,:,16:16) - tprg_rcs => diag3d(:,:,17:17) - tprs_rcs => diag3d(:,:,18:18) - tprr_rci => diag3d(:,:,19:19) - tprg_rcg => diag3d(:,:,20:20) - tprw_vcd_c => diag3d(:,:,21:21) - tprw_vcd_e => diag3d(:,:,22:22) - tprr_sml => diag3d(:,:,23:23) - tprr_gml => diag3d(:,:,24:24) - tprr_rcg => diag3d(:,:,25:25) - tprr_rcs => diag3d(:,:,26:26) - tprv_rev => diag3d(:,:,27:27) - tten3 => diag3d(:,:,28:28) - qvten3 => diag3d(:,:,29:29) - qrten3 => diag3d(:,:,30:30) - qsten3 => diag3d(:,:,31:31) - qgten3 => diag3d(:,:,32:32) - qiten3 => diag3d(:,:,33:33) - niten3 => diag3d(:,:,34:34) - nrten3 => diag3d(:,:,35:35) - ncten3 => diag3d(:,:,36:36) - qcten3 => diag3d(:,:,37:37) - else - allocate(prw_vcdc (0,0,0)) - allocate(prw_vcde (0,0,0)) - allocate(tpri_inu (0,0,0)) - allocate(tpri_ide_d (0,0,0)) - allocate(tpri_ide_s (0,0,0)) - allocate(tprs_ide (0,0,0)) - allocate(tprs_sde_d (0,0,0)) - allocate(tprs_sde_s (0,0,0)) - allocate(tprg_gde_d (0,0,0)) - allocate(tprg_gde_s (0,0,0)) - allocate(tpri_iha (0,0,0)) - allocate(tpri_wfz (0,0,0)) - allocate(tpri_rfz (0,0,0)) - allocate(tprg_rfz (0,0,0)) - allocate(tprs_scw (0,0,0)) - allocate(tprg_scw (0,0,0)) - allocate(tprg_rcs (0,0,0)) - allocate(tprs_rcs (0,0,0)) - allocate(tprr_rci (0,0,0)) - allocate(tprg_rcg (0,0,0)) - allocate(tprw_vcd_c (0,0,0)) - allocate(tprw_vcd_e (0,0,0)) - allocate(tprr_sml (0,0,0)) - allocate(tprr_gml (0,0,0)) - allocate(tprr_rcg (0,0,0)) - allocate(tprr_rcs (0,0,0)) - allocate(tprv_rev (0,0,0)) - allocate(tten3 (0,0,0)) - allocate(qvten3 (0,0,0)) - allocate(qrten3 (0,0,0)) - allocate(qsten3 (0,0,0)) - allocate(qgten3 (0,0,0)) - allocate(qiten3 (0,0,0)) - allocate(niten3 (0,0,0)) - allocate(nrten3 (0,0,0)) - allocate(ncten3 (0,0,0)) - allocate(qcten3 (0,0,0)) - end if set_extended_diagnostic_pointers - !> - Call mp_gt_driver() with or without aerosols, with or without effective radii, ... - if (is_aerosol_aware) then - if (is_hail_aware) then - call tempo_3d_to_1d_driver(qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, qb=vh, ni=ni, nr=nr, & - nc=nc, ng=chw, nwfa=nwfa, nifa=nifa, nwfa2d=nwfa2d, nifa2d=nifa2d, & - tt=tgrs, p=prsl, w=w, dz=dz, dt_in=dtstep, dt_inner=dt_inner, & - sedi_semi=sedi_semi, decfl=decfl, lsm=islmsk, & - rainnc=rain_mp, rainncv=delta_rain_mp, & - snownc=snow_mp, snowncv=delta_snow_mp, & - icenc=ice_mp, icencv=delta_ice_mp, & - graupelnc=graupel_mp, graupelncv=delta_graupel_mp, sr=sr, & - refl_10cm=refl_10cm, & - diagflag=diagflag, do_radar_ref=do_radar_ref_mp, & - max_hail_diam_sfc=max_hail_diam_sfc, & - has_reqc=has_reqc, has_reqi=has_reqi, has_reqs=has_reqs, & - aero_ind_fdb=aero_ind_fdb, rand_perturb_on=spp_mp_opt, & - kme_stoch=kme_stoch, & - rand_pert=spp_wts_mp, spp_var_list=spp_var_list, & - spp_prt_list=spp_prt_list, n_var_spp=n_var_spp, & - spp_stddev_cutoff=spp_stddev_cutoff, & - ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & - ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & - its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - fullradar_diag=fullradar_diag, istep=istep, nsteps=nsteps, & - first_time_step=first_time_step, errmsg=errmsg, errflg=errflg, & - ! Extended diagnostics - ext_diag=ext_diag, pfils=pfils, pflls=pflls) - else - -! write(errmsg,'(*(a))') "TEMPO aerosol-aware UNTESTED -- DO NOT USE" -! errflg = 1 -! return - call tempo_3d_to_1d_driver(qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & - nc=nc, nwfa=nwfa, nifa=nifa, nwfa2d=nwfa2d, nifa2d=nifa2d, & - tt=tgrs, p=prsl, w=w, dz=dz, dt_in=dtstep, dt_inner=dt_inner, & - sedi_semi=sedi_semi, decfl=decfl, lsm=islmsk, & - rainnc=rain_mp, rainncv=delta_rain_mp, & - snownc=snow_mp, snowncv=delta_snow_mp, & - icenc=ice_mp, icencv=delta_ice_mp, & - graupelnc=graupel_mp, graupelncv=delta_graupel_mp, sr=sr, & - refl_10cm=refl_10cm, & - diagflag=diagflag, do_radar_ref=do_radar_ref_mp, & - max_hail_diam_sfc=max_hail_diam_sfc, & - has_reqc=has_reqc, has_reqi=has_reqi, has_reqs=has_reqs, & - aero_ind_fdb=aero_ind_fdb, rand_perturb_on=spp_mp_opt, & - kme_stoch=kme_stoch, & - rand_pert=spp_wts_mp, spp_var_list=spp_var_list, & - spp_prt_list=spp_prt_list, n_var_spp=n_var_spp, & - spp_stddev_cutoff=spp_stddev_cutoff, & - ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & - ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & - its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - fullradar_diag=fullradar_diag, istep=istep, nsteps=nsteps, & - first_time_step=first_time_step, errmsg=errmsg, errflg=errflg, & - ! Extended diagnostics - ext_diag=ext_diag, pfils=pfils, pflls=pflls) - ! ! vts1=vts1, txri=txri, txrc=txrc, & - ! prw_vcdc=prw_vcdc, & - ! prw_vcde=prw_vcde, tpri_inu=tpri_inu, tpri_ide_d=tpri_ide_d, & - ! tpri_ide_s=tpri_ide_s, tprs_ide=tprs_ide, & - ! tprs_sde_d=tprs_sde_d, & - ! tprs_sde_s=tprs_sde_s, tprg_gde_d=tprg_gde_d, & - ! tprg_gde_s=tprg_gde_s, tpri_iha=tpri_iha, & - ! tpri_wfz=tpri_wfz, tpri_rfz=tpri_rfz, tprg_rfz=tprg_rfz, & - ! tprs_scw=tprs_scw, tprg_scw=tprg_scw, tprg_rcs=tprg_rcs, & - ! tprs_rcs=tprs_rcs, & - ! tprr_rci=tprr_rci, tprg_rcg=tprg_rcg, tprw_vcd_c=tprw_vcd_c, & - ! tprw_vcd_e=tprw_vcd_e, tprr_sml=tprr_sml, tprr_gml=tprr_gml, & - ! tprr_rcg=tprr_rcg, tprr_rcs=tprr_rcs, & - ! tprv_rev=tprv_rev, tten3=tten3, & - ! qvten3=qvten3, qrten3=qrten3, qsten3=qsten3, qgten3=qgten3, & - ! qiten3=qiten3, niten3=niten3, nrten3=nrten3, ncten3=ncten3, & - ! qcten3=qcten3, - endif - else if (merra2_aerosol_aware) then - write(errmsg,'(*(a))') "TEMPO aerosol-aware with MERRA2 UNTESTED -- DO NOT USE" - errflg = 1 - return - call tempo_3d_to_1d_driver(qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & - nc=nc, nwfa=nwfa, nifa=nifa, & - tt=tgrs, p=prsl, w=w, dz=dz, dt_in=dtstep, dt_inner=dt_inner, & - sedi_semi=sedi_semi, decfl=decfl, lsm=islmsk, & - rainnc=rain_mp, rainncv=delta_rain_mp, & - snownc=snow_mp, snowncv=delta_snow_mp, & - icenc=ice_mp, icencv=delta_ice_mp, & - graupelnc=graupel_mp, graupelncv=delta_graupel_mp, sr=sr, & - refl_10cm=refl_10cm, & - diagflag=diagflag, do_radar_ref=do_radar_ref_mp, & - max_hail_diam_sfc=max_hail_diam_sfc, & - has_reqc=has_reqc, has_reqi=has_reqi, has_reqs=has_reqs, & - aero_ind_fdb=aero_ind_fdb, rand_perturb_on=spp_mp_opt, & - kme_stoch=kme_stoch, & - rand_pert=spp_wts_mp, spp_var_list=spp_var_list, & - spp_prt_list=spp_prt_list, n_var_spp=n_var_spp, & - spp_stddev_cutoff=spp_stddev_cutoff, & - ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & - ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & - its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - fullradar_diag=fullradar_diag, istep=istep, nsteps=nsteps, & - first_time_step=first_time_step, errmsg=errmsg, errflg=errflg, & - ! Extended diagnostics - ext_diag=ext_diag, pfils=pfils, pflls=pflls) - ! ! vts1=vts1, txri=txri, txrc=txrc, & - ! prw_vcdc=prw_vcdc, & - ! prw_vcde=prw_vcde, tpri_inu=tpri_inu, tpri_ide_d=tpri_ide_d, & - ! tpri_ide_s=tpri_ide_s, tprs_ide=tprs_ide, & - ! tprs_sde_d=tprs_sde_d, & - ! tprs_sde_s=tprs_sde_s, tprg_gde_d=tprg_gde_d, & - ! tprg_gde_s=tprg_gde_s, tpri_iha=tpri_iha, & - ! tpri_wfz=tpri_wfz, tpri_rfz=tpri_rfz, tprg_rfz=tprg_rfz, & - ! tprs_scw=tprs_scw, tprg_scw=tprg_scw, tprg_rcs=tprg_rcs, & - ! tprs_rcs=tprs_rcs, & - ! tprr_rci=tprr_rci, tprg_rcg=tprg_rcg, tprw_vcd_c=tprw_vcd_c, & - ! tprw_vcd_e=tprw_vcd_e, tprr_sml=tprr_sml, tprr_gml=tprr_gml, & - ! tprr_rcg=tprr_rcg, tprr_rcs=tprr_rcs, & - ! tprv_rev=tprv_rev, tten3=tten3, & - ! qvten3=qvten3, qrten3=qrten3, qsten3=qsten3, qgten3=qgten3, & - ! qiten3=qiten3, niten3=niten3, nrten3=nrten3, ncten3=ncten3, & - ! qcten3=qcten3, - else - call tempo_3d_to_1d_driver(qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & - tt=tgrs, p=prsl, w=w, dz=dz, dt_in=dtstep, dt_inner=dt_inner, & - sedi_semi=sedi_semi, decfl=decfl, lsm=islmsk, & - rainnc=rain_mp, rainncv=delta_rain_mp, & - snownc=snow_mp, snowncv=delta_snow_mp, & - icenc=ice_mp, icencv=delta_ice_mp, & - graupelnc=graupel_mp, graupelncv=delta_graupel_mp, sr=sr, & - refl_10cm=refl_10cm, & - diagflag=diagflag, do_radar_ref=do_radar_ref_mp, & - max_hail_diam_sfc=max_hail_diam_sfc, & - has_reqc=has_reqc, has_reqi=has_reqi, has_reqs=has_reqs, & - rand_perturb_on=spp_mp_opt, kme_stoch=kme_stoch, & - rand_pert=spp_wts_mp, spp_var_list=spp_var_list, & - spp_prt_list=spp_prt_list, n_var_spp=n_var_spp, & - spp_stddev_cutoff=spp_stddev_cutoff, & - ids=ids, ide=ide, jds=jds, jde=jde, kds=kds, kde=kde, & - ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, & - its=its, ite=ite, jts=jts, jte=jte, kts=kts, kte=kte, & - fullradar_diag=fullradar_diag, istep=istep, nsteps=nsteps, & - first_time_step=first_time_step, errmsg=errmsg, errflg=errflg, & - ! Extended diagnostics - ext_diag=ext_diag, pfils=pfils, pflls=pflls) - !! vts1=vts1, txri=txri, txrc=txrc, & - ! prw_vcdc=prw_vcdc, & - ! prw_vcde=prw_vcde, tpri_inu=tpri_inu, tpri_ide_d=tpri_ide_d, & - ! tpri_ide_s=tpri_ide_s, tprs_ide=tprs_ide, & - ! tprs_sde_d=tprs_sde_d, & - ! tprs_sde_s=tprs_sde_s, tprg_gde_d=tprg_gde_d, & - ! tprg_gde_s=tprg_gde_s, tpri_iha=tpri_iha, & - ! tpri_wfz=tpri_wfz, tpri_rfz=tpri_rfz, tprg_rfz=tprg_rfz, & - ! tprs_scw=tprs_scw, tprg_scw=tprg_scw, tprg_rcs=tprg_rcs, & - ! tprs_rcs=tprs_rcs, & - ! tprr_rci=tprr_rci, tprg_rcg=tprg_rcg, tprw_vcd_c=tprw_vcd_c, & - ! tprw_vcd_e=tprw_vcd_e, tprr_sml=tprr_sml, tprr_gml=tprr_gml, & - ! tprr_rcg=tprr_rcg, tprr_rcs=tprr_rcs, & - ! tprv_rev=tprv_rev, tten3=tten3, & - ! qvten3=qvten3, qrten3=qrten3, qsten3=qsten3, qgten3=qgten3, & - ! qiten3=qiten3, niten3=niten3, nrten3=nrten3, ncten3=ncten3, & - ! qcten3=qcten3) - end if + !ADD AEROSOL SOURCE/SINKS HERE + + call tempo_run(tempo_cfgs=tempo_cfgs, & + dt=dt_inner, itimestep=itimestep , & + qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & + w=w, t=tgrs, p=prsl, dz=dz, & + ids = ids , ide = ide , jds = jds , jde = jde , kds = kds , kde = kde , & + ims = ims , ime = ime , jms = jms , jme = jme , kms = kms , kme = kme , & + its = its , ite = ite , jts = jts , jte = jte , kts = kts , kte = kte , & + tempo_diags=tempo_driver_diags) + + if (mpirank==mpiroot) write(*,*) 'Calling tempo_run() with itimestep = ', itimestep + itimestep = itimestep + 1 + if (errflg/=0) return - ! DH* - do this only if istep == nsteps? Would be ok if it was - ! guaranteed that nothing else in the same subcycle group - ! was using these arrays, but it is somewhat dangerous. - !> - Convert water vapor mixing ratio back to specific humidity spechum = qv/(1.0_kind_phys+qv) @@ -970,98 +420,26 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & qi = qi/(1.0_kind_phys+qv) qs = qs/(1.0_kind_phys+qv) qg = qg/(1.0_kind_phys+qv) - ni = ni/(1.0_kind_phys+qv) nr = nr/(1.0_kind_phys+qv) if (is_hail_aware) then - chw = chw/(1.0_kind_phys+qv) - vh = vh/(1.0_kind_phys+qv) + ng = ng/(1.0_kind_phys+qv) + volg = volg/(1.0_kind_phys+qv) endif - if (is_aerosol_aware .or. merra2_aerosol_aware) then + if (is_aerosol_aware) then nc = nc/(1.0_kind_phys+qv) nwfa = nwfa/(1.0_kind_phys+qv) nifa = nifa/(1.0_kind_phys+qv) end if end if - ! *DH - - !> - Convert rainfall deltas from mm to m (on physics timestep); add to inout variables - ! "rain" in Thompson MP refers to precipitation (total of liquid rainfall+snow+graupel+ice) - prcp = prcp + max(0.0, delta_rain_mp/1000.0_kind_phys) - graupel = graupel + max(0.0, delta_graupel_mp/1000.0_kind_phys) - ice = ice + max(0.0, delta_ice_mp/1000.0_kind_phys) - snow = snow + max(0.0, delta_snow_mp/1000.0_kind_phys) - rain = rain + max(0.0, (delta_rain_mp - (delta_graupel_mp + delta_ice_mp + delta_snow_mp))/1000.0_kind_phys) - - ! Recompute sr at last subcycling step - if (nsteps>1 .and. istep == nsteps) then - ! Unlike inside mp_gt_driver, rain does not contain frozen precip - sr = (snow + graupel + ice)/(rain + snow + graupel + ice +1.e-12) - end if - - ! output instantaneous ice/snow and rain water 3d precipitation fluxes - if(cplchm) then - pfi_lsan(:,:) = pfils(:,:,1) - pfl_lsan(:,:) = pflls(:,:,1) - end if - - ! DH* Not really needed because they go out of scope ... - ! But having them in here seems to cause problems with Intel? - ! It looked like this is also nullifying the pointers passed - ! from the CCPP caps. - !unset_extended_diagnostic_pointers: if (ext_diag) then - ! !vts1 => null() - ! !txri => null() - ! !txrc => null() - ! prw_vcdc => null() - ! prw_vcde => null() - ! tpri_inu => null() - ! tpri_ide_d => null() - ! tpri_ide_s => null() - ! tprs_ide => null() - ! tprs_sde_d => null() - ! tprs_sde_s => null() - ! tprg_gde_d => null() - ! tprg_gde_s => null() - ! tpri_iha => null() - ! tpri_wfz => null() - ! tpri_rfz => null() - ! tprg_rfz => null() - ! tprs_scw => null() - ! tprg_scw => null() - ! tprg_rcs => null() - ! tprs_rcs => null() - ! tprr_rci => null() - ! tprg_rcg => null() - ! tprw_vcd_c => null() - ! tprw_vcd_e => null() - ! tprr_sml => null() - ! tprr_gml => null() - ! tprr_rcg => null() - ! tprr_rcs => null() - ! tprv_rev => null() - ! tten3 => null() - ! qvten3 => null() - ! qrten3 => null() - ! qsten3 => null() - ! qgten3 => null() - ! qiten3 => null() - ! niten3 => null() - ! nrten3 => null() - ! ncten3 => null() - ! qcten3 => null() - !end if unset_extended_diagnostic_pointers - ! *DH end subroutine mp_tempo_run -!>@} !> \section arg_table_mp_tempo_finalize Argument Table !! \htmlinclude mp_tempo_finalize.html !! subroutine mp_tempo_finalize(is_initialized, errmsg, errflg) - - implicit none + logical, intent(inout) :: is_initialized character(len=*), intent( out) :: errmsg integer, intent( out) :: errflg @@ -1072,55 +450,8 @@ subroutine mp_tempo_finalize(is_initialized, errmsg, errflg) if (.not.is_initialized) return - call tempo_finalize() - is_initialized = .false. end subroutine mp_tempo_finalize - subroutine get_niwfa(aerfld, nifa, nwfa, ncol, nlev) - ! To calculate nifa and nwfa from bins of aerosols. - ! In GOCART and MERRA2, aerosols are given as mixing ratio (kg/kg). To - ! convert from kg/kg to #/kg, the "unit mass" (mass of one particle) - ! within the mass bins is calculated. A lognormal size distribution - ! within aerosol bins is used to find the size based upon the median - ! mass. NIFA is mainly summarized over five dust bins and NWFA over the - ! other 10 bins. The parameters besides each bins are carefully tuned - ! for a good performance of the scheme. - ! - ! The fields for the last index of the aerfld array - ! are specified as below. - ! 1: dust bin 1, 0.1 to 1.0 micrometers - ! 2: dust bin 2, 1.0 to 1.8 micrometers - ! 3: dust bin 3, 1.8 to 3.0 micrometers - ! 4: dust bin 4, 3.0 to 6.0 micrometers - ! 5: dust bin 5, 6.0 to 10.0 micrometers - ! 6: sea salt bin 1, 0.03 to 0.1 micrometers - ! 7: sea salt bin 2, 0.1 to 0.5 micrometers - ! 8: sea salt bin 3, 0.5 to 1.5 micrometers - ! 9: sea salt bin 4, 1.5 to 5.0 micrometers - ! 10: sea salt bin 5, 5.0 to 10.0 micrometers - ! 11: Sulfate, 0.35 (mean) micrometers - ! 15: water-friendly organic carbon, 0.35 (mean) micrometers - ! - ! Bin densities are as follows: - ! 1: dust bin 1: 2500 kg/m2 - ! 2-5: dust bin 2-5: 2650 kg/m2 - ! 6-10: sea salt bins 6-10: 2200 kg/m2 - ! 11: sulfate: 1700 kg/m2 - ! 15: organic carbon: 1800 kg/m2 - - implicit none - integer, intent(in)::ncol, nlev - real (kind=kind_phys), dimension(:,:,:), intent(in) :: aerfld - real (kind=kind_phys), dimension(:,:), intent(out ):: nifa, nwfa - - nifa=(aerfld(:,:,1)/4.0737762+aerfld(:,:,2)/30.459203+aerfld(:,:,3)/153.45048+ & - aerfld(:,:,4)/1011.5142+ aerfld(:,:,5)/5683.3501)*1.e15 - - nwfa=((aerfld(:,:,6)/0.0045435214+aerfld(:,:,7)/0.2907854+aerfld(:,:,8)/12.91224+ & - aerfld(:,:,9)/206.2216+ aerfld(:,:,10)/4326.23)*9.+aerfld(:,:,11)/0.3053104*5+ & - aerfld(:,:,15)/0.3232698*8)*1.e15 - end subroutine get_niwfa - end module mp_tempo diff --git a/physics/MP/TEMPO/mp_tempo.meta b/physics/MP/TEMPO/mp_tempo.meta index 0bac3e856..65abcd8d6 100644 --- a/physics/MP/TEMPO/mp_tempo.meta +++ b/physics/MP/TEMPO/mp_tempo.meta @@ -2,12 +2,15 @@ name = mp_tempo type = scheme dependencies = ../../hooks/machine.F - dependencies = ../module_mp_radar.F90 - dependencies = TEMPO/module_mp_tempo_params.F90 - dependencies = TEMPO/module_mp_tempo_utils.F90 - dependencies = TEMPO/module_mp_tempo_main.F90 - dependencies = module_mp_tempo.F90 - + dependencies = tempo_v3/src/module_mp_tempo_params.F90 + dependencies = tempo_v3/src/module_mp_tempo_cfgs.F90 + dependencies = tempo_v3/src/module_mp_tempo_ml.F90 + dependencies = tempo_v3/src/module_mp_tempo_utils.F90 + dependencies = tempo_v3/src/module_mp_tempo_aerosols.F90 + dependencies = tempo_v3/src/module_mp_tempo_diags.F90 + dependencies = tempo_v3/src/module_mp_tempo_main.F90 + dependencies = tempo_v3/src/module_mp_tempo_driver.F90 + ######################################################################## [ccpp-arg-table] name = mp_tempo_init @@ -26,93 +29,62 @@ dimensions = () type = integer intent = in -[con_pi] - standard_name = pi - long_name = ratio of a circle's circumference to its diameter - units = none - dimensions = () - type = real - kind = kind_phys - intent = in -[con_t0c] - standard_name = temperature_at_zero_celsius - long_name = temperature at 0 degrees Celsius - units = K - dimensions = () - type = real - kind = kind_phys - intent = in -[con_rv] - standard_name = gas_constant_water_vapor - long_name = ideal gas constant for water vapor - units = J kg-1 K-1 - dimensions = () - type = real - kind = kind_phys - intent = in -[con_cp] - standard_name = specific_heat_of_dry_air_at_constant_pressure - long_name = specific heat of dry air at constant pressure - units = J kg-1 K-1 +[is_initialized] + standard_name = flag_for_tempo_mp_scheme_initialization + long_name = flag carrying scheme initialization status + units = flag dimensions = () - type = real - kind = kind_phys - intent = in -[con_rgas] - standard_name = molar_gas_constant - long_name = universal ideal molar gas constant - units = J K-1 mol-1 + type = logical + intent = inout +[errmsg] + standard_name = ccpp_error_message + long_name = error message for error handling in CCPP + units = none dimensions = () - type = real - kind = kind_phys - intent = in -[con_boltz] - standard_name = boltzmann_constant - long_name = Boltzmann constant - units = J K-1 + type = character + kind = len=* + intent = out +[errflg] + standard_name = ccpp_error_code + long_name = error code for error handling in CCPP + units = 1 dimensions = () - type = real - kind = kind_phys - intent = in -[con_amd] - standard_name = molecular_weight_of_dry_air - long_name = molecular weight of dry air - units = g mol-1 + type = integer + intent = out +[imp_physics] + standard_name = control_for_microphysics_scheme + long_name = choice of microphysics scheme + units = flag dimensions = () - type = real - kind = kind_phys + type = integer intent = in -[con_amw] - standard_name = molecular_weight_of_water_vapor - long_name = molecular weight of water vapor - units = g mol-1 +[imp_physics_tempo] + standard_name = identifier_for_tempo_microphysics_scheme + long_name = choice of TEMPO microphysics scheme + units = flag dimensions = () - type = real - kind = kind_phys + type = integer intent = in -[con_avgd] - standard_name = avogadro_consant - long_name = Avogadro constant - units = mol-1 +[mpicomm] + standard_name = mpi_communicator + long_name = MPI communicator + units = index dimensions = () - type = real - kind = kind_phys + type = MPI_Comm intent = in -[con_hvap] - standard_name = latent_heat_of_vaporization_of_water_at_0C - long_name = latent heat of evaporation/sublimation - units = J kg-1 +[mpirank] + standard_name = mpi_rank + long_name = current MPI-rank + units = index dimensions = () - type = real - kind = kind_phys + type = integer intent = in -[con_hfus] - standard_name = latent_heat_of_fusion_of_water_at_0C - long_name = latent heat of fusion - units = J kg-1 +[mpiroot] + standard_name = mpi_root + long_name = master MPI-rank + units = index dimensions = () - type = real - kind = kind_phys + type = integer intent = in [con_g] standard_name = gravitational_acceleration @@ -145,20 +117,6 @@ dimensions = () type = logical intent = in -[imp_physics] - standard_name = control_for_microphysics_scheme - long_name = choice of microphysics scheme - units = flag - dimensions = () - type = integer - intent = in -[imp_physics_tempo] - standard_name = identifier_for_tempo_microphysics_scheme - long_name = choice of TEMPO microphysics scheme - units = flag - dimensions = () - type = integer - intent = in [convert_dry_rho] standard_name = flag_for_converting_hydrometeors_from_moist_to_dry_air long_name = flag for converting hydrometeors from moist to dry air @@ -166,88 +124,6 @@ dimensions = () type = logical intent = in -[spechum] - standard_name = specific_humidity - long_name = water vapor specific humidity - units = kg kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout -[qc] - standard_name = cloud_liquid_water_mixing_ratio - long_name = cloud water mixing ratio wrt dry+vapor (no condensates) - units = kg kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout -[qr] - standard_name = rain_mixing_ratio - long_name = rain water mixing ratio wrt dry+vapor (no condensates) - units = kg kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout -[qi] - standard_name = cloud_ice_mixing_ratio - long_name = ice water mixing ratio wrt dry+vapor (no condensates) - units = kg kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout -[qs] - standard_name = snow_mixing_ratio - long_name = snow water mixing ratio wrt dry+vapor (no condensates) - units = kg kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout -[qg] - standard_name = graupel_mixing_ratio - long_name = graupel mixing ratio wrt dry+vapor (no condensates) - units = kg kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout -[chw] - standard_name = mass_number_concentration_of_graupel_in_air - long_name = graupel number concentration - units = kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout - optional = True -[vh] - standard_name = graupel_volume - long_name = graupel particle volume - units = m3 kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout - optional = True -[ni] - standard_name = mass_number_concentration_of_cloud_ice_water_crystals_in_air - long_name = ice number concentration - units = kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout -[nr] - standard_name = mass_number_concentration_of_rain_water_in_air - long_name = rain number concentration - units = kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout [is_aerosol_aware] standard_name = flag_for_aerosol_physics long_name = flag for aerosol-aware physics @@ -262,22 +138,28 @@ dimensions = () type = logical intent = in -[merra2_aerosol_aware] - standard_name = do_merra2_aerosol_awareness - long_name = flag for merra2 aerosol-aware physics for example the thompson microphysics +[semi_sedi] + standard_name = flag_for_semi_Lagrangian_sedi_rain + long_name = flag for semi Lagrangian sedi of rain units = flag dimensions = () type = logical intent = in -[nc] - standard_name = mass_number_concentration_of_cloud_liquid_water_particles_in_air - long_name = cloud droplet number concentration - units = kg-1 +[do_sat_adj] + standard_name = flag_for_saturation_adjustment_for_microphysics_in_dynamics + long_name = flag for saturation adjustment for microphysics in dynamics + units = none + dimensions = () + type = logical + intent = in +[spechum] + standard_name = specific_humidity + long_name = water vapor specific humidity + units = kg kg-1 dimensions = (horizontal_dimension,vertical_layer_dimension) type = real kind = kind_phys intent = inout - optional = True [nwfa2d] standard_name = tendency_of_hygroscopic_aerosols_at_surface_adjacent_layer long_name = instantaneous fake water-friendly surface aerosol source @@ -314,6 +196,13 @@ kind = kind_phys intent = inout optional = True +[tempo_cfgs] + standard_name = configuration_for_TEMPO_microphysics + long_name = configuration information for TEMPO microphysics + units = mixed + dimensions = () + intent = inout + type = ty_tempo_cfgs [tgrs] standard_name = air_temperature long_name = model layer mean temperature @@ -338,21 +227,24 @@ type = real kind = kind_phys intent = in -[area] - standard_name = cell_area - long_name = area of the grid cell - units = m2 - dimensions = (horizontal_dimension) - type = real - kind = kind_phys + +######################################################################## +[ccpp-arg-table] + name = mp_tempo_run + type = scheme +[ncol] + standard_name = horizontal_loop_extent + long_name = horizontal loop extent + units = count + dimensions = () + type = integer intent = in -[aerfld] - standard_name = mass_mixing_ratio_of_aerosol_from_gocart_or_merra2 - long_name = mass mixing ratio of aerosol from gocart or merra2 - units = kg kg-1 - dimensions = (horizontal_dimension,vertical_layer_dimension,number_of_aerosol_tracers_MG) - type = real - kind = kind_phys +[nlev] + standard_name = vertical_layer_dimension + long_name = number of vertical levels + units = count + dimensions = () + type = integer intent = in [mpicomm] standard_name = mpi_communicator @@ -375,36 +267,20 @@ dimensions = () type = integer intent = in -[threads] - standard_name = number_of_openmp_threads - long_name = number of OpenMP threads available to scheme - units = count +[blkno] + standard_name = ccpp_block_number + long_name = number of block for explicit data blocking in CCPP + units = index dimensions = () type = integer intent = in -[ext_diag] - standard_name = flag_for_extended_diagnostic_output_from_thompson_microphysics - long_name = flag for extended diagnostic output from thompson microphysics - units = flag - dimensions = () - type = logical - intent = in -[diag3d] - standard_name = extended_diagnostics_output_from_thompson_microphysics - long_name = set of 3d arrays for extended diagnostics output from thompson microphysics - units = none - dimensions = (horizontal_dimension,vertical_layer_dimension,number_of_3d_diagnostic_output_arrays_from_thompson_microphysics) - type = real - kind = kind_phys - intent = in - optional = True [is_initialized] - standard_name = flag_for_thompson_mp_scheme_initialization + standard_name = flag_for_tempo_mp_scheme_initialization long_name = flag carrying scheme initialization status units = flag dimensions = () type = logical - intent = inout + intent = in [errmsg] standard_name = ccpp_error_message long_name = error message for error handling in CCPP @@ -420,49 +296,6 @@ dimensions = () type = integer intent = out - -######################################################################## -[ccpp-arg-table] - name = mp_tempo_run - type = scheme -[ncol] - standard_name = horizontal_loop_extent - long_name = horizontal loop extent - units = count - dimensions = () - type = integer - intent = in -[nlev] - standard_name = vertical_layer_dimension - long_name = number of vertical levels - units = count - dimensions = () - type = integer - intent = in -[con_g] - standard_name = gravitational_acceleration - long_name = gravitational acceleration - units = m s-2 - dimensions = () - type = real - kind = kind_phys - intent = in -[con_rd] - standard_name = gas_constant_of_dry_air - long_name = ideal gas constant for dry air - units = J kg-1 K-1 - dimensions = () - type = real - kind = kind_phys - intent = in -[con_eps] - standard_name = ratio_of_dry_air_to_water_vapor_gas_constants - long_name = rd/rv - units = none - dimensions = () - type = real - kind = kind_phys - intent = in [convert_dry_rho] standard_name = flag_for_converting_hydrometeors_from_moist_to_dry_air long_name = flag for converting hydrometeors from moist to dry air @@ -518,24 +351,6 @@ type = real kind = kind_phys intent = inout -[chw] - standard_name = mass_number_concentration_of_graupel_of_new_state - long_name = graupel number concentration - units = kg-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout - optional = True -[vh] - standard_name = graupel_volume_of_new_state - long_name = graupel particle volume - units = m3 kg-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout - optional = True [ni] standard_name = mass_number_concentration_of_cloud_ice_water_crystals_in_air_of_new_state long_name = ice number concentration @@ -552,27 +367,6 @@ type = real kind = kind_phys intent = inout -[is_aerosol_aware] - standard_name = flag_for_aerosol_physics - long_name = flag for aerosol-aware physics - units = flag - dimensions = () - type = logical - intent = in -[is_hail_aware] - standard_name = flag_for_hail_physics - long_name = flag for hail-aware physics - units = flag - dimensions = () - type = logical - intent = in -[merra2_aerosol_aware] - standard_name = do_merra2_aerosol_awareness - long_name = flag for merra2 aerosol-aware physics for example the thompson microphysics - units = flag - dimensions = () - type = logical - intent = in [nc] standard_name = mass_number_concentration_of_cloud_liquid_water_particles_in_air_of_new_state long_name = cloud droplet number concentration @@ -618,12 +412,47 @@ kind = kind_phys intent = in optional = True -[aero_ind_fdb] - standard_name = do_smoke_aerosol_indirect_feedback - long_name = flag for wfa ifa emission indirect feedback - units = flag +[ng] + standard_name = mass_number_concentration_of_graupel_of_new_state + long_name = graupel number concentration + units = kg-1 + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + type = real + kind = kind_phys + intent = inout + optional = True +[volg] + standard_name = graupel_volume_of_new_state + long_name = graupel particle volume + units = m3 kg-1 + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + type = real + kind = kind_phys + intent = inout + optional = True +[con_g] + standard_name = gravitational_acceleration + long_name = gravitational acceleration + units = m s-2 dimensions = () - type = logical + type = real + kind = kind_phys + intent = in +[con_rd] + standard_name = gas_constant_of_dry_air + long_name = ideal gas constant for dry air + units = J kg-1 K-1 + dimensions = () + type = real + kind = kind_phys + intent = in +[con_eps] + standard_name = ratio_of_dry_air_to_water_vapor_gas_constants + long_name = rd/rv + units = none + dimensions = () + type = real + kind = kind_phys intent = in [tgrs] standard_name = air_temperature_of_new_state @@ -657,27 +486,13 @@ type = real kind = kind_phys intent = in -[sedi_semi] - standard_name = flag_for_semi_Lagrangian_sedi_rain - long_name = flag for semi Lagrangian sedi of rain - units = flag - dimensions = () - type = logical - intent = in -[decfl] - standard_name = deformed_CFL_factor - long_name = deformed CFL factor - units = count +[tempo_cfgs] + standard_name = configuration_for_TEMPO_microphysics + long_name = configuration information for TEMPO microphysics + units = mixed dimensions = () - type = integer - intent = in -[islmsk] - standard_name = sea_land_ice_mask - long_name = sea/land/ice mask (=0/1/2) - units = flag - dimensions = (horizontal_loop_extent) - type = integer intent = in + type = ty_tempo_cfgs [dtp] standard_name = timestep_for_physics long_name = physics timestep @@ -694,271 +509,27 @@ type = real kind = kind_phys intent = in -[first_time_step] - standard_name = flag_for_first_timestep - long_name = flag for first time step for time integration loop (cold/warmstart) - units = flag - dimensions = () - type = logical - intent = in -[istep] - standard_name = ccpp_loop_counter - long_name = loop counter for subcycling loops in CCPP - units = index - dimensions = () - type = integer - intent = in -[nsteps] - standard_name = ccpp_loop_extent - long_name = loop extent for subcycling loops in CCPP - units = count - dimensions = () - type = integer - intent = in -[prcp] - standard_name = lwe_thickness_of_explicit_precipitation_amount - long_name = explicit precipitation (rain, ice, snow, graupel) on physics timestep - units = m - dimensions = (horizontal_loop_extent) - type = real - kind = kind_phys - intent = inout -[rain] - standard_name = lwe_thickness_of_explicit_rain_amount - long_name = explicit rain fall on physics timestep - units = m - dimensions = (horizontal_loop_extent) - type = real - kind = kind_phys - intent = inout - optional = True -[graupel] - standard_name = lwe_thickness_of_graupel_amount - long_name = graupel fall on physics timestep - units = m - dimensions = (horizontal_loop_extent) - type = real - kind = kind_phys - intent = inout - optional = True -[ice] - standard_name = lwe_thickness_of_ice_amount - long_name = ice fall on physics timestep - units = m - dimensions = (horizontal_loop_extent) - type = real - kind = kind_phys - intent = inout - optional = True -[snow] - standard_name = lwe_thickness_of_snow_amount - long_name = snow fall on physics timestep - units = m - dimensions = (horizontal_loop_extent) - type = real - kind = kind_phys - intent = inout - optional = True -[sr] - standard_name = ratio_of_snowfall_to_rainfall - long_name = ratio of snowfall to large-scale rainfall - units = frac - dimensions = (horizontal_loop_extent) - type = real - kind = kind_phys - intent = out -[refl_10cm] - standard_name = radar_reflectivity_10cm - long_name = instantaneous refl_10cm - units = dBZ - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = out -[max_hail_diam_sfc] - standard_name = max_hail_diameter_sfc - long_name = instantaneous maximum hail diameter at lowest model level - units = m - dimensions = (horizontal_loop_extent) - type = real - kind = kind_phys - intent = inout -[fullradar_diag] - standard_name = do_full_radar_reflectivity - long_name = flag for computing full radar reflectivity - units = flag - dimensions = () - type = logical - intent = in -[do_radar_ref] - standard_name = flag_for_radar_reflectivity - long_name = flag for radar reflectivity - units = flag - dimensions = () - type = logical - intent = in -[aerfld] - standard_name = mass_mixing_ratio_of_aerosol_from_gocart_or_merra2 - long_name = mass mixing ratio of aerosol from gocart or merra2 - units = kg kg-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_aerosol_tracers_MG) - type = real - kind = kind_phys - intent = in -[mpicomm] - standard_name = mpi_communicator - long_name = MPI communicator - units = index - dimensions = () - type = MPI_Comm - intent = in -[mpirank] - standard_name = mpi_rank - long_name = current MPI-rank - units = index - dimensions = () - type = integer - intent = in -[mpiroot] - standard_name = mpi_root - long_name = master MPI-rank - units = index - dimensions = () - type = integer - intent = in -[blkno] - standard_name = ccpp_block_number - long_name = number of block for explicit data blocking in CCPP - units = index - dimensions = () - type = integer - intent = in -[ext_diag] - standard_name = flag_for_extended_diagnostic_output_from_thompson_microphysics - long_name = flag for extended diagnostic output from thompson microphysics - units = flag - dimensions = () - type = logical - intent = in -[diag3d] - standard_name = extended_diagnostics_output_from_thompson_microphysics - long_name = set of 3d arrays for extended diagnostics output from thompson microphysics - units = none - dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_3d_diagnostic_output_arrays_from_thompson_microphysics) - type = real - kind = kind_phys - intent = inout - optional = True -[reset_diag3d] - standard_name = flag_reset_extended_diagnostics_output_arrays_from_thompson_microphysics - long_name = flag for resetting extended diagnostics output arrays from thompson microphysics +[is_aerosol_aware] + standard_name = flag_for_aerosol_physics + long_name = flag for aerosol-aware physics units = flag dimensions = () type = logical intent = in -[spp_wts_mp] - standard_name = spp_weights_for_microphysics_scheme - long_name = spp weights for microphysics scheme - units = 1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - intent = in - optional = True -[spp_mp] - standard_name = control_for_microphysics_spp_perturbations - long_name = control for microphysics spp perturbations - units = count - dimensions = () - type = integer - intent = in -[n_var_spp] - standard_name = number_of_perturbed_spp_schemes - long_name = number of perturbed spp schemes - units = count - dimensions = () - type = integer - intent = in -[spp_prt_list] - standard_name = magnitude_of_spp_perturbations - long_name = magnitude of spp perturbations - units = 1 - dimensions = (number_of_perturbed_spp_schemes) - type = real - kind = kind_phys - intent = in - optional = True -[spp_stddev_cutoff] - standard_name = magnitude_of_spp_standard_deviation_cutoff - long_name = magnitude of spp standard deviation cutoff - units = 1 - dimensions = (number_of_perturbed_spp_schemes) - type = real - kind = kind_phys - intent = in - optional = True -[spp_var_list] - standard_name = perturbed_spp_schemes - long_name = perturbed spp schemes - units = none - dimensions = (number_of_perturbed_spp_schemes) - type = character - kind = len=10 - intent = in - optional = True -[cplchm] - standard_name = flag_for_chemistry_coupling - long_name = flag controlling cplchm collection (default off) +[is_hail_aware] + standard_name = flag_for_hail_physics + long_name = flag for hail-aware physics units = flag dimensions = () type = logical intent = in -[pfi_lsan] - standard_name = ice_flux_due_to_large_scale_precipitation - long_name = instantaneous 3D flux of ice from nonconvective precipitation - units = kg m-2 s-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout - optional = True -[pfl_lsan] - standard_name = liquid_flux_due_to_large_scale_precipitation - long_name = instantaneous 3D flux of liquid water from nonconvective precipitation - units = kg m-2 s-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = inout - optional = True -[is_initialized] - standard_name = flag_for_thompson_mp_scheme_initialization - long_name = flag carrying scheme initialization status - units = flag - dimensions = () - type = logical - intent = inout -[errmsg] - standard_name = ccpp_error_message - long_name = error message for error handling in CCPP - units = none - dimensions = () - type = character - kind = len=* - intent = out -[errflg] - standard_name = ccpp_error_code - long_name = error code for error handling in CCPP - units = 1 - dimensions = () - type = integer - intent = out - + ######################################################################## [ccpp-arg-table] name = mp_tempo_finalize type = scheme [is_initialized] - standard_name = flag_for_thompson_mp_scheme_initialization + standard_name = flag_for_tempo_mp_scheme_initialization long_name = flag carrying scheme initialization status units = flag dimensions = () diff --git a/physics/MP/TEMPO/mp_tempo_condensation.F90 b/physics/MP/TEMPO/mp_tempo_condensation.F90 new file mode 100644 index 000000000..5ec14cbd8 --- /dev/null +++ b/physics/MP/TEMPO/mp_tempo_condensation.F90 @@ -0,0 +1,186 @@ +!>\file mp_tempo_condensation.F90 +!! This file contains tempo condensation. + + +!>\defgroup tempo condensation +!! This module contains tempo condensation +module mp_tempo_condensation + + use mpi_f08 + use machine, only : kind_phys, kind_dyn + + use module_mp_tempo_params, only : roverrv, rv, rdry, eps, r1, t0, cp + use module_mp_tempo_cfgs, only : ty_tempo_cfgs + use module_mp_tempo_main, only : cloud_check_and_update + use module_mp_tempo_utils, only : calc_rslf + + implicit none + + public :: mp_tempo_condensation_init, mp_tempo_condensation_run, mp_tempo_condensation_finalize + + private + + contains + +!! \section arg_table_mp_tempo_condensation_init Argument Table +!! \htmlinclude mp_tempo_condensation_init.html +!! + subroutine mp_tempo_condensation_init(errmsg, errflg) + + character(len=*), intent( out) :: errmsg + integer, intent( out) :: errflg + + errmsg = '' + errflg = 0 + end subroutine mp_tempo_condensation_init + + +!> \section arg_table_mp_tempo_condensation_run Argument Table +!! \htmlinclude mp_tempo_condensation_run.html +!! + subroutine mp_tempo_condensation_run(mpicomm, mpirank, mpiroot, & + tgrs, prsl, spechum, qc, mdt, errmsg, errflg, & + is, ie, js, je, isc1, iec1, jsc1, jec1, & + isc2, iec2, jsc2, jec2, isd, ied, jsd, jed, km) + + integer, intent(in ) :: isc1, iec1, jsc1, jec1 + integer, intent(in ) :: isd, ied, jsd, jed, is, ie, js, je, km, isc2, iec2, jsc2, jec2 + type(MPI_Comm), intent(in ) :: mpicomm + integer, intent(in ) :: mpirank + integer, intent(in ) :: mpiroot + real(kind_dyn), intent(in ) :: mdt + real(kind_dyn), intent(inout) :: spechum(isd:ied, jsd:jed, 1:km) + real(kind_dyn), intent(inout) :: qc(isd:ied, jsd:jed, 1:km) + real(kind_dyn), intent(inout) :: tgrs(isd:ied, jsd:jed, 1:km) + real(kind_dyn), intent(in ) :: prsl(is:ie, 1:km+1, js:je) + + real(kind_phys) :: qv(is:ie, js:je, 1:km) +!! real(kind_phys) :: qc2(is:ie, js:je, 1:km) + real(kind_phys) :: qvs(is:ie, js:je, 1:km) + real(kind_phys) :: rho(is:ie, js:je, 1:km) + real(kind_phys) :: temp(is:ie, js:je, 1:km) + real(kind_phys) :: satw(1:km) + real(kind_phys) :: ssatw(1:km) + real(kind_phys) :: lvap(1:km) + real(kind_phys) :: tcond(1:km) + real(kind_phys) :: diffu(1:km) + real(kind_phys) :: ocp(1:km) + real(kind_phys) :: lvt2(1:km) + real(kind_phys) :: rc(1:km) + real(kind_phys) :: nc(1:km) + real(kind_phys) :: ilamc(1:km) + real(kind_phys) :: mvd_c(1:km) + real(kind_phys) :: qcten(1:km) + real(kind_phys) :: ncten(1:km) + logical :: l_qc(1:km) + real(kind_phys) :: out(is:ie, js:je, 1:km) + real(kind_phys) :: orho, clap, fcd, dfcd, xrc + + ! CCPP error handling + character(len=*), intent( out) :: errmsg + integer, intent( out) :: errflg + integer :: i, j, k, n + ! Initialize the CCPP error handling variables + errmsg = '' + errflg = 0 + + if (mpirank==mpiroot) then + write(*,*) 'Calling condensation for Tempo MP' + endif + + do k = 1, km + do j = js, je + do i = is, ie + spechum(i,j,k) = max(1.e-10, spechum(i,j,k)) + qv(i,j,k) = spechum(i,j,k)/(1.0_kind_phys-spechum(i,j,k)) + qc(i,j,k) = qc(i,j,k) / (1.-spechum(i,j,k)) ! convert from moist to dry rho +! qc2(i,j,k) = qc(i,j,k) + temp(i,j,k) = tgrs(i,j,k) / ((0.608 * spechum(i,j,k)) + 1.) + rho(i,j,k) = roverrv * exp(prsl(i,k,j)) / (rdry*temp(i,j,k) * (qv(i,j,k)+roverrv)) + qvs(i,j,k) = calc_rslf(exp(prsl(i,k,j)), temp(i,j,k)) + enddo + enddo + enddo + + out = 0. + do j = js, je + do i = is, ie + l_qc = .false. + rc = 0. + nc = 0. + qcten = 0. + ncten = 0. + + ! returns cloud mass concentration + call cloud_check_and_update(rho=rho(i,j,:), l_qc=l_qc, qc1d=qc(i,j,:), & + rc=rc, nc=nc, qcten=qcten, ncten=ncten, ilamc=ilamc, mvd_c=mvd_c) + + + do k = 1, km + satw(k) = qv(i,j,k)/qvs(i,j,k) + ssatw(k) = satw(k) - 1. + if (abs(ssatw(k)) < eps) ssatw(k) = 0. + lvap(k) = 2.5e6 + (2106.0 - 4218.0)*(temp(i,j,k)-t0) + tcond(k) = (5.69 + 0.0168*(temp(i,j,k)-t0))*1.0e-5 * 418.936 + diffu(k) = 2.11e-5*(temp(i,j,k)/t0)**1.94 * (101325./exp(prsl(i,k,j))) + ocp(k) = 1./(cp*(1.+0.887*qv(i,j,k))) + lvt2(k) = lvap(k)*lvap(k)*ocp(k)*(1./rv)*(1./temp(i,j,k))*(1./temp(i,j,k)) + + if (abs(ssatw(k)) >= eps) then + orho = 1./rho(i,j,k) + clap = (qv(i,j,k)-qvs(i,j,k))/(1. + lvt2(k)*qvs(i,j,k)) + do n = 1, 3 + fcd = qvs(i,j,k)*exp(lvt2(k)*clap) - qv(i,j,k) + clap + dfcd = qvs(i,j,k)*lvt2(k)*exp(lvt2(k)*clap) + 1. + clap = clap - fcd/dfcd + enddo + xrc = rc(k) + clap*rho(i,j,k) + + if (xrc > r1) then + out(i,j,k) = clap / mdt + + if (l_qc(k) .and. ssatw(k) < -1.e-6 .and. clap < -eps) then ! evaporation + out(i,j,k) = max(-rc(k)*0.99*orho/mdt, out(i,j,k)) + endif + else + out(i,j,k) = -rc(k)*orho/mdt + endif + endif + + qv(i,j,k) = qv(i,j,k) - out(i,j,k)*mdt + qc(i,j,k) = qc(i,j,k) + out(i,j,k)*mdt +!! qc2(i,j,k) = qc2(i,j,k) + out(i,j,k)*mdt + temp(i,j,k) = temp(i,j,k) + lvap(k)*ocp(k)*out(i,j,k)*mdt + enddo + + call cloud_check_and_update(rho=rho(i,j,:), l_qc=l_qc, qc1d=qc(i,j,:), & + rc=rc, nc=nc, qcten=qcten, ncten=ncten, ilamc=ilamc, mvd_c=mvd_c) + enddo + enddo + + do k = 1, km + do j = js, je + do i = is, ie + spechum(i,j,k) = max(1.e-10, qv(i,j,k)/(1.+qv(i,j,k))) + qc(i,j,k) = qc(i,j,k)/(1.+qv(i,j,k)) + tgrs(i,j,k) = temp(i,j,k)*((0.608*spechum(i,j,k)) + 1.) +! qc(i,j,k) = qc2(i,j,k) + enddo + enddo + enddo + + end subroutine mp_tempo_condensation_run + +!> \section arg_table_mp_tempo_condensation_finalize Argument Table +!! \htmlinclude mp_tempo_condensation_finalize.html +!! + subroutine mp_tempo_condensation_finalize(errmsg, errflg) + + character(len=*), intent( out) :: errmsg + integer, intent( out) :: errflg + + errmsg = '' + errflg = 0 + end subroutine mp_tempo_condensation_finalize + +end module mp_tempo_condensation diff --git a/physics/MP/TEMPO/mp_tempo_condensation.meta b/physics/MP/TEMPO/mp_tempo_condensation.meta new file mode 100644 index 000000000..8ee07b3d9 --- /dev/null +++ b/physics/MP/TEMPO/mp_tempo_condensation.meta @@ -0,0 +1,252 @@ +[ccpp-table-properties] + name = mp_tempo_condensation + type = scheme + dependencies = ../../hooks/machine.F + dependencies = tempo_v3/src/module_mp_tempo_params.F90 + dependencies = tempo_v3/src/module_mp_tempo_cfgs.F90 + dependencies = tempo_v3/src/module_mp_tempo_ml.F90 + dependencies = tempo_v3/src/module_mp_tempo_utils.F90 + dependencies = tempo_v3/src/module_mp_tempo_aerosols.F90 + dependencies = tempo_v3/src/module_mp_tempo_diags.F90 + dependencies = tempo_v3/src/module_mp_tempo_main.F90 + dependencies = tempo_v3/src/module_mp_tempo_driver.F90 + +######################################################################## +[ccpp-arg-table] + name = mp_tempo_condensation_init + type = scheme +[errmsg] + standard_name = ccpp_error_message + long_name = error message for error handling in CCPP + units = none + dimensions = () + type = character + kind = len=*n + intent = out +[errflg] + standard_name = ccpp_error_code + long_name = error code for error handling in CCPP + units = 1 + dimensions = () + type = integer + intent = out + +######################################################################## +[ccpp-arg-table] + name = mp_tempo_condensation_run + type = scheme +[mdt] + standard_name = time_step_for_remapping_for_fast_physics + long_name = remapping time step for fast physics + units = s + dimensions = () + type = real + kind = kind_dyn + intent = in +[mpicomm] + standard_name = mpi_communicator + long_name = MPI communicator + units = index + dimensions = () + type = MPI_Comm + intent = in +[mpirank] + standard_name = mpi_rank + long_name = current MPI-rank + units = index + dimensions = () + type = integer + intent = in +[mpiroot] + standard_name = mpi_root + long_name = master MPI-rank + units = index + dimensions = () + type = integer + intent = in +[isc1] + standard_name = starting_x_direction_index_alloc1 + long_name = starting X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[iec1] + standard_name = ending_x_direction_index_alloc1 + long_name = ending X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[jsc1] + standard_name = starting_y_direction_index_alloc1 + long_name = starting X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[jec1] + standard_name = ending_y_direction_index_alloc1 + long_name = ending X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[km] + standard_name = vertical_dimension_for_fast_physics + long_name = number of vertical levels + units = count + dimensions = () + type = integer + intent = in +[tgrs] + standard_name = virtual_temperature_at_Lagrangian_surface + long_name = virtual temperature at Lagrangian surface + units = K + dimensions = (starting_x_direction_index_alloc1:ending_x_direction_index_alloc1,starting_y_direction_index_alloc1:ending_y_direction_index_alloc1,ccpp_constant_one:vertical_dimension_for_fast_physics) + type = real + kind = kind_dyn + intent = inout +[spechum] + standard_name = water_vapor_specific_humidity_at_Lagrangian_surface + long_name = water vapor specific humidity updated by fast physics at Lagrangian surface + units = kg kg-1 + dimensions = (starting_x_direction_index_alloc1:ending_x_direction_index_alloc1,starting_y_direction_index_alloc1:ending_y_direction_index_alloc1,ccpp_constant_one:vertical_dimension_for_fast_physics) + type = real + kind = kind_dyn + intent = inout +[prsl] + standard_name = log_pressure_at_Lagrangian_surface + long_name = logarithm of pressure at Lagrangian surface + units = Pa + dimensions = (starting_x_direction_index_alloc2:ending_x_direction_index_alloc2,ccpp_constant_one:vertical_dimension_for_fast_physics_plus_one,starting_y_direction_index_alloc2:ending_y_direction_index_alloc2) + type = real + kind = kind_dyn + intent = in +[isc2] + standard_name = starting_x_direction_index_alloc2 + long_name = starting X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[iec2] + standard_name = ending_x_direction_index_alloc2 + long_name = ending X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[jsc2] + standard_name = starting_y_direction_index_alloc2 + long_name = starting X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[jec2] + standard_name = ending_y_direction_index_alloc2 + long_name = ending X direction index for allocation + units = count + dimensions = () + type = integer + intent = in +[qc] + standard_name = cloud_liquid_water_specific_humidity_at_Lagrangian_surface + long_name = cloud liquid water specific humidity updated by fast physics at Lagrangian surface + units = kg kg-1 + dimensions = (starting_x_direction_index_alloc1:ending_x_direction_index_alloc1,starting_y_direction_index_alloc1:ending_y_direction_index_alloc1,ccpp_constant_one:vertical_dimension_for_fast_physics) + type = real + kind = kind_dyn + intent = inout +[errmsg] + standard_name = ccpp_error_message + long_name = error message for error handling in CCPP + units = none + dimensions = () + type = character + kind = len=* + intent = out +[errflg] + standard_name = ccpp_error_code + long_name = error code for error handling in CCPP + units = 1 + dimensions = () + type = integer + intent = out +[isd] + standard_name = starting_x_direction_index_domain + long_name = starting X direction index for domain + units = count + dimensions = () + type = integer + intent = in +[ied] + standard_name = ending_x_direction_index_domain + long_name = ending X direction index for domain + units = count + dimensions = () + type = integer + intent = in +[jsd] + standard_name = starting_y_direction_index_domain + long_name = starting X direction index for domain + units = count + dimensions = () + type = integer + intent = in +[jed] + standard_name = ending_y_direction_index_domain + long_name = ending X direction index for domain + units = count + dimensions = () + type = integer + intent = in +[is] + standard_name = starting_x_direction_index + long_name = starting X direction index + units = count + dimensions = () + type = integer + intent = in +[ie] + standard_name = ending_x_direction_index + long_name = ending X direction index + units = count + dimensions = () + type = integer + intent = in +[js] + standard_name = starting_y_direction_index + long_name = starting Y direction index + units = count + dimensions = () + type = integer + intent = in +[je] + standard_name = ending_y_direction_index + long_name = ending Y direction index + units = count + dimensions = () + type = integer + intent = in + +######################################################################## +[ccpp-arg-table] + name = mp_tempo_condensation_finalize + type = scheme +[errmsg] + standard_name = ccpp_error_message + long_name = error message for error handling in CCPP + units = none + dimensions = () + type = character + kind = len=* + intent = out +[errflg] + standard_name = ccpp_error_code + long_name = error code for error handling in CCPP + units = 1 + dimensions = () + type = integer + intent = out diff --git a/physics/MP/TEMPO/tempo_v3 b/physics/MP/TEMPO/tempo_v3 index b29fb2da3..adede234f 160000 --- a/physics/MP/TEMPO/tempo_v3 +++ b/physics/MP/TEMPO/tempo_v3 @@ -1 +1 @@ -Subproject commit b29fb2da35f342f18b384b37a3091901c7a86381 +Subproject commit adede234fc58e53bbd7650c742982149e7fe1fba From d8171f02a96464637c60cf78608a07fc4a76ddf9 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Fri, 13 Feb 2026 14:24:29 +0000 Subject: [PATCH 06/10] radiation to use tempo v2 for now --- physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 | 4 ++-- physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta | 2 +- .../UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 | 2 +- .../UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.meta | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 index eaf66490c..1b03b4c3a 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 @@ -88,7 +88,7 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& make_DropletNumber_thompson => make_DropletNumber, & make_RainNumber_thompson => make_RainNumber - use module_mp_tempo_params, only: & + use module_mp_tempo_params_v2, only: & Nt_c_l_tempo => Nt_c_l, & Nt_c_o_tempo => Nt_c_o, & re_qc_min_tempo => re_qc_min, & @@ -98,7 +98,7 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& re_qs_min_tempo => re_qs_min, & re_qs_max_tempo => re_qs_max - use module_mp_tempo_utils, only: & + use module_mp_tempo_utils_v2, only: & calc_effectRad_tempo => calc_effectRad, & make_IceNumber_tempo => make_IceNumber, & make_DropletNumber_tempo => make_DropletNumber, & diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta index fa81230ab..260e7b35b 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta @@ -3,7 +3,7 @@ type = scheme dependencies_path = ../../ dependencies = tools/funcphys.f90,hooks/machine.F - dependencies = MP/TEMPO/TEMPO/module_mp_tempo_params.F90,MP/TEMPO/TEMPO/module_mp_tempo_utils.F90 + dependencies = MP/TEMPO/TEMPO/module_mp_tempo_params_v2.F90,MP/TEMPO/TEMPO/module_mp_tempo_utils_v2.F90 dependencies = MP/Thompson/module_mp_thompson.F90,MP/Thompson/module_mp_thompson_make_number_concentrations.F90 dependencies = Radiation/RRTMG/radcons.f90,Radiation/radiation_aerosols.f dependencies = Radiation/radiation_astronomy.f,Radiation/radiation_clouds.f,Radiation/radiation_gases.f diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 index 0a808aa10..41b55fda5 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 @@ -20,7 +20,7 @@ subroutine GFS_suite_interstitial_4_run (im, levs, ltaerosol, tracers_total, ntr make_IceNumber_thompson => make_IceNumber, & make_DropletNumber_thompson => make_DropletNumber - use module_mp_tempo_utils, only: & + use module_mp_tempo_utils_v2, only: & make_IceNumber_tempo => make_IceNumber, & make_DropletNumber_tempo => make_DropletNumber diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.meta b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.meta index 718b6ab95..fdaf0dbfd 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.meta +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.meta @@ -4,7 +4,7 @@ type = scheme dependencies_path = ../../ dependencies = hooks/machine.F - dependencies = MP/TEMPO/TEMPO/module_mp_tempo_utils.F90 + dependencies = MP/TEMPO/TEMPO/module_mp_tempo_utils_v2.F90 dependencies = MP/Thompson/module_mp_thompson_make_number_concentrations.F90 ######################################################################## From 391e7b39fe6e94207132eaadd12747aa2f9b9ee1 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Fri, 13 Feb 2026 21:07:47 +0000 Subject: [PATCH 07/10] adds diagnostics and optional arguments to tempo --- physics/MP/TEMPO/mp_tempo.F90 | 50 ++++++++++++++++++++------- physics/MP/TEMPO/mp_tempo.meta | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 12 deletions(-) diff --git a/physics/MP/TEMPO/mp_tempo.F90 b/physics/MP/TEMPO/mp_tempo.F90 index eda4943ae..121b09747 100644 --- a/physics/MP/TEMPO/mp_tempo.F90 +++ b/physics/MP/TEMPO/mp_tempo.F90 @@ -219,13 +219,16 @@ subroutine mp_tempo_run(ncol, nlev, & nc, nwfa, nifa, nwfa2d, nifa2d, ng, volg, & con_g, con_rd, con_eps, & tgrs, prsl, phii, omega, & - is_aerosol_aware, is_hail_aware, & + is_aerosol_aware, is_hail_aware, & + prcp, rain, graupel, ice, snow, sr, refl_10cm, & + do_radar_ref, & is_initialized, tempo_cfgs, errmsg, errflg) ! Interface variables logical, intent(in ) :: is_initialized logical, intent(in ) :: convert_dry_rho + logical, intent(in ) :: do_radar_ref ! Dimensions and constants integer, intent(in ) :: ncol integer, intent(in ) :: nlev @@ -250,6 +253,15 @@ subroutine mp_tempo_run(ncol, nlev, & real(kind_phys), optional, intent(inout) :: volg(:,:) logical, intent(in) :: is_aerosol_aware logical, intent(in) :: is_hail_aware + ! Precip/rain/snow/graupel fall amounts and fraction of frozen precip + real(kind_phys), intent(inout) :: prcp(:) + real(kind_phys), intent(inout) :: rain(:) + real(kind_phys), intent(inout) :: graupel(:) + real(kind_phys), intent(inout) :: ice(:) + real(kind_phys), intent(inout) :: snow(:) + real(kind_phys), intent( out) :: sr(:) + ! Radar reflectivity + real(kind_phys), intent(inout) :: refl_10cm(:,:) ! State variables and timestep information real(kind_phys), intent(inout) :: tgrs(:,:) real(kind_phys), intent(in ) :: prsl(:,:) @@ -271,9 +283,8 @@ subroutine mp_tempo_run(ncol, nlev, & type(ty_tempo_driver_diags) :: tempo_driver_diags ! Local variables - ! ! Reduced time step if subcycling is used - ! real(kind_phys) :: dtstep - ! integer :: ndt + ! Reduced time step if dt_inner + real(kind_phys) :: dt ! Air density real(kind_phys) :: rho(1:ncol,1:nlev) !< kg m-3 ! Water vapor mixing ratio (instead of specific humidity) @@ -283,6 +294,7 @@ subroutine mp_tempo_run(ncol, nlev, & real(kind_phys) :: dz(1:ncol,1:nlev) !< m ! Dimensions + integer :: ndt integer :: ids,ide, jds,jde, kds,kde, & ims,ime, jms,jme, kms,kme, & its,ite, jts,jte, kts,kte @@ -335,12 +347,9 @@ subroutine mp_tempo_run(ncol, nlev, & ! end if ! end if - ! Set reduced time step if subcycling is used -! if (nsteps>1) then -! dtstep = dtp/real(nsteps, kind=kind_phys) -! else -! dtstep = dtp -! end if + ndt = max(nint(dtp/dt_inner), 1) + dt = dtp/ndt + if (dt <= dt_inner) dt = dt_inner !> - Convert specific humidity to water vapor mixing ratio. !> - Also, hydrometeor variables are mass or number mixing ratio @@ -398,15 +407,17 @@ subroutine mp_tempo_run(ncol, nlev, & !ADD AEROSOL SOURCE/SINKS HERE call tempo_run(tempo_cfgs=tempo_cfgs, & - dt=dt_inner, itimestep=itimestep , & + dt=dt, itimestep=itimestep , & qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & + nc=nc, nwfa=nwfa, nifa=nifa, & + ng=ng, qb=volg, & w=w, t=tgrs, p=prsl, dz=dz, & ids = ids , ide = ide , jds = jds , jde = jde , kds = kds , kde = kde , & ims = ims , ime = ime , jms = jms , jme = jme , kms = kms , kme = kme , & its = its , ite = ite , jts = jts , jte = jte , kts = kts , kte = kte , & tempo_diags=tempo_driver_diags) - if (mpirank==mpiroot) write(*,*) 'Calling tempo_run() with itimestep = ', itimestep + if (mpirank==mpiroot) write(*,*) 'Calling tempo_run() with itimestep = ', itimestep itimestep = itimestep + 1 if (errflg/=0) return @@ -433,6 +444,21 @@ subroutine mp_tempo_run(ncol, nlev, & end if end if + if (do_radar_ref) then + refl_10cm = tempo_driver_diags%refl10cm(:,:,1) + endif + + ice = ice + max(0.0, tempo_driver_diags%ice_liquid_equiv_precip(:,1)/1000.0_kind_phys) + snow = snow + (max(0.0, tempo_driver_diags%ice_liquid_equiv_precip(:,1)) + & + max(0.0, tempo_driver_diags%snow_liquid_equiv_precip(:,1)))/1000.0_kind_phys + graupel = graupel + max(0.0, tempo_driver_diags%graupel_liquid_equiv_precip(:,1)/1000.0_kind_phys) + rain = rain + max(0.0, tempo_driver_diags%rain_precip(:,1)/1000.0_kind_phys) + prcp = prcp + (max(0.0, tempo_driver_diags%ice_liquid_equiv_precip(:,1)) + & + max(0.0, tempo_driver_diags%snow_liquid_equiv_precip(:,1)) + & + max(0.0, tempo_driver_diags%graupel_liquid_equiv_precip(:,1)) + & + max(0.0, tempo_driver_diags%rain_precip(:,1)))/1000._kind_phys + sr = tempo_driver_diags%frozen_fraction(:,1) + end subroutine mp_tempo_run !> \section arg_table_mp_tempo_finalize Argument Table diff --git a/physics/MP/TEMPO/mp_tempo.meta b/physics/MP/TEMPO/mp_tempo.meta index 65abcd8d6..257acafbd 100644 --- a/physics/MP/TEMPO/mp_tempo.meta +++ b/physics/MP/TEMPO/mp_tempo.meta @@ -430,6 +430,69 @@ kind = kind_phys intent = inout optional = True +[prcp] + standard_name = lwe_thickness_of_explicit_precipitation_amount + long_name = explicit precipitation (rain, ice, snow, graupel) on physics timestep + units = m + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys + intent = inout +[rain] + standard_name = lwe_thickness_of_explicit_rain_amount + long_name = explicit rain fall on physics timestep + units = m + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys + intent = inout +[graupel] + standard_name = lwe_thickness_of_graupel_amount + long_name = graupel fall on physics timestep + units = m + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys + intent = inout +[ice] + standard_name = lwe_thickness_of_ice_amount + long_name = ice fall on physics timestep + units = m + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys + intent = inout +[snow] + standard_name = lwe_thickness_of_snow_amount + long_name = snow fall on physics timestep + units = m + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys + intent = inout +[sr] + standard_name = ratio_of_snowfall_to_rainfall + long_name = ratio of snowfall to large-scale rainfall + units = frac + dimensions = (horizontal_loop_extent) + type = real + kind = kind_phys + intent = out +[do_radar_ref] + standard_name = flag_for_radar_reflectivity + long_name = flag for radar reflectivity + units = flag + dimensions = () + type = logical + intent = in +[refl_10cm] + standard_name = radar_reflectivity_10cm + long_name = instantaneous refl_10cm + units = dBZ + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + type = real + kind = kind_phys + intent = out [con_g] standard_name = gravitational_acceleration long_name = gravitational acceleration From af6f85251618f61b668b745db708ab0ce05cf18e Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Fri, 13 Feb 2026 22:17:18 +0000 Subject: [PATCH 08/10] add aerosol surface emissions to tempo and aerosol and hail aware flags --- physics/MP/TEMPO/mp_tempo.F90 | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/physics/MP/TEMPO/mp_tempo.F90 b/physics/MP/TEMPO/mp_tempo.F90 index 121b09747..82c560ae3 100644 --- a/physics/MP/TEMPO/mp_tempo.F90 +++ b/physics/MP/TEMPO/mp_tempo.F90 @@ -11,7 +11,7 @@ module mp_tempo use module_mp_tempo_params use module_mp_tempo_cfgs, only : ty_tempo_cfgs - use module_mp_tempo_driver, only : tempo_init, tempo_run, ty_tempo_driver_diags + use module_mp_tempo_driver, only : tempo_init, tempo_run, ty_tempo_driver_diags, tempo_aerosol_surface_emissions implicit none @@ -72,6 +72,7 @@ subroutine mp_tempo_init(ncol, nlev, & real(kind_phys) :: hgt(1:ncol,1:nlev) ! m real(kind_phys) :: rho(1:ncol,1:nlev) ! kg m-3 real(kind_phys) :: orho(1:ncol,1:nlev) ! m3 kg-1 + real (kind=kind_phys) :: h_01, z1, niIN3, niCCN3 integer :: i, k @@ -92,7 +93,7 @@ subroutine mp_tempo_init(ncol, nlev, & if (mpirank==mpiroot) write(*,*) 'Calling tempo_init()' ! Main call to tempo_init() - call tempo_init(aerosolaware_flag=.false., hailaware_flag=.false., & + call tempo_init(aerosolaware_flag=is_aerosol_aware, hailaware_flag=is_hail_aware, & semi_sedi_flag=semi_sedi, cloud_condensation_flag=(.not. do_sat_adj), & tempo_cfgs=tempo_cfgs) @@ -292,6 +293,8 @@ subroutine mp_tempo_run(ncol, nlev, & ! Vertical velocity and level width real(kind_phys) :: w(1:ncol,1:nlev) !< m s-1 real(kind_phys) :: dz(1:ncol,1:nlev) !< m + real(kind_phys) :: xnwfa(1:ncol,1:nlev,1) + real(kind_phys) :: xnwfa2d(1:ncol,1) ! Dimensions integer :: ndt @@ -404,8 +407,14 @@ subroutine mp_tempo_run(ncol, nlev, & kme = nlev kte = nlev - !ADD AEROSOL SOURCE/SINKS HERE - + if (present(nwfa) .and. present(nwfa2d)) then + xnwfa(:,:,1) = nwfa(:,:) + xnwfa2d(:,1) = nwfa2d(:) + call tempo_aerosol_surface_emissions(dt=dt, nwfa=xnwfa, nwfa2d=xnwfa2d, ims=ims, ime=ime, & + jms=jms, jme=jme, kms=kms, kme=kme, kts=kts) + nwfa(:,:) = xnwfa(:,:,1) + endif + call tempo_run(tempo_cfgs=tempo_cfgs, & dt=dt, itimestep=itimestep , & qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & From d6e6ed6b8202807793da2a15ed2eed0458fed399 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Fri, 13 Feb 2026 22:17:53 +0000 Subject: [PATCH 09/10] couple tempo to MYNN in ccpp --- physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90 | 10 ++++++---- physics/PBL/MYNN_EDMF/mynnedmf_wrapper.meta | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90 b/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90 index ff2e9e24f..418ede96f 100644 --- a/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90 +++ b/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90 @@ -156,6 +156,7 @@ SUBROUTINE mynnedmf_wrapper_run( & & imp_physics, imp_physics_gfdl, & & imp_physics_thompson, imp_physics_wsm6, & & imp_physics_fa, imfdeepcnv, imfdeepcnv_c3, & + & imp_physics_tempo, & & imfdeepcnv_samf, & & chem3d, frp, mix_chem, rrfs_sd, enh_mix, & & nchem, ndvel, vdep, smoke_dbg, & @@ -206,6 +207,7 @@ SUBROUTINE mynnedmf_wrapper_run( & & bl_mynn_output, & & imp_physics, imp_physics_wsm6, & & imp_physics_thompson, imp_physics_gfdl, & + & imp_physics_tempo, & & imp_physics_nssl, imp_physics_fa, imfdeepcnv, & & imfdeepcnv_c3, imfdeepcnv_samf, & & spp_pbl, & @@ -426,7 +428,7 @@ SUBROUTINE mynnedmf_wrapper_run( & qnbca(i,k) = 0. enddo enddo - elseif (imp_physics == imp_physics_thompson) then + elseif (imp_physics == imp_physics_thompson .or. imp_physics == imp_physics_tempo) then ! Thompson if(ltaerosol) then FLAG_QI = .true. @@ -451,7 +453,7 @@ SUBROUTINE mynnedmf_wrapper_run( & qnbca(i,k) = 0. enddo enddo - else if(mraerosol) then + else if(mraerosol .and. imp_physics == imp_physics_thompson) then FLAG_QI = .true. FLAG_QNI= .true. FLAG_QC = .true. @@ -845,7 +847,7 @@ SUBROUTINE mynnedmf_wrapper_run( & ! !dqdt_ozone(i,k) = 0.0 ! enddo !enddo - elseif (imp_physics == imp_physics_thompson) then + elseif (imp_physics == imp_physics_thompson .or. imp_physics == imp_physics_tempo) then ! Thompson-Aerosol if(ltaerosol) then do k=1,levs @@ -882,7 +884,7 @@ SUBROUTINE mynnedmf_wrapper_run( & ! !qgrs_ice_aer_num_conc(i,k) = qgrs_ice_aer_num_conc(i,k) + RQNIFABLTEN(i,k)*delt ! enddo !enddo - else if(mraerosol) then + else if(mraerosol .and. imp_physics == imp_physics_thompson) then do k=1,levs do i=1,im dqdt_water_vapor(i,k) = RQVBLTEN(i,k) !/(1.0 + qv(i,k)) diff --git a/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.meta b/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.meta index e7b8a5a32..df80c3b09 100644 --- a/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.meta +++ b/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.meta @@ -1399,6 +1399,13 @@ dimensions = () type = integer intent = in +[imp_physics_tempo] + standard_name = identifier_for_tempo_microphysics_scheme + long_name = choice of Tempo microphysics scheme + units = flag + dimensions = () + type = integer + intent = in [imp_physics_wsm6] standard_name = identifier_for_wsm6_microphysics_scheme long_name = choice of WSM6 microphysics scheme From 425e3f030976228b8d31a10027130721b9c89827 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Mon, 16 Feb 2026 16:46:07 +0000 Subject: [PATCH 10/10] update pointer to tempo and fix missing qv variable --- physics/MP/TEMPO/mp_tempo.F90 | 24 +++++++++++++++++++----- physics/MP/TEMPO/tempo_v3 | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/physics/MP/TEMPO/mp_tempo.F90 b/physics/MP/TEMPO/mp_tempo.F90 index 82c560ae3..d24f04bcd 100644 --- a/physics/MP/TEMPO/mp_tempo.F90 +++ b/physics/MP/TEMPO/mp_tempo.F90 @@ -90,7 +90,7 @@ subroutine mp_tempo_init(ncol, nlev, & end if ! Call tempo init (also sets initial default values of physical constants) - if (mpirank==mpiroot) write(*,*) 'Calling tempo_init()' + if (mpirank==mpiroot) write(*,*) 'Calling tempo_init()', is_aerosol_aware, is_hail_aware, semi_sedi, do_sat_adj ! Main call to tempo_init() call tempo_init(aerosolaware_flag=is_aerosol_aware, hailaware_flag=is_hail_aware, & @@ -104,7 +104,9 @@ subroutine mp_tempo_init(ncol, nlev, & is_initialized = .true. return end if - + + where(spechum<0) spechum = 1.0e-10 + qv = spechum/(1.0_kind_phys-spechum) if (convert_dry_rho) then if (is_aerosol_aware) then nwfa = nwfa/(1.0_kind_phys-spechum) @@ -297,7 +299,7 @@ subroutine mp_tempo_run(ncol, nlev, & real(kind_phys) :: xnwfa2d(1:ncol,1) ! Dimensions - integer :: ndt + integer :: ndt, i, k integer :: ids,ide, jds,jde, kds,kde, & ims,ime, jms,jme, kms,kme, & its,ite, jts,jte, kts,kte @@ -350,6 +352,7 @@ subroutine mp_tempo_run(ncol, nlev, & ! end if ! end if + ndt = max(nint(dtp/dt_inner), 1) dt = dtp/ndt if (dt <= dt_inner) dt = dt_inner @@ -415,18 +418,29 @@ subroutine mp_tempo_run(ncol, nlev, & nwfa(:,:) = xnwfa(:,:,1) endif + if (mpirank==mpiroot) write(*,*) 'Calling tempo_run() with itimestep = ', itimestep +! do k = 1, nlev +! write(*,*) 'aaj tempo_run', k, tgrs(5,k), prsl(5,k), qv(5,k), qc(5,k), & +! qr(5,k), qi(5,k), qs(5,k), qg(5,k), ni(5,k), nr(5,k), dt, w(5,k), dz(5,k) +! enddo + +! if (present(nwfa)) write(*,*) 'aaj nwfa present' +! if (present(nifa)) write(*,*) 'aaj nifa present' +! if (present(nc)) write(*,*) 'aaj nc present' +! if (present(ng)) write(*,*) 'aaj ng present' +! if (present(volg)) write(*,*) 'aaj volg present' + call tempo_run(tempo_cfgs=tempo_cfgs, & dt=dt, itimestep=itimestep , & qv=qv, qc=qc, qr=qr, qi=qi, qs=qs, qg=qg, ni=ni, nr=nr, & nc=nc, nwfa=nwfa, nifa=nifa, & - ng=ng, qb=volg, & +!! ng=ng, qb=volg, & w=w, t=tgrs, p=prsl, dz=dz, & ids = ids , ide = ide , jds = jds , jde = jde , kds = kds , kde = kde , & ims = ims , ime = ime , jms = jms , jme = jme , kms = kms , kme = kme , & its = its , ite = ite , jts = jts , jte = jte , kts = kts , kte = kte , & tempo_diags=tempo_driver_diags) - if (mpirank==mpiroot) write(*,*) 'Calling tempo_run() with itimestep = ', itimestep itimestep = itimestep + 1 if (errflg/=0) return diff --git a/physics/MP/TEMPO/tempo_v3 b/physics/MP/TEMPO/tempo_v3 index adede234f..cce77d029 160000 --- a/physics/MP/TEMPO/tempo_v3 +++ b/physics/MP/TEMPO/tempo_v3 @@ -1 +1 @@ -Subproject commit adede234fc58e53bbd7650c742982149e7fe1fba +Subproject commit cce77d029261a085297e73fe9266b02ccccf2381