From c61d9f194415061b28380ddd3a69136e337c412e Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Mon, 1 Dec 2025 23:49:21 +0000 Subject: [PATCH 1/8] - removed unused configuration variable - added graupel volume to init_atmosphere registry - formatted code --- src/core_init_atmosphere/Registry.xml | 26 +++++++++---------- .../mpas_init_atm_cases.F | 4 --- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/core_init_atmosphere/Registry.xml b/src/core_init_atmosphere/Registry.xml index 8e3b34bed2..9dc479f15b 100644 --- a/src/core_init_atmosphere/Registry.xml +++ b/src/core_init_atmosphere/Registry.xml @@ -326,11 +326,6 @@ description="Whether to interpolate first-guess fields from intermediate file" possible_values="true or false"/> - - - - - + + + @@ -1234,7 +1229,7 @@ description="Graupel mixing ratio"/> + description="Hail mixing ratio"/> @@ -1251,6 +1246,9 @@ + + @@ -1302,7 +1300,7 @@ - - + - + diff --git a/src/core_init_atmosphere/mpas_init_atm_cases.F b/src/core_init_atmosphere/mpas_init_atm_cases.F index ef31596e99..9120567727 100644 --- a/src/core_init_atmosphere/mpas_init_atm_cases.F +++ b/src/core_init_atmosphere/mpas_init_atm_cases.F @@ -70,7 +70,6 @@ subroutine init_atm_setup_case(domain, stream_manager) logical, pointer :: config_native_gwd_static logical, pointer :: config_native_gwd_gsl_static logical, pointer :: config_met_interp - logical, pointer :: config_aerosol_climo logical, pointer :: config_blend_bdy_terrain character (len=StrKIND), pointer :: config_start_time character (len=StrKIND), pointer :: config_met_prefix @@ -232,7 +231,6 @@ subroutine init_atm_setup_case(domain, stream_manager) call mpas_pool_get_config(block_ptr % configs, 'config_native_gwd_static', config_native_gwd_static) call mpas_pool_get_config(block_ptr % configs, 'config_native_gwd_gsl_static', config_native_gwd_gsl_static) call mpas_pool_get_config(block_ptr % configs, 'config_met_interp', config_met_interp) - call mpas_pool_get_config(block_ptr % configs, 'config_aerosol_climo', config_aerosol_climo) call mpas_pool_get_config(block_ptr % configs, 'config_blend_bdy_terrain', config_blend_bdy_terrain) call mpas_pool_get_subpool(block_ptr % structs, 'mesh', mesh) @@ -397,8 +395,6 @@ subroutine init_atm_setup_case(domain, stream_manager) call mpas_pool_get_dimension(block_ptr % dimensions, 'nEdges', nEdges) call mpas_pool_get_dimension(block_ptr % dimensions, 'nVertLevels', nVertLevels) - call mpas_pool_get_config(block_ptr % configs, 'config_aerosol_climo', config_aerosol_climo) - call mpas_get_time(curr_time, dateTimeString=timeString) xtime = timeString ! Set field valid time, xtime, to the current time in the time loop time_since_start = curr_time - start_time From 4e732be9034983c0e4994fb9cbe3969a69690bcf Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Tue, 2 Dec 2025 01:02:36 +0000 Subject: [PATCH 2/8] - cleaned up core_atmosphere registry for tempo --- src/core_atmosphere/Registry.xml | 60 ++++++++++++++++---------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/core_atmosphere/Registry.xml b/src/core_atmosphere/Registry.xml index e10a20dcfa..b04e0e420d 100644 --- a/src/core_atmosphere/Registry.xml +++ b/src/core_atmosphere/Registry.xml @@ -421,9 +421,9 @@ - - - + + + @@ -2765,29 +2765,34 @@ units="-" description="configuration for cloud microphysics schemes" possible_values="`suite',`mp_wsm6',`mp_tempo',`mp_thompson',`mp_thompson_aerosols', `mp_kessler',`mp_nssl2m',`off'"/> + + - - - - - - @@ -2988,11 +2993,6 @@ description="configuration for spp boundary layer" possible_values="`0: off',`1: activated'"/> - - - - - - - Date: Sat, 13 Dec 2025 22:55:25 +0000 Subject: [PATCH 3/8] cleaned up mpas tempo driver call and removed tempo table build from mpas --- src/core_atmosphere/physics/Makefile | 4 +- .../mpas_atmphys_driver_microphysics.F | 137 ++++----------- .../physics/mpas_atmphys_init_tempo.F | 158 +----------------- .../physics/physics_noaa/TEMPO | 2 +- src/core_atmosphere/utils/Makefile | 14 +- 5 files changed, 37 insertions(+), 278 deletions(-) diff --git a/src/core_atmosphere/physics/Makefile b/src/core_atmosphere/physics/Makefile index 2fe1019b08..fa2dd14cb6 100644 --- a/src/core_atmosphere/physics/Makefile +++ b/src/core_atmosphere/physics/Makefile @@ -65,7 +65,7 @@ core_physics_mmm: core_physics_init (cd physics_mmm; $(MAKE) -f Makefile.mpas all) core_microphysics: core_physics_init core_physics_mmm - (cd physics_noaa/TEMPO; cp ./drivers/mpas/module_mp_tempo.F90 .; $(MAKE) all COREDEF="$(COREDEF)") + (cd physics_noaa/TEMPO; $(MAKE) -f Makefile.mpas) core_SMOKE: core_physics_init (cd physics_noaa/SMOKE; cp ./MPAS/Makefile .; cp ./MPAS/mpas_smoke_wrapper.F90 .; $(MAKE) all) @@ -286,7 +286,7 @@ clean: ( cd physics_noahmp/drivers/mpas; $(MAKE) clean ) ( cd physics_noahmp/src; $(MAKE) clean ) ( cd physics_noahmp/utility; $(MAKE) clean ) - ( if [ -d physics_noaa/TEMPO ]; then cd physics_noaa/TEMPO; $(MAKE) clean; fi ) + ( if [ -d physics_noaa/TEMPO ]; then cd physics_noaa/TEMPO; $(MAKE) -f Makefile.mpas clean; fi ) ( if [ -d physics_noaa/UGWP ]; then cd physics_noaa/UGWP; $(MAKE) clean; fi ) ( if [ -d physics_noaa/RUCLSM ]; then cd physics_noaa/RUCLSM; $(MAKE) -f MPAS/Makefile clean; fi ) ( if [ -d physics_noaa/MYNN-EDMF ]; then cd physics_noaa/MYNN-EDMF; cp ./MPAS/Makefile .; $(MAKE) clean; fi ) diff --git a/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F b/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F index d78d56bec3..5e8cdff5ca 100644 --- a/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F +++ b/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F @@ -21,8 +21,8 @@ module mpas_atmphys_driver_microphysics !wrf physics: use module_mp_kessler use module_mp_thompson - use module_mp_tempo,only: tempo_3d_to_1d_driver, tempo_init - ! use module_mp_tempo_utils + use module_mp_tempo_driver,only: tempo_driver + use module_mp_tempo_init,only: tempo_init use module_mp_wsm6,only: wsm6 use mp_wsm6,only: mp_wsm6_init,refl10cm_wsm6 use module_mp_nssl_2mom @@ -485,8 +485,8 @@ subroutine init_microphysics(dminfo,configs,mesh,state,time_lev,sfc_input,diag_p end select microp2_select case("mp_tempo") - call tempo_init(l_mp_tables=l_mp_tables, & - hail_aware_flag=config_tempo_hailaware, aerosol_aware_flag=config_tempo_aerosolaware) + call tempo_init(aerosolaware_flag=config_tempo_aerosolaware, & + hailaware_flag=config_tempo_hailaware) if (config_tempo_aerosolaware) then call init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,diag_physics) @@ -532,11 +532,9 @@ subroutine driver_microphysics(configs,mesh,state,time_lev,diag,diag_physics,ten !local pointers: character(len=StrKIND),pointer:: microp_scheme - logical,pointer:: config_tempo_aerosolaware,config_tempo_hailaware + logical,pointer:: config_tempo_aerosolaware, config_tempo_hailaware character(len=StrKIND),pointer:: nssl_moments - integer :: tempo_options - !local variables and arrays: integer:: istep integer, pointer :: do_diag_dbz @@ -595,111 +593,32 @@ subroutine driver_microphysics(configs,mesh,state,time_lev,diag,diag_physics,ten case ("mp_tempo") call mpas_timer_start('mp_tempo') - tempo_options = 0 - if (config_tempo_hailaware) tempo_options = tempo_options + 1 - if (config_tempo_aerosolaware) tempo_options = tempo_options + 1 istep = 1 do while (istep .le. n_microp) - - tempo_opts: select case(tempo_options) - case(0) - call tempo_3d_to_1d_driver( & - th = th_p , qv = qv_p , qc = qc_p , & - qr = qr_p , qi = qi_p , qs = qs_p , & - qg = qg_p , ni = ni_p , nr = nr_p , & - !! ng = ng_p , qb = volg_p , & - !! nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & - !! nwfa2d = nwfa2d_p , nifa2d = nifa2d_p , & - pii = pi_p , p = pres_p , dz = dz_p , & - w = w_p , dt_in = dt_microp , itimestep = itimestep , & - rainnc = rainnc_p , rainncv = rainncv_p , snownc = snownc_p , & - snowncv = snowncv_p , graupelnc = graupelnc_p , graupelncv = graupelncv_p , & - sr = sr_p , rainprod = rainprod_p , evapprod = evapprod_p , & - re_cloud = recloud_p , re_ice = reice_p , re_snow = resnow_p , & - has_reqc = has_reqc , has_reqi = has_reqi , has_reqs = has_reqs , & - !! ntc = ntc_p , muc = muc_p , & - refl_10cm = refl10cm_p , frainnc = frainnc_p , & - 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 & - ) - case(1) - if (config_tempo_aerosolaware) then - call tempo_3d_to_1d_driver( & - th = th_p , qv = qv_p , qc = qc_p , & - qr = qr_p , qi = qi_p , qs = qs_p , & - qg = qg_p , ni = ni_p , nr = nr_p , & - !! ng = ng_p , qb = volg_p , & - nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & - nwfa2d = nwfa2d_p , nifa2d = nifa2d_p , & - pii = pi_p , p = pres_p , dz = dz_p , & - w = w_p , dt_in = dt_microp , itimestep = itimestep , & - rainnc = rainnc_p , rainncv = rainncv_p , snownc = snownc_p , & - snowncv = snowncv_p , graupelnc = graupelnc_p , graupelncv = graupelncv_p , & - sr = sr_p , rainprod = rainprod_p , evapprod = evapprod_p , & - re_cloud = recloud_p , re_ice = reice_p , re_snow = resnow_p , & - has_reqc = has_reqc , has_reqi = has_reqi , has_reqs = has_reqs , & - !! ntc = ntc_p , muc = muc_p , & - refl_10cm = refl10cm_p , frainnc = frainnc_p , & - qcbl = qcbl_p , cldfrac = cldfrac_p , & - 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 & - ) - elseif (config_tempo_hailaware) then - call tempo_3d_to_1d_driver( & - th = th_p , qv = qv_p , qc = qc_p , & - qr = qr_p , qi = qi_p , qs = qs_p , & - qg = qg_p , ni = ni_p , nr = nr_p , & - ng = ng_p , qb = volg_p , & - !! nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & - !! nwfa2d = nwfa2d_p , nifa2d = nifa2d_p , & - pii = pi_p , p = pres_p , dz = dz_p , & - w = w_p , dt_in = dt_microp , itimestep = itimestep , & - rainnc = rainnc_p , rainncv = rainncv_p , snownc = snownc_p , & - snowncv = snowncv_p , graupelnc = graupelnc_p , graupelncv = graupelncv_p , & - sr = sr_p , rainprod = rainprod_p , evapprod = evapprod_p , & - re_cloud = recloud_p , re_ice = reice_p , re_snow = resnow_p , & - has_reqc = has_reqc , has_reqi = has_reqi , has_reqs = has_reqs , & - !! ntc = ntc_p , muc = muc_p , & - refl_10cm = refl10cm_p , frainnc = frainnc_p , & - !! qcbl = qcbl_p , cldfrac = cldfrac_p , & - 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 & - ) - else - call physics_error_fatal('driver_microphysics(): TEMPO called with invalid options -- case 1') - endif - case(2) - call tempo_3d_to_1d_driver( & - th = th_p , qv = qv_p , qc = qc_p , & - qr = qr_p , qi = qi_p , qs = qs_p , & - qg = qg_p , ni = ni_p , nr = nr_p , & - ng = ng_p , qb = volg_p , & - nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & - nwfa2d = nwfa2d_p , nifa2d = nifa2d_p , & - pii = pi_p , p = pres_p , dz = dz_p , & - w = w_p , dt_in = dt_microp , itimestep = itimestep , & - rainnc = rainnc_p , rainncv = rainncv_p , snownc = snownc_p , & - snowncv = snowncv_p , graupelnc = graupelnc_p , graupelncv = graupelncv_p , & - sr = sr_p , rainprod = rainprod_p , evapprod = evapprod_p , & - re_cloud = recloud_p , re_ice = reice_p , re_snow = resnow_p , & - has_reqc = has_reqc , has_reqi = has_reqi , has_reqs = has_reqs , & - !! ntc = ntc_p , muc = muc_p , & - refl_10cm = refl10cm_p , frainnc = frainnc_p , & - max_hail_diameter_sfc = max_hail_diameter_sfc_p , & - max_hail_diameter_column = max_hail_diameter_column_p , & - qcbl = qcbl_p , cldfrac = cldfrac_p , & - 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 & - ) - case default - call physics_error_fatal('driver_microphysics(): TEMPO called with invalid options -- case default') - end select tempo_opts - + call tempo_driver( & + th = th_p , qv = qv_p , qc = qc_p , & + qr = qr_p , qi = qi_p , qs = qs_p , & + qg = qg_p , ni = ni_p , nr = nr_p , & + ng = ng_p , qb = volg_p , & + nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & + nwfa2d = nwfa2d_p , nifa2d = nifa2d_p , & + pii = pi_p , p = pres_p , dz = dz_p , & + w = w_p , dt_in = dt_microp , itimestep = itimestep , & + rainnc = rainnc_p , rainncv = rainncv_p , snownc = snownc_p , & + snowncv = snowncv_p , graupelnc = graupelnc_p , graupelncv = graupelncv_p , & + sr = sr_p , rainprod = rainprod_p , evapprod = evapprod_p , & + re_cloud = recloud_p , re_ice = reice_p , re_snow = resnow_p , & + has_reqc = has_reqc , has_reqi = has_reqi , has_reqs = has_reqs , & + !! ntc = ntc_p , muc = muc_p , & + refl_10cm = refl10cm_p , frainnc = frainnc_p , & + max_hail_diameter_sfc = max_hail_diameter_sfc_p , & + max_hail_diameter_column = max_hail_diameter_column_p , & + qcbl = qcbl_p , cldfrac = cldfrac_p , & + 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 & + ) istep = istep + 1 enddo call mpas_timer_stop('mp_tempo') diff --git a/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F b/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F index dac3b2d20a..5ce5a01ebe 100644 --- a/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F +++ b/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F @@ -15,9 +15,7 @@ module mpas_atmphys_init_tempo use mpas_pool_routines use mpas_atmphys_utilities - use module_mp_tempo_params, only: ntb_arc,ntb_arw,ntb_art,ntb_arr,ntb_ark,tnccn_act, & - naCCN1,naCCN0,naIN0,naIN1,nwfa_default,aero_max, & - nc_ml_input, nc_ml_nodes, nc_ml_output, & + use module_mp_tempo_params, only: nc_ml_input, nc_ml_nodes, nc_ml_output, & nr_ml_input, nr_ml_nodes, nr_ml_output, & nc_ml_trans_mean, nc_ml_trans_var, & nc_ml_w00, nc_ml_w01, nc_ml_b00, nc_ml_b01 @@ -30,7 +28,6 @@ module mpas_atmphys_init_tempo !MPAS main initialization of the TEMPO parameterization of cloud microphysics with nucleation of cloud !droplets based on distributions of CCNs and INs (aerosol-aware parameterization). - contains !================================================================================================================= @@ -127,10 +124,8 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia integer,pointer:: nCellsSolve,nVertLevels integer,pointer:: index_nifa,index_nwfa - real(kind=RKIND),dimension(:),pointer :: areaCell real(kind=RKIND),dimension(:),pointer :: nifa2d,nwfa2d - real(kind=RKIND),dimension(:,:),pointer :: zgrid,zz - real(kind=RKIND),dimension(:,:),pointer :: rho_zz,nifa,nwfa + real(kind=RKIND),dimension(:,:),pointer :: nifa,nwfa real(kind=RKIND),dimension(:,:,:),pointer:: scalars character(len=StrKIND):: mess @@ -138,21 +133,10 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia integer:: iCell, k real(kind=RKIND):: max_test - real(kind=RKIND):: airmass, deltaz - real(kind=RKIND):: h_01 - real(kind=RKIND):: niIN3,niCCN3 real(kind=RKIND):: nifa_max,nifa_min,global_nifa_max,global_nifa_min real(kind=RKIND):: nwfa_max,nwfa_min,global_nwfa_max,global_nwfa_min - real(kind=RKIND),dimension(:,:),allocatable:: hgt !----------------------------------------------------------------------------------------------------------------- -!call mpas_log_write('--- enter subroutine init_tempo_aerosols_forMPAS:') - -!... read a static file containing CCN activation of aerosols. The data were created from a parcel model by -!... Feingold & Heymsfield with further changes by Eidhammer and Kriedenweis. - call table_ccnAct(dminfo) - call mpas_log_write('--- end read table_ccnAct:') - !... if do_restart is true, then we do not need to check the initialization of nwfa, nifa, and nwfa2d. If false, ! then, we proceed with the initialization: if(do_restart) return @@ -160,10 +144,6 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia call mpas_pool_get_dimension(mesh,'nCellsSolve',nCellsSolve) call mpas_pool_get_dimension(mesh,'nVertLevels',nVertLevels) - call mpas_pool_get_array(mesh,'areaCell',areaCell) - call mpas_pool_get_array(mesh,'zgrid' ,zgrid ) - call mpas_pool_get_array(mesh,'zz' ,zz ) - call mpas_pool_get_array(diag_physics,'nifa2d',nifa2d) call mpas_pool_get_array(diag_physics,'nwfa2d',nwfa2d) @@ -174,15 +154,6 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia nifa => scalars(index_nifa,:,:) nwfa => scalars(index_nwfa,:,:) - call mpas_pool_get_array(state,'rho_zz',rho_zz,time_lev) - - if(.not.allocated(hgt)) allocate(hgt(1:nVertLevels,1:nCellsSolve)) - do iCell = 1, nCellsSolve - do k = 1, nVertLevels - hgt(k,iCell) = 0.5_RKIND * (zgrid(k,iCell)+zgrid(k+1,iCell)) - enddo - enddo - !... initialize the distribution of hygroscopic ("water friendly") aerosols if not already initialized using ! GOCART data: global_nwfa_min = 0._RKIND @@ -194,24 +165,8 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia call mpas_log_write('--- global_nwfa_min = $r',realArgs=(/global_nwfa_min/)) call mpas_log_write('--- global_nwfa_max = $r',realArgs=(/global_nwfa_max/)) - if(global_nwfa_min == 0._RKIND .and. global_nwfa_max == 0._RKIND) then - call mpas_log_write('--- initialize nwfa using an exponential distribution of CCN as a function of height.') - do iCell = 1, nCellsSolve - if(hgt(1,iCell).le.1000.0) then - h_01 = 0.8 - elseif(hgt(1,iCell).ge.2500.0) then - h_01 = 0.01 - else - h_01 = 0.8*cos(hgt(1,iCell)*0.001 - 1.0) - endif - niCCN3 = -1.0*ALOG(naCCN1/naCCN0)/h_01 - nwfa(1,iCell) = naCCN1+naCCN0*exp(-((hgt(2,iCell)-hgt(1,iCell))/1000.)*niCCN3) - do k = 2, nVertLevels - nwfa(k,iCell) = naCCN1+naCCN0*exp(-((hgt(k,iCell)-hgt(1,iCell))/1000.)*niCCN3) - enddo - enddo - else - call mpas_log_write('--- initialize nwfa using the climatological GOCART data.') + if(global_nwfa_min /= 0._RKIND .and. global_nwfa_max /= 0._RKIND) then + call mpas_log_write('--- tempo() info: initialized nwfa using the climatological GOCART data.') endif !... initialize the distribution of nonhygroscopic ("ice friendly") aerosols if not already initialized using @@ -226,114 +181,11 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia call mpas_log_write('--- global_nifa_max = $r',realArgs=(/global_nifa_max/)) if(global_nifa_min == 0._RKIND .and. global_nifa_max == 0._RKIND) then - call mpas_log_write('--- initialize nifa using an exponential distribution of IN as a function of height.') - do iCell = 1, nCellsSolve - if(hgt(1,iCell).le.1000.0) then - h_01 = 0.8 - elseif(hgt(1,iCell).ge.2500.0) then - h_01 = 0.01 - else - h_01 = 0.8*cos(hgt(1,iCell)*0.001 - 1.0) - endif - niIN3 = -1.0*ALOG(naIN1/naIN0)/h_01 - nifa(1,iCell) = naIN1+naIN0*exp(-((hgt(2,iCell)-hgt(1,iCell))/1000.)*niIN3) - do k = 2, nVertLevels - nifa(k,iCell) = naIN1+naIN0*exp(-((hgt(k,iCell)-hgt(1,iCell))/1000.)*niIN3) - enddo - enddo - else - call mpas_log_write('--- initialize nifa using the climatological GOCART data.') + call mpas_log_write('--- initialize nifa using the climatological GOCART data.') endif -!... 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). - - k = 1 - do iCell = 1, nCellsSolve - ! airmass = rho_zz(k,iCell)*zz(k,iCell) - ! airmass = airmass*(zgrid(k+1,iCell)-zgrid(k,iCell))*areaCell(iCell) ! (in kg) - ! nwfa2d(iCell) = nwfa(k,iCell)*0.000196*airmass*0.5e-10 - - deltaz = zgrid(k+1,iCell)-zgrid(k,iCell) - if (deltaz < 9.0) then - deltaz = 9.0 - endif - nwfa2d(iCell) = max(nwfa_default, min(aero_max, nwfa(k,iCell))) * & - 0.000196 * (5.0 / deltaz) * (areaCell(iCell) / 9.e6) - nifa2d(iCell) = 0._RKIND -! call mpas_log_write('$i $r $r $r',intArgs=(/iCell/),realArgs=(/airmass,nwfa2d(iCell),nifa2d(iCell)/)) - enddo - -!... deallocate local arrays: - if(allocated(hgt)) deallocate(hgt) - -!call mpas_log_write('--- end subroutine init_tempo_aerosols_forMPAS.') - end subroutine init_tempo_aerosols_forMPAS -!================================================================================================================= - subroutine table_ccnAct(dminfo) -!================================================================================================================= - -!input variables: - type(dm_info),intent(in):: dminfo - -!local variables: - logical:: opened - integer:: ccn_unit,i,istat - character(len=StrKIND):: errmess -!----------------------------------------------------------------------------------------------------------------- - - if(.not.allocated(tnccn_act)) allocate(tnccn_act(ntb_arc,ntb_arw,ntb_art,ntb_arr,ntb_ark)) - -!get a unit to open binary file: - istat = -999 - if(dminfo % my_proc_id == IO_NODE) then - do i = 10,99 - inquire(i,opened = opened,iostat=istat) - if(.not. opened ) then - ccn_unit = i - exit - endif - enddo - if(istat /= 0) & - call physics_error_fatal('mpas_atmphys_init_microphysics table_ccnAct: Can not '// & - 'find unused fortran unit to read in lookup table.' ) - endif - -!distribute unit to other processors: - call mpas_dmpar_bcast_int(dminfo,ccn_unit) - -!open binary file: - istat = -999 - if(dminfo % my_proc_id == IO_NODE) then - open(ccn_unit,file='CCN_ACTIVATE_DATA',form='UNFORMATTED',status='OLD',iostat=istat) - if(istat /= 0) then - write(errmess,'(A,I4)') 'mpas_atmphys_init_microphysics table_ccnAct:: '// & - 'error opening CCN_ACTIVATE_DATA on unit', ccn_unit - call physics_error_fatal(errmess) - endif - endif - -!read and broadcast data to all nodes: - istat = -999 - if(dminfo % my_proc_id == IO_NODE) then - read(ccn_unit,iostat=istat) tnccn_act - if(istat /= 0) then - write(errmess,'(A,I4)') 'mpas_atmphys_init_microphysics table_ccnAct:: '// & - 'error reading tnccn_act on unit', ccn_unit - call physics_error_fatal(errmess) - endif - endif - - DM_BCAST_MACRO(tnccn_act) - - end subroutine table_ccnAct - !================================================================================================================= end module mpas_atmphys_init_tempo !================================================================================================================= diff --git a/src/core_atmosphere/physics/physics_noaa/TEMPO b/src/core_atmosphere/physics/physics_noaa/TEMPO index f325c9d778..f6ab1773c3 160000 --- a/src/core_atmosphere/physics/physics_noaa/TEMPO +++ b/src/core_atmosphere/physics/physics_noaa/TEMPO @@ -1 +1 @@ -Subproject commit f325c9d778ca34ecb781ed92757791749a373a52 +Subproject commit f6ab1773c36af85199519afed5c52ddceb2a829d diff --git a/src/core_atmosphere/utils/Makefile b/src/core_atmosphere/utils/Makefile index cf4e2fd172..ede5830d5a 100644 --- a/src/core_atmosphere/utils/Makefile +++ b/src/core_atmosphere/utils/Makefile @@ -4,27 +4,15 @@ ifdef PHYSICS UTILS = build_tables endif -all: $(UTILS) build_tables_tempo +all: $(UTILS) build_tables: build_tables.o atmphys_build_tables_thompson.o $(LINKER) $(LDFLAGS) -o build_tables build_tables.o atmphys_build_tables_thompson.o -L../../framework -L../physics -lphys -lframework $(LIBS) -L../../external/esmf_time_f90 -lesmf_time mv build_tables ../../.. -build_tables_tempo: build_tables_tempo.o atmphys_build_tables_tempo.o - $(LINKER) $(LDFLAGS) -o build_tables_tempo build_tables_tempo.o atmphys_build_tables_tempo.o -L../../framework -L../physics -lphys -lframework $(LIBS) -L../../external/esmf_time_f90 -lesmf_time - mv build_tables_tempo ../../.. - build_tables.o: \ atmphys_build_tables_thompson.o -build_tables_tempo.o: \ - atmphys_build_tables_tempo.o - -atmphys_build_tables_tempo.o: \ - ../physics/physics_noaa/TEMPO/module_mp_tempo.o \ - ../physics/physics_noaa/TEMPO/module_mp_tempo_utils.o \ - ../physics/physics_noaa/TEMPO/module_mp_tempo_params.o - clean: $(RM) ../../../build_tables $(RM) *.o *.mod *.f90 From 4f47418f918bba914db81d08d3aee3ffc00dc106 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Tue, 6 Jan 2026 00:25:29 +0000 Subject: [PATCH 4/8] v3.0.0 updates consistent with tempo refactor --- src/core_atmosphere/Registry.xml | 11 +- src/core_atmosphere/mpas_atm_core.F | 1 - .../physics/Registry_tempo.xml | 20 ++ .../mpas_atmphys_driver_microphysics.F | 66 ++++--- .../physics/mpas_atmphys_init_tempo.F | 183 +++++++++--------- 5 files changed, 150 insertions(+), 131 deletions(-) create mode 100644 src/core_atmosphere/physics/Registry_tempo.xml diff --git a/src/core_atmosphere/Registry.xml b/src/core_atmosphere/Registry.xml index b04e0e420d..ecd53d4258 100644 --- a/src/core_atmosphere/Registry.xml +++ b/src/core_atmosphere/Registry.xml @@ -2766,16 +2766,6 @@ description="configuration for cloud microphysics schemes" possible_values="`suite',`mp_wsm6',`mp_tempo',`mp_thompson',`mp_thompson_aerosols', `mp_kessler',`mp_nssl2m',`off'"/> - - - - diff --git a/src/core_atmosphere/mpas_atm_core.F b/src/core_atmosphere/mpas_atm_core.F index 3f628a0cce..e10171e8c8 100644 --- a/src/core_atmosphere/mpas_atm_core.F +++ b/src/core_atmosphere/mpas_atm_core.F @@ -588,7 +588,6 @@ subroutine atm_mpas_init_block(dminfo, stream_manager, block, mesh, dt) !initialization of all physics: call physics_init(dminfo, stream_manager, clock, block % configs, mesh, diag, tend, state, 1, & diag_physics, diag_physics_noahmp, ngw_input, atm_input, sfc_input, output_noahmp) - call tempo_ml_init(block % configs) endif #endif diff --git a/src/core_atmosphere/physics/Registry_tempo.xml b/src/core_atmosphere/physics/Registry_tempo.xml new file mode 100644 index 0000000000..88d6f2de9f --- /dev/null +++ b/src/core_atmosphere/physics/Registry_tempo.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F b/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F index 5e8cdff5ca..12c2e7a4c1 100644 --- a/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F +++ b/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F @@ -21,7 +21,8 @@ module mpas_atmphys_driver_microphysics !wrf physics: use module_mp_kessler use module_mp_thompson - use module_mp_tempo_driver,only: tempo_driver + use module_mp_tempo_cfgs,only: ty_tempo_cfgs + use module_mp_tempo_driver,only: tempo_driver, ty_tempo_driver_diags, tempo_aerosol_surface_emissions use module_mp_tempo_init,only: tempo_init use module_mp_wsm6,only: wsm6 use mp_wsm6,only: mp_wsm6_init,refl10cm_wsm6 @@ -94,7 +95,7 @@ module mpas_atmphys_driver_microphysics !--- initialization option for WSM6 from WRF version 3.8.1. this option could also be set as a namelist parameter. integer,parameter:: hail_opt = 0 - + type(ty_tempo_cfgs) :: tempo_cfgs contains @@ -486,7 +487,7 @@ subroutine init_microphysics(dminfo,configs,mesh,state,time_lev,sfc_input,diag_p case("mp_tempo") call tempo_init(aerosolaware_flag=config_tempo_aerosolaware, & - hailaware_flag=config_tempo_hailaware) + hailaware_flag=config_tempo_hailaware, tempo_cfgs=tempo_cfgs) if (config_tempo_aerosolaware) then call init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,diag_physics) @@ -532,7 +533,6 @@ subroutine driver_microphysics(configs,mesh,state,time_lev,diag,diag_physics,ten !local pointers: character(len=StrKIND),pointer:: microp_scheme - logical,pointer:: config_tempo_aerosolaware, config_tempo_hailaware character(len=StrKIND),pointer:: nssl_moments !local variables and arrays: @@ -544,6 +544,7 @@ subroutine driver_microphysics(configs,mesh,state,time_lev,diag,diag_physics,ten character(len=StrKIND):: errmsg integer:: errflg + type(ty_tempo_driver_diags) :: tempo_driver_diags !----------------------------------------------------------------------------------------------------------------- !call mpas_log_write('') !call mpas_log_write('---enter subroutine driver_microphysics:') @@ -553,8 +554,6 @@ subroutine driver_microphysics(configs,mesh,state,time_lev,diag,diag_physics,ten errflg = 0 call mpas_pool_get_config(configs,'config_microp_scheme',microp_scheme) - call mpas_pool_get_config(configs,'config_tempo_hailaware',config_tempo_hailaware) - call mpas_pool_get_config(configs,'config_tempo_aerosolaware',config_tempo_aerosolaware) call mpas_pool_get_config(configs,'config_nssl_moments',nssl_moments) call mpas_pool_get_array(diag_physics,'do_diag_dbz',do_diag_dbz) @@ -592,33 +591,42 @@ subroutine driver_microphysics(configs,mesh,state,time_lev,diag,diag_physics,ten call mpas_timer_stop('mp_kessler') case ("mp_tempo") + + if (allocated(nwfa_p) .and. allocated(nwfa2d_p)) then + call tempo_aerosol_surface_emissions(dt=dt_microp, nwfa=nwfa_p, nwfa2d=nwfa2d_p, & + ims=ims, ime=ime, jms=jms, jme=jme, kms=kms, kme=kme, kts=kts) + endif + call mpas_timer_start('mp_tempo') istep = 1 do while (istep .le. n_microp) - call tempo_driver( & - th = th_p , qv = qv_p , qc = qc_p , & - qr = qr_p , qi = qi_p , qs = qs_p , & - qg = qg_p , ni = ni_p , nr = nr_p , & - ng = ng_p , qb = volg_p , & - nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & - nwfa2d = nwfa2d_p , nifa2d = nifa2d_p , & - pii = pi_p , p = pres_p , dz = dz_p , & - w = w_p , dt_in = dt_microp , itimestep = itimestep , & - rainnc = rainnc_p , rainncv = rainncv_p , snownc = snownc_p , & - snowncv = snowncv_p , graupelnc = graupelnc_p , graupelncv = graupelncv_p , & - sr = sr_p , rainprod = rainprod_p , evapprod = evapprod_p , & - re_cloud = recloud_p , re_ice = reice_p , re_snow = resnow_p , & - has_reqc = has_reqc , has_reqi = has_reqi , has_reqs = has_reqs , & - !! ntc = ntc_p , muc = muc_p , & - refl_10cm = refl10cm_p , frainnc = frainnc_p , & - max_hail_diameter_sfc = max_hail_diameter_sfc_p , & - max_hail_diameter_column = max_hail_diameter_column_p , & - qcbl = qcbl_p , cldfrac = cldfrac_p , & - 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 & - ) + call tempo_driver( tempo_cfgs=tempo_cfgs, & + dt = dt_microp , itimestep = itimestep , & + th = th_p , qv = qv_p , qc = qc_p , & + qr = qr_p , qi = qi_p , qs = qs_p , & + qg = qg_p , ni = ni_p , nr = nr_p , & + ng = ng_p , qb = volg_p , w = w_p , & + nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & + pii = pi_p , p = pres_p , dz = dz_p , & + 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) + snownc_p = tempo_driver_diags%snow_liquid_equiv_precip + snowncv_p = tempo_driver_diags%snow_liquid_equiv_precip + graupelnc_p = tempo_driver_diags%graupel_liquid_equiv_precip + graupelncv_p = tempo_driver_diags%graupel_liquid_equiv_precip + rainnc_p = tempo_driver_diags%rain_precip+ snownc_p + graupelnc_p + tempo_driver_diags%ice_liquid_equiv_precip + rainncv_p = tempo_driver_diags%rain_precip + snownc_p + graupelnc_p + tempo_driver_diags%ice_liquid_equiv_precip + frainnc_p = tempo_driver_diags%frz_rain_precip + refl10cm_p = tempo_driver_diags%refl10cm + recloud_p = tempo_driver_diags%re_cloud + reice_p = tempo_driver_diags%re_ice + resnow_p = tempo_driver_diags%re_snow + sr_p = tempo_driver_diags%frozen_fraction + max_hail_diameter_sfc_p = tempo_driver_diags%max_hail_diameter_sfc + max_hail_diameter_column_p = tempo_driver_diags%max_hail_diameter_column istep = istep + 1 enddo call mpas_timer_stop('mp_tempo') diff --git a/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F b/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F index 5ce5a01ebe..743dee98d4 100644 --- a/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F +++ b/src/core_atmosphere/physics/mpas_atmphys_init_tempo.F @@ -15,99 +15,19 @@ module mpas_atmphys_init_tempo use mpas_pool_routines use mpas_atmphys_utilities - use module_mp_tempo_params, only: nc_ml_input, nc_ml_nodes, nc_ml_output, & - nr_ml_input, nr_ml_nodes, nr_ml_output, & - nc_ml_trans_mean, nc_ml_trans_var, & - nc_ml_w00, nc_ml_w01, nc_ml_b00, nc_ml_b01 - use module_mp_tempo_ml, only: MLdata, tempo_save_or_read_ml_data + use module_mp_tempo_params, only: nwfa_default, aero_max, & + naCCN1,naCCN0,naIN0,naIN1 implicit none private - public:: init_tempo_aerosols_forMPAS, tempo_ml_init + public:: init_tempo_aerosols_forMPAS -!MPAS main initialization of the TEMPO parameterization of cloud microphysics with nucleation of cloud -!droplets based on distributions of CCNs and INs (aerosol-aware parameterization). +!MPAS initialization of aerosols for TEMPO parameterization. contains !================================================================================================================= - subroutine tempo_ml_init(configs) -! Called once to initial data for tempo_ml -!================================================================================================================= - -!input arguments: -type(mpas_pool_type),intent(in):: configs - -!local variables and pointers: - type(MLdata), dimension(2) :: tempo_ml_data - logical,pointer:: config_tempo_ml_nc_pbl,config_tempo_ml_nc,config_tempo_ml_nr - - call mpas_pool_get_config(configs, 'config_tempo_ml_nc_pbl', config_tempo_ml_nc_pbl) - call mpas_pool_get_config(configs, 'config_tempo_ml_nc', config_tempo_ml_nc) - call mpas_pool_get_config(configs, 'config_tempo_ml_nr', config_tempo_ml_nr) - - if(.not. (config_tempo_ml_nc_pbl .or. config_tempo_ml_nc .or. config_tempo_ml_nr)) then - call mpas_log_write('--- All configuration flags for TEMPO ML are false... TEMPO ML will not be used') - return - endif - - if(config_tempo_ml_nc .or. config_tempo_ml_nr) then - call mpas_log_write('--- TEMPO ML for nc and nr prediction not yet working... These flags will be ignored') - endif - - if(config_tempo_ml_nc_pbl) then - call mpas_log_write('--- Using TEMPO ML prediction to give life to the PBL clouds') - endif - - ! Cloud water - tempo_ml_data(1)%input_size = nc_ml_input - tempo_ml_data(1)%node_size = nc_ml_nodes - tempo_ml_data(1)%output_size = nc_ml_output - - if (.not.allocated(tempo_ml_data(1)%transform_mean)) allocate(tempo_ml_data(1)%transform_mean(nc_ml_input)) - if (.not.allocated(tempo_ml_data(1)%transform_var)) allocate(tempo_ml_data(1)%transform_var(nc_ml_input)) - - tempo_ml_data(1)%transform_mean = nc_ml_trans_mean - tempo_ml_data(1)%transform_var = nc_ml_trans_var - - if (.not.allocated(tempo_ml_data(1)%weights00)) allocate(tempo_ml_data(1)%weights00(nc_ml_nodes,nc_ml_input)) - if (.not.allocated(tempo_ml_data(1)%weights01)) allocate(tempo_ml_data(1)%weights01(nc_ml_output,nc_ml_nodes)) - if (.not.allocated(tempo_ml_data(1)%bias00)) allocate(tempo_ml_data(1)%bias00(nc_ml_nodes)) - if (.not.allocated(tempo_ml_data(1)%bias01)) allocate(tempo_ml_data(1)%bias01(nc_ml_output)) - - tempo_ml_data(1)%weights00 = reshape(nc_ml_w00, (/nc_ml_nodes, nc_ml_input/)) - tempo_ml_data(1)%weights01 = reshape(nc_ml_w01, (/nc_ml_output, nc_ml_nodes/)) - tempo_ml_data(1)%bias00 = nc_ml_b00 - tempo_ml_data(1)%bias01 = nc_ml_b01 - - ! Rain water - tempo_ml_data(2)%input_size = nc_ml_input - tempo_ml_data(2)%node_size = nc_ml_nodes - tempo_ml_data(2)%output_size = nc_ml_output - - if (.not.allocated(tempo_ml_data(2)%transform_mean)) allocate(tempo_ml_data(2)%transform_mean(nc_ml_input)) - if (.not.allocated(tempo_ml_data(2)%transform_var)) allocate(tempo_ml_data(2)%transform_var(nc_ml_input)) - - tempo_ml_data(2)%transform_mean = nc_ml_trans_mean - tempo_ml_data(2)%transform_var = nc_ml_trans_var - - if (.not.allocated(tempo_ml_data(2)%weights00)) allocate(tempo_ml_data(2)%weights00(nc_ml_nodes,nc_ml_input)) - if (.not.allocated(tempo_ml_data(2)%weights01)) allocate(tempo_ml_data(2)%weights01(nc_ml_output,nc_ml_nodes)) - if (.not.allocated(tempo_ml_data(2)%bias00)) allocate(tempo_ml_data(2)%bias00(nc_ml_nodes)) - if (.not.allocated(tempo_ml_data(2)%bias01)) allocate(tempo_ml_data(2)%bias01(nc_ml_output)) - - tempo_ml_data(2)%weights00 = reshape(nc_ml_w00, (/nc_ml_nodes, nc_ml_input/)) - tempo_ml_data(2)%weights01 = reshape(nc_ml_w01, (/nc_ml_output, nc_ml_nodes/)) - tempo_ml_data(2)%bias00 = nc_ml_b00 - tempo_ml_data(2)%bias01 = nc_ml_b01 - - ! Save neural network - call tempo_save_or_read_ml_data(ml_data_in=tempo_ml_data) - - end subroutine tempo_ml_init - -!================================================================================================================= - subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,diag_physics) +subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,diag_physics) !================================================================================================================= !input variables: @@ -124,8 +44,10 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia integer,pointer:: nCellsSolve,nVertLevels integer,pointer:: index_nifa,index_nwfa + real(kind=RKIND),dimension(:),pointer :: areaCell real(kind=RKIND),dimension(:),pointer :: nifa2d,nwfa2d - real(kind=RKIND),dimension(:,:),pointer :: nifa,nwfa + real(kind=RKIND),dimension(:,:),pointer :: zgrid,zz + real(kind=RKIND),dimension(:,:),pointer :: rho_zz,nifa,nwfa real(kind=RKIND),dimension(:,:,:),pointer:: scalars character(len=StrKIND):: mess @@ -133,10 +55,16 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia integer:: iCell, k real(kind=RKIND):: max_test + real(kind=RKIND):: airmass, deltaz + real(kind=RKIND):: h_01 + real(kind=RKIND):: niIN3,niCCN3 real(kind=RKIND):: nifa_max,nifa_min,global_nifa_max,global_nifa_min real(kind=RKIND):: nwfa_max,nwfa_min,global_nwfa_max,global_nwfa_min + real(kind=RKIND),dimension(:,:),allocatable:: hgt !----------------------------------------------------------------------------------------------------------------- +!call mpas_log_write('--- enter subroutine init_tempo_aerosols_forMPAS:') + !... if do_restart is true, then we do not need to check the initialization of nwfa, nifa, and nwfa2d. If false, ! then, we proceed with the initialization: if(do_restart) return @@ -144,6 +72,10 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia call mpas_pool_get_dimension(mesh,'nCellsSolve',nCellsSolve) call mpas_pool_get_dimension(mesh,'nVertLevels',nVertLevels) + call mpas_pool_get_array(mesh,'areaCell',areaCell) + call mpas_pool_get_array(mesh,'zgrid' ,zgrid ) + call mpas_pool_get_array(mesh,'zz' ,zz ) + call mpas_pool_get_array(diag_physics,'nifa2d',nifa2d) call mpas_pool_get_array(diag_physics,'nwfa2d',nwfa2d) @@ -154,6 +86,15 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia nifa => scalars(index_nifa,:,:) nwfa => scalars(index_nwfa,:,:) + call mpas_pool_get_array(state,'rho_zz',rho_zz,time_lev) + + if(.not.allocated(hgt)) allocate(hgt(1:nVertLevels,1:nCellsSolve)) + do iCell = 1, nCellsSolve + do k = 1, nVertLevels + hgt(k,iCell) = 0.5_RKIND * (zgrid(k,iCell)+zgrid(k+1,iCell)) + enddo + enddo + !... initialize the distribution of hygroscopic ("water friendly") aerosols if not already initialized using ! GOCART data: global_nwfa_min = 0._RKIND @@ -165,8 +106,24 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia call mpas_log_write('--- global_nwfa_min = $r',realArgs=(/global_nwfa_min/)) call mpas_log_write('--- global_nwfa_max = $r',realArgs=(/global_nwfa_max/)) - if(global_nwfa_min /= 0._RKIND .and. global_nwfa_max /= 0._RKIND) then - call mpas_log_write('--- tempo() info: initialized nwfa using the climatological GOCART data.') + if(global_nwfa_min == 0._RKIND .and. global_nwfa_max == 0._RKIND) then + call mpas_log_write('--- initialize nwfa using an exponential distribution of CCN as a function of height.') + do iCell = 1, nCellsSolve + if(hgt(1,iCell).le.1000.0) then + h_01 = 0.8 + elseif(hgt(1,iCell).ge.2500.0) then + h_01 = 0.01 + else + h_01 = 0.8*cos(hgt(1,iCell)*0.001 - 1.0) + endif + niCCN3 = -1.0*ALOG(naCCN1/naCCN0)/h_01 + nwfa(1,iCell) = naCCN1+naCCN0*exp(-((hgt(2,iCell)-hgt(1,iCell))/1000.)*niCCN3) + do k = 2, nVertLevels + nwfa(k,iCell) = naCCN1+naCCN0*exp(-((hgt(k,iCell)-hgt(1,iCell))/1000.)*niCCN3) + enddo + enddo + else + call mpas_log_write('--- initialize nwfa using the climatological GOCART data.') endif !... initialize the distribution of nonhygroscopic ("ice friendly") aerosols if not already initialized using @@ -181,11 +138,55 @@ subroutine init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,dia call mpas_log_write('--- global_nifa_max = $r',realArgs=(/global_nifa_max/)) if(global_nifa_min == 0._RKIND .and. global_nifa_max == 0._RKIND) then - call mpas_log_write('--- initialize nifa using the climatological GOCART data.') + call mpas_log_write('--- initialize nifa using an exponential distribution of IN as a function of height.') + do iCell = 1, nCellsSolve + if(hgt(1,iCell).le.1000.0) then + h_01 = 0.8 + elseif(hgt(1,iCell).ge.2500.0) then + h_01 = 0.01 + else + h_01 = 0.8*cos(hgt(1,iCell)*0.001 - 1.0) + endif + niIN3 = -1.0*ALOG(naIN1/naIN0)/h_01 + nifa(1,iCell) = naIN1+naIN0*exp(-((hgt(2,iCell)-hgt(1,iCell))/1000.)*niIN3) + do k = 2, nVertLevels + nifa(k,iCell) = naIN1+naIN0*exp(-((hgt(k,iCell)-hgt(1,iCell))/1000.)*niIN3) + enddo + enddo + else + call mpas_log_write('--- initialize nifa using the climatological GOCART data.') endif +!... 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). + + k = 1 + do iCell = 1, nCellsSolve + ! airmass = rho_zz(k,iCell)*zz(k,iCell) + ! airmass = airmass*(zgrid(k+1,iCell)-zgrid(k,iCell))*areaCell(iCell) ! (in kg) + ! nwfa2d(iCell) = nwfa(k,iCell)*0.000196*airmass*0.5e-10 + + deltaz = zgrid(k+1,iCell)-zgrid(k,iCell) + if (deltaz < 9.0) then + deltaz = 9.0 + endif + nwfa2d(iCell) = max(nwfa_default, min(aero_max, nwfa(k,iCell))) * & + 0.000196 * (5.0 / deltaz) * (areaCell(iCell) / 9.e6) + nifa2d(iCell) = 0._RKIND +! call mpas_log_write('$i $r $r $r',intArgs=(/iCell/),realArgs=(/airmass,nwfa2d(iCell),nifa2d(iCell)/)) + enddo + +!... deallocate local arrays: + if(allocated(hgt)) deallocate(hgt) + +!call mpas_log_write('--- end subroutine init_tempo_aerosols_forMPAS.') + end subroutine init_tempo_aerosols_forMPAS -!================================================================================================================= + !================================================================================================================= end module mpas_atmphys_init_tempo -!================================================================================================================= +!================================================================================================================= \ No newline at end of file From 7306023cb401689b08dde06f36eac09ed1853f4f Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Tue, 6 Jan 2026 00:27:11 +0000 Subject: [PATCH 5/8] update pointer to tempo refactor --- src/core_atmosphere/physics/physics_noaa/TEMPO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_atmosphere/physics/physics_noaa/TEMPO b/src/core_atmosphere/physics/physics_noaa/TEMPO index f6ab1773c3..1abd31ada0 160000 --- a/src/core_atmosphere/physics/physics_noaa/TEMPO +++ b/src/core_atmosphere/physics/physics_noaa/TEMPO @@ -1 +1 @@ -Subproject commit f6ab1773c36af85199519afed5c52ddceb2a829d +Subproject commit 1abd31ada0df486059c8d21e3ea8f607f10ed441 From 50294c1a15b87e1947fab9bf1b18a2e6af446329 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Wed, 7 Jan 2026 00:06:24 +0000 Subject: [PATCH 6/8] v3.0.0 tempo refactor with ml prediction for bl clouds --- src/core_atmosphere/Registry.xml | 5 --- .../physics/Registry_tempo.xml | 28 ++++++++------- .../mpas_atmphys_driver_microphysics.F | 35 +++++++++++-------- .../physics/mpas_atmphys_interface.F | 6 ++-- .../physics/physics_noaa/TEMPO | 2 +- 5 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/core_atmosphere/Registry.xml b/src/core_atmosphere/Registry.xml index ecd53d4258..03446df61d 100644 --- a/src/core_atmosphere/Registry.xml +++ b/src/core_atmosphere/Registry.xml @@ -2765,11 +2765,6 @@ units="-" description="configuration for cloud microphysics schemes" possible_values="`suite',`mp_wsm6',`mp_tempo',`mp_thompson',`mp_thompson_aerosols', `mp_kessler',`mp_nssl2m',`off'"/> - - - + - - - + + + - + - + + \ No newline at end of file diff --git a/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F b/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F index 12c2e7a4c1..fba1db829c 100644 --- a/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F +++ b/src/core_atmosphere/physics/mpas_atmphys_driver_microphysics.F @@ -111,14 +111,14 @@ subroutine allocate_microphysics(configs) character(len=StrKIND),pointer:: microp_scheme character(len=StrKIND),pointer:: nssl_moments logical,pointer:: config_tempo_hailaware, config_tempo_aerosolaware - logical,pointer:: config_tempo_ml_nc_pbl + logical,pointer:: config_tempo_ml_for_bl_nc !----------------------------------------------------------------------------------------------------------------- call mpas_pool_get_config(configs,'config_microp_scheme',microp_scheme) call mpas_pool_get_config(configs,'config_nssl_moments',nssl_moments) call mpas_pool_get_config(configs,'config_tempo_hailaware',config_tempo_hailaware) call mpas_pool_get_config(configs,'config_tempo_aerosolaware',config_tempo_aerosolaware) - call mpas_pool_get_config(configs,'config_tempo_ml_nc_pbl',config_tempo_ml_nc_pbl) + call mpas_pool_get_config(configs,'config_tempo_ml_for_bl_nc',config_tempo_ml_for_bl_nc) !sounding variables: if(.not.allocated(rho_p) ) allocate(rho_p(ims:ime,kms:kme,jms:jme) ) @@ -224,7 +224,7 @@ subroutine allocate_microphysics(configs) if(.not.allocated(volg_p)) allocate(volg_p(ims:ime,kms:kme,jms:jme)) endif - if (config_tempo_ml_nc_pbl) then + if (config_tempo_ml_for_bl_nc) then if(.not.allocated(cldfrac_p) ) allocate(cldfrac_p(ims:ime,kms:kme,jms:jme)) if(.not.allocated(qcbl_p) ) allocate(qcbl_p(ims:ime,kms:kme,jms:jme)) endif @@ -276,7 +276,7 @@ subroutine deallocate_microphysics(configs) character(len=StrKIND),pointer:: microp_scheme character(len=StrKIND),pointer:: nssl_moments logical,pointer:: config_tempo_hailaware, config_tempo_aerosolaware - logical,pointer:: config_tempo_ml_nc_pbl + logical,pointer:: config_tempo_ml_for_bl_nc !----------------------------------------------------------------------------------------------------------------- @@ -284,7 +284,7 @@ subroutine deallocate_microphysics(configs) call mpas_pool_get_config(configs,'config_nssl_moments',nssl_moments) call mpas_pool_get_config(configs,'config_tempo_hailaware',config_tempo_hailaware) call mpas_pool_get_config(configs,'config_tempo_aerosolaware',config_tempo_aerosolaware) - call mpas_pool_get_config(configs,'config_tempo_ml_nc_pbl',config_tempo_ml_nc_pbl) + call mpas_pool_get_config(configs,'config_tempo_ml_for_bl_nc',config_tempo_ml_for_bl_nc) !sounding variables: if(allocated(rho_p) ) deallocate(rho_p ) @@ -388,7 +388,7 @@ subroutine deallocate_microphysics(configs) if(allocated(volg_p) ) deallocate(volg_p ) endif - if (config_tempo_ml_nc_pbl) then + if (config_tempo_ml_for_bl_nc) then if(allocated(cldfrac_p) ) deallocate(cldfrac_p) if(allocated(qcbl_p) ) deallocate(qcbl_p) endif @@ -451,6 +451,7 @@ subroutine init_microphysics(dminfo,configs,mesh,state,time_lev,sfc_input,diag_p logical,pointer:: do_restart character(len=StrKIND),pointer:: microp_scheme logical,pointer:: config_tempo_hailaware, config_tempo_aerosolaware + logical,pointer:: config_tempo_ml_for_bl_nc character(len=StrKIND),pointer:: nssl_moments logical :: outputon = .false. @@ -470,6 +471,7 @@ subroutine init_microphysics(dminfo,configs,mesh,state,time_lev,sfc_input,diag_p call mpas_pool_get_config(configs,'config_microp_scheme',microp_scheme) call mpas_pool_get_config(configs,'config_tempo_hailaware',config_tempo_hailaware) call mpas_pool_get_config(configs,'config_tempo_aerosolaware',config_tempo_aerosolaware) + call mpas_pool_get_config(configs,'config_tempo_ml_for_bl_nc',config_tempo_ml_for_bl_nc) call mpas_pool_get_config(configs,'config_nssl_moments',nssl_moments) call mpas_pool_get_config(configs,'config_do_restart' ,do_restart ) @@ -487,7 +489,8 @@ subroutine init_microphysics(dminfo,configs,mesh,state,time_lev,sfc_input,diag_p case("mp_tempo") call tempo_init(aerosolaware_flag=config_tempo_aerosolaware, & - hailaware_flag=config_tempo_hailaware, tempo_cfgs=tempo_cfgs) + hailaware_flag=config_tempo_hailaware, & + ml_for_bl_nc_flag = config_tempo_ml_for_bl_nc, tempo_cfgs=tempo_cfgs) if (config_tempo_aerosolaware) then call init_tempo_aerosols_forMPAS(do_restart,dminfo,mesh,state,time_lev,diag_physics) @@ -609,17 +612,21 @@ subroutine driver_microphysics(configs,mesh,state,time_lev,diag,diag_physics,ten ng = ng_p , qb = volg_p , w = w_p , & nc = nc_p , nwfa = nwfa_p , nifa = nifa_p , & pii = pi_p , p = pres_p , dz = dz_p , & + qc_bl = qcbl_p , qcfrac_bl = cldfrac_p , & 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) - snownc_p = tempo_driver_diags%snow_liquid_equiv_precip - snowncv_p = tempo_driver_diags%snow_liquid_equiv_precip - graupelnc_p = tempo_driver_diags%graupel_liquid_equiv_precip - graupelncv_p = tempo_driver_diags%graupel_liquid_equiv_precip - rainnc_p = tempo_driver_diags%rain_precip+ snownc_p + graupelnc_p + tempo_driver_diags%ice_liquid_equiv_precip - rainncv_p = tempo_driver_diags%rain_precip + snownc_p + graupelnc_p + tempo_driver_diags%ice_liquid_equiv_precip - frainnc_p = tempo_driver_diags%frz_rain_precip + ! precipitation variables are added in case of multiple calls when n_microp > 1 + snownc_p = snownc_p + tempo_driver_diags%snow_liquid_equiv_precip + snowncv_p = snowncv_p + tempo_driver_diags%snow_liquid_equiv_precip + graupelnc_p = graupelnc_p + tempo_driver_diags%graupel_liquid_equiv_precip + graupelncv_p = graupelncv_p + tempo_driver_diags%graupel_liquid_equiv_precip + rainnc_p = rainnc_p + tempo_driver_diags%rain_precip + & + snownc_p + graupelnc_p + tempo_driver_diags%ice_liquid_equiv_precip + rainncv_p = rainncv_p + tempo_driver_diags%rain_precip + & + snownc_p + graupelnc_p + tempo_driver_diags%ice_liquid_equiv_precip + frainnc_p = frainnc_p + tempo_driver_diags%frz_rain_precip refl10cm_p = tempo_driver_diags%refl10cm recloud_p = tempo_driver_diags%re_cloud reice_p = tempo_driver_diags%re_ice diff --git a/src/core_atmosphere/physics/mpas_atmphys_interface.F b/src/core_atmosphere/physics/mpas_atmphys_interface.F index 35d577efab..156950af30 100644 --- a/src/core_atmosphere/physics/mpas_atmphys_interface.F +++ b/src/core_atmosphere/physics/mpas_atmphys_interface.F @@ -664,7 +664,7 @@ subroutine microphysics_from_MPAS(configs,mesh,state,time_lev,diag,diag_physics, !TEMPO/NSSL character(len=StrKIND),pointer:: nssl_moments logical,pointer:: config_tempo_hailaware, config_tempo_aerosolaware - logical,pointer:: config_tempo_ml_nc_pbl + logical,pointer:: config_tempo_ml_for_bl_nc integer,pointer:: index_qh integer,pointer:: index_zrw,index_zgw,index_zhw integer,pointer:: index_ns,index_ng,index_nh,index_nccn @@ -696,7 +696,7 @@ subroutine microphysics_from_MPAS(configs,mesh,state,time_lev,diag,diag_physics, call mpas_pool_get_config(configs,'config_nssl_moments',nssl_moments) call mpas_pool_get_config(configs,'config_tempo_hailaware',config_tempo_hailaware) call mpas_pool_get_config(configs,'config_tempo_aerosolaware',config_tempo_aerosolaware) - call mpas_pool_get_config(configs,'config_tempo_ml_nc_pbl',config_tempo_ml_nc_pbl) + call mpas_pool_get_config(configs,'config_tempo_ml_for_bl_nc',config_tempo_ml_for_bl_nc) call mpas_pool_get_array(mesh,'zgrid',zgrid) call mpas_pool_get_array(mesh,'zz' ,zz ) @@ -888,7 +888,7 @@ subroutine microphysics_from_MPAS(configs,mesh,state,time_lev,diag,diag_physics, enddo enddo - if(config_tempo_ml_nc_pbl) then + if(config_tempo_ml_for_bl_nc) then call mpas_pool_get_array(diag_physics,'qc_bl',qc_bl) call mpas_pool_get_array(diag_physics,'cldfrac_bl',cldfrac_bl) do j = jts, jte diff --git a/src/core_atmosphere/physics/physics_noaa/TEMPO b/src/core_atmosphere/physics/physics_noaa/TEMPO index 1abd31ada0..3060f842ba 160000 --- a/src/core_atmosphere/physics/physics_noaa/TEMPO +++ b/src/core_atmosphere/physics/physics_noaa/TEMPO @@ -1 +1 @@ -Subproject commit 1abd31ada0df486059c8d21e3ea8f607f10ed441 +Subproject commit 3060f842bad28414fe6dce63358ac0bee33e297d From abd6351b8d0b21a3e862c6bf5639c5a146584a38 Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Wed, 7 Jan 2026 17:10:34 +0000 Subject: [PATCH 7/8] update tempo pointer --- src/core_atmosphere/physics/physics_noaa/TEMPO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_atmosphere/physics/physics_noaa/TEMPO b/src/core_atmosphere/physics/physics_noaa/TEMPO index 3060f842ba..62122bfe4b 160000 --- a/src/core_atmosphere/physics/physics_noaa/TEMPO +++ b/src/core_atmosphere/physics/physics_noaa/TEMPO @@ -1 +1 @@ -Subproject commit 3060f842bad28414fe6dce63358ac0bee33e297d +Subproject commit 62122bfe4be6125facb72d43109a066601979775 From 563d91eb674aa00b85aa3c2a07a92cccd15e94ba Mon Sep 17 00:00:00 2001 From: AndersJensen-NOAA Date: Wed, 7 Jan 2026 17:22:21 +0000 Subject: [PATCH 8/8] update tempo pointer --- src/core_atmosphere/physics/physics_noaa/TEMPO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core_atmosphere/physics/physics_noaa/TEMPO b/src/core_atmosphere/physics/physics_noaa/TEMPO index 62122bfe4b..68c8c18c86 160000 --- a/src/core_atmosphere/physics/physics_noaa/TEMPO +++ b/src/core_atmosphere/physics/physics_noaa/TEMPO @@ -1 +1 @@ -Subproject commit 62122bfe4be6125facb72d43109a066601979775 +Subproject commit 68c8c18c863e72da4a80c092fc0de7a21b517bee