Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions components/eamxx/src/share/field/field_layout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>& dims () const { return m_dims; }
const extents_type& extents () const { return m_extents; }
Expand Down Expand Up @@ -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<FieldTag> m_tags;
Expand All @@ -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
Expand All @@ -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");

Expand Down
13 changes: 12 additions & 1 deletion components/eamxx/src/share/field/field_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,23 @@ 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<int>(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<num_indices; ++i) {
EKAT_REQUIRE_MSG ( indices[i]>=0 && indices[i]<fl.dim(tags[i],false),
"Error! Requested slice index is out of bound.\n"
" - field name: " + f.name() + "\n"
" - field layout: " + fl.to_string() + "\n"
" - hyperslab tags: (" + ekat::join(tags2str(tags),",") + ")\n"
" - hyperslab indices: (" + ekat::join(indices,",") + ")\n");
}

switch (dt) {
case DataType::IntType:
Expand Down
4 changes: 4 additions & 0 deletions components/eamxx/src/share/field/tests/field_header_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
5 changes: 5 additions & 0 deletions components/eamxx/src/share/field/tests/field_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,11 @@ TEST_CASE ("print_field_hyperslab") {
}

REQUIRE (out.str()==expected.str());

loc_idxs[0] = nel;
REQUIRE_THROWS(print_field_hyperslab(f,loc_tags,loc_idxs,out));
loc_idxs[0] = -1;
REQUIRE_THROWS(print_field_hyperslab(f,loc_tags,loc_idxs,out));
}
SECTION ("slice_0234") {
std::vector<FieldTag> loc_tags = {EL,GP,GP,LEV};
Expand Down
Loading