-
Notifications
You must be signed in to change notification settings - Fork 78
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
Improve refinement and partially support adaptivity for CpGrid #723
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work!
I will try to do this review iteratively. This is the review of CpGridData.cpp
// Refined cells in parent cell: k*cells_per_dim[0]*cells_per_dim[1] + j*cells_per_dim[0] + i | ||
std::array<int,3> ijk = {0,0,0}; | ||
ijk[0] = idxInParentCell % cells_per_dim[0]; | ||
idxInParentCell -= ijk[0]; // k*cells_per_dim[0]*cells_per_dim[1] + j*cells_per_dim[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick:
The subtractions don't hurt, but I think they are not needed.
Integer devision should make sure that (M+n)/N == M/N
holds for n<N
and M being a multiple of N.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I skip this one for now, might come back once I'm done with the other comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Next batch of comments. Still two files to comment on.
tests/cpgrid/adapt_cpgrid_test.cpp
Outdated
{ | ||
const auto& elem = Dune::cpgrid::Entity<0>(*(coarse_grid.chooseData()[startingGridIdx]), elemIdx, true); | ||
coarse_grid.mark(1, elem); | ||
coarse_grid.getMark(elem); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line could be removed. The check of the return value is 2 lines below, anyway.
tests/cpgrid/adapt_cpgrid_test.cpp
Outdated
auto equiv_cell_iter = blockRefinement_leaf.geomVector<3>().begin(); | ||
while (cell.center() != equiv_cell_iter->center()) { | ||
++equiv_cell_iter; | ||
} | ||
CHECK_COORDINATES(cell.center(), equiv_cell_iter->center()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto equiv_cell_iter = blockRefinement_leaf.geomVector<3>().begin(); | |
while (cell.center() != equiv_cell_iter->center()) { | |
++equiv_cell_iter; | |
} | |
CHECK_COORDINATES(cell.center(), equiv_cell_iter->center()); | |
auto equiv_cell_iter = std::find_if(blockRefinement_leaf.geomVector<3>().begin(), | |
blockRefinement_leaf.geomVector<3>().end(), | |
[center1 = cell.center](const auto& center1){ | |
return center1 == equiv_cell_iter->center()) | |
}); | |
BOOST_CHECK( equiv_cell_iter != blockRefinement_leaf.geomVector<3>().end()); |
The last line was already checked in the loop.
We should probably allow the centers to differ a bit inside of the lambda and use some tolerance when comparing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had some trouble with that lambda, but I did add the check of the iterator not being at the end.
tests/cpgrid/adapt_cpgrid_test.cpp
Outdated
CHECK_COORDINATES(cell.center(), equiv_cell_iter->center()); | ||
for(const auto& coord: cell.center()) | ||
BOOST_TEST(std::isfinite(coord)); | ||
BOOST_CHECK_CLOSE(cell.volume(), equiv_cell_iter->volume(), 1e-6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could try to lower the tolerance here.
tests/cpgrid/adapt_cpgrid_test.cpp
Outdated
bool closedCenter = (std::abs(element.geometry().center()[0] - equiv_element_iter->geometry().center()[0]) < 1e-12) && | ||
(std::abs(element.geometry().center()[1] - equiv_element_iter->geometry().center()[1]) < 1e-12) && | ||
(std::abs(element.geometry().center()[2] - equiv_element_iter->geometry().center()[2])< 1e-12); | ||
|
||
while (!closedCenter) { | ||
++equiv_element_iter; | ||
closedCenter = (std::abs(element.geometry().center()[0] - equiv_element_iter->geometry().center()[0]) < 1e-12) && | ||
(std::abs(element.geometry().center()[1] - equiv_element_iter->geometry().center()[1]) < 1e-12) && | ||
(std::abs(element.geometry().center()[2] - equiv_element_iter->geometry().center()[2])< 1e-12); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make the bullet-proof we should check whether the equiv_element_iter is valid:
while (equiv_element_iter != equiv_grid_view.end<0>() && !closedCenter)
Maybe even use std::find_if
from the STL instead like suggested above? The we only need to check the return value of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm adding the check that the iterator is not the end one (in many places). With the lambda-expression suggested, I'm having some issues. I postpone that change for now. Thanks!
tests/cpgrid/adapt_cpgrid_test.cpp
Outdated
referenceElem_entity_center[c] /= cells_per_dim[0]*cells_per_dim[1]*cells_per_dim[2]; | ||
referenceElem_entity_center_it[c] /= cells_per_dim[0]*cells_per_dim[1]*cells_per_dim[2]; | ||
} | ||
BOOST_CHECK_CLOSE(referenceElemOneParent_volume, 1, 1e-6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could try to tighten the tolerance a bit here. On the other hand the grid is large enough, so there is probably no change for now.
tests/cpgrid/grid_lgr_test.cpp
Outdated
while (!closedCenter) { | ||
++equiv_element_iter; | ||
closedCenter = (std::abs(element.geometry().center()[0] - equiv_element_iter->geometry().center()[0]) < 1e-12) && | ||
(std::abs(element.geometry().center()[1] - equiv_element_iter->geometry().center()[1]) < 1e-12) && | ||
(std::abs(element.geometry().center()[2] - equiv_element_iter->geometry().center()[2])< 1e-12); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment here as for the other test file. Check whether equiv_element_iter
is invalid or even better use an STL algorithm,
// To determine that, we track the level of the Entity and | ||
// check if it was marked for refinement in the previos state | ||
// of current_view_data_ | ||
return (isLeaf() && hasFather()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed this is WIP but works for only refining once. For multiple refinement we need to do this differently
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the WIP is accidentally still there. From your comment, I'm assuming I should keep it. Maybe this is also related to my potentially wrong interpretation of preAdapt, adapt, postAdapt...
bool Entity<codim>::mightVanish() const | ||
{ | ||
const auto refinementMark = pgrid_ -> getMark(*this); | ||
return (refinementMark == 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I this tested?
Shouldn't this be `return refinementMark < 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably again related to my interpretation of how the marking-elements process goes. I assume that when your stating grid is certain_grid with N cells, you marked some element on that grid, let's sat n1< ... < nr < N. Those marked element get mark equal to 1 when they will vanished and replaced by their refined children cells. Is this correct? When the mark is 0 or -1, it means "do nothing" or "coarsening (not supported yet, and in this case, this cell and "all its siblings cells" will vanish)".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a few comments in some of the places where mightVanish() get tested, in adapted_cpgrid_test.cpp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One file to go.
opm/grid/CpGrid.hpp
Outdated
const std::shared_ptr<cpgrid::CpGridData>& elemLgr_ptr) const; | ||
|
||
/// @brief Determine if a refined corner is located on the boundary of the single-cell-refinement, and does not coincide with | ||
/// a preApradt-existing corner. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// a preApradt-existing corner. | |
/// a preAdapt-existing corner. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the next portion of my review.
Last file (CpGrid.cpp) is the largest to review. This is the first part. I am at defineChildToParentAndIdxInParentCell
opm/grid/cpgrid/CpGrid.cpp
Outdated
if(data_.size()>1) { | ||
// Get the level where the element was born and its index in that level. | ||
const auto& elemLevel = element.level(); | ||
const auto& elemInLevel = (elemLevel == 0) ? element.getOrigin() : element.getLevelElem(); | ||
// Mark element in its level | ||
data_[elemLevel] -> mark(refCount, elemInLevel); | ||
} | ||
// Mark element (also) in current_view_data_ | ||
return current_view_data_-> mark(refCount, element); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we make sure that CpGridData::mark
is written such that it allows us to write (please skip if we can't):
if(data_.size()>1) { | |
// Get the level where the element was born and its index in that level. | |
const auto& elemLevel = element.level(); | |
const auto& elemInLevel = (elemLevel == 0) ? element.getOrigin() : element.getLevelElem(); | |
// Mark element in its level | |
data_[elemLevel] -> mark(refCount, elemInLevel); | |
} | |
// Mark element (also) in current_view_data_ | |
return current_view_data_-> mark(refCount, element); | |
const auto& elemLevel = element.level(); | |
return data_[elemLevel] -> mark(refCount, elemInLevel); |
Note that I removed marking on the current_view_data_. Do we need that? If that is the case then please keep it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I skip this comment until we meet and define how to design the adapt process ( in which grid we are allowed to mark elements, etc)
opm/grid/cpgrid/CpGrid.cpp
Outdated
|
||
bool CpGrid::adapt() | ||
{ | ||
const std::vector<std::array<int,3>>& cells_per_dim_vec = {{3,3,3}}; // Arbitrary chosen values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think {2, 2, 2}
would be more intuitive, at least for me. Might not be the case for others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's trust in your intuition then :)
const auto& preAdaptMaxLevel = this ->maxLevel(); | ||
for (int elemIdx = 0; elemIdx < static_cast<int>(current_view_data_->size(0)); ++elemIdx) { | ||
const auto& element = cpgrid::Entity<0>(*current_view_data_, elemIdx, true); | ||
assignRefinedLevel[elemIdx] = (this->getMark(element) == 1) ? (preAdaptMaxLevel +1) : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe more future proof for the case of multiple levels.
assignRefinedLevel[elemIdx] = (this->getMark(element) == 1) ? (preAdaptMaxLevel +1) : 0; | |
assignRefinedLevel[elemIdx] = (this->getMark(element) == 1) ? (element.level() + 1) : element.level(); |
Note that the purpose of assignRefinedLevel is not 100% clear to me. So I could very well be wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clearer now. It is the level where the kids will be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! I'll add this in the list of things to be discussed, just in case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Next batch of comments.
I am still in CpGrid.cpp. Now function CpGrid::identifyRefinedCornersPerLevel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Next batch.
I still want to check the functions in line 3440 and below (CpGrid::isRefinedCornerInInteriorLgr, etc.).
@blattms many thanks for your valuable feedback! I believe I handled all/most of your comments (being the main: (1) change count-argument with find-approach, and (2) solve the dangling pointers issue via swap). I would say this PR is ready for a "final review" |
jenkins build this please |
@blattms Changes are pushed now! Many thanks again! |
jenkins build this please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the updates.
jenkins build this please |
This PR
Marking cells with no neighboring connections for refinement is not supported yet.
Cells can be marked for refinement, without any assumption on the shape of the total cells to be refined. Previously, only a block of cells.
The adapted grid is the mix of coarse cells (not involved in refinement) and the refined entities.