41 using GridView =
typename LinearSolverTraits::GridView;
42 using DofMapper =
typename LinearSolverTraits::DofMapper;
45 static constexpr std::size_t ghostMarker_ = 1<<24;
47 class BaseGatherScatter
49 static constexpr int numCodims_ = GridView::dimension + 1;
51 static constexpr auto getActiveCodims_()
53 if constexpr (
requires { LinearSolverTraits::dofCodims; })
54 return LinearSolverTraits::dofCodims;
56 return std::bitset<numCodims_>{ 1UL << LinearSolverTraits::dofCodim };
60 BaseGatherScatter(
const DofMapper& mapper)
63 template<
class EntityType>
64 int index(
const EntityType& e)
const
65 {
return mapper_.index(e); }
67 template<
class EntityType>
68 auto indices(
const EntityType& e)
const
71 bool contains(
int dim,
int codim)
const
72 {
return codim >= 0 && codim < numCodims_ && activeCodims_.test(codim); }
76 bool fixedSize(
int dim,
int codim)
const
78 if (codim < 0 || codim >= numCodims_ || !activeCodims_.test(codim))
return true;
79 const auto& gtypes = mapper_.types(codim);
80 if (gtypes.empty())
return true;
81 const auto nDofs = mapper_.size(gtypes[0]);
82 for (
const auto& gt : gtypes)
83 if (mapper_.size(gt) != nDofs)
return false;
88 template<
class EntityType>
89 std::size_t size(EntityType& e)
const
92 template<
class EntityType>
93 bool isNeitherInteriorNorBorderEntity(EntityType& e)
const
94 {
return e.partitionType() != Dune::InteriorEntity && e.partitionType() != Dune::BorderEntity; }
97 const DofMapper& mapper_;
99 static constexpr auto activeCodims_ = getActiveCodims_();
108 class GhostGatherScatter
109 :
public BaseGatherScatter
110 ,
public Dune::CommDataHandleIF<GhostGatherScatter, std::size_t>
113 using DataType = std::size_t;
114 using BaseGatherScatter::contains;
115 using BaseGatherScatter::fixedSize;
116 using BaseGatherScatter::size;
118 GhostGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
119 : BaseGatherScatter(mapper)
123 template<
class MessageBuffer,
class EntityType>
124 void gather(MessageBuffer& buff,
const EntityType& e)
const
126 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
127 for (
auto i : this->indices(e)) {
128 auto& data = ranks_[i];
129 if (
isGhost) data = ghostMarker_;
134 template<
class MessageBuffer,
class EntityType>
135 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
137 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
138 for (
auto i : this->indices(e)) {
141 if (
isGhost) ranks_[i] = ghostMarker_;
145 std::vector<std::size_t>& ranks_;
154 class InteriorBorderGatherScatter
155 :
public BaseGatherScatter
156 ,
public Dune::CommDataHandleIF<InteriorBorderGatherScatter, std::size_t>
159 using DataType = std::size_t;
160 using BaseGatherScatter::contains;
161 using BaseGatherScatter::fixedSize;
162 using BaseGatherScatter::size;
164 InteriorBorderGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
165 : BaseGatherScatter(mapper)
172 template<
class MessageBuffer,
class EntityType>
173 void gather(MessageBuffer& buff,
const EntityType& e)
const
175 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
176 for (
auto i : this->indices(e)) {
177 auto& data = ranks_[i];
178 if (
isGhost) data = ghostMarker_;
186 template<
class MessageBuffer,
class EntityType>
187 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
189 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
190 for (
auto i : this->indices(e)) {
193 auto& data = ranks_[i];
198 data =
isGhost ? x : min(data, x);
202 std::vector<std::size_t>& ranks_;
209 struct NeighbourGatherScatter
210 :
public BaseGatherScatter
211 ,
public Dune::CommDataHandleIF<NeighbourGatherScatter, int>
213 using DataType = int;
214 using BaseGatherScatter::contains;
215 using BaseGatherScatter::fixedSize;
216 using BaseGatherScatter::size;
218 NeighbourGatherScatter(
const DofMapper& mapper,
int rank, std::set<int>& neighbours)
219 : BaseGatherScatter(mapper)
221 , neighbours_(neighbours)
225 template<
class EntityType>
226 std::size_t size(EntityType& e)
const {
return 1; }
227 bool fixedSize(
int dim,
int codim)
const {
return true; }
229 template<
class MessageBuffer,
class EntityType>
230 void gather(MessageBuffer& buff,
const EntityType& e)
const
235 template<
class MessageBuffer,
class EntityType>
236 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
240 neighbours_.insert(x);
244 std::set<int>& neighbours_;
251 struct SharedGatherScatter
252 :
public BaseGatherScatter
253 ,
public Dune::CommDataHandleIF<SharedGatherScatter, int>
255 using DataType = int;
256 using BaseGatherScatter::contains;
257 using BaseGatherScatter::fixedSize;
258 using BaseGatherScatter::size;
260 SharedGatherScatter(std::vector<int>& shared,
const DofMapper& mapper)
261 : BaseGatherScatter(mapper)
265 template<
class MessageBuffer,
class EntityType>
266 void gather(MessageBuffer& buff, EntityType& e)
const
268 for (std::size_t k = 0; k < this->indices(e).size(); ++k)
269 buff.write(
int(
true));
272 template<
class MessageBuffer,
class EntityType>
273 void scatter(MessageBuffer& buff,
const EntityType &e, std::size_t n)
275 for (
auto i : this->indices(e)) {
278 shared_[i] = shared_[i] || x;
282 std::vector<int>& shared_;
289 template<
typename GlobalIndex>
290 struct GlobalIndexGatherScatter
291 :
public BaseGatherScatter
292 ,
public Dune::CommDataHandleIF<GlobalIndexGatherScatter<GlobalIndex>, GlobalIndex>
294 using DataType = GlobalIndex;
295 using BaseGatherScatter::contains;
296 using BaseGatherScatter::fixedSize;
297 using BaseGatherScatter::size;
299 GlobalIndexGatherScatter(std::vector<GlobalIndex>& globalIndices,
const DofMapper& mapper)
300 : BaseGatherScatter(mapper)
301 , globalIndices_(globalIndices)
304 template<
class MessageBuffer,
class EntityType>
305 void gather(MessageBuffer& buff,
const EntityType& e)
const
307 for (
auto i : this->indices(e))
308 buff.write(globalIndices_[i]);
311 template<
class MessageBuffer,
class EntityType>
312 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
314 for (
auto i : this->indices(e)) {
318 globalIndices_[i] = min(globalIndices_[i], x);
322 std::vector<GlobalIndex>& globalIndices_;
328 : gridView_(
gridView), mapper_(mapper)
330 if constexpr (LinearSolverTraits::canCommunicate)
331 initGhostsAndOwners_();
333 DUNE_THROW(Dune::InvalidStateException,
334 "Cannot initialize parallel helper for a grid that cannot communicate."
339 {
return isGhost_[i] == ghostMarker_; }
342 {
return isOwned_[i] == 1; }
358 if constexpr (LinearSolverTraits::canCommunicate)
360 if (gridView_.comm().size() <= 1)
362 comm.remoteIndices().template rebuild<false>();
367 std::vector<int> isShared(mapper_.size(),
false);
368 SharedGatherScatter sgs(isShared, mapper_);
369 gridView_.communicate(sgs, Dune::All_All_Interface, Dune::ForwardCommunication);
372 using GlobalIndex =
typename Comm::ParallelIndexSet::GlobalIndex;
373 GlobalIndex count = 0;
374 for (std::size_t i = 0; i < isShared.size(); ++i)
375 if (isShared[i] && isOwned_[i] == 1)
378 std::vector<GlobalIndex> counts(gridView_.comm().size());
379 gridView_.comm().allgather(&count, 1, counts.data());
382 const int rank = gridView_.comm().rank();
383 auto start = std::accumulate(counts.begin(), counts.begin() + rank, GlobalIndex(0));
386 std::vector<GlobalIndex> globalIndices(mapper_.size(), std::numeric_limits<GlobalIndex>::max());
387 for (std::size_t i = 0; i < globalIndices.size(); ++i)
389 if (isOwned_[i] == 1 && isShared[i])
391 globalIndices[i] = start;
397 GlobalIndexGatherScatter<GlobalIndex> gigs(globalIndices, mapper_);
398 gridView_.communicate(gigs, Dune::All_All_Interface, Dune::ForwardCommunication);
401 resizeAndFillIndexSet_(comm, globalIndices);
404 std::set<int> neighbours;
405 NeighbourGatherScatter ngs(mapper_, gridView_.comm().rank(), neighbours);
406 gridView_.communicate(ngs, Dune::All_All_Interface, Dune::ForwardCommunication);
407 comm.remoteIndices().setNeighbours(neighbours);
409 comm.remoteIndices().template rebuild<false>();
412 DUNE_THROW(Dune::InvalidStateException,
413 "Cannot build parallel index set for a grid that cannot communicate."
423 {
return gridView_; }
434 void initGhostsAndOwners_()
436 const auto rank = gridView_.comm().rank();
437 isOwned_.assign(mapper_.size(), rank);
440 GhostGatherScatter ggs(isOwned_, mapper_);
442 if (gridView_.comm().size() > 1)
443 gridView_.communicate(ggs, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
451 InteriorBorderGatherScatter dh(isOwned_, mapper_);
453 if (gridView_.comm().size() > 1)
454 gridView_.communicate(dh, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication);
457 for (
auto& v : isOwned_)
458 v = (v == rank) ? 1 : 0;
461 template<
class Comm,
class GlobalIndices>
462 void resizeAndFillIndexSet_(Comm& comm,
const GlobalIndices& globalIndices)
const
464 comm.indexSet().beginResize();
468 for (std::size_t localIndex = 0; localIndex < globalIndices.size(); ++localIndex)
470 const auto globalIndex = globalIndices[localIndex];
471 if (globalIndex != std::numeric_limits<typename GlobalIndices::value_type>::max())
473 const bool isOwned = isOwned_[localIndex] > 0;
474 const auto attr = getAttribute_(comm, isOwned, isGhost(localIndex));
475 using LocalIndex =
typename Comm::ParallelIndexSet::LocalIndex;
476 comm.indexSet().add(globalIndex, LocalIndex{localIndex, attr});
480 comm.indexSet().endResize();
484 Dune::OwnerOverlapCopyAttributeSet::AttributeSet
485 getAttribute_(
const Comm& comm,
const bool isOwned,
const bool isGhost)
const
488 return Dune::OwnerOverlapCopyAttributeSet::owner;
489 else if (isGhost && (comm.category() == Dune::SolverCategory::nonoverlapping) )
490 return Dune::OwnerOverlapCopyAttributeSet::overlap;
492 return Dune::OwnerOverlapCopyAttributeSet::copy;
495 const GridView gridView_;
496 const DofMapper& mapper_;
498 std::vector<std::size_t> isOwned_;
500 std::vector<std::size_t> isGhost_;
666 using IdType =
typename GridView::Traits::Grid::Traits::GlobalIdSet::IdType;
673 friend bool operator<(
const DofIdKey& a,
const DofIdKey& b)
675 if (a.codim != b.codim)
676 return a.codim < b.codim;
702 template<
class ColIsGhostFunc>
703 struct MatrixPatternExchange
704 :
public Dune::CommDataHandleIF<MatrixPatternExchange<ColIsGhostFunc>, DofIdKey>
707 using DataType = DofIdKey;
719 MatrixPatternExchange(
const RowDofMapper& rowEntityMapper,
720 const std::map<DofIdKey,int>& globalToLocal,
721 const std::map<int,DofIdKey>& localToGlobal,
723 std::vector<std::set<int>>& sparsityPattern,
724 const ColIsGhostFunc& isGhostColumDof)
725 : rowEntityMapper_(rowEntityMapper)
726 , idToIndex_(globalToLocal), indexToID_(localToGlobal)
727 , sparsityPattern_(sparsityPattern), A_(A), isGhostColumDof_(isGhostColumDof)
729 sparsityPattern_.resize(A.N());
735 bool contains (
int dim,
int codim)
const
736 {
return (codim == rowDofCodim); }
739 bool fixedSize(
int dim,
int codim)
const
745 template<
class EntityType>
746 std::size_t size(EntityType& e)
const
748 const auto rowIdx = rowEntityMapper_.index(e);
752 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
754 if (indexToID_.count(colIt.index()))
764 template<
class MessageBuffer,
class EntityType>
765 void gather(MessageBuffer& buff,
const EntityType& e)
const
767 const auto rowIdx = rowEntityMapper_.index(e);
770 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
772 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
773 buff.write(it->second);
780 template<
class MessageBuffer,
class EntityType>
781 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
783 const auto rowIdx = rowEntityMapper_.index(e);
784 for (std::size_t k = 0; k < n; k++)
791 if (
const auto it = idToIndex_.find(key); it != idToIndex_.end())
793 const auto colIdx = it->second;
794 if (!isGhostColumDof_(colIdx))
795 sparsityPattern_[rowIdx].insert(colIdx);
801 const RowDofMapper& rowEntityMapper_;
802 const std::map<DofIdKey, int>& idToIndex_;
803 const std::map<int, DofIdKey>& indexToID_;
804 std::vector<std::set<int>>& sparsityPattern_;
806 const ColIsGhostFunc& isGhostColumDof_;
814 typename Matrix::block_type second;
818 struct MatrixEntryExchange
819 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
822 using DataType = MatrixEntry;
824 MatrixEntryExchange(
const RowDofMapper& rowEntityMapper,
825 const std::map<DofIdKey, int>& globalToLocal,
826 const std::map<int, DofIdKey>& localToGlobal,
828 : rowEntityMapper_(rowEntityMapper)
829 , idToIndex_(globalToLocal), indexToID_(localToGlobal)
836 bool contains(
int dim,
int codim)
const
837 {
return (codim == rowDofCodim); }
840 bool fixedSize(
int dim,
int codim)
const
846 template<
class EntityType>
847 std::size_t size(EntityType& e)
const
849 const auto rowIdx = rowEntityMapper_.index(e);
851 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
853 if (indexToID_.count(colIt.index()))
863 template<
class MessageBuffer,
class EntityType>
864 void gather(MessageBuffer& buff,
const EntityType& e)
const
866 const auto rowIdx = rowEntityMapper_.index(e);
868 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
870 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
871 buff.write(MatrixEntry{ it->second, *colIt });
878 template<
class MessageBuffer,
class EntityType>
879 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
881 const auto rowIdx = rowEntityMapper_.index(e);
882 for (std::size_t k = 0; k < n; k++)
886 const auto& [colDofID, matrixBlock] = m;
889 if (
auto it = idToIndex_.find(colDofID); it != idToIndex_.end())
891 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
892 A_[rowIdx][it->second] += matrixBlock;
898 const RowDofMapper& rowEntityMapper_;
899 const std::map<DofIdKey, int>& idToIndex_;
900 const std::map<int, DofIdKey>& indexToID_;
908 : gridView_(gridView), mapper_(mapper)
919 if constexpr (codim <= GridView::dimension)
921 for (
const auto& element : elements(gridView_))
923 for (
int i = 0; i < element.subEntities(codim); ++i)
925 const auto entity = element.template subEntity<codim>(i);
926 if (entity.partitionType() == Dune::BorderEntity)
928 const auto localIdx = mapper_.index(entity);
929 const DofIdKey key{codim, gridView_.grid().globalIdSet().id(entity)};
930 idToIndex_.emplace(key, localIdx);
931 indexToID_.emplace(localIdx, key);
945 template<
class IsGhostFunc>
948 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
950 if (gridView_.comm().size() <= 1)
954 Matrix matrixAsAssembled(A);
957 std::size_t numNonZeroEntries = 0;
958 std::vector<std::set<int>> sparsityPattern;
959 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost);
960 gridView_.communicate(
961 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
965 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
967 const auto colEndIt = A[rowIt.index()].end();
968 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
969 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
970 sparsityPattern[rowIt.index()].insert(colIt.index());
972 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
976 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
977 A.setBuildMode(Matrix::row_wise);
978 auto citer = A.createbegin();
979 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i!=end; ++i, ++citer)
980 for (
auto si = i->begin(), send = i->end(); si!=send; ++si)
985 const auto rowEndIt = matrixAsAssembled.end();
986 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
987 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
988 A[rowIt.index()][colIt.index()] = *colIt;
994 DUNE_THROW(Dune::InvalidStateException,
"Cannot call extendMatrix for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities.");
1012 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
1014 if (gridView_.comm().size() <= 1)
1017 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A);
1018 gridView_.communicate(
1019 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
1023 DUNE_THROW(Dune::InvalidStateException,
1024 "Cannot call sumEntries for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities."
1029 const GridView gridView_;
1030 const RowDofMapper& mapper_;
1031 std::map<DofIdKey, int> idToIndex_;
1032 std::map<int, DofIdKey> indexToID_;
1043 using IdType =
typename GridView::Traits::Grid::Traits::GlobalIdSet::IdType;
1051 friend bool operator<(
const DofIdKey& a,
const DofIdKey& b)
1053 if (a.codim != b.codim)
1054 return a.codim < b.codim;
1057 return a.subIndex < b.subIndex;
1069 template<
class ColIsGhostFunc>
1070 struct MatrixPatternExchange
1071 :
public Dune::CommDataHandleIF<MatrixPatternExchange<ColIsGhostFunc>, PatternEntry>
1073 using DataType = PatternEntry;
1075 MatrixPatternExchange(
const DofMapper& dofMapper,
1076 const std::map<DofIdKey, int>& globalToLocal,
1077 const std::map<int, DofIdKey>& localToGlobal,
1079 std::vector<std::set<int>>& sparsityPattern,
1080 const ColIsGhostFunc& isGhostColumDof,
1081 const std::bitset<numCodims>& activeCodims)
1082 : dofMapper_(dofMapper)
1083 , idToIndex_(globalToLocal)
1084 , indexToID_(localToGlobal)
1085 , sparsityPattern_(sparsityPattern)
1087 , isGhostColumDof_(isGhostColumDof)
1088 , activeCodims_(activeCodims)
1090 sparsityPattern_.resize(A.N());
1093 bool contains(
int dim,
int codim)
const
1095 if (codim < 0 || codim >=
static_cast<int>(numCodims))
1097 return activeCodims_.test(codim);
1100 bool fixedSize(
int dim,
int codim)
const
1104 template<
class EntityType>
1105 std::size_t size(EntityType& e)
const
1109 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1110 if (indexToID_.count(colIt.index()))
1116 template<
class MessageBuffer,
class EntityType>
1117 void gather(MessageBuffer& buff,
const EntityType& e)
const
1122 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1123 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
1124 buff.write(PatternEntry{rowSub, it->second});
1130 template<
class MessageBuffer,
class EntityType>
1131 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
1133 const auto baseIdx = dofMapper_.index(e);
1134 for (std::size_t k = 0; k < n; k++)
1138 const auto rowIdx = baseIdx + entry.rowSubIndex;
1139 if (
const auto it = idToIndex_.find(entry.colKey); it != idToIndex_.end())
1141 const auto colIdx = it->second;
1142 if (!isGhostColumDof_(colIdx))
1143 sparsityPattern_[rowIdx].insert(colIdx);
1149 const DofMapper& dofMapper_;
1150 const std::map<DofIdKey, int>& idToIndex_;
1151 const std::map<int, DofIdKey>& indexToID_;
1152 std::vector<std::set<int>>& sparsityPattern_;
1154 const ColIsGhostFunc& isGhostColumDof_;
1155 const std::bitset<numCodims>& activeCodims_;
1162 typename Matrix::block_type block;
1165 struct MatrixEntryExchange
1166 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
1168 using DataType = MatrixEntry;
1170 MatrixEntryExchange(
const DofMapper& dofMapper,
1171 const std::map<DofIdKey, int>& globalToLocal,
1172 const std::map<int, DofIdKey>& localToGlobal,
1174 const std::bitset<numCodims>& activeCodims)
1175 : dofMapper_(dofMapper)
1176 , idToIndex_(globalToLocal)
1177 , indexToID_(localToGlobal)
1179 , activeCodims_(activeCodims)
1182 bool contains(
int dim,
int codim)
const
1184 if (codim < 0 || codim >=
static_cast<int>(numCodims))
1186 return activeCodims_.test(codim);
1189 bool fixedSize(
int dim,
int codim)
const
1193 template<
class EntityType>
1194 std::size_t size(EntityType& e)
const
1198 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1199 if (indexToID_.count(colIt.index()))
1205 template<
class MessageBuffer,
class EntityType>
1206 void gather(MessageBuffer& buff,
const EntityType& e)
const
1211 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1212 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
1213 buff.write(MatrixEntry{rowSub, it->second, *colIt});
1219 template<
class MessageBuffer,
class EntityType>
1220 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
1222 const auto baseIdx = dofMapper_.index(e);
1223 for (std::size_t k = 0; k < n; k++)
1227 const auto rowIdx = baseIdx + m.rowSubIndex;
1228 if (
auto it = idToIndex_.find(m.colKey); it != idToIndex_.end())
1230 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
1231 A_[rowIdx][it->second] += m.block;
1237 const DofMapper& dofMapper_;
1238 const std::map<DofIdKey, int>& idToIndex_;
1239 const std::map<int, DofIdKey>& indexToID_;
1241 const std::bitset<numCodims>& activeCodims_;
1249 const DofMapper& mapper,
1250 const std::bitset<numCodims>& activeCodims)
1251 : gridView_(gridView)
1253 , activeCodims_(activeCodims)
1254 , includeGhostAndAdjacent_(false)
1255 , commInterface_(
Dune::InteriorBorder_InteriorBorder_Interface)
1257 initMapsForCodim_<0>();
1267 const DofMapper& mapper,
1268 const std::bitset<numCodims>& activeCodims,
1269 bool includeGhostAndAdjacent)
1270 : gridView_(gridView)
1272 , activeCodims_(activeCodims)
1273 , includeGhostAndAdjacent_(includeGhostAndAdjacent)
1278 , commInterface_(includeGhostAndAdjacent ?
Dune::InteriorBorder_All_Interface
1279 :
Dune::InteriorBorder_InteriorBorder_Interface)
1281 initMapsForCodim_<0>();
1284 template<
class IsGhostFunc>
1287 if (gridView_.comm().size() <= 1)
1290 Matrix matrixAsAssembled(A);
1291 std::size_t numNonZeroEntries = 0;
1292 std::vector<std::set<int>> sparsityPattern;
1293 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost, activeCodims_);
1294 gridView_.communicate(dataHandle, commInterface_, Dune::ForwardCommunication);
1296 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
1298 const auto colEndIt = A[rowIt.index()].end();
1299 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
1301 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
1302 sparsityPattern[rowIt.index()].insert(colIt.index());
1305 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
1308 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
1309 A.setBuildMode(Matrix::row_wise);
1310 auto citer = A.createbegin();
1311 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i != end; ++i, ++citer)
1312 for (
auto si = i->begin(), send = i->end(); si != send; ++si)
1316 const auto rowEndIt = matrixAsAssembled.end();
1317 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
1318 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
1319 A[rowIt.index()][colIt.index()] = *colIt;
1324 if (gridView_.comm().size() <= 1)
1327 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A, activeCodims_);
1328 gridView_.communicate(dataHandle, commInterface_, Dune::ForwardCommunication);
1332 template<std::
size_t codim>
1333 void initMapsForCodim_()
1335 if constexpr (codim <= GridView::dimension)
1337 if (activeCodims_.test(codim))
1339 for (
const auto& element : elements(gridView_))
1341 for (
int i = 0; i < element.subEntities(codim); ++i)
1343 const auto entity = element.template subEntity<codim>(i);
1344 const auto pt = entity.partitionType();
1348 bool shouldProcess = (codim == 0) || (pt == Dune::BorderEntity)
1349 || (pt == Dune::InteriorEntity && elementHasBorderSubEntity_(element));
1352 if (!shouldProcess && includeGhostAndAdjacent_)
1353 shouldProcess = (pt == Dune::GhostEntity);
1360 const auto globalId = gridView_.grid().globalIdSet().id(entity);
1364 const DofIdKey key{
static_cast<int>(codim), globalId, subIdx};
1365 idToIndex_.emplace(key, dofIdx);
1366 indexToID_.emplace(dofIdx, key);
1374 initMapsForCodim_<codim + 1>();
1379 template<
class Element>
1380 static bool elementHasBorderSubEntity_(
const Element& element)
1382 for (
int i = 0; i <
element.subEntities(1); ++i)
1383 if (
element.template subEntity<1>(i).partitionType() == Dune::BorderEntity)
1385 if constexpr (Element::mydimension >= 2)
1386 for (
int i = 0; i <
element.subEntities(2); ++i)
1387 if (
element.template subEntity<2>(i).partitionType() == Dune::BorderEntity)
1389 if constexpr (Element::mydimension >= 3)
1390 for (
int i = 0; i <
element.subEntities(3); ++i)
1391 if (
element.template subEntity<3>(i).partitionType() == Dune::BorderEntity)
1396 const GridView gridView_;
1397 const DofMapper& mapper_;
1398 std::bitset<numCodims> activeCodims_;
1399 bool includeGhostAndAdjacent_;
1400 Dune::InterfaceType commInterface_;
1401 std::map<DofIdKey, int> idToIndex_;
1402 std::map<int, DofIdKey> indexToID_;