From 895438c85caa74dee38146bb66d6b32201d378af Mon Sep 17 00:00:00 2001 From: Walter Hannah Date: Thu, 11 Sep 2025 15:27:48 -0600 Subject: [PATCH 1/3] Update field_utils.hpp --- components/eamxx/src/share/field/field_utils.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/components/eamxx/src/share/field/field_utils.cpp b/components/eamxx/src/share/field/field_utils.cpp index 4268401f8060..cfe0ce3445b5 100644 --- a/components/eamxx/src/share/field/field_utils.cpp +++ b/components/eamxx/src/share/field/field_utils.cpp @@ -313,12 +313,22 @@ void print_field_hyperslab (const Field& f, { const auto dt = f.data_type(); const auto rank = f.rank(); + const auto& fl = f.get_header().get_identifier().get_layout(); EKAT_REQUIRE_MSG (rank>=static_cast(tags.size()), "Error! Requested location incompatible with field rank.\n" " - field name: " + f.name() + "\n" " - field rank: " + std::to_string(rank) + "\n" - " - requested indices: (" + ekat::join(indices,",") + "\n"); + " - requested indices: (" + ekat::join(indices,",") + ")\n"); + + const int num_indices = indices.size(); + for (int i=0; i=0 && indices[i] Date: Wed, 24 Sep 2025 14:23:30 -0600 Subject: [PATCH 2/3] EAMxx: make some methods of FieldLayout more flexible --- .../eamxx/src/share/field/field_layout.hpp | 36 +++++++++++-------- .../share/field/tests/field_header_tests.cpp | 4 +++ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/components/eamxx/src/share/field/field_layout.hpp b/components/eamxx/src/share/field/field_layout.hpp index 46d9918004b4..38ce16202c2d 100644 --- a/components/eamxx/src/share/field/field_layout.hpp +++ b/components/eamxx/src/share/field/field_layout.hpp @@ -92,10 +92,12 @@ class FieldLayout { // The rank is the number of tags associated to this field. int rank () const { return m_rank; } - int dim_idx (const FieldTag t) const; + // If throw_if_multiple_matches=false, simply return the idx of the + // first match, otherwise throws an exception if 2+ matches are found + int dim_idx (const FieldTag t, bool throw_if_multiple_matches = true) const; - int dim (const std::string& name) const; - int dim (const FieldTag tag) const; + int dim (const std::string& name, bool throw_if_multiple_matches = true) const; + int dim (const FieldTag tag, bool throw_if_multiple_matches = true) const; int dim (const int idim) const; const std::vector& dims () const { return m_dims; } const extents_type& extents () const { return m_extents; } @@ -157,8 +159,7 @@ class FieldLayout { void compute_type (); void set_extents (); void add_dim (const FieldTag t, const int extent, const std::string& name, - bool prepend_instead_of_append = false); - + bool prepend_instead_of_append = false); int m_rank; std::vector m_tags; @@ -174,22 +175,27 @@ bool operator== (const FieldLayout& fl1, const FieldLayout& fl2); // ========================== IMPLEMENTATION ======================= // -inline int FieldLayout::dim_idx (const FieldTag t) const { - // Check exactly one tag (no ambiguity) - EKAT_REQUIRE_MSG(ekat::count(m_tags,t)==1, - "Error! FieldTag::dim_idx requires that the tag appears exactly once.\n" +inline int FieldLayout::dim_idx (const FieldTag t, bool throw_if_multiple_matches) const { + EKAT_REQUIRE_MSG( (not throw_if_multiple_matches) or ekat::count(m_tags,t)<=1, + "[FieldTag::dim_idx] Error! Multiple matches found for the requested tag.\n" + " - field tag: " + e2str(t) + "\n" + " - field layout: " + this->to_string() + "\n"); + + auto it = ekat::find(m_tags,t); + EKAT_REQUIRE_MSG (it!=m_tags.end(), + "[FieldTag::dim_idx] Error! Requested tag not found.\n" " - field tag: " + e2str(t) + "\n" - " - tag count: " + std::to_string(ekat::count(m_tags,t)) + "\n"); + " - field layout: " + this->to_string() + "\n"); - return std::distance(m_tags.begin(),ekat::find(m_tags,t)); + return std::distance(m_tags.begin(),it); } // returns extent -inline int FieldLayout::dim (const FieldTag t) const { - return m_dims[dim_idx(t)]; +inline int FieldLayout::dim (const FieldTag t, bool throw_if_multiple_matches) const { + return m_dims[dim_idx(t,throw_if_multiple_matches)]; } -inline int FieldLayout::dim (const std::string& name) const { +inline int FieldLayout::dim (const std::string& name, bool throw_if_multiple_matches) const { auto it = ekat::find(m_names,name); // Check if found @@ -198,7 +204,7 @@ inline int FieldLayout::dim (const std::string& name) const { " - layout dims: " + ekat::join(m_names,",") + "\n"); // Check only one tag (no ambiguity) - EKAT_REQUIRE_MSG(ekat::count(m_names,name)==1, + EKAT_REQUIRE_MSG( (not throw_if_multiple_matches) or ekat::count(m_names,name)==1, "Error! Dimension name '" + name + "' appears multiple times.\n" " - layout dims: " + ekat::join(m_names,",") + "\n"); diff --git a/components/eamxx/src/share/field/tests/field_header_tests.cpp b/components/eamxx/src/share/field/tests/field_header_tests.cpp index c166efca0377..726317ef68f8 100644 --- a/components/eamxx/src/share/field/tests/field_header_tests.cpp +++ b/components/eamxx/src/share/field/tests/field_header_tests.cpp @@ -29,6 +29,10 @@ TEST_CASE("field_layout", "") { REQUIRE (fl5.type()==LayoutType::Vector3D); REQUIRE (fl6.type()==LayoutType::Tensor3D); + REQUIRE (fl3.dim(COL)==1); + REQUIRE_THROWS (fl3.dim(CMP)); + REQUIRE (fl3.dim(CMP,false)==3); + REQUIRE (not fl1.is_vector_layout()); REQUIRE ( fl2.is_vector_layout()); REQUIRE (not fl3.is_vector_layout()); From a5452e015c93230c01e67caf40b715b1eca37d7b Mon Sep 17 00:00:00 2001 From: Luca Bertagna Date: Wed, 24 Sep 2025 11:37:08 -0600 Subject: [PATCH 3/3] EAMxx: fix sanity check in print_field_hyperslab Also, add test to verify the check works --- components/eamxx/src/share/field/field_utils.cpp | 7 ++++--- components/eamxx/src/share/field/tests/field_utils.cpp | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/components/eamxx/src/share/field/field_utils.cpp b/components/eamxx/src/share/field/field_utils.cpp index cfe0ce3445b5..2d0c390e747c 100644 --- a/components/eamxx/src/share/field/field_utils.cpp +++ b/components/eamxx/src/share/field/field_utils.cpp @@ -323,11 +323,12 @@ void print_field_hyperslab (const Field& f, const int num_indices = indices.size(); for (int i=0; i=0 && indices[i]=0 && indices[i] loc_tags = {EL,GP,GP,LEV};