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

Point ids for refined grids and addLgrsUpdateLeafGridView refactorization #802

Merged
merged 1 commit into from
Nov 27, 2024

Conversation

aritorto
Copy link
Member

@aritorto aritorto commented Nov 21, 2024

This PR introduces a structure to manage the point global IDs of all refined child cells per parent. This structure ensures the correct assignment of global point IDs in refined grids, gathering already-assigned IDs for interior cells and distributing them for overlap cells.

Current approach avoids duplicated point ids in the following setting:
Let's say a block of cells to be refined is distributed in P_{i_0}, ..., P_{i_n}, with n+1 < grid.comm().size().
If all cells to be refined are not "seen"(neither interior nor overlap) for every process P with P != P_{i_j}, j = 0, ..., n.

Points that may have multiple ids as shown and explained in #806.
Cells that only share corners (not faces) with interior cells of a process are not included in its overlap layer, therefore, some point may have multiple ids.

Keeping this potential multiple point ids in mind, this PR allows distributing Local Grid Refinements (LGRs) across different processes, subject to first distribute level zero grid, and after that add the LGRs. To be able to run the simulation, some changes to respect this order must be done in opm-simulators.

Improvement/replacement for #801

Not relevant for the Reference Manual

@aritorto aritorto changed the title [refactor] Improve readability by splitting code on addLgrsUpdateLeafGridView Point global ids for refined level grids and addLgrsUpdateLeafGridView refactorization Nov 21, 2024
@aritorto
Copy link
Member Author

jenkins build this serial please

@aritorto aritorto requested a review from blattms November 21, 2024 12:47
@aritorto aritorto changed the title Point global ids for refined level grids and addLgrsUpdateLeafGridView refactorization Point ids for refined grids and addLgrsUpdateLeafGridView refactorization Nov 21, 2024
@akva2
Copy link
Member

akva2 commented Nov 21, 2024

some new warnings, please address

@aritorto
Copy link
Member Author

jenkins build this serial please

1 similar comment
@aritorto
Copy link
Member Author

jenkins build this serial please

Copy link
Member

@blattms blattms left a comment

Choose a reason for hiding this comment

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

Thanks a lot.
I have a few suggestions where you should probably change the code.

@@ -202,6 +202,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/grid/LookUpData.hh
opm/grid/cpgrid/OrientedEntityTable.hpp
opm/grid/cpgrid/ParentToChildrenCellGlobalIdHandle.hpp
opm/grid/cpgrid/ParentToChildCellToPointGlobalIdHandle.hpp
Copy link
Member

Choose a reason for hiding this comment

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

Please check whitespace here. Mabye you used a tab here? I would use copy and paste to get the correct whitespace.

@@ -1089,6 +1072,34 @@ namespace Dune
int elemLgr) const;
/// --------------- Auxiliary methods to support Adaptivity (end) ---------------

// @brief Check if there non neighboring connections on blocks of cells selected for refinement.
Copy link
Member

Choose a reason for hiding this comment

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

Please fix indentation. and use three slashes ///

