Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EAMxx: add p3 rates diags #6936

Closed
mahf708 opened this issue Jan 23, 2025 · 1 comment
Closed

EAMxx: add p3 rates diags #6936

mahf708 opened this issue Jan 23, 2025 · 1 comment
Assignees
Labels
EAMxx PRs focused on capabilities for EAMxx enhancement

Comments

@mahf708
Copy link
Contributor

mahf708 commented Jan 23, 2025

We need a temporary plan to output all sorts of p3 diagnostics; maybe following shoc's lead

relevant code (maybe?!): https://github.com/E3SM-Project/scream/tree/beydoun/add_p3_diags_v1

plan of attack:

  • add runtime flag to, e.g., p3_extra_diags_out
  • encapsulate all these extra fields into if-else blocks
  • need to be careful about wsm-vs-not (buffer, etc.) stuff
@mahf708
Copy link
Contributor Author

mahf708 commented Jan 28, 2025

The following patch is a good start to get these diagnostics. People interested in pursuing these diagnostics can apply the patch and move forward. There are two problems highlighted in #6938 (comment), but they don't influence the main eamxx runtime as far as I could tell.

patch

From 366edc6d62dcff6453c2848c3dc1dfff53a90211 Mon Sep 17 00:00:00 2001
From: mahf708 <naser.mahfouz@pnnl.gov>
Date: Thu, 23 Jan 2025 16:15:44 -0800
Subject: [PATCH] EAMxx: add some extra p3 diags

this impl is kind of hacky because
we don't yet have the facility to
request output fields adhoc
and these fields are buried deep
in the p3 impl; in the future,
this could be edited to be done
more smartly, but for now, this
may be just enough...
---
 .../cime_config/namelist_defaults_scream.xml  |  1 +
 .../src/physics/p3/disp/p3_main_impl_disp.cpp | 14 ++++
 .../p3/disp/p3_main_impl_part2_disp.cpp       | 16 +++-
 .../physics/p3/eamxx_p3_process_interface.cpp | 62 +++++++++++++-
 .../eamxx/src/physics/p3/eamxx_p3_run.cpp     | 19 +++++
 .../src/physics/p3/impl/p3_main_impl.hpp      | 24 +++++-
 .../physics/p3/impl/p3_main_impl_part2.hpp    | 26 ++++++
 .../eamxx/src/physics/p3/p3_functions.hpp     | 42 ++++++++++
 .../src/physics/p3/tests/infra/p3_data.cpp    | 16 ++++
 .../src/physics/p3/tests/infra/p3_data.hpp    |  1 +
 .../physics/p3/tests/infra/p3_main_wrap.cpp   |  4 +-
 .../physics/p3/tests/infra/p3_test_data.cpp   | 81 ++++++++++++++++---
 .../physics/p3/tests/infra/p3_test_data.hpp   | 19 +++--
 .../physics/p3/tests/p3_main_unit_tests.cpp   |  8 +-
 .../eamxx/src/physics/p3/tests/p3_tests.cpp   |  2 +-
 15 files changed, 308 insertions(+), 27 deletions(-)

diff --git a/components/eamxx/cime_config/namelist_defaults_scream.xml b/components/eamxx/cime_config/namelist_defaults_scream.xml
index 68add18ddcd9..c96d704749c8 100644
--- a/components/eamxx/cime_config/namelist_defaults_scream.xml
+++ b/components/eamxx/cime_config/namelist_defaults_scream.xml
@@ -227,6 +227,7 @@ be lost if SCREAM_HACK_XML is not enabled.
       <set_cld_frac_l_to_one type="logical" doc="set P3 input liquid cloud fraction to 1 everywhere">false</set_cld_frac_l_to_one>
       <set_cld_frac_r_to_one type="logical" doc="set P3 input rain cloud fraction to 1 everywhere"  >false</set_cld_frac_r_to_one>
       <set_cld_frac_i_to_one type="logical" doc="set P3 input ice cloud fraction to 1 everywhere"   >false</set_cld_frac_i_to_one>
+      <p3_extra_diags type="logical" doc="Extra P3 diagnostics">false</p3_extra_diags>
     </p3>
 
     <!-- SHOC macrophysics -->
