From ff57c9bbb8c0a613b0444d8a26ca071f5c0e5737 Mon Sep 17 00:00:00 2001 From: James Foucar Date: Fri, 28 Aug 2026 13:42:08 -0600 Subject: [PATCH 1/8] ZM remove f90 support [BFB] --- .../physics/zm/tests/infra/zm_test_data.cpp | 210 ------------------ .../physics/zm/tests/infra/zm_test_data.hpp | 19 +- .../zm_calc_fractional_entrainment_tests.cpp | 7 +- .../zm/tests/zm_calc_output_tend_tests.cpp | 7 +- .../src/physics/zm/tests/zm_closure_tests.cpp | 7 +- .../zm/tests/zm_cloud_properties_tests.cpp | 7 +- .../zm_compute_cape_from_parcel_tests.cpp | 7 +- .../zm/tests/zm_compute_dilute_cape_tests.cpp | 7 +- .../tests/zm_compute_dilute_parcel_tests.cpp | 7 +- .../physics/zm/tests/zm_conv_evap_tests.cpp | 7 +- .../physics/zm/tests/zm_conv_main_tests.cpp | 9 +- .../zm_conv_mcsp_calculate_shear_tests.cpp | 7 +- .../zm/tests/zm_conv_mcsp_tend_tests.cpp | 7 +- .../tests/zm_downdraft_properties_tests.cpp | 7 +- .../src/physics/zm/tests/zm_entropy_tests.cpp | 7 +- .../zm/tests/zm_find_mse_max_tests.cpp | 7 +- .../physics/zm/tests/zm_ientropy_tests.cpp | 7 +- .../zm/tests/zm_transport_momentum_tests.cpp | 7 +- .../zm/tests/zm_transport_tracer_tests.cpp | 7 +- 19 files changed, 19 insertions(+), 331 deletions(-) diff --git a/components/eamxx/src/physics/zm/tests/infra/zm_test_data.cpp b/components/eamxx/src/physics/zm/tests/infra/zm_test_data.cpp index e064e0d410df..1501f9ac3ce8 100644 --- a/components/eamxx/src/physics/zm/tests/infra/zm_test_data.cpp +++ b/components/eamxx/src/physics/zm/tests/infra/zm_test_data.cpp @@ -9,10 +9,6 @@ using scream::Real; using scream::Int; -// -// A C++ interface to ZM fortran calls and vice versa -// - namespace scream { namespace zm { @@ -32,61 +28,8 @@ using view3dr_d = ZMF::view_3d; using WSM = typename ZMF::WorkspaceManager; -extern "C" { - -void zm_opts_init_bridge_f(); - -void zm_opts_finalize_bridge_f(); - -void ientropy_bridge_f(Real s, Real p, Real qt, Real* t, Real* qst, Real tfg); - -void entropy_bridge_f(Real tk, Real p, Real qtot, Real* entropy); - -void zm_transport_tracer_bridge_f(Int pcols, Int pver, bool* doconvtran, Real* q, Int ncnst, Real* mu, Real* md, Real* du, Real* eu, Real* ed, Real* dp, Int* jt, Int* mx, Int* ideep, Int il1g, Int il2g, Real* fracis, Real* dqdt, Real* dpdry, Real dt); - -void zm_transport_momentum_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Real* wind_in, Int nwind, Real* mu, Real* md, Real* du, Real* eu, Real* ed, Real* dp, Int* jt, Int* mx, Int* ideep, Int il1g, Int il2g, Real* wind_tend, Real* pguall, Real* pgdall, Real* icwu, Real* icwd, Real dt, Real* seten); - -void compute_dilute_cape_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Int num_cin, Int num_msg, Real* sp_humidity_in, Real* temperature_in, Real* zmid, Real* pmid, Real* pint, Int* pblt, Real* tpert, Real* parcel_temp, Real* parcel_qsat, Int* msemax_klev, Real* lcl_temperature, Int* lcl_klev, Int* eql_klev, Real* cape, bool calc_msemax_klev, Int* prev_msemax_klev, bool use_input_tq_mx, Real* q_mx, Real* t_mx); - -void find_mse_max_bridge_f(Int pcols, Int ncol, Int pver, Int num_msg, Int* msemax_top_k, bool pergro_active, Real* temperature, Real* zmid, Real* sp_humidity, Int* msemax_klev, Real* mse_max_val); - -void compute_dilute_parcel_bridge_f(Int pcols, Int ncol, Int pver, Int num_msg, Int* klaunch, Real* pmid, Real* temperature, Real* sp_humidity, Real* tpert, Int* pblt, Real* parcel_temp, Real* parcel_vtemp, Real* parcel_qsat, Real* lcl_pmid, Real* lcl_temperature, Int* lcl_klev); - -void compute_cape_from_parcel_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Int num_cin, Int num_msg, Real* temperature, Real* tv, Real* sp_humidity, Real* pint, Int* msemax_klev, Real* lcl_pmid, Int* lcl_klev, Real* parcel_qsat, Real* parcel_temp, Real* parcel_vtemp, Int* eql_klev, Real* cape); - -void zm_conv_mcsp_calculate_shear_bridge_f(Int pcols, Int ncol, Int pver, Real* state_pmid, Real* state_u, Real* state_v, Real* mcsp_shear); - -void zm_conv_mcsp_tend_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Real ztodt, Int* jctop, Real* state_pmid, Real* state_pint, Real* state_pdel, Real* state_s, Real* state_q, Real* state_u, Real* state_v, Real* ptend_zm_s, Real* ptend_zm_q, Real* ptend_s, Real* ptend_q, Real* ptend_u, Real* ptend_v, Real* mcsp_ds_out, Real* mcsp_dq_out, Real* mcsp_du_out, Real* mcsp_dv_out, Real* mcsp_freq, Real* mcsp_shear, Real* zm_depth); - -void zm_conv_main_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, bool is_first_step, Real time_step, Real* t_mid, Real* q_mid_in, Real* omega, Real* p_mid_in, Real* p_int_in, Real* p_del_in, Real* geos, Real* z_mid_in, Real* z_int_in, Real* pbl_hgt, Real* tpert, Real* landfrac, Real* t_star, Real* q_star, Int* lengath, Int* gather_index, Int* msemax_klev_g, Int* jctop, Int* jcbot, Int* jt, Real* prec, Real* heat, Real* qtnd, Real* cape, Real* dcape, Real* mcon, Real* pflx, Real* zdu, Real* mflx_up, Real* entr_up, Real* detr_up, Real* mflx_dn, Real* entr_dn, Real* p_del, Real* dsubcld, Real* ql, Real* rliq, Real* rprd, Real* dlf); - -void zm_conv_evap_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Real time_step, Real* p_mid, Real* p_del, Real* t_mid, Real* q_mid, Real* prdprec, Real* cldfrc, Real* tend_s, Real* tend_q, Real* tend_s_snwprd, Real* tend_s_snwevmlt, Real* prec, Real* snow, Real* ntprprd, Real* ntsnprd, Real* flxprec, Real* flxsnow); - -void zm_calc_fractional_entrainment_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Int msg, Int* jb, Int* jt, Int* j0, Real* z_mid, Real* z_int, Real* dz, Real* h_env, Real* h_env_sat, Real* h_env_min, Real* lambda, Real* lambda_max); - -void zm_downdraft_properties_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Int msg, Int* jb, Int* jt, Int* j0, Int* jd, Real* z_int, Real* dz, Real* s_mid, Real* q_mid, Real* h_env, Real* lambda, Real* lambda_max, Real* qsthat, Real* hsthat, Real* gamhat, Real* rprd, Real* mflx_up, Real* mflx_dn, Real* entr_dn, Real* s_dnd, Real* q_dnd, Real* h_dnd, Real* q_dnd_sat, Real* evp, Real* totevp); - -void zm_cloud_properties_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Int msg, Int limcnv, Real* p_mid, Real* z_mid, Real* z_int, Real* t_mid, Real* s_mid, Real* s_int, Real* q_mid, Real* landfrac, Real* tpert_g, Int* jb, Int* lel, Int* jt, Int* jlcl, Int* j0, Int* jd, Real* mflx_up, Real* entr_up, Real* detr_up, Real* mflx_dn, Real* entr_dn, Real* mflx_net, Real* s_upd, Real* q_upd, Real* ql, Real* s_dnd, Real* q_dnd, Real* qst, Real* cu, Real* evp, Real* pflx, Real* rprd); - -void zm_closure_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Int msg, Real cape_threshold_in, Int* lcl, Int* lel, Int* jt, Int* mx, Real* dsubcld, Real* z_mid, Real* z_int, Real* p_mid, Real* p_del, Real* t_mid, Real* s_mid, Real* q_mid, Real* qs, Real* ql, Real* s_int, Real* q_int, Real* t_pcl_lcl, Real* t_pcl, Real* q_pcl_sat, Real* s_upd, Real* q_upd, Real* mflx_net, Real* detr_up, Real* mflx_up, Real* mflx_dn, Real* q_dnd, Real* s_dnd, Real* cape, Real* cld_base_mass_flux); - -void zm_calc_output_tend_bridge_f(Int pcols, Int ncol, Int pver, Int pverp, Int msg, Int* jt, Int* mx, Real* dsubcld, Real* p_del, Real* s_int, Real* q_int, Real* s_upd, Real* q_upd, Real* mflx_up, Real* detr_up, Real* mflx_dn, Real* s_dnd, Real* q_dnd, Real* ql, Real* evp, Real* cu, Real* dsdt, Real* dqdt, Real* dl); -} // extern "C" : end _f decls - -// Inits and finalizes are not intended to be called outside this comp unit namespace { -void zm_opts_init_f() -{ - zm_opts_init_bridge_f(); -} - -void zm_opts_finalize_f() -{ - zm_opts_finalize_bridge_f(); -} - - // Wrapper around zm_opts_init for cxx void zm_opts_init() { @@ -100,15 +43,6 @@ void zm_finalize_cxx() } -void ientropy_f(IentropyData& d) -{ - d.transition(); - zm_opts_init_f(); - ientropy_bridge_f(d.s, d.p, d.qt, &d.t, &d.qst, d.tfg); - zm_opts_finalize_f(); - d.transition(); -} - void ientropy(IentropyData& d) { zm_opts_init(); @@ -146,15 +80,6 @@ void ientropy(IentropyData& d) zm_finalize_cxx(); } -void entropy_f(EntropyData& d) -{ - d.transition(); - zm_opts_init_f(); - entropy_bridge_f(d.tk, d.p, d.qtot, &d.entropy); - zm_opts_finalize_f(); - d.transition(); -} - void entropy(EntropyData& d) { zm_opts_init(); @@ -183,15 +108,6 @@ void entropy(EntropyData& d) zm_finalize_cxx(); } -void zm_transport_tracer_f(ZmTransportTracerData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_transport_tracer_bridge_f(d.pcols, d.pver, d.doconvtran, d.q, d.ncnst, d.mu, d.md, d.du, d.eu, d.ed, d.dp, d.jt, d.mx, d.ideep, d.il1g, d.il2g, d.fracis, d.dqdt, d.dpdry, d.dt); - zm_opts_finalize_f(); - d.transition(); -} - void zm_transport_tracer(ZmTransportTracerData& d) { zm_opts_init(); @@ -304,15 +220,6 @@ void zm_transport_tracer(ZmTransportTracerData& d) zm_finalize_cxx(); } -void zm_transport_momentum_f(ZmTransportMomentumData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_transport_momentum_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.wind_in, d.nwind, d.mu, d.md, d.du, d.eu, d.ed, d.dp, d.jt, d.mx, d.ideep, d.il1g, d.il2g, d.wind_tend, d.pguall, d.pgdall, d.icwu, d.icwd, d.dt, d.seten); - zm_opts_finalize_f(); - d.transition(); -} - void zm_transport_momentum(ZmTransportMomentumData& d) { zm_opts_init(); @@ -470,15 +377,6 @@ void zm_transport_momentum(ZmTransportMomentumData& d) zm_finalize_cxx(); } -void compute_dilute_cape_f(ComputeDiluteCapeData& d) -{ - d.transition(); - zm_opts_init_f(); - compute_dilute_cape_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.num_cin, d.num_msg, d.sp_humidity_in, d.temperature_in, d.zmid, d.pmid, d.pint, d.pblt, d.tpert, d.parcel_temp, d.parcel_qsat, d.msemax_klev, d.lcl_temperature, d.lcl_klev, d.eql_klev, d.cape, d.calc_msemax_klev, d.prev_msemax_klev, d.use_input_tq_mx, d.q_mx, d.t_mx); - zm_opts_finalize_f(); - d.transition(); -} - void compute_dilute_cape(ComputeDiluteCapeData& d) { zm_opts_init(); @@ -586,15 +484,6 @@ void compute_dilute_cape(ComputeDiluteCapeData& d) zm_finalize_cxx(); } -void find_mse_max_f(FindMseMaxData& d) -{ - d.transition(); - zm_opts_init_f(); - find_mse_max_bridge_f(d.pcols, d.ncol, d.pver, d.num_msg, d.msemax_top_k, d.pergro_active, d.temperature, d.zmid, d.sp_humidity, d.msemax_klev, d.mse_max_val); - zm_opts_finalize_f(); - d.transition(); -} - void find_mse_max(FindMseMaxData& d) { zm_opts_init(); @@ -663,15 +552,6 @@ void find_mse_max(FindMseMaxData& d) zm_finalize_cxx(); } -void compute_dilute_parcel_f(ComputeDiluteParcelData& d) -{ - d.transition(); - zm_opts_init_f(); - compute_dilute_parcel_bridge_f(d.pcols, d.ncol, d.pver, d.num_msg, d.klaunch, d.pmid, d.temperature, d.sp_humidity, d.tpert, d.pblt, d.parcel_temp, d.parcel_vtemp, d.parcel_qsat, d.lcl_pmid, d.lcl_temperature, d.lcl_klev); - zm_opts_finalize_f(); - d.transition(); -} - void compute_dilute_parcel(ComputeDiluteParcelData& d) { zm_opts_init(); @@ -758,15 +638,6 @@ void compute_dilute_parcel(ComputeDiluteParcelData& d) zm_finalize_cxx(); } -void compute_cape_from_parcel_f(ComputeCapeFromParcelData& d) -{ - d.transition(); - zm_opts_init_f(); - compute_cape_from_parcel_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.num_cin, d.num_msg, d.temperature, d.tv, d.sp_humidity, d.pint, d.msemax_klev, d.lcl_pmid, d.lcl_klev, d.parcel_qsat, d.parcel_temp, d.parcel_vtemp, d.eql_klev, d.cape); - zm_opts_finalize_f(); - d.transition(); -} - void compute_cape_from_parcel(ComputeCapeFromParcelData& d) { zm_opts_init(); @@ -860,15 +731,6 @@ void compute_cape_from_parcel(ComputeCapeFromParcelData& d) zm_finalize_cxx(); } -void zm_conv_mcsp_calculate_shear_f(ZmConvMcspCalculateShearData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_conv_mcsp_calculate_shear_bridge_f(d.pcols, d.ncol, d.pver, d.state_pmid, d.state_u, d.state_v, d.mcsp_shear); - zm_opts_finalize_f(); - d.transition(); -} - void zm_conv_mcsp_calculate_shear(ZmConvMcspCalculateShearData& d) { zm_opts_init(); @@ -916,15 +778,6 @@ void zm_conv_mcsp_calculate_shear(ZmConvMcspCalculateShearData& d) zm_finalize_cxx(); } -void zm_conv_mcsp_tend_f(ZmConvMcspTendData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_conv_mcsp_tend_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.ztodt, d.jctop, d.state_pmid, d.state_pint, d.state_pdel, d.state_s, d.state_q, d.state_u, d.state_v, d.ptend_zm_s, d.ptend_zm_q, d.ptend_s, d.ptend_q, d.ptend_u, d.ptend_v, d.mcsp_ds_out, d.mcsp_dq_out, d.mcsp_du_out, d.mcsp_dv_out, d.mcsp_freq, d.mcsp_shear, d.zm_depth); - zm_opts_finalize_f(); - d.transition(); -} - void zm_conv_mcsp_tend(ZmConvMcspTendData& d) { zm_opts_init(); @@ -1041,15 +894,6 @@ void zm_conv_mcsp_tend(ZmConvMcspTendData& d) zm_finalize_cxx(); } -void zm_conv_main_f(ZmConvMainData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_conv_main_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.is_first_step, d.time_step, d.t_mid, d.q_mid_in, d.omega, d.p_mid_in, d.p_int_in, d.p_del_in, d.geos, d.z_mid_in, d.z_int_in, d.pbl_hgt, d.tpert, d.landfrac, d.t_star, d.q_star, &d.lengath, d.gather_index, d.msemax_klev, d.jctop, d.jcbot, d.jt, d.prec, d.heat, d.qtnd, d.cape, d.dcape, d.mcon, d.pflx, d.zdu, d.mflx_up, d.entr_up, d.detr_up, d.mflx_dn, d.entr_dn, d.p_del, d.dsubcld, d.ql, d.rliq, d.rprd, d.dlf); - zm_opts_finalize_f(); - d.transition(); -} - std::vector zm_conv_main(ZmConvMainData& d) { zm_opts_init(); @@ -1156,15 +1000,6 @@ std::vector zm_conv_main(ZmConvMainData& d) return active_v; } -void zm_conv_evap_f(ZmConvEvapData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_conv_evap_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.time_step, d.p_mid, d.p_del, d.t_mid, d.q_mid, d.prdprec, d.cldfrc, d.tend_s, d.tend_q, d.tend_s_snwprd, d.tend_s_snwevmlt, d.prec, d.snow, d.ntprprd, d.ntsnprd, d.flxprec, d.flxsnow); - zm_opts_finalize_f(); - d.transition(); -} - void zm_conv_evap(ZmConvEvapData& d) { zm_opts_init(); @@ -1263,15 +1098,6 @@ void zm_conv_evap(ZmConvEvapData& d) zm_finalize_cxx(); } -void zm_calc_fractional_entrainment_f(ZmCalcFractionalEntrainmentData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_calc_fractional_entrainment_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.msg, d.jb, d.jt, d.j0, d.z_mid, d.z_int, d.dz, d.h_env, d.h_env_sat, d.h_env_min, d.lambda, d.lambda_max); - zm_opts_finalize_f(); - d.transition(); -} - void zm_calc_fractional_entrainment(ZmCalcFractionalEntrainmentData& d) { zm_opts_init(); @@ -1358,15 +1184,6 @@ void zm_calc_fractional_entrainment(ZmCalcFractionalEntrainmentData& d) zm_finalize_cxx(); } -void zm_downdraft_properties_f(ZmDowndraftPropertiesData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_downdraft_properties_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.msg, d.jb, d.jt, d.j0, d.jd, d.z_int, d.dz, d.s_mid, d.q_mid, d.h_env, d.lambda, d.lambda_max, d.qsthat, d.hsthat, d.gamhat, d.rprd, d.mflx_up, d.mflx_dn, d.entr_dn, d.s_dnd, d.q_dnd, d.h_dnd, d.q_dnd_sat, d.evp, d.totevp); - zm_opts_finalize_f(); - d.transition(); -} - void zm_downdraft_properties(ZmDowndraftPropertiesData& d) { zm_opts_init(); @@ -1493,15 +1310,6 @@ void zm_downdraft_properties(ZmDowndraftPropertiesData& d) zm_finalize_cxx(); } -void zm_cloud_properties_f(ZmCloudPropertiesData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_cloud_properties_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.msg, d.limcnv, d.p_mid, d.z_mid, d.z_int, d.t_mid, d.s_mid, d.s_int, d.q_mid, d.landfrac, d.tpert_g, d.jb, d.lel, d.jt, d.jlcl, d.j0, d.jd, d.mflx_up, d.entr_up, d.detr_up, d.mflx_dn, d.entr_dn, d.mflx_net, d.s_upd, d.q_upd, d.ql, d.s_dnd, d.q_dnd, d.qst, d.cu, d.evp, d.pflx, d.rprd); - zm_opts_finalize_f(); - d.transition(); -} - void zm_cloud_properties(ZmCloudPropertiesData& d) { zm_opts_init(); @@ -1647,15 +1455,6 @@ void zm_cloud_properties(ZmCloudPropertiesData& d) zm_finalize_cxx(); } -void zm_closure_f(ZmClosureData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_closure_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.msg, d.cape_threshold_in, d.lcl, d.lel, d.jt, d.mx, d.dsubcld, d.z_mid, d.z_int, d.p_mid, d.p_del, d.t_mid, d.s_mid, d.q_mid, d.qs, d.ql, d.s_int, d.q_int, d.t_pcl_lcl, d.t_pcl, d.q_pcl_sat, d.s_upd, d.q_upd, d.mflx_net, d.detr_up, d.mflx_up, d.mflx_dn, d.q_dnd, d.s_dnd, d.cape, d.cld_base_mass_flux); - zm_opts_finalize_f(); - d.transition(); -} - void zm_closure(ZmClosureData& d) { zm_opts_init(); @@ -1791,15 +1590,6 @@ void zm_closure(ZmClosureData& d) zm_finalize_cxx(); } -void zm_calc_output_tend_f(ZmCalcOutputTendData& d) -{ - d.transition(); - zm_opts_init_f(); - zm_calc_output_tend_bridge_f(d.pcols, d.ncol, d.pver, d.pverp, d.msg, d.jt, d.mx, d.dsubcld, d.p_del, d.s_int, d.q_int, d.s_upd, d.q_upd, d.mflx_up, d.detr_up, d.mflx_dn, d.s_dnd, d.q_dnd, d.ql, d.evp, d.cu, d.dsdt, d.dqdt, d.dl); - zm_opts_finalize_f(); - d.transition(); -} - void zm_calc_output_tend(ZmCalcOutputTendData& d) { zm_opts_init(); diff --git a/components/eamxx/src/physics/zm/tests/infra/zm_test_data.hpp b/components/eamxx/src/physics/zm/tests/infra/zm_test_data.hpp index 73ec02123945..ca2c9d196a8e 100644 --- a/components/eamxx/src/physics/zm/tests/infra/zm_test_data.hpp +++ b/components/eamxx/src/physics/zm/tests/infra/zm_test_data.hpp @@ -860,40 +860,23 @@ struct ZmCalcOutputTendData : public PhysicsTestData { } }; -// Glue functions for host test data. We can call either fortran or CXX with this data (_f -> fortran) -void ientropy_f(IentropyData& d); +// Glue functions for host test data void ientropy(IentropyData& d); -void entropy_f(EntropyData& d); void entropy(EntropyData& d); -void zm_transport_tracer_f(ZmTransportTracerData& d); void zm_transport_tracer(ZmTransportTracerData& d); -void zm_transport_momentum_f(ZmTransportMomentumData& d); void zm_transport_momentum(ZmTransportMomentumData& d); -void compute_dilute_cape_f(ComputeDiluteCapeData& d); void compute_dilute_cape(ComputeDiluteCapeData& d); -void find_mse_max_f(FindMseMaxData& d); void find_mse_max(FindMseMaxData& d); -void compute_dilute_parcel_f(ComputeDiluteParcelData& d); void compute_dilute_parcel(ComputeDiluteParcelData& d); -void compute_cape_from_parcel_f(ComputeCapeFromParcelData& d); void compute_cape_from_parcel(ComputeCapeFromParcelData& d); -void zm_conv_mcsp_calculate_shear_f(ZmConvMcspCalculateShearData& d); void zm_conv_mcsp_calculate_shear(ZmConvMcspCalculateShearData& d); -void zm_conv_mcsp_tend_f(ZmConvMcspTendData& d); void zm_conv_mcsp_tend(ZmConvMcspTendData& d); -void zm_conv_main_f(ZmConvMainData& d); std::vector zm_conv_main(ZmConvMainData& d); -void zm_conv_evap_f(ZmConvEvapData& d); void zm_conv_evap(ZmConvEvapData& d); -void zm_calc_fractional_entrainment_f(ZmCalcFractionalEntrainmentData& d); void zm_calc_fractional_entrainment(ZmCalcFractionalEntrainmentData& d); -void zm_downdraft_properties_f(ZmDowndraftPropertiesData& d); void zm_downdraft_properties(ZmDowndraftPropertiesData& d); -void zm_cloud_properties_f(ZmCloudPropertiesData& d); void zm_cloud_properties(ZmCloudPropertiesData& d); -void zm_closure_f(ZmClosureData& d); void zm_closure(ZmClosureData& d); -void zm_calc_output_tend_f(ZmCalcOutputTendData& d); void zm_calc_output_tend(ZmCalcOutputTendData& d); // End glue function decls diff --git a/components/eamxx/src/physics/zm/tests/zm_calc_fractional_entrainment_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_calc_fractional_entrainment_tests.cpp index 420aa0cd0c4d..0ccaf54f0ecb 100644 --- a/components/eamxx/src/physics/zm/tests/zm_calc_fractional_entrainment_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_calc_fractional_entrainment_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmCalcFractionalEntrainment : public UnitWrap: // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_calc_fractional_entrainment_f(d); - } - else { - zm_calc_fractional_entrainment(d); - } + zm_calc_fractional_entrainment(d); } // TODO - Remove? diff --git a/components/eamxx/src/physics/zm/tests/zm_calc_output_tend_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_calc_output_tend_tests.cpp index a3c5e134f968..8997d04114c4 100644 --- a/components/eamxx/src/physics/zm/tests/zm_calc_output_tend_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_calc_output_tend_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmCalcOutputTend : public UnitWrap::UnitTestm_baseline_action == GENERATE) { - zm_calc_output_tend_f(d); - } - else { - zm_calc_output_tend(d); - } + zm_calc_output_tend(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_closure_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_closure_tests.cpp index f7460f2770e1..04136e908679 100644 --- a/components/eamxx/src/physics/zm/tests/zm_closure_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_closure_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmClosure : public UnitWrap::UnitTest::Base // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_closure_f(d); - } - else { - zm_closure(d); - } + zm_closure(d); } // TODO - Remove? diff --git a/components/eamxx/src/physics/zm/tests/zm_cloud_properties_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_cloud_properties_tests.cpp index af7a63ff8237..448fe7a74ab8 100644 --- a/components/eamxx/src/physics/zm/tests/zm_cloud_properties_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_cloud_properties_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmCloudProperties : public UnitWrap::UnitTest< // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_cloud_properties_f(d); - } - else { - zm_cloud_properties(d); - } + zm_cloud_properties(d); } const auto margin = std::numeric_limits::epsilon() * diff --git a/components/eamxx/src/physics/zm/tests/zm_compute_cape_from_parcel_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_compute_cape_from_parcel_tests.cpp index 4e13914af78f..9107c8091fcf 100644 --- a/components/eamxx/src/physics/zm/tests/zm_compute_cape_from_parcel_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_compute_cape_from_parcel_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestComputeCapeFromParcel : public UnitWrap::UnitT // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - compute_cape_from_parcel_f(d); - } - else { - compute_cape_from_parcel(d); - } + compute_cape_from_parcel(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_compute_dilute_cape_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_compute_dilute_cape_tests.cpp index 5ac1c9b487fe..d99eebca3995 100644 --- a/components/eamxx/src/physics/zm/tests/zm_compute_dilute_cape_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_compute_dilute_cape_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestComputeDiluteCape : public UnitWrap::UnitTest< // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - compute_dilute_cape_f(d); - } - else { - compute_dilute_cape(d); - } + compute_dilute_cape(d); } const auto margin = std::numeric_limits::epsilon() * diff --git a/components/eamxx/src/physics/zm/tests/zm_compute_dilute_parcel_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_compute_dilute_parcel_tests.cpp index 1c8336321d51..c13122093a21 100644 --- a/components/eamxx/src/physics/zm/tests/zm_compute_dilute_parcel_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_compute_dilute_parcel_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestComputeDiluteParcel : public UnitWrap::UnitTes // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - compute_dilute_parcel_f(d); - } - else { - compute_dilute_parcel(d); - } + compute_dilute_parcel(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_conv_evap_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_conv_evap_tests.cpp index fe65aeae0341..697d6f0ccee5 100644 --- a/components/eamxx/src/physics/zm/tests/zm_conv_evap_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_conv_evap_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmConvEvap : public UnitWrap::UnitTest::Bas // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_conv_evap_f(d); - } - else { - zm_conv_evap(d); - } + zm_conv_evap(d); } const auto margin = std::numeric_limits::epsilon() * diff --git a/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp index 5283de72134e..697c5c93346f 100644 --- a/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp @@ -53,13 +53,8 @@ struct UnitWrap::UnitTest::TestZmConvMain : public UnitWrap::UnitTest::Bas // Get data from test std::vector> actives; for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_conv_main_f(d); - } - else { - auto active = zm_conv_main(d); - actives.push_back(active); - } + auto active = zm_conv_main(d); + actives.push_back(active); } const auto margin = std::numeric_limits::epsilon() * diff --git a/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_calculate_shear_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_calculate_shear_tests.cpp index 5bc3adbb9412..e139fd224c79 100644 --- a/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_calculate_shear_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_calculate_shear_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmConvMcspCalculateShear : public UnitWrap::Un // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_conv_mcsp_calculate_shear_f(d); - } - else { - zm_conv_mcsp_calculate_shear(d); - } + zm_conv_mcsp_calculate_shear(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_tend_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_tend_tests.cpp index 6c370eb29033..f599391b588a 100644 --- a/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_tend_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_conv_mcsp_tend_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmConvMcspTend : public UnitWrap::UnitTest: // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_conv_mcsp_tend_f(d); - } - else { - zm_conv_mcsp_tend(d); - } + zm_conv_mcsp_tend(d); } // zm_conv_mcsp_test does a few sum reductions and we can't guarantee diff --git a/components/eamxx/src/physics/zm/tests/zm_downdraft_properties_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_downdraft_properties_tests.cpp index be1b7a64e618..afc32e908989 100644 --- a/components/eamxx/src/physics/zm/tests/zm_downdraft_properties_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_downdraft_properties_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmDowndraftProperties : public UnitWrap::UnitT // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_downdraft_properties_f(d); - } - else { - zm_downdraft_properties(d); - } + zm_downdraft_properties(d); } // TODO - Remove? diff --git a/components/eamxx/src/physics/zm/tests/zm_entropy_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_entropy_tests.cpp index 1e22b0183172..08402cd8957c 100644 --- a/components/eamxx/src/physics/zm/tests/zm_entropy_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_entropy_tests.cpp @@ -46,12 +46,7 @@ struct UnitWrap::UnitTest::TestEntropy : public UnitWrap::UnitTest::Base { // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - entropy_f(d); - } - else { - entropy(d); - } + entropy(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_find_mse_max_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_find_mse_max_tests.cpp index e0cfbc76dbd5..b5a0154f82ea 100644 --- a/components/eamxx/src/physics/zm/tests/zm_find_mse_max_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_find_mse_max_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestFindMseMax : public UnitWrap::UnitTest::Bas // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - find_mse_max_f(d); - } - else { - find_mse_max(d); - } + find_mse_max(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_ientropy_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_ientropy_tests.cpp index b6500d37589e..0a6b9e2a8965 100644 --- a/components/eamxx/src/physics/zm/tests/zm_ientropy_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_ientropy_tests.cpp @@ -46,12 +46,7 @@ struct UnitWrap::UnitTest::TestIentropy : public UnitWrap::UnitTest::Base // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - ientropy_f(d); - } - else { - ientropy(d); - } + ientropy(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_transport_momentum_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_transport_momentum_tests.cpp index 13b7b1661474..3a28b4fe9f4e 100644 --- a/components/eamxx/src/physics/zm/tests/zm_transport_momentum_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_transport_momentum_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmTransportMomentum : public UnitWrap::UnitTes // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_transport_momentum_f(d); - } - else { - zm_transport_momentum(d); - } + zm_transport_momentum(d); } // Verify BFB results, all data should be in C layout diff --git a/components/eamxx/src/physics/zm/tests/zm_transport_tracer_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_transport_tracer_tests.cpp index c3196bc16c4d..cbd773716010 100644 --- a/components/eamxx/src/physics/zm/tests/zm_transport_tracer_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_transport_tracer_tests.cpp @@ -52,12 +52,7 @@ struct UnitWrap::UnitTest::TestZmTransportTracer : public UnitWrap::UnitTest< // Get data from test for (auto& d : test_data) { - if (this->m_baseline_action == GENERATE) { - zm_transport_tracer_f(d); - } - else { - zm_transport_tracer(d); - } + zm_transport_tracer(d); } // Verify BFB results, all data should be in C layout From f04a16c7594847430f955add26064ab80cf63a58 Mon Sep 17 00:00:00 2001 From: James Foucar Date: Fri, 28 Aug 2026 13:43:14 -0600 Subject: [PATCH 2/8] Remove all bridging --- .../eamxx/src/physics/zm/CMakeLists.txt | 37 +- .../zm/fortran_bridge/zm_eamxx_bridge.cpp | 134 ---- .../zm/fortran_bridge/zm_eamxx_bridge.hpp | 31 - .../fortran_bridge/zm_eamxx_bridge_main.F90 | 394 ---------- .../zm_eamxx_bridge_methods.F90 | 284 ------- .../fortran_bridge/zm_eamxx_bridge_params.F90 | 24 - .../zm_eamxx_bridge_physconst.F90 | 105 --- .../zm_eamxx_bridge_wv_saturation.F90 | 737 ------------------ 8 files changed, 1 insertion(+), 1745 deletions(-) delete mode 100644 components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.cpp delete mode 100644 components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.hpp delete mode 100644 components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_main.F90 delete mode 100644 components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_methods.F90 delete mode 100644 components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_params.F90 delete mode 100644 components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_physconst.F90 delete mode 100644 components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_wv_saturation.F90 diff --git a/components/eamxx/src/physics/zm/CMakeLists.txt b/components/eamxx/src/physics/zm/CMakeLists.txt index 8f89f0959956..1792a49aa527 100644 --- a/components/eamxx/src/physics/zm/CMakeLists.txt +++ b/components/eamxx/src/physics/zm/CMakeLists.txt @@ -1,37 +1,3 @@ -set(PATH_TO_LEGACY_ZM ${SCREAM_BASE_DIR}/../eam/src/physics/cam/zm/) - -set(ZM_F90_SRCS - # ---------------------------------------------------------------------------- - # EAMxx side C++ bridge methods - ${CMAKE_CURRENT_SOURCE_DIR}/fortran_bridge/zm_eamxx_bridge.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/fortran_bridge/zm_eamxx_bridge_main.F90 - ${CMAKE_CURRENT_SOURCE_DIR}/fortran_bridge/zm_eamxx_bridge_params.F90 - ${CMAKE_CURRENT_SOURCE_DIR}/fortran_bridge/zm_eamxx_bridge_methods.F90 - ${CMAKE_CURRENT_SOURCE_DIR}/fortran_bridge/zm_eamxx_bridge_physconst.F90 - ${CMAKE_CURRENT_SOURCE_DIR}/fortran_bridge/zm_eamxx_bridge_wv_saturation.F90 - # ---------------------------------------------------------------------------- - # Fortran ZM code - ${PATH_TO_LEGACY_ZM}/zm_conv.F90 - ${PATH_TO_LEGACY_ZM}/zm_conv_cape.F90 - ${PATH_TO_LEGACY_ZM}/zm_conv_util.F90 - ${PATH_TO_LEGACY_ZM}/zm_conv_types.F90 - ${PATH_TO_LEGACY_ZM}/zm_aero_type.F90 - ${PATH_TO_LEGACY_ZM}/zm_microphysics_state.F90 - ${PATH_TO_LEGACY_ZM}/zm_conv_mcsp.F90 - ${PATH_TO_LEGACY_ZM}/zm_transport.F90 - # ---------------------------------------------------------------------------- - # shared fotran modules - ${SCREAM_BASE_DIR}/../../share/util/shr_sys_mod.F90 - ${SCREAM_BASE_DIR}/../../share/util/shr_kind_mod.F90 - ${SCREAM_BASE_DIR}/../../share/util/shr_assert_mod.F90.in - # ---------------------------------------------------------------------------- - # misc other fotran modules - ${SCREAM_BASE_DIR}/../eam/src/physics/cam/wv_sat_methods.F90 - ${SCREAM_BASE_DIR}/../eam/src/utils/cam_abortutils.F90 - ${SCREAM_BASE_DIR}/../eam/src/control/cam_logfile.F90 - # ---------------------------------------------------------------------------- -) - set(ZM_SRCS # ---------------------------------------------------------------------------- # C++/EAMxx atomsphere process for ZM @@ -65,7 +31,7 @@ if (NOT EAMXX_ENABLE_GPU OR Kokkos_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE OR Kokkos ) # ZM ETI SRCS endif() -add_library(zm ${ZM_F90_SRCS} ${ZM_SRCS}) +add_library(zm ${ZM_SRCS}) set_target_properties(zm PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules @@ -75,7 +41,6 @@ target_compile_definitions(zm PUBLIC EAMXX_HAS_ZM) target_include_directories(zm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/fortran_bridge ${CMAKE_CURRENT_BINARY_DIR}/modules ${PATH_TO_LEGACY_ZM} ${PATH_TO_LEGACY_ZM}/.. diff --git a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.cpp b/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.cpp deleted file mode 100644 index 8312423be48c..000000000000 --- a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "zm_eamxx_bridge.hpp" - -using scream::Real; -using scream::Int; - -// A C++ interface to ZM fortran calls and vice versa - -extern "C" { - -void zm_eamxx_bridge_init_c( Int pver_in, Int limcnv_in, - bool trig_dcape_in, bool trig_ull_in, - bool clos_dyn_adj_in, bool mcsp_enabled_in ); - -void zm_eamxx_bridge_run_c( Int ncol, // 01 - Real dtime, // 02 - bool is_first_step, // 03 - const Real *state_phis, // 04 - Real *state_z_mid, // 05 - Real *state_z_int, // 06 - const Real *state_p_mid, // 07 - const Real *state_p_int, // 08 - const Real *state_p_del, // 09 - Real *state_t, // 10 - Real *state_qv, // 11 - Real *state_u, // 12 - Real *state_v, // 13 - Real *state_omega, // 14 - const Real *state_cldfrac,// 15 - const Real *state_pblh, // 16 - const Real *tpert, // 17 - const Real *landfrac, // 18 - Real *t_star, // 19 DCAPE T from time step n-1 - Real *q_star, // 20 DCAPE q from time step n-1 - Real *output_prec, // 21 - Real *output_snow, // 22 - Real *output_cape, // 23 - Real *output_dcape, // 24 - Int *output_activity, // 25 - Real *output_tend_t, // 26 - Real *output_tend_q, // 27 - Real *output_tend_u, // 28 - Real *output_tend_v, // 29 - Real *output_rain_prod, // 30 - Real *output_snow_prod, // 31 - Real *output_prec_flux, // 32 - Real *output_snow_flux, // 33 - Real *output_mass_flux, // 34 - Real *output_dlf, // 35 - Real *mcsp_freq, // 36 - Real *mcsp_shear, // 37 - Real *zm_depth, // 38 - Real *mcsp_ds_out, // 39 - Real *mcsp_dq_out, // 40 - Real *mcsp_du_out, // 41 - Real *mcsp_dv_out, // 42 - Real *evap_ds_out, // 43 - Real *evap_dq_out // 44 - ); -} // extern "C" : end _c decls - -namespace scream { -namespace zm { - -void zm_eamxx_bridge_init( Int pver, Int limcnv_in, - bool trig_dcape_in, bool trig_ull_in, - bool clos_dyn_adj_in, bool mcsp_enabled_in ){ - zm_eamxx_bridge_init_c( pver, limcnv_in, - trig_dcape_in, trig_ull_in, - clos_dyn_adj_in, mcsp_enabled_in ); -} - -void zm_eamxx_bridge_run( Int ncol, Int pver, Real dtime, bool is_first_step, - ZMF::ZmInputState& zm_input, - ZMF::ZmOutputTend& zm_output, - ZMF::ZmRuntimeOpt& zm_opts - ){ - //---------------------------------------------------------------------------- - zm_input.transpose(ncol,pver); - - zm_eamxx_bridge_run_c( ncol, // 01 - dtime, // 02 - is_first_step, // 03 - zm_input.h_phis .data(), // 04 - zm_input.h_z_mid .data(), // 05 - zm_input.h_z_int .data(), // 06 - zm_input.h_p_mid .data(), // 07 - zm_input.h_p_int .data(), // 08 - zm_input.h_p_del .data(), // 09 - zm_input.h_T_mid .data(), // 10 - zm_input.h_qv .data(), // 11 - zm_input.h_uwind .data(), // 12 - zm_input.h_vwind .data(), // 13 - zm_input.h_omega .data(), // 14 - zm_input.h_cldfrac .data(), // 15 - zm_input.h_pblh .data(), // 16 - zm_input.h_tpert .data(), // 17 - zm_input.h_landfrac .data(), // 18 - zm_input.h_t_prev .data(), // 19 - zm_input.h_q_prev .data(), // 20 - zm_output.h_prec .data(), // 21 - zm_output.h_snow .data(), // 22 - zm_output.h_cape .data(), // 23 - zm_output.h_dcape .data(), // 24 - zm_output.h_activity .data(), // 25 - zm_output.h_tend_t .data(), // 26 - zm_output.h_tend_qv .data(), // 27 - zm_output.h_tend_u .data(), // 28 - zm_output.h_tend_v .data(), // 29 - zm_output.h_rain_prod .data(), // 30 - zm_output.h_snow_prod .data(), // 31 - zm_output.h_prec_flux .data(), // 32 - zm_output.h_snow_flux .data(), // 33 - zm_output.h_mass_flux .data(), // 34 - zm_output.h_dlf .data(), // 35 - zm_output.h_mcsp_freq .data(), // 36 - zm_output.h_mcsp_shear .data(), // 37 - zm_output.h_zm_depth .data(), // 38 - zm_output.h_mcsp_ds_out.data(), // 39 - zm_output.h_mcsp_dq_out.data(), // 40 - zm_output.h_mcsp_du_out.data(), // 41 - zm_output.h_mcsp_dv_out.data(), // 42 - zm_output.h_evap_ds_out.data(), // 43 - zm_output.h_evap_dq_out.data() // 44 - ); - - zm_output.transpose(ncol,pver); - - //---------------------------------------------------------------------------- -} - -// end _c impls - -} // namespace zm -} // namespace scream diff --git a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.hpp b/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.hpp deleted file mode 100644 index c5270fae6a10..000000000000 --- a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "share/core/eamxx_types.hpp" - -#include -#include -#include // for shared_ptr - -#include "zm_functions.hpp" - -// Bridge functions to call fortran version of ZM functions from C++ - -namespace scream { -namespace zm { - -using ZMF = zm::Functions; - -// Glue functions to call fortran from from C++ with the Data struct -void zm_eamxx_bridge_init( Int pver, Int limcnv_in, - bool trig_dcape_in, bool trig_ull_in, - bool clos_dyn_adj_in, bool mcsp_enabled_in ); -void zm_eamxx_bridge_run( Int ncol, Int pver, Real dtime, bool is_first_step, - ZMF::ZmInputState& zm_input, - ZMF::ZmOutputTend& zm_output, - ZMF::ZmRuntimeOpt& zm_opts - ); - -extern "C" { // _f function decls -} - -} // namespace zm -} // namespace scream - diff --git a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_main.F90 b/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_main.F90 deleted file mode 100644 index a1f90149cbec..000000000000 --- a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_main.F90 +++ /dev/null @@ -1,394 +0,0 @@ -module zm_eamxx_bridge_main - !----------------------------------------------------------------------------- - ! Purpose: This replicates the functionality of zm_conv_intr.F90 to provide - ! an interface between EAMxx and EAM's fortran Zhang-McFarlane Deeep Cu scheme - !----------------------------------------------------------------------------- - use iso_c_binding - use cam_logfile, only: iulog - use shr_sys_mod, only: shr_sys_flush - use zm_eamxx_bridge_params, only: masterproc, r8, pver, pverp, top_lev - !----------------------------------------------------------------------------- - implicit none - private - !----------------------------------------------------------------------------- - ! public methods - public :: zm_eamxx_bridge_init_c - public :: zm_eamxx_bridge_run_c - -!=================================================================================================== -#include "eamxx_config.f" -#ifdef SCREAM_DOUBLE_PRECISION -# define c_real c_double -#else -# define c_real c_float -#endif -!=================================================================================================== -contains -!=================================================================================================== - -subroutine zm_eamxx_bridge_init_c( pver_in, limcnv_in, & - trig_dcape_in, trig_ull_in, & - clos_dyn_adj_in, mcsp_enabled_in ) bind(C) - use mpi - use zm_conv, only: zm_const, zm_param - use zm_conv_types, only: zm_const_set_for_testing, zm_param_set_for_testing - use zm_conv_types, only: zm_param_mpi_broadcast, zm_param_print - use zm_eamxx_bridge_wv_saturation, only: wv_sat_init - !----------------------------------------------------------------------------- - ! Arguments - integer(kind=c_int), value, intent(in) :: pver_in - integer(kind=c_int), value, intent(in) :: limcnv_in - logical(kind=c_bool),value, intent(in) :: trig_dcape_in - logical(kind=c_bool),value, intent(in) :: trig_ull_in - logical(kind=c_bool),value, intent(in) :: clos_dyn_adj_in - logical(kind=c_bool),value, intent(in) :: mcsp_enabled_in - !----------------------------------------------------------------------------- - ! Local variables - integer :: mpi_rank, ierror - !----------------------------------------------------------------------------- - pver = pver_in - pverp = pver+1 - top_lev = 1 - !----------------------------------------------------------------------------- - ! obtain master process ID - call mpi_comm_rank(MPI_COMM_WORLD, mpi_rank, ierror) - masterproc = .false. - if (mpi_rank==0) masterproc = .true. - !----------------------------------------------------------------------------- - ! set ZM constants and parameters - call zm_const_set_for_testing(zm_const) - call zm_param_set_for_testing(zm_param) - zm_param%limcnv = limcnv_in ! override testing value when running the fortran bridge - call zm_param_mpi_broadcast(zm_param) - ! override some settings - zm_param%zm_microp = .false. - zm_param%old_snow = .true. - zm_param%trig_dcape = trig_dcape_in - zm_param%trig_ull = trig_ull_in - zm_param%clos_dyn_adj = clos_dyn_adj_in - zm_param%mcsp_enabled = mcsp_enabled_in - call zm_param_print(zm_param) - !----------------------------------------------------------------------------- - call wv_sat_init() - !----------------------------------------------------------------------------- - return -end subroutine zm_eamxx_bridge_init_c - -!=================================================================================================== - -subroutine zm_eamxx_bridge_run_c( ncol, dtime, is_first_step, & - state_phis, state_zm, state_zi, & - state_p_mid, state_p_int, state_p_del, & - state_t, state_qv, state_u, state_v, & - state_omega, state_cldfrac, state_pblh, tpert, landfrac, & - t_star_in, q_star_in, & - output_prec, output_snow, output_cape, output_dcape, output_activity, & - output_tend_t, output_tend_q, output_tend_u, output_tend_v, & - output_rain_prod, output_snow_prod, & - output_prec_flux, output_snow_flux, output_mass_flux, & - output_dlf, mcsp_freq, mcsp_shear, zm_depth, & - mcsp_ds_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, & - evap_ds_out, evap_dq_out ) bind(C) - use zm_conv, only: zm_const, zm_param - use zm_aero_type, only: zm_aero_t - use zm_microphysics_state, only: zm_microp_st - use zm_eamxx_bridge_methods, only: zm_tend_init, zm_physics_update - use zm_conv, only: zm_conv_main, zm_conv_evap - use zm_conv_mcsp, only: zm_conv_mcsp_tend - use zm_transport, only: zm_transport_momentum - ! use zm_transport, only: zm_transport_tracer - use zm_conv_types, only: zm_param_print, zm_const_print - !----------------------------------------------------------------------------- - ! Arguments - integer(kind=c_int), value, intent(in ) :: ncol ! 01 number of columns on rank - real(kind=c_real), value, intent(in ) :: dtime ! 02 time step - logical(kind=c_bool), value, intent(in ) :: is_first_step ! 03 flag for first step - real(kind=c_real), dimension(ncol), intent(in ) :: state_phis ! 04 input state surface geopotential height - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_zm ! 05 input state altitude at mid-levels - real(kind=c_real), dimension(ncol,pverp),intent(in ) :: state_zi ! 06 input state altitude at interfaces - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_p_mid ! 07 input state mid-point pressure - real(kind=c_real), dimension(ncol,pverp),intent(in ) :: state_p_int ! 08 input state interface pressure - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_p_del ! 09 input state pressure thickness - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_t ! 10 input state temperature - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_qv ! 11 input state water vapor - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_u ! 12 input state zonal wind - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_v ! 13 input state meridional wind - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_omega ! 14 input state vertical pressure velocity - real(kind=c_real), dimension(ncol,pver), intent(in ) :: state_cldfrac ! 15 input state cloud fraction (cld) - real(kind=c_real), dimension(ncol), intent(in ) :: state_pblh ! 16 input planetary boundary layer height (pblh) - real(kind=c_real), dimension(ncol), intent(in ) :: tpert ! 17 input parcel temperature perturbation - real(kind=c_real), dimension(ncol), intent(in ) :: landfrac ! 18 land fraction - real(kind=c_real), dimension(ncol,pver), intent(inout) :: t_star_in ! 19 DCAPE T from time step n-1 - real(kind=c_real), dimension(ncol,pver), intent(inout) :: q_star_in ! 20 DCAPE q from time step n-1 - real(kind=c_real), dimension(ncol), intent( out) :: output_prec ! 21 output total precipitation (prec) - real(kind=c_real), dimension(ncol), intent( out) :: output_snow ! 22 output frozen precipitation (snow) - real(kind=c_real), dimension(ncol), intent( out) :: output_cape ! 23 output convective avail. pot. energy (cape) - real(kind=c_real), dimension(ncol), intent( out) :: output_dcape ! 24 output dynamic cape - integer(kind=c_int),dimension(ncol), intent( out) :: output_activity ! 25 integer deep convection activity flag (ideep) - real(kind=c_real), dimension(ncol,pver), intent( out) :: output_tend_t ! 26 output tendency of temperature (ptend_loc_s) - real(kind=c_real), dimension(ncol,pver), intent( out) :: output_tend_q ! 27 output tendency of water vapor (ptend_loc_q) - real(kind=c_real), dimension(ncol,pver), intent( out) :: output_tend_u ! 28 output tendency of zonal wind (ptend_loc_u) - real(kind=c_real), dimension(ncol,pver), intent( out) :: output_tend_v ! 29 output tendency of meridional wind (ptend_loc_v) - real(kind=c_real), dimension(ncol,pver), intent( out) :: output_rain_prod ! 30 rain production rate (rprd) - real(kind=c_real), dimension(ncol,pver), intent( out) :: output_snow_prod ! 31 snow production rate (sprd) - real(kind=c_real), dimension(ncol,pverp),intent( out) :: output_prec_flux ! 32 output precip flux at each mid-levels (flxprec/pflx) - real(kind=c_real), dimension(ncol,pverp),intent( out) :: output_snow_flux ! 33 output precip flux at each mid-levels (flxsnow) - real(kind=c_real), dimension(ncol,pverp),intent( out) :: output_mass_flux ! 34 output convective mass flux--m sub c (mcon) - real(kind=c_real), dimension(ncol,pver), intent( out) :: output_dlf ! 35 detrained convective cloud water (dlf) - real(kind=c_real), dimension(ncol), intent( out) :: mcsp_freq ! 36 MCSP diagnostic output - real(kind=c_real), dimension(ncol), intent( out) :: mcsp_shear ! 37 MCSP diagnostic output - real(kind=c_real), dimension(ncol), intent( out) :: zm_depth ! 38 MCSP diagnostic output - real(kind=c_real), dimension(ncol,pver), intent( out) :: mcsp_ds_out ! 39 MCSP tendency - real(kind=c_real), dimension(ncol,pver), intent( out) :: mcsp_dq_out ! 40 MCSP tendency - real(kind=c_real), dimension(ncol,pver), intent( out) :: mcsp_du_out ! 41 MCSP tendency - real(kind=c_real), dimension(ncol,pver), intent( out) :: mcsp_dv_out ! 42 MCSP tendency - real(kind=c_real), dimension(ncol,pver), intent( out) :: evap_ds_out ! 43 zm_conv_evap tendency - real(kind=c_real), dimension(ncol,pver), intent( out) :: evap_dq_out ! 44 zm_conv_evap tendency - !----------------------------------------------------------------------------- - ! Local variables - integer :: i,k - - logical(kind=c_bool) :: loc_is_first_step - - ! arguments for zm_conv_main - order somewhat consistent with current interface - integer, dimension(ncol) :: jctop ! output top-of-deep-convection indices - integer, dimension(ncol) :: jcbot ! output bot-of-deep-convection indices - real(r8), dimension(ncol,pver) :: zdu ! detraining mass flux - real(r8), dimension(ncol,pver) :: mu ! updraft cloud mass flux - real(r8), dimension(ncol,pver) :: md ! downdraft cloud mass flux - real(r8), dimension(ncol,pver) :: du ! detrainment in updraft - real(r8), dimension(ncol,pver) :: eu ! entrainment in updraft - real(r8), dimension(ncol,pver) :: ed ! entrainment in downdraft - real(r8), dimension(ncol,pver) :: dp ! layer thickness [mb] - real(r8), dimension(ncol) :: dsubcld ! sub-cloud layer thickness - integer, dimension(ncol) :: jt ! top level index of convection - integer, dimension(ncol) :: maxg ! gathered values of maxi - integer, dimension(ncol) :: ideep ! flag to indicate ZM is active - integer :: lengath ! number of gathered columns per chunk - real(r8), dimension(ncol) :: rliq ! reserved liquid (not yet in cldliq) for energy integrals - real(r8), dimension(ncol,pver), target :: local_t_star ! DCAPE T from time step n-1 - real(r8), dimension(ncol,pver), target :: local_q_star ! DCAPE q from time step n-1 - ! real(r8), dimension(ncol) :: dcape ! DCAPE cape change - type(zm_aero_t) :: aero ! derived type for aerosol information - type(zm_microp_st) :: microp_st ! ZM microphysics data structure - - real(r8), dimension(ncol,pver) :: state_s ! dry static energy - real(r8), dimension(ncol,pver) :: zm_qc ! convective in-cloud liquid water - - ! local copy of state variables for calling zm_conv_evap() - real(r8), dimension(ncol,pver) :: local_state_t - real(r8), dimension(ncol,pver) :: local_state_qv - real(r8), dimension(ncol,pver) :: local_state_zm - real(r8), dimension(ncol,pverp):: local_state_zi - - real(r8), dimension(ncol,pver) :: output_tend_s ! dry static energy tendency used to set output_tend_t - - ! temporary local tendencies for calling zm_conv_evap() - real(r8), dimension(ncol,pver) :: local_tend_s ! temporary tendency of dry static energy (ptend_loc_s) - real(r8), dimension(ncol,pver) :: local_tend_q ! temporary tendency of water vapor (ptend_loc_q) - real(r8), dimension(ncol,pver) :: local_tend_u ! temporary tendency of zonal wind - real(r8), dimension(ncol,pver) :: local_tend_v ! temporary tendency of meridional wind - - real(r8), dimension(ncol,pver) :: tend_s_snwprd ! DSE tend from snow production - real(r8), dimension(ncol,pver) :: tend_s_snwevmlt ! DSE tend from snow evap/melt - real(r8), dimension(ncol,pver) :: ntprprd ! net precip production in layer - real(r8), dimension(ncol,pver) :: ntsnprd ! net snow production in layer - - ! used in momentum transport calculations - real(r8), dimension(ncol,pver,2) :: tx_winds - real(r8), dimension(ncol,pver,2) :: tx_wind_tend - real(r8), dimension(ncol,pver,2) :: tx_pguall - real(r8), dimension(ncol,pver,2) :: tx_pgdall - real(r8), dimension(ncol,pver,2) :: tx_icwu - real(r8), dimension(ncol,pver,2) :: tx_icwd - - !----------------------------------------------------------------------------- - ! initialize various thing - - loc_is_first_step = is_first_step - - !----------------------------------------------------------------------------- - ! initialize output tendencies - normally done by physics_ptend_init() - - do i = 1,ncol - output_prec(i) = 0 - output_snow(i) = 0 - output_cape(i) = 0 - output_activity(i) = 0 - do k = 1,pver - output_tend_t(i,k) = 0 - output_tend_q(i,k) = 0 - output_tend_u(i,k) = 0 - output_tend_v(i,k) = 0 - output_rain_prod(i,k) = 0 - output_snow_prod(i,k) = 0 - output_prec_flux(i,k) = 0 - output_snow_flux(i,k) = 0 - output_mass_flux(i,k) = 0 - output_dlf(i,k) = 0 - end do - end do - - !----------------------------------------------------------------------------- - ! populate local copies of state variables for zm_conv_evap() - - do i = 1,ncol - do k = 1,pver - local_state_t (i,k) = state_t (i,k) - local_state_qv(i,k) = state_qv(i,k) - local_state_zm(i,k) = state_zm(i,k) - local_state_zi(i,k) = state_zi(i,k) - local_t_star (i,k) = t_star_in(i,k) - local_q_star (i,k) = q_star_in(i,k) - end do - end do - - !----------------------------------------------------------------------------- - ! Call the primary Zhang-McFarlane convection parameterization - - call zm_conv_main(ncol, ncol, pver, pverp, loc_is_first_step, dtime, & - state_t, state_qv, state_omega, & - state_p_mid, state_p_int, state_p_del, & - state_phis, state_zm, state_zi, state_pblh, & - tpert, landfrac, local_t_star, local_q_star, & - lengath, ideep, maxg, jctop, jcbot, jt, & - output_prec, output_tend_s, output_tend_q, & - output_cape, output_dcape, output_mass_flux, output_prec_flux, & - zdu, mu, eu, du, md, ed, dp, dsubcld, & - zm_qc, rliq, output_rain_prod, output_dlf, & - aero, microp_st ) - - !----------------------------------------------------------------------------- - ! mesoscale coherent structure parameterization (MCSP)- modifies tendencies from zm_conv_main() prior to updating the state - - if (zm_param%mcsp_enabled) then - - ! initialize local output tendencies for MCSP - call zm_tend_init( ncol, pver, local_tend_s, local_tend_q, local_tend_u, local_tend_v ) - - do i = 1,ncol - do k = 1,pver - state_s(i,k) = state_t(i,k)*zm_const%cpair - end do - end do - - ! perform the MCSP calculations - call zm_conv_mcsp_tend( ncol, ncol, pver, pverp, & - dtime, jctop, zm_const, zm_param, & - state_p_mid, state_p_int, state_p_del, & - state_s, state_qv, state_u, state_v, & - output_tend_s, output_tend_q, & - local_tend_s, local_tend_q, & - local_tend_u, local_tend_v, & - mcsp_ds_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, & - mcsp_freq, mcsp_shear, zm_depth ) - - ! add MCSP tendencies to ZM convective tendencies - do i = 1,ncol - do k = 1,pver - output_tend_s(i,k) = output_tend_s(i,k) + local_tend_s(i,k) - output_tend_q(i,k) = output_tend_q(i,k) + local_tend_q(i,k) - output_tend_u(i,k) = output_tend_u(i,k) + local_tend_u(i,k) - output_tend_v(i,k) = output_tend_v(i,k) + local_tend_v(i,k) - end do - end do - - end if - - !----------------------------------------------------------------------------- - ! apply tendencies from zm_conv_main() & MCSP to local copy of state variables - - call zm_physics_update( ncol, dtime, & - state_phis, local_state_zm, local_state_zi, & - state_p_mid, state_p_int, state_p_del, & - local_state_t, local_state_qv, & - output_tend_s, output_tend_q) - - !----------------------------------------------------------------------------- - ! Compute the precipitation, rain evaporation, and snow formation/melting - ! Note - this routine expects an updated state following zm_conv_main() (+MCSP) - - ! initialize local output tendencies for zm_conv_evap() - call zm_tend_init( ncol, pver, local_tend_s, local_tend_q, local_tend_u, local_tend_v ) - - ! perform the convective evaporation calculations - call zm_conv_evap(ncol, ncol, pver, pverp, dtime, & - state_p_mid, state_p_del, & - local_state_t, local_state_qv, & - output_rain_prod, state_cldfrac, & - local_tend_s, local_tend_q, & - tend_s_snwprd, tend_s_snwevmlt, & - output_prec, output_snow, ntprprd, ntsnprd, & - output_prec_flux, output_snow_flux, microp_st) - - ! add tendencies from zm_conv_evap() to output tendencies - do i = 1,ncol - do k = 1,pver - output_tend_s(i,k) = output_tend_s(i,k) + local_tend_s(i,k) - output_tend_q(i,k) = output_tend_q(i,k) + local_tend_q(i,k) - evap_ds_out(i,k) = local_tend_s(i,k) - evap_dq_out(i,k) = local_tend_q(i,k) - end do - end do - - !----------------------------------------------------------------------------- - ! convective momentum transport - - ! initialize local output tendencies for zm_transport_momentum() - call zm_tend_init( ncol, pver, local_tend_s, local_tend_q, tx_wind_tend(:,:,1), tx_wind_tend(:,:,2) ) - - do i = 1,ncol - do k = 1,pver - ! zm_transport_momentum expects winds that may have been modified by MCSP, - ! but normally this is disabled, so U/V tendencies will be zero - tx_winds(i,k,1) = state_u(i,k) + output_tend_u(i,k)*dtime - tx_winds(i,k,2) = state_v(i,k) + output_tend_v(i,k)*dtime - end do - end do - - call zm_transport_momentum( ncol, ncol, pver, pverp, tx_winds, 2, & - mu, md, du, eu, ed, dp, & - jt, maxg, ideep, 1, lengath, & - tx_wind_tend, tx_pguall, tx_pgdall, & - tx_icwu, tx_icwd, dtime, local_tend_s ) - - ! add tendencies from zm_transport_momentum() to output tendencies - do i = 1,ncol - do k = 1,pver - output_tend_s(i,k) = output_tend_s(i,k) + local_tend_s(i,k) - output_tend_u(i,k) = output_tend_u(i,k) + tx_wind_tend(i,k,1) - output_tend_v(i,k) = output_tend_v(i,k) + tx_wind_tend(i,k,2) - end do - end do - - !----------------------------------------------------------------------------- - ! convective tracer transport - - ! this is just a placeholder for now - ! call zm_transport_tracer(...) - - !----------------------------------------------------------------------------- - ! populate deep convection activity flag - - if (lengath.gt.0) then - do i=1,lengath - output_activity(ideep(i)) = 1 - end do - end if - - !----------------------------------------------------------------------------- - ! convert dry static energy tendency to temperature tendency - - do i = 1,ncol - do k = 1,pver - output_tend_t(i,k) = output_tend_s(i,k)/zm_const%cpair - end do - end do - - !----------------------------------------------------------------------------- - return -end subroutine zm_eamxx_bridge_run_c - -!=================================================================================================== - -end module zm_eamxx_bridge_main diff --git a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_methods.F90 b/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_methods.F90 deleted file mode 100644 index 46f39cfe6262..000000000000 --- a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_methods.F90 +++ /dev/null @@ -1,284 +0,0 @@ -module zm_eamxx_bridge_methods - !----------------------------------------------------------------------------- - use zm_eamxx_bridge_params, only: r8 - !----------------------------------------------------------------------------- - implicit none - private - !----------------------------------------------------------------------------- - ! public methods copied from EAM - public :: cldfrc_fice - public :: zm_tend_init - public :: zm_physics_update - public :: vertinterp - -!=================================================================================================== -contains -!=================================================================================================== - -! Copied from cloud_fraction.F90 (and adjusted indentation) -subroutine cldfrc_fice(ncol, pver, top_lev, t, fice, fsnow) - ! - ! Compute the fraction of the total cloud water which is in ice phase. - ! The fraction depends on temperature only. - ! This is the form that was used for radiation, the code came from cldefr originally - ! - ! Author: B. A. Boville Sept 10, 2002 - ! modified: PJR 3/13/03 (added fsnow to ascribe snow production for convection ) - !----------------------------------------------------------------------- - use zm_eamxx_bridge_physconst, only: tmelt - - ! Arguments - integer, intent(in) :: ncol, pver, top_lev ! number of active columns - real(r8), intent(in) :: t(ncol,pver) ! temperature - - real(r8), intent(out) :: fice(ncol,pver) ! Fractional ice content within cloud - real(r8), intent(out) :: fsnow(ncol,pver) ! Fractional snow content for convection - - ! Local variables - real(r8) :: tmax_fice ! max temperature for cloud ice formation - real(r8) :: tmin_fice ! min temperature for cloud ice formation - real(r8) :: tmax_fsnow ! max temperature for transition to convective snow - real(r8) :: tmin_fsnow ! min temperature for transition to convective snow - - integer :: i,k ! loop indexes - - !----------------------------------------------------------------------- - - tmax_fice = tmelt - 10._r8 ! max temperature for cloud ice formation - tmin_fice = tmax_fice - 30._r8 ! min temperature for cloud ice formation - tmax_fsnow = tmelt ! max temperature for transition to convective snow - tmin_fsnow = tmelt - 5._r8 ! min temperature for transition to convective snow - fice(:,:top_lev-1) = 0._r8 - fsnow(:,:top_lev-1) = 0._r8 - - ! Define fractional amount of cloud that is ice - do k=top_lev,pver - do i=1,ncol - ! If warmer than tmax then water phase - if (t(i,k) > tmax_fice) then - fice(i,k) = 0.0_r8 - ! If colder than tmin then ice phase - else if (t(i,k) < tmin_fice) then - fice(i,k) = 1.0_r8 - ! Otherwise mixed phase, with ice fraction decreasing linearly from tmin to tmax - else - fice(i,k) =(tmax_fice - t(i,k)) / (tmax_fice - tmin_fice) - end if - ! snow fraction partitioning - ! If warmer than tmax then water phase - if (t(i,k) > tmax_fsnow) then - fsnow(i,k) = 0.0_r8 - ! If colder than tmin then ice phase - else if (t(i,k) < tmin_fsnow) then - fsnow(i,k) = 1.0_r8 - ! Otherwise mixed phase, with ice fraction decreasing linearly from tmin to tmax - else - fsnow(i,k) =(tmax_fsnow - t(i,k)) / (tmax_fsnow - tmin_fsnow) - end if - end do - end do -end subroutine cldfrc_fice - -!=================================================================================================== - -! This mimics the functionality of physics_ptend_init() -subroutine zm_tend_init( ncol, pver, tend_s, tend_q, tend_u, tend_v ) - !----------------------------------------------------------------------------- - ! Arguments - integer, intent(in ) :: ncol ! number of local columns - integer, intent(in ) :: pver ! number of local columns - real(r8), dimension(ncol,pver), intent(inout) :: tend_s ! tendency of dry static energy - real(r8), dimension(ncol,pver), intent(inout) :: tend_q ! tendency of water vapor - real(r8), dimension(ncol,pver), intent(inout) :: tend_u ! tendency of zonal wind - real(r8), dimension(ncol,pver), intent(inout) :: tend_v ! tendency of meridional wind - !----------------------------------------------------------------------------- - ! Local variables - integer :: i,k - !----------------------------------------------------------------------------- - ! initialize tendency variables - do i = 1,ncol - do k = 1,pver - tend_s(i,k) = 0 - tend_q(i,k) = 0 - tend_u(i,k) = 0 - tend_v(i,k) = 0 - end do - end do -end subroutine - -!=================================================================================================== - -! This combines functionality of: -! - physics_update() [see physics_update_mod.F90] -! - physics_update_main() [see physics_types.F90] -subroutine zm_physics_update( ncol, dt, state_phis, state_zm, state_zi, & - state_p_mid, state_p_int, state_p_del, & - state_t, state_qv, ptend_s, ptend_q) - use zm_eamxx_bridge_physconst, only: cpair - use zm_eamxx_bridge_params, only: pverp, pver - !----------------------------------------------------------------------------- - ! Arguments - integer, intent(in ) :: ncol ! number of local columns - real(r8), intent(in ) :: dt ! time step - real(r8), dimension(ncol), intent(in ) :: state_phis ! input state surface geopotential height - real(r8), dimension(ncol,pver), intent(inout) :: state_zm ! input state altitude at mid-levels - real(r8), dimension(ncol,pverp),intent(inout) :: state_zi ! input state altitude at interfaces - real(r8), dimension(ncol,pver), intent(in ) :: state_p_mid ! input state mid-point pressure - real(r8), dimension(ncol,pverp),intent(in ) :: state_p_int ! input state interface pressure - real(r8), dimension(ncol,pver), intent(in ) :: state_p_del ! input state pressure thickness - ! real(r8), dimension(ncol,pver), intent(inout) :: state_dse ! input state dry static energy - real(r8), dimension(ncol,pver), intent(inout) :: state_t ! input state temperature - real(r8), dimension(ncol,pver), intent(inout) :: state_qv ! input state water vapor - real(r8), dimension(ncol,pver), intent(in ) :: ptend_s ! tendency of dry static energy - real(r8), dimension(ncol,pver), intent(in ) :: ptend_q ! tendency of water vapor - !----------------------------------------------------------------------------- - ! Local variables - integer :: i,k - !----------------------------------------------------------------------------- - do i = 1,ncol - do k = 1, pver - ! update water vapor - state_qv(i,k) = state_qv(i,k) + ptend_q(i,k) * dt - ! update temperature - assume that dS is really dEn, En=enthalpy=c_p*T, then dT = dEn/c_p, so, state%t += ds/c_p. - state_t(i,k) = state_t(i,k) + ptend_s(i,k)/cpair * dt - end do - end do - - call zm_geopotential_t( ncol, state_p_int, state_p_mid, state_p_del, state_t, state_qv, state_zi, state_zm ) - - ! skip DSE update for EAMxx - ! do i = 1,ncol - ! do k = 1, pver - ! ! update dry static energy using updated temperature - ! state_dse(i,k) = state_t(i,k)*cpair + gravit*state_zm(i,k) + state_phis(i) - ! end do - ! end do - -end subroutine zm_physics_update - -!=================================================================================================== - -! copied and modified from geopotential.F90 -subroutine zm_geopotential_t( ncol, pint, pmid, pdel, t, q, zi, zm ) - use zm_eamxx_bridge_physconst, only: zvir, rair, gravit - use zm_eamxx_bridge_params, only: pverp, pver - !----------------------------------------------------------------------- - ! Purpose: Compute the geopotential height (above the surface) at the - ! midpoints and interfaces using the input temperatures and pressures - !----------------------------------------------------------------------------- - ! Arguments - integer, intent(in ) :: ncol ! Number of columns - real(r8), dimension(ncol,pverp),intent(in ) :: pint ! Interface pressures - real(r8), dimension(ncol,pver), intent(in ) :: pmid ! Midpoint pressures - real(r8), dimension(ncol,pver), intent(in ) :: pdel ! layer thickness - real(r8), dimension(ncol,pver), intent(in ) :: t ! temperature - real(r8), dimension(ncol,pver), intent(in ) :: q ! specific humidity - real(r8), dimension(ncol,pverp),intent(inout) :: zi ! Height above surface at interfaces - real(r8), dimension(ncol,pver), intent(inout) :: zm ! Geopotential height at mid level - !----------------------------------------------------------------------------- - ! Local variables - integer :: i,k ! Lon, level indices - real(r8) :: hkk(ncol) ! diagonal element of hydrostatic matrix - real(r8) :: hkl(ncol) ! off-diagonal element - real(r8) :: tv ! virtual temperature - real(r8) :: tvfac ! Tv/T - !----------------------------------------------------------------------------- - ! The lowest height interface is at the surface, and thus zero by definition - do i = 1,ncol - zi(i,pverp) = 0.0_r8 - end do - ! Compute zi, zm from bottom up - do k = pver, 1, -1 - ! First set hydrostatic elements consistent with dynamics - do i = 1,ncol - hkl(i) = pdel(i,k) / pmid(i,k) - hkk(i) = 0.5_r8 * hkl(i) - end do - ! Now compute tv, zm, zi - do i = 1,ncol - tvfac = 1._r8 + zvir * q(i,k) - tv = t(i,k) * tvfac - zm(i,k) = zi(i,k+1) + (rair/gravit) * tv * hkk(i) - zi(i,k) = zi(i,k+1) + (rair/gravit) * tv * hkl(i) - end do - end do - return -end subroutine zm_geopotential_t - -!=================================================================================================== - -! copied from components/eam/src/control/interpolate_data.F90 -subroutine vertinterp(ncol, ncold, nlev, pmid, pout, arrin, arrout) - !----------------------------------------------------------------------- - ! Purpose: Vertically interpolate input array to output pressure level - ! Copy values at boundaries. - !----------------------------------------------------------------------- - implicit none - !------------------------------Arguments-------------------------------- - integer , intent(in) :: ncol ! column dimension - integer , intent(in) :: ncold ! declared column dimension - integer , intent(in) :: nlev ! vertical dimension - real(r8), intent(in) :: pmid(ncold,nlev) ! input level pressure levels - real(r8), intent(in) :: pout ! output pressure level - real(r8), intent(in) :: arrin(ncold,nlev) ! input array - real(r8), intent(out) :: arrout(ncold) ! output array (interpolated) - !---------------------------Local variables----------------------------- - integer i,k ! indices - integer kupper(ncold) ! Level indices for interpolation - real(r8) dpu ! upper level pressure difference - real(r8) dpl ! lower level pressure difference - logical found(ncold) ! true if input levels found - logical error ! error flag - !----------------------------------------------------------------- - ! - ! Initialize index array and logical flags - ! - do i=1,ncol - found(i) = .false. - kupper(i) = 1 - end do - error = .false. - ! - ! Store level indices for interpolation. - ! If all indices for this level have been found, - ! do the interpolation - ! - do k=1,nlev-1 - do i=1,ncol - if ((.not. found(i)) .and. pmid(i,k)= pmid(i,nlev)) then - arrout(i) = arrin(i,nlev) - else if (found(i)) then - dpu = pout - pmid(i,kupper(i)) - dpl = pmid(i,kupper(i)+1) - pout - arrout(i) = (arrin(i,kupper(i) )*dpl + arrin(i,kupper(i)+1)*dpu)/(dpl + dpu) - else - error = .true. - end if - end do - ! - ! Error check - ! - ! if (error) then - ! call endrun ('VERTINTERP: ERROR FLAG') - ! end if - - return - end subroutine vertinterp - -!=================================================================================================== - -end module zm_eamxx_bridge_methods diff --git a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_params.F90 b/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_params.F90 deleted file mode 100644 index 75891c551e4d..000000000000 --- a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_params.F90 +++ /dev/null @@ -1,24 +0,0 @@ -module zm_eamxx_bridge_params - !----------------------------------------------------------------------------- - ! Purpose: - !----------------------------------------------------------------------------- - use iso_c_binding - !----------------------------------------------------------------------------- -#include "eamxx_config.f" -#ifdef SCREAM_DOUBLE_PRECISION -# define c_real c_double -#else - ZM BRIDGE DOES NOT SUPPORT SINGLE PRECISION -# define c_real c_float -#endif - !----------------------------------------------------------------------------- - ! public variables - integer, public, parameter :: r8 = c_real - integer, public, parameter :: btype = c_bool - logical, public :: masterproc - - integer, public :: pver - integer, public :: pverp - integer, public :: top_lev - -end module zm_eamxx_bridge_params diff --git a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_physconst.F90 b/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_physconst.F90 deleted file mode 100644 index 91d42d48647b..000000000000 --- a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_physconst.F90 +++ /dev/null @@ -1,105 +0,0 @@ -! this module is a version of components/eam/src/physics/cam/physconst.F90 -! modified to facilitate bridging to the fortran ZM deep convection scheme -module zm_eamxx_bridge_physconst - - ! Physical constants. Use CCSM shared values whenever available. - - use zm_eamxx_bridge_params, only: r8, pver, pverp - use shr_const_mod, only: shr_const_g, shr_const_stebol, shr_const_tkfrz, & - shr_const_mwdair, shr_const_rdair, shr_const_mwwv, & - shr_const_latice, shr_const_latvap, shr_const_cpdair, & - shr_const_rhofw, shr_const_cpwv, shr_const_rgas, & - shr_const_karman, shr_const_pstd, shr_const_rhodair,& - shr_const_avogad, shr_const_boltz, shr_const_cpfw, & - shr_const_rwv, shr_const_zvir, shr_const_pi, & - shr_const_rearth, shr_const_sday, shr_const_cday, & - shr_const_spval, shr_const_omega, shr_const_cpvir, & - shr_const_tktrip - - implicit none - - private - save - - ! Constantants for MAM spciesi classes - integer, public, parameter :: spec_class_undefined = 0 - integer, public, parameter :: spec_class_cldphysics = 1 - integer, public, parameter :: spec_class_aerosol = 2 - integer, public, parameter :: spec_class_gas = 3 - integer, public, parameter :: spec_class_other = 4 - - ! Constants based off share code or defined in physconst - - real(r8), public, parameter :: avogad = shr_const_avogad ! Avogadro's number (molecules/kmole) - real(r8), public, parameter :: boltz = shr_const_boltz ! Boltzman's constant (J/K/molecule) - real(r8), public, parameter :: cday = shr_const_cday ! sec in calendar day ~ sec - real(r8), public, parameter :: cpair = shr_const_cpdair ! specific heat of dry air (J/K/kg) - real(r8), public, parameter :: cpliq = shr_const_cpfw ! specific heat of fresh h2o (J/K/kg) - real(r8), public, parameter :: karman = shr_const_karman ! Von Karman constant - real(r8), public, parameter :: latice = shr_const_latice ! Latent heat of fusion (J/kg) - real(r8), public, parameter :: latvap = shr_const_latvap ! Latent heat of vaporization (J/kg) - real(r8), public, parameter :: pi = shr_const_pi ! 3.14... - real(r8), public, parameter :: pstd = shr_const_pstd ! Standard pressure (Pascals) - real(r8), public, parameter :: r_universal = shr_const_rgas ! Universal gas constant (J/K/kmol) - real(r8), public, parameter :: rhoh2o = shr_const_rhofw ! Density of liquid water (STP) - real(r8), public, parameter :: spval = shr_const_spval !special value - real(r8), public, parameter :: stebol = shr_const_stebol ! Stefan-Boltzmann's constant (W/m^2/K^4) - real(r8), public, parameter :: h2otrip = shr_const_tktrip ! Triple point temperature of water (K) - - real(r8), public, parameter :: c0 = 2.99792458e8_r8 ! Speed of light in a vacuum (m/s) - real(r8), public, parameter :: planck = 6.6260755e-34_r8 ! Planck's constant (J.s) - - ! Molecular weights - real(r8), public, parameter :: mwco2 = 44._r8 ! molecular weight co2 - real(r8), public, parameter :: mwn2o = 44._r8 ! molecular weight n2o - real(r8), public, parameter :: mwch4 = 16._r8 ! molecular weight ch4 - real(r8), public, parameter :: mwf11 = 136._r8 ! molecular weight cfc11 - real(r8), public, parameter :: mwf12 = 120._r8 ! molecular weight cfc12 - real(r8), public, parameter :: mwo3 = 48._r8 ! molecular weight O3 - real(r8), public, parameter :: mwso2 = 64._r8 - real(r8), public, parameter :: mwso4 = 96._r8 - real(r8), public, parameter :: mwh2o2 = 34._r8 - real(r8), public, parameter :: mwdms = 62._r8 - real(r8), public, parameter :: mwnh4 = 18._r8 - - - ! modifiable physical constants for aquaplanet or doubly periodic mode - - real(r8), public :: gravit = shr_const_g ! gravitational acceleration (m/s**2) - real(r8), public :: sday = shr_const_sday ! sec in siderial day ~ sec - real(r8), public :: mwh2o = shr_const_mwwv ! molecular weight h2o - real(r8), public :: cpwv = shr_const_cpwv ! specific heat of water vapor (J/K/kg) - real(r8), public :: mwdry = shr_const_mwdair! molecular weight dry air - real(r8), public :: rearth = shr_const_rearth! radius of earth (m) - real(r8), public :: tmelt = shr_const_tkfrz ! Freezing point of water (K) - real(r8), public :: omega = shr_const_omega ! earth rot ~ rad/sec - -!--------------- Variables below here are derived from those above ----------------------- - - real(r8), public :: rga = 1._r8/shr_const_g ! reciprocal of gravit - real(r8), public :: ra = 1._r8/shr_const_rearth ! reciprocal of earth radius - real(r8), public :: rh2o = shr_const_rwv ! Water vapor gas constant ~ J/K/kg - real(r8), public :: rair = shr_const_rdair ! Dry air gas constant ~ J/K/kg - real(r8), public :: epsilo = shr_const_mwwv/shr_const_mwdair ! ratio of h2o to dry air molecular weights - real(r8), public :: zvir = shr_const_zvir ! (rh2o/rair) - 1 - real(r8), public :: cpvir = shr_const_cpvir ! CPWV/CPDAIR - 1.0 - real(r8), public :: rhodair = shr_const_rhodair ! density of dry air at STP ~ kg/m^3 - real(r8), public :: cappa = (shr_const_rgas/shr_const_mwdair)/shr_const_cpdair ! R/Cp - real(r8), public :: ez ! Coriolis expansion coeff -> omega/sqrt(0.375) - real(r8), public :: Cpd_on_Cpv = shr_const_cpdair/shr_const_cpwv - -!--------------- Variables below here are for WACCM-X ----------------------- - real(r8), public, dimension(:,:,:), pointer :: cpairv ! composition dependent specific heat at constant pressure - real(r8), public, dimension(:,:,:), pointer :: rairv ! composition dependent gas "constant" - real(r8), public, dimension(:,:,:), pointer :: cappav ! rairv/cpairv - real(r8), public, dimension(:,:,:), pointer :: mbarv ! composition dependent atmosphere mean mass - real(r8), public, dimension(:,:,:), pointer :: kmvis ! molecular viscosity kg/m/s - real(r8), public, dimension(:,:,:), pointer :: kmcnd ! molecular conductivity J/m/s/K - -!--------------- Variables below here are for turbulent mountain stress ----------------------- - - real(r8), public :: tms_orocnst - real(r8), public :: tms_z0fac - -end module zm_eamxx_bridge_physconst - diff --git a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_wv_saturation.F90 b/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_wv_saturation.F90 deleted file mode 100644 index 642dc89e2b02..000000000000 --- a/components/eamxx/src/physics/zm/fortran_bridge/zm_eamxx_bridge_wv_saturation.F90 +++ /dev/null @@ -1,737 +0,0 @@ -! this module is a version of components/eam/src/physics/cam/wv_saturation.F90 -! modified to facilitate bridging to the fortran ZM deep convection scheme -module zm_eamxx_bridge_wv_saturation - -!--------------------------------------------------------------------! -! Module Overview: ! -! ! -! This module provides an interface to wv_sat_methods, providing ! -! saturation vapor pressure and related calculations to CAM. ! -! ! -! The original wv_saturation codes were introduced by J. J. Hack, ! -! February 1990. The code has been extensively rewritten since then, ! -! including a total refactoring in Summer 2012. ! -! ! -!--------------------------------------------------------------------! -! Methods: ! -! ! -! Pure water/ice saturation vapor pressures are calculated on the ! -! fly, with the specific method determined by a runtime option. ! -! Mixed phase SVP is interpolated from the internal table, estbl, ! -! which is created during initialization. ! -! ! -! The default method for calculating SVP is determined by a namelist ! -! option, and used whenever svp_water/ice or qsat are called. ! -! ! -!--------------------------------------------------------------------! - -use zm_eamxx_bridge_params, only: r8 -use zm_eamxx_bridge_physconst, only: epsilo, & - latvap, & - latice, & - rh2o, & - cpair, & - tmelt, & - h2otrip - -use wv_sat_methods, only: & - svp_to_qsat => wv_sat_svp_to_qsat - -implicit none -private -save - -! Public interfaces -! Namelist, initialization, finalization -public wv_sat_init -public wv_sat_final - -! Saturation vapor pressure calculations -public svp_water -public svp_ice - -! Mixed phase (water + ice) saturation vapor pressure table lookup -public estblf - -public svp_to_qsat - -! Subroutines that return both SVP and humidity -! Optional arguments do temperature derivatives -public qsat ! Mixed phase -public qsat_water ! SVP over water only -public qsat_ice ! SVP over ice only - -! Wet bulb temperature solver -public findsp_vc, findsp - -! Data - -! This value is slightly high, but it seems to be the value for the -! steam point of water originally (and most frequently) used in the -! Goff & Gratch scheme. -real(r8), parameter :: tboil = 373.16_r8 - -! Table of saturation vapor pressure values (estbl) from tmin to -! tmax+1 Kelvin, in one degree increments. ttrice defines the -! transition region, estbl contains a combination of ice & water -! values. -! Make these public parameters in case another module wants to see the -! extent of the table. - real(r8), public, parameter :: tmin = 127.16_r8 - real(r8), public, parameter :: tmax = 375.16_r8 - - real(r8), parameter :: ttrice = 20.00_r8 ! transition range from es over H2O to es over ice - - integer :: plenest ! length of estbl - real(r8), allocatable :: estbl(:) ! table values of saturation vapor pressure - - real(r8) :: omeps ! 1.0_r8 - epsilo - - real(r8) :: c3 ! parameter used by findsp - - ! Set coefficients for polynomial approximation of difference - ! between saturation vapor press over water and saturation pressure - ! over ice for -ttrice < t < 0 (degrees C). NOTE: polynomial is - ! valid in the range -40 < t < 0 (degrees C). - real(r8) :: pcf(5) = (/ & - 5.04469588506e-01_r8, & - -5.47288442819e+00_r8, & - -3.67471858735e-01_r8, & - -8.95963532403e-03_r8, & - -7.78053686625e-05_r8 /) - -contains - -!--------------------------------------------------------------------- -! ADMINISTRATIVE FUNCTIONS -!--------------------------------------------------------------------- - -subroutine wv_sat_init - !------------------------------------------------------------------! - ! Purpose: ! - ! Initialize module (e.g. setting parameters, initializing the ! - ! SVP lookup table). ! - !------------------------------------------------------------------! - use zm_eamxx_bridge_params, only: masterproc - use wv_sat_methods, only: wv_sat_methods_init, & - wv_sat_get_scheme_idx, & - wv_sat_valid_idx - use cam_logfile, only: iulog - use cam_abortutils, only: endrun - use shr_assert_mod, only: shr_assert_in_domain - ! use error_messages, only: handle_errmsg - - integer :: status - - ! For wv_sat_methods error reporting. - character(len=256) :: errstring - - ! For generating internal SVP table. - real(r8) :: t ! Temperature - integer :: i ! Increment counter - - ! Precalculated because so frequently used. - omeps = 1.0_r8 - epsilo - - ! Transition range method is only valid for transition temperatures at: - ! -40 deg C < T < 0 deg C - call shr_assert_in_domain(ttrice, ge=0._r8, le=40._r8, varname="ttrice",& - msg="wv_sat_init: Invalid transition temperature range.") - -! This parameter uses a hardcoded 287.04_r8? - c3 = 287.04_r8*(7.5_r8*log(10._r8))/cpair - -! Init "methods" module containing actual SVP formulae. - - call wv_sat_methods_init(r8, tmelt, h2otrip, tboil, ttrice, & - epsilo, errstring) - - ! call handle_errmsg(errstring, subname="wv_sat_methods_init") - - ! Add two to make the table slightly too big, just in case. - plenest = ceiling(tmax-tmin) + 2 - - ! Allocate SVP table. - allocate(estbl(plenest), stat=status) - if (status /= 0) then - call endrun('wv_sat_init :: ERROR allocating saturation vapor pressure table') - return - end if - - do i = 1, plenest - estbl(i) = svp_trans(tmin + real(i-1,r8)) - end do - - if (masterproc) then - write(iulog,*)' *** SATURATION VAPOR PRESSURE TABLE COMPLETED ***' - end if - -end subroutine wv_sat_init - -subroutine wv_sat_final - !------------------------------------------------------------------! - ! Purpose: ! - ! Deallocate global variables in module. ! - !------------------------------------------------------------------! - use cam_abortutils, only: endrun - - integer :: status - - if (allocated(estbl)) then - - deallocate(estbl, stat=status) - - if (status /= 0) then - call endrun('wv_sat_final :: ERROR deallocating table') - return - end if - - end if - -end subroutine wv_sat_final - -!--------------------------------------------------------------------- -! DEFAULT SVP FUNCTIONS -!--------------------------------------------------------------------- - -! Compute saturation vapor pressure over water -elemental function svp_water(t) result(es) - - use wv_sat_methods, only: & - wv_sat_svp_water - - real(r8), intent(in) :: t ! Temperature (K) - real(r8) :: es ! SVP (Pa) - - es = wv_sat_svp_water(T) - -end function svp_water - -! Compute saturation vapor pressure over ice -elemental function svp_ice(t) result(es) - - use wv_sat_methods, only: & - wv_sat_svp_ice - - real(r8), intent(in) :: t ! Temperature (K) - real(r8) :: es ! SVP (Pa) - - es = wv_sat_svp_ice(T) - -end function svp_ice - -! Compute saturation vapor pressure with an ice-water transition -elemental function svp_trans(t) result(es) - - use wv_sat_methods, only: & - wv_sat_svp_trans - - real(r8), intent(in) :: t ! Temperature (K) - real(r8) :: es ! SVP (Pa) - - es = wv_sat_svp_trans(T) - -end function svp_trans - -!--------------------------------------------------------------------- -! UTILITIES -!--------------------------------------------------------------------- - -! Does linear interpolation from nearest values found -! in the table (estbl). -elemental function estblf(t) result(es) - - real(r8), intent(in) :: t ! Temperature - real(r8) :: es ! SVP (Pa) - - integer :: i ! Index for t in the table - real(r8) :: t_tmp ! intermediate temperature for es look-up - - real(r8) :: weight ! Weight for interpolation - - t_tmp = max(min(t,tmax)-tmin, 0._r8) ! Number of table entries above tmin - i = int(t_tmp) + 1 ! Corresponding index. - weight = t_tmp - aint(t_tmp, r8) ! Fractional part of t_tmp (for interpolation). - es = (1._r8 - weight)*estbl(i) + weight*estbl(i+1) - -end function estblf - -! Get enthalpy based only on temperature -! and specific humidity. -elemental function tq_enthalpy(t, q, hltalt) result(enthalpy) - - real(r8), intent(in) :: t ! Temperature - real(r8), intent(in) :: q ! Specific humidity - real(r8), intent(in) :: hltalt ! Modified hlat for T derivatives - - real(r8) :: enthalpy - - enthalpy = cpair * t + hltalt * q - -end function tq_enthalpy - -!--------------------------------------------------------------------- -! LATENT HEAT OF VAPORIZATION CORRECTIONS -!--------------------------------------------------------------------- - -elemental subroutine no_ip_hltalt(t, hltalt) - !------------------------------------------------------------------! - ! Purpose: ! - ! Calculate latent heat of vaporization of pure liquid water at ! - ! a given temperature. ! - !------------------------------------------------------------------! - - ! Inputs - real(r8), intent(in) :: t ! Temperature - ! Outputs - real(r8), intent(out) :: hltalt ! Appropriately modified hlat - - hltalt = latvap - - ! Account for change of latvap with t above freezing where - ! constant slope is given by -2369 j/(kg c) = cpv - cw - if (t >= tmelt) then - hltalt = hltalt - 2369.0_r8*(t-tmelt) - end if - -end subroutine no_ip_hltalt - -elemental subroutine calc_hltalt(t, hltalt, tterm) - !------------------------------------------------------------------! - ! Purpose: ! - ! Calculate latent heat of vaporization of water at a given ! - ! temperature, taking into account the ice phase if temperature ! - ! is below freezing. ! - ! Optional argument also calculates a term used to calculate ! - ! d(es)/dT within the water-ice transition range. ! - !------------------------------------------------------------------! - - ! Inputs - real(r8), intent(in) :: t ! Temperature - ! Outputs - real(r8), intent(out) :: hltalt ! Appropriately modified hlat - ! Term to account for d(es)/dT in transition region. - real(r8), intent(out), optional :: tterm - - ! Local variables - real(r8) :: tc ! Temperature in degrees C - real(r8) :: weight ! Weight for es transition from water to ice - ! Loop iterator - integer :: i - - if (present(tterm)) tterm = 0.0_r8 - - call no_ip_hltalt(t,hltalt) - if (t < tmelt) then - ! Weighting of hlat accounts for transition from water to ice. - tc = t - tmelt - - if (tc >= -ttrice) then - weight = -tc/ttrice - - ! polynomial expression approximates difference between es - ! over water and es over ice from 0 to -ttrice (C) (max of - ! ttrice is 40): required for accurate estimate of es - ! derivative in transition range from ice to water - if (present(tterm)) then - do i = size(pcf), 1, -1 - tterm = pcf(i) + tc*tterm - end do - tterm = tterm/ttrice - end if - - else - weight = 1.0_r8 - end if - - hltalt = hltalt + weight*latice - - end if - -end subroutine calc_hltalt - -!--------------------------------------------------------------------- -! OPTIONAL OUTPUTS -!--------------------------------------------------------------------- - -! Temperature derivative outputs, for qsat_* -elemental subroutine deriv_outputs(t, p, es, qs, hltalt, tterm, & - gam, dqsdt) - - ! Inputs - real(r8), intent(in) :: t ! Temperature - real(r8), intent(in) :: p ! Pressure - real(r8), intent(in) :: es ! Saturation vapor pressure - real(r8), intent(in) :: qs ! Saturation specific humidity - real(r8), intent(in) :: hltalt ! Modified latent heat - real(r8), intent(in) :: tterm ! Extra term for d(es)/dT in - ! transition region. - - ! Outputs - real(r8), intent(out), optional :: gam ! (hltalt/cpair)*(d(qs)/dt) - real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) - - ! Local variables - real(r8) :: desdt ! d(es)/dt - real(r8) :: dqsdt_loc ! local copy of dqsdt - - if (qs == 1.0_r8) then - dqsdt_loc = 0._r8 - else - desdt = hltalt*es/(rh2o*t*t) + tterm - dqsdt_loc = qs*p*desdt/(es*(p-omeps*es)) - end if - - if (present(dqsdt)) dqsdt = dqsdt_loc - if (present(gam)) gam = dqsdt_loc * (hltalt/cpair) - -end subroutine deriv_outputs - -!--------------------------------------------------------------------- -! QSAT (SPECIFIC HUMIDITY) PROCEDURES -!--------------------------------------------------------------------- - -elemental subroutine qsat(t, p, es, qs, gam, dqsdt, enthalpy) - !------------------------------------------------------------------! - ! Purpose: ! - ! Look up and return saturation vapor pressure from precomputed ! - ! table, then calculate and return saturation specific humidity. ! - ! Optionally return various temperature derivatives or enthalpy ! - ! at saturation. ! - !------------------------------------------------------------------! - - ! Inputs - real(r8), intent(in) :: t ! Temperature - real(r8), intent(in) :: p ! Pressure - ! Outputs - real(r8), intent(out) :: es ! Saturation vapor pressure - real(r8), intent(out) :: qs ! Saturation specific humidity - - real(r8), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) - real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) - real(r8), intent(out), optional :: enthalpy ! cpair*t + hltalt*q - - ! Local variables - real(r8) :: hltalt ! Modified latent heat for T derivatives - real(r8) :: tterm ! Account for d(es)/dT in transition region - - es = estblf(t) - - qs = svp_to_qsat(es, p) - - ! Ensures returned es is consistent with limiters on qs. - es = min(es, p) - - ! Calculate optional arguments. - if (present(gam) .or. present(dqsdt) .or. present(enthalpy)) then - - ! "generalized" analytic expression for t derivative of es - ! accurate to within 1 percent for 173.16 < t < 373.16 - call calc_hltalt(t, hltalt, tterm) - - if (present(enthalpy)) enthalpy = tq_enthalpy(t, qs, hltalt) - - call deriv_outputs(t, p, es, qs, hltalt, tterm, & - gam=gam, dqsdt=dqsdt) - - end if - -end subroutine qsat - -elemental subroutine qsat_water(t, p, es, qs, gam, dqsdt, enthalpy) - !------------------------------------------------------------------! - ! Purpose: ! - ! Calculate SVP over water at a given temperature, and then ! - ! calculate and return saturation specific humidity. ! - ! Optionally return various temperature derivatives or enthalpy ! - ! at saturation. ! - !------------------------------------------------------------------! - - use wv_sat_methods, only: wv_sat_qsat_water - - ! Inputs - real(r8), intent(in) :: t ! Temperature - real(r8), intent(in) :: p ! Pressure - ! Outputs - real(r8), intent(out) :: es ! Saturation vapor pressure - real(r8), intent(out) :: qs ! Saturation specific humidity - - real(r8), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) - real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) - real(r8), intent(out), optional :: enthalpy ! cpair*t + hltalt*q - - ! Local variables - real(r8) :: hltalt ! Modified latent heat for T derivatives - - call wv_sat_qsat_water(t, p, es, qs) - - if (present(gam) .or. present(dqsdt) .or. present(enthalpy)) then - - ! "generalized" analytic expression for t derivative of es - ! accurate to within 1 percent for 173.16 < t < 373.16 - call no_ip_hltalt(t, hltalt) - - if (present(enthalpy)) enthalpy = tq_enthalpy(t, qs, hltalt) - - ! For pure water/ice transition term is 0. - call deriv_outputs(t, p, es, qs, hltalt, 0._r8, & - gam=gam, dqsdt=dqsdt) - - end if - -end subroutine qsat_water - -elemental subroutine qsat_ice(t, p, es, qs, gam, dqsdt, enthalpy) - !------------------------------------------------------------------! - ! Purpose: ! - ! Calculate SVP over ice at a given temperature, and then ! - ! calculate and return saturation specific humidity. ! - ! Optionally return various temperature derivatives or enthalpy ! - ! at saturation. ! - !------------------------------------------------------------------! - - use wv_sat_methods, only: wv_sat_qsat_ice - - ! Inputs - real(r8), intent(in) :: t ! Temperature - real(r8), intent(in) :: p ! Pressure - ! Outputs - real(r8), intent(out) :: es ! Saturation vapor pressure - real(r8), intent(out) :: qs ! Saturation specific humidity - - real(r8), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) - real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) - real(r8), intent(out), optional :: enthalpy ! cpair*t + hltalt*q - - ! Local variables - real(r8) :: hltalt ! Modified latent heat for T derivatives - - call wv_sat_qsat_ice(t, p, es, qs) - - if (present(gam) .or. present(dqsdt) .or. present(enthalpy)) then - - ! For pure ice, just add latent heats. - hltalt = latvap + latice - - if (present(enthalpy)) enthalpy = tq_enthalpy(t, qs, hltalt) - - ! For pure water/ice transition term is 0. - call deriv_outputs(t, p, es, qs, hltalt, 0._r8, & - gam=gam, dqsdt=dqsdt) - - end if - -end subroutine qsat_ice - -!--------------------------------------------------------------------- -! FINDSP (WET BULB TEMPERATURE) PROCEDURES -!--------------------------------------------------------------------- - -subroutine findsp_vc(q, t, p, use_ice, tsp, qsp) - - use cam_logfile, only: iulog - use cam_abortutils, only: endrun - ! Wrapper for findsp which is 1D and handles the output status. - ! Changing findsp to elemental restricted debugging output. - ! If that output is needed again, it's preferable *not* to copy findsp, - ! but to change the existing version. - - ! input arguments - real(r8), intent(in) :: q(:) ! water vapor (kg/kg) - real(r8), intent(in) :: t(:) ! temperature (K) - real(r8), intent(in) :: p(:) ! pressure (Pa) - logical, intent(in) :: use_ice ! flag to include ice phase in calculations - - ! output arguments - real(r8), intent(out) :: tsp(:) ! saturation temp (K) - real(r8), intent(out) :: qsp(:) ! saturation mixing ratio (kg/kg) - - integer :: status(size(q)) ! flag representing state of output - ! 0 => Successful convergence - ! 1 => No calculation done: pressure or specific - ! humidity not within usable range - ! 2 => Run failed to converge - ! 4 => Temperature fell below minimum - ! 8 => Enthalpy not conserved - - integer :: n, i - - n = size(q) - - call findsp(q, t, p, use_ice, tsp, qsp, status) - - ! Currently, only 2 and 8 seem to be treated as fatal errors. - do i = 1,n - if (status(i) == 2) then - write(iulog,*) ' findsp not converging at i = ', i - write(iulog,*) ' t, q, p ', t(i), q(i), p(i) - write(iulog,*) ' tsp, qsp ', tsp(i), qsp(i) - call endrun ('wv_saturation::FINDSP -- not converging') - else if (status(i) == 8) then - write(iulog,*) ' the enthalpy is not conserved at i = ', i - write(iulog,*) ' t, q, p ', t(i), q(i), p(i) - write(iulog,*) ' tsp, qsp ', tsp(i), qsp(i) - call endrun ('wv_saturation::FINDSP -- enthalpy is not conserved') - endif - end do - -end subroutine findsp_vc - -elemental subroutine findsp (q, t, p, use_ice, tsp, qsp, status) -!----------------------------------------------------------------------- -! -! Purpose: -! find the wet bulb temperature for a given t and q -! in a longitude height section -! wet bulb temp is the temperature and spec humidity that is -! just saturated and has the same enthalpy -! if q > qs(t) then tsp > t and qsp = qs(tsp) < q -! if q < qs(t) then tsp < t and qsp = qs(tsp) > q -! -! Method: -! a Newton method is used -! first guess uses an algorithm provided by John Petch from the UKMO -! we exclude points where the physical situation is unrealistic -! e.g. where the temperature is outside the range of validity for the -! saturation vapor pressure, or where the water vapor pressure -! exceeds the ambient pressure, or the saturation specific humidity is -! unrealistic -! -! Author: P. Rasch -! -!----------------------------------------------------------------------- -! -! input arguments -! - - real(r8), intent(in) :: q ! water vapor (kg/kg) - real(r8), intent(in) :: t ! temperature (K) - real(r8), intent(in) :: p ! pressure (Pa) - logical, intent(in) :: use_ice ! flag to include ice phase in calculations -! -! output arguments -! - real(r8), intent(out) :: tsp ! saturation temp (K) - real(r8), intent(out) :: qsp ! saturation mixing ratio (kg/kg) - integer, intent(out) :: status ! flag representing state of output - ! 0 => Successful convergence - ! 1 => No calculation done: pressure or specific - ! humidity not within usable range - ! 2 => Run failed to converge - ! 4 => Temperature fell below minimum - ! 8 => Enthalpy not conserved -! -! local variables -! - integer, parameter :: iter = 8 ! max number of times to iterate the calculation - integer :: l ! iterator - - real(r8) es ! sat. vapor pressure - real(r8) gam ! change in sat spec. hum. wrt temperature (times hltalt/cpair) - real(r8) dgdt ! work variable - real(r8) g ! work variable - real(r8) hltalt ! lat. heat. of vap. - real(r8) qs ! spec. hum. of water vapor - -! work variables - real(r8) t1, q1, dt, dq - real(r8) qvd - real(r8) r1b, c1, c2 - real(r8), parameter :: dttol = 1.e-4_r8 ! the relative temp error tolerance required to quit the iteration - real(r8), parameter :: dqtol = 1.e-4_r8 ! the relative moisture error tolerance required to quit the iteration - real(r8) enin, enout - - ! Saturation specific humidity at this temperature - if (use_ice) then - call qsat(t, p, es, qs) - else - call qsat_water(t, p, es, qs) - end if - - ! make sure a meaningful calculation is possible - if (p <= 5._r8*es .or. qs <= 0._r8 .or. qs >= 0.5_r8 & - .or. t < tmin .or. t > tmax) then - status = 1 - ! Keep initial parameters when conditions aren't suitable - tsp = t - qsp = q - enin = 1._r8 - enout = 1._r8 - - return - end if - - ! Prepare to iterate - status = 2 - - ! Get initial enthalpy - if (use_ice) then - call calc_hltalt(t,hltalt) - else - call no_ip_hltalt(t,hltalt) - end if - enin = tq_enthalpy(t, q, hltalt) - - ! make a guess at the wet bulb temp using a UKMO algorithm (from J. Petch) - c1 = hltalt*c3 - c2 = (t + 36._r8)**2 - r1b = c2/(c2 + c1*qs) - qvd = r1b * (q - qs) - tsp = t + ((hltalt/cpair)*qvd) - - ! Generate qsp, gam, and enout from tsp. - if (use_ice) then - call qsat(tsp, p, es, qsp, gam=gam, enthalpy=enout) - else - call qsat_water(tsp, p, es, qsp, gam=gam, enthalpy=enout) - end if - - ! iterate on first guess - do l = 1, iter - - g = enin - enout - dgdt = -cpair * (1 + gam) - - ! New tsp - t1 = tsp - g/dgdt - dt = abs(t1 - tsp)/t1 - tsp = t1 - - ! bail out if past end of temperature range - if ( tsp < tmin ) then - tsp = tmin - ! Get latent heat and set qsp to a value - ! that preserves enthalpy. - if (use_ice) then - call calc_hltalt(tsp,hltalt) - else - call no_ip_hltalt(tsp,hltalt) - end if - qsp = (enin - cpair*tsp)/hltalt - enout = tq_enthalpy(tsp, qsp, hltalt) - status = 4 - exit - end if - - ! Re-generate qsp, gam, and enout from new tsp. - if (use_ice) then - call qsat(tsp, p, es, q1, gam=gam, enthalpy=enout) - else - call qsat_water(tsp, p, es, q1, gam=gam, enthalpy=enout) - end if - dq = abs(q1 - qsp)/max(q1,1.e-12_r8) - qsp = q1 - - ! if converged at this point, exclude it from more iterations - if (dt < dttol .and. dq < dqtol) then - status = 0 - exit - endif - end do - - ! Test for enthalpy conservation - if (abs((enin-enout)/(enin+enout)) > 1.e-4_r8) status = 8 - -end subroutine findsp - -end module zm_eamxx_bridge_wv_saturation From 083bff311e7d4babecd7bb2655c7153e4f888271 Mon Sep 17 00:00:00 2001 From: James Foucar Date: Fri, 28 Aug 2026 14:47:30 -0600 Subject: [PATCH 3/8] Get rid of inactive tracking now the f90 is gone --- .../physics/zm/tests/zm_conv_main_tests.cpp | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp b/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp index 697c5c93346f..1a865be81a60 100644 --- a/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp +++ b/components/eamxx/src/physics/zm/tests/zm_conv_main_tests.cpp @@ -80,20 +80,17 @@ struct UnitWrap::UnitTest::TestZmConvMain : public UnitWrap::UnitTest::Bas REQUIRE(d_baseline.total(d_baseline.prec) == d_test.total(d_test.jctop)); REQUIRE(d_baseline.total(d_baseline.prec) == d_test.total(d_test.jcbot)); REQUIRE(d_baseline.total(d_baseline.prec) == d_test.total(d_test.jt)); - Int inactive_cnt = 0; for (Int k = 0; k < d_baseline.total(d_baseline.prec); ++k) { const bool active_col = actives[i][k]; - if (!active_col) ++inactive_cnt; - const Int fgindex = k-inactive_cnt; REQUIRE(d_baseline.prec[k] == Approx(d_test.prec[k]).margin(margin)); REQUIRE(d_baseline.cape[k] == Approx(d_test.cape[k]).margin(margin)); REQUIRE(d_baseline.dcape[k] == Approx(d_test.dcape[k]).margin(margin)); REQUIRE(d_baseline.rliq[k] == Approx(d_test.rliq[k]).margin(margin)); // Gathered 1-d variables if (active_col) { - REQUIRE(d_baseline.dsubcld[fgindex] == Approx(d_test.dsubcld[k]).margin(margin)); - REQUIRE(d_baseline.msemax_klev[fgindex] == d_test.msemax_klev[k]); - REQUIRE(d_baseline.jt[fgindex] == d_test.jt[k]); + REQUIRE(d_baseline.dsubcld[k] == Approx(d_test.dsubcld[k]).margin(margin)); + REQUIRE(d_baseline.msemax_klev[k] == d_test.msemax_klev[k]); + REQUIRE(d_baseline.jt[k] == d_test.jt[k]); REQUIRE(d_baseline.jctop[k] == d_test.jctop[k]); REQUIRE(d_baseline.jcbot[k] == d_test.jcbot[k]); } @@ -112,22 +109,19 @@ struct UnitWrap::UnitTest::TestZmConvMain : public UnitWrap::UnitTest::Bas REQUIRE(d_baseline.total(d_baseline.heat) == d_test.total(d_test.dlf)); REQUIRE(d_baseline.total(d_baseline.mcon) == d_test.total(d_test.mcon)); REQUIRE(d_baseline.total(d_baseline.mcon) == d_test.total(d_test.pflx)); - inactive_cnt = 0; for (Int n = 0; n < ncol; ++n) { const bool active_col = actives[i][n]; - if (!active_col) ++inactive_cnt; if (active_col) { for (Int k = 0; k < pverp; ++k) { const Int offset = n*pver + k; const Int offsetp = n*pverp + k; - const Int fgoffset = (n-inactive_cnt)*pver + k; if (k < pver) { - REQUIRE(d_baseline.mflx_up[fgoffset] == Approx(d_test.mflx_up[offset]).margin(margin)); - REQUIRE(d_baseline.entr_up[fgoffset] == Approx(d_test.entr_up[offset]).margin(margin)); - REQUIRE(d_baseline.detr_up[fgoffset] == Approx(d_test.detr_up[offset]).margin(margin)); - REQUIRE(d_baseline.mflx_dn[fgoffset] == Approx(d_test.mflx_dn[offset]).margin(margin)); - REQUIRE(d_baseline.entr_dn[fgoffset] == Approx(d_test.entr_dn[offset]).margin(margin)); - REQUIRE(d_baseline.p_del[fgoffset] == d_test.p_del[offset]); + REQUIRE(d_baseline.mflx_up[offset] == Approx(d_test.mflx_up[offset]).margin(margin)); + REQUIRE(d_baseline.entr_up[offset] == Approx(d_test.entr_up[offset]).margin(margin)); + REQUIRE(d_baseline.detr_up[offset] == Approx(d_test.detr_up[offset]).margin(margin)); + REQUIRE(d_baseline.mflx_dn[offset] == Approx(d_test.mflx_dn[offset]).margin(margin)); + REQUIRE(d_baseline.entr_dn[offset] == Approx(d_test.entr_dn[offset]).margin(margin)); + REQUIRE(d_baseline.p_del[offset] == d_test.p_del[offset]); REQUIRE(d_baseline.heat[offset] == Approx(d_test.heat[offset]).margin(margin)); REQUIRE(d_baseline.qtnd[offset] == Approx(d_test.qtnd[offset]).margin(margin)); REQUIRE(d_baseline.zdu[offset] == Approx(d_test.zdu[offset]).margin(margin)); @@ -135,7 +129,7 @@ struct UnitWrap::UnitTest::TestZmConvMain : public UnitWrap::UnitTest::Bas REQUIRE(d_baseline.rprd[offset] == Approx(d_test.rprd[offset]).margin(margin)); REQUIRE(d_baseline.dlf[offset] == Approx(d_test.dlf[offset]).margin(margin)); } - // pverp variables (both gathered) + // pverp variables REQUIRE(d_baseline.mcon[offsetp] == Approx(d_test.mcon[offsetp]).margin(margin)); REQUIRE(d_baseline.pflx[offsetp] == Approx(d_test.pflx[offsetp]).margin(margin)); } From bec6064056bec61dc2aa00f7b81c54edbfb910c5 Mon Sep 17 00:00:00 2001 From: James Foucar Date: Fri, 28 Aug 2026 14:48:56 -0600 Subject: [PATCH 4/8] Remove last traces of bridging --- .../physics/zm/eamxx_zm_process_interface.cpp | 454 ++++++++---------- .../src/physics/zm/tests/infra/CMakeLists.txt | 1 - .../physics/zm/tests/infra/zm_c2f_bridge.f90 | 360 -------------- 3 files changed, 190 insertions(+), 625 deletions(-) delete mode 100644 components/eamxx/src/physics/zm/tests/infra/zm_c2f_bridge.f90 diff --git a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp index 3b76490285f5..cbc23a8de00b 100644 --- a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp +++ b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp @@ -4,8 +4,6 @@ #include "eamxx_zm_process_interface.hpp" #include "share/physics/physics_constants.hpp" -#include "zm_eamxx_bridge.hpp" - #include #include #include @@ -133,15 +131,7 @@ void ZMDeepConvection::initialize_impl (const RunType) if (this->get_comm().am_i_root()) ZMF::s_zm_opts.print(); //---------------------------------------------------------------------------- if (ZMF::s_zm_opts.use_fortran_bridge) { - // allocate host mirror variables for fortran bridging - zm_input.init_host_mirrors (m_ncol, m_nlev); - zm_output.init_host_mirrors(m_ncol, m_nlev); - // initialize variables on the fortran side - zm::zm_eamxx_bridge_init( m_nlev, ZMF::s_zm_opts.limcnv+1, - ZMF::s_zm_opts.trig_dcape, - ZMF::s_zm_opts.trig_ull, - ZMF::s_zm_opts.clos_dyn_adj, - ZMF::s_zm_opts.mcsp_enabled); + EKAT_REQUIRE_MSG(false, "ZM fortran bridge no longer supported"); } // if use_fortran_bridge //---------------------------------------------------------------------------- } // ZMDeepConvection::initialize_impl @@ -316,216 +306,208 @@ void ZMDeepConvection::run_impl (const double dt) //---------------------------------------------------------------------------- // run the ZM scheme - if (zm_opts.use_fortran_bridge) { - - zm_eamxx_bridge_run(m_ncol, nlev_mid, dt, is_first_step, zm_input, zm_output, zm_opts); - - } else { - // Allocate the Workspace for the MCSP / evap / momentum kernels below. - // Slot length is nlev_int*nwind to fit zm_transport_momentum's (nwind, nlev_int) buffers. - WSM wsm( nlev_int*nwind, 16, team_policy); - - //-------------------------------------------------------------------------- - // run the main ZM scheme - ZMF::zm_conv_main(zm_opts, m_ncol, nlev_mid, nlev_int, is_first_step, dt, - zm_input.T_mid, zm_input.qv, zm_input.omega, - zm_input.p_mid, zm_input.p_int, zm_input.p_del, - zm_input.phis, zm_input.z_mid, zm_input.z_int, - zm_input.pblh, zm_input.tpert, zm_input.landfrac, - zm_input.t_prev, zm_input.q_prev, - zm_output.msemax_klev, zm_output.jctop, zm_output.jcbot, zm_output.jt, - zm_output.activity, - zm_output.prec, zm_output.tend_out_s, zm_output.tend_out_qv, - zm_output.cape, zm_output.dcape, - zm_output.mass_flux, zm_output.prec_flux, - zm_output.zdu, - zm_output.mflx_up, zm_output.entr_up, zm_output.detr_up, - zm_output.mflx_dn, zm_output.entr_dn, - zm_output.p_del_mb, zm_output.dsubcld, - zm_output.ql, zm_output.rliq, zm_output.rain_prod, zm_output.dlf, - zm_output.ktm, zm_output.kbm ); - - //-------------------------------------------------------------------------- - // MCSP modifies tendencies from zm_conv_main() prior to updating the state - - if (zm_opts.mcsp_enabled) { - - // initialize intermediate output tendencies for MCSP - zm_output.init_tmp(m_ncol, nlev_mid); - - // perform the MCSP calculations - Kokkos::parallel_for(team_policy, KOKKOS_LAMBDA(const KT::MemberType& team) { - const Int i = team.league_rank(); - const auto phis_i = loc_zm_input_phis(i); - const auto jctop_i = loc_zm_output_jctop(i); - const auto z_mid_i = ekat::subview(loc_zm_input_z_mid, i); - const auto p_mid_i = ekat::subview(loc_zm_input_p_mid, i); - const auto p_int_i = ekat::subview(loc_zm_input_p_int, i); - const auto p_del_i = ekat::subview(loc_zm_input_p_del, i); - const auto T_mid_i = ekat::subview(loc_zm_input_T_mid, i); - const auto qv_i = ekat::subview(loc_zm_input_qv, i); - const auto uwind_i = ekat::subview(loc_zm_input_uwind, i); - const auto vwind_i = ekat::subview(loc_zm_input_vwind, i); - const auto tmp_s_mid_i = ekat::subview(loc_zm_input_tmp_s_mid, i); - const auto tend_out_s_i = ekat::subview(loc_zm_output_tend_out_s, i); - const auto tend_out_qv_i = ekat::subview(loc_zm_output_tend_out_qv, i); - const auto tend_out_u_i = ekat::subview(loc_zm_output_tend_out_u, i); - const auto tend_out_v_i = ekat::subview(loc_zm_output_tend_out_v, i); - const auto tend_tmp_s_i = ekat::subview(loc_zm_output_tend_tmp_s, i); - const auto tend_tmp_qv_i = ekat::subview(loc_zm_output_tend_tmp_qv, i); - const auto tend_tmp_winds_i = ekat::subview(loc_zm_output_tend_tmp_winds, i); // (nwind, nlev) - const auto tend_tmp_u_i = ekat::subview(tend_tmp_winds_i, 0); // (nlev) - const auto tend_tmp_v_i = ekat::subview(tend_tmp_winds_i, 1); // (nlev) - const auto mcsp_ds_out_i = ekat::subview(loc_zm_output_mcsp_ds_out, i); - const auto mcsp_dq_out_i = ekat::subview(loc_zm_output_mcsp_dq_out, i); - const auto mcsp_du_out_i = ekat::subview(loc_zm_output_mcsp_du_out, i); - const auto mcsp_dv_out_i = ekat::subview(loc_zm_output_mcsp_dv_out, i); - auto& mcsp_freq_i = loc_zm_output_mcsp_freq(i); - auto& mcsp_shear_i = loc_zm_output_mcsp_shear(i); - auto& zm_depth_i = loc_zm_output_zm_depth(i); - - // calculate DSE for MCSP - Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_mid), [&] (const int k) { - tmp_s_mid_i(k) = T_mid_i(k)*PC::CP.value + z_mid_i(k)*PC::gravit.value + phis_i; - }); - team.team_barrier(); - - // call the MCSP scheme - ZMF::zm_conv_mcsp_tend( team, wsm.get_workspace(team), zm_opts, nlev_mid, nlev_int, dt, - jctop_i, p_mid_i, p_int_i, p_del_i, tmp_s_mid_i, qv_i, uwind_i, vwind_i, - tend_out_s_i, tend_out_qv_i, - tend_tmp_s_i, tend_tmp_qv_i, tend_tmp_u_i, tend_tmp_v_i, - mcsp_ds_out_i, mcsp_dq_out_i, mcsp_du_out_i, mcsp_dv_out_i, - mcsp_freq_i, mcsp_shear_i, zm_depth_i ); - - // add MCSP tendencies to output tendencies - Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_mid), [&] (const int k) { - tend_out_s_i(k) += tend_tmp_s_i(k); - tend_out_qv_i(k) += tend_tmp_qv_i(k); - tend_out_u_i(k) += tend_tmp_u_i(k); - tend_out_v_i(k) += tend_tmp_v_i(k); - }); - }); - - } - - //-------------------------------------------------------------------------- - // apply tendencies from zm_conv_main() (& MCSP) to temporary state variables for zm_conv_evap() - - Kokkos::parallel_for(KT::RangePolicy(0, m_ncol*nlev_mid), KOKKOS_LAMBDA (const int idx) { - const int i = idx/nlev_mid; - const int k = idx%nlev_mid; - // calculate temporary T/qv for zm_conv_evap() - loc_zm_input_tmp_T_mid(i,k) = loc_zm_input_T_mid(i,k) + loc_zm_output_tend_out_s(i,k)/PC::CP.value * dt; - loc_zm_input_tmp_qv(i,k) = loc_zm_input_qv(i,k) + loc_zm_output_tend_out_qv(i,k) * dt; - // calculate temporary winds for zm_transport_momentum() - loc_zm_input_tmp_winds(i,0,k) = loc_zm_input_uwind(i,k) + loc_zm_output_tend_out_u(i,k) * dt; - loc_zm_input_tmp_winds(i,1,k) = loc_zm_input_vwind(i,k) + loc_zm_output_tend_out_v(i,k) * dt; - }); - - //-------------------------------------------------------------------------- - // Compute the precipitation, rain evaporation, and snow formation/melting - // Note - this routine expects an updated state following zm_conv_main() (+MCSP) - - // initialize intermediate output tendencies for zm_conv_evap() + // Allocate the Workspace for the MCSP / evap / momentum kernels below. + // Slot length is nlev_int*nwind to fit zm_transport_momentum's (nwind, nlev_int) buffers. + WSM wsm( nlev_int*nwind, 16, team_policy); + + //-------------------------------------------------------------------------- + // run the main ZM scheme + ZMF::zm_conv_main(zm_opts, m_ncol, nlev_mid, nlev_int, is_first_step, dt, + zm_input.T_mid, zm_input.qv, zm_input.omega, + zm_input.p_mid, zm_input.p_int, zm_input.p_del, + zm_input.phis, zm_input.z_mid, zm_input.z_int, + zm_input.pblh, zm_input.tpert, zm_input.landfrac, + zm_input.t_prev, zm_input.q_prev, + zm_output.msemax_klev, zm_output.jctop, zm_output.jcbot, zm_output.jt, + zm_output.activity, + zm_output.prec, zm_output.tend_out_s, zm_output.tend_out_qv, + zm_output.cape, zm_output.dcape, + zm_output.mass_flux, zm_output.prec_flux, + zm_output.zdu, + zm_output.mflx_up, zm_output.entr_up, zm_output.detr_up, + zm_output.mflx_dn, zm_output.entr_dn, + zm_output.p_del_mb, zm_output.dsubcld, + zm_output.ql, zm_output.rliq, zm_output.rain_prod, zm_output.dlf, + zm_output.ktm, zm_output.kbm ); + + //-------------------------------------------------------------------------- + // MCSP modifies tendencies from zm_conv_main() prior to updating the state + + if (zm_opts.mcsp_enabled) { + + // initialize intermediate output tendencies for MCSP zm_output.init_tmp(m_ncol, nlev_mid); - // perform the convective evaporation calculations + // perform the MCSP calculations Kokkos::parallel_for(team_policy, KOKKOS_LAMBDA(const KT::MemberType& team) { const Int i = team.league_rank(); - // skip inactive columns: zm_conv_main leaves p_del_mb (=dp) zero for them, - // and zm_transport_momentum divides by dp, which would produce NaNs - if (!loc_zm_output_activity(i)) return; - const auto p_mid_i = ekat::subview(loc_zm_input_p_mid, i); - const auto p_del_i = ekat::subview(loc_zm_input_p_del, i); - const auto T_mid_i = ekat::subview(loc_zm_input_T_mid, i); - const auto qv_i = ekat::subview(loc_zm_input_qv, i); - const auto tmp_T_mid_i = ekat::subview(loc_zm_input_tmp_T_mid, i); - const auto tmp_qv_i = ekat::subview(loc_zm_input_tmp_qv, i); - const auto rain_prod_i = ekat::subview(loc_zm_output_rain_prod, i); - const auto cldfrac_i = ekat::subview(loc_zm_input_cldfrac, i); - const auto tend_out_s_i = ekat::subview(loc_zm_output_tend_out_s, i); - const auto tend_out_qv_i = ekat::subview(loc_zm_output_tend_out_qv, i); - const auto tend_tmp_s_i = ekat::subview(loc_zm_output_tend_tmp_s, i); - const auto tend_tmp_qv_i = ekat::subview(loc_zm_output_tend_tmp_qv, i); - const auto tend_s_snwprd_i = ekat::subview(loc_zm_output_tend_s_snwprd, i); - const auto tend_s_snwevmlt_i = ekat::subview(loc_zm_output_tend_s_snwevmlt, i); - const auto ntprprd_i = ekat::subview(loc_zm_output_ntprprd, i); - const auto ntsnprd_i = ekat::subview(loc_zm_output_ntsnprd, i); - const auto flxprec_i = ekat::subview(loc_zm_output_flxprec, i); - const auto flxsnow_i = ekat::subview(loc_zm_output_flxsnow, i); - const auto evap_ds_out_i = ekat::subview(loc_zm_output_evap_ds_out, i); - const auto evap_dq_out_i = ekat::subview(loc_zm_output_evap_dq_out, i); - - // call the ZM evap scheme - ZMF::zm_conv_evap( team, zm_opts, nlev_mid, nlev_int, dt, - p_mid_i, p_del_i, tmp_T_mid_i, tmp_qv_i, rain_prod_i, cldfrac_i, - tend_tmp_s_i, tend_tmp_qv_i, tend_s_snwprd_i, tend_s_snwevmlt_i, - loc_zm_output_prec(i), loc_zm_output_snow(i), - ntprprd_i, ntsnprd_i, flxprec_i, flxsnow_i ); - - // add zm_conv_evap() tendencies to output tendencies and update temporary state variables + const auto phis_i = loc_zm_input_phis(i); + const auto jctop_i = loc_zm_output_jctop(i); + const auto z_mid_i = ekat::subview(loc_zm_input_z_mid, i); + const auto p_mid_i = ekat::subview(loc_zm_input_p_mid, i); + const auto p_int_i = ekat::subview(loc_zm_input_p_int, i); + const auto p_del_i = ekat::subview(loc_zm_input_p_del, i); + const auto T_mid_i = ekat::subview(loc_zm_input_T_mid, i); + const auto qv_i = ekat::subview(loc_zm_input_qv, i); + const auto uwind_i = ekat::subview(loc_zm_input_uwind, i); + const auto vwind_i = ekat::subview(loc_zm_input_vwind, i); + const auto tmp_s_mid_i = ekat::subview(loc_zm_input_tmp_s_mid, i); + const auto tend_out_s_i = ekat::subview(loc_zm_output_tend_out_s, i); + const auto tend_out_qv_i = ekat::subview(loc_zm_output_tend_out_qv, i); + const auto tend_out_u_i = ekat::subview(loc_zm_output_tend_out_u, i); + const auto tend_out_v_i = ekat::subview(loc_zm_output_tend_out_v, i); + const auto tend_tmp_s_i = ekat::subview(loc_zm_output_tend_tmp_s, i); + const auto tend_tmp_qv_i = ekat::subview(loc_zm_output_tend_tmp_qv, i); + const auto tend_tmp_winds_i = ekat::subview(loc_zm_output_tend_tmp_winds, i); // (nwind, nlev) + const auto tend_tmp_u_i = ekat::subview(tend_tmp_winds_i, 0); // (nlev) + const auto tend_tmp_v_i = ekat::subview(tend_tmp_winds_i, 1); // (nlev) + const auto mcsp_ds_out_i = ekat::subview(loc_zm_output_mcsp_ds_out, i); + const auto mcsp_dq_out_i = ekat::subview(loc_zm_output_mcsp_dq_out, i); + const auto mcsp_du_out_i = ekat::subview(loc_zm_output_mcsp_du_out, i); + const auto mcsp_dv_out_i = ekat::subview(loc_zm_output_mcsp_dv_out, i); + auto& mcsp_freq_i = loc_zm_output_mcsp_freq(i); + auto& mcsp_shear_i = loc_zm_output_mcsp_shear(i); + auto& zm_depth_i = loc_zm_output_zm_depth(i); + + // calculate DSE for MCSP + Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_mid), [&] (const int k) { + tmp_s_mid_i(k) = T_mid_i(k)*PC::CP.value + z_mid_i(k)*PC::gravit.value + phis_i; + }); + team.team_barrier(); + + // call the MCSP scheme + ZMF::zm_conv_mcsp_tend( team, wsm.get_workspace(team), zm_opts, nlev_mid, nlev_int, dt, + jctop_i, p_mid_i, p_int_i, p_del_i, tmp_s_mid_i, qv_i, uwind_i, vwind_i, + tend_out_s_i, tend_out_qv_i, + tend_tmp_s_i, tend_tmp_qv_i, tend_tmp_u_i, tend_tmp_v_i, + mcsp_ds_out_i, mcsp_dq_out_i, mcsp_du_out_i, mcsp_dv_out_i, + mcsp_freq_i, mcsp_shear_i, zm_depth_i ); + + // add MCSP tendencies to output tendencies Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_mid), [&] (const int k) { tend_out_s_i(k) += tend_tmp_s_i(k); tend_out_qv_i(k) += tend_tmp_qv_i(k); - evap_ds_out_i(k) = tend_tmp_s_i(k); - evap_dq_out_i(k) = tend_tmp_qv_i(k); + tend_out_u_i(k) += tend_tmp_u_i(k); + tend_out_v_i(k) += tend_tmp_v_i(k); }); - }); - //-------------------------------------------------------------------------- - // convective momentum transport - - // initialize intermediate output tendencies for zm_transport_momentum() - zm_output.init_tmp(m_ncol, nlev_mid); + } - // domain-wide convection level bounds from zm_conv_main (host scalars captured by value) - const Int ktm = zm_output.ktm; - const Int kbm = zm_output.kbm; + //-------------------------------------------------------------------------- + // apply tendencies from zm_conv_main() (& MCSP) to temporary state variables for zm_conv_evap() - Kokkos::parallel_for(team_policy, KOKKOS_LAMBDA(const KT::MemberType& team) { - const Int i = team.league_rank(); - // skip inactive columns: zm_conv_main leaves p_del_mb (=dp) zero for them, - // and zm_transport_momentum divides by dp, which would produce NaNs - if (!loc_zm_output_activity(i)) return; - // MCSP-updated winds in (nwind, nlev) == (m,k) layout for wind_mid - const auto wind_mid_i = ekat::subview(loc_zm_input_tmp_winds, i); - const auto mflx_up_i = ekat::subview(loc_zm_output_mflx_up, i); - const auto mflx_dn_i = ekat::subview(loc_zm_output_mflx_dn, i); - const auto detr_up_i = ekat::subview(loc_zm_output_detr_up, i); - const auto entr_up_i = ekat::subview(loc_zm_output_entr_up, i); - const auto entr_dn_i = ekat::subview(loc_zm_output_entr_dn, i); - const auto p_del_mb_i = ekat::subview(loc_zm_output_p_del_mb, i); + Kokkos::parallel_for(KT::RangePolicy(0, m_ncol*nlev_mid), KOKKOS_LAMBDA (const int idx) { + const int i = idx/nlev_mid; + const int k = idx%nlev_mid; + // calculate temporary T/qv for zm_conv_evap() + loc_zm_input_tmp_T_mid(i,k) = loc_zm_input_T_mid(i,k) + loc_zm_output_tend_out_s(i,k)/PC::CP.value * dt; + loc_zm_input_tmp_qv(i,k) = loc_zm_input_qv(i,k) + loc_zm_output_tend_out_qv(i,k) * dt; + // calculate temporary winds for zm_transport_momentum() + loc_zm_input_tmp_winds(i,0,k) = loc_zm_input_uwind(i,k) + loc_zm_output_tend_out_u(i,k) * dt; + loc_zm_input_tmp_winds(i,1,k) = loc_zm_input_vwind(i,k) + loc_zm_output_tend_out_v(i,k) * dt; + }); - const auto tend_out_s_i = ekat::subview(loc_zm_output_tend_out_s, i); - const auto tend_out_u_i = ekat::subview(loc_zm_output_tend_out_u, i); - const auto tend_out_v_i = ekat::subview(loc_zm_output_tend_out_v, i); + //-------------------------------------------------------------------------- + // Compute the precipitation, rain evaporation, and snow formation/melting + // Note - this routine expects an updated state following zm_conv_main() (+MCSP) + + // initialize intermediate output tendencies for zm_conv_evap() + zm_output.init_tmp(m_ncol, nlev_mid); + + // perform the convective evaporation calculations + Kokkos::parallel_for(team_policy, KOKKOS_LAMBDA(const KT::MemberType& team) { + const Int i = team.league_rank(); + // skip inactive columns: zm_conv_main leaves p_del_mb (=dp) zero for them, + // and zm_transport_momentum divides by dp, which would produce NaNs + if (!loc_zm_output_activity(i)) return; + const auto p_mid_i = ekat::subview(loc_zm_input_p_mid, i); + const auto p_del_i = ekat::subview(loc_zm_input_p_del, i); + const auto T_mid_i = ekat::subview(loc_zm_input_T_mid, i); + const auto qv_i = ekat::subview(loc_zm_input_qv, i); + const auto tmp_T_mid_i = ekat::subview(loc_zm_input_tmp_T_mid, i); + const auto tmp_qv_i = ekat::subview(loc_zm_input_tmp_qv, i); + const auto rain_prod_i = ekat::subview(loc_zm_output_rain_prod, i); + const auto cldfrac_i = ekat::subview(loc_zm_input_cldfrac, i); + const auto tend_out_s_i = ekat::subview(loc_zm_output_tend_out_s, i); + const auto tend_out_qv_i = ekat::subview(loc_zm_output_tend_out_qv, i); + const auto tend_tmp_s_i = ekat::subview(loc_zm_output_tend_tmp_s, i); + const auto tend_tmp_qv_i = ekat::subview(loc_zm_output_tend_tmp_qv, i); + const auto tend_s_snwprd_i = ekat::subview(loc_zm_output_tend_s_snwprd, i); + const auto tend_s_snwevmlt_i = ekat::subview(loc_zm_output_tend_s_snwevmlt, i); + const auto ntprprd_i = ekat::subview(loc_zm_output_ntprprd, i); + const auto ntsnprd_i = ekat::subview(loc_zm_output_ntsnprd, i); + const auto flxprec_i = ekat::subview(loc_zm_output_flxprec, i); + const auto flxsnow_i = ekat::subview(loc_zm_output_flxsnow, i); + const auto evap_ds_out_i = ekat::subview(loc_zm_output_evap_ds_out, i); + const auto evap_dq_out_i = ekat::subview(loc_zm_output_evap_dq_out, i); + + // call the ZM evap scheme + ZMF::zm_conv_evap( team, zm_opts, nlev_mid, nlev_int, dt, + p_mid_i, p_del_i, tmp_T_mid_i, tmp_qv_i, rain_prod_i, cldfrac_i, + tend_tmp_s_i, tend_tmp_qv_i, tend_s_snwprd_i, tend_s_snwevmlt_i, + loc_zm_output_prec(i), loc_zm_output_snow(i), + ntprprd_i, ntsnprd_i, flxprec_i, flxsnow_i ); + + // add zm_conv_evap() tendencies to output tendencies and update temporary state variables + Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_mid), [&] (const int k) { + tend_out_s_i(k) += tend_tmp_s_i(k); + tend_out_qv_i(k) += tend_tmp_qv_i(k); + evap_ds_out_i(k) = tend_tmp_s_i(k); + evap_dq_out_i(k) = tend_tmp_qv_i(k); + }); - // seten output buffer, and combined (nwind, nlev) momentum tendency output - const auto tend_tmp_s_i = ekat::subview(loc_zm_output_tend_tmp_s, i); - const auto wind_tend_i = ekat::subview(loc_zm_output_tend_tmp_winds, i); - - // call the ZM momentum transport scheme - ZMF::zm_transport_momentum( team, wsm.get_workspace(team), nlev_mid, nlev_int, dt, - wind_mid_i, 2, - mflx_up_i, mflx_dn_i, detr_up_i, entr_up_i, entr_dn_i, p_del_mb_i, - loc_zm_output_jt(i), loc_zm_output_msemax_klev(i), ktm, kbm, - wind_tend_i, // momentum tendency (nwind, nlev) - tend_tmp_s_i ); // seten (KE-dissipation dry static energy tendency) - - // add zm_transport_momentum tendencies to output tendencies - // (mirrors EAM: output_tend_{u,v} += tx_wind_tend; output_tend_s += seten) - Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_mid), [&] (const int k) { - tend_out_s_i(k) += tend_tmp_s_i(k); - tend_out_u_i(k) += wind_tend_i(0,k); - tend_out_v_i(k) += wind_tend_i(1,k); - }); + }); + //-------------------------------------------------------------------------- + // convective momentum transport + + // initialize intermediate output tendencies for zm_transport_momentum() + zm_output.init_tmp(m_ncol, nlev_mid); + + // domain-wide convection level bounds from zm_conv_main (host scalars captured by value) + const Int ktm = zm_output.ktm; + const Int kbm = zm_output.kbm; + + Kokkos::parallel_for(team_policy, KOKKOS_LAMBDA(const KT::MemberType& team) { + const Int i = team.league_rank(); + // skip inactive columns: zm_conv_main leaves p_del_mb (=dp) zero for them, + // and zm_transport_momentum divides by dp, which would produce NaNs + if (!loc_zm_output_activity(i)) return; + // MCSP-updated winds in (nwind, nlev) == (m,k) layout for wind_mid + const auto wind_mid_i = ekat::subview(loc_zm_input_tmp_winds, i); + const auto mflx_up_i = ekat::subview(loc_zm_output_mflx_up, i); + const auto mflx_dn_i = ekat::subview(loc_zm_output_mflx_dn, i); + const auto detr_up_i = ekat::subview(loc_zm_output_detr_up, i); + const auto entr_up_i = ekat::subview(loc_zm_output_entr_up, i); + const auto entr_dn_i = ekat::subview(loc_zm_output_entr_dn, i); + const auto p_del_mb_i = ekat::subview(loc_zm_output_p_del_mb, i); + + const auto tend_out_s_i = ekat::subview(loc_zm_output_tend_out_s, i); + const auto tend_out_u_i = ekat::subview(loc_zm_output_tend_out_u, i); + const auto tend_out_v_i = ekat::subview(loc_zm_output_tend_out_v, i); + + // seten output buffer, and combined (nwind, nlev) momentum tendency output + const auto tend_tmp_s_i = ekat::subview(loc_zm_output_tend_tmp_s, i); + const auto wind_tend_i = ekat::subview(loc_zm_output_tend_tmp_winds, i); + + // call the ZM momentum transport scheme + ZMF::zm_transport_momentum( team, wsm.get_workspace(team), nlev_mid, nlev_int, dt, + wind_mid_i, 2, + mflx_up_i, mflx_dn_i, detr_up_i, entr_up_i, entr_dn_i, p_del_mb_i, + loc_zm_output_jt(i), loc_zm_output_msemax_klev(i), ktm, kbm, + wind_tend_i, // momentum tendency (nwind, nlev) + tend_tmp_s_i ); // seten (KE-dissipation dry static energy tendency) + + // add zm_transport_momentum tendencies to output tendencies + // (mirrors EAM: output_tend_{u,v} += tx_wind_tend; output_tend_s += seten) + Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_mid), [&] (const int k) { + tend_out_s_i(k) += tend_tmp_s_i(k); + tend_out_u_i(k) += wind_tend_i(0,k); + tend_out_v_i(k) += wind_tend_i(1,k); }); - //-------------------------------------------------------------------------- - } + }); //---------------------------------------------------------------------------- // update prognostic fields @@ -564,10 +546,9 @@ void ZMDeepConvection::run_impl (const double dt) zm_detr_ni(i,k) = zm_detr_qi(i,k) / ( 4.0/3.0*PC::Pi * Kokkos::pow(ZMF::ZMC::cld_ice_radius,3.0) * ZMF::ZMC::cld_ice_density); - // convert dry static energy tendency to temperature tendency (if not using fortran bridge) - if (not zm_opts.use_fortran_bridge) { - loc_zm_output_tend_out_t(i,k) = loc_zm_output_tend_out_s(i,k)/PC::CP.value; - } + // convert dry static energy tendency to temperature tendency + loc_zm_output_tend_out_t(i,k) = loc_zm_output_tend_out_s(i,k)/PC::CP.value; + // apply tendencies (winds via the combined (ncol,nwind,nlev) field view) T_mid(i,k) += loc_zm_output_tend_out_t (i,k) * dt; qv (i,k) += loc_zm_output_tend_out_qv(i,k) * dt; @@ -659,15 +640,6 @@ size_t ZMDeepConvection::requested_buffer_size_in_bytes() const zm_buffer_size+= ZMF::ZmOutputTend::num_2d_intfc * sizeof(Real) * m_ncol * nlev_int; zm_buffer_size+= ZMF::ZmOutputTend::num_3d_midlv * sizeof(Real) * m_ncol * nwind * nlev_mid; - // fortran-bridge (LayoutLeft) transpose buffers are only used when running - // the fortran bridge, so only reserve space for them in that case - if (ZMF::s_zm_opts.use_fortran_bridge) { - constexpr int num_f_mid = ZMF::ZmInputState::num_f_midlv + ZMF::ZmOutputTend::num_f_midlv; - constexpr int num_f_int = ZMF::ZmInputState::num_f_intfc + ZMF::ZmOutputTend::num_f_intfc; - zm_buffer_size+= num_f_mid * sizeof(Real) * m_ncol * m_nlev; - zm_buffer_size+= num_f_int * sizeof(Real) * m_ncol * (m_nlev+1); - } - return zm_buffer_size; } @@ -725,53 +697,7 @@ void ZMDeepConvection::init_buffers(const ATMBufferManager &buffer_manager) // TEMPORARY // *************************************************************************** Real* r_mem = reinterpret_cast(scl_mem); - //---------------------------------------------------------------------------- - // fortran-bridge (LayoutLeft) transpose buffers are only carved out when - // running the fortran bridge (must match requested_buffer_size_in_bytes()) - if (ZMF::s_zm_opts.use_fortran_bridge) { - // device 2D views on mid-point levels - ZMF::uview_2dl* ptrs_f_midlv[num_f_mid] = { &zm_input.f_z_mid, - &zm_input.f_p_mid, - &zm_input.f_p_del, - &zm_input.f_T_mid, - &zm_input.f_qv, - &zm_input.f_uwind, - &zm_input.f_vwind, - &zm_input.f_omega, - &zm_input.f_cldfrac, - &zm_input.f_t_prev, - &zm_input.f_q_prev, - &zm_output.f_tend_t, - &zm_output.f_tend_qv, - &zm_output.f_tend_u, - &zm_output.f_tend_v, - &zm_output.f_rain_prod, - &zm_output.f_snow_prod, - &zm_output.f_dlf, - &zm_output.f_mcsp_ds_out, - &zm_output.f_mcsp_dq_out, - &zm_output.f_mcsp_du_out, - &zm_output.f_mcsp_dv_out, - &zm_output.f_evap_ds_out, - &zm_output.f_evap_dq_out, - }; - for (auto& v : ptrs_f_midlv) { - *v = ZMF::uview_2dl(r_mem, m_ncol, m_nlev); - r_mem += v->size(); - } - //-------------------------------------------------------------------------- - // device 2D views on interface levels - ZMF::uview_2dl* ptrs_f_intfc[num_f_int] = { &zm_input.f_z_int, - &zm_input.f_p_int, - &zm_output.f_prec_flux, - &zm_output.f_snow_flux, - &zm_output.f_mass_flux, - }; - for (auto& v : ptrs_f_intfc) { - *v = ZMF::uview_2dl(r_mem, m_ncol, (m_nlev+1)); - r_mem += v->size(); - } - } + //---------------------------------------------------------------------------- // *************************************************************************** // TEMPORARY diff --git a/components/eamxx/src/physics/zm/tests/infra/CMakeLists.txt b/components/eamxx/src/physics/zm/tests/infra/CMakeLists.txt index ad1eb3609d6d..5e3df3b0f68d 100644 --- a/components/eamxx/src/physics/zm/tests/infra/CMakeLists.txt +++ b/components/eamxx/src/physics/zm/tests/infra/CMakeLists.txt @@ -1,5 +1,4 @@ set(INFRA_SRCS - zm_c2f_bridge.f90 zm_test_data.cpp ) diff --git a/components/eamxx/src/physics/zm/tests/infra/zm_c2f_bridge.f90 b/components/eamxx/src/physics/zm/tests/infra/zm_c2f_bridge.f90 deleted file mode 100644 index fede6c75eed0..000000000000 --- a/components/eamxx/src/physics/zm/tests/infra/zm_c2f_bridge.f90 +++ /dev/null @@ -1,360 +0,0 @@ -module zm_c2f_bridge - use iso_c_binding - implicit none - -#include "eamxx_config.f" -#ifdef SCREAM_DOUBLE_PRECISION -# define c_real c_double -#else -# define c_real c_float -#endif - -!=================================================================================================== -contains -!=================================================================================================== - -subroutine zm_opts_init_bridge_f() bind(C) - use zm_eamxx_bridge_wv_saturation, only: wv_sat_init - - call wv_sat_init() -end subroutine zm_opts_init_bridge_f - -subroutine zm_opts_finalize_bridge_f() bind(C) - use zm_eamxx_bridge_wv_saturation, only: wv_sat_final - - call wv_sat_final() -end subroutine zm_opts_finalize_bridge_f - -subroutine ientropy_bridge_f(s, p, qt, t, qst, tfg) bind(C) - use zm_conv_util, only : ientropy - use zm_conv_types, only: zm_const_t, zm_const_set_for_testing - - real(kind=c_real) , value, intent(in) :: s, p, qt, tfg - real(kind=c_real) , intent(out) :: t, qst - - type(zm_const_t) :: zm_const - - call zm_const_set_for_testing(zm_const) - call ientropy(1, s, p, qt, t, qst, tfg, zm_const) -end subroutine ientropy_bridge_f - -subroutine entropy_bridge_f(tk, p, qtot, entropy_rv) bind(C) - use zm_conv_util, only : entropy - use zm_conv_types, only: zm_const_t, zm_const_set_for_testing - - real(kind=c_real) , value, intent(in) :: tk, p, qtot - real(kind=c_real) , intent(out) :: entropy_rv - - type(zm_const_t) :: zm_const - - call zm_const_set_for_testing(zm_const) - entropy_rv = entropy(tk, p, qtot, zm_const) -end subroutine entropy_bridge_f - -subroutine zm_transport_tracer_bridge_f(pcols, pver, doconvtran, q, ncnst, mu, md, du, eu, ed, dp, jt, mx, ideep, il1g, il2g, fracis, dqdt, dpdry, dt) bind(C) - use zm_transport, only : zm_transport_tracer - - integer(kind=c_int) , value, intent(in) :: pcols, pver, ncnst, il1g, il2g - logical(kind=c_bool) , intent(in), dimension(ncnst) :: doconvtran - real(kind=c_real) , intent(in), dimension(pcols, pver, ncnst) :: q, fracis - real(kind=c_real) , intent(in), dimension(pcols, pver) :: mu, md, du, eu, ed, dp, dpdry - integer(kind=c_int) , intent(in), dimension(pcols) :: jt, mx, ideep - real(kind=c_real) , intent(out), dimension(pcols, pver, ncnst) :: dqdt - real(kind=c_real) , value, intent(in) :: dt - - call zm_transport_tracer(pcols, pver, doconvtran, q, ncnst, mu, md, du, eu, ed, dp, jt, mx, ideep, il1g, il2g, fracis, dqdt, dpdry, dt) -end subroutine zm_transport_tracer_bridge_f - -subroutine zm_transport_momentum_bridge_f(pcols, ncol, pver, pverp, wind_in, nwind, mu, md, du, eu, ed, dp, jt, mx, ideep, il1g, il2g, wind_tend, pguall, pgdall, icwu, icwd, dt, seten) bind(C) - use zm_transport, only : zm_transport_momentum - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, nwind, il1g, il2g - real(kind=c_real) , intent(in), dimension(pcols, pver, nwind) :: wind_in - real(kind=c_real) , intent(in), dimension(pcols, pver) :: mu, md, du, eu, ed, dp - integer(kind=c_int) , intent(in), dimension(pcols) :: jt, mx, ideep - real(kind=c_real) , intent(out), dimension(pcols, pver, nwind) :: wind_tend, pguall, pgdall, icwu, icwd - real(kind=c_real) , value, intent(in) :: dt - real(kind=c_real) , intent(out), dimension(pcols, pver) :: seten - - call zm_transport_momentum(pcols, ncol, pver, pverp, wind_in, nwind, mu, md, du, eu, ed, dp, jt, mx, ideep, il1g, il2g, wind_tend, pguall, pgdall, icwu, icwd, dt, seten) -end subroutine zm_transport_momentum_bridge_f - -subroutine compute_dilute_cape_bridge_f(pcols, ncol, pver, pverp, num_cin, num_msg, sp_humidity_in, temperature_in, zmid, pmid, pint, pblt, tpert, parcel_temp, parcel_qsat, msemax_klev, lcl_temperature, lcl_klev, eql_klev, cape, calc_msemax_klev, prev_msemax_klev, use_input_tq_mx, q_mx, t_mx) bind(C) - use zm_conv_cape, only : compute_dilute_cape - use zm_conv_types, only: zm_const_t, zm_param_t - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, num_cin, num_msg - real(kind=c_real) , intent(in), dimension(pcols, pver) :: sp_humidity_in, temperature_in, zmid, pmid - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: pint - integer(kind=c_int) , intent(in), dimension(pcols) :: pblt, prev_msemax_klev - real(kind=c_real) , intent(in), dimension(pcols) :: tpert - real(kind=c_real) , intent(out), dimension(pcols, pver) :: parcel_temp - real(kind=c_real) , intent(inout), dimension(pcols, pver) :: parcel_qsat - integer(kind=c_int) , intent(inout), dimension(pcols) :: msemax_klev, lcl_klev, eql_klev - real(kind=c_real) , intent(out), dimension(pcols) :: lcl_temperature - real(kind=c_real) , intent(inout), dimension(pcols) :: cape, q_mx, t_mx - logical(kind=c_bool) , value, intent(in) :: calc_msemax_klev, use_input_tq_mx - - type(zm_const_t) :: zm_const ! derived type to hold ZM constants - type(zm_param_t) :: zm_param ! derived type to hold ZM tunable parameters - !----------------------------------------------------------------------------- - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call compute_dilute_cape(pcols, ncol, pver, pverp, num_cin, num_msg, sp_humidity_in, temperature_in, zmid, pmid, pint, pblt, tpert, parcel_temp, parcel_qsat, msemax_klev, lcl_temperature, lcl_klev, eql_klev, cape, zm_const, zm_param, calc_msemax_klev, prev_msemax_klev, use_input_tq_mx, q_mx, t_mx) -end subroutine compute_dilute_cape_bridge_f - -subroutine find_mse_max_bridge_f(pcols, ncol, pver, num_msg, msemax_top_k, pergro_active, temperature, zmid, sp_humidity, msemax_klev, mse_max_val) bind(C) - use zm_conv_cape, only : find_mse_max - use zm_conv_types, only: zm_const_t, zm_param_t - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, num_msg - integer(kind=c_int) , intent(in), dimension(pcols) :: msemax_top_k - logical(kind=c_bool) , value, intent(in) :: pergro_active - real(kind=c_real) , intent(in), dimension(pcols, pver) :: temperature, zmid, sp_humidity - integer(kind=c_int) , intent(inout), dimension(pcols) :: msemax_klev - real(kind=c_real) , intent(inout), dimension(pcols) :: mse_max_val - - type(zm_const_t) :: zm_const ! derived type to hold ZM constants - type(zm_param_t) :: zm_param ! derived type to hold ZM tunable parameters - !----------------------------------------------------------------------------- - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call find_mse_max(pcols, ncol, pver, num_msg, msemax_top_k, pergro_active, temperature, zmid, sp_humidity, zm_const, zm_param, msemax_klev, mse_max_val) -end subroutine find_mse_max_bridge_f - -subroutine compute_dilute_parcel_bridge_f(pcols, ncol, pver, num_msg, klaunch, pmid, temperature, sp_humidity, tpert, pblt, parcel_temp, parcel_vtemp, parcel_qsat, lcl_pmid, lcl_temperature, lcl_klev) bind(C) - use zm_conv_cape, only : compute_dilute_parcel - use zm_conv_types, only: zm_const_t, zm_param_t - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, num_msg - integer(kind=c_int) , intent(in), dimension(pcols) :: klaunch, pblt - real(kind=c_real) , intent(in), dimension(pcols, pver) :: pmid, temperature, sp_humidity - real(kind=c_real) , intent(in), dimension(pcols) :: tpert - real(kind=c_real) , intent(inout), dimension(pcols, pver) :: parcel_temp, parcel_vtemp, parcel_qsat - real(kind=c_real) , intent(inout), dimension(pcols) :: lcl_pmid, lcl_temperature - integer(kind=c_int) , intent(inout), dimension(pcols) :: lcl_klev - - type(zm_const_t) :: zm_const ! derived type to hold ZM constants - type(zm_param_t) :: zm_param ! derived type to hold ZM tunable parameters - !----------------------------------------------------------------------------- - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call compute_dilute_parcel(pcols, ncol, pver, num_msg, klaunch, pmid, temperature, sp_humidity, tpert, pblt, zm_const, zm_param, parcel_temp, parcel_vtemp, parcel_qsat, lcl_pmid, lcl_temperature, lcl_klev) -end subroutine compute_dilute_parcel_bridge_f - -subroutine compute_cape_from_parcel_bridge_f(pcols, ncol, pver, pverp, num_cin, num_msg, temperature, tv, sp_humidity, pint, msemax_klev, lcl_pmid, lcl_klev, parcel_qsat, parcel_temp, parcel_vtemp, eql_klev, cape) bind(C) - use zm_conv_cape, only : compute_cape_from_parcel - use zm_conv_types, only: zm_const_t, zm_param_t - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, num_cin, num_msg - real(kind=c_real) , intent(in), dimension(pcols, pver) :: temperature, tv, sp_humidity - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: pint - integer(kind=c_int) , intent(in), dimension(pcols) :: msemax_klev, lcl_klev - real(kind=c_real) , intent(in), dimension(pcols) :: lcl_pmid - real(kind=c_real) , intent(inout), dimension(pcols, pver) :: parcel_qsat, parcel_temp, parcel_vtemp - integer(kind=c_int) , intent(inout), dimension(pcols) :: eql_klev - real(kind=c_real) , intent(inout), dimension(pcols) :: cape - - type(zm_const_t) :: zm_const ! derived type to hold ZM constants - type(zm_param_t) :: zm_param ! derived type to hold ZM tunable parameters - !----------------------------------------------------------------------------- - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call compute_cape_from_parcel(pcols, ncol, pver, pverp, num_cin, num_msg, temperature, tv, sp_humidity, pint, msemax_klev, lcl_pmid, lcl_klev, zm_const, zm_param, parcel_qsat, parcel_temp, parcel_vtemp, eql_klev, cape) -end subroutine compute_cape_from_parcel_bridge_f - -subroutine zm_conv_mcsp_calculate_shear_bridge_f(pcols, ncol, pver, state_pmid, state_u, state_v, mcsp_shear) bind(C) - use zm_conv_mcsp, only : zm_conv_mcsp_calculate_shear - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver - real(kind=c_real) , intent(in), dimension(pcols, pver) :: state_pmid, state_u, state_v - real(kind=c_real) , intent(out), dimension(pcols) :: mcsp_shear - - call zm_conv_mcsp_calculate_shear(pcols, ncol, pver, state_pmid, state_u, state_v, mcsp_shear) -end subroutine zm_conv_mcsp_calculate_shear_bridge_f - -subroutine zm_conv_mcsp_tend_bridge_f(pcols, ncol, pver, pverp, ztodt, jctop, state_pmid, state_pint, state_pdel, state_s, state_q, state_u, state_v, ptend_zm_s, ptend_zm_q, ptend_s, ptend_q, ptend_u, ptend_v, mcsp_ds_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, mcsp_freq, mcsp_shear, zm_depth) bind(C) - use zm_conv_mcsp, only : zm_conv_mcsp_tend - use zm_conv_types, only: zm_const_t, zm_param_t - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp - real(kind=c_real) , value, intent(in) :: ztodt - integer(kind=c_int) , intent(in), dimension(pcols) :: jctop - real(kind=c_real) , intent(in), dimension(pcols, pver) :: state_pmid, state_pdel, state_s, state_q, state_u, state_v, ptend_zm_s, ptend_zm_q - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: state_pint - real(kind=c_real) , intent(inout), dimension(pcols, pver) :: ptend_s, ptend_q, ptend_u, ptend_v - real(kind=c_real) , intent(out), dimension(pcols, pver) :: mcsp_ds_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out - real(kind=c_real) , intent(out), dimension(pcols) :: mcsp_freq, mcsp_shear, zm_depth - - type(zm_const_t) :: zm_const ! derived type to hold ZM constants - type(zm_param_t) :: zm_param ! derived type to hold ZM tunable parameters - !----------------------------------------------------------------------------- - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call zm_conv_mcsp_tend(pcols, ncol, pver, pverp, ztodt, jctop, zm_const, zm_param, state_pmid, state_pint, state_pdel, state_s, state_q, state_u, state_v, ptend_zm_s, ptend_zm_q, ptend_s, ptend_q, ptend_u, ptend_v, mcsp_ds_out, mcsp_dq_out, mcsp_du_out, mcsp_dv_out, mcsp_freq, mcsp_shear, zm_depth) -end subroutine zm_conv_mcsp_tend_bridge_f - -subroutine zm_conv_main_bridge_f(pcols, ncol, pver, pverp, is_first_step, time_step, t_mid, q_mid_in, omega, p_mid_in, p_int_in, p_del_in, geos, z_mid_in, z_int_in, pbl_hgt, tpert, landfrac, t_star, q_star, lengath, gather_index, msemax_klev_g, jctop, jcbot, jt, prec, heat, qtnd, cape, dcape, mcon, pflx, zdu, mflx_up, entr_up, detr_up, mflx_dn, entr_dn, p_del, dsubcld, ql, rliq, rprd, dlf) bind(C) - use zm_conv, only : zm_conv_main, zm_const, zm_param - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - use zm_aero_type, only: zm_aero_t - use zm_microphysics_state, only: zm_microp_st - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp - logical(kind=c_bool) , value, intent(in) :: is_first_step - real(kind=c_real) , value, intent(in) :: time_step - real(kind=c_real) , target, intent(in), dimension(pcols, pver) :: t_mid, q_mid_in, omega, p_mid_in, p_del_in, z_mid_in, t_star, q_star - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: p_int_in, z_int_in - real(kind=c_real) , intent(in), dimension(pcols) :: geos, pbl_hgt, tpert, landfrac - integer(kind=c_int) , intent(out) :: lengath - integer(kind=c_int) , intent(out), dimension(pcols) :: gather_index, msemax_klev_g, jctop, jcbot, jt - real(kind=c_real) , intent(out), dimension(pcols) :: prec, cape, dcape, dsubcld, rliq - real(kind=c_real) , intent(out), dimension(pcols, pver) :: heat, qtnd, zdu, mflx_up, entr_up, detr_up, mflx_dn, entr_dn, p_del, ql, rprd, dlf - real(kind=c_real) , intent(out), dimension(pcols, pverp) :: mcon, pflx - - type(zm_aero_t) :: aero ! aerosol object - type(zm_microp_st) :: microp_st - - real(kind=c_real), pointer :: t_star_ptr(:,:), q_star_ptr(:,:) - - t_star_ptr => t_star - q_star_ptr => q_star - - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call zm_conv_main(pcols, ncol, pver, pverp, is_first_step, time_step, t_mid, q_mid_in, omega, p_mid_in, p_int_in, p_del_in, geos, z_mid_in, z_int_in, pbl_hgt, tpert, landfrac, t_star_ptr, q_star_ptr, lengath, gather_index, msemax_klev_g, jctop, jcbot, jt, prec, heat, qtnd, cape, dcape, mcon, pflx, zdu, mflx_up, entr_up, detr_up, mflx_dn, entr_dn, p_del, dsubcld, ql, rliq, rprd, dlf, aero, microp_st) -end subroutine zm_conv_main_bridge_f - -subroutine zm_conv_evap_bridge_f(pcols, ncol, pver, pverp, time_step, p_mid, p_del, t_mid, q_mid, prdprec, cldfrc, tend_s, tend_q, tend_s_snwprd, tend_s_snwevmlt, prec, snow, ntprprd, ntsnprd, flxprec, flxsnow) bind(C) - use zm_conv, only : zm_conv_evap, zm_const, zm_param - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - use zm_microphysics_state, only: zm_microp_st - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp - real(kind=c_real) , value, intent(in) :: time_step - real(kind=c_real) , intent(in), dimension(pcols, pver) :: p_mid, p_del, t_mid, q_mid, prdprec, cldfrc - real(kind=c_real) , intent(inout), dimension(pcols, pver) :: tend_s, tend_q - real(kind=c_real) , intent(out), dimension(pcols, pver) :: tend_s_snwprd, tend_s_snwevmlt, ntprprd, ntsnprd - real(kind=c_real) , intent(inout), dimension(pcols) :: prec - real(kind=c_real) , intent(out), dimension(pcols) :: snow - real(kind=c_real) , intent(out), dimension(pcols, pverp) :: flxprec, flxsnow - - type(zm_microp_st) :: microp_st - - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call zm_conv_evap(pcols, ncol, pver, pverp, time_step, p_mid, p_del, t_mid, q_mid, prdprec, cldfrc, tend_s, tend_q, tend_s_snwprd, tend_s_snwevmlt, prec, snow, ntprprd, ntsnprd, flxprec, flxsnow, microp_st) -end subroutine zm_conv_evap_bridge_f - -subroutine zm_calc_fractional_entrainment_bridge_f(pcols, ncol, pver, pverp, msg, jb, jt, j0, z_mid, z_int, dz, h_env, h_env_sat, h_env_min, lambda, lambda_max) bind(C) - use zm_conv, only : zm_calc_fractional_entrainment, zm_const, zm_param - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, msg - integer(kind=c_int) , intent(in), dimension(pcols) :: jb, jt - integer(kind=c_int) , intent(inout), dimension(pcols) :: j0 - real(kind=c_real) , intent(in), dimension(pcols, pver) :: z_mid, dz, h_env, h_env_sat - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: z_int - real(kind=c_real) , intent(inout), dimension(pcols) :: h_env_min - real(kind=c_real) , intent(out), dimension(pcols, pver) :: lambda - real(kind=c_real) , intent(out), dimension(pcols) :: lambda_max - - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call zm_calc_fractional_entrainment(pcols, ncol, pver, pverp, msg, jb, jt, j0, z_mid, z_int, dz, h_env, h_env_sat, h_env_min, lambda, lambda_max) -end subroutine zm_calc_fractional_entrainment_bridge_f - -subroutine zm_downdraft_properties_bridge_f(pcols, ncol, pver, pverp, msg, jb, jt, j0, jd, z_int, dz, s_mid, q_mid, h_env, lambda, lambda_max, qsthat, hsthat, gamhat, rprd, mflx_up, mflx_dn, entr_dn, s_dnd, q_dnd, h_dnd, q_dnd_sat, evp, totevp) bind(C) - use zm_conv, only : zm_downdraft_properties, zm_const, zm_param - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, msg - integer(kind=c_int) , intent(in), dimension(pcols) :: jb, j0 - integer(kind=c_int) , intent(inout), dimension(pcols) :: jt, jd - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: z_int - real(kind=c_real) , intent(in), dimension(pcols, pver) :: dz, s_mid, q_mid, h_env, lambda, qsthat, hsthat, gamhat, rprd, mflx_up - real(kind=c_real) , intent(in), dimension(pcols) :: lambda_max - real(kind=c_real) , intent(inout), dimension(pcols, pver) :: mflx_dn, entr_dn, s_dnd, q_dnd, h_dnd, q_dnd_sat, evp - real(kind=c_real) , intent(inout), dimension(pcols) :: totevp - - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call zm_downdraft_properties(pcols, ncol, pver, pverp, msg, jb, jt, j0, jd, z_int, dz, s_mid, q_mid, h_env, lambda, lambda_max, qsthat, hsthat, gamhat, rprd, mflx_up, mflx_dn, entr_dn, s_dnd, q_dnd, h_dnd, q_dnd_sat, evp, totevp) -end subroutine zm_downdraft_properties_bridge_f - -subroutine zm_cloud_properties_bridge_f(pcols, ncol, pver, pverp, msg, limcnv, p_mid, z_mid, z_int, t_mid, s_mid, s_int, q_mid, landfrac, tpert_g, jb, lel, jt, jlcl, j0, jd, mflx_up, entr_up, detr_up, mflx_dn, entr_dn, mflx_net, s_upd, q_upd, ql, s_dnd, q_dnd, qst, cu, evp, pflx, rprd) bind(C) - use zm_conv, only : zm_cloud_properties, zm_const, zm_param - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - use zm_aero_type, only: zm_aero_t - use zm_microphysics_state, only: zm_microp_st - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, msg, limcnv - real(kind=c_real) , intent(in), dimension(pcols, pver) :: p_mid, z_mid, t_mid, s_mid, s_int, q_mid - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: z_int - real(kind=c_real) , intent(in), dimension(pcols) :: landfrac, tpert_g - integer(kind=c_int) , intent(in), dimension(pcols) :: jb, lel - integer(kind=c_int) , intent(out), dimension(pcols) :: jt, jlcl, j0, jd - real(kind=c_real) , intent(out), dimension(pcols, pver) :: mflx_up, entr_up, detr_up, mflx_dn, entr_dn, mflx_net, s_upd, q_upd, ql, s_dnd, q_dnd, qst, cu, evp, rprd - real(kind=c_real) , intent(out), dimension(pcols, pverp) :: pflx - - type(zm_aero_t) :: aero - type(zm_microp_st) :: microp_st - - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call zm_cloud_properties(pcols, ncol, pver, pverp, msg, limcnv, p_mid, z_mid, z_int, t_mid, s_mid, s_int, q_mid, landfrac, tpert_g, jb, lel, jt, jlcl, j0, jd, mflx_up, entr_up, detr_up, mflx_dn, entr_dn, mflx_net, s_upd, q_upd, ql, s_dnd, q_dnd, qst, cu, evp, pflx, rprd, aero, microp_st) -end subroutine zm_cloud_properties_bridge_f - -subroutine zm_closure_bridge_f(pcols, ncol, pver, pverp, msg, cape_threshold_in, lcl, lel, jt, mx, dsubcld, z_mid, z_int, p_mid, p_del, t_mid, s_mid, q_mid, qs, ql, s_int, q_int, t_pcl_lcl, t_pcl, q_pcl_sat, s_upd, q_upd, mflx_net, detr_up, mflx_up, mflx_dn, q_dnd, s_dnd, cape, cld_base_mass_flux) bind(C) - use zm_conv, only : zm_closure, zm_const, zm_param - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, msg - real(kind=c_real) , value, intent(in) :: cape_threshold_in - integer(kind=c_int) , intent(in), dimension(pcols) :: lcl, lel, jt, mx - real(kind=c_real) , intent(in), dimension(pcols) :: dsubcld, t_pcl_lcl, cape - real(kind=c_real) , intent(in), dimension(pcols, pver) :: z_mid, p_mid, p_del, t_mid, s_mid, q_mid, qs, ql, s_int, q_int, t_pcl, q_pcl_sat, s_upd, q_upd, mflx_net, detr_up, mflx_up, mflx_dn, q_dnd, s_dnd - real(kind=c_real) , intent(in), dimension(pcols, pverp) :: z_int - real(kind=c_real) , intent(out), dimension(pcols) :: cld_base_mass_flux - - call zm_const_set_for_testing(zm_const) - call zm_param_set_for_testing(zm_param) - - call zm_closure(pcols, ncol, pver, pverp, msg, cape_threshold_in, lcl, lel, jt, mx, dsubcld, z_mid, z_int, p_mid, p_del, t_mid, s_mid, q_mid, qs, ql, s_int, q_int, t_pcl_lcl, t_pcl, q_pcl_sat, s_upd, q_upd, mflx_net, detr_up, mflx_up, mflx_dn, q_dnd, s_dnd, cape, cld_base_mass_flux) -end subroutine zm_closure_bridge_f - -subroutine zm_calc_output_tend_bridge_f(pcols, ncol, pver, pverp, msg, jt, mx, dsubcld, p_del, s_int, q_int, s_upd, q_upd, mflx_up, detr_up, mflx_dn, s_dnd, q_dnd, ql, evp, cu, dsdt, dqdt, dl) bind(C) - use zm_conv, only : zm_calc_output_tend, zm_const, zm_param - use zm_conv_types, only: zm_param_set_for_testing, zm_const_set_for_testing - use zm_microphysics_state, only: zm_microp_st - - integer(kind=c_int) , value, intent(in) :: pcols, ncol, pver, pverp, msg - integer(kind=c_int) , intent(in), dimension(pcols) :: jt, mx - real(kind=c_real) , intent(in), dimension(pcols) :: dsubcld - real(kind=c_real) , intent(in), dimension(pcols, pver) :: p_del, s_int, q_int, s_upd, q_upd, mflx_up, detr_up, mflx_dn, s_dnd, q_dnd, ql, evp, cu - real(kind=c_real) , intent(out), dimension(pcols, pver) :: dsdt, dqdt, dl - - type(zm_microp_st) :: microp_st - - call zm_param_set_for_testing(zm_param) - call zm_const_set_for_testing(zm_const) - - call zm_calc_output_tend(pcols, ncol, pver, pverp, msg, jt, mx, dsubcld, p_del, s_int, q_int, s_upd, q_upd, mflx_up, detr_up, mflx_dn, s_dnd, q_dnd, ql, evp, cu, dsdt, dqdt, dl, microp_st) -end subroutine zm_calc_output_tend_bridge_f - -end module zm_c2f_bridge From 66c2b18b46e4a5a4648930ace92a65df47825ded Mon Sep 17 00:00:00 2001 From: James Foucar Date: Fri, 28 Aug 2026 14:51:25 -0600 Subject: [PATCH 5/8] Remove unused --- components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp index cbc23a8de00b..61d6f1d24a61 100644 --- a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp +++ b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp @@ -658,9 +658,6 @@ void ZMDeepConvection::init_buffers(const ATMBufferManager &buffer_manager) constexpr auto num_2d_midlv = ZMF::ZmInputState::num_2d_midlv + ZMF::ZmOutputTend::num_2d_midlv; constexpr auto num_2d_intfc = ZMF::ZmInputState::num_2d_intfc + ZMF::ZmOutputTend::num_2d_intfc; - constexpr int num_f_mid = ZMF::ZmInputState::num_f_midlv + ZMF::ZmOutputTend::num_f_midlv; - constexpr int num_f_int = ZMF::ZmInputState::num_f_intfc + ZMF::ZmOutputTend::num_f_intfc; - //---------------------------------------------------------------------------- Int* i_mem = reinterpret_cast(buffer_manager.get_memory()); //---------------------------------------------------------------------------- From 1a3b77aa54229321572120653ab69ac28deea3b8 Mon Sep 17 00:00:00 2001 From: James Foucar Date: Fri, 28 Aug 2026 15:18:54 -0600 Subject: [PATCH 6/8] Fix copilot comments --- components/eamxx/src/physics/zm/CMakeLists.txt | 2 -- components/eamxx/src/physics/zm/zm_functions.hpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/components/eamxx/src/physics/zm/CMakeLists.txt b/components/eamxx/src/physics/zm/CMakeLists.txt index 1792a49aa527..60bb75d0a397 100644 --- a/components/eamxx/src/physics/zm/CMakeLists.txt +++ b/components/eamxx/src/physics/zm/CMakeLists.txt @@ -42,8 +42,6 @@ target_compile_definitions(zm PUBLIC EAMXX_HAS_ZM) target_include_directories(zm PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/modules - ${PATH_TO_LEGACY_ZM} - ${PATH_TO_LEGACY_ZM}/.. ) target_link_libraries(zm eamxx_physics_share scream_share csm_share) diff --git a/components/eamxx/src/physics/zm/zm_functions.hpp b/components/eamxx/src/physics/zm/zm_functions.hpp index c4a3d748243c..6e7deb4fab38 100644 --- a/components/eamxx/src/physics/zm/zm_functions.hpp +++ b/components/eamxx/src/physics/zm/zm_functions.hpp @@ -151,7 +151,7 @@ struct Functions { void load_runtime_options(ekat::ParameterList& params) { apply_detr_tend = params.get("apply_detr_tend", true); - use_fortran_bridge = params.get("use_fortran_bridge", true); + use_fortran_bridge = params.get("use_fortran_bridge", false); upper_limit_pref = params.get("upper_limit_pref", 40e2); tau = params.get("tau", 3600); alfa = params.get("alfa", ZMC::alfa); From 8ddda9e03789bec205421ee1335451295eaee437 Mon Sep 17 00:00:00 2001 From: James Foucar Date: Fri, 28 Aug 2026 15:20:22 -0600 Subject: [PATCH 7/8] Remove old banners --- .../eamxx/src/physics/zm/eamxx_zm_process_interface.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp index 61d6f1d24a61..58bc5f0a0f64 100644 --- a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp +++ b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp @@ -690,15 +690,9 @@ void ZMDeepConvection::init_buffers(const ATMBufferManager &buffer_manager) } //---------------------------------------------------------------------------- - // *************************************************************************** - // TEMPORARY - // *************************************************************************** Real* r_mem = reinterpret_cast(scl_mem); //---------------------------------------------------------------------------- - // *************************************************************************** - // TEMPORARY - // *************************************************************************** // device 2D views on mid-point levels ZMF::uview_2d* ptrs_2d_midlv[num_2d_midlv] = { &zm_input.z_mid, &zm_input.z_del, From 6a17a2d34a37f5a82084f31e5fe9de73ccea540f Mon Sep 17 00:00:00 2001 From: James Foucar Date: Mon, 31 Aug 2026 10:04:38 -0600 Subject: [PATCH 8/8] Remove fortran bridge option for ZM --- components/eamxx/cime_config/namelist_defaults_eamxx.xml | 1 - .../eamxx/src/physics/zm/eamxx_zm_process_interface.cpp | 5 ----- components/eamxx/src/physics/zm/impl/zm_opts_impl.hpp | 1 - components/eamxx/src/physics/zm/zm_functions.hpp | 2 -- 4 files changed, 9 deletions(-) diff --git a/components/eamxx/cime_config/namelist_defaults_eamxx.xml b/components/eamxx/cime_config/namelist_defaults_eamxx.xml index 3e206a3b8b67..784b2d916f96 100644 --- a/components/eamxx/cime_config/namelist_defaults_eamxx.xml +++ b/components/eamxx/cime_config/namelist_defaults_eamxx.xml @@ -272,7 +272,6 @@ be lost if SCREAM_HACK_XML is not enabled. true - false true true false diff --git a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp index 58bc5f0a0f64..3be78ace6933 100644 --- a/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp +++ b/components/eamxx/src/physics/zm/eamxx_zm_process_interface.cpp @@ -129,11 +129,6 @@ void ZMDeepConvection::initialize_impl (const RunType) //---------------------------------------------------------------------------- ZMF::s_zm_opts.set_limcnv(m_grid); if (this->get_comm().am_i_root()) ZMF::s_zm_opts.print(); - //---------------------------------------------------------------------------- - if (ZMF::s_zm_opts.use_fortran_bridge) { - EKAT_REQUIRE_MSG(false, "ZM fortran bridge no longer supported"); - } // if use_fortran_bridge - //---------------------------------------------------------------------------- } // ZMDeepConvection::initialize_impl /*------------------------------------------------------------------------------------------------*/ diff --git a/components/eamxx/src/physics/zm/impl/zm_opts_impl.hpp b/components/eamxx/src/physics/zm/impl/zm_opts_impl.hpp index e940a4caed54..61110f0aab93 100644 --- a/components/eamxx/src/physics/zm/impl/zm_opts_impl.hpp +++ b/components/eamxx/src/physics/zm/impl/zm_opts_impl.hpp @@ -14,7 +14,6 @@ namespace zm { template void Functions::zm_opts_init() { - s_zm_opts.use_fortran_bridge = false; s_zm_opts.apply_detr_tend = true; s_zm_opts.upper_limit_pref = 40e2; s_zm_opts.plenest = static_cast(ZMC::tmax-ZMC::tmin) + 3; diff --git a/components/eamxx/src/physics/zm/zm_functions.hpp b/components/eamxx/src/physics/zm/zm_functions.hpp index 6e7deb4fab38..465d0028bda1 100644 --- a/components/eamxx/src/physics/zm/zm_functions.hpp +++ b/components/eamxx/src/physics/zm/zm_functions.hpp @@ -151,7 +151,6 @@ struct Functions { void load_runtime_options(ekat::ParameterList& params) { apply_detr_tend = params.get("apply_detr_tend", true); - use_fortran_bridge = params.get("use_fortran_bridge", false); upper_limit_pref = params.get("upper_limit_pref", 40e2); tau = params.get("tau", 3600); alfa = params.get("alfa", ZMC::alfa); @@ -275,7 +274,6 @@ struct Functions { bool clos_dyn_adj; // flag for mass flux adjustment to CAPE closure bool no_deep_pbl; // flag to eliminate deep convection within PBL bool apply_detr_tend; - bool use_fortran_bridge; // ZM micro parameters bool zm_microp; // switch for convective microphysics bool old_snow; // switch to calculate snow prod in zm_conv_evap() (old treatment before zm_microp was implemented)