Skip to content

Commit 99aa1cc

Browse files
hnilclaude
andcommitted
CpGrid: build point communication interfaces from all points of a cell
The codim-3 (point) communication interface and the point-via-cell data handle were built from cell_to_point_, i.e. only the eight canonical corners of each cell. On corner-point grids with hanging nodes a face can reference nodes that are not canonical corners of the neighbouring cell; such nodes never entered point_interfaces_, so they were invisible to codim-3 communication and their ownership failed to be a partition of unity across ranks (observed as 'Owner is not a partition of unity' in vertex-based mechanics assembly). Introduce cell_to_allpoint_ (SparseTable: every node of every face of each cell, sorted and deduplicated) and use it for the point interface and for PointViaCellHandleWrapper. AttributeDataHandle::fixedSize() now returns false since rows vary in length, and row iteration uses the SparseTable iterators. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent c8d9f45 commit 99aa1cc

3 files changed

Lines changed: 49 additions & 9 deletions

File tree

opm/grid/cpgrid/CpGridData.cpp

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ PartitionType getPartitionType(const PartitionTypeIndicator& p, int i,
206206
return p.getPartitionType(Entity<3>(grid, i, true));
207207
}
208208

209+
// Row entries of Opm::SparseTable<int> are visited through this iterator type.
210+
int getIndex(std::vector<int>::const_iterator i)
211+
{
212+
return *i;
213+
}
214+
209215
int getIndex(const int* i)
210216
{
211217
return *i;
@@ -934,7 +940,8 @@ struct AttributeDataHandle
934940

935941
bool fixedSize()
936942
{
937-
return true;
943+
// SparseTable rows have varying length (all points of a cell).
944+
return false;
938945
}
939946
std::size_t size(std::size_t i)
940947
{
@@ -943,8 +950,7 @@ struct AttributeDataHandle
943950
template<class B>
944951
void gather(B& buffer, std::size_t i)
945952
{
946-
typedef typename GetRowType<T>::type::const_iterator RowIter;
947-
for(RowIter f=c2e_[i].begin(), fend=c2e_[i].end();
953+
for(auto f=c2e_[i].begin(), fend=c2e_[i].end();
948954
f!=fend; ++f)
949955
{
950956
char t=getPartitionType(indicator_, *f, grid_);
@@ -955,8 +961,7 @@ struct AttributeDataHandle
955961
template<class B>
956962
void scatter(B& buffer, std::size_t i, std::size_t s)
957963
{
958-
typedef typename GetRowType<T>::type::const_iterator RowIter;
959-
for(RowIter f=c2e_[i].begin(), fend=c2e_[i].end();
964+
for(auto f=c2e_[i].begin(), fend=c2e_[i].end();
960965
f!=fend; ++f, --s)
961966
{
962967
std::pair<int,char> rank_attr;
@@ -1697,10 +1702,40 @@ void CpGridData::computeCommunicationInterfaces([[maybe_unused]] int noExistingP
16971702
face_interfaces_);
16981703
std::vector<std::map<int,char> >().swap(face_attributes);
16991704
*/
1705+
// Build the point (codim 3) communication interface from ALL points of
1706+
// each cell -- every node of every face -- not only the eight canonical
1707+
// corners stored in cell_to_point_. On corner-point grids with hanging
1708+
// nodes a face can reference nodes that are not canonical corners of the
1709+
// neighbouring cell; interfaces built from the canonical corners only
1710+
// miss those nodes, leaving them without communication (node ownership
1711+
// then fails to be a partition of unity).
1712+
// The gather/scatter of AttributeDataHandle pairs entries of the
1713+
// sender's and the receiver's row for the same cell BY POSITION, so the
1714+
// rows must list the points in an order that is identical on every rank
1715+
// sharing the cell. Local point indices differ between ranks; the
1716+
// face/point traversal order is copied from the global grid during
1717+
// distribution and is rank-independent. Deduplicate while preserving
1718+
// the first-occurrence traversal order -- do NOT sort by local index.
1719+
const std::size_t nc = cell_to_point_.size();
1720+
std::vector<int> points;
1721+
for (std::size_t cell = 0; cell < nc; ++cell) {
1722+
points.clear();
1723+
const auto& faces = cell_to_face_[cpgrid::EntityRep<0>(cell, true)];
1724+
const int nf = faces.size();
1725+
for (int f = 0; f < nf; ++f) {
1726+
for (const auto& fv : face_to_point_[faces[f].index()]) {
1727+
if (std::find(points.begin(), points.end(), fv) == points.end()) {
1728+
points.push_back(fv);
1729+
}
1730+
}
1731+
}
1732+
cell_to_allpoint_.appendRow(points.begin(), points.end());
1733+
}
1734+
17001735
std::vector<std::map<int,char> > point_attributes(noExistingPoints);
1701-
AttributeDataHandle<std::vector<std::array<int,8> > >
1736+
AttributeDataHandle<Opm::SparseTable<int> >
17021737
point_handle(ccobj_.rank(), *partition_type_indicator_,
1703-
point_attributes, cell_to_point_, *this);
1738+
point_attributes, cell_to_allpoint_, *this);
17041739
if( static_cast<const Dune::Interface&>(std::get<All_All_Interface>(cell_interfaces_))
17051740
.interfaces().size() )
17061741
{
@@ -1928,7 +1963,7 @@ bool CpGridData::preAdapt()
19281963
if (local_empty)
19291964
mark_.resize(size(0));
19301965
}
1931-
1966+
19321967
// Detect the maximum mark across processes, and rewrite
19331968
// the local entry in mark_, i.e.,
19341969
// mark_[ element.index() ] = max{ local marks in processes where this element belongs to}.

opm/grid/cpgrid/CpGridData.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,11 @@ class CpGridData
775775
cpgrid::OrientedEntityTable<1, 0> face_to_cell_;
776776
/** @brief Container for the lookup of the points for each face. */
777777
Opm::SparseTable<int> face_to_point_;
778+
/** @brief All points of each cell, i.e. every point of every face of the
779+
* cell, not only the eight canonical corners. On corner-point grids
780+
* with hanging nodes the extra points are essential for building
781+
* complete codim-3 communication interfaces. */
782+
Opm::SparseTable<int> cell_to_allpoint_;
778783
/** @brief Vector that contains an arrays of the points of each cell*/
779784
std::vector< std::array<int,8> > cell_to_point_;
780785
/** @brief The size of the underlying logical cartesian grid.

opm/grid/cpgrid/DataHandleWrappers.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ template<class Handle>
148148
struct PointViaCellHandleWrapper : public PointViaCellWarner
149149
{
150150
using DataType = typename Handle::DataType;
151-
using C2PTable = std::vector< std::array<int,8> >;
151+
using C2PTable = Opm::SparseTable<int>;
152152

153153
/// \brief Constructs the data handle
154154
///

0 commit comments

Comments
 (0)