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

Unify FM over all grids #6981

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tcclevenger
Copy link
Contributor

Store a single FieldManager for all fields over all grids.

This solves the issue in #6789 where having a group as a subset of another, and allocated on different grids, was causing subview indices mismatch between grids.

Also

  • Remove Derivation type. Now groups contain the union of all fields registered over all grids. I.e., requesting "tracers" on GLL grid without registering any tracers on GLL will give all tracers registered on PG2 grid.
  • Remove "Preferred" bundling. You either require bundling or not.

Also
- remove devivation type
- simplify group logic to ensure subfields over grids have same index
@tcclevenger tcclevenger marked this pull request as draft February 7, 2025 01:17
Copy link
Contributor Author

@tcclevenger tcclevenger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments highlight the important pieces since this is such a large PR. So many of the changes come from every instance of the FM has to be used differently (passing grid names instead of only one grid being stored).

// we register a corresponding version of the field on the "target" FM.

// Helper lambda to reduce code duplication
auto process_imported_groups = [&](const std::set<GroupRequest>& group_requests) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this logic to FieldManager::pre_process_groups().

Comment on lines +27 to +36
Field::clone(const std::string& name) const {
return clone(name, get_header().get_identifier().get_grid_name());
}

Field
Field::clone(const std::string& name) const {
Field::clone(const std::string& name, const std::string& grid_name) const {
// Create new field
const auto& my_fid = get_header().get_identifier();
FieldIdentifier fid(name,my_fid.get_layout(),my_fid.get_units(),
my_fid.get_grid_name(),my_fid.data_type());
grid_name,my_fid.data_type());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed to add a grid argument to Field::clone() because, in many cases, we are cloning a grid (giving it a new name), constructing a FM(new_grid), but using a field whose ID gives a grid name from the old grid, and the new FM was complaining that the grid was not in the internal grids manager.

@@ -185,7 +190,7 @@ Field Field::subfield(const std::string& sf_name,
"Error! Input field must be allocated in order to subview it.\n");

auto sf_layout = lt.clone();
sf_layout.reset_dim(idim, index_end - index_beg);
sf_layout.reset_dim(idim, index_end+1 - index_beg);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kokkos::subview(..., beg, end, ...) has inclusive bounds, but we were treating the subview bound as [bed, end).

@@ -88,7 +88,7 @@ FieldAllocProp FieldAllocProp::subview(const int idim,
EKAT_REQUIRE_MSG(index_beg < index_end,
"Error! Slice indices are invalid (non-increasing).\n");
EKAT_REQUIRE_MSG(
index_beg >= 0 && index_end < m_layout.dim(idim),
index_beg >= 0 && index_end <= m_layout.dim(idim),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as comment above about Kokkos bounds

@@ -117,6 +117,7 @@ class FieldLayout {
// calls get_vector_component_idx()
int get_vector_dim () const;
FieldTag get_vector_tag () const;
std::vector<std::string> get_dim_names() const;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed by the new equivalent_layout() function.

info.m_subview_idx [*it] = std::distance(cluster_ordered_fields.begin(),it);
}
info.m_bundled = true;
}
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now indices info is independent of grid, guaranteeing each grid agrees.

return it==m_fields.end() ? nullptr : it->second;
FieldManager::get_field_ptr (const std::string& name, const std::string& grid_name) const {
auto it = m_fields.at(grid_name).find(name);
return it==m_fields.at(grid_name).end() ? nullptr : it->second;
}

void FieldManager::pre_process_group_requests () {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important function for gathering which grids should register which group fields

// the parent field. So at registration time, simply keep track of the subfields,
// and create them at registration_ends() time, after all other fields.
std::map<std::string,FieldRequest> m_subfield_requests;

// The map group_name -> FieldGroupInfo
group_info_map m_field_groups;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't change, group info is the same for all grids.

@@ -115,6 +115,53 @@ AbstractGrid::get_3d_tensor_layout (const bool midpoints, const std::vector<int>
return get_3d_tensor_layout(midpoints,cmp_dims,names);
}

FieldLayout
AbstractGrid::equivalent_layout (const FieldLayout& template_layout) const
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how we get the layout for tracer on a new grid.

Comment on lines +139 to +149
std::set<std::string> GridsManager::
get_grid_names () const {
std::set<std::string> names;
if (m_grids.size()==0) {
return names;
}
for (const auto& g : m_grids) {
names.emplace(g.second->name());
}
return names;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up using this function a lot, but I don't know that I love it. It doesn't take into account aliases. I could instead always loop over the grid manager's grid map and query the names from there.

@tcclevenger
Copy link
Contributor Author

Quite a few fails in the CI, odd some didn't trigger on my workstation (rrtmgp standalone for instance)... Leaving Draft for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant