25#ifndef DUMUX_LINEAR_PARALLELHELPERS_HH
26#define DUMUX_LINEAR_PARALLELHELPERS_HH
30#include <dune/geometry/dimension.hh>
31#include <dune/grid/common/datahandleif.hh>
32#include <dune/grid/common/partitionset.hh>
33#include <dune/istl/owneroverlapcopy.hh>
34#include <dune/istl/paamg/pinfo.hh>
45template<
class LinearSolverTraits>
48 using GridView =
typename LinearSolverTraits::GridView;
49 using DofMapper =
typename LinearSolverTraits::DofMapper;
50 enum { dofCodim = LinearSolverTraits::dofCodim };
53 static constexpr std::size_t ghostMarker_ = 1<<24;
55 class BaseGatherScatter
58 BaseGatherScatter(
const DofMapper& mapper)
61 template<
class EntityType>
62 int index(
const EntityType& e)
const
63 {
return mapper_.index(e); }
65 bool contains(
int dim,
int codim)
const
66 {
return dofCodim == codim; }
69 bool fixedSize(
int dim,
int codim)
const
72 template<
class EntityType>
73 std::size_t size(EntityType& e)
const
76 template<
class EntityType>
77 bool isNeitherInteriorNorBorderEntity(EntityType& e)
const
78 {
return e.partitionType() != Dune::InteriorEntity && e.partitionType() != Dune::BorderEntity; }
81 const DofMapper& mapper_;
90 class GhostGatherScatter
91 :
public BaseGatherScatter,
92 public Dune::CommDataHandleIF<GhostGatherScatter,std::size_t>
95 using DataType = std::size_t;
96 using BaseGatherScatter::contains;
97 using BaseGatherScatter::fixedSize;
98 using BaseGatherScatter::size;
100 GhostGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
101 : BaseGatherScatter(mapper), ranks_(ranks)
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), ranks_(ranks)
146 template<
class MessageBuffer,
class EntityType>
147 void gather(MessageBuffer& buff,
const EntityType& e)
const
149 auto& data = ranks_[this->index(e)];
150 if (this->isNeitherInteriorNorBorderEntity(e))
155 template<
class MessageBuffer,
class EntityType>
156 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
160 auto& data = ranks_[this->index(e)];
162 data = this->isNeitherInteriorNorBorderEntity(e) ? x : min(data,x);
165 std::vector<std::size_t>& ranks_;
172 struct NeighbourGatherScatter
173 :
public BaseGatherScatter,
174 public Dune::CommDataHandleIF<NeighbourGatherScatter,int>
176 using DataType = int;
177 using BaseGatherScatter::contains;
178 using BaseGatherScatter::fixedSize;
179 using BaseGatherScatter::size;
181 NeighbourGatherScatter(
const DofMapper& mapper,
int rank, std::set<int>& neighbours)
182 : BaseGatherScatter(mapper), rank_(rank), neighbours_(neighbours)
185 template<
class MessageBuffer,
class EntityType>
186 void gather(MessageBuffer& buff,
const EntityType& e)
const
191 template<
class MessageBuffer,
class EntityType>
192 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
196 neighbours_.insert(x);
200 std::set<int>& neighbours_;
208 struct SharedGatherScatter
209 :
public BaseGatherScatter,
210 public Dune::CommDataHandleIF<SharedGatherScatter,int>
212 using DataType = int;
213 using BaseGatherScatter::contains;
214 using BaseGatherScatter::fixedSize;
215 using BaseGatherScatter::size;
217 SharedGatherScatter(std::vector<int>& shared,
const DofMapper& mapper)
218 : BaseGatherScatter(mapper), shared_(shared)
221 template<
class MessageBuffer,
class EntityType>
222 void gather(MessageBuffer& buff, EntityType& e)
const
228 template<
class MessageBuffer,
class EntityType>
229 void scatter(MessageBuffer& buff,
const EntityType &e, std::size_t n)
233 auto& data = shared_[this->index(e)];
237 std::vector<int>& shared_;
244 template<
typename GlobalIndex>
245 struct GlobalIndexGatherScatter
246 :
public BaseGatherScatter,
247 public Dune::CommDataHandleIF<GlobalIndexGatherScatter<GlobalIndex>, GlobalIndex>
249 using DataType = GlobalIndex;
250 using BaseGatherScatter::contains;
251 using BaseGatherScatter::fixedSize;
252 using BaseGatherScatter::size;
254 GlobalIndexGatherScatter(std::vector<GlobalIndex>& globalIndices,
const DofMapper& mapper)
255 : BaseGatherScatter(mapper), globalIndices_(globalIndices)
258 template<
class MessageBuffer,
class EntityType>
259 void gather(MessageBuffer& buff,
const EntityType& e)
const
261 buff.write(globalIndices_[this->index(e)]);
264 template<
class MessageBuffer,
class EntityType>
265 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
270 auto& data = globalIndices_[this->index(e)];
274 std::vector<GlobalIndex>& globalIndices_;
280 : gridView_(
gridView), mapper_(mapper)
282 initGhostsAndOwners_();
286 {
return isGhost_[i] == ghostMarker_; }
297 if (gridView_.comm().size() <= 1)
299 comm.remoteIndices().template rebuild<false>();
304 std::vector<int> isShared(mapper_.size(),
false);
306 SharedGatherScatter sgs(isShared, mapper_);
307 gridView_.communicate(sgs, Dune::All_All_Interface, Dune::ForwardCommunication);
310 using GlobalIndex =
typename Comm::ParallelIndexSet::GlobalIndex;
311 GlobalIndex count = 0;
312 for (std::size_t i = 0; i < isShared.size(); ++i)
313 if (isShared[i] && isOwned_[i] == 1)
316 std::vector<GlobalIndex> counts(gridView_.comm().size());
317 gridView_.comm().allgather(&count, 1, counts.data());
320 const int rank = gridView_.comm().rank();
321 auto start = std::accumulate(counts.begin(), counts.begin() + rank, GlobalIndex(0));
323 std::vector<GlobalIndex> globalIndices(mapper_.size(), std::numeric_limits<GlobalIndex>::max());
325 for (std::size_t i = 0; i < globalIndices.size(); ++i)
327 if (isOwned_[i] == 1 && isShared[i])
329 globalIndices[i] =
start;
335 GlobalIndexGatherScatter<GlobalIndex> gigs(globalIndices, mapper_);
336 gridView_.communicate(gigs, Dune::All_All_Interface, Dune::ForwardCommunication);
338 resizeIndexSet_(comm, globalIndices);
341 std::set<int> neighbours;
342 NeighbourGatherScatter ngs(mapper_, gridView_.comm().rank(), neighbours);
343 gridView_.communicate(ngs, Dune::All_All_Interface, Dune::ForwardCommunication);
344 comm.remoteIndices().setNeighbours(neighbours);
346 comm.remoteIndices().template rebuild<false>();
355 {
return gridView_; }
358 void initGhostsAndOwners_()
360 const auto rank = gridView_.comm().rank();
361 isOwned_.assign(mapper_.size(), rank);
363 GhostGatherScatter ggs(isOwned_, mapper_);
365 if (gridView_.comm().size() > 1)
366 gridView_.communicate(ggs, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
371 InteriorBorderGatherScatter dh(isOwned_, mapper_);
373 if (gridView_.comm().size() > 1)
374 gridView_.communicate(dh, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication);
377 for (
auto& v : isOwned_)
378 v = (v == rank) ? 1 : 0;
381 template<
class Comm,
class GlobalIndices>
382 void resizeIndexSet_(Comm& comm,
const GlobalIndices& globalIndices)
const
384 comm.indexSet().beginResize();
386 for (std::size_t localIndex = 0; localIndex < globalIndices.size(); ++localIndex)
388 const auto globalIndex = globalIndices[localIndex];
389 if (globalIndex != std::numeric_limits<typename GlobalIndices::value_type>::max())
391 const bool isOwned = isOwned_[localIndex] > 0;
392 const auto attr = getAttribute_(comm, isOwned,
isGhost(localIndex));
393 using LocalIndex =
typename Comm::ParallelIndexSet::LocalIndex;
394 comm.indexSet().add(globalIndex, LocalIndex{localIndex, attr});
398 comm.indexSet().endResize();
402 Dune::OwnerOverlapCopyAttributeSet::AttributeSet
403 getAttribute_(
const Comm& comm,
const bool isOwned,
const bool isGhost)
const
406 return Dune::OwnerOverlapCopyAttributeSet::owner;
407 else if (
isGhost && (comm.category() ==
static_cast<int>(Dune::SolverCategory::nonoverlapping)) )
408 return Dune::OwnerOverlapCopyAttributeSet::overlap;
410 return Dune::OwnerOverlapCopyAttributeSet::copy;
413 const GridView gridView_;
414 const DofMapper& mapper_;
415 std::vector<std::size_t> isOwned_;
416 std::vector<std::size_t> isGhost_;
420template<
class Gr
idView,
class DofMapper,
int dofCodim>
425 : gridView_(gridView), mapper_(mapper)
429 template<
class Block,
class Alloc>
433 if (gridView_.comm().size() > 1)
434 gridView_.communicate(gs, Dune::InteriorBorder_InteriorBorder_Interface,
435 Dune::ForwardCommunication);
439 const GridView gridView_;
440 const DofMapper& mapper_;
447template<
class Matrix,
class Gr
idView,
class DofMapper,
int dofCodim>
450 static constexpr int dim = GridView::dimension;
451 using Grid =
typename GridView::Traits::Grid;
452 using BlockType =
typename Matrix::block_type;
453 using IDS =
typename Grid::Traits::GlobalIdSet;
454 using IdType =
typename IDS::IdType;
477 template<
class IsGhostFunc>
478 struct MatrixPatternExchange
479 :
public Dune::CommDataHandleIF<MatrixPatternExchange<IsGhostFunc>, IdType>
482 using DataType = IdType;
484 MatrixPatternExchange(
const DofMapper& mapper,
485 const std::map<IdType,int>& globalToLocal,
486 const std::map<int,IdType>& localToGlobal,
488 std::vector<std::set<int>>& sparsity,
489 const IsGhostFunc& isGhost)
490 : mapper_(mapper), idToIndex_(globalToLocal), indexToID_(localToGlobal)
491 , sparsity_(sparsity), A_(A), isGhost_(isGhost)
493 sparsity_.resize(A.N());
499 bool contains (
int dim,
int codim)
const
500 {
return (codim == dofCodim); }
503 bool fixedSize(
int dim,
int codim)
const
509 template<
class EntityType>
510 std::size_t size(EntityType& e)
const
512 const auto rowIdx = mapper_.index(e);
514 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
515 if (indexToID_.count(colIt.index()))
524 template<
class MessageBuffer,
class EntityType>
525 void gather(MessageBuffer& buff,
const EntityType& e)
const
527 const auto rowIdx = mapper_.index(e);
528 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
530 auto it = indexToID_.find(colIt.index());
531 if (it != indexToID_.end())
532 buff.write(it->second);
539 template<
class MessageBuffer,
class EntityType>
540 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
542 const auto rowIdx = mapper_.index(e);
543 for (std::size_t k = 0; k < n; k++)
548 const auto it = idToIndex_.find(
id);
549 if (it != idToIndex_.end())
551 const auto colIdx = it->second;
552 if (!sparsity_[rowIdx].count(colIdx) && !isGhost_(colIdx))
553 sparsity_[rowIdx].insert(colIdx);
559 const DofMapper& mapper_;
560 const std::map<IdType,int>& idToIndex_;
561 const std::map<int,IdType>& indexToID_;
562 std::vector<std::set<int>>& sparsity_;
564 const IsGhostFunc& isGhost_;
573 MatrixEntry (
const IdType& f,
const BlockType& s) : first(f), second(s) {}
578 struct MatrixEntryExchange
579 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
582 using DataType = MatrixEntry;
584 MatrixEntryExchange(
const DofMapper& mapper,
585 const std::map<IdType,int>& globalToLocal,
586 const std::map<int,IdType>& localToGlobal,
588 : mapper_(mapper), idToIndex_(globalToLocal), indexToID_(localToGlobal), A_(A)
594 bool contains(
int dim,
int codim)
const
595 {
return (codim == dofCodim); }
598 bool fixedSize(
int dim,
int codim)
const
604 template<
class EntityType>
605 std::size_t size(EntityType& e)
const
607 const auto rowIdx = mapper_.index(e);
609 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
610 if (indexToID_.count(colIt.index()))
619 template<
class MessageBuffer,
class EntityType>
620 void gather(MessageBuffer& buff,
const EntityType& e)
const
622 const auto rowIdx = mapper_.index(e);
623 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
625 auto it = indexToID_.find(colIt.index());
626 if (it != indexToID_.end())
627 buff.write(MatrixEntry(it->second,*colIt));
634 template<
class MessageBuffer,
class EntityType>
635 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
637 const auto rowIdx = mapper_.index(e);
638 for (std::size_t k = 0; k < n; k++)
643 auto it = idToIndex_.find(m.first);
644 if (it != idToIndex_.end())
645 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
646 A_[rowIdx][it->second] += m.second;
651 const DofMapper& mapper_;
652 const std::map<IdType,int>& idToIndex_;
653 const std::map<int,IdType>& indexToID_;
661 : gridView_(gridView), mapper_(mapper)
666 for (
const auto& entity : entities(gridView_, Dune::Codim<dofCodim>()))
668 if (entity.partitionType() == Dune::BorderEntity)
670 const int localIdx = mapper_.index(entity);
671 IdType dofIdxGlobal = gridView_.grid().globalIdSet().id(entity);
673 idToIndex_.emplace(dofIdxGlobal, localIdx);
674 indexToID_.emplace(localIdx, dofIdxGlobal);
684 template<
class IsGhostFunc>
687 if (gridView_.comm().size() <= 1)
693 std::vector<std::set<int>> sparsity;
694 MatrixPatternExchange<IsGhostFunc> datahandle(mapper_, idToIndex_, indexToID_, A, sparsity, isGhost);
695 gridView_.communicate(datahandle, Dune::InteriorBorder_InteriorBorder_Interface,
696 Dune::ForwardCommunication);
698 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
700 for (
auto colIt = A[rowIt.index()].begin(); colIt != A[rowIt.index()].end(); ++colIt)
701 if (!sparsity[rowIt.index()].count(colIt.index()))
702 sparsity[rowIt.index()].insert(colIt.index());
704 nnz += sparsity[rowIt.index()].size();
707 A.setSize(tmp.N(), tmp.N(), nnz);
708 A.setBuildMode(Matrix::row_wise);
709 auto citer = A.createbegin();
710 for (
auto i = sparsity.begin(), end = sparsity.end(); i!=end; ++i, ++citer)
712 for (
auto si = i->begin(), send = i->end(); si!=send; ++si)
718 for (
auto rowIt = tmp.begin(); rowIt != tmp.end(); ++rowIt)
719 for (
auto colIt = tmp[rowIt.index()].begin(); colIt != tmp[rowIt.index()].end(); ++colIt)
720 A[rowIt.index()][colIt.index()] = tmp[rowIt.index()][colIt.index()];
729 if (gridView_.comm().size() <= 1)
732 MatrixEntryExchange datahandle(mapper_, idToIndex_, indexToID_, A);
733 gridView_.communicate(datahandle, Dune::InteriorBorder_InteriorBorder_Interface,
734 Dune::ForwardCommunication);
738 const GridView gridView_;
739 const DofMapper& mapper_;
740 std::map<IdType, int> idToIndex_;
741 std::map<int, IdType> indexToID_;
749 class Matrix,
class Vector,
class ParallelHelper>
752 if constexpr (ParallelTraits::isNonOverlapping)
756 using GridView =
typename LinearSolverTraits::GridView;
757 using DofMapper =
typename LinearSolverTraits::DofMapper;
758 static constexpr int dofCodim = LinearSolverTraits::dofCodim;
760 matrixHelper.
extendMatrix(A, [&pHelper](
auto idx){
return pHelper.isGhost(idx); });
772 class Matrix,
class Vector,
class ParallelHelper>
774 std::shared_ptr<typename ParallelTraits::Comm>& comm,
775 std::shared_ptr<typename ParallelTraits::LinearOperator>& fop,
776 std::shared_ptr<typename ParallelTraits::ScalarProduct>& sp,
777 ParallelHelper& pHelper)
779 prepareLinearAlgebraParallel<LinearSolverTraits, ParallelTraits>(A, b, pHelper);
780 const auto category = ParallelTraits::isNonOverlapping ?
781 Dune::SolverCategory::nonoverlapping : Dune::SolverCategory::overlapping;
783 comm = std::make_shared<typename ParallelTraits::Comm>(pHelper.gridView().comm(), category);
784 pHelper.createParallelIndexSet(*comm);
785 fop = std::make_shared<typename ParallelTraits::LinearOperator>(A, *comm);
786 sp = std::make_shared<typename ParallelTraits::ScalarProduct>(*comm);
Contains a class to exchange entries of a vector.
int start(int argc, char **argv, void(*usage)(const char *, const std::string &))
Provides a main function with error handling.
Definition: start.hh:127
void prepareLinearAlgebraParallel(Matrix &A, Vector &b, ParallelHelper &pHelper)
Prepare linear algebra variables for parallel solvers.
Definition: parallelhelpers.hh:750
LinearSolverTraitsImpl< GridGeometry, GridGeometry::discMethod > LinearSolverTraits
The type traits required for using the IstlFactoryBackend.
Definition: linearsolvertraits.hh:72
A parallel helper class providing a nonoverlapping decomposition of all degrees of freedom.
Definition: parallelhelpers.hh:47
bool isGhost(std::size_t i) const
Definition: parallelhelpers.hh:285
void createParallelIndexSet(Comm &comm) const
Creates a parallel index set.
Definition: parallelhelpers.hh:295
const DofMapper & dofMapper() const
Return the dofMapper.
Definition: parallelhelpers.hh:350
const GridView & gridView() const
Return the gridView.
Definition: parallelhelpers.hh:354
ParallelISTLHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:279
Definition: parallelhelpers.hh:422
ParallelVectorHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:424
void makeNonOverlappingConsistent(Dune::BlockVector< Block, Alloc > &v) const
Definition: parallelhelpers.hh:430
Helper class for adding up matrix entries on border.
Definition: parallelhelpers.hh:449
ParallelMatrixHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:660
void extendMatrix(Matrix &A, const IsGhostFunc &isGhost)
communicates values for the sparsity pattern of the new matrix.
Definition: parallelhelpers.hh:685
void sumEntries(Matrix &A)
Sums up the entries corresponding to border vertices.
Definition: parallelhelpers.hh:727
A data handle class to exchange entries of a vector.
Definition: vectorcommdatahandle.hh:78