25#ifndef DUMUX_LINEAR_PARALLELHELPERS_HH
26#define DUMUX_LINEAR_PARALLELHELPERS_HH
30#include <dune/common/version.hh>
31#include <dune/geometry/dimension.hh>
32#include <dune/grid/common/datahandleif.hh>
33#include <dune/grid/common/partitionset.hh>
34#include <dune/istl/owneroverlapcopy.hh>
35#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; }
68#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
70 bool fixedSize(
int dim,
int codim)
const
74 bool fixedsize(
int dim,
int codim)
const
78 template<
class EntityType>
79 std::size_t size(EntityType& e)
const
82 template<
class EntityType>
83 bool isNeitherInteriorNorBorderEntity(EntityType& e)
const
84 {
return e.partitionType() != Dune::InteriorEntity && e.partitionType() != Dune::BorderEntity; }
87 const DofMapper& mapper_;
94 class ConsistencyBoxGatherScatter
95 :
public BaseGatherScatter,
96 public Dune::CommDataHandleIF<ConsistencyBoxGatherScatter<V>,typename V::block_type>
99 using DataType =
typename V::block_type;
100 using BaseGatherScatter::contains;
101#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
102 using BaseGatherScatter::fixedSize;
104 using BaseGatherScatter::fixedsize;
106 using BaseGatherScatter::size;
108 ConsistencyBoxGatherScatter(V& container,
const DofMapper& mapper)
109 : BaseGatherScatter(mapper), container_(container)
112 template<
class MessageBuffer,
class EntityType>
113 void gather(MessageBuffer& buff,
const EntityType& e)
const
115 buff.write(container_[this->index(e)]);
118 template<
class MessageBuffer,
class EntityType>
119 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
121 typename V::block_type block;
123 container_[this->index(e)] += block;
136 class GhostGatherScatter
137 :
public BaseGatherScatter,
138 public Dune::CommDataHandleIF<GhostGatherScatter,std::size_t>
141 using DataType = std::size_t;
142 using BaseGatherScatter::contains;
143#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
144 using BaseGatherScatter::fixedSize;
146 using BaseGatherScatter::fixedsize;
148 using BaseGatherScatter::size;
150 GhostGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
151 : BaseGatherScatter(mapper), ranks_(ranks)
154 template<
class MessageBuffer,
class EntityType>
155 void gather(MessageBuffer& buff,
const EntityType& e)
const
157 auto& data = ranks_[this->index(e)];
158 if (this->isNeitherInteriorNorBorderEntity(e))
163 template<
class MessageBuffer,
class EntityType>
164 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
168 auto& data = ranks_[this->index(e)];
169 if (this->isNeitherInteriorNorBorderEntity(e))
173 std::vector<std::size_t>& ranks_;
182 class InteriorBorderGatherScatter
183 :
public BaseGatherScatter,
184 public Dune::CommDataHandleIF<InteriorBorderGatherScatter,std::size_t>
187 using DataType = std::size_t;
188 using BaseGatherScatter::contains;
189#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
190 using BaseGatherScatter::fixedSize;
192 using BaseGatherScatter::fixedsize;
194 using BaseGatherScatter::size;
196 InteriorBorderGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
197 : BaseGatherScatter(mapper), ranks_(ranks)
200 template<
class MessageBuffer,
class EntityType>
201 void gather(MessageBuffer& buff,
const EntityType& e)
const
203 auto& data = ranks_[this->index(e)];
204 if (this->isNeitherInteriorNorBorderEntity(e))
209 template<
class MessageBuffer,
class EntityType>
210 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
214 auto& data = ranks_[this->index(e)];
216 data = this->isNeitherInteriorNorBorderEntity(e) ? x : min(data,x);
219 std::vector<std::size_t>& ranks_;
226 struct NeighbourGatherScatter
227 :
public BaseGatherScatter,
228 public Dune::CommDataHandleIF<NeighbourGatherScatter,int>
230 using DataType = int;
231 using BaseGatherScatter::contains;
232#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
233 using BaseGatherScatter::fixedSize;
235 using BaseGatherScatter::fixedsize;
237 using BaseGatherScatter::size;
239 NeighbourGatherScatter(
const DofMapper& mapper,
int rank, std::set<int>& neighbours)
240 : BaseGatherScatter(mapper), rank_(rank), neighbours_(neighbours)
243 template<
class MessageBuffer,
class EntityType>
244 void gather(MessageBuffer& buff,
const EntityType& e)
const
249 template<
class MessageBuffer,
class EntityType>
250 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
254 neighbours_.insert(x);
258 std::set<int>& neighbours_;
266 struct SharedGatherScatter
267 :
public BaseGatherScatter,
268 public Dune::CommDataHandleIF<SharedGatherScatter,int>
270 using DataType = int;
271 using BaseGatherScatter::contains;
272#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
273 using BaseGatherScatter::fixedSize;
275 using BaseGatherScatter::fixedsize;
277 using BaseGatherScatter::size;
279 SharedGatherScatter(std::vector<int>& shared,
const DofMapper& mapper)
280 : BaseGatherScatter(mapper), shared_(shared)
283 template<
class MessageBuffer,
class EntityType>
284 void gather(MessageBuffer& buff, EntityType& e)
const
290 template<
class MessageBuffer,
class EntityType>
291 void scatter(MessageBuffer& buff,
const EntityType &e, std::size_t n)
295 auto& data = shared_[this->index(e)];
299 std::vector<int>& shared_;
306 template<
typename GlobalIndex>
307 struct GlobalIndexGatherScatter
308 :
public BaseGatherScatter,
309 public Dune::CommDataHandleIF<GlobalIndexGatherScatter<GlobalIndex>, GlobalIndex>
311 using DataType = GlobalIndex;
312 using BaseGatherScatter::contains;
313#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
314 using BaseGatherScatter::fixedSize;
316 using BaseGatherScatter::fixedsize;
318 using BaseGatherScatter::size;
320 GlobalIndexGatherScatter(std::vector<GlobalIndex>& globalIndices,
const DofMapper& mapper)
321 : BaseGatherScatter(mapper), globalIndices_(globalIndices)
324 template<
class MessageBuffer,
class EntityType>
325 void gather(MessageBuffer& buff,
const EntityType& e)
const
327 buff.write(globalIndices_[this->index(e)]);
330 template<
class MessageBuffer,
class EntityType>
331 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
336 auto& data = globalIndices_[this->index(e)];
340 std::vector<GlobalIndex>& globalIndices_;
346 : gridView_(
gridView), mapper_(mapper), initialized_(false)
353 const auto rank = gridView_.comm().rank();
354 isOwned_.resize(mapper_.size(), rank);
356 GhostGatherScatter ggs(isOwned_, mapper_);
358 if (gridView_.comm().size() > 1)
359 gridView_.communicate(ggs, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
364 InteriorBorderGatherScatter dh(isOwned_, mapper_);
366 if (gridView_.comm().size() > 1)
367 gridView_.communicate(dh, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication);
370 for (
auto& v : isOwned_)
371 v = (v == rank) ? 1 : 0;
377 {
return isGhost_[i] == ghostMarker_; }
380 template<
class B,
class A>
383 ConsistencyBoxGatherScatter<Dune::BlockVector<B,A> > gs(v, mapper_);
384 if (gridView_.comm().size() > 1)
385 gridView_.communicate(gs, Dune::InteriorBorder_InteriorBorder_Interface,
386 Dune::ForwardCommunication);
406 if (gridView_.comm().size() <= 1)
408 comm.remoteIndices().template rebuild<false>();
413 std::vector<int> isShared(mapper_.size(),
false);
415 SharedGatherScatter sgs(isShared, mapper_);
416 gridView_.communicate(sgs, Dune::All_All_Interface, Dune::ForwardCommunication);
419 using GlobalIndex =
typename Comm::ParallelIndexSet::GlobalIndex;
420 GlobalIndex count = 0;
421 for (std::size_t i = 0; i < isShared.size(); ++i)
422 if (isShared[i] && isOwned_[i] == 1)
425 std::vector<GlobalIndex> counts(gridView_.comm().size());
426 gridView_.comm().allgather(&count, 1, counts.data());
429 const int rank = gridView_.comm().rank();
430 auto start = std::accumulate(counts.begin(), counts.begin() + rank, GlobalIndex(0));
432 std::vector<GlobalIndex> globalIndices(mapper_.size(), std::numeric_limits<GlobalIndex>::max());
434 for (std::size_t i = 0; i < globalIndices.size(); ++i)
436 if (isOwned_[i] == 1 && isShared[i])
438 globalIndices[i] =
start;
444 GlobalIndexGatherScatter<GlobalIndex> gigs(globalIndices, mapper_);
445 gridView_.communicate(gigs, Dune::All_All_Interface, Dune::ForwardCommunication);
447 resizeIndexSet_(comm, globalIndices);
450 std::set<int> neighbours;
451 NeighbourGatherScatter ngs(mapper_, gridView_.comm().rank(), neighbours);
452 gridView_.communicate(ngs, Dune::All_All_Interface, Dune::ForwardCommunication);
453 comm.remoteIndices().setNeighbours(neighbours);
455 comm.remoteIndices().template rebuild<false>();
464 {
return gridView_; }
467 template<
class Comm,
class GlobalIndices>
468 void resizeIndexSet_(Comm& comm,
const GlobalIndices& globalIndices)
const
470 comm.indexSet().beginResize();
472 for (std::size_t localIndex = 0; localIndex < globalIndices.size(); ++localIndex)
474 const auto globalIndex = globalIndices[localIndex];
475 if (globalIndex != std::numeric_limits<typename GlobalIndices::value_type>::max())
477 const bool isOwned = isOwned_[localIndex] > 0;
478 const auto attr = getAttribute_(comm, isOwned,
isGhost(localIndex));
479 using LocalIndex =
typename Comm::ParallelIndexSet::LocalIndex;
480 comm.indexSet().add(globalIndex, LocalIndex{localIndex, attr});
484 comm.indexSet().endResize();
488 Dune::OwnerOverlapCopyAttributeSet::AttributeSet
489 getAttribute_(
const Comm& comm,
const bool isOwned,
const bool isGhost)
const
492 return Dune::OwnerOverlapCopyAttributeSet::owner;
493#if DUNE_VERSION_GTE(DUNE_ISTL, 2, 7)
494 else if (
isGhost && (comm.category() ==
static_cast<int>(Dune::SolverCategory::nonoverlapping)) )
496 else if (
isGhost && (comm.getSolverCategory() ==
static_cast<int>(Dune::SolverCategory::nonoverlapping)) )
498 return Dune::OwnerOverlapCopyAttributeSet::overlap;
500 return Dune::OwnerOverlapCopyAttributeSet::copy;
503 const GridView gridView_;
504 const DofMapper& mapper_;
505 std::vector<std::size_t> isOwned_;
506 std::vector<std::size_t> isGhost_;
515template<
class Matrix,
class Gr
idView,
class DofMapper,
int dofCodim>
518 static constexpr int dim = GridView::dimension;
519 using Grid =
typename GridView::Traits::Grid;
520 using BlockType =
typename Matrix::block_type;
521 using IDS =
typename Grid::Traits::GlobalIdSet;
522 using IdType =
typename IDS::IdType;
545 template<
class IsGhostFunc>
546 struct MatrixPatternExchange
547 :
public Dune::CommDataHandleIF<MatrixPatternExchange<IsGhostFunc>, IdType>
550 using DataType = IdType;
552 MatrixPatternExchange(
const DofMapper& mapper,
553 const std::map<IdType,int>& globalToLocal,
554 const std::map<int,IdType>& localToGlobal,
556 std::vector<std::set<int>>& sparsity,
557 const IsGhostFunc& isGhost)
558 : mapper_(mapper), idToIndex_(globalToLocal), indexToID_(localToGlobal)
559 , sparsity_(sparsity), A_(A), isGhost_(isGhost)
561 sparsity_.resize(A.N());
567 bool contains (
int dim,
int codim)
const
568 {
return (codim == dofCodim); }
570#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
572 bool fixedSize(
int dim,
int codim)
const
576 bool fixedsize(
int dim,
int codim)
const
583 template<
class EntityType>
584 std::size_t size(EntityType& e)
const
586 const auto rowIdx = mapper_.index(e);
588 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
589 if (indexToID_.count(colIt.index()))
598 template<
class MessageBuffer,
class EntityType>
599 void gather(MessageBuffer& buff,
const EntityType& e)
const
601 const auto rowIdx = mapper_.index(e);
602 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
604 auto it = indexToID_.find(colIt.index());
605 if (it != indexToID_.end())
606 buff.write(it->second);
613 template<
class MessageBuffer,
class EntityType>
614 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
616 const auto rowIdx = mapper_.index(e);
617 for (std::size_t k = 0; k < n; k++)
622 const auto it = idToIndex_.find(
id);
623 if (it != idToIndex_.end())
625 const auto colIdx = it->second;
626 if (!sparsity_[rowIdx].count(colIdx) && !isGhost_(colIdx))
627 sparsity_[rowIdx].insert(colIdx);
633 const DofMapper& mapper_;
634 const std::map<IdType,int>& idToIndex_;
635 const std::map<int,IdType>& indexToID_;
636 std::vector<std::set<int>>& sparsity_;
638 const IsGhostFunc& isGhost_;
647 MatrixEntry (
const IdType& f,
const BlockType& s) : first(f), second(s) {}
652 struct MatrixEntryExchange
653 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
656 using DataType = MatrixEntry;
658 MatrixEntryExchange(
const DofMapper& mapper,
659 const std::map<IdType,int>& globalToLocal,
660 const std::map<int,IdType>& localToGlobal,
662 : mapper_(mapper), idToIndex_(globalToLocal), indexToID_(localToGlobal), A_(A)
668 bool contains(
int dim,
int codim)
const
669 {
return (codim == dofCodim); }
671#if DUNE_VERSION_GTE(DUNE_GRID,2,7)
673 bool fixedSize(
int dim,
int codim)
const
677 bool fixedsize(
int dim,
int codim)
const
684 template<
class EntityType>
685 std::size_t size(EntityType& e)
const
687 const auto rowIdx = mapper_.index(e);
689 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
690 if (indexToID_.count(colIt.index()))
699 template<
class MessageBuffer,
class EntityType>
700 void gather(MessageBuffer& buff,
const EntityType& e)
const
702 const auto rowIdx = mapper_.index(e);
703 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
705 auto it = indexToID_.find(colIt.index());
706 if (it != indexToID_.end())
707 buff.write(MatrixEntry(it->second,*colIt));
714 template<
class MessageBuffer,
class EntityType>
715 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
717 const auto rowIdx = mapper_.index(e);
718 for (std::size_t k = 0; k < n; k++)
723 auto it = idToIndex_.find(m.first);
724 if (it != idToIndex_.end())
725 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
726 A_[rowIdx][it->second] += m.second;
731 const DofMapper& mapper_;
732 const std::map<IdType,int>& idToIndex_;
733 const std::map<int,IdType>& indexToID_;
741 : gridView_(gridView), mapper_(mapper)
746 for (
const auto& entity : entities(gridView_, Dune::Codim<dofCodim>()))
748 if (entity.partitionType() == Dune::BorderEntity)
750 const int localIdx = mapper_.index(entity);
751 IdType dofIdxGlobal = gridView_.grid().globalIdSet().id(entity);
753 idToIndex_.emplace(dofIdxGlobal, localIdx);
754 indexToID_.emplace(localIdx, dofIdxGlobal);
764 template<
class IsGhostFunc>
767 if (gridView_.comm().size() <= 1)
773 std::vector<std::set<int>> sparsity;
774 MatrixPatternExchange<IsGhostFunc> datahandle(mapper_, idToIndex_, indexToID_, A, sparsity, isGhost);
775 gridView_.communicate(datahandle, Dune::InteriorBorder_InteriorBorder_Interface,
776 Dune::ForwardCommunication);
778 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
780 for (
auto colIt = A[rowIt.index()].begin(); colIt != A[rowIt.index()].end(); ++colIt)
781 if (!sparsity[rowIt.index()].count(colIt.index()))
782 sparsity[rowIt.index()].insert(colIt.index());
784 nnz += sparsity[rowIt.index()].size();
787 A.setSize(tmp.N(), tmp.N(), nnz);
788 A.setBuildMode(Matrix::row_wise);
789 auto citer = A.createbegin();
790 for (
auto i = sparsity.begin(), end = sparsity.end(); i!=end; ++i, ++citer)
792 for (
auto si = i->begin(), send = i->end(); si!=send; ++si)
798 for (
auto rowIt = tmp.begin(); rowIt != tmp.end(); ++rowIt)
799 for (
auto colIt = tmp[rowIt.index()].begin(); colIt != tmp[rowIt.index()].end(); ++colIt)
800 A[rowIt.index()][colIt.index()] = tmp[rowIt.index()][colIt.index()];
809 if (gridView_.comm().size() <= 1)
812 MatrixEntryExchange datahandle(mapper_, idToIndex_, indexToID_, A);
813 gridView_.communicate(datahandle, Dune::InteriorBorder_InteriorBorder_Interface,
814 Dune::ForwardCommunication);
818 const GridView gridView_;
819 const DofMapper& mapper_;
820 std::map<IdType, int> idToIndex_;
821 std::map<int, IdType> indexToID_;
829 class Matrix,
class Vector,
class ParallelHelper>
831 std::shared_ptr<typename ParallelTraits::Comm>& comm,
832 std::shared_ptr<typename ParallelTraits::LinearOperator>& fop,
833 std::shared_ptr<typename ParallelTraits::ScalarProduct>& sp,
834 ParallelHelper& pHelper)
836 if constexpr (ParallelTraits::isNonOverlapping)
840 using GridView =
typename LinearSolverTraits::GridView;
841 using DofMapper =
typename LinearSolverTraits::DofMapper;
842 static constexpr int dofCodim = LinearSolverTraits::dofCodim;
844 matrixHelper.
extendMatrix(A, [&pHelper](
auto idx){
return pHelper.isGhost(idx); });
847 pHelper.makeNonOverlappingConsistent(b);
850 const auto category = Dune::SolverCategory::nonoverlapping;
851 comm = std::make_shared<typename ParallelTraits::Comm>(pHelper.gridView().comm(), category);
852 pHelper.createParallelIndexSet(*comm);
853 fop = std::make_shared<typename ParallelTraits::LinearOperator>(A, *comm);
854 sp = std::make_shared<typename ParallelTraits::ScalarProduct>(*comm);
859 const auto category = Dune::SolverCategory::overlapping;
860 comm = std::make_shared<typename ParallelTraits::Comm>(pHelper.gridView().comm(), category);
861 pHelper.createParallelIndexSet(*comm);
862 fop = std::make_shared<typename ParallelTraits::LinearOperator>(A, *comm);
863 sp = std::make_shared<typename ParallelTraits::ScalarProduct>(*comm);
int start(int argc, char **argv, void(*usage)(const char *, const std::string &))
Provides a main function with error handling.
Definition: start.hh:127
LinearSolverTraitsImpl< GridGeometry, GridGeometry::discMethod > LinearSolverTraits
The type traits required for using the IstlFactoryBackend.
Definition: linearsolvertraits.hh:72
void prepareLinearAlgebraParallel(Matrix &A, Vector &b, std::shared_ptr< typename ParallelTraits::Comm > &comm, std::shared_ptr< typename ParallelTraits::LinearOperator > &fop, std::shared_ptr< typename ParallelTraits::ScalarProduct > &sp, ParallelHelper &pHelper)
Prepare linear algebra variables for parallel solvers.
Definition: parallelhelpers.hh:830
A parallel helper class providing a nonoverlapping decomposition of all degrees of freedom.
Definition: parallelhelpers.hh:47
void makeNonOverlappingConsistent(Dune::BlockVector< B, A > &v)
Definition: parallelhelpers.hh:381
bool isGhost(std::size_t i) const
Definition: parallelhelpers.hh:376
const DofMapper & dofMapper() const
Return the dofMapper.
Definition: parallelhelpers.hh:459
void createParallelIndexSet(Comm &comm)
Creates a parallel index set.
Definition: parallelhelpers.hh:396
const GridView & gridView() const
Return the gridView.
Definition: parallelhelpers.hh:463
ParallelISTLHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:345
void initGhostsAndOwners()
Definition: parallelhelpers.hh:351
Helper class for adding up matrix entries on border.
Definition: parallelhelpers.hh:517
ParallelMatrixHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:740
void extendMatrix(Matrix &A, const IsGhostFunc &isGhost)
communicates values for the sparsity pattern of the new matrix.
Definition: parallelhelpers.hh:765
void sumEntries(Matrix &A)
Sums up the entries corresponding to border vertices.
Definition: parallelhelpers.hh:807