diff --git a/components/eamxx/src/physics/p3/disp/p3_main_impl_disp.cpp b/components/eamxx/src/physics/p3/disp/p3_main_impl_disp.cpp
index 99a2381ca23d..f1f3956efd8c 100644
--- a/components/eamxx/src/physics/p3/disp/p3_main_impl_disp.cpp
+++ b/components/eamxx/src/physics/p3/disp/p3_main_impl_disp.cpp
@@ -166,6 +166,18 @@ ::p3_main_internal_disp(
   auto liq_ice_exchange        = history_only.liq_ice_exchange;
   auto vap_liq_exchange        = history_only.vap_liq_exchange;
   auto vap_ice_exchange        = history_only.vap_ice_exchange;
+  auto P3_qr2qv_evap           = history_only.P3_qr2qv_evap;
+  auto P3_qi2qv_sublim         = history_only.P3_qi2qv_sublim;
+  auto P3_qc2qr_accret         = history_only.P3_qc2qr_accret;
+  auto P3_qc2qr_autoconv       = history_only.P3_qc2qr_autoconv;
+  auto P3_qv2qi_vapdep         = history_only.P3_qv2qi_vapdep;
+  auto P3_qc2qi_berg           = history_only.P3_qc2qi_berg;
+  auto P3_qc2qr_ice_shed       = history_only.P3_qc2qr_ice_shed;
+  auto P3_qc2qi_collect        = history_only.P3_qc2qi_collect;
+  auto P3_qr2qi_collect        = history_only.P3_qr2qi_collect;
+  auto P3_qc2qi_hetero_freeze  = history_only.P3_qc2qi_hetero_freeze;
+  auto P3_qr2qi_immers_freeze  = history_only.P3_qr2qi_immers_freeze;
+  auto P3_qi2qr_melt           = history_only.P3_qi2qr_melt;
   auto mu_r                    = temporaries.mu_r;
   auto T_atm                   = temporaries.T_atm;
   auto lamr                    = temporaries.lamr;
@@ -260,6 +272,8 @@ ::p3_main_internal_disp(
       nr_incld, ni_incld, bm_incld, mu_c, nu, lamc, cdist, cdist1, cdistr,
       mu_r, lamr, logn0r, qv2qi_depos_tend, precip_total_tend, nevapr, qr_evap_tend,
       vap_liq_exchange, vap_ice_exchange, liq_ice_exchange,
+      P3_qr2qv_evap, P3_qi2qv_sublim, P3_qc2qr_accret, P3_qc2qr_autoconv, P3_qv2qi_vapdep, P3_qc2qi_berg,
+      P3_qc2qr_ice_shed, P3_qc2qi_collect, P3_qr2qi_collect, P3_qc2qi_hetero_freeze, P3_qr2qi_immers_freeze, P3_qi2qr_melt,
       pratot, prctot, nucleationPossible, hydrometeorsPresent, runtime_options);
 
   //NOTE: At this point, it is possible to have negative (but small) nc, nr, ni.  This is not
diff --git a/components/eamxx/src/physics/p3/disp/p3_main_impl_part2_disp.cpp b/components/eamxx/src/physics/p3/disp/p3_main_impl_part2_disp.cpp
index 9f7987abbb59..2fc9d06d7b6f 100644
--- a/components/eamxx/src/physics/p3/disp/p3_main_impl_part2_disp.cpp
+++ b/components/eamxx/src/physics/p3/disp/p3_main_impl_part2_disp.cpp
@@ -86,6 +86,18 @@ ::p3_main_part2_disp(
   const uview_2d<Spack>& vap_liq_exchange,
   const uview_2d<Spack>& vap_ice_exchange,
   const uview_2d<Spack>& liq_ice_exchange,
+  const uview_2d<Spack>& P3_qr2qv_evap,
+  const uview_2d<Spack>& P3_qi2qv_sublim,
+  const uview_2d<Spack>& P3_qc2qr_accret,
+  const uview_2d<Spack>& P3_qc2qr_autoconv,
+  const uview_2d<Spack>& P3_qv2qi_vapdep,
+  const uview_2d<Spack>& P3_qc2qi_berg,
+  const uview_2d<Spack>& P3_qc2qr_ice_shed,
+  const uview_2d<Spack>& P3_qc2qi_collect,
+  const uview_2d<Spack>& P3_qr2qi_collect,
+  const uview_2d<Spack>& P3_qc2qi_hetero_freeze,
+  const uview_2d<Spack>& P3_qr2qi_immers_freeze,
+  const uview_2d<Spack>& P3_qi2qr_melt,
   const uview_2d<Spack>& pratot,
   const uview_2d<Spack>& prctot,
   const uview_1d<bool>& nucleationPossible,
@@ -124,7 +136,9 @@ ::p3_main_part2_disp(
       ekat::subview(ni_incld, i), ekat::subview(bm_incld, i), ekat::subview(mu_c, i), ekat::subview(nu, i), ekat::subview(lamc, i), ekat::subview(cdist, i),
       ekat::subview(cdist1, i), ekat::subview(cdistr, i), ekat::subview(mu_r, i), ekat::subview(lamr, i), ekat::subview(logn0r, i),
       ekat::subview(qv2qi_depos_tend, i), ekat::subview(precip_total_tend, i),
-      ekat::subview(nevapr, i), ekat::subview(qr_evap_tend, i), ekat::subview(vap_liq_exchange, i), ekat::subview(vap_ice_exchange, i), ekat::subview(liq_ice_exchange, i),
+      ekat::subview(nevapr, i), ekat::subview(qr_evap_tend, i), ekat::subview(vap_liq_exchange, i), ekat::subview(vap_ice_exchange, i), ekat::subview(liq_ice_exchange, i), ekat::subview(P3_qr2qv_evap, i), ekat::subview(P3_qi2qv_sublim, i), ekat::subview(P3_qc2qr_accret,i),  ekat::subview(P3_qc2qr_autoconv,i), ekat::subview(P3_qv2qi_vapdep,i), ekat::subview(P3_qc2qi_berg,i),
+      ekat::subview(P3_qc2qr_ice_shed,i), ekat::subview(P3_qc2qi_collect,i), ekat::subview(P3_qr2qi_collect,i), ekat::subview(P3_qc2qi_hetero_freeze,i), 
+      ekat::subview(P3_qr2qi_immers_freeze,i), ekat::subview(P3_qi2qr_melt,i),
       ekat::subview(pratot, i), ekat::subview(prctot, i), hydrometeorsPresent(i), nk, runtime_options);
 
     if (!hydrometeorsPresent(i)) return;
diff --git a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp
index 15437fd567a9..ae7bba86a72e 100644
--- a/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp
+++ b/components/eamxx/src/physics/p3/eamxx_p3_process_interface.cpp
@@ -35,6 +35,9 @@ void P3Microphysics::set_grids(const std::shared_ptr<const GridsManager> grids_m
   m_num_cols = m_grid->get_num_local_dofs(); // Number of columns on this rank
   m_num_levs = m_grid->get_num_vertical_levels();  // Number of levels per column
 
+  // Gather runtime options from file
+  runtime_options.load_runtime_options_from_file(m_params);
+
   // --Infrastructure
   // dt is passed as an argument to run_impl
   infrastructure.it  = 0;
@@ -108,6 +111,24 @@ void P3Microphysics::set_grids(const std::shared_ptr<const GridsManager> grids_m
   add_field<Computed>("micro_vap_liq_exchange", scalar3d_layout_mid, kg/kg,  grid_name, ps);
   add_field<Computed>("micro_vap_ice_exchange", scalar3d_layout_mid, kg/kg,  grid_name, ps);
   add_field<Computed>("rainfrac",               scalar3d_layout_mid, nondim, grid_name, ps);
+  // P3 process rate diagnostics, use convention P3_<process_rate>
+  if (runtime_options.p3_extra_diags){
+    add_field<Computed>("P3_qr2qv_evap", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qi2qv_sublim", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qc2qr_accret", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qc2qr_autoconv", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qv2qi_vapdep", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qc2qi_berg", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qc2qr_ice_shed", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qc2qi_collect", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qr2qi_collect", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qc2qi_hetero_freeze", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qr2qi_immers_freeze", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qi2qr_melt", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qr_sed", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qc_sed", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+    add_field<Computed>("P3_qi_sed", scalar3d_layout_mid, kg/kg/s,  grid_name, ps);
+  }
 
   // Boundary flux fields for energy and mass conservation checks
   if (has_column_conservation_check()) {
@@ -217,8 +238,6 @@ void P3Microphysics::init_buffers(const ATMBufferManager &buffer_manager)
 // =========================================================================================
 void P3Microphysics::initialize_impl (const RunType /* run_type */)
 {
-  // Gather runtime options from file
-  runtime_options.load_runtime_options_from_file(m_params);
 
   // Set property checks for fields in this process
   add_invariant_check<FieldWithinIntervalCheck>(get_field_out("T_mid"),m_grid,100.0,500.0,false);
@@ -332,6 +351,45 @@ void P3Microphysics::initialize_impl (const RunType /* run_type */)
   history_only.liq_ice_exchange = get_field_out("micro_liq_ice_exchange").get_view<Pack**>();
   history_only.vap_liq_exchange = get_field_out("micro_vap_liq_exchange").get_view<Pack**>();
   history_only.vap_ice_exchange = get_field_out("micro_vap_ice_exchange").get_view<Pack**>();
+  if(runtime_options.p3_extra_diags) {
+    // if we are doing extra diagnostics, assign the fields to the history only struct
+    history_only.P3_qr2qv_evap   = get_field_out("P3_qr2qv_evap").get_view<Pack**>();
+    history_only.P3_qi2qv_sublim = get_field_out("P3_qi2qv_sublim").get_view<Pack**>();
+    history_only.P3_qc2qr_accret = get_field_out("P3_qc2qr_accret").get_view<Pack**>();
+    history_only.P3_qc2qr_autoconv = get_field_out("P3_qc2qr_autoconv").get_view<Pack**>();
+    history_only.P3_qv2qi_vapdep = get_field_out("P3_qv2qi_vapdep").get_view<Pack**>();
+    history_only.P3_qc2qi_berg = get_field_out("P3_qc2qi_berg").get_view<Pack**>();
+    history_only.P3_qc2qr_ice_shed = get_field_out("P3_qc2qr_ice_shed").get_view<Pack**>();
+    history_only.P3_qc2qi_collect = get_field_out("P3_qc2qi_collect").get_view<Pack**>();
+    history_only.P3_qr2qi_collect = get_field_out("P3_qr2qi_collect").get_view<Pack**>();
+    history_only.P3_qc2qi_hetero_freeze = get_field_out("P3_qc2qi_hetero_freeze").get_view<Pack**>();
+    history_only.P3_qr2qi_immers_freeze = get_field_out("P3_qr2qi_immers_freeze").get_view<Pack**>();
+    history_only.P3_qi2qr_melt = get_field_out("P3_qi2qr_melt").get_view<Pack**>();
+    history_only.P3_qr_sed = get_field_out("P3_qr_sed").get_view<Pack**>();
+    history_only.P3_qc_sed = get_field_out("P3_qc_sed").get_view<Pack**>();
+    history_only.P3_qi_sed = get_field_out("P3_qi_sed").get_view<Pack**>();
+  } else {
+    // if not, let's just use the buffer for the unused? field
+    // TODO: check if this is actually okay and doesn't have uintended consequences
+    // if we are not outputing these fields, we really don't care about their values
+    // but would this have side effects or memory issues? idk
+    // TODO: maybe just use more buffer and assign stuff?
+    history_only.P3_qr2qv_evap   = m_buffer.unused;
+    history_only.P3_qi2qv_sublim = m_buffer.unused;
+    history_only.P3_qc2qr_accret = m_buffer.unused;
+    history_only.P3_qc2qr_autoconv = m_buffer.unused;
+    history_only.P3_qv2qi_vapdep = m_buffer.unused;
+    history_only.P3_qc2qi_berg = m_buffer.unused;
+    history_only.P3_qc2qr_ice_shed = m_buffer.unused;
+    history_only.P3_qc2qi_collect = m_buffer.unused;
+    history_only.P3_qr2qi_collect = m_buffer.unused;
+    history_only.P3_qc2qi_hetero_freeze = m_buffer.unused;
+    history_only.P3_qr2qi_immers_freeze = m_buffer.unused;
+    history_only.P3_qi2qr_melt = m_buffer.unused;
+    history_only.P3_qr_sed = m_buffer.unused;
+    history_only.P3_qc_sed = m_buffer.unused;
+    history_only.P3_qi_sed = m_buffer.unused;
+  }
 #ifdef SCREAM_P3_SMALL_KERNELS
   // Temporaries
   temporaries.mu_r                    = m_buffer.mu_r;
diff --git a/components/eamxx/src/physics/p3/eamxx_p3_run.cpp b/components/eamxx/src/physics/p3/eamxx_p3_run.cpp
index 3de8184319af..72e1c97512fd 100644
--- a/components/eamxx/src/physics/p3/eamxx_p3_run.cpp
+++ b/components/eamxx/src/physics/p3/eamxx_p3_run.cpp
@@ -28,6 +28,25 @@ void P3Microphysics::run_impl (const double dt)
   get_field_out("micro_vap_liq_exchange").deep_copy(0.0);
   get_field_out("micro_vap_ice_exchange").deep_copy(0.0);
 
+  // Optional extra p3 diags
+  if (runtime_options.p3_extra_diags) {
+    get_field_out("P3_qr2qv_evap").deep_copy(0.0);
+    get_field_out("P3_qi2qv_sublim").deep_copy(0.0);
+    get_field_out("P3_qc2qr_accret").deep_copy(0.0);
+    get_field_out("P3_qc2qr_autoconv").deep_copy(0.0);
+    get_field_out("P3_qv2qi_vapdep").deep_copy(0.0);
+    get_field_out("P3_qc2qi_berg").deep_copy(0.0);
+    get_field_out("P3_qc2qr_ice_shed").deep_copy(0.0);
+    get_field_out("P3_qc2qi_collect").deep_copy(0.0);
+    get_field_out("P3_qr2qi_collect").deep_copy(0.0);
+    get_field_out("P3_qc2qi_hetero_freeze").deep_copy(0.0);
+    get_field_out("P3_qr2qi_immers_freeze").deep_copy(0.0);
+    get_field_out("P3_qi2qr_melt").deep_copy(0.0);
+    get_field_out("P3_qr_sed").deep_copy(0.0);
+    get_field_out("P3_qc_sed").deep_copy(0.0);
+    get_field_out("P3_qi_sed").deep_copy(0.0);
+  }
+
   P3F::p3_main(runtime_options, prog_state, diag_inputs, diag_outputs, infrastructure,
                history_only, lookup_tables,
 #ifdef SCREAM_P3_SMALL_KERNELS
diff --git a/components/eamxx/src/physics/p3/impl/p3_main_impl.hpp b/components/eamxx/src/physics/p3/impl/p3_main_impl.hpp
index fb76ac0290e8..32f5403b26db 100644
--- a/components/eamxx/src/physics/p3/impl/p3_main_impl.hpp
+++ b/components/eamxx/src/physics/p3/impl/p3_main_impl.hpp
@@ -198,6 +198,21 @@ ::p3_main_internal(
     const auto oliq_ice_exchange   = ekat::subview(history_only.liq_ice_exchange, i);
     const auto ovap_liq_exchange   = ekat::subview(history_only.vap_liq_exchange, i);
     const auto ovap_ice_exchange   = ekat::subview(history_only.vap_ice_exchange, i);
+    const auto oP3_qr2qv_evap      = ekat::subview(history_only.P3_qr2qv_evap, i);
+    const auto oP3_qi2qv_sublim    = ekat::subview(history_only.P3_qi2qv_sublim, i);
+    const auto oP3_qc2qr_accret    = ekat::subview(history_only.P3_qc2qr_accret,i);
+    const auto oP3_qc2qr_autoconv  = ekat::subview(history_only.P3_qc2qr_autoconv,i);
+    const auto oP3_qv2qi_vapdep    = ekat::subview(history_only.P3_qv2qi_vapdep,i);
+    const auto oP3_qc2qi_berg      = ekat::subview(history_only.P3_qc2qi_berg,i);
+    const auto oP3_qc2qr_ice_shed  = ekat::subview(history_only.P3_qc2qr_ice_shed,i);
+    const auto oP3_qc2qi_collect   = ekat::subview(history_only.P3_qc2qi_collect,i);
+    const auto oP3_qr2qi_collect   = ekat::subview(history_only.P3_qr2qi_collect,i);
+    const auto oP3_qc2qi_hetero_freeze = ekat::subview(history_only.P3_qc2qi_hetero_freeze,i);
+    const auto oP3_qr2qi_immers_freeze = ekat::subview(history_only.P3_qr2qi_immers_freeze,i);
+    const auto oP3_qi2qr_melt      =  ekat::subview(history_only.P3_qi2qr_melt,i);
+    const auto oP3_qr_sed          = ekat::subview(history_only.P3_qr_sed, i);
+    const auto oP3_qc_sed          = ekat::subview(history_only.P3_qc_sed, i);
+    const auto oP3_qi_sed          = ekat::subview(history_only.P3_qi_sed, i);
     const auto oqv_prev            = ekat::subview(diagnostic_inputs.qv_prev, i);
     const auto ot_prev             = ekat::subview(diagnostic_inputs.t_prev, i);
 
@@ -250,7 +265,8 @@ ::p3_main_internal(
       qc_incld, qr_incld, qi_incld, qm_incld, nc_incld,
       nr_incld, ni_incld, bm_incld, mu_c, nu, lamc, cdist, cdist1, cdistr,
       mu_r, lamr, logn0r, oqv2qi_depos_tend, oprecip_total_tend, onevapr, qr_evap_tend,
-      ovap_liq_exchange, ovap_ice_exchange, oliq_ice_exchange,
+      ovap_liq_exchange, ovap_ice_exchange, oliq_ice_exchange,oP3_qr2qv_evap,oP3_qi2qv_sublim,oP3_qc2qr_accret, oP3_qc2qr_autoconv, oP3_qv2qi_vapdep,
+      oP3_qc2qi_berg, oP3_qc2qr_ice_shed, oP3_qc2qi_collect, oP3_qr2qi_collect, oP3_qc2qi_hetero_freeze, oP3_qr2qi_immers_freeze, oP3_qi2qr_melt,
       pratot, prctot, hydrometeorsPresent, nk, runtime_options);
 
     //NOTE: At this point, it is possible to have negative (but small) nc, nr, ni.  This is not
@@ -271,21 +287,21 @@ ::p3_main_internal(
     cloud_sedimentation(
       qc_incld, rho, inv_rho, ocld_frac_l, acn, inv_dz, lookup_tables.dnu_table_vals, team, workspace,
       nk, ktop, kbot, kdir, infrastructure.dt, inv_dt, infrastructure.predictNc,
-      oqc, onc, nc_incld, mu_c, lamc, qtend_ignore, ntend_ignore,
+      oqc, onc, nc_incld, mu_c, lamc, oP3_qc_sed, ntend_ignore,
       diagnostic_outputs.precip_liq_surf(i));
 
     // Rain sedimentation:  (adaptive substepping)
     rain_sedimentation(
       rho, inv_rho, rhofacr, ocld_frac_r, inv_dz, qr_incld, team, workspace,
       lookup_tables.vn_table_vals, lookup_tables.vm_table_vals, nk, ktop, kbot, kdir, infrastructure.dt, inv_dt, oqr,
-      onr, nr_incld, mu_r, lamr, oprecip_liq_flux, qtend_ignore, ntend_ignore,
+      onr, nr_incld, mu_r, lamr, oprecip_liq_flux, oP3_qr_sed, ntend_ignore,
       diagnostic_outputs.precip_liq_surf(i), runtime_options);
 
     // Ice sedimentation:  (adaptive substepping)
     ice_sedimentation(
       rho, inv_rho, rhofaci, ocld_frac_i, inv_dz, team, workspace, nk, ktop, kbot,
       kdir, infrastructure.dt, inv_dt, oqi, qi_incld, oni, ni_incld,
-      oqm, qm_incld, obm, bm_incld, qtend_ignore, ntend_ignore,
+      oqm, qm_incld, obm, bm_incld, oP3_qi_sed, ntend_ignore,
       lookup_tables.ice_table_vals, diagnostic_outputs.precip_ice_surf(i), runtime_options);
 
     // homogeneous freezing of cloud and rain
diff --git a/components/eamxx/src/physics/p3/impl/p3_main_impl_part2.hpp b/components/eamxx/src/physics/p3/impl/p3_main_impl_part2.hpp
index 3214549a3b65..466be61b7a88 100644
--- a/components/eamxx/src/physics/p3/impl/p3_main_impl_part2.hpp
+++ b/components/eamxx/src/physics/p3/impl/p3_main_impl_part2.hpp
@@ -89,6 +89,18 @@ ::p3_main_part2(
   const uview_1d<Spack>& vap_liq_exchange,
   const uview_1d<Spack>& vap_ice_exchange,
   const uview_1d<Spack>& liq_ice_exchange,
+  const uview_1d<Spack>& P3_qr2qv_evap,
+  const uview_1d<Spack>& P3_qi2qv_sublim,
+  const uview_1d<Spack>& P3_qc2qr_accret,
+  const uview_1d<Spack>& P3_qc2qr_autoconv,
+  const uview_1d<Spack>& P3_qv2qi_vapdep,
+  const uview_1d<Spack>& P3_qc2qi_berg,
+  const uview_1d<Spack>& P3_qc2qr_ice_shed,
+  const uview_1d<Spack>& P3_qc2qi_collect,
+  const uview_1d<Spack>& P3_qr2qi_collect,
+  const uview_1d<Spack>& P3_qc2qi_hetero_freeze,
+  const uview_1d<Spack>& P3_qr2qi_immers_freeze,
+  const uview_1d<Spack>& P3_qi2qr_melt,
   const uview_1d<Spack>& pratot,
   const uview_1d<Spack>& prctot,
   bool& hydrometeorsPresent, const Int& nk,
@@ -469,6 +481,20 @@ ::p3_main_part2(
     vap_liq_exchange(k).set(not_skip_all, -qr2qv_evap_tend);
     liq_ice_exchange(k).set(not_skip_all, qc2qi_hetero_freeze_tend + qr2qi_immers_freeze_tend - qi2qr_melt_tend + qc2qi_berg_tend + qc2qi_collect_tend + qr2qi_collect_tend);
 
+   // set tendencies
+    P3_qr2qv_evap(k).set(not_skip_all, qr2qv_evap_tend);
+    P3_qi2qv_sublim(k).set(not_skip_all, qi2qv_sublim_tend);
+    P3_qc2qr_accret(k).set(not_skip_all, qc2qr_accret_tend);
+    P3_qc2qr_autoconv(k).set(not_skip_all, qc2qr_autoconv_tend);
+    P3_qv2qi_vapdep(k).set(not_skip_all, qv2qi_vapdep_tend);
+    P3_qc2qi_berg(k).set(not_skip_all, qc2qi_berg_tend);
+    P3_qc2qr_ice_shed(k).set(not_skip_all, qc2qr_ice_shed_tend);
+    P3_qc2qi_collect(k).set(not_skip_all, qc2qi_collect_tend);
+    P3_qr2qi_collect(k).set(not_skip_all, qr2qi_collect_tend);
+    P3_qc2qi_hetero_freeze(k).set(not_skip_all, qc2qi_hetero_freeze_tend);
+    P3_qr2qi_immers_freeze(k).set(not_skip_all, qr2qi_immers_freeze_tend);
+    P3_qi2qr_melt(k).set(not_skip_all, qi2qr_melt_tend);
+
     // clipping for small hydrometeor values
     const auto qc_small    = qc(k) < qsmall    && not_skip_all;
     const auto qr_small    = qr(k) < qsmall    && not_skip_all;
diff --git a/components/eamxx/src/physics/p3/p3_functions.hpp b/components/eamxx/src/physics/p3/p3_functions.hpp
index f91c08da93c3..1739c9729d97 100644
--- a/components/eamxx/src/physics/p3/p3_functions.hpp
+++ b/components/eamxx/src/physics/p3/p3_functions.hpp
@@ -134,6 +134,7 @@ struct Functions
     bool set_cld_frac_l_to_one = false;
     bool set_cld_frac_i_to_one = false;
     bool set_cld_frac_r_to_one = false;
+    bool p3_extra_diags = false;
 
     void load_runtime_options_from_file(ekat::ParameterList& params) {
       max_total_ni = params.get<double>("max_total_ni", max_total_ni);
@@ -159,6 +160,7 @@ struct Functions
       set_cld_frac_l_to_one = params.get<bool>("set_cld_frac_l_to_one", set_cld_frac_l_to_one);
       set_cld_frac_i_to_one = params.get<bool>("set_cld_frac_i_to_one", set_cld_frac_i_to_one);
       set_cld_frac_r_to_one = params.get<bool>("set_cld_frac_r_to_one", set_cld_frac_r_to_one);
+      p3_extra_diags = params.get<bool>("p3_extra_diags", p3_extra_diags);
     }
 
   };
@@ -279,6 +281,22 @@ struct Functions
     view_2d<Spack> vap_liq_exchange;
     // Sum of vap-ice phase change tendencies
     view_2d<Spack> vap_ice_exchange;
+    // Some diags
+    view_2d<Spack> P3_qr2qv_evap;
+    view_2d<Spack> P3_qi2qv_sublim;
+    view_2d<Spack> P3_qc2qr_accret;
+    view_2d<Spack> P3_qc2qr_autoconv; 
+    view_2d<Spack> P3_qv2qi_vapdep;
+    view_2d<Spack> P3_qc2qi_berg;
+    view_2d<Spack> P3_qc2qr_ice_shed;
+    view_2d<Spack> P3_qc2qi_collect;
+    view_2d<Spack> P3_qr2qi_collect;
+    view_2d<Spack> P3_qc2qi_hetero_freeze;
+    view_2d<Spack> P3_qr2qi_immers_freeze;
+    view_2d<Spack> P3_qi2qr_melt;
+    view_2d<Spack> P3_qr_sed;
+    view_2d<Spack> P3_qc_sed;
+    view_2d<Spack> P3_qi_sed;
   };
 
   // This struct stores kokkos views for the lookup tables needed in p3_main()
@@ -1191,6 +1209,18 @@ struct Functions
     const uview_1d<Spack>& vap_liq_exchange,
     const uview_1d<Spack>& vap_ice_exchange,
     const uview_1d<Spack>& liq_ice_exchange,
+    const uview_1d<Spack>& P3_qr2qv_evap,
+    const uview_1d<Spack>& P3_qi2qv_sublim,
+    const uview_1d<Spack>& P3_qc2qr_accret,
+    const uview_1d<Spack>& P3_qc2qr_autoconv,
+    const uview_1d<Spack>& P3_qv2qi_vapdep,
+    const uview_1d<Spack>& P3_qc2qi_berg,
+    const uview_1d<Spack>& P3_qc2qr_ice_shed,
+    const uview_1d<Spack>& P3_qc2qi_collect,
+    const uview_1d<Spack>& P3_qr2qi_collect,
+    const uview_1d<Spack>& P3_qc2qi_hetero_freeze,
+    const uview_1d<Spack>& P3_qr2qi_immers_freeze,
+    const uview_1d<Spack>& P3_qi2qr_melt,
     const uview_1d<Spack>& pratot,
     const uview_1d<Spack>& prctot,
     bool& is_hydromet_present,
@@ -1269,6 +1299,18 @@ struct Functions
     const uview_2d<Spack>& vap_liq_exchange,
     const uview_2d<Spack>& vap_ice_exchange,
     const uview_2d<Spack>& liq_ice_exchange,
+    const uview_2d<Spack>& P3_qr2qv_evap,
+    const uview_2d<Spack>& P3_qi2qv_sublim,
+    const uview_2d<Spack>& P3_qc2qr_accret,
+    const uview_2d<Spack>& P3_qc2qr_autoconv,
+    const uview_2d<Spack>& P3_qv2qi_vapdep,
+    const uview_2d<Spack>& P3_qc2qi_berg,
+    const uview_2d<Spack>& P3_qc2qr_ice_shed,
+    const uview_2d<Spack>& P3_qc2qi_collect,
+    const uview_2d<Spack>& P3_qr2qi_collect,
+    const uview_2d<Spack>& P3_qc2qi_hetero_freeze,
+    const uview_2d<Spack>& P3_qr2qi_immers_freeze,
+    const uview_2d<Spack>& P3_qi2qr_melt,
     const uview_2d<Spack>& pratot,
     const uview_2d<Spack>& prctot,
     const uview_1d<bool>& is_nucleat_possible,
diff --git a/components/eamxx/src/physics/p3/tests/infra/p3_data.cpp b/components/eamxx/src/physics/p3/tests/infra/p3_data.cpp
index 24fd6529f22d..f72d69f44087 100644
--- a/components/eamxx/src/physics/p3/tests/infra/p3_data.cpp
+++ b/components/eamxx/src/physics/p3/tests/infra/p3_data.cpp
@@ -54,6 +54,21 @@ P3Data::P3Data (Int ncol_, Int nlev_)
   liq_ice_exchange   = Array2("sum of liq-ice phase change tendenices", ncol, nlev);
   vap_liq_exchange   = Array2("sum of vap-liq phase change tendenices", ncol, nlev);
   vap_ice_exchange   = Array2("sum of vap-ice phase change tendenices", ncol, nlev);
+  P3_qr2qv_evap     = Array2("Rain evaporation to vapor", ncol, nlev);
+  P3_qi2qv_sublim   = Array2("Ice sublimation to vapor", ncol, nlev);
+  P3_qc2qr_accret   = Array2("Cloud water accretion to rain", ncol, nlev);
+  P3_qc2qr_autoconv = Array2("Cloud water autoconversion to rain", ncol, nlev);
+  P3_qv2qi_vapdep   = Array2("Vapor deposition to ice", ncol, nlev);
+  P3_qc2qi_berg     = Array2("Cloud water to ice (Bergeron)", ncol, nlev);
+  P3_qc2qr_ice_shed = Array2("Cloud water to rain (autoconversion)", ncol, nlev);
+  P3_qc2qi_collect  = Array2("Cloud water to ice (collection)", ncol, nlev);
+  P3_qr2qi_collect  = Array2("Rain to ice (collection)", ncol, nlev);
+  P3_qc2qi_hetero_freeze = Array2("Cloud water to ice (heterogeneous freezing)", ncol, nlev);
+  P3_qr2qi_immers_freeze = Array2("Rain to ice (immersion freezing)", ncol, nlev);
+  P3_qi2qr_melt    = Array2("Ice to rain (melting)", ncol, nlev);
+  P3_qc_sed = Array2("Cloud water sedimentation", ncol, nlev);
+  P3_qi_sed = Array2("Ice sedimentation", ncol, nlev);
+  P3_qr_sed = Array2("Rain sedimentation", ncol, nlev);
 }
 
 P3DataIterator::P3DataIterator (const P3Data::Ptr& d) {
@@ -78,6 +93,7 @@ void P3DataIterator::init (const P3Data::Ptr& dp) {
   fdipb(cld_frac_r); fdipb(cld_frac_l); fdipb(cld_frac_i);
   fdipb(liq_ice_exchange); fdipb(vap_liq_exchange);
   fdipb(vap_ice_exchange); fdipb(qv_prev); fdipb(t_prev);;
+  fdipb(P3_qr2qv_evap); fdipb(P3_qi2qv_sublim); fdipb(P3_qc2qr_accret); fdipb(P3_qc2qr_autoconv); fdipb(P3_qv2qi_vapdep); fdipb(P3_qc2qi_berg); fdipb(P3_qc2qr_ice_shed); fdipb(P3_qc2qi_collect); fdipb(P3_qr2qi_collect); fdipb(P3_qc2qi_hetero_freeze); fdipb(P3_qr2qi_immers_freeze); fdipb(P3_qi2qr_melt); fdipb(P3_qr_sed); fdipb(P3_qc_sed); fdipb(P3_qi_sed);
 #undef fdipb
 }
 
diff --git a/components/eamxx/src/physics/p3/tests/infra/p3_data.hpp b/components/eamxx/src/physics/p3/tests/infra/p3_data.hpp
index 55e74300215c..3a1a0df1c0fc 100644
--- a/components/eamxx/src/physics/p3/tests/infra/p3_data.hpp
+++ b/components/eamxx/src/physics/p3/tests/infra/p3_data.hpp
@@ -35,6 +35,7 @@ struct P3Data {
          precip_liq_flux, precip_ice_flux, cld_frac_r, cld_frac_l, cld_frac_i;
   Array3 p3_tend_out;
   Array2 liq_ice_exchange,vap_liq_exchange,vap_ice_exchange;
+  Array2 P3_qr2qv_evap, P3_qi2qv_sublim, P3_qc2qr_accret, P3_qc2qr_autoconv, P3_qv2qi_vapdep, P3_qc2qi_berg, P3_qc2qr_ice_shed, P3_qc2qi_collect, P3_qr2qi_collect, P3_qc2qi_hetero_freeze, P3_qr2qi_immers_freeze, P3_qi2qr_melt, P3_qr_sed, P3_qc_sed, P3_qi_sed;
 
   P3Data(Int ncol, Int nlev);
 };
diff --git a/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.cpp b/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.cpp
index d4faa4c70527..3fef62a84bb1 100644
--- a/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.cpp
+++ b/components/eamxx/src/physics/p3/tests/infra/p3_main_wrap.cpp
@@ -24,7 +24,9 @@ Int p3_main_wrap(const P3Data& d) {
                       d.precip_liq_flux.data(), d.precip_ice_flux.data(),
                       d.cld_frac_r.data(), d.cld_frac_l.data(), d.cld_frac_i.data(),
                       d.liq_ice_exchange.data(), d.vap_liq_exchange.data(),
-                      d.vap_ice_exchange.data(),d.qv_prev.data(),d.t_prev.data() );
+                      d.vap_ice_exchange.data(),
+                      d.P3_qr2qv_evap.data(), d.P3_qi2qv_sublim.data(), d.P3_qc2qr_accret.data(), d.P3_qc2qr_autoconv.data(), d.P3_qv2qi_vapdep.data(), d.P3_qc2qi_berg.data(), d.P3_qc2qr_ice_shed.data(), d.P3_qc2qi_collect.data(), d.P3_qr2qi_collect.data(), d.P3_qc2qi_hetero_freeze.data(), d.P3_qr2qi_immers_freeze.data(), d.P3_qi2qr_melt.data(), d.P3_qr_sed.data(), d.P3_qc_sed.data(), d.P3_qi_sed.data(),
+                      d.qv_prev.data(),d.t_prev.data() );
 }
 
 int test_p3_init () {
diff --git a/components/eamxx/src/physics/p3/tests/infra/p3_test_data.cpp b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.cpp
index 2dff7183ec61..8d197d2da0bf 100644
--- a/components/eamxx/src/physics/p3/tests/infra/p3_test_data.cpp
+++ b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.cpp
@@ -166,7 +166,9 @@ P3MainPart2Data::P3MainPart2Data(
     &qv, &th_atm, &qc, &nc, &qr, &nr, &qi, &ni, &qm, &bm, &latent_heat_vapor, &latent_heat_sublim, &latent_heat_fusion, &qc_incld, &qr_incld,
     &qi_incld, &qm_incld, &nc_incld, &nr_incld, &ni_incld, &bm_incld, &mu_c, &nu, &lamc, &cdist, &cdist1,
     &cdistr, &mu_r, &lamr, &logn0r, &qv2qi_depos_tend, &precip_total_tend, &nevapr, &qr_evap_tend, &vap_liq_exchange,
-    &vap_ice_exchange, &liq_ice_exchange, &pratot, &prctot} }),
+    &vap_ice_exchange, &liq_ice_exchange,
+    &P3_qr2qv_evap, &P3_qi2qv_sublim, &P3_qc2qr_accret, &P3_qc2qr_autoconv, &P3_qv2qi_vapdep, &P3_qc2qi_berg, &P3_qc2qr_ice_shed, &P3_qc2qi_collect, &P3_qr2qi_collect, &P3_qc2qi_hetero_freeze, &P3_qr2qi_immers_freeze, &P3_qi2qr_melt,
+    &pratot, &prctot} }),
   kts(kts_), kte(kte_), kbot(kbot_), ktop(ktop_), kdir(kdir_),
   do_predict_nc(do_predict_nc_), do_prescribed_CCN(do_prescribed_CCN_), dt(dt_), inv_dt(1 / dt)
 {}
@@ -194,7 +196,9 @@ P3MainData::P3MainData(
     &pres, &dz, &nc_nuceat_tend, &nccn_prescribed, &ni_activated, &dpres, &inv_exner, &cld_frac_i, &cld_frac_l, &cld_frac_r,
     &inv_qc_relvar, &qc, &nc, &qr, &nr, &qi, &qm, &ni, &bm, &qv, &th_atm, &qv_prev, &t_prev,
     &diag_eff_radius_qc, &diag_eff_radius_qi, &diag_eff_radius_qr, &rho_qi, &mu_c, &lamc, &qv2qi_depos_tend, &precip_total_tend, &nevapr,
-    &qr_evap_tend, &liq_ice_exchange, &vap_liq_exchange, &vap_ice_exchange, &precip_liq_flux,
+    &qr_evap_tend, &liq_ice_exchange,
+    &P3_qr2qv_evap, &P3_qi2qv_sublim, &P3_qc2qr_accret, &P3_qc2qr_autoconv, &P3_qv2qi_vapdep, &P3_qc2qi_berg, &P3_qc2qr_ice_shed, &P3_qc2qi_collect, &P3_qr2qi_collect, &P3_qc2qi_hetero_freeze, &P3_qr2qi_immers_freeze, &P3_qi2qr_melt, &P3_qr_sed, &P3_qc_sed, &P3_qi_sed,
+    &vap_liq_exchange, &vap_ice_exchange, &precip_liq_flux,
     &precip_ice_flux},
     {&precip_liq_surf, &precip_ice_surf} }), // these two are (ni, nk+1)
   its(its_), ite(ite_), kts(kts_), kte(kte_), it(it_), dt(dt_), do_predict_nc(do_predict_nc_), do_prescribed_CCN(do_prescribed_CCN_)
@@ -953,7 +957,9 @@ void p3_main_part2_host(
   Real* acn, Real* qv, Real* th_atm, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni,
   Real* qm, Real* bm, Real* qc_incld, Real* qr_incld, Real* qi_incld, Real* qm_incld, Real* nc_incld, Real* nr_incld,
   Real* ni_incld, Real* bm_incld, Real* mu_c, Real* nu, Real* lamc, Real* cdist, Real* cdist1, Real* cdistr, Real* mu_r, Real* lamr, Real* logn0r, Real* qv2qi_depos_tend, Real* precip_total_tend,
-  Real* nevapr, Real* qr_evap_tend, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* liq_ice_exchange, Real* pratot,
+  Real* nevapr, Real* qr_evap_tend, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* liq_ice_exchange,
+  Real* P3_qr2qv_evap, Real* P3_qi2qv_sublim, Real* P3_qc2qr_accret, Real* P3_qc2qr_autoconv, Real* P3_qv2qi_vapdep, Real* P3_qc2qi_berg, Real* P3_qc2qr_ice_shed, Real* P3_qc2qi_collect, Real* P3_qr2qi_collect, Real* P3_qc2qi_hetero_freeze, Real* P3_qr2qi_immers_freeze, Real* P3_qi2qr_melt,
+  Real* pratot,
   Real* prctot, bool* is_hydromet_present)
 {
   using P3F  = Functions<Real, DefaultDevice>;
@@ -985,7 +991,9 @@ void p3_main_part2_host(
         qv, th_atm, qc, nc, qr, nr, qi, ni, qm, bm, qc_incld, qr_incld,
         qi_incld, qm_incld, nc_incld, nr_incld, ni_incld, bm_incld, mu_c, nu, lamc, cdist, cdist1,
         cdistr, mu_r, lamr, logn0r, qv2qi_depos_tend, precip_total_tend, nevapr, qr_evap_tend, vap_liq_exchange,
-        vap_ice_exchange, liq_ice_exchange, pratot, prctot, qv_prev, t_prev
+        vap_ice_exchange, liq_ice_exchange,
+        P3_qr2qv_evap, P3_qi2qv_sublim, P3_qc2qr_accret, P3_qc2qr_autoconv, P3_qv2qi_vapdep, P3_qc2qi_berg, P3_qc2qr_ice_shed, P3_qc2qi_collect, P3_qr2qi_collect, P3_qc2qi_hetero_freeze, P3_qr2qi_immers_freeze, P3_qi2qr_melt,
+        pratot, prctot, qv_prev, t_prev
         },
     nk, temp_d);
 
@@ -1048,6 +1056,18 @@ void p3_main_part2_host(
     vap_liq_exchange_d  (temp_d[current_index++]),
     vap_ice_exchange_d  (temp_d[current_index++]),
     liq_ice_exchange_d  (temp_d[current_index++]),
+    P3_qr2qv_evap_d     (temp_d[current_index++]),
+    P3_qi2qv_sublim_d   (temp_d[current_index++]),
+    P3_qc2qr_accret_d   (temp_d[current_index++]),
+    P3_qc2qr_autoconv_d (temp_d[current_index++]),
+    P3_qv2qi_vapdep_d   (temp_d[current_index++]),
+    P3_qc2qi_berg_d     (temp_d[current_index++]),
+    P3_qc2qr_ice_shed_d (temp_d[current_index++]),
+    P3_qc2qi_collect_d  (temp_d[current_index++]),
+    P3_qr2qi_collect_d  (temp_d[current_index++]),
+    P3_qc2qi_hetero_freeze_d (temp_d[current_index++]),
+    P3_qr2qi_immers_freeze_d (temp_d[current_index++]),
+    P3_qi2qr_melt_d     (temp_d[current_index++]),
     pratot_d            (temp_d[current_index++]),
     prctot_d            (temp_d[current_index++]),
     qv_prev_d           (temp_d[current_index++]),
@@ -1073,7 +1093,11 @@ void p3_main_part2_host(
       qm_incld_d, nc_incld_d, nr_incld_d, ni_incld_d, bm_incld_d,
       mu_c_d, nu_d, lamc_d, cdist_d, cdist1_d, cdistr_d, mu_r_d, lamr_d,
       logn0r_d, qv2qi_depos_tend_d, precip_total_tend_d, nevapr_d, qr_evap_tend_d, vap_liq_exchange_d,
-      vap_ice_exchange_d, liq_ice_exchange_d, pratot_d, prctot_d, bools_d(0),nk, P3F::P3Runtime());
+      vap_ice_exchange_d, liq_ice_exchange_d,
+      P3_qr2qv_evap_d, P3_qi2qv_sublim_d, P3_qc2qr_accret_d, P3_qc2qr_autoconv_d, P3_qv2qi_vapdep_d,
+      P3_qc2qi_berg_d, P3_qc2qr_ice_shed_d, P3_qc2qi_collect_d, P3_qr2qi_collect_d, P3_qc2qi_hetero_freeze_d,
+      P3_qr2qi_immers_freeze_d, P3_qi2qr_melt_d,
+      pratot_d, prctot_d, bools_d(0),nk, P3F::P3Runtime());
   });
 
   // Sync back to host. Skip intent in variables.
