diff --git a/components/eamxx/cime_config/namelist_defaults_eamxx.xml b/components/eamxx/cime_config/namelist_defaults_eamxx.xml index 213c71e712d6..d86ef3162458 100644 --- a/components/eamxx/cime_config/namelist_defaults_eamxx.xml +++ b/components/eamxx/cime_config/namelist_defaults_eamxx.xml @@ -296,6 +296,16 @@ be lost if SCREAM_HACK_XML is not enabled. 0.0 + + + 0 + + + + + 0 + + false diff --git a/components/eamxx/src/physics/CMakeLists.txt b/components/eamxx/src/physics/CMakeLists.txt index 296b0b8b50bc..2d7ee5afdfe8 100644 --- a/components/eamxx/src/physics/CMakeLists.txt +++ b/components/eamxx/src/physics/CMakeLists.txt @@ -20,3 +20,4 @@ if (SCREAM_ENABLE_MAM) add_subdirectory(mam) endif() add_subdirectory(gw) +add_subdirectory(aux_tracers) diff --git a/components/eamxx/src/physics/aux_tracers/CMakeLists.txt b/components/eamxx/src/physics/aux_tracers/CMakeLists.txt new file mode 100644 index 000000000000..99043ce890ea --- /dev/null +++ b/components/eamxx/src/physics/aux_tracers/CMakeLists.txt @@ -0,0 +1,34 @@ +# Auxiliary tracers for EAMxx. +# +# This folder groups the "auxiliary tracer" physics processes. Currently, +# there are two options: passive water tracers and, built on top of them, +# water isotopes. Additional tracer classes could be added in an analagous +# way. The build is governed by these CMake options: +# +# EAMXX_ENABLE_WATER_TRACERS - build the passive water tracer process +# EAMXX_ENABLE_WATER_ISOTOPES - build the water isotope process +# +# Water isotopes are implemented on top of the water tracer infrastructure, so +# they can ONLY be built when water tracers are also enabled. If isotopes are +# requested without tracers we auto-enable tracers and warn, rather than build +# an inconsistent configuration. + +option(EAMXX_ENABLE_WATER_TRACERS "Whether to build the EAMxx water tracer process" OFF) +option(EAMXX_ENABLE_WATER_ISOTOPES "Whether to build the EAMxx water isotope process" OFF) + +# Enforce the dependency: isotopes require tracers. +if (EAMXX_ENABLE_WATER_ISOTOPES AND NOT EAMXX_ENABLE_WATER_TRACERS) + message(STATUS "WARNING: EAMXX_ENABLE_WATER_ISOTOPES=ON requires EAMXX_ENABLE_WATER_TRACERS; " + "auto-enabling water tracers.") + set(EAMXX_ENABLE_WATER_TRACERS ON CACHE BOOL "Whether to build the EAMxx water tracer process" FORCE) +endif() + +# Each process lives in its own sibling subdirectory. Descend +# into each only when the corresponding process is enabled. water_isotopes must +# be added after water_tracers, since it depends on the water_tracers target. +if (EAMXX_ENABLE_WATER_TRACERS) + add_subdirectory(water_tracers) +endif() +if (EAMXX_ENABLE_WATER_ISOTOPES) + add_subdirectory(water_isotopes) +endif() diff --git a/components/eamxx/src/physics/aux_tracers/water_isotopes/CMakeLists.txt b/components/eamxx/src/physics/aux_tracers/water_isotopes/CMakeLists.txt new file mode 100644 index 000000000000..cb69f08fc21e --- /dev/null +++ b/components/eamxx/src/physics/aux_tracers/water_isotopes/CMakeLists.txt @@ -0,0 +1,28 @@ +# Water isotope physics process. +# +# This directory is only entered when EAMXX_ENABLE_WATER_ISOTOPES is ON, +# which in turn guarantees EAMXX_ENABLE_WATER_TRACERS is ON +# (isotopes are layered on top of the water tracer infrastructure). Following +# the EAMxx one-library-per-process pattern, the water isotope process gets its +# own library. + +add_library(water_isotopes + eamxx_water_isotopes_process_interface.cpp +) + +# Public compile definition so the registration guard in register_physics.hpp +# becomes active. +target_compile_definitions(water_isotopes PUBLIC EAMXX_HAS_WATER_ISOTOPES) + +# Expose this directory +target_include_directories(water_isotopes PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(water_isotopes PUBLIC scream_share) +target_link_libraries(water_isotopes PRIVATE water_tracers) + +# Link into the eamxx_physics INTERFACE target. +if (TARGET eamxx_physics) + target_link_libraries(eamxx_physics INTERFACE water_isotopes) +endif() diff --git a/components/eamxx/src/physics/aux_tracers/water_isotopes/eamxx_water_isotopes_process_interface.cpp b/components/eamxx/src/physics/aux_tracers/water_isotopes/eamxx_water_isotopes_process_interface.cpp new file mode 100644 index 000000000000..dffd1a98ac2a --- /dev/null +++ b/components/eamxx/src/physics/aux_tracers/water_isotopes/eamxx_water_isotopes_process_interface.cpp @@ -0,0 +1,23 @@ +#include "eamxx_water_isotopes_process_interface.hpp" + +namespace scream +{ + +// ========================================================================================= +WaterIsotopes::WaterIsotopes(const ekat::Comm& comm, const ekat::ParameterList& params) + : WaterTracers(comm, params) +{ + // Water isotopes will inherit all tracer handling from WaterTracers + // No additional initialization needed at this stage +} + +// ========================================================================================= +void WaterIsotopes::run_impl(const double dt) +{ + // Call base class tracer physics (currently a no-op) + WaterTracers::run_impl(dt); + + // TODO: Add fractionation physics here +} + +} // namespace scream diff --git a/components/eamxx/src/physics/aux_tracers/water_isotopes/eamxx_water_isotopes_process_interface.hpp b/components/eamxx/src/physics/aux_tracers/water_isotopes/eamxx_water_isotopes_process_interface.hpp new file mode 100644 index 000000000000..e3249e9f1dc2 --- /dev/null +++ b/components/eamxx/src/physics/aux_tracers/water_isotopes/eamxx_water_isotopes_process_interface.hpp @@ -0,0 +1,46 @@ +#ifndef SCREAM_WATER_ISOTOPES_HPP +#define SCREAM_WATER_ISOTOPES_HPP + +#include "physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.hpp" +#include "ekat/ekat_parameter_list.hpp" + +#include + +namespace scream +{ +/* + * The class responsible to handle water isotope transport and fractionation + * + * This process extends WaterTracers to add equilibrium and kinetic fractionation + * during phase changes for water isotope species. + * + * By inheriting from WaterTracers, this class reuses all tracer field handling + * and only needs to override specific fractionation hooks. + * + * Note: This is a stub implementation that registers the process. Fractionation + * physics will be added later. +*/ + +class WaterIsotopes : public WaterTracers +{ +public: + // Constructors + WaterIsotopes (const ekat::Comm& comm, const ekat::ParameterList& params); + + // Override the name to distinguish from base WaterTracers + std::string name () const override { return "water_isotopes"; } + +protected: + + // Override run_impl to add fractionation physics + // For now, just calls base class implementation + void run_impl (const double dt) override; + + // TODO: Add virtual hooks for fractionation processes + // e.g., apply_equilibrium_fractionation(), apply_kinetic_fractionation() + +}; // class WaterIsotopes + +} // namespace scream + +#endif // SCREAM_WATER_ISOTOPES_HPP diff --git a/components/eamxx/src/physics/aux_tracers/water_tracers/CMakeLists.txt b/components/eamxx/src/physics/aux_tracers/water_tracers/CMakeLists.txt new file mode 100644 index 000000000000..5607cd5036ae --- /dev/null +++ b/components/eamxx/src/physics/aux_tracers/water_tracers/CMakeLists.txt @@ -0,0 +1,28 @@ +# Water tracer physics process. +# +# This directory is only entered when EAMXX_ENABLE_WATER_TRACERS is ON. +# Following the EAMxx one-library-per-process pattern, the +# water tracer process gets its own library. The sibling water_isotopes library +# depends on this one. + +add_library(water_tracers + eamxx_water_tracers_process_interface.cpp +) + +# Public compile definition so the registration guard in register_physics.hpp +# becomes active. +target_compile_definitions(water_tracers PUBLIC EAMXX_HAS_WATER_TRACERS) + +# Expose this directory to allow includes of the +# process interface headers. +target_include_directories(water_tracers PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Link required EAMxx libraries. +target_link_libraries(water_tracers scream_share) + +# Link into the eamxx_physics INTERFACE target. +if (TARGET eamxx_physics) + target_link_libraries(eamxx_physics INTERFACE water_tracers) +endif() diff --git a/components/eamxx/src/physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.cpp b/components/eamxx/src/physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.cpp new file mode 100644 index 000000000000..729ed701edfb --- /dev/null +++ b/components/eamxx/src/physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.cpp @@ -0,0 +1,51 @@ +#include "eamxx_water_tracers_process_interface.hpp" + +#include + +namespace scream +{ + +// ========================================================================================= +WaterTracers::WaterTracers(const ekat::Comm& comm, const ekat::ParameterList& params) + : AtmosphereProcess(comm, params) + , m_tracer_count(0) +{ + // Read tracer count from parameter list (default 0) + m_tracer_count = m_params.get("tracer_count", 0); +} + +// ========================================================================================= +void WaterTracers::create_requests() +{ + // Get the grid for this process + m_grid = m_grids_manager->get_grid("physics"); + 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 + + // TODO: Define field requests for water tracer arrays + // For now, this process requires no fields and computes no fields + // Field definitions will be added later +} + +// ========================================================================================= +void WaterTracers::initialize_impl(const RunType /* run_type */) +{ + // TODO: Initialize tracer field arrays and any precomputed data + // For now, this is a no-op since no fields are defined yet +} + +// ========================================================================================= +void WaterTracers::run_impl(const double /* dt */) +{ + // TODO: Implement tracer transport and physics + // This stub implementation performs no operations + // Tracer physics will be added in subsequent PRs +} + +// ========================================================================================= +void WaterTracers::finalize_impl() +{ + // Nothing to finalize at this stage +} + +} // namespace scream diff --git a/components/eamxx/src/physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.hpp b/components/eamxx/src/physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.hpp new file mode 100644 index 000000000000..6d8e36e9b2fe --- /dev/null +++ b/components/eamxx/src/physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.hpp @@ -0,0 +1,60 @@ +#ifndef SCREAM_WATER_TRACERS_HPP +#define SCREAM_WATER_TRACERS_HPP + +#include "share/atm_process/atmosphere_process.hpp" +#include "ekat/ekat_parameter_list.hpp" + +#include + +namespace scream +{ +/* + * The class responsible to handle water tracer transport through the atmosphere + * + * This process manages additional water species that track through the model + * without undergoing fractionation. Water isotopes (a special case with + * fractionation) are handled by the WaterIsotopes subclass. + * + * Note: This is a stub implementation that registers the process and sets up + * the basic infrastructure. Field definitions and physics implementation are + * deferred to later specs in the water isotope campaign. +*/ + +class WaterTracers : public AtmosphereProcess +{ +public: + using KT = ekat::KokkosTypes; + + // Constructors + WaterTracers (const ekat::Comm& comm, const ekat::ParameterList& params); + + // The type of subcomponent + AtmosphereProcessType type () const { return AtmosphereProcessType::Physics; } + + // The name of the subcomponent + virtual std::string name () const { return "water_tracers"; } + + // Create grid-dependent field requests + void create_requests (); + +protected: + + // The three main overrides for the subcomponent + void initialize_impl (const RunType run_type); + void run_impl (const double dt); + void finalize_impl (); + + // Keep track of field dimensions + int m_num_cols; + int m_num_levs; + + // Number of tracers to track (from parameter list) + int m_tracer_count; + + std::shared_ptr m_grid; + +}; // class WaterTracers + +} // namespace scream + +#endif // SCREAM_WATER_TRACERS_HPP diff --git a/components/eamxx/src/physics/register_physics.hpp b/components/eamxx/src/physics/register_physics.hpp index 75b88bd73022..b61c37b4a2ee 100644 --- a/components/eamxx/src/physics/register_physics.hpp +++ b/components/eamxx/src/physics/register_physics.hpp @@ -53,6 +53,12 @@ #ifdef EAMXX_HAS_CLD_FRAC_NET #include "physics/cld_fraction/cld_frac_net/eamxx_cld_frac_net_process_interface.hpp" #endif +#ifdef EAMXX_HAS_WATER_TRACERS +#include "physics/aux_tracers/water_tracers/eamxx_water_tracers_process_interface.hpp" +#endif +#ifdef EAMXX_HAS_WATER_ISOTOPES +#include "physics/aux_tracers/water_isotopes/eamxx_water_isotopes_process_interface.hpp" +#endif namespace scream { @@ -106,6 +112,12 @@ inline void register_physics () { #ifdef EAMXX_HAS_CLD_FRAC_NET proc_factory.register_product("cld_frac_net",&create_atmosphere_process); #endif +#ifdef EAMXX_HAS_WATER_TRACERS + proc_factory.register_product("water_tracers",&create_atmosphere_process); +#endif +#ifdef EAMXX_HAS_WATER_ISOTOPES + proc_factory.register_product("water_isotopes",&create_atmosphere_process); +#endif // If no physics was enabled, silence compile warning about unused var (void) proc_factory;