40 using GridView =
typename LinearSolverTraits::GridView;
41 using DofMapper =
typename LinearSolverTraits::DofMapper;
44 static constexpr std::size_t ghostMarker_ = 1<<24;
46 class BaseGatherScatter
48 static constexpr int numCodims_ = GridView::dimension + 1;
50 static constexpr auto getActiveCodims_()
52 if constexpr (
requires { LinearSolverTraits::dofCodims; })
53 return LinearSolverTraits::dofCodims;
55 return std::bitset<numCodims_>{ 1UL << LinearSolverTraits::dofCodim };
59 BaseGatherScatter(
const DofMapper& mapper)
62 template<
class EntityType>
63 int index(
const EntityType& e)
const
64 {
return mapper_.index(e); }
66 template<
class EntityType>
67 auto indices(
const EntityType& e)
const
70 bool contains(
int dim,
int codim)
const
71 {
return codim >= 0 && codim < numCodims_ && activeCodims_.test(codim); }
75 bool fixedSize(
int dim,
int codim)
const
77 if (codim < 0 || codim >= numCodims_ || !activeCodims_.test(codim))
return true;
78 const auto& gtypes = mapper_.types(codim);
79 if (gtypes.empty())
return true;
80 const auto nDofs = mapper_.size(gtypes[0]);
81 for (
const auto& gt : gtypes)
82 if (mapper_.size(gt) != nDofs)
return false;
87 template<
class EntityType>
88 std::size_t size(EntityType& e)
const
91 template<
class EntityType>
92 bool isNeitherInteriorNorBorderEntity(EntityType& e)
const
93 {
return e.partitionType() != Dune::InteriorEntity && e.partitionType() != Dune::BorderEntity; }
96 const DofMapper& mapper_;
98 static constexpr auto activeCodims_ = getActiveCodims_();
107 class GhostGatherScatter
108 :
public BaseGatherScatter
109 ,
public Dune::CommDataHandleIF<GhostGatherScatter, std::size_t>
112 using DataType = std::size_t;
113 using BaseGatherScatter::contains;
114 using BaseGatherScatter::fixedSize;
115 using BaseGatherScatter::size;
117 GhostGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
118 : BaseGatherScatter(mapper)
122 template<
class MessageBuffer,
class EntityType>
123 void gather(MessageBuffer& buff,
const EntityType& e)
const
125 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
126 for (
auto i : this->indices(e)) {
127 auto& data = ranks_[i];
128 if (
isGhost) data = ghostMarker_;
133 template<
class MessageBuffer,
class EntityType>
134 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
136 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
137 for (
auto i : this->indices(e)) {
140 if (
isGhost) ranks_[i] = ghostMarker_;
144 std::vector<std::size_t>& ranks_;
153 class InteriorBorderGatherScatter
154 :
public BaseGatherScatter
155 ,
public Dune::CommDataHandleIF<InteriorBorderGatherScatter, std::size_t>
158 using DataType = std::size_t;
159 using BaseGatherScatter::contains;
160 using BaseGatherScatter::fixedSize;
161 using BaseGatherScatter::size;
163 InteriorBorderGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
164 : BaseGatherScatter(mapper)
171 template<
class MessageBuffer,
class EntityType>
172 void gather(MessageBuffer& buff,
const EntityType& e)
const
174 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
175 for (
auto i : this->indices(e)) {
176 auto& data = ranks_[i];
177 if (
isGhost) data = ghostMarker_;
185 template<
class MessageBuffer,
class EntityType>
186 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
188 const bool isGhost = this->isNeitherInteriorNorBorderEntity(e);
189 for (
auto i : this->indices(e)) {
192 auto& data = ranks_[i];
197 data =
isGhost ? x : min(data, x);
201 std::vector<std::size_t>& ranks_;
208 struct NeighbourGatherScatter
209 :
public BaseGatherScatter
210 ,
public Dune::CommDataHandleIF<NeighbourGatherScatter, int>
212 using DataType = int;
213 using BaseGatherScatter::contains;
214 using BaseGatherScatter::fixedSize;
215 using BaseGatherScatter::size;
217 NeighbourGatherScatter(
const DofMapper& mapper,
int rank, std::set<int>& neighbours)
218 : BaseGatherScatter(mapper)
220 , neighbours_(neighbours)
224 template<
class EntityType>
225 std::size_t size(EntityType& e)
const {
return 1; }
226 bool fixedSize(
int dim,
int codim)
const {
return true; }
228 template<
class MessageBuffer,
class EntityType>
229 void gather(MessageBuffer& buff,
const EntityType& e)
const
234 template<
class MessageBuffer,
class EntityType>
235 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
239 neighbours_.insert(x);
243 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_;
667 using IdType =
typename GridView::Traits::Grid::Traits::GlobalIdSet::IdType;
674 friend bool operator<(
const DofIdKey& a,
const DofIdKey& b)
676 if (a.codim != b.codim)
677 return a.codim < b.codim;
703 template<
class ColIsGhostFunc>
704 struct MatrixPatternExchange
705 :
public Dune::CommDataHandleIF<MatrixPatternExchange<ColIsGhostFunc>, DofIdKey>
708 using DataType = DofIdKey;
720 MatrixPatternExchange(
const RowDofMapper& rowEntityMapper,
721 const std::map<DofIdKey,int>& globalToLocal,
722 const std::map<int,DofIdKey>& localToGlobal,
724 std::vector<std::set<int>>& sparsityPattern,
725 const ColIsGhostFunc& isGhostColumDof)
726 : rowEntityMapper_(rowEntityMapper)
727 , idToIndex_(globalToLocal), indexToID_(localToGlobal)
728 , sparsityPattern_(sparsityPattern), A_(A), isGhostColumDof_(isGhostColumDof)
730 sparsityPattern_.resize(A.N());
736 bool contains (
int dim,
int codim)
const
737 {
return (codim == rowDofCodim); }
740 bool fixedSize(
int dim,
int codim)
const
746 template<
class EntityType>
747 std::size_t size(EntityType& e)
const
749 const auto rowIdx = rowEntityMapper_.index(e);
753 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
755 if (indexToID_.count(colIt.index()))
765 template<
class MessageBuffer,
class EntityType>
766 void gather(MessageBuffer& buff,
const EntityType& e)
const
768 const auto rowIdx = rowEntityMapper_.index(e);
771 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
773 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
774 buff.write(it->second);
781 template<
class MessageBuffer,
class EntityType>
782 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
784 const auto rowIdx = rowEntityMapper_.index(e);
785 for (std::size_t k = 0; k < n; k++)
792 if (
const auto it = idToIndex_.find(key); it != idToIndex_.end())
794 const auto colIdx = it->second;
795 if (!isGhostColumDof_(colIdx))
796 sparsityPattern_[rowIdx].insert(colIdx);
802 const RowDofMapper& rowEntityMapper_;
803 const std::map<DofIdKey, int>& idToIndex_;
804 const std::map<int, DofIdKey>& indexToID_;
805 std::vector<std::set<int>>& sparsityPattern_;
807 const ColIsGhostFunc& isGhostColumDof_;
815 typename Matrix::block_type second;
819 struct MatrixEntryExchange
820 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
823 using DataType = MatrixEntry;
825 MatrixEntryExchange(
const RowDofMapper& rowEntityMapper,
826 const std::map<DofIdKey, int>& globalToLocal,
827 const std::map<int, DofIdKey>& localToGlobal,
829 : rowEntityMapper_(rowEntityMapper)
830 , idToIndex_(globalToLocal), indexToID_(localToGlobal)
837 bool contains(
int dim,
int codim)
const
838 {
return (codim == rowDofCodim); }
841 bool fixedSize(
int dim,
int codim)
const
847 template<
class EntityType>
848 std::size_t size(EntityType& e)
const
850 const auto rowIdx = rowEntityMapper_.index(e);
852 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
854 if (indexToID_.count(colIt.index()))
864 template<
class MessageBuffer,
class EntityType>
865 void gather(MessageBuffer& buff,
const EntityType& e)
const
867 const auto rowIdx = rowEntityMapper_.index(e);
869 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
871 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
872 buff.write(MatrixEntry{ it->second, *colIt });
879 template<
class MessageBuffer,
class EntityType>
880 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
882 const auto rowIdx = rowEntityMapper_.index(e);
883 for (std::size_t k = 0; k < n; k++)
887 const auto& [colDofID, matrixBlock] = m;
890 if (
auto it = idToIndex_.find(colDofID); it != idToIndex_.end())
892 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
893 A_[rowIdx][it->second] += matrixBlock;
899 const RowDofMapper& rowEntityMapper_;
900 const std::map<DofIdKey, int>& idToIndex_;
901 const std::map<int, DofIdKey>& indexToID_;
909 : gridView_(gridView), mapper_(mapper)
920 if constexpr (codim <= GridView::dimension)
922 for (
const auto& element : elements(gridView_))
924 for (
int i = 0; i < element.subEntities(codim); ++i)
926 const auto entity = element.template subEntity<codim>(i);
927 if (entity.partitionType() == Dune::BorderEntity)
929 const auto localIdx = mapper_.index(entity);
930 const DofIdKey key{codim, gridView_.grid().globalIdSet().id(entity)};
931 idToIndex_.emplace(key, localIdx);
932 indexToID_.emplace(localIdx, key);
946 template<
class IsGhostFunc>
949 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
951 if (gridView_.comm().size() <= 1)
955 Matrix matrixAsAssembled(A);
958 std::size_t numNonZeroEntries = 0;
959 std::vector<std::set<int>> sparsityPattern;
960 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost);
961 gridView_.communicate(
962 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
966 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
968 const auto colEndIt = A[rowIt.index()].end();
969 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
970 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
971 sparsityPattern[rowIt.index()].insert(colIt.index());
973 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
977 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
978 A.setBuildMode(Matrix::row_wise);
979 auto citer = A.createbegin();
980 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i!=end; ++i, ++citer)
981 for (
auto si = i->begin(), send = i->end(); si!=send; ++si)
986 const auto rowEndIt = matrixAsAssembled.end();
987 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
988 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
989 A[rowIt.index()][colIt.index()] = *colIt;
995 DUNE_THROW(Dune::InvalidStateException,
"Cannot call extendMatrix for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities.");
1013 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
1015 if (gridView_.comm().size() <= 1)
1018 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A);
1019 gridView_.communicate(
1020 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
1024 DUNE_THROW(Dune::InvalidStateException,
1025 "Cannot call sumEntries for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities."
1030 const GridView gridView_;
1031 const RowDofMapper& mapper_;
1032 std::map<DofIdKey, int> idToIndex_;
1033 std::map<int, DofIdKey> indexToID_;
1044 using IdType =
typename GridView::Traits::Grid::Traits::GlobalIdSet::IdType;
1052 friend bool operator<(
const DofIdKey& a,
const DofIdKey& b)
1054 if (a.codim != b.codim)
1055 return a.codim < b.codim;
1058 return a.subIndex < b.subIndex;
1070 template<
class ColIsGhostFunc>
1071 struct MatrixPatternExchange
1072 :
public Dune::CommDataHandleIF<MatrixPatternExchange<ColIsGhostFunc>, PatternEntry>
1074 using DataType = PatternEntry;
1076 MatrixPatternExchange(
const DofMapper& dofMapper,
1077 const std::map<DofIdKey, int>& globalToLocal,
1078 const std::map<int, DofIdKey>& localToGlobal,
1080 std::vector<std::set<int>>& sparsityPattern,
1081 const ColIsGhostFunc& isGhostColumDof,
1082 const std::bitset<numCodims>& activeCodims)
1083 : dofMapper_(dofMapper)
1084 , idToIndex_(globalToLocal)
1085 , indexToID_(localToGlobal)
1086 , sparsityPattern_(sparsityPattern)
1088 , isGhostColumDof_(isGhostColumDof)
1089 , activeCodims_(activeCodims)
1091 sparsityPattern_.resize(A.N());
1094 bool contains(
int dim,
int codim)
const
1096 if (codim < 0 || codim >=
static_cast<int>(numCodims))
1098 return activeCodims_.test(codim);
1101 bool fixedSize(
int dim,
int codim)
const
1105 template<
class EntityType>
1106 std::size_t size(EntityType& e)
const
1110 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1111 if (indexToID_.count(colIt.index()))
1117 template<
class MessageBuffer,
class EntityType>
1118 void gather(MessageBuffer& buff,
const EntityType& e)
const
1123 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1124 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
1125 buff.write(PatternEntry{rowSub, it->second});
1131 template<
class MessageBuffer,
class EntityType>
1132 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
1134 const auto baseIdx = dofMapper_.index(e);
1135 for (std::size_t k = 0; k < n; k++)
1139 const auto rowIdx = baseIdx + entry.rowSubIndex;
1140 if (
const auto it = idToIndex_.find(entry.colKey); it != idToIndex_.end())
1142 const auto colIdx = it->second;
1143 if (!isGhostColumDof_(colIdx))
1144 sparsityPattern_[rowIdx].insert(colIdx);
1150 const DofMapper& dofMapper_;
1151 const std::map<DofIdKey, int>& idToIndex_;
1152 const std::map<int, DofIdKey>& indexToID_;
1153 std::vector<std::set<int>>& sparsityPattern_;
1155 const ColIsGhostFunc& isGhostColumDof_;
1156 const std::bitset<numCodims>& activeCodims_;
1163 typename Matrix::block_type block;
1166 struct MatrixEntryExchange
1167 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
1169 using DataType = MatrixEntry;
1171 MatrixEntryExchange(
const DofMapper& dofMapper,
1172 const std::map<DofIdKey, int>& globalToLocal,
1173 const std::map<int, DofIdKey>& localToGlobal,
1175 const std::bitset<numCodims>& activeCodims)
1176 : dofMapper_(dofMapper)
1177 , idToIndex_(globalToLocal)
1178 , indexToID_(localToGlobal)
1180 , activeCodims_(activeCodims)
1183 bool contains(
int dim,
int codim)
const
1185 if (codim < 0 || codim >=
static_cast<int>(numCodims))
1187 return activeCodims_.test(codim);
1190 bool fixedSize(
int dim,
int codim)
const
1194 template<
class EntityType>
1195 std::size_t size(EntityType& e)
const
1199 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1200 if (indexToID_.count(colIt.index()))
1206 template<
class MessageBuffer,
class EntityType>
1207 void gather(MessageBuffer& buff,
const EntityType& e)
const
1212 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
1213 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
1214 buff.write(MatrixEntry{rowSub, it->second, *colIt});
1220 template<
class MessageBuffer,
class EntityType>
1221 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
1223 const auto baseIdx = dofMapper_.index(e);
1224 for (std::size_t k = 0; k < n; k++)
1228 const auto rowIdx = baseIdx + m.rowSubIndex;
1229 if (
auto it = idToIndex_.find(m.colKey); it != idToIndex_.end())
1231 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
1232 A_[rowIdx][it->second] += m.block;
1238 const DofMapper& dofMapper_;
1239 const std::map<DofIdKey, int>& idToIndex_;
1240 const std::map<int, DofIdKey>& indexToID_;
1242 const std::bitset<numCodims>& activeCodims_;
1250 const DofMapper& mapper,
1251 const std::bitset<numCodims>& activeCodims)
1252 : gridView_(gridView)
1254 , activeCodims_(activeCodims)
1255 , includeGhostAndAdjacent_(false)
1256 , commInterface_(
Dune::InteriorBorder_InteriorBorder_Interface)
1258 initMapsForCodim_<0>();
1268 const DofMapper& mapper,
1269 const std::bitset<numCodims>& activeCodims,
1270 bool includeGhostAndAdjacent)
1271 : gridView_(gridView)
1273 , activeCodims_(activeCodims)
1274 , includeGhostAndAdjacent_(includeGhostAndAdjacent)
1279 , commInterface_(includeGhostAndAdjacent ?
Dune::InteriorBorder_All_Interface
1280 :
Dune::InteriorBorder_InteriorBorder_Interface)
1282 initMapsForCodim_<0>();
1285 template<
class IsGhostFunc>
1288 if (gridView_.comm().size() <= 1)
1291 Matrix matrixAsAssembled(A);
1292 std::size_t numNonZeroEntries = 0;
1293 std::vector<std::set<int>> sparsityPattern;
1294 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost, activeCodims_);
1295 gridView_.communicate(dataHandle, commInterface_, Dune::ForwardCommunication);
1297 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
1299 const auto colEndIt = A[rowIt.index()].end();
1300 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
1302 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
1303 sparsityPattern[rowIt.index()].insert(colIt.index());
1306 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
1309 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
1310 A.setBuildMode(Matrix::row_wise);
1311 auto citer = A.createbegin();
1312 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i != end; ++i, ++citer)
1313 for (
auto si = i->begin(), send = i->end(); si != send; ++si)
1317 const auto rowEndIt = matrixAsAssembled.end();
1318 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
1319 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
1320 A[rowIt.index()][colIt.index()] = *colIt;
1325 if (gridView_.comm().size() <= 1)
1328 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A, activeCodims_);
1329 gridView_.communicate(dataHandle, commInterface_, Dune::ForwardCommunication);
1333 template<std::
size_t codim>
1334 void initMapsForCodim_()
1336 if constexpr (codim <= GridView::dimension)
1338 if (activeCodims_.test(codim))
1340 for (
const auto& element : elements(gridView_))
1342 for (
int i = 0; i < element.subEntities(codim); ++i)
1344 const auto entity = element.template subEntity<codim>(i);
1345 const auto pt = entity.partitionType();
1348 bool shouldProcess = (pt == Dune::BorderEntity);
1353 if (!shouldProcess && includeGhostAndAdjacent_) {
1354 if constexpr (codim == 0) {
1357 shouldProcess = (pt == Dune::GhostEntity)
1358 || (pt == Dune::InteriorEntity
1359 && elementHasBorderSubEntity_(entity));
1361 shouldProcess = (pt == Dune::GhostEntity);
1370 const auto globalId = gridView_.grid().globalIdSet().id(entity);
1374 const DofIdKey key{
static_cast<int>(codim), globalId, subIdx};
1375 idToIndex_.emplace(key, dofIdx);
1376 indexToID_.emplace(dofIdx, key);
1384 initMapsForCodim_<codim + 1>();
1389 template<
class Element>
1390 static bool elementHasBorderSubEntity_(
const Element& element)
1392 for (
int i = 0; i <
element.subEntities(1); ++i)
1393 if (
element.template subEntity<1>(i).partitionType() == Dune::BorderEntity)
1395 if constexpr (Element::mydimension >= 2)
1396 for (
int i = 0; i <
element.subEntities(2); ++i)
1397 if (
element.template subEntity<2>(i).partitionType() == Dune::BorderEntity)
1399 if constexpr (Element::mydimension >= 3)
1400 for (
int i = 0; i <
element.subEntities(3); ++i)
1401 if (
element.template subEntity<3>(i).partitionType() == Dune::BorderEntity)
1406 const GridView gridView_;
1407 const DofMapper& mapper_;
1408 std::bitset<numCodims> activeCodims_;
1409 bool includeGhostAndAdjacent_;
1410 Dune::InterfaceType commInterface_;
1411 std::map<DofIdKey, int> idToIndex_;
1412 std::map<int, DofIdKey> indexToID_;