@@ -1084,7 +1108,11 @@ void p3_main_part2_host(
     nc_incld_d, nr_incld_d, ni_incld_d, bm_incld_d, mu_c_d, nu_d, lamc_d,
     cdist_d, cdist1_d, cdistr_d, mu_r_d, lamr_d, logn0r_d, qv2qi_depos_tend_d, precip_total_tend_d,
     nevapr_d, qr_evap_tend_d, vap_liq_exchange_d, vap_ice_exchange_d,
-    liq_ice_exchange_d, pratot_d, prctot_d
+    liq_ice_exchange_d, 
+    P3_qr2qv_evap_d, P3_qi2qv_sublim_d, P3_qc2qr_accret_d, P3_qc2qr_autoconv_d, P3_qv2qi_vapdep_d,
+    P3_qc2qi_berg_d, P3_qc2qr_ice_shed_d, P3_qc2qi_collect_d, P3_qr2qi_collect_d, P3_qc2qi_hetero_freeze_d,
+    P3_qr2qi_immers_freeze_d, P3_qi2qr_melt_d,
+    pratot_d, prctot_d
   };
 
   ekat::device_to_host({
@@ -1093,6 +1121,9 @@ void p3_main_part2_host(
       qi_incld, qm_incld, nc_incld, nr_incld, ni_incld, bm_incld,
       mu_c, nu, lamc, cdist, cdist1, cdistr, mu_r, lamr, logn0r, qv2qi_depos_tend, precip_total_tend,
       nevapr, qr_evap_tend, vap_liq_exchange, vap_ice_exchange, liq_ice_exchange,
+      P3_qr2qv_evap, P3_qi2qv_sublim, P3_qc2qr_accret, P3_qc2qr_autoconv, P3_qv2qi_vapdep,
+      P3_qc2qi_berg, P3_qc2qr_ice_shed, P3_qc2qi_collect, P3_qr2qi_collect, P3_qc2qi_hetero_freeze,
+      P3_qr2qi_immers_freeze, P3_qi2qr_melt,
       pratot, prctot},
     nk, inout_views);
 
@@ -1218,7 +1249,9 @@ Int p3_main_host(
   Real* precip_ice_surf, Int its, Int ite, Int kts, Int kte, Real* diag_eff_radius_qc,
   Real* diag_eff_radius_qi, Real* diag_eff_radius_qr, Real* rho_qi, bool do_predict_nc, bool do_prescribed_CCN, Real* dpres, Real* inv_exner,
   Real* qv2qi_depos_tend, Real* precip_liq_flux, Real* precip_ice_flux, Real* cld_frac_r, Real* cld_frac_l, Real* cld_frac_i,
-  Real* liq_ice_exchange, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* qv_prev, Real* t_prev)
+  Real* liq_ice_exchange, Real* vap_liq_exchange, Real* vap_ice_exchange, 
+  Real* P3_qr2qv_evap, Real* P3_qi2qv_sublim, Real* P3_qc2qr_accret, Real* P3_qc2qr_autoconv, Real* P3_qv2qi_vapdep, Real* P3_qc2qi_berg, Real* P3_qc2qr_ice_shed, Real* P3_qc2qi_collect, Real* P3_qr2qi_collect, Real* P3_qc2qi_hetero_freeze, Real* P3_qr2qi_immers_freeze, Real* P3_qi2qr_melt, Real* P3_qr_sed, Real* P3_qc_sed, Real* P3_qi_sed,
+  Real* qv_prev, Real* t_prev)
 {
   using P3F  = Functions<Real, DefaultDevice>;
 
@@ -1248,7 +1281,9 @@ Int p3_main_host(
     pres, dz, nc_nuceat_tend, nccn_prescribed, ni_activated, dpres, inv_exner, cld_frac_i, cld_frac_l, cld_frac_r, inv_qc_relvar,
     qc, nc, qr, nr, qi, qm, ni, bm, qv, th_atm, qv_prev, t_prev, diag_eff_radius_qc, diag_eff_radius_qi, diag_eff_radius_qr,
     rho_qi, qv2qi_depos_tend,
-    liq_ice_exchange, vap_liq_exchange, vap_ice_exchange, precip_liq_flux, precip_ice_flux, precip_liq_surf, precip_ice_surf
+    liq_ice_exchange, vap_liq_exchange, vap_ice_exchange, 
+    P3_qr2qv_evap, P3_qi2qv_sublim, P3_qc2qr_accret, P3_qc2qr_autoconv, P3_qv2qi_vapdep, P3_qc2qi_berg, P3_qc2qr_ice_shed, P3_qc2qi_collect, P3_qr2qi_collect, P3_qc2qi_hetero_freeze, P3_qr2qi_immers_freeze, P3_qi2qr_melt, P3_qr_sed, P3_qc_sed, P3_qi_sed,
+    precip_liq_flux, precip_ice_flux, precip_liq_surf, precip_ice_surf
   };
 
   int dim_sizes_len = dim1_sizes.size();
@@ -1299,6 +1334,21 @@ Int p3_main_host(
     liq_ice_exchange_d     (temp_d[counter++]),
     vap_liq_exchange_d     (temp_d[counter++]),
     vap_ice_exchange_d     (temp_d[counter++]), //30
+    P3_qr2qv_evap_d           (temp_d[counter++]), //35
+    P3_qi2qv_sublim_d         (temp_d[counter++]),
+    P3_qc2qr_accret_d         (temp_d[counter++]),
+    P3_qc2qr_autoconv_d       (temp_d[counter++]),
+    P3_qv2qi_vapdep_d         (temp_d[counter++]),
+    P3_qc2qi_berg_d           (temp_d[counter++]), //40
+    P3_qc2qr_ice_shed_d       (temp_d[counter++]),
+    P3_qc2qi_collect_d        (temp_d[counter++]),
+    P3_qr2qi_collect_d        (temp_d[counter++]),
+    P3_qc2qi_hetero_freeze_d  (temp_d[counter++]),
+    P3_qr2qi_immers_freeze_d  (temp_d[counter++]), //45
+    P3_qi2qr_melt_d           (temp_d[counter++]), //46
+    P3_qr_sed_d               (temp_d[counter++]),
+    P3_qc_sed_d               (temp_d[counter++]),
+    P3_qi_sed_d               (temp_d[counter++]), //49
     precip_liq_flux_d      (temp_d[counter++]),
     precip_ice_flux_d      (temp_d[counter++]),
     precip_liq_surf_temp_d (temp_d[counter++]),
@@ -1335,7 +1385,11 @@ Int p3_main_host(
   P3F::P3Infrastructure infrastructure{dt, it, its, ite, kts, kte,
                                        do_predict_nc, do_prescribed_CCN, col_location_d};
   P3F::P3HistoryOnly history_only{liq_ice_exchange_d, vap_liq_exchange_d,
-                                  vap_ice_exchange_d};
+                                  vap_ice_exchange_d,
+                                  P3_qr2qv_evap_d, P3_qi2qv_sublim_d, P3_qc2qr_accret_d, P3_qc2qr_autoconv_d, P3_qv2qi_vapdep_d,
+                                  P3_qc2qi_berg_d, P3_qc2qr_ice_shed_d, P3_qc2qi_collect_d, P3_qr2qi_collect_d, P3_qc2qi_hetero_freeze_d,
+                                  P3_qr2qi_immers_freeze_d, P3_qi2qr_melt_d, P3_qr_sed_d, P3_qc_sed_d, P3_qi_sed_d
+                                  };
 
   const Int nk_pack = ekat::npack<Spack>(nk);
 #ifdef SCREAM_P3_SMALL_KERNELS
@@ -1393,6 +1447,9 @@ Int p3_main_host(
     diag_eff_radius_qc_d, diag_eff_radius_qi_d, diag_eff_radius_qr_d, rho_qi_d,
     qv2qi_depos_tend_d,
     liq_ice_exchange_d, vap_liq_exchange_d, vap_ice_exchange_d,
+    P3_qr2qv_evap_d, P3_qi2qv_sublim_d, P3_qc2qr_accret_d, P3_qc2qr_autoconv_d, P3_qv2qi_vapdep_d,
+    P3_qc2qi_berg_d, P3_qc2qr_ice_shed_d, P3_qc2qi_collect_d, P3_qr2qi_collect_d, P3_qc2qi_hetero_freeze_d,
+    P3_qr2qi_immers_freeze_d, P3_qi2qr_melt_d, P3_qr_sed_d, P3_qc_sed_d, P3_qi_sed_d,
     precip_liq_flux_d, precip_ice_flux_d, precip_liq_surf_temp_d, precip_ice_surf_temp_d
   };
   std::vector<size_t> dim1_sizes_out(P3MainData::NUM_ARRAYS - 13, nj);
@@ -1406,7 +1463,11 @@ Int p3_main_host(
   ekat::device_to_host({
       qc, nc, qr, nr, qi, qm, ni, bm, qv, th_atm, diag_eff_radius_qc, diag_eff_radius_qi, diag_eff_radius_qr,
       rho_qi, qv2qi_depos_tend,
-      liq_ice_exchange, vap_liq_exchange, vap_ice_exchange, precip_liq_flux, precip_ice_flux, precip_liq_surf, precip_ice_surf
+      liq_ice_exchange, vap_liq_exchange, vap_ice_exchange,
+      P3_qr2qv_evap, P3_qi2qv_sublim, P3_qc2qr_accret, P3_qc2qr_autoconv, P3_qv2qi_vapdep,
+      P3_qc2qi_berg, P3_qc2qr_ice_shed, P3_qc2qi_collect, P3_qr2qi_collect, P3_qc2qi_hetero_freeze,
+      P3_qr2qi_immers_freeze, P3_qi2qr_melt, P3_qr_sed, P3_qc_sed, P3_qi_sed,
+      precip_liq_flux, precip_ice_flux, precip_liq_surf, precip_ice_surf
     },
     dim1_sizes_out, dim2_sizes_out, inout_views);
 
diff --git a/components/eamxx/src/physics/p3/tests/infra/p3_test_data.hpp b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.hpp
index 775120e080dc..22f5a13f1070 100644
--- a/components/eamxx/src/physics/p3/tests/infra/p3_test_data.hpp
+++ b/components/eamxx/src/physics/p3/tests/infra/p3_test_data.hpp
@@ -679,7 +679,7 @@ struct P3MainPart1Data : public PhysicsTestData
 
 struct P3MainPart2Data : public PhysicsTestData
 {
-  static constexpr size_t NUM_ARRAYS = 64;
+  static constexpr size_t NUM_ARRAYS = 76;
 
   // Inputs
   Int kts, kte, kbot, ktop, kdir;
@@ -692,7 +692,9 @@ struct P3MainPart2Data : public PhysicsTestData
     *qv, *th_atm, *qc, *nc, *qr, *nr, *qi, *ni, *qm, *bm, *latent_heat_vapor, *latent_heat_sublim, *latent_heat_fusion, *qc_incld, *qr_incld,
     *qi_incld, *qm_incld, *nc_incld, *nr_incld, *ni_incld, *bm_incld, *mu_c, *nu, *lamc, *cdist, *cdist1,
     *cdistr, *mu_r, *lamr, *logn0r, *qv2qi_depos_tend, *precip_total_tend, *nevapr, *qr_evap_tend, *vap_liq_exchange,
-    *vap_ice_exchange, *liq_ice_exchange, *pratot, *prctot;
+    *vap_ice_exchange, *liq_ice_exchange, 
+    *P3_qr2qv_evap, *P3_qi2qv_sublim, *P3_qc2qr_accret, *P3_qc2qr_autoconv, *P3_qv2qi_vapdep, *P3_qc2qi_berg, *P3_qc2qr_ice_shed, *P3_qc2qi_collect, *P3_qr2qi_collect, *P3_qc2qi_hetero_freeze, *P3_qr2qi_immers_freeze, *P3_qi2qr_melt,
+    *pratot, *prctot;
 
   bool is_hydromet_present;
 
@@ -708,7 +710,7 @@ struct P3MainPart2Data : public PhysicsTestData
 
 struct P3MainPart3Data : public PhysicsTestData
 {
-  static constexpr size_t NUM_ARRAYS = 34;
+  static constexpr size_t NUM_ARRAYS = 47;
 
   // Inputs
   Int kts, kte, kbot, ktop, kdir;
@@ -733,7 +735,7 @@ struct P3MainPart3Data : public PhysicsTestData
 
 struct P3MainData : public PhysicsTestData
 {
-  static constexpr size_t NUM_ARRAYS = 35;
+  static constexpr size_t NUM_ARRAYS = 50;
   static constexpr size_t NUM_INPUT_ARRAYS = 24;
 
   // Inputs
@@ -748,6 +750,7 @@ struct P3MainData : public PhysicsTestData
   // Out
   Real *diag_eff_radius_qc, *diag_eff_radius_qi, *diag_eff_radius_qr, *rho_qi, *mu_c, *lamc, *qv2qi_depos_tend, *precip_total_tend, *nevapr,
        *qr_evap_tend, *liq_ice_exchange, *vap_liq_exchange, *vap_ice_exchange,
+       *P3_qr2qv_evap, *P3_qi2qv_sublim, *P3_qc2qr_accret, *P3_qc2qr_autoconv, *P3_qv2qi_vapdep, *P3_qc2qi_berg, *P3_qc2qr_ice_shed, *P3_qc2qi_collect, *P3_qr2qi_collect, *P3_qc2qi_hetero_freeze, *P3_qr2qi_immers_freeze, *P3_qi2qr_melt, *P3_qr_sed, *P3_qc_sed, *P3_qi_sed,
        *precip_liq_flux, *precip_ice_flux, *precip_liq_surf, *precip_ice_surf;
   Real elapsed_s;
 
@@ -875,7 +878,9 @@ void p3_main_part2_host(
   Real* T_atm, Real* rho, Real* inv_rho, Real* qv_sat_l, Real* qv_sat_i, Real* qv_supersat_i, Real* rhofacr, Real* rhofaci, Real* acn, Real* qv, Real* th_atm, Real* qc, Real* nc, Real* qr, Real* nr, Real* qi, Real* ni,
   Real* qm, Real* bm, Real* qc_incld, Real* qr_incld, Real* qi_incld, Real* qm_incld, Real* nc_incld, Real* nr_incld,
   Real* ni_incld, Real* bm_incld, Real* mu_c, Real* nu, Real* lamc, Real* cdist, Real* cdist1, Real* cdistr, Real* mu_r, Real* lamr, Real* logn0r, Real* qv2qi_depos_tend, Real* precip_total_tend,
-  Real* nevapr, Real* qr_evap_tend, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* liq_ice_exchange, Real* pratot,
+  Real* nevapr, Real* qr_evap_tend, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* liq_ice_exchange, 
+  Real* P3_qr2qv_evap, Real* P3_qi2qv_sublim, Real* P3_qc2qr_accret, Real* P3_qc2qr_autoconv, Real* P3_qv2qi_vapdep, Real* P3_qc2qi_berg, Real* P3_qc2qr_ice_shed, Real* P3_qc2qi_collect, Real* P3_qr2qi_collect, Real* P3_qc2qi_hetero_freeze, Real* P3_qr2qi_immers_freeze, Real* P3_qi2qr_melt,
+  Real* pratot,
   Real* prctot, bool* is_hydromet_present);
 
 void p3_main_part3_host(
@@ -892,7 +897,9 @@ Int p3_main_host(
   Real* precip_ice_surf, Int its, Int ite, Int kts, Int kte, Real* diag_eff_radius_qc,
   Real* diag_eff_radius_qi, Real* diag_eff_radius_qr, Real* rho_qi, bool do_predict_nc, bool do_prescribed_CCN, Real* dpres, Real* inv_exner,
   Real* qv2qi_depos_tend, Real* precip_liq_flux, Real* precip_ice_flux, Real* cld_frac_r, Real* cld_frac_l, Real* cld_frac_i,
-  Real* liq_ice_exchange, Real* vap_liq_exchange, Real* vap_ice_exchange, Real* qv_prev, Real* t_prev);
+  Real* liq_ice_exchange, Real* vap_liq_exchange, Real* vap_ice_exchange,
+  Real* P3_qr2qv_evap, Real* P3_qi2qv_sublim, Real* P3_qc2qr_accret, Real* P3_qc2qr_autoconv, Real* P3_qv2qi_vapdep, Real* P3_qc2qi_berg, Real* P3_qc2qr_ice_shed, Real* P3_qc2qi_collect, Real* P3_qr2qi_collect, Real* P3_qc2qi_hetero_freeze, Real* P3_qr2qi_immers_freeze, Real* P3_qi2qr_melt, Real* P3_qr_sed, Real* P3_qc_sed, Real* P3_qi_sed,
+  Real* qv_prev, Real* t_prev);
 
 }  // namespace p3
 }  // namespace scream
diff --git a/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp
index c60efd2b8824..8f318ee2bad3 100644
--- a/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp
+++ b/components/eamxx/src/physics/p3/tests/p3_main_unit_tests.cpp
@@ -219,7 +219,9 @@ void run_bfb_p3_main_part2()
       d.T_atm, d.rho, d.inv_rho, d.qv_sat_l, d.qv_sat_i, d.qv_supersat_i, d.rhofacr, d.rhofaci, d.acn, d.qv, d.th_atm, d.qc, d.nc, d.qr, d.nr, d.qi, d.ni,
       d.qm, d.bm, d.qc_incld, d.qr_incld, d.qi_incld, d.qm_incld, d.nc_incld, d.nr_incld,
       d.ni_incld, d.bm_incld, d.mu_c, d.nu, d.lamc, d.cdist, d.cdist1, d.cdistr, d.mu_r, d.lamr, d.logn0r, d.qv2qi_depos_tend, d.precip_total_tend,
-      d.nevapr, d.qr_evap_tend, d.vap_liq_exchange, d.vap_ice_exchange, d.liq_ice_exchange, d.pratot,
+      d.nevapr, d.qr_evap_tend, d.vap_liq_exchange, d.vap_ice_exchange, d.liq_ice_exchange, 
+      d.P3_qr2qv_evap, d.P3_qi2qv_sublim, d.P3_qc2qr_accret, d.P3_qc2qr_autoconv, d.P3_qv2qi_vapdep, d.P3_qc2qi_berg, d.P3_qc2qr_ice_shed, d.P3_qc2qi_collect, d.P3_qr2qi_collect, d.P3_qc2qi_hetero_freeze, d.P3_qr2qi_immers_freeze, d.P3_qi2qr_melt,
+      d.pratot,
       d.prctot, &d.is_hydromet_present);
   }
 
@@ -451,7 +453,9 @@ void run_bfb_p3_main()
       d.precip_ice_surf, d.its, d.ite, d.kts, d.kte, d.diag_eff_radius_qc, d.diag_eff_radius_qi, d.diag_eff_radius_qr,
       d.rho_qi, d.do_predict_nc, d.do_prescribed_CCN, d.dpres, d.inv_exner, d.qv2qi_depos_tend,
       d.precip_liq_flux, d.precip_ice_flux, d.cld_frac_r, d.cld_frac_l, d.cld_frac_i,
-      d.liq_ice_exchange, d.vap_liq_exchange, d.vap_ice_exchange, d.qv_prev, d.t_prev);
+      d.liq_ice_exchange, d.vap_liq_exchange, d.vap_ice_exchange,
+      d.P3_qr2qv_evap, d.P3_qi2qv_sublim, d.P3_qc2qr_accret, d.P3_qc2qr_autoconv, d.P3_qv2qi_vapdep, d.P3_qc2qi_berg, d.P3_qc2qr_ice_shed, d.P3_qc2qi_collect, d.P3_qr2qi_collect, d.P3_qc2qi_hetero_freeze, d.P3_qr2qi_immers_freeze, d.P3_qi2qr_melt,d.P3_qr_sed,d.P3_qc_sed,d.P3_qi_sed,
+      d.qv_prev, d.t_prev);
   }
 
   if (SCREAM_BFB_TESTING && this->m_baseline_action == COMPARE) {
diff --git a/components/eamxx/src/physics/p3/tests/p3_tests.cpp b/components/eamxx/src/physics/p3/tests/p3_tests.cpp
index 858a231094d4..2c503bc792f6 100644
--- a/components/eamxx/src/physics/p3/tests/p3_tests.cpp
+++ b/components/eamxx/src/physics/p3/tests/p3_tests.cpp
@@ -14,7 +14,7 @@ TEST_CASE("P3DataIterator", "p3") {
   using scream::p3::ic::Factory;
   const auto d = Factory::create(Factory::mixed);
   scream::p3::P3DataIterator fdi(d);
-  REQUIRE(fdi.nfield() == 35);
+  REQUIRE(fdi.nfield() == 50);
   const auto& f = fdi.getfield(0);
   REQUIRE(f.dim == 2);
   REQUIRE(f.extent[0] == 1);

@mahf708 mahf708 closed this as not planned Won't fix, can't repro, duplicate, stale Jan 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
EAMxx PRs focused on capabilities for EAMxx enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants