Skip to content

Commit

Permalink
Use lambda without if (#17)
Browse files Browse the repository at this point in the history
* Revert "Reduce code duplication in markElem... detectActiveLgrs"

This reverts commit bffee42.

* Use helper function with lambda
  • Loading branch information
blattms authored and aritorto committed Dec 3, 2024
1 parent 4f59eaa commit ae2fc66
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 89 deletions.
51 changes: 36 additions & 15 deletions opm/grid/CpGrid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,26 +1083,47 @@ namespace Dune
bool nonNNCsSelectedCellsLGR( const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec) const;

/// @brief Detect active LGRs, mark element and assign their level.
/// @brief Detect active LGRs in each process.
///
/// Given blocks of cells selected for refinement on a level zero distributed grid, detect which LGRs are active
/// in each process. If "onlyDetectLgrs = false", additionally, mark selected elements and assign them their corresponding
/// (refined) level (grid).
/// in each process.
///
/// @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.
/// @param [in] onlyDetectLgrs If true, the return the second vector of the return pair<vector<int>, vector<int>> is empty
/// since the method will only detect the active lgrs, and skip marking elements and assigning
/// their levels. If false, both pair.fisrt (representing active lgrs) and pair.second
/// (representing the assigned refined levels) will be populated
/// @return [lgr_with_at_least_one_active_cell, Determine if an LGR is not empty in a given process, we set
/// assignRefinedLevel] lgr_with_at_least_one_active_cell[in that level] to 1 if it contains
/// at least one active cell, and to 0 otherwise.
/// Assign level for the refinement of each marked cell. Example: refined
/// element from LGR1 have level 1, refined element rfom LGR2 have level 2, etc.
std::pair<std::vector<int>, std::vector<int>> markElemAssignLevelDetectActiveLgrs(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
bool onlyDetectLgrs);
/// @param [out] lgr_with_at_least_one_active_cell Determine if an LGR is not empty in a given process, we set
/// lgr_with_at_least_one_active_cell[in that level] to 1 if it contains
/// at least one active cell, and to 0 otherwise.
void detectActiveLgrs(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
std::vector<int>& lgr_with_at_least_one_active_cell);

/// @brief Mark selected elements, assign them their corresponding level, and detect active LGRs.
///
/// Given blocks of cells selected for refinement, mark selected elements and assign them their corresponding
/// (refined) level (grid). When level zero grid is distributed before refinement, detect which LGRs are active
/// in each process.
///
/// @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.
/// @param [out] assignRefinedLevel Assign level for the refinement of each marked cell. Example: refined element from
/// LGR1 have level 1, refined element rfom LGR2 have level 2, etc.
/// @param [out] lgr_with_at_least_one_active_cell Determine if an LGR is not empty in a given process, we set
/// lgr_with_at_least_one_active_cell[in that level] to 1 if it contains
/// at least one active cell, and to 0 otherwise.
void markElemAssignLevelDetectActiveLgrs(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
std::vector<int>& assignRefinedLevel,
std::vector<int>& lgr_with_at_least_one_active_cell);

/// @brief Auxilliary function to compute one or more properties on selected block of parent cells.
///
/// @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.
/// @param [in] function Lambda expression/function that computes the desired properties for each parent cell.
template<class T>
void computeOnLgrParents(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
T func);

/// @brief Predict minimum cell and point global ids per process.
///
Expand Down
113 changes: 71 additions & 42 deletions opm/grid/cpgrid/CpGrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,26 +1020,22 @@ void CpGrid::globalRefine (int refCount)
OPM_THROW(std::logic_error, "Global refinement of a mixed grid with coarse and refined cells is not supported yet.");
}
}
// For a distributed grid, global refinement can be called only once - for now.
if ( (refCount>1) && (!distributed_data_.empty()) ) {
OPM_THROW(std::logic_error, "Multiple calls of global refinement on a distributed grid are not supported yet.");
}
if (refCount>0) {
const std::vector<std::array<int,3>>& cells_per_dim_vec = {{2,2,2}}; // Arbitrary chosen values.
for (int refinedLevel = 0; refinedLevel < refCount; ++refinedLevel) {

std::vector<int> assignRefinedLevel(current_view_data_-> size(0));
const auto& preAdaptMaxLevel = this ->maxLevel();
std::vector<std::string> lgr_name_vec = { "GR" + std::to_string(preAdaptMaxLevel +1) };
bool isCARFIN = true;
const std::array<int,3>& endIJK = currentData().back()->logicalCartesianSize();

for(const auto& element: elements(this-> leafGridView())) {
// Mark all the elements of the current leaf grid view for refinement
mark(1, element);
assignRefinedLevel[element.index()] = preAdaptMaxLevel +1;
}

std::vector<std::string> lgr_name_vec = { "GR" + std::to_string(preAdaptMaxLevel +1) };
bool isCARFIN = true;
const std::array<int,3>& endIJK = currentData().back()->logicalCartesianSize();
preAdapt();
adapt(cells_per_dim_vec, assignRefinedLevel, lgr_name_vec, isCARFIN, {{0,0,0}}, {endIJK});
postAdapt();
Expand Down Expand Up @@ -1260,30 +1256,11 @@ bool CpGrid::nonNNCsSelectedCellsLGR( const std::vector<std::array<int,3>>& star
return true;
}

std::pair<std::vector<int>, std::vector<int>> CpGrid::markElemAssignLevelDetectActiveLgrs(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
bool onlyDetectLgrs)
template<class T>
void CpGrid::computeOnLgrParents(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
T func)
{
// Auxiliary function.
// If onlyDetectLgrs == true, then only activeLgrs gets populated.
// Otherwise, both activeLgrs and assignLevel get populated.
auto detectLgrs_maybeAssignLevel = [this](const Dune::cpgrid::Entity<0>& element,
int level,
std::vector<int>& active_lgrs,
std::vector<int>& assign_level,
bool only_detect_lgrs)
{
// shifted since starting grid is level 0, and refined grids levels are >= 1.
active_lgrs[level] = 1;
if (!only_detect_lgrs)
{
this-> mark(1, element);
assign_level[element.index()] = level+1; // shifted since starting grid is level 0, and refined grids levels are >= 1.
}
};

std::vector<int> activeLgrs(startIJK_vec.size());
std::vector<int> assignLevel(onlyDetectLgrs ? 0 : currentData().back()->size(0));
// Find out which (ACTIVE) elements belong to the block cells defined by startIJK and endIJK values.
for(const auto& element: elements(this->leafGridView())) {
std::array<int,3> ijk;
Expand All @@ -1296,11 +1273,37 @@ std::pair<std::vector<int>, std::vector<int>> CpGrid::markElemAssignLevelDetectA
break;
}
if(belongsToLevel) {
detectLgrs_maybeAssignLevel(element, level, activeLgrs, assignLevel, onlyDetectLgrs);
func(element, level);
}
}
}
return std::make_pair<std::vector<int>, std::vector<int>>(std::move(activeLgrs), std::move(assignLevel));
}

void CpGrid::detectActiveLgrs(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
std::vector<int>& lgr_with_at_least_one_active_cell)
{
auto markLgr = [&lgr_with_at_least_one_active_cell]([[maybe_unused]] const cpgrid::Entity<0>& element, int level)
{
// shifted since starting grid is level 0, and refined grids levels are >= 1.
lgr_with_at_least_one_active_cell[level] = 1;
};
computeOnLgrParents(startIJK_vec, endIJK_vec, markLgr);
}

void CpGrid::markElemAssignLevelDetectActiveLgrs(const std::vector<std::array<int,3>>& startIJK_vec,
const std::vector<std::array<int,3>>& endIJK_vec,
std::vector<int>& assignRefinedLevel,
std::vector<int>& lgr_with_at_least_one_active_cell)
{
auto assignAndDetect = [this, &assignRefinedLevel, &lgr_with_at_least_one_active_cell](const cpgrid::Entity<0>& element, int level)
{
mark(1, element);
assignRefinedLevel[element.index()] = level+1;
// shifted since starting grid is level 0, and refined grids levels are >= 1.
lgr_with_at_least_one_active_cell[level] = 1;
};
computeOnLgrParents(startIJK_vec, endIJK_vec, assignAndDetect);
}

void CpGrid::predictMinCellAndPointGlobalIdPerProcess([[maybe_unused]] const std::vector<int>& assignRefinedLevel,
Expand Down Expand Up @@ -1942,11 +1945,37 @@ bool CpGrid::adapt()
std::vector<int> assignRefinedLevel(current_view_data_-> size(0));
const auto& preAdaptMaxLevel = this ->maxLevel();

int local_marked_elem_count = 0;
for (int elemIdx = 0; elemIdx < 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;
if (this->getMark(element) == 1) {
++local_marked_elem_count;
}
}

// Check if its a global refinement
bool is_global_refine = false;
std::vector<std::string> lgr_name_vec = { "LGR" + std::to_string(preAdaptMaxLevel +1) };
// Rewrite if global refinement
#if HAVE_MPI
auto global_marked_elem_count = comm().sum(local_marked_elem_count);
auto global_cell_count_before_adapt = comm().sum(current_view_data_-> size(0)); // Recall overlap cells are also marked
if (global_marked_elem_count == global_cell_count_before_adapt) {
// GR stands for GLOBAL REFINEMET
lgr_name_vec = { "GR" + std::to_string(preAdaptMaxLevel +1) };
is_global_refine = true; // parallel
}
#endif
if ( (comm().size() == 0) && (local_marked_elem_count == current_view_data_-> size(0)) ) {
// GR stands for GLOBAL REFINEMET
lgr_name_vec = { "GR" + std::to_string(preAdaptMaxLevel +1) };
is_global_refine = true; // sequential
}
if (is_global_refine) { // parallel or sequential
const std::array<int,3>& endIJK = currentData().back()->logicalCartesianSize();
return this->adapt(cells_per_dim_vec, assignRefinedLevel, lgr_name_vec, is_global_refine, {{0,0,0}}, {endIJK});
}
return this-> adapt(cells_per_dim_vec, assignRefinedLevel, lgr_name_vec);
}

Expand All @@ -1973,11 +2002,8 @@ bool CpGrid::adapt(const std::vector<std::array<int,3>>& cells_per_dim_vec,
// To determine if an LGR is not empty in a given process, we set
// lgr_with_at_least_one_active_cell[in that level] to 1 if it contains
// at least one active cell, and to 0 otherwise.
// "rubissh" denotes an empty vector. The method 'markElemAssignLevelDetectActiveLgrs' skips marking elements and the assignment of their
// level when the passed boolean is 'true' ("onlyDetectLgrs").
const auto& [lgr_with_at_least_one_active_cell, rubissh] = markElemAssignLevelDetectActiveLgrs(startIJK_vec,
endIJK_vec,
true /*onlyDetectLgrs*/);
std::vector<int> lgr_with_at_least_one_active_cell(levels);
detectActiveLgrs(startIJK_vec, endIJK_vec, lgr_with_at_least_one_active_cell);

// To store/build refined level grids.
std::vector<std::vector<std::shared_ptr<Dune::cpgrid::CpGridData>>> refined_data_vec(levels, data);
Expand Down Expand Up @@ -2403,7 +2429,7 @@ bool CpGrid::adapt(const std::vector<std::array<int,3>>& cells_per_dim_vec,
this->global_id_set_ptr_->insertIdSet(*data[refinedLevelGridIdx]);
}

// Only for parallel runs
// Only for parallel runs
// - Define global ids for refined level grids (level 1, 2, ..., maxLevel)
// - Define GlobalIdMapping (cellMapping, faceMapping, pointMapping required per level)
// - Define ParallelIndex for overlap cells and their neighbors
Expand Down Expand Up @@ -2594,13 +2620,16 @@ void CpGrid::addLgrsUpdateLeafView(const std::vector<std::array<int,3>>& cells_p
OPM_THROW(std::logic_error, "NNC face on a cell containing LGR is not supported yet.");
}

// Determine the assigned level for the refinement of each marked cell
std::vector<int> assignRefinedLevel(current_view_data_->size(0));
// To determine if an LGR is not empty in a given process, we set
// lgr_with_at_least_one_active_cell[in that level] to 1 if it contains
// at least one active cell, and to 0 otherwise.
// Determine the assigned level for the refinement of each marked cell
const auto& [lgr_with_at_least_one_active_cell, assignRefinedLevel] = markElemAssignLevelDetectActiveLgrs(startIJK_vec,
endIJK_vec,
false /*onlydetecLgrs*/);
std::vector<int> lgr_with_at_least_one_active_cell(startIJK_vec.size());
markElemAssignLevelDetectActiveLgrs(startIJK_vec,
endIJK_vec,
assignRefinedLevel,
lgr_with_at_least_one_active_cell);

int non_empty_lgrs = 0;
for (std::size_t level = 0; level < startIJK_vec.size(); ++level) {
Expand Down
41 changes: 9 additions & 32 deletions tests/cpgrid/addLgrsOnDistributedGrid_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ BOOST_AUTO_TEST_CASE(throw_not_fully_interior_lgr)
}
}

