diff --git a/.gitmodules b/.gitmodules index 60cb1f2a8..4320dd80c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,8 +2,8 @@ path = physics/Radiation/RRTMGP/rte-rrtmgp url = https://github.com/NCAR/rte-rrtmgp branch = main -[submodule "physics/MP/TEMPO/TEMPO"] - path = physics/MP/TEMPO/TEMPO +[submodule "physics/MP/TEMPO/tempo_v3"] + path = physics/MP/TEMPO/tempo_v3 url = https://github.com/NCAR/TEMPO branch = main [submodule "physics/SFC_Layer/MYNN/MYNN"] 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 d50713fa1..f7aa382fa 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_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_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 742b2aa27..cab479912 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.F90 @@ -10,15 +10,14 @@ module GFS_PBL_generic_post !! 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, & - tend_opt_pbl, 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_mg, & + tend_opt_pbl, 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_mg, 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, ten_t_pbl, ten_q_pbl,ten_t, ten_u, ten_v, ten_q, & - dusfc1, dvsfc1, dtsfc1, dqsfc1, dtf, dtp, dudt, dvdt, dtdt, & - dqdt, dusfc_cpl, dvsfc_cpl, dtsfc_cpl, dtend, dtidx, index_of_temperature, index_of_x_wind, index_of_y_wind, & - index_of_process_pbl, dqsfc_cpl, dusfci_cpl, dvsfci_cpl, dtsfci_cpl, dqsfci_cpl, dusfc_diag, dvsfc_diag, dtsfc_diag, & - dqsfc_diag, dusfci_diag, dvsfci_diag, dtsfci_diag, dqsfci_diag, & + shinhong, do_ysu, dvdftra, ten_t_pbl, ten_q_pbl, ten_t, ten_u, ten_v, ten_q, dusfc1, dvsfc1, dtsfc1, dqsfc1, dtf, dtp, & + dudt, dvdt, dtdt, dqdt, dusfc_cpl, dvsfc_cpl, dtsfc_cpl, dtend, dtidx, index_of_temperature, index_of_x_wind, & + index_of_y_wind, index_of_process_pbl, dqsfc_cpl, dusfci_cpl, dvsfci_cpl, dtsfci_cpl, dqsfci_cpl, dusfc_diag, & + dvsfc_diag, dtsfc_diag, dqsfc_diag, dusfci_diag, dvsfci_diag, dtsfci_diag, dqsfci_diag, & rd, cp, fvirt, hvap, t1, q1, prsl, hflx, ushfsfci, oceanfrac, kdt, dusfc_cice, dvsfc_cice, & dtsfc_cice, dqsfc_cice, use_med_flux, dtsfc_med, dqsfc_med, dusfc_med, dvsfc_med, wet, dry, icy, wind, stress_wat, & hflx_wat, evap_wat, ugrs1, vgrs1, hffac, ugrs, vgrs, tgrs, qgrs, huge, & @@ -35,11 +34,11 @@ subroutine GFS_PBL_generic_post_run (im, levs, nvdiff, ntrac, integer, intent(in) :: ntccn, nthl, nthnc, ntgv, nthv, ntrz, ntgz, nthz integer, intent(in) :: tend_opt_pbl 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_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 @@ -115,7 +114,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_nssl,& nssl_hail_on, nssl_ccn_on, nssl_3moment, kk, & @@ -206,6 +206,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 87f911d80..54a00bc82 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.meta +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_post.meta @@ -260,6 +260,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 9c91d1f93..9451c568f 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_PBL_generic_pre.F90 @@ -14,8 +14,8 @@ 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_mg, imp_physics_fer_hires, imp_physics_nssl, & - ltaerosol, mraerosol, nssl_ccn_on, nssl_hail_on, nssl_3moment, & + imp_physics_tempo, lthailaware, 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, & ugrs, vgrs, tgrs, errmsg, errflg) @@ -31,9 +31,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 - 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_mg, imp_physics_fer_hires - logical, intent(in) :: ltaerosol, hybedmf, do_shoc, satmedmf, mraerosol + logical, intent(in) :: ltaerosol, hybedmf, do_shoc, satmedmf, mraerosol, lthailaware integer, intent(in) :: imp_physics_nssl logical, intent(in) :: nssl_hail_on, nssl_ccn_on, nssl_3moment @@ -138,6 +138,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 @@ -262,6 +299,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_nssl, & nssl_hail_on, nssl_ccn_on, nssl_3moment, kk, & 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 ed5e215f7..6621c28bd 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 @@ -294,6 +301,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_rrtmg_pre.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 index 426c5cf13..189c30def 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.F90 @@ -46,10 +46,10 @@ 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 + use machine, only: kind_phys, kind_dbl_prec use radcons, only: itsfc, qmin, qme5, qme6, epsq, prsmin use funcphys, only: fpvs @@ -87,23 +87,9 @@ 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: & - ty_tempo_cfg, & - Nt_c_l_tempo => Nt_c_l, & - Nt_c_o_tempo => Nt_c_o, & - re_qc_min_tempo => re_qc_min, & - re_qc_max_tempo => re_qc_max, & - re_qi_min_tempo => re_qi_min, & - re_qi_max_tempo => re_qi_max, & - re_qs_min_tempo => re_qs_min, & - re_qs_max_tempo => re_qs_max - - use module_mp_tempo_utils, only: & - calc_effectRad_tempo => calc_effectRad, & - make_IceNumber_tempo => make_IceNumber, & - make_DropletNumber_tempo => make_DropletNumber, & - make_RainNumber_tempo => make_RainNumber - + use module_mp_tempo_main, only : cloud_check_and_update, ice_check_and_update, snow_check_and_update + use module_mp_tempo_utils, only : get_constant_cloud_number + use module_mp_tempo_diags, only : effective_radius ! For NRL Ozone use module_ozphys, only: ty_ozphys implicit none @@ -254,12 +240,20 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& real(kind=kind_phys), dimension(im,lm+LTP) :: & qv_mp, qc_mp, qi_mp, qs_mp, & nc_mp, ni_mp, nwfa + ! tempo + real(kind=kind_phys), dimension(im,lm+LTP) :: & + rc, nc, qcten, ncten, mvd_c, & + ri, ni, qiten, niten, & + rs, qsten + + real(kind=kind_dbl_prec), dimension(im,lm+LTP) :: & + ilamc, ilami + + logical, dimension(im,lm+LTP) :: & + l_qc, l_qi, l_qs 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 @@ -762,8 +756,7 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& enddo enddo ! for Thompson MP - prepare variables for calc_effr - if_thompson: if ((imp_physics == imp_physics_thompson .or. & - imp_physics == imp_physics_tempo) .and. (ltaerosol .or. mraerosol)) then + if_thompson: if (imp_physics == imp_physics_thompson .and. (ltaerosol .or. mraerosol)) then do k=1,LMK do i=1,IM qvs = qlyr(i,k) @@ -778,7 +771,7 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& nwfa (i,k) = tracer1(i,k,ntwa) enddo enddo - elseif (imp_physics == imp_physics_thompson .or. imp_physics == imp_physics_tempo) then + elseif (imp_physics == imp_physics_thompson) then do k=1,LMK do i=1,IM qvs = qlyr(i,k) @@ -789,22 +782,48 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& qi_mp (i,k) = tracer1(i,k,ntiw)/(1.-qvs) qs_mp (i,k) = tracer1(i,k,ntsw)/(1.-qvs) 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 - nc_mp (i,k) = Nt_c_l_tempo*orho(i,k) - endif + nc_mp (i,k) = Nt_c_l_thompson*orho(i,k) else - if (imp_physics == imp_physics_thompson) then - nc_mp (i,k) = Nt_c_o_thompson*orho(i,k) - else - nc_mp (i,k) = Nt_c_o_tempo*orho(i,k) - endif + nc_mp (i,k) = Nt_c_o_thompson*orho(i,k) endif ni_mp (i,k) = tracer1(i,k,ntinc)/(1.-qvs) enddo enddo endif if_thompson + if (imp_physics == imp_physics_tempo) then + do k=1,LMK + do i=1,IM + qvs = qlyr(i,k) + qv_mp (i,k) = qvs/(1.-qvs) + rho (i,k) = con_eps*plyr(i,k)*100./(con_rd*tlyr(i,k)*(qv_mp(i,k)+con_eps)) + orho (i,k) = 1.0/rho(i,k) + qc_mp (i,k) = tracer1(i,k,ntcw)/(1.-qvs) + qi_mp (i,k) = tracer1(i,k,ntiw)/(1.-qvs) + qs_mp (i,k) = tracer1(i,k,ntsw)/(1.-qvs) + ni_mp (i,k) = tracer1(i,k,ntinc)/(1.-qvs) + if (ltaerosol) nc_mp (i,k) = tracer1(i,k,ntlnc)/(1.-qvs) + + qcten (i,k) = 0. + ncten (i,k) = 0. + qiten (i,k) = 0. + niten (i,k) = 0. + qsten (i,k) = 0. + enddo + enddo + do i=1,IM + + if (.not. ltaerosol) call get_constant_cloud_number(land=nint(slmsk(i)), nc=nc_mp(i,:)) + + call cloud_check_and_update(rho=rho(i,:), l_qc=l_qc(i,:), qc1d=qc_mp(i,:), & + nc1d=nc_mp(i,:), rc=rc(i,:), nc=nc(i,:), qcten=qcten(i,:), ncten=ncten(i,:), & + ilamc=ilamc(i,:), mvd_c=mvd_c(i,:), dt=1., odt=1.) + call ice_check_and_update(rho=rho(i,:), l_qi=l_qi(i,:), qi1d=qi_mp(i,:), & + ni1d=ni_mp(i,:), ri=ri(i,:), ni=ni(i,:), qiten=qiten(i,:), niten=niten(i,:), & + ilami=ilami(i,:), dt=1., odt=1.) + call snow_check_and_update(rho=rho(i,:), l_qs=l_qs(i,:), qs1d=qs_mp(i,:), & + rs=rs(i,:), qsten=qsten(i,:), dt=1., odt=1.) + enddo + endif endif do n=1,ncndl do k=1,LMK @@ -912,27 +931,21 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& ! not used yet -- effr_in should always be true for now endif - elseif (imp_physics == imp_physics_thompson .or. imp_physics == imp_physics_tempo) then ! Thompson MP + elseif (imp_physics == imp_physics_thompson) then ! Thompson MP ! ! Compute effective radii for QC, QI, QS with (GF, MYNN) or without (all others) sub-grid clouds ! ! Update number concentration, consistent with sub-grid clouds (GF, MYNN) or without (all others) do k=1,lm do i=1,im +! if (imp_physics == imp_physics_thompson) then 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 - nc_mp(i,k) = make_DropletNumber_tempo(qc_mp(i,k)*rho(i,k), nwfa(i,k)*rho(i,k)) * orho(i,k) - endif + nc_mp(i,k) = make_DropletNumber_thompson(qc_mp(i,k)*rho(i,k), nwfa(i,k)*rho(i,k)) * orho(i,k) 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 - ni_mp(i,k) = make_IceNumber_tempo(qi_mp(i,k)*rho(i,k), tlyr(i,k)) * orho(i,k) - endif + ni_mp(i,k) = make_IceNumber_thompson(qi_mp(i,k)*rho(i,k), tlyr(i,k)) * orho(i,k) endif +! endif end do end do !> - Call Thompson's subroutine calc_effectRad() to compute effective radii @@ -943,7 +956,7 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& ! calc_effectRad (4.99-125.0 for WRFv3.8.1; 2.49-125.0 for WRFv4+) ! it will raise the low limit from 5 to 10, but the high limit will remain 125. - if (imp_physics == imp_physics_thompson) then + ! if (imp_physics == imp_physics_thompson) then 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 ) @@ -956,22 +969,33 @@ 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 - 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) - ! Scale Thompson's effective radii from meter to micron + end do + effrr(:,:) = 1000. ! rrain_def=1000. + ! Update global arrays + do k=1,lm + k1 = k + kd + do i=1,im + effrl_inout(i,k) = effrl(i,k1) + effri_inout(i,k) = effri(i,k1) + effrs_inout(i,k) = effrs(i,k1) + enddo + enddo + + elseif (imp_physics == imp_physics_tempo) then ! Tempo + do i=1,im + islmsk = nint(slmsk(i)) + call effective_radius(temp=tlyr(i,:), l_qc=l_qc(i,:), nc=nc_mp(i,:), & + ilamc=ilamc(i,:), l_qi=l_qi(i,:), ilami=ilami(i,:), l_qs=l_qs(i,:), rs=rs(i,:), & + re_qc=effrl(i,:), re_qi=effri(i,:), re_qs=effrs(i,:)) + ! use min/max values from Thompson for now do k=1,lm - effrl(i,k) = MAX(re_qc_min_tempo, MIN(effrl(i,k), re_qc_max_tempo))*1.e6 - effri(i,k) = MAX(re_qi_min_tempo, MIN(effri(i,k), re_qi_max_tempo))*1.e6 - effrs(i,k) = MAX(re_qs_min_tempo, MIN(effrs(i,k), re_qs_max_tempo))*1.e6 + effrl(i,k) = MAX(re_qc_min_thompson, MIN(effrl(i,k), re_qc_max_thompson))*1.e6 + effri(i,k) = MAX(re_qi_min_thompson, MIN(effri(i,k), re_qi_max_thompson))*1.e6 + effrs(i,k) = MAX(re_qs_min_thompson, MIN(effrs(i,k), re_qs_max_thompson))*1.e6 end do - effrl(i,lmk) = re_qc_min_tempo*1.e6 - effri(i,lmk) = re_qi_min_tempo*1.e6 - effrs(i,lmk) = re_qs_min_tempo*1.e6 - endif - + 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 end do effrr(:,:) = 1000. ! rrain_def=1000. ! Update global arrays @@ -982,7 +1006,9 @@ subroutine GFS_rrtmg_pre_run (im, levs, lm, lmk, lmp, n_var_lndp, lextop,& effri_inout(i,k) = effri(i,k1) effrs_inout(i,k) = effrs(i,k1) enddo - enddo + enddo + + else ! all other cases cldcov = 0.0 endif diff --git a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta index 1ed82a176..d293db865 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_rrtmg_pre.meta @@ -3,7 +3,14 @@ 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_v3/src/module_mp_tempo_params.F90 + dependencies = MP/TEMPO/tempo_v3/src/module_mp_tempo_cfgs.F90 + dependencies = MP/TEMPO/tempo_v3/src/module_mp_tempo_ml.F90 + dependencies = MP/TEMPO/tempo_v3/src/module_mp_tempo_utils.F90 + dependencies = MP/TEMPO/tempo_v3/src/module_mp_tempo_aerosols.F90 + dependencies = MP/TEMPO/tempo_v3/src/module_mp_tempo_diags.F90 + dependencies = MP/TEMPO/tempo_v3/src/module_mp_tempo_main.F90 + dependencies = MP/TEMPO/tempo_v3/src/module_mp_tempo_driver.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 @@ -267,13 +274,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/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 index d59b2295b..def35d791 100644 --- a/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 +++ b/physics/Interstitials/UFS_SCM_NEPTUNE/GFS_suite_interstitial_4.F90 @@ -20,10 +20,10 @@ 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 - + implicit none ! interface variables 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 ce8801084..aa796df9d 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/module_mp_tempo_utils_v2.F90 dependencies = MP/Thompson/module_mp_thompson_make_number_concentrations.F90 ######################################################################## diff --git a/physics/MP/TEMPO/TEMPO b/physics/MP/TEMPO/TEMPO deleted file mode 160000 index c62efd27c..000000000 --- a/physics/MP/TEMPO/TEMPO +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c62efd27caa26f660edf24232f33f154e608b77a diff --git a/physics/MP/TEMPO/module_mp_tempo_utils_v2.F90 b/physics/MP/TEMPO/module_mp_tempo_utils_v2.F90 new file mode 100644 index 000000000..b617dcc91 --- /dev/null +++ b/physics/MP/TEMPO/module_mp_tempo_utils_v2.F90 @@ -0,0 +1,164 @@ +! Utilities for TEMPO Microphysics +!================================================================================================================= +module module_mp_tempo_utils_v2 + + use machine, only: wp => kind_phys, sp => kind_sngl_prec, dp => kind_dbl_prec + use module_mp_tempo_params, only: pi, rho_i, am_r + + implicit none + + public +contains + !================================================================================================================= + + !>\ingroup aathompson + !!Table of lookup values of radiative effective radius of ice crystals + !! as a function of Temperature from -94C to 0C. Taken from WRF RRTMG + !! radiation code where it is attributed to Jon Egill Kristjansson + !! and coauthors. + elemental real function make_IceNumber (Q_ice, temp) + + !IMPLICIT NONE + real, intent(in):: Q_ice, temp + integer idx_rei + real corr, reice, deice + double precision lambda + + !+---+-----------------------------------------------------------------+ + !..Table of lookup values of radiative effective radius of ice crystals + !.. as a function of Temperature from -94C to 0C. Taken from WRF RRTMG + !.. radiation code where it is attributed to Jon Egill Kristjansson + !.. and coauthors. + !+---+-----------------------------------------------------------------+ + + real, dimension(95), parameter:: retab = (/ & + 5.92779, 6.26422, 6.61973, 6.99539, 7.39234, & + 7.81177, 8.25496, 8.72323, 9.21800, 9.74075, 10.2930, & + 10.8765, 11.4929, 12.1440, 12.8317, 13.5581, 14.2319, & + 15.0351, 15.8799, 16.7674, 17.6986, 18.6744, 19.6955, & + 20.7623, 21.8757, 23.0364, 24.2452, 25.5034, 26.8125, & + 27.7895, 28.6450, 29.4167, 30.1088, 30.7306, 31.2943, & + 31.8151, 32.3077, 32.7870, 33.2657, 33.7540, 34.2601, & + 34.7892, 35.3442, 35.9255, 36.5316, 37.1602, 37.8078, & + 38.4720, 39.1508, 39.8442, 40.5552, 41.2912, 42.0635, & + 42.8876, 43.7863, 44.7853, 45.9170, 47.2165, 48.7221, & + 50.4710, 52.4980, 54.8315, 57.4898, 60.4785, 63.7898, & + 65.5604, 71.2885, 75.4113, 79.7368, 84.2351, 88.8833, & + 93.6658, 98.5739, 103.603, 108.752, 114.025, 119.424, & + 124.954, 130.630, 136.457, 142.446, 148.608, 154.956, & + 161.503, 168.262, 175.248, 182.473, 189.952, 197.699, & + 205.728, 214.055, 222.694, 231.661, 240.971, 250.639 /) + + if (Q_ice == 0) then + make_IceNumber = 0 + return + end if + + !+---+-----------------------------------------------------------------+ + !..From the model 3D temperature field, subtract 179K for which + !.. index value of retab as a start. Value of corr is for + !.. interpolating between neighboring values in the table. + !+---+-----------------------------------------------------------------+ + + idx_rei = int(temp-179.) + idx_rei = min(max(idx_rei,1),94) + corr = temp - int(temp) + reice = retab(idx_rei)*(1.-corr) + retab(idx_rei+1)*corr + deice = 2.*reice * 1.E-6 + + !+---+-----------------------------------------------------------------+ + !..Now we have the final radiative effective size of ice (as function + !.. of temperature only). This size represents 3rd moment divided by + !.. second moment of the ice size distribution, so we can compute a + !.. number concentration from the mean size and mass mixing ratio. + !.. The mean (radiative effective) diameter is 3./Slope for an inverse + !.. exponential size distribution. So, starting with slope, work + !.. backwords to get number concentration. + !+---+-----------------------------------------------------------------+ + + lambda = 3.0 / deice + make_IceNumber = Q_ice * lambda*lambda*lambda / (PI*rho_i) + + !+---+-----------------------------------------------------------------+ + !..Example1: Common ice size coming from Thompson scheme is about 30 microns. + !.. An example ice mixing ratio could be 0.001 g/kg for a temperature of -50C. + !.. Remember to convert both into MKS units. This gives N_ice=357652 per kg. + !..Example2: Lower in atmosphere at T=-10C matching ~162 microns in retab, + !.. and assuming we have 0.1 g/kg mixing ratio, then N_ice=28122 per kg, + !.. which is 28 crystals per liter of air if the air density is 1.0. + !+---+-----------------------------------------------------------------+ + + return + end function make_IceNumber + + !================================================================================================================= + elemental real function make_DropletNumber (Q_cloud, qnwfa) + + !IMPLICIT NONE + + real, intent(in):: Q_cloud, qnwfa + + real, dimension(15), parameter:: g_ratio = (/24,60,120,210,336, & + & 504,720,990,1320,1716,2184,2730,3360,4080,4896/) + double precision:: lambda, qnc + real:: q_nwfa, x1, xDc + integer:: nu_c + + if (Q_cloud == 0) then + make_DropletNumber = 0 + return + end if + + !+---+ + + q_nwfa = MAX(99.E6, MIN(qnwfa,5.E10)) + nu_c = MAX(2, MIN(NINT(2.5E10/q_nwfa), 15)) + + x1 = MAX(1., MIN(q_nwfa*1.E-9, 10.)) - 1. + xDc = (30. - x1*20./9.) * 1.E-6 + + lambda = (4.0D0 + nu_c) / xDc + qnc = Q_cloud / g_ratio(nu_c) * lambda*lambda*lambda / am_r + make_DropletNumber = SNGL(qnc) + + return + end function make_DropletNumber + + !================================================================================================================= + elemental real function make_RainNumber (Q_rain, temp) + + IMPLICIT NONE + + real, intent(in):: Q_rain, temp + double precision:: lambda, N0, qnr + + if (Q_rain == 0) then + make_RainNumber = 0 + return + end if + + !+---+-----------------------------------------------------------------+ + !.. Not thrilled with it, but set Y-intercept parameter to Marshal-Palmer value + !.. that basically assumes melting snow becomes typical rain. However, for + !.. -2C < T < 0C, make linear increase in exponent to attempt to keep + !.. supercooled collision-coalescence (warm-rain) similar to drizzle rather + !.. than bigger rain drops. While this could also exist at T>0C, it is + !.. more difficult to assume it directly from having mass and not number. + !+---+-----------------------------------------------------------------+ + + N0 = 8.E6 + + if (temp .le. 271.15) then + N0 = 8.E8 + elseif (temp .gt. 271.15 .and. temp.lt.273.15) then + N0 = 8. * 10**(279.15-temp) + endif + + lambda = SQRT(SQRT(N0*am_r*6.0/Q_rain)) + qnr = Q_rain / 6.0 * lambda*lambda*lambda / am_r + make_RainNumber = SNGL(qnr) + + return + end function make_RainNumber + +end module module_mp_tempo_utils_v2 diff --git a/physics/MP/TEMPO/mp_tempo.F90 b/physics/MP/TEMPO/mp_tempo.F90 index 94b7745a9..d7ea315f7 100644 --- a/physics/MP/TEMPO/mp_tempo.F90 +++ b/physics/MP/TEMPO/mp_tempo.F90 @@ -9,9 +9,12 @@ module mp_tempo use mpi_f08 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 + !physical constants that are set from the host + use module_mp_tempo_params, only : pi, lvap0, lfus, lsub, rv, rdry, cp, t0, r_uni, rho_w + use module_mp_tempo_params, only : roverrv, eps, naccn0, naccn1, nain0, nain1 + use module_mp_tempo_params, only : initialize_parameters + use module_mp_tempo_cfgs, only : ty_tempo_cfgs + use module_mp_tempo_driver, only : tempo_init, tempo_run, ty_tempo_driver_diags, tempo_aerosol_surface_emissions implicit none @@ -19,126 +22,111 @@ 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, & + mpirank, mpiroot, & + tgrs, prsl, phil, con_pi, con_hvap, con_hfus, & + con_rv, con_g, con_rd, con_cp, & + con_t0c, con_rgas, rhowater, & + 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_pi, con_hvap, con_hfus, & + con_rv, con_g, con_rd, con_cp, & + con_t0c, con_rgas, rhowater + ! 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 + if (do_sat_adj) then + if ((is_aerosol_aware) .or. (is_hail_aware)) then + write(errmsg, fmt='((a))') 'do_sat_adj should be run with is_aerosol_aware=F and is_hail_aware=F' + errflg = 1 + return + endif + end if + if (is_initialized) return ! 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() with ltaerosol= ', is_aerosol_aware, & + ' lthailaware= ', is_hail_aware, ' sedi_semi= ', semi_sedi, ' do_sat_adj= ', do_sat_adj - 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=is_aerosol_aware, hailaware_flag=is_hail_aware, & + semi_sedi_flag=semi_sedi, cloud_condensation_flag=(.not. do_sat_adj), & + tempo_cfgs=tempo_cfgs) + + ! Set local TEMPO MP module constants from host model and overwrite derived constants calculated in module_mp_tempo_params/initialize_parameters() + pi = con_pi + lvap0 = con_hvap + lfus = con_hfus + lsub = lvap0 + lfus + rv = con_rv + rdry = con_rd + cp = con_cp + t0 = con_t0c + r_uni = con_rgas + rho_w = rhowater + + ! Although initialize_parameters() is already called during the call to tempo_init() above, it needs to be called again with the host-set constants to recalculate dependent parameters + call initialize_parameters() - ! 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 @@ -146,109 +134,30 @@ subroutine mp_tempo_init(ncol, nlev, con_pi, con_t0c, con_rv, & is_initialized = .true. 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) + where(spechum<0) spechum = 1.0e-10 + 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)) + rho = roverrv*prsl/(rdry*tgrs*(qv+roverrv)) 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 +175,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 +213,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,99 +244,69 @@ 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, ten_q, dspechum, & - dqc, dqr, dqi, dqs, dqg, dni, dnr, & - dnc, dnwfa, dnifa, dchw, dvh, dtgrs, & - ten_u, ten_v, errmsg, errflg) +!>\section gen_tempo TEMPO MP General Algorithm + subroutine mp_tempo_run(ncol, nlev, blkno, & + convert_dry_rho, dtp, dt_inner, & + spechum, qc, qr, qi, qs, qg, ni, nr, & + nc, nwfa, nifa, nwfa2d, nifa2d, ng, volg, & + con_g, first_time_step, & + tgrs, prsl, phii, omega, & + is_aerosol_aware, is_hail_aware, & + prcp, rain, graupel, ice, snow, sr, refl_10cm, & + do_radar_ref, & + is_initialized, tempo_cfgs, ten_q, ten_t, ten_u, ten_v, & + dspechum, dqc, dqr, dqi, dqs, dqg, dni, dnr, dnc, dnwfa, & + dnifa, dng, dvolg, errmsg, errflg) - implicit none ! Interface variables - logical, intent(inout) :: is_initialized + 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 real(kind_phys), intent(in ) :: con_g - 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(in ) :: spechum(:,:) - real(kind_phys), intent(in ) :: qc(:,:) - real(kind_phys), intent(in ) :: qr(:,:) - real(kind_phys), intent(in ) :: qi(:,:) - real(kind_phys), intent(in ) :: qs(:,:) - real(kind_phys), intent(in ) :: qg(:,:) - real(kind_phys), intent(in ) :: ni(:,:) - real(kind_phys), intent(in ) :: nr(:,:) - real(kind_phys), optional, intent(in ) :: 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(in ) :: nc(:,:) - real(kind_phys), optional, intent(in ) :: nwfa(:,:) - real(kind_phys), optional, intent(in ) :: nifa(:,:) + real(kind_phys), intent(in) :: spechum(:,:) + real(kind_phys), intent(in) :: qc(:,:) + real(kind_phys), intent(in) :: qr(:,:) + real(kind_phys), intent(in) :: qi(:,:) + real(kind_phys), intent(in) :: qs(:,:) + real(kind_phys), intent(in) :: qg(:,:) + real(kind_phys), intent(in) :: ni(:,:) + real(kind_phys), intent(in) :: nr(:,:) + real(kind_phys), optional, intent(in) :: nc(:,:) + real(kind_phys), optional, intent(in) :: nwfa(:,:) + real(kind_phys), optional, intent(in) :: 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(in) :: ng(:,:) + real(kind_phys), optional, intent(in) :: 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(in ) :: 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(kind=kind_phys), 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 real(kind_phys), intent( out) :: ten_q(:,:,:) + real(kind_phys), intent( out) :: ten_t(:,:) real(kind_phys), intent( out) :: ten_u(:,:) real(kind_phys), intent( out) :: ten_v(:,:) real(kind_phys), intent( out) :: dspechum(:,:) @@ -478,32 +320,19 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & real(kind_phys), optional, intent( out) :: dnc(:,:) real(kind_phys), optional, intent( out) :: dnwfa(:,:) real(kind_phys), optional, intent( out) :: dnifa(:,:) - real(kind_phys), optional, intent( out) :: dchw(:,:) - real(kind_phys), optional, intent( out) :: dvh(:,:) - real(kind_phys), intent( out) :: dtgrs(:,:) + real(kind_phys), optional, intent( out) :: dng(:,:) + real(kind_phys), optional, intent( out) :: dvolg(:,:) ! 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 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) @@ -511,16 +340,10 @@ 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) :: xnwfa(1:ncol,1:nlev,1) + real(kind_phys) :: xnwfa2d(1:ncol,1) + !temporary new states used to calculate tendencies real(kind_phys) :: new_spechum(1:ncol,1:nlev) real(kind_phys) :: new_qc(1:ncol,1:nlev) real(kind_phys) :: new_qr(1:ncol,1:nlev) @@ -529,78 +352,32 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & real(kind_phys) :: new_qg(1:ncol,1:nlev) real(kind_phys) :: new_ni(1:ncol,1:nlev) real(kind_phys) :: new_nr(1:ncol,1:nlev) - real(kind_phys), allocatable :: new_nc(:,:), new_nwfa(:,:), new_nifa(:,:) - real(kind_phys), allocatable :: new_chw(:,:), new_vh(:,:) + real(kind_phys), allocatable :: new_nc(:,:) + real(kind_phys), allocatable :: new_nwfa(:,:) + real(kind_phys), allocatable :: new_nifa(:,:) + real(kind_phys), allocatable :: new_ng(:,:) + real(kind_phys), allocatable :: new_volg(:,:) real(kind_phys) :: new_tgrs(1:ncol,1:nlev) - - 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 :: ndt, i, k, it 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 - + ten_q = 0.0 ! Since this scheme is outputting tracer tendencies individually, ! we also need to initialize the entire array to 0, so that when ! tendencies are applied, all tracer tendencies other than those ! set in this scheme are 0. + ten_t = 0.0 ten_u = 0.0 ten_v = 0.0 + dspechum = 0.0 dqc = 0.0 dqr = 0.0 @@ -609,7 +386,6 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & dqg = 0.0 dni = 0.0 dnr = 0.0 - dtgrs = 0.0 new_spechum = spechum new_qc = qc @@ -620,8 +396,8 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & new_ni = ni new_nr = nr new_tgrs = tgrs - - if (is_aerosol_aware .or. merra2_aerosol_aware) then + + if (is_aerosol_aware) then dnc = 0.0 dnwfa = 0.0 dnifa = 0.0 @@ -633,90 +409,33 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & new_nwfa = nwfa new_nifa = nifa endif - + if (is_hail_aware) then - dchw = 0.0 - dvh = 0.0 + dng = 0.0 + dvolg = 0.0 - allocate(new_chw(ncol,nlev)) - allocate(new_vh(ncol,nlev)) - new_chw = chw - new_vh = vh - endif - - 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 + allocate(new_ng(ncol,nlev)) + allocate(new_volg(ncol,nlev)) + new_ng = ng + new_volg = volg endif - if (first_time_step .and. istep==1 .and. blkno==1) then + if (first_time_step .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 - - ! 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, new_nifa, new_nwfa, ncol, nlev) - 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 !> - 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 = new_spechum/(1.0_kind_phys-new_spechum) if (convert_dry_rho) then @@ -725,50 +444,22 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & new_qi = new_qi/(1.0_kind_phys-new_spechum) new_qs = new_qs/(1.0_kind_phys-new_spechum) new_qg = new_qg/(1.0_kind_phys-new_spechum) - new_ni = new_ni/(1.0_kind_phys-new_spechum) new_nr = new_nr/(1.0_kind_phys-new_spechum) if (is_hail_aware) then - new_chw = new_chw/(1.0_kind_phys-new_spechum) - new_vh = new_vh/(1.0_kind_phys-new_spechum) + new_ng = new_ng/(1.0_kind_phys-new_spechum) + new_volg = new_volg/(1.0_kind_phys-new_spechum) endif - if (is_aerosol_aware .or. merra2_aerosol_aware) then + if (is_aerosol_aware) then new_nc = new_nc/(1.0_kind_phys-new_spechum) new_nwfa = new_nwfa/(1.0_kind_phys-new_spechum) new_nifa = new_nifa/(1.0_kind_phys-new_spechum) end if end if - ! *DH - - !> - Density of air in kg m-3 - rho = con_eps*prsl/(con_rd*new_tgrs*(qv+con_eps)) - - !> - Convert omega in Pa s-1 to vertical velocity w in m s-1 - w = -omega/(rho*con_g) !> - 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 @@ -788,260 +479,56 @@ 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=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, qb=new_vh, ni=new_ni, nr=new_nr, & - nc=new_nc, ng=new_chw, nwfa=new_nwfa, nifa=new_nifa, nwfa2d=nwfa2d, nifa2d=nifa2d, & - tt=new_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 + ! handle dt_inner < dtp + do it = 1, ndt + + !> - Density of air in kg m-3 + rho = roverrv*prsl/(rdry*new_tgrs*(qv+roverrv)) + + !> - Convert omega in Pa s-1 to vertical velocity w in m s-1 + w = -omega/(rho*con_g) + + 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) + new_nwfa(:,:) = xnwfa(:,:,1) + endif + + call tempo_run(tempo_cfgs=tempo_cfgs, & + dt=dt, itimestep=itimestep , & + qv=qv, qc=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, ni=new_ni, nr=new_nr, & + nc=new_nc, nwfa=new_nwfa, nifa=new_nifa, & + ng=new_ng, qb=new_volg, & + w=w, t=new_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) + + 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 + enddo + + ! diagnostics that are not precipitation don't need to be in the inner time loop + sr = tempo_driver_diags%frozen_fraction(:,1) -! write(errmsg,'(*(a))') "TEMPO aerosol-aware UNTESTED -- DO NOT USE" -! errflg = 1 -! return - call tempo_3d_to_1d_driver(qv=qv, qc=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, ni=new_ni, nr=new_nr, & - nc=new_nc, nwfa=new_nwfa, nifa=new_nifa, nwfa2d=nwfa2d, nifa2d=nifa2d, & - tt=new_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, + if (do_radar_ref) then + refl_10cm = tempo_driver_diags%refl10cm(:,:,1) 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=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, ni=new_ni, nr=new_nr, & - nc=new_nc, nwfa=new_nwfa, nifa=new_nifa, & - tt=new_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=new_qc, qr=new_qr, qi=new_qi, qs=new_qs, qg=new_qg, ni=new_ni, nr=new_nr, & - tt=new_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 - 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. + itimestep = itimestep + 1 + + if (errflg/=0) return !> - Convert water vapor mixing ratio back to specific humidity new_spechum = qv/(1.0_kind_phys+qv) @@ -1052,41 +539,19 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & new_qi = new_qi/(1.0_kind_phys+qv) new_qs = new_qs/(1.0_kind_phys+qv) new_qg = new_qg/(1.0_kind_phys+qv) - new_ni = new_ni/(1.0_kind_phys+qv) new_nr = new_nr/(1.0_kind_phys+qv) if (is_hail_aware) then - new_chw = new_chw/(1.0_kind_phys+qv) - new_vh = new_vh/(1.0_kind_phys+qv) + new_ng = new_ng/(1.0_kind_phys+qv) + new_volg = new_volg/(1.0_kind_phys+qv) endif - if (is_aerosol_aware .or. merra2_aerosol_aware) then + if (is_aerosol_aware) then new_nc = new_nc/(1.0_kind_phys+qv) new_nwfa = new_nwfa/(1.0_kind_phys+qv) new_nifa = new_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 - dspechum = (new_spechum - spechum)/dtp dqc = (new_qc - qc)/dtp dqr = (new_qr - qr)/dtp @@ -1095,78 +560,28 @@ subroutine mp_tempo_run(ncol, nlev, con_g, con_rd, & dqg = (new_qg - qg)/dtp dni = (new_ni - ni)/dtp dnr = (new_nr - nr)/dtp - dtgrs = (new_tgrs - tgrs)/dtp + ten_t = (new_tgrs - tgrs)/dtp if (is_hail_aware) then - dchw = (new_chw - chw)/dtp - dvh = (new_vh - vh)/dtp + dng = (new_ng - ng)/dtp + dvolg = (new_volg - volg)/dtp - deallocate (new_chw, new_vh) + deallocate (new_ng, new_volg) end if - if (is_aerosol_aware .or. merra2_aerosol_aware) then + if (is_aerosol_aware) then dnc = (new_nc - nc)/dtp dnwfa = (new_nwfa - nwfa)/dtp dnifa = (new_nifa - nifa)/dtp deallocate(new_nc, new_nwfa, new_nifa) 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 @@ -1177,55 +592,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 +end module mp_tempo \ No newline at end of file diff --git a/physics/MP/TEMPO/mp_tempo.meta b/physics/MP/TEMPO/mp_tempo.meta index b994d5ce7..c736bc122 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,74 +29,60 @@ 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 +[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_rv] - standard_name = gas_constant_water_vapor - long_name = ideal gas constant for water vapor - units = J kg-1 K-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_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 + 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_rgas] - standard_name = molar_gas_constant - long_name = universal ideal molar gas constant - units = J K-1 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_boltz] - standard_name = boltzmann_constant - long_name = Boltzmann constant - units = J K-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_amd] - standard_name = molecular_weight_of_dry_air - long_name = molecular weight of dry air - units = g mol-1 +[mpirank] + standard_name = mpi_rank + long_name = current MPI-rank + units = index 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 +[mpiroot] + standard_name = mpi_root + long_name = master MPI-rank + units = index dimensions = () - type = real - kind = kind_phys + type = integer intent = in -[con_avgd] - standard_name = avogadro_constant - long_name = Avogadro constant - units = mol-1 +[con_pi] + standard_name = pi + long_name = ratio of a circle's circumference to its diameter + units = none dimensions = () type = real kind = kind_phys @@ -114,6 +103,14 @@ 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_g] standard_name = gravitational_acceleration long_name = gravitational acceleration @@ -130,34 +127,44 @@ 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 +[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 dimensions = () type = real kind = kind_phys intent = in -[restart] - standard_name = flag_for_restart - long_name = flag for restart (warmstart) or coldstart - units = flag +[con_t0c] + standard_name = temperature_at_zero_celsius + long_name = temperature at 0 degree Celsius + units = K dimensions = () - type = logical + type = real + kind = kind_phys intent = in -[imp_physics] - standard_name = control_for_microphysics_scheme - long_name = choice of microphysics scheme - units = flag +[con_rgas] + standard_name = molar_gas_constant + long_name = universal ideal molar gas constant + units = J K-1 mol-1 dimensions = () - type = integer + type = real + kind = kind_phys intent = in -[imp_physics_tempo] - standard_name = identifier_for_tempo_microphysics_scheme - long_name = choice of TEMPO microphysics scheme +[rhowater] + standard_name = fresh_liquid_water_density_at_0c + long_name = density of liquid water + units = kg m-3 + dimensions = () + type = real + kind = kind_phys + intent = in +[restart] + standard_name = flag_for_restart + long_name = flag for restart (warmstart) or coldstart units = flag dimensions = () - type = integer + type = logical intent = in [convert_dry_rho] standard_name = flag_for_converting_hydrometeors_from_moist_to_dry_air @@ -166,88 +173,6 @@ dimensions = () type = logical intent = in -[spechum] - standard_name = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 = physics_timestep_initial_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 +187,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 = physics_timestep_initial_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 = physics_timestep_initial_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 @@ -297,7 +228,7 @@ intent = inout optional = True [nwfa] - standard_name = physics_timestep_initial_mass_number_concentration_of_hygroscopic_aerosols + standard_name = mass_number_concentration_of_hygroscopic_aerosols long_name = number concentration of water-friendly aerosols units = kg-1 dimensions = (horizontal_dimension,vertical_layer_dimension) @@ -306,7 +237,7 @@ intent = inout optional = True [nifa] - standard_name = physics_timestep_initial_mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols + standard_name = mass_number_concentration_of_nonhygroscopic_ice_nucleating_aerosols long_name = number concentration of ice-friendly aerosols units = kg-1 dimensions = (horizontal_dimension,vertical_layer_dimension) @@ -314,6 +245,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 = physics_timestep_initial_air_temperature long_name = model layer mean temperature @@ -338,88 +276,6 @@ 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 - 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 - 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 -[threads] - standard_name = number_of_openmp_threads - long_name = number of OpenMP threads available to scheme - units = count - 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 - 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] @@ -439,37 +295,36 @@ dimensions = () type = integer intent = in -[con_g] - standard_name = gravitational_acceleration - long_name = gravitational acceleration - units = m s-2 +[blkno] + standard_name = ccpp_block_number + long_name = number of block for explicit data blocking in CCPP + units = index dimensions = () - type = real - kind = kind_phys + type = integer 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 +[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 + units = flag + dimensions = () + type = logical + intent = in +[dtp] + standard_name = timestep_for_physics + long_name = physics timestep + units = s 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 +[dt_inner] + standard_name = time_step_for_inner_loop + long_name = time step for inner loop + units = s 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 - units = flag - dimensions = () - type = logical - intent = in [spechum] standard_name = specific_humidity long_name = water vapor specific humidity @@ -493,7 +348,7 @@ dimensions = (horizontal_loop_extent,vertical_layer_dimension) type = real kind = kind_phys - intent = in + intent = inout [qi] standard_name = cloud_ice_mixing_ratio long_name = ice water mixing ratio wrt dry+vapor (no condensates) @@ -518,24 +373,6 @@ type = real kind = kind_phys intent = in -[chw] - standard_name = mass_number_concentration_of_graupel - long_name = graupel number concentration - units = kg-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = in - optional = True -[vh] - standard_name = graupel_volume - long_name = graupel particle volume - units = m3 kg-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = in - optional = True [ni] standard_name = mass_number_concentration_of_cloud_ice_water_crystals_in_air long_name = ice number concentration @@ -552,27 +389,6 @@ type = real kind = kind_phys intent = in -[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 long_name = cloud droplet number concentration @@ -618,9 +434,35 @@ 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 +[ng] + standard_name = mass_number_concentration_of_graupel + long_name = graupel number concentration + units = kg-1 + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + type = real + kind = kind_phys + intent = in + optional = True +[volg] + standard_name = graupel_volume + long_name = graupel particle volume + units = m3 kg-1 + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + type = real + kind = kind_phys + intent = in + optional = True +[con_g] + standard_name = gravitational_acceleration + long_name = gravitational acceleration + units = m s-2 + dimensions = () + 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 @@ -657,64 +499,20 @@ 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 +[is_aerosol_aware] + standard_name = flag_for_aerosol_physics + long_name = flag for aerosol-aware physics units = flag dimensions = () type = logical intent = in -[decfl] - standard_name = deformed_CFL_factor - long_name = deformed CFL factor - units = count - 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 -[dtp] - standard_name = timestep_for_physics - long_name = physics timestep - units = s - dimensions = () - type = real - kind = kind_phys - intent = in -[dt_inner] - standard_name = time_step_for_inner_loop - long_name = time step for inner loop - units = s - dimensions = () - 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) +[is_hail_aware] + standard_name = flag_for_hail_physics + long_name = flag for hail-aware physics 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 @@ -731,7 +529,6 @@ type = real kind = kind_phys intent = inout - optional = True [graupel] standard_name = lwe_thickness_of_graupel_amount long_name = graupel fall on physics timestep @@ -740,7 +537,6 @@ type = real kind = kind_phys intent = inout - optional = True [ice] standard_name = lwe_thickness_of_ice_amount long_name = ice fall on physics timestep @@ -749,7 +545,6 @@ type = real kind = kind_phys intent = inout - optional = True [snow] standard_name = lwe_thickness_of_snow_amount long_name = snow fall on physics timestep @@ -758,7 +553,6 @@ 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 @@ -775,21 +569,6 @@ type = real kind = kind_phys intent = inout -[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 @@ -797,152 +576,49 @@ 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_initialized] + standard_name = flag_for_tempo_mp_scheme_initialization + long_name = flag carrying scheme initialization status 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 - kind = kind_phys - 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 +[tempo_cfgs] + standard_name = configuration_for_TEMPO_microphysics + long_name = configuration information for TEMPO microphysics + units = mixed 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 = ty_tempo_cfgs +[ten_q] + standard_name = tendency_of_tracer_concentration + long_name = tendency of tracer concentration calculated by one physics scheme + units = kg kg-1 s-1 + dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_tracers) 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) - 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 + intent = out +[ten_t] + standard_name = tendency_of_air_temperature + long_name = tendency of air temperature calculated by one physics scheme + units = K 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 + intent = out +[ten_u] + standard_name = tendency_of_x_wind + long_name = tendency of x wind calculated by one physics scheme + units = m s-2 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 -[ten_q] - standard_name = tendency_of_tracer_concentration - long_name = tendency of tracer concentration calculated by one physics scheme - units = kg kg-1 s-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_tracers) + intent = out +[ten_v] + standard_name = tendency_of_y_wind + long_name = tendency of y wind calculated by one physics scheme + units = m s-2 + dimensions = (horizontal_loop_extent,vertical_layer_dimension) type = real kind = kind_phys intent = out @@ -1037,7 +713,7 @@ kind = kind_phys intent = out optional = True -[dchw] +[dng] standard_name = tendency_of_mass_number_concentration_of_graupel long_name = number concentration of graupel tendency units = kg-1 s-1 @@ -1046,7 +722,7 @@ kind = kind_phys intent = out optional = True -[dvh] +[dvolg] standard_name = tendency_of_graupel_volume long_name = graupel volume tendency units = m3 kg-1 s-1 @@ -1055,30 +731,6 @@ kind = kind_phys intent = out optional = True -[dtgrs] - standard_name = tendency_of_air_temperature - long_name = tendency of air temperature calculated by one physics scheme - units = K s-1 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = out -[ten_u] - standard_name = tendency_of_x_wind - long_name = tendency of x wind calculated by one physics scheme - units = m s-2 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = out -[ten_v] - standard_name = tendency_of_y_wind - long_name = tendency of y wind calculated by one physics scheme - units = m s-2 - dimensions = (horizontal_loop_extent,vertical_layer_dimension) - type = real - kind = kind_phys - intent = out [errmsg] standard_name = ccpp_error_message long_name = error message for error handling in CCPP @@ -1093,14 +745,14 @@ units = 1 dimensions = () type = integer - intent = out - + 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 = () @@ -1120,4 +772,4 @@ units = 1 dimensions = () type = integer - intent = out + intent = out \ No newline at end of file diff --git a/physics/MP/TEMPO/mp_tempo_condensation.F90 b/physics/MP/TEMPO/mp_tempo_condensation.F90 new file mode 100644 index 000000000..5177b88ef --- /dev/null +++ b/physics/MP/TEMPO/mp_tempo_condensation.F90 @@ -0,0 +1,190 @@ +!>\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, kind_dbl_prec + + use module_mp_tempo_params, only : roverrv, rv, rdry, eps, r1, t0, cp, initialize_parameters + 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, get_constant_cloud_number + + 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) :: qc_mixing_ratio(is:ie, js:je, 1:km) + real(kind_phys) :: nc3d(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_dbl_prec) :: 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) :: condensation(is:ie, js:je, 1:km) + real(kind_phys) :: orho, clap, fcd, dfcd, xrc, odt + + ! CCPP error handling + character(len=*), intent( out) :: errmsg + integer, intent( out) :: errflg + integer :: i, j, k, n + logical, save :: need_tempo_params = .true. + + ! Initialize the CCPP error handling variables + errmsg = '' + errflg = 0 + odt = 1._kind_phys/real(mdt,kind=kind_phys) + + if (need_tempo_params) then + call initialize_parameters() + need_tempo_params = .false. + endif + + if (mpirank == mpiroot) write(*,*) 'tempo condensation on re-mapping timestep' + 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_mixing_ratio(i,j,k) = real(qc(i,j,k),kind=kind_phys) / (1._kind_phys-real(spechum(i,j,k),kind=kind_phys)) ! convert from moist to dry rho + temp(i,j,k) = tgrs(i,j,k) / ((0.608 * spechum(i,j,k)) + 1.) ! tgrs is virtual temperature + 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(real(exp(prsl(i,k,j)),kind=kind_phys), real(temp(i,j,k),kind=kind_phys)) ! prsl is log pressure + enddo + enddo + enddo + + condensation = 0. + do j = js, je + do i = is, ie + l_qc = .false. + rc = 0. + nc = 0. + qcten = 0. + ncten = 0. + + call get_constant_cloud_number(nc=nc3d(i,j,:)) + + ! returns cloud mass concentration + call cloud_check_and_update(dt=real(mdt,kind=kind_phys), odt=odt, rho=rho(i,j,:), l_qc=l_qc, & + qc1d=qc_mixing_ratio(i,j,:), nc1d=nc3d(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 + condensation(i,j,k) = clap / mdt + + if (l_qc(k) .and. ssatw(k) < -1.e-6 .and. clap < -eps) then ! evaporation + condensation(i,j,k) = max(-rc(k)*0.99*orho/mdt, condensation(i,j,k)) + endif + else + condensation(i,j,k) = -rc(k)*orho/mdt + endif + endif + + qv(i,j,k) = qv(i,j,k) - condensation(i,j,k)*mdt + qc_mixing_ratio(i,j,k) = qc_mixing_ratio(i,j,k) + condensation(i,j,k)*mdt + temp(i,j,k) = temp(i,j,k) + lvap(k)*ocp(k)*condensation(i,j,k)*mdt + enddo + + call cloud_check_and_update(dt=real(mdt,kind=kind_phys), odt=odt, rho=rho(i,j,:), l_qc=l_qc, & + qc1d=qc_mixing_ratio(i,j,:), nc1d=nc3d(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, real(qv(i,j,k),kind=kind_dyn)/(1. + real(qv(i,j,k), kind=kind_dyn))) + qc(i,j,k) = real(qc_mixing_ratio(i,j,k), kind=kind_dyn)/(1. + real(qv(i,j,k), kind=kind_dyn)) + tgrs(i,j,k) = temp(i,j,k)*((0.608*spechum(i,j,k)) + 1.) + 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..ce80fe907 --- /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=* + 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 new file mode 160000 index 000000000..20fac698c --- /dev/null +++ b/physics/MP/TEMPO/tempo_v3 @@ -0,0 +1 @@ +Subproject commit 20fac698c55dcf15e0ebbd838bb7196d509e7464 diff --git a/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90 b/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.F90 index 0ce7b5fa9..beab00d81 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, & @@ -450,7 +452,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. @@ -475,7 +477,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. @@ -860,7 +862,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 @@ -897,7 +899,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 0412ad928..0e240d7bc 100644 --- a/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.meta +++ b/physics/PBL/MYNN_EDMF/mynnedmf_wrapper.meta @@ -1410,6 +1410,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 diff --git a/physics/Radiation/radiation_clouds.f b/physics/Radiation/radiation_clouds.f index efcafb432..c18392b74 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_mg, iovr, iovr_rand, iovr_maxrand, iovr_max, ! ! iovr_dcorr, iovr_exp, iovr_exprand, idcor, idcor_con, ! ! idcor_hogan, idcor_oreopoulos, ! @@ -422,6 +423,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_mg : Morrison-Gettelman microphysics scheme ! ! iovr : choice of cloud-overlap !