From 77ff7a4a22f078def23894592d80482fcf1ac72a Mon Sep 17 00:00:00 2001 From: Luca Bertagna Date: Tue, 19 May 2026 16:31:10 -0600 Subject: [PATCH 1/3] EAMxx: add FieldLayout static method to get 0d layout --- components/eamxx/src/share/field/field_layout.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/eamxx/src/share/field/field_layout.hpp b/components/eamxx/src/share/field/field_layout.hpp index 6b037b90750d..3379f9859b63 100644 --- a/components/eamxx/src/share/field/field_layout.hpp +++ b/components/eamxx/src/share/field/field_layout.hpp @@ -77,6 +77,9 @@ class FieldLayout { // Create invalid layout static FieldLayout invalid () { return FieldLayout({FieldTag::Invalid},{0}); } + // Create scalar layout + static FieldLayout scalar () { return FieldLayout({},{}); } + // ----- Getters ----- // LayoutType type () const { return m_type; } From 60d88cc8e547c4d9701291c21335f143052e210c Mon Sep 17 00:00:00 2001 From: Luca Bertagna Date: Tue, 19 May 2026 16:33:00 -0600 Subject: [PATCH 2/3] EAMxx: add p0 to grids geo data whenever lev/ilev geo data is added Ensures IO will take care of outputing it (if geo data is requested) --- .../eamxx/src/dynamics/homme/homme_grids_manager.cpp | 12 +++++++----- .../share/data_managers/mesh_free_grids_manager.cpp | 12 +++++++++--- .../eamxx/src/share/util/io_metadata/io_metadata.csv | 1 + 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp b/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp index b72d2d47f42d..aaad3269d175 100644 --- a/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp +++ b/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp @@ -16,6 +16,7 @@ #include "share/remap/inverse_remapper.hpp" #include "share/grid/se_grid.hpp" #include "share/io/scorpio_input.hpp" +#include "share/physics/physics_constants.hpp" // Get all Homme's compile-time dims and constants #include "PhysicalConstants.hpp" @@ -275,6 +276,9 @@ build_physics_grid (const ci_string& type, const ci_string& rebalance) { auto hybm = phys_grid->create_geometry_data("hybm",layout_mid,none); auto lev = phys_grid->create_geometry_data("lev", layout_mid,mbar); auto ilev = phys_grid->create_geometry_data("ilev",layout_int,mbar); + auto P0 = phys_grid->create_geometry_data("P0", FieldLayout::scalar(), Pa); + const auto p0_val = physics::Constants::P0.value; + P0.deep_copy(p0_val); for (auto f : {hyai, hybi, hyam, hybm}) { auto f_d = get_grid("dynamics")->get_geometry_data(f.name()); @@ -283,8 +287,6 @@ build_physics_grid (const ci_string& type, const ci_string& rebalance) { } // Build lev from hyam and hybm - const Real ps0 = 100000.0; - auto hyam_v = hyam.get_view(); auto hybm_v = hybm.get_view(); auto hyai_v = hyai.get_view(); @@ -293,10 +295,10 @@ build_physics_grid (const ci_string& type, const ci_string& rebalance) { auto ilev_v = ilev.get_view(); auto num_v_levs = phys_grid->get_num_vertical_levels(); for (int ii=0;ii("geo_data_source"); if (geo_data_source=="CREATE_EMPTY_DATA") { - using namespace ShortFieldTagsNames; - using namespace ekat::units; - auto layout_mid = grid->get_vertical_layout(LEV); auto layout_int = grid->get_vertical_layout(ILEV); @@ -189,6 +189,12 @@ add_geo_data (const nonconstgrid_ptr_type& grid) const load_vertical_coordinates(grid,filename); } } + + // This is to ensure output streams will save P0 among the geo data. + // NOTE: MeshFreeGridsManager is mostly for unit tests, so this is somewhat moot, + // but it helps to have consistent treatment of geo data across GM's + auto P0 = grid->create_geometry_data("P0", FieldLayout::scalar(), Pa); + P0.deep_copy(physics::Constants::P0.value); } void MeshFreeGridsManager:: diff --git a/components/eamxx/src/share/util/io_metadata/io_metadata.csv b/components/eamxx/src/share/util/io_metadata/io_metadata.csv index 0b188530e1df..6ff599c747d0 100644 --- a/components/eamxx/src/share/util/io_metadata/io_metadata.csv +++ b/components/eamxx/src/share/util/io_metadata/io_metadata.csv @@ -1,6 +1,7 @@ variable,standard_name,long_name lev,,hybrid level at midpoints (1000*(A+B)) ilev,,hybrid level at interfaces (1000*(A+B)) +P0,,reference pressure hyai,,hybrid A coefficient at layer interfaces hybi,,hybrid B coefficient at layer interfaces hyam,,hybrid A coefficient at layer midpoints From 6e06de40209ae15c23e625a2c9c3f83ec3ac7299 Mon Sep 17 00:00:00 2001 From: Luca Bertagna Date: Wed, 20 May 2026 20:48:42 -0600 Subject: [PATCH 3/3] EAMxx: add formula_terms, standard_name, and positive atts to lev/ilev output variables --- .../src/dynamics/homme/homme_grids_manager.cpp | 13 +++++++++++-- .../data_managers/mesh_free_grids_manager.cpp | 16 ++++++++++++++++ .../src/share/util/io_metadata/io_metadata.csv | 4 ++-- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp b/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp index aaad3269d175..c4dd9226af97 100644 --- a/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp +++ b/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp @@ -198,7 +198,8 @@ void HommeGridsManager::build_dynamics_grid () { } void HommeGridsManager:: -build_physics_grid (const ci_string& type, const ci_string& rebalance) { +build_physics_grid (const ci_string& type, const ci_string& rebalance) +{ std::string name = "physics_" + type; if (rebalance != "none") { name += " " + rebalance; @@ -285,7 +286,15 @@ build_physics_grid (const ci_string& type, const ci_string& rebalance) { f.deep_copy(f_d); f.sync_to_host(); } - + + using stratts_t = std::map; + auto& lev_io_atts = lev.get_header().get_extra_data("io: string attributes"); + auto& ilev_io_atts = ilev.get_header().get_extra_data("io: string attributes"); + lev_io_atts["formula_terms"] = "a: hyam b: hybm p0: P0 ps: ps" ; + ilev_io_atts["formula_terms"] = "a: hyai b: hybi p0: P0 ps: ps" ; + lev_io_atts["positive"] = "down"; + ilev_io_atts["positive"] = "down"; + // Build lev from hyam and hybm auto hyam_v = hyam.get_view(); auto hybm_v = hybm.get_view(); diff --git a/components/eamxx/src/share/data_managers/mesh_free_grids_manager.cpp b/components/eamxx/src/share/data_managers/mesh_free_grids_manager.cpp index 9682259ecee3..56c532163c19 100644 --- a/components/eamxx/src/share/data_managers/mesh_free_grids_manager.cpp +++ b/components/eamxx/src/share/data_managers/mesh_free_grids_manager.cpp @@ -162,6 +162,14 @@ add_geo_data (const nonconstgrid_ptr_type& grid) const auto lev = grid->create_geometry_data("lev" , layout_mid, mbar); auto ilev = grid->create_geometry_data("ilev" , layout_int, mbar); + using stratts_t = std::map; + auto& lev_io_atts = lev.get_header().get_extra_data("io: string attributes"); + auto& ilev_io_atts = ilev.get_header().get_extra_data("io: string attributes"); + lev_io_atts["formula_terms"] = "a: hyam b: hybm p0: P0 ps: ps" ; + ilev_io_atts["formula_terms"] = "a: hyai b: hybi p0: P0 ps: ps" ; + lev_io_atts["positive"] = "down"; + ilev_io_atts["positive"] = "down"; + const auto invalid = ekat::invalid(); lat.deep_copy(invalid);; lon.deep_copy(invalid); @@ -274,6 +282,14 @@ load_vertical_coordinates (const nonconstgrid_ptr_type& grid, const std::string& scorpio::read_var(filename,"ilev",ilev_v.data()); scorpio::release_file(filename); + using stratts_t = std::map; + auto& lev_io_atts = lev.get_header().get_extra_data("io: string attributes"); + auto& ilev_io_atts = ilev.get_header().get_extra_data("io: string attributes"); + lev_io_atts["formula_terms"] = "a: hyam b: hybm p0: P0 ps: ps" ; + ilev_io_atts["formula_terms"] = "a: hyai b: hybi p0: P0 ps: ps" ; + lev_io_atts["positive"] = "down"; + ilev_io_atts["positive"] = "down"; + // Build lev and ilev from hyam and hybm, and ilev from hyai and hybi using PC = scream::physics::Constants; const Real ps0 = PC::P0.value; diff --git a/components/eamxx/src/share/util/io_metadata/io_metadata.csv b/components/eamxx/src/share/util/io_metadata/io_metadata.csv index 6ff599c747d0..2c1049cbb726 100644 --- a/components/eamxx/src/share/util/io_metadata/io_metadata.csv +++ b/components/eamxx/src/share/util/io_metadata/io_metadata.csv @@ -1,6 +1,6 @@ variable,standard_name,long_name -lev,,hybrid level at midpoints (1000*(A+B)) -ilev,,hybrid level at interfaces (1000*(A+B)) +lev,atmosphere_hybrid_sigma_pressure_coordinate,hybrid level at midpoints (1000*(A+B)) +ilev,atmosphere_hybrid_sigma_pressure_coordinate,hybrid level at interfaces (1000*(A+B)) P0,,reference pressure hyai,,hybrid A coefficient at layer interfaces hybi,,hybrid B coefficient at layer interfaces