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)
922 if (!mapper_.types(codim).empty())
924 for (
const auto& element : elements(gridView_))
926 for (
int i = 0; i < element.subEntities(codim); ++i)
928 const auto entity = element.template subEntity<codim>(i);
929 if (entity.partitionType() == Dune::BorderEntity)
931 const auto localIdx = mapper_.index(entity);
932 const DofIdKey key{codim, gridView_.grid().globalIdSet().id(entity)};
933 idToIndex_.emplace(key, localIdx);
934 indexToID_.emplace(localIdx, key);
949 template<
class IsGhostFunc>
952 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
954 if (gridView_.comm().size() <= 1)
958 Matrix matrixAsAssembled(A);
961 std::size_t numNonZeroEntries = 0;
962 std::vector<std::set<int>> sparsityPattern;
963 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost);
964 gridView_.communicate(
965 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
969 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
971 const auto colEndIt = A[rowIt.index()].end();
972 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
973 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
974 sparsityPattern[rowIt.index()].insert(colIt.index());
976 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
980 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
981 A.setBuildMode(Matrix::row_wise);
982 auto citer = A.createbegin();
983 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i!=end; ++i, ++citer)
984 for (
auto si = i->begin(), send = i->end(); si!=send; ++si)
989 const auto rowEndIt = matrixAsAssembled.end();
990 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
991 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
992 A[rowIt.index()][colIt.index()] = *colIt;
998 DUNE_THROW(Dune::InvalidStateException,
"Cannot call extendMatrix for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities.");
1016 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
1018 if (gridView_.comm().size() <= 1)
1021 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A);
1022 gridView_.communicate(
1023 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
1027 DUNE_THROW(Dune::InvalidStateException,
1028 "Cannot call sumEntries for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities."
1033 const GridView gridView_;
1034 const RowDofMapper& mapper_;
1035 std::map<DofIdKey, int> idToIndex_;
1036 std::map<int, DofIdKey> indexToID_;
1047 using IdType =
typename GridView::Traits::Grid::Traits::GlobalIdSet::IdType;
1055 friend bool operator<(
const DofIdKey& a,
const DofIdKey& b)
1057 if (a.codim != b.codim)
1058 return a.codim < b.codim;
1061 return a.subIndex < b.subIndex;
1073 template<
class ColIsGhostFunc>
1074 struct MatrixPatternExchange
1075 :
public Dune::CommDataHandleIF<MatrixPatternExchange<ColIsGhostFunc>, PatternEntry>
1077 using DataType = PatternEntry;
1079 MatrixPatternExchange(
const DofMapper& dofMapper,
1080 const std::map<DofIdKey, int>& globalToLocal,
1081 const std::map<int, DofIdKey>& localToGlobal,
1083 std::vector<std::set<int>>& sparsityPattern,
1084 const ColIsGhostFunc& isGhostColumDof,
1085 const std::bitset<numCodims>& activeCodims)
1086 : dofMapper_(dofMapper)
1087 , idToIndex_(globalToLocal)
1088 , indexToID_(localToGlobal)
1089 , sparsityPattern_(sparsityPattern)
1091 , isGhostColumDof_(isGhostColumDof)
1092 , activeCodims_(activeCodims)
1094 sparsityPattern_.resize(A.N());
1097 bool contains(
int dim,
int codim)
const
1099 if (codim < 0 || codim >=
static_cast<int>(numCodims))
1101 return activeCodims_.test(codim);
1104 bool fixedSize(
int dim,
int codim)
const
1108 template<
class EntityType>
1109 std::size_t size(EntityType& e)
const
1113 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1114 if (indexToID_.count(colIt.index()))
1120 template<
class MessageBuffer,
class EntityType>
1121 void gather(MessageBuffer& buff,
const EntityType& e)
const
1126 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1127 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
1128 buff.write(PatternEntry{rowSub, it->second});
1134 template<
class MessageBuffer,
class EntityType>
1135 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
1137 const auto baseIdx = dofMapper_.index(e);
1138 for (std::size_t k = 0; k < n; k++)
1142 const auto rowIdx = baseIdx + entry.rowSubIndex;
1143 if (
const auto it = idToIndex_.find(entry.colKey); it != idToIndex_.end())
1145 const auto colIdx = it->second;
1146 if (!isGhostColumDof_(colIdx))
1147 sparsityPattern_[rowIdx].insert(colIdx);
1153 const DofMapper& dofMapper_;
1154 const std::map<DofIdKey, int>& idToIndex_;
1155 const std::map<int, DofIdKey>& indexToID_;
1156 std::vector<std::set<int>>& sparsityPattern_;
1158 const ColIsGhostFunc& isGhostColumDof_;
1159 const std::bitset<numCodims>& activeCodims_;
1166 typename Matrix::block_type block;
1169 struct MatrixEntryExchange
1170 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
1172 using DataType = MatrixEntry;
1174 MatrixEntryExchange(
const DofMapper& dofMapper,
1175 const std::map<DofIdKey, int>& globalToLocal,
1176 const std::map<int, DofIdKey>& localToGlobal,
1178 const std::bitset<numCodims>& activeCodims)
1179 : dofMapper_(dofMapper)
1180 , idToIndex_(globalToLocal)
1181 , indexToID_(localToGlobal)
1183 , activeCodims_(activeCodims)
1186 bool contains(
int dim,
int codim)
const
1188 if (codim < 0 || codim >=
static_cast<int>(numCodims))
1190 return activeCodims_.test(codim);
1193 bool fixedSize(
int dim,
int codim)
const
1197 template<
class EntityType>
1198 std::size_t size(EntityType& e)
const
1202 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1203 if (indexToID_.count(colIt.index()))
1209 template<
class MessageBuffer,
class EntityType>
1210 void gather(MessageBuffer& buff,
const EntityType& e)
const
1215 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1216 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
1217 buff.write(MatrixEntry{rowSub, it->second, *colIt});
1223 template<
class MessageBuffer,
class EntityType>
1224 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
1226 const auto baseIdx = dofMapper_.index(e);
1227 for (std::size_t k = 0; k < n; k++)
1231 const auto rowIdx = baseIdx + m.rowSubIndex;
1232 if (
auto it = idToIndex_.find(m.colKey); it != idToIndex_.end())
1234 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
1235 A_[rowIdx][it->second] += m.block;
1241 const DofMapper& dofMapper_;
1242 const std::map<DofIdKey, int>& idToIndex_;
1243 const std::map<int, DofIdKey>& indexToID_;
1245 const std::bitset<numCodims>& activeCodims_;
1253 const DofMapper& mapper,
1254 const std::bitset<numCodims>& activeCodims)
1255 : gridView_(gridView)
1257 , activeCodims_(activeCodims)
1258 , includeGhostAndAdjacent_(false)
1259 , commInterface_(
Dune::InteriorBorder_InteriorBorder_Interface)
1261 initMapsForCodim_<0>();
1271 const DofMapper& mapper,
1272 const std::bitset<numCodims>& activeCodims,
1273 bool includeGhostAndAdjacent)
1274 : gridView_(gridView)
1276 , activeCodims_(activeCodims)
1277 , includeGhostAndAdjacent_(includeGhostAndAdjacent)
1282 , commInterface_(includeGhostAndAdjacent ?
Dune::InteriorBorder_All_Interface
1283 :
Dune::InteriorBorder_InteriorBorder_Interface)
1285 initMapsForCodim_<0>();
1288 template<
class IsGhostFunc>
1291 if (gridView_.comm().size() <= 1)
1294 Matrix matrixAsAssembled(A);
1295 std::size_t numNonZeroEntries = 0;
1296 std::vector<std::set<int>> sparsityPattern;
1297 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost, activeCodims_);
1298 gridView_.communicate(dataHandle, commInterface_, Dune::ForwardCommunication);
1300 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
1302 const auto colEndIt = A[rowIt.index()].end();
1303 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
1305 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
1306 sparsityPattern[rowIt.index()].insert(colIt.index());
1309 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
1312 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
1313 A.setBuildMode(Matrix::row_wise);
1314 auto citer = A.createbegin();
1315 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i != end; ++i, ++citer)
1316 for (
auto si = i->begin(), send = i->end(); si != send; ++si)
1320 const auto rowEndIt = matrixAsAssembled.end();
1321 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
1322 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
1323 A[rowIt.index()][colIt.index()] = *colIt;
1328 if (gridView_.comm().size() <= 1)
1331 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A, activeCodims_);
1332 gridView_.communicate(dataHandle, commInterface_, Dune::ForwardCommunication);
1336 template<std::
size_t codim>
1337 void initMapsForCodim_()
1339 if constexpr (codim <= GridView::dimension)
1341 if (activeCodims_.test(codim))
1343 for (
const auto& element : elements(gridView_))
1345 for (
int i = 0; i < element.subEntities(codim); ++i)
1347 const auto entity = element.template subEntity<codim>(i);
1348 const auto pt = entity.partitionType();
1352 bool shouldProcess = (codim == 0) || (pt == Dune::BorderEntity)
1353 || (pt == Dune::InteriorEntity && elementHasBorderSubEntity_(element));
1356 if (!shouldProcess && includeGhostAndAdjacent_)
1357 shouldProcess = (pt == Dune::GhostEntity);
1364 const auto globalId = gridView_.grid().globalIdSet().id(entity);
1368 const DofIdKey key{
static_cast<int>(codim), globalId, subIdx};
1369 idToIndex_.emplace(key, dofIdx);
1370 indexToID_.emplace(dofIdx, key);
1378 initMapsForCodim_<codim + 1>();
1383 template<
class Element>
1384 static bool elementHasBorderSubEntity_(
const Element& element)
1386 for (
int i = 0; i <
element.subEntities(1); ++i)
1387 if (
element.template subEntity<1>(i).partitionType() == Dune::BorderEntity)
1389 if constexpr (Element::mydimension >= 2)
1390 for (
int i = 0; i <
element.subEntities(2); ++i)
1391 if (
element.template subEntity<2>(i).partitionType() == Dune::BorderEntity)
1393 if constexpr (Element::mydimension >= 3)
1394 for (
int i = 0; i <
element.subEntities(3); ++i)
1395 if (
element.template subEntity<3>(i).partitionType() == Dune::BorderEntity)
1400 const GridView gridView_;
1401 const DofMapper& mapper_;
1402 std::bitset<numCodims> activeCodims_;
1403 bool includeGhostAndAdjacent_;
1404 Dune::InterfaceType commInterface_;
1405 std::map<DofIdKey, int> idToIndex_;
1406 std::map<int, DofIdKey> indexToID_;