24#ifndef DUMUX_LINEAR_PARALLELHELPERS_HH
25#define DUMUX_LINEAR_PARALLELHELPERS_HH
27#include <dune/common/exceptions.hh>
28#include <dune/geometry/dimension.hh>
29#include <dune/grid/common/datahandleif.hh>
30#include <dune/grid/common/partitionset.hh>
31#include <dune/istl/owneroverlapcopy.hh>
32#include <dune/istl/paamg/pinfo.hh>
44template<
class LinearSolverTraits>
47 using GridView =
typename LinearSolverTraits::GridView;
48 using DofMapper =
typename LinearSolverTraits::DofMapper;
49 static constexpr int dofCodim = LinearSolverTraits::dofCodim;
52 static constexpr std::size_t ghostMarker_ = 1<<24;
54 class BaseGatherScatter
57 BaseGatherScatter(
const DofMapper& mapper)
60 template<
class EntityType>
61 int index(
const EntityType& e)
const
62 {
return mapper_.index(e); }
64 bool contains(
int dim,
int codim)
const
65 {
return dofCodim == codim; }
68 bool fixedSize(
int dim,
int codim)
const
71 template<
class EntityType>
72 std::size_t size(EntityType& e)
const
75 template<
class EntityType>
76 bool isNeitherInteriorNorBorderEntity(EntityType& e)
const
77 {
return e.partitionType() != Dune::InteriorEntity && e.partitionType() != Dune::BorderEntity; }
80 const DofMapper& mapper_;
89 class GhostGatherScatter
90 :
public BaseGatherScatter
91 ,
public Dune::CommDataHandleIF<GhostGatherScatter, std::size_t>
94 using DataType = std::size_t;
95 using BaseGatherScatter::contains;
96 using BaseGatherScatter::fixedSize;
97 using BaseGatherScatter::size;
99 GhostGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
100 : BaseGatherScatter(mapper)
104 template<
class MessageBuffer,
class EntityType>
105 void gather(MessageBuffer& buff,
const EntityType& e)
const
107 auto& data = ranks_[this->index(e)];
108 if (this->isNeitherInteriorNorBorderEntity(e))
113 template<
class MessageBuffer,
class EntityType>
114 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
118 auto& data = ranks_[this->index(e)];
119 if (this->isNeitherInteriorNorBorderEntity(e))
123 std::vector<std::size_t>& ranks_;
132 class InteriorBorderGatherScatter
133 :
public BaseGatherScatter
134 ,
public Dune::CommDataHandleIF<InteriorBorderGatherScatter, std::size_t>
137 using DataType = std::size_t;
138 using BaseGatherScatter::contains;
139 using BaseGatherScatter::fixedSize;
140 using BaseGatherScatter::size;
142 InteriorBorderGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
143 : BaseGatherScatter(mapper)
150 template<
class MessageBuffer,
class EntityType>
151 void gather(MessageBuffer& buff,
const EntityType& e)
const
153 auto& data = ranks_[this->index(e)];
154 if (this->isNeitherInteriorNorBorderEntity(e))
162 template<
class MessageBuffer,
class EntityType>
163 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
167 auto& data = ranks_[this->index(e)];
173 data = this->isNeitherInteriorNorBorderEntity(e) ? x : min(data, x);
176 std::vector<std::size_t>& ranks_;
183 struct NeighbourGatherScatter
184 :
public BaseGatherScatter
185 ,
public Dune::CommDataHandleIF<NeighbourGatherScatter, int>
187 using DataType = int;
188 using BaseGatherScatter::contains;
189 using BaseGatherScatter::fixedSize;
190 using BaseGatherScatter::size;
192 NeighbourGatherScatter(
const DofMapper& mapper,
int rank, std::set<int>& neighbours)
193 : BaseGatherScatter(mapper)
195 , neighbours_(neighbours)
198 template<
class MessageBuffer,
class EntityType>
199 void gather(MessageBuffer& buff,
const EntityType& e)
const
204 template<
class MessageBuffer,
class EntityType>
205 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
209 neighbours_.insert(x);
213 std::set<int>& neighbours_;
221 struct SharedGatherScatter
222 :
public BaseGatherScatter
223 ,
public Dune::CommDataHandleIF<SharedGatherScatter, int>
225 using DataType = int;
226 using BaseGatherScatter::contains;
227 using BaseGatherScatter::fixedSize;
228 using BaseGatherScatter::size;
230 SharedGatherScatter(std::vector<int>& shared,
const DofMapper& mapper)
231 : BaseGatherScatter(mapper)
235 template<
class MessageBuffer,
class EntityType>
236 void gather(MessageBuffer& buff, EntityType& e)
const
242 template<
class MessageBuffer,
class EntityType>
243 void scatter(MessageBuffer& buff,
const EntityType &e, std::size_t n)
247 auto& data = shared_[this->index(e)];
251 std::vector<int>& shared_;
258 template<
typename GlobalIndex>
259 struct GlobalIndexGatherScatter
260 :
public BaseGatherScatter
261 ,
public Dune::CommDataHandleIF<GlobalIndexGatherScatter<GlobalIndex>, GlobalIndex>
263 using DataType = GlobalIndex;
264 using BaseGatherScatter::contains;
265 using BaseGatherScatter::fixedSize;
266 using BaseGatherScatter::size;
268 GlobalIndexGatherScatter(std::vector<GlobalIndex>& globalIndices,
const DofMapper& mapper)
269 : BaseGatherScatter(mapper)
270 , globalIndices_(globalIndices)
273 template<
class MessageBuffer,
class EntityType>
274 void gather(MessageBuffer& buff,
const EntityType& e)
const
276 buff.write(globalIndices_[this->index(e)]);
279 template<
class MessageBuffer,
class EntityType>
280 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
285 auto& data = globalIndices_[this->index(e)];
289 std::vector<GlobalIndex>& globalIndices_;
295 : gridView_(
gridView), mapper_(mapper)
297 if constexpr (Detail::canCommunicate<typename GridView::Traits::Grid, dofCodim>)
298 initGhostsAndOwners_();
300 DUNE_THROW(Dune::InvalidStateException,
301 "Cannot initialize parallel helper for a grid that cannot communicate codim-" << dofCodim <<
"-entities."
306 {
return isGhost_[i] == ghostMarker_; }
309 {
return isOwned_[i] == 1; }
325 if constexpr (Detail::canCommunicate<typename GridView::Traits::Grid, dofCodim>)
327 if (gridView_.comm().size() <= 1)
329 comm.remoteIndices().template rebuild<false>();
334 std::vector<int> isShared(mapper_.size(),
false);
335 SharedGatherScatter sgs(isShared, mapper_);
336 gridView_.communicate(sgs, Dune::All_All_Interface, Dune::ForwardCommunication);
339 using GlobalIndex =
typename Comm::ParallelIndexSet::GlobalIndex;
340 GlobalIndex count = 0;
341 for (std::size_t i = 0; i < isShared.size(); ++i)
342 if (isShared[i] && isOwned_[i] == 1)
345 std::vector<GlobalIndex> counts(gridView_.comm().size());
346 gridView_.comm().allgather(&count, 1, counts.data());
349 const int rank = gridView_.comm().rank();
350 auto start = std::accumulate(counts.begin(), counts.begin() + rank, GlobalIndex(0));
353 std::vector<GlobalIndex> globalIndices(mapper_.size(), std::numeric_limits<GlobalIndex>::max());
354 for (std::size_t i = 0; i < globalIndices.size(); ++i)
356 if (isOwned_[i] == 1 && isShared[i])
358 globalIndices[i] = start;
364 GlobalIndexGatherScatter<GlobalIndex> gigs(globalIndices, mapper_);
365 gridView_.communicate(gigs, Dune::All_All_Interface, Dune::ForwardCommunication);
368 resizeAndFillIndexSet_(comm, globalIndices);
371 std::set<int> neighbours;
372 NeighbourGatherScatter ngs(mapper_, gridView_.comm().rank(), neighbours);
373 gridView_.communicate(ngs, Dune::All_All_Interface, Dune::ForwardCommunication);
374 comm.remoteIndices().setNeighbours(neighbours);
376 comm.remoteIndices().template rebuild<false>();
379 DUNE_THROW(Dune::InvalidStateException,
380 "Cannot build parallel index set for a grid that cannot communicate codim-" << dofCodim <<
"-entities."
390 {
return gridView_; }
401 void initGhostsAndOwners_()
403 const auto rank = gridView_.comm().rank();
404 isOwned_.assign(mapper_.size(), rank);
407 GhostGatherScatter ggs(isOwned_, mapper_);
409 if (gridView_.comm().size() > 1)
410 gridView_.communicate(ggs, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
418 InteriorBorderGatherScatter dh(isOwned_, mapper_);
420 if (gridView_.comm().size() > 1)
421 gridView_.communicate(dh, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication);
424 for (
auto& v : isOwned_)
425 v = (v == rank) ? 1 : 0;
428 template<
class Comm,
class GlobalIndices>
429 void resizeAndFillIndexSet_(Comm& comm,
const GlobalIndices& globalIndices)
const
431 comm.indexSet().beginResize();
435 for (std::size_t localIndex = 0; localIndex < globalIndices.size(); ++localIndex)
437 const auto globalIndex = globalIndices[localIndex];
438 if (globalIndex != std::numeric_limits<typename GlobalIndices::value_type>::max())
440 const bool isOwned = isOwned_[localIndex] > 0;
441 const auto attr = getAttribute_(comm,
isOwned,
isGhost(localIndex));
442 using LocalIndex =
typename Comm::ParallelIndexSet::LocalIndex;
443 comm.indexSet().add(globalIndex, LocalIndex{localIndex, attr});
447 comm.indexSet().endResize();
451 Dune::OwnerOverlapCopyAttributeSet::AttributeSet
452 getAttribute_(
const Comm& comm,
const bool isOwned,
const bool isGhost)
const
455 return Dune::OwnerOverlapCopyAttributeSet::owner;
456 else if (
isGhost && (comm.category() == Dune::SolverCategory::nonoverlapping) )
457 return Dune::OwnerOverlapCopyAttributeSet::overlap;
459 return Dune::OwnerOverlapCopyAttributeSet::copy;
462 const GridView gridView_;
463 const DofMapper& mapper_;
465 std::vector<std::size_t> isOwned_;
467 std::vector<std::size_t> isGhost_;
471template<
class Gr
idView,
class DofMapper,
int dofCodim>
476 : gridView_(gridView), mapper_(mapper)
480 template<
class Block,
class Alloc>
483 if constexpr (Detail::canCommunicate<typename GridView::Traits::Grid, dofCodim>)
486 if (gridView_.comm().size() > 1)
487 gridView_.communicate(gs, Dune::InteriorBorder_InteriorBorder_Interface,
488 Dune::ForwardCommunication);
491 DUNE_THROW(Dune::InvalidStateException,
"Cannot call makeNonOverlappingConsistent for a grid that cannot communicate codim-" << dofCodim <<
"-entities.");
495 const GridView gridView_;
496 const DofMapper& mapper_;
507template<
class Matrix,
class GridView,
508 class RowDofMapper,
int rowDofCodim>
511 using IdType =
typename GridView::Traits::Grid::Traits::GlobalIdSet::IdType;
534 template<
class ColIsGhostFunc>
535 struct MatrixPatternExchange
536 :
public Dune::CommDataHandleIF<MatrixPatternExchange<ColIsGhostFunc>, IdType>
539 using DataType = IdType;
551 MatrixPatternExchange(
const RowDofMapper& rowEntityMapper,
552 const std::map<IdType,int>& globalToLocal,
553 const std::map<int,IdType>& localToGlobal,
555 std::vector<std::set<int>>& sparsityPattern,
556 const ColIsGhostFunc& isGhostColumDof)
557 : rowEntityMapper_(rowEntityMapper), idToIndex_(globalToLocal), indexToID_(localToGlobal)
558 , sparsityPattern_(sparsityPattern), A_(A), isGhostColumDof_(isGhostColumDof)
560 sparsityPattern_.resize(A.N());
566 bool contains (
int dim,
int codim)
const
567 {
return (codim == rowDofCodim); }
570 bool fixedSize(
int dim,
int codim)
const
576 template<
class EntityType>
577 std::size_t size(EntityType& e)
const
579 const auto rowIdx = rowEntityMapper_.index(e);
583 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
584 if (indexToID_.count(colIt.index()))
593 template<
class MessageBuffer,
class EntityType>
594 void gather(MessageBuffer& buff,
const EntityType& e)
const
596 const auto rowIdx = rowEntityMapper_.index(e);
599 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
600 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
601 buff.write(it->second);
607 template<
class MessageBuffer,
class EntityType>
608 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
610 const auto rowIdx = rowEntityMapper_.index(e);
611 for (std::size_t k = 0; k < n; k++)
618 if (
const auto it = idToIndex_.find(
id); it != idToIndex_.end())
620 const auto colIdx = it->second;
623 if (!isGhostColumDof_(colIdx))
625 sparsityPattern_[rowIdx].insert(colIdx);
631 const RowDofMapper& rowEntityMapper_;
632 const std::map<IdType, int>& idToIndex_;
633 const std::map<int, IdType>& indexToID_;
634 std::vector<std::set<int>>& sparsityPattern_;
636 const ColIsGhostFunc& isGhostColumDof_;
644 typename Matrix::block_type second;
648 struct MatrixEntryExchange
649 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
652 using DataType = MatrixEntry;
654 MatrixEntryExchange(
const RowDofMapper& rowEntityMapper,
655 const std::map<IdType, int>& globalToLocal,
656 const std::map<int, IdType>& localToGlobal,
658 : rowEntityMapper_(rowEntityMapper), idToIndex_(globalToLocal), indexToID_(localToGlobal), A_(A)
664 bool contains(
int dim,
int codim)
const
665 {
return (codim == rowDofCodim); }
668 bool fixedSize(
int dim,
int codim)
const
674 template<
class EntityType>
675 std::size_t size(EntityType& e)
const
677 const auto rowIdx = rowEntityMapper_.index(e);
679 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
680 if (indexToID_.count(colIt.index()))
689 template<
class MessageBuffer,
class EntityType>
690 void gather(MessageBuffer& buff,
const EntityType& e)
const
692 const auto rowIdx = rowEntityMapper_.index(e);
694 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
695 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
696 buff.write(MatrixEntry{ it->second, *colIt });
702 template<
class MessageBuffer,
class EntityType>
703 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
705 const auto rowIdx = rowEntityMapper_.index(e);
706 for (std::size_t k = 0; k < n; k++)
710 const auto& [colDofID, matrixBlock] = m;
713 if (
auto it = idToIndex_.find(colDofID); it != idToIndex_.end())
714 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
715 A_[rowIdx][it->second] += matrixBlock;
720 const RowDofMapper& rowEntityMapper_;
721 const std::map<IdType, int>& idToIndex_;
722 const std::map<int, IdType>& indexToID_;
730 : gridView_(gridView), mapper_(mapper)
735 for (
const auto& entity : entities(gridView_, Dune::Codim<rowDofCodim>()))
737 if (entity.partitionType() == Dune::BorderEntity)
739 const int localIdx = mapper_.index(entity);
740 IdType dofIdxGlobal = gridView_.grid().globalIdSet().id(entity);
742 idToIndex_.emplace(dofIdxGlobal, localIdx);
743 indexToID_.emplace(localIdx, dofIdxGlobal);
753 template<
class IsGhostFunc>
756 if constexpr (Detail::canCommunicate<typename GridView::Grid, rowDofCodim>)
758 if (gridView_.comm().size() <= 1)
762 Matrix matrixAsAssembled(A);
765 std::size_t numNonZeroEntries = 0;
766 std::vector<std::set<int>> sparsityPattern;
767 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost);
768 gridView_.communicate(
769 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
773 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
775 const auto colEndIt = A[rowIt.index()].end();
776 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
777 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
778 sparsityPattern[rowIt.index()].insert(colIt.index());
780 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
784 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
785 A.setBuildMode(Matrix::row_wise);
786 auto citer = A.createbegin();
787 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i!=end; ++i, ++citer)
788 for (
auto si = i->begin(), send = i->end(); si!=send; ++si)
793 const auto rowEndIt = matrixAsAssembled.end();
794 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
795 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
796 A[rowIt.index()][colIt.index()] = *colIt;
802 DUNE_THROW(Dune::InvalidStateException,
"Cannot call extendMatrix for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities.");
820 if constexpr (Detail::canCommunicate<typename GridView::Grid, rowDofCodim>)
822 if (gridView_.comm().size() <= 1)
825 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A);
826 gridView_.communicate(
827 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
831 DUNE_THROW(Dune::InvalidStateException,
832 "Cannot call sumEntries for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities."
837 const GridView gridView_;
838 const RowDofMapper& mapper_;
839 std::map<IdType, int> idToIndex_;
840 std::map<int, IdType> indexToID_;
848 class Matrix,
class Vector,
class ParallelHelper>
851 if constexpr (ParallelTraits::isNonOverlapping)
855 using GridView =
typename LinearSolverTraits::GridView;
856 using DofMapper =
typename LinearSolverTraits::DofMapper;
857 static constexpr int dofCodim = LinearSolverTraits::dofCodim;
859 matrixHelper.
extendMatrix(A, [&pHelper](
auto idx){
return pHelper.isGhost(idx); });
871 class Matrix,
class Vector,
class ParallelHelper>
873 std::shared_ptr<typename ParallelTraits::Comm>& comm,
874 std::shared_ptr<typename ParallelTraits::LinearOperator>& fop,
875 std::shared_ptr<typename ParallelTraits::ScalarProduct>& sp,
876 ParallelHelper& pHelper)
878 prepareLinearAlgebraParallel<LinearSolverTraits, ParallelTraits>(A, b, pHelper);
879 const auto category = ParallelTraits::isNonOverlapping ?
880 Dune::SolverCategory::nonoverlapping : Dune::SolverCategory::overlapping;
882 comm = std::make_shared<typename ParallelTraits::Comm>(pHelper.gridView().comm(), category);
883 pHelper.createParallelIndexSet(*comm);
884 fop = std::make_shared<typename ParallelTraits::LinearOperator>(A, *comm);
885 sp = std::make_shared<typename ParallelTraits::ScalarProduct>(*comm);
dune-grid capabilities compatibility layer
Contains a class to exchange entries of a vector.
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
void prepareLinearAlgebraParallel(Matrix &A, Vector &b, ParallelHelper &pHelper)
Prepare linear algebra variables for parallel solvers.
Definition: parallelhelpers.hh:849
LinearSolverTraitsImpl< GridGeometry, typename GridGeometry::DiscretizationMethod > LinearSolverTraits
The type traits required for using the IstlFactoryBackend.
Definition: linearsolvertraits.hh:49
A parallel helper class providing a nonoverlapping decomposition of all degrees of freedom.
Definition: parallelhelpers.hh:46
bool isGhost(std::size_t i) const
Definition: parallelhelpers.hh:305
void createParallelIndexSet(Comm &comm) const
Creates a parallel index set for a communicator.
Definition: parallelhelpers.hh:323
const DofMapper & dofMapper() const
Return the dofMapper.
Definition: parallelhelpers.hh:385
bool isOwned(std::size_t i) const
Definition: parallelhelpers.hh:308
const GridView & gridView() const
Return the gridView.
Definition: parallelhelpers.hh:389
ParallelISTLHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:294
Definition: parallelhelpers.hh:473
ParallelVectorHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:475
void makeNonOverlappingConsistent(Dune::BlockVector< Block, Alloc > &v) const
Definition: parallelhelpers.hh:481
Helper class for adding up matrix entries for border entities.
Definition: parallelhelpers.hh:510
ParallelMatrixHelper(const GridView &gridView, const RowDofMapper &mapper)
Definition: parallelhelpers.hh:729
void sumEntries(Matrix &A)
Sums up the entries corresponding to border entities (usually vertices or faces)
Definition: parallelhelpers.hh:818
void extendMatrix(Matrix &A, const IsGhostFunc &isGhost)
communicates values for the sparsity pattern of the new matrix.
Definition: parallelhelpers.hh:754
A data handle class to exchange entries of a vector.
Definition: vectorcommdatahandle.hh:78