opm/grid/CpGrid.hpp Show resolved Hide resolved
opm/grid/cpgrid/CpGrid.cpp Outdated Show resolved Hide resolved
Comment on lines 1224 to 1231
getIJK(element.index(), ijk);
for (std::size_t level = 0; level < startIJK_vec.size(); ++level) {
bool belongsToLevel = true;
for (int c = 0; c < 3; ++c) {
belongsToLevel = belongsToLevel && ( (ijk[c] >= startIJK_vec[level][c]) && (ijk[c] < endIJK_vec[level][c]) );
if (!belongsToLevel)
break;
}
Copy link
Member

Choose a reason for hiding this comment

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

Do we mark the cells of an LGR? If we do we can probably simplify this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Code is slightly simplified in a coming-soon-commit. In nonNNCsSelectedCellsLGR(...) we only check if the selected cells for refinement (via blocks with startIJK endIJK values) have NNCs. If at least one cell of one block has NNCs, we return false.

We mark elements for refinement in CpGrid::markElemeAssignLevelDetectActiveLgrs(...)

// LGR1 dim 6x2x2 -> 7x3x3 = 63 points
std::vector<int> local_point_ids;
local_point_ids.reserve(63); // expected_point_ids in LGR1
for (const auto& element : elements(grid.levelGridView(1))) {
Copy link
Member

Choose a reason for hiding this comment

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

What is the reason why we do not iterate over vertices directly?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point!

}
auto [all_point_ids, displPoint ] = Opm::allGatherv(local_point_ids, grid.comm());
const std::set<int> all_point_ids_set(all_point_ids.begin(), all_point_ids.end());
// Difference with preveious test case:
Copy link
Member

Choose a reason for hiding this comment

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

previous

Copy link
Member

@blattms blattms Nov 27, 2024

Choose a reason for hiding this comment

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

Typo still there, though 😅 preveious -> previous

Copy link
Member Author

Choose a reason for hiding this comment

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

sorry for that, I thought I fixed it...

// - P1 does NOT see cells 2 and 6, but sees the rest of them.
// - P2 does NOT see cell 13, but sees all the others.
// - P3 does NOT see cell 1, 5 and 17, but sees all the others.
// Remark: the LGR is distributed only in 2 processes which are the only two processes seeing these cells.
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand this sentence. Are there more than 1 LGR (which is said to be distributed among all processes above)

Copy link
Member Author

@aritorto aritorto Nov 26, 2024

Choose a reason for hiding this comment

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

I will try to improve the comment. There is only one LGR here. The block of parent cells has dimension 2x2x2, the parent cell indices are {1,2,5,6,13,14,17,18}. Each parent cell gets refined into 2x2x2 children, therefore the LGR dimension is 4x4x4.

That comment is probably a copy-paste misunderstanding from the previous case. Sorry for that!

auto [all_point_ids, displPoint ] = Opm::allGatherv(local_point_ids, grid.comm());
const std::set<int> all_point_ids_set(all_point_ids.begin(), all_point_ids.end());
// Difference with preveious test case:
// Global cell ids of cells to be refined = {1,2,5,6,13,14,17,18}
Copy link
Member

Choose a reason for hiding this comment

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

Please indicate that this a bug originating from the way that we add overlap cells.

Copy link
Member

@blattms blattms Nov 27, 2024

Choose a reason for hiding this comment

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

I am still not sure. Do we test how things should be below, or do we test in a certain way, just to make the test succeed for now (i.e. 145 is actually not the correct number). If it is the latter then the comment does not really tell me that.

Copy link
Member Author

Choose a reason for hiding this comment

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

All the comments are to explain why we get more than the expected amount of point ids. I could remove the check since in principle it's not what we want. On the other hand, there is this PR #806 showing that "we cannot do better" in some cases... Shall I remove all the "checks" of cases where we cannot guarantee unique point ids?

Comment on lines 77 to 87
// Not every cell has children. When they have children, the amount might vary.
bool fixedSize(std::size_t, std::size_t)
{
return false;
}
// Only communicate values attached to cells.
bool contains(std::size_t, std::size_t codim)
{
return codim == 0;
}
// Communicate variable size: 1 (rank) + (8* amount of child cells) from an interior parent cell from level zero grid.
Copy link
Member

Choose a reason for hiding this comment

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

These comments seem more like comments about the implementation. Maybe move them inside the methods?

@aritorto
Copy link
Member Author

@blattms all commnets have been addressed, many thanks for your review!

@aritorto
Copy link
Member Author

jenkins build this serial please

Copy link
Member

@blattms blattms left a comment

Choose a reason for hiding this comment

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

Probably just nitpicks about documentation.

/// @param [in] startIJK_vec Vector of ijk values denoting the start of each block of cells selected for refinement.
/// @param [in] endIJK_vec Vector of ijk values denoting the end of each block of cells selected for refinement.
///
/// @return bool True when all blocks of cells do not contain any NNCs (non-neighboring-connection).
Copy link
Member

@blattms blattms Nov 27, 2024

Choose a reason for hiding this comment

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

I don't think you specify a type here. Please use /// @return True if, "when" should be probably be "if"

bool nonNNCsSelectedCellsLGR( const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec) const;

/// @brief Given blocks of cells selected for refinement, mark selected elements and assign them their corresponding
Copy link
Member

Choose a reason for hiding this comment

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

Everything after @brief until an empty comment line will be used as the brief documentation. Maybe we should shorten this a bit and move the rest after an empty comment line.

opm/grid/cpgrid/CpGridData.hpp Show resolved Hide resolved
Comment on lines +1375 to +1395
// To decide which "candidate" point global id wins, the rank is stored. The smallest ranks wins,
// i.e., the other non-selected candidates get rewritten with the values from the smallest (winner) rank.
std::vector<std::vector<int>> level_winning_ranks(cells_per_dim_vec.size());

for (std::size_t level = 1; level < cells_per_dim_vec.size()+1; ++level) {

level_cell_to_point[level -1] = currentData()[level]->cell_to_point_;
// Set std::numeric_limits<int>::max() to make sure that, during communication, the rank of the interior cell
// wins (int between 0 and comm().size()).
level_winning_ranks[level-1].resize(currentData()[level]->size(3), std::numeric_limits<int>::max());

for (const auto& element : elements(levelGridView(level))) {
// For interior cells, rewrite the rank value - later used in "point global id competition".
if (element.partitionType() == InteriorEntity) {
for (const auto& corner : currentData()[level]->cell_to_point_[element.index()]){
int rank = comm().rank();
level_winning_ranks[level -1][corner] = rank;
}
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be much cleaner if this is moved into the constructor of the handle. The container level_winning_ranks is not used here and is an implementation detail that should rather be hidden.

Copy link
Member Author

@aritorto aritorto Nov 27, 2024

Choose a reason for hiding this comment

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

I see your point, but the Handle does not see any grid, so changing the for-loop to elemIdx with size of level_cell_to_point_ would be okay, but then to detect if the each element is interior we need an Entity<0>. To create an Entity, we need each refined level grid.
It can be done, but implies passing to the constructor of the handle all refined level grids... I would say that this implementation detail is already hidden in CpGrid::selectWinnerPointIds() defintion


// Scatter global ids of child cells of a coarse overlap parent cell
template <class B, class T> // T = Entity<0>
void scatter(B& buffer, const T& element, std::size_t num_children) // check num_children
Copy link
Member

Choose a reason for hiding this comment

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

Actually, num_children is not the number of children. It is the number integers received. If there are no children it is 1 and otherwise it is 8 times the number of children + 1.

Hence maybe change the variable name to a simple size to prevent wrong assumptions.

}
auto [all_point_ids, displPoint ] = Opm::allGatherv(local_point_ids, grid.comm());
const std::set<int> all_point_ids_set(all_point_ids.begin(), all_point_ids.end());
// Difference with preveious test case:
Copy link
Member

@blattms blattms Nov 27, 2024

Choose a reason for hiding this comment

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

Typo still there, though 😅 preveious -> previous

auto [all_point_ids, displPoint ] = Opm::allGatherv(local_point_ids, grid.comm());
const std::set<int> all_point_ids_set(all_point_ids.begin(), all_point_ids.end());
// Difference with preveious test case:
// Global cell ids of cells to be refined = {1,2,5,6,13,14,17,18}
Copy link
Member

@blattms blattms Nov 27, 2024

Choose a reason for hiding this comment

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

I am still not sure. Do we test how things should be below, or do we test in a certain way, just to make the test succeed for now (i.e. 145 is actually not the correct number). If it is the latter then the comment does not really tell me that.

@aritorto
Copy link
Member Author

jenkins build this serial please

Copy link
Member

@blattms blattms left a comment

Choose a reason for hiding this comment

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

Thanks. Fair enough. Merging

@blattms blattms merged commit ec75718 into OPM:master Nov 27, 2024
1 check passed
@aritorto aritorto deleted the splitCode branch December 4, 2024 11:16
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.

3 participants