//Calling (only once, with argument equal to 1) globalRefine on a distributed grid is supported now.
//Calling globalRefine on a distributed grid is supported now.
BOOST_AUTO_TEST_CASE(globalRefine1)
{
// Create a grid
Expand Down Expand Up @@ -715,7 +715,7 @@ BOOST_AUTO_TEST_CASE(globalRefine2)
const std::array<int, 3> grid_dim = {4,3,3};
grid.createCartesian(grid_dim, cell_sizes);

std::vector<int> parts(36);
std::vector<int> parts(36);
std::vector<std::vector<int>> cells_per_rank = { {0,1,4,5,8,9,16,20,21},
{12,13,17,24,25,28,29,32,33},
{2,3,6,7,10,11,18,22,23},
Expand All @@ -739,29 +739,6 @@ BOOST_AUTO_TEST_CASE(globalRefine2)
}
}

BOOST_AUTO_TEST_CASE(globalRefine_throw)
{
// Create a grid
Dune::CpGrid grid;
const std::array<double, 3> cell_sizes = {1.0, 1.0, 1.0};
const std::array<int, 3> grid_dim = {4,2,1};
grid.createCartesian(grid_dim, cell_sizes);

std::vector<int> parts(8);
std::vector<std::vector<int>> cells_per_rank = {{0,4},{1,5},{2,6}, {3,7}};
for (int rank = 0; rank < 4; ++rank) {
for (const auto& elemIdx : cells_per_rank[rank]) {
parts[elemIdx] = rank;
}
}
// Distribute the grid
if(grid.comm().size()>1)
{
grid.loadBalance();
BOOST_CHECK_THROW(grid.globalRefine(2), std::logic_error);
}
}

BOOST_AUTO_TEST_CASE(distributed_lgr)
{
// Create a grid
Expand Down Expand Up @@ -1053,8 +1030,8 @@ BOOST_AUTO_TEST_CASE(call_adapt_with_args_on_distributed_grid)
}
}

// Cannot call adapt() on a distribted grid
/*BOOST_AUTO_TEST_CASE(call_adapt_on_distributed_grid)
// Call adapt() on a distribted grid, marking all the elements (equivalent to call globalRefine).
BOOST_AUTO_TEST_CASE(call_adapt_on_distributed_grid)
{
// Only for testing assignment of new global ids for refined entities (cells and point belonging to
// refined level grids).
Expand All @@ -1066,9 +1043,9 @@ BOOST_AUTO_TEST_CASE(call_adapt_with_args_on_distributed_grid)
grid.createCartesian(grid_dim, cell_sizes);
std::vector<int> parts(36);
std::vector<std::vector<int>> cells_per_rank = { {0,1,4,5,8,9,16,20,21},
{12,13,17,24,25,28,29,32,33},
{2,3,6,7,10,11,18,22,23},
{14,15,19,26,27,30,31,34,35} };
{12,13,17,24,25,28,29,32,33},
{2,3,6,7,10,11,18,22,23},
{14,15,19,26,27,30,31,34,35} };
for (int rank = 0; rank < 4; ++rank) {
for (const auto& elemIdx : cells_per_rank[rank]) {
parts[elemIdx] = rank;
Expand All @@ -1077,7 +1054,7 @@ BOOST_AUTO_TEST_CASE(call_adapt_with_args_on_distributed_grid)
if(grid.comm().size()>1)
{
grid.loadBalance(parts);
// Mark all elements -> indirect global refinement
// Mark all elements -> 'indirect' global refinement
for (const auto& element : elements(grid.leafGridView())){
grid.mark(1, element);
}
Expand All @@ -1092,5 +1069,5 @@ BOOST_AUTO_TEST_CASE(call_adapt_with_args_on_distributed_grid)

refinePatch_and_check(grid, cells_per_dim_vec, startIJK_vec, endIJK_vec, lgr_name_vec);
}
}*/
}

0 comments on commit ae2fc66

Please sign in to comment.