12#ifndef DUMUX_LINEAR_PARALLELHELPERS_HH
13#define DUMUX_LINEAR_PARALLELHELPERS_HH
15#include <dune/common/exceptions.hh>
16#include <dune/geometry/dimension.hh>
17#include <dune/grid/common/datahandleif.hh>
18#include <dune/grid/common/partitionset.hh>
19#include <dune/istl/owneroverlapcopy.hh>
20#include <dune/istl/paamg/pinfo.hh>
21#include <dune/istl/bvector.hh>
22#include <dune/istl/multitypeblockvector.hh>
28template<
class LinearSolverTraits,
bool canCommunicate = false>
31template<
class LinearSolverTraits>
34 using GridView =
typename LinearSolverTraits::GridView;
35 using DofMapper =
typename LinearSolverTraits::DofMapper;
36 static constexpr int dofCodim = LinearSolverTraits::dofCodim;
39 static constexpr std::size_t ghostMarker_ = 1<<24;
41 class BaseGatherScatter
44 BaseGatherScatter(
const DofMapper& mapper)
47 template<
class EntityType>
48 int index(
const EntityType& e)
const
49 {
return mapper_.index(e); }
51 bool contains(
int dim,
int codim)
const
52 {
return dofCodim == codim; }
55 bool fixedSize(
int dim,
int codim)
const
58 template<
class EntityType>
59 std::size_t size(EntityType& e)
const
62 template<
class EntityType>
63 bool isNeitherInteriorNorBorderEntity(EntityType& e)
const
64 {
return e.partitionType() != Dune::InteriorEntity && e.partitionType() != Dune::BorderEntity; }
67 const DofMapper& mapper_;
76 class GhostGatherScatter
77 :
public BaseGatherScatter
78 ,
public Dune::CommDataHandleIF<GhostGatherScatter, std::size_t>
81 using DataType = std::size_t;
82 using BaseGatherScatter::contains;
83 using BaseGatherScatter::fixedSize;
84 using BaseGatherScatter::size;
86 GhostGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
87 : BaseGatherScatter(mapper)
91 template<
class MessageBuffer,
class EntityType>
92 void gather(MessageBuffer& buff,
const EntityType& e)
const
94 auto& data = ranks_[this->index(e)];
95 if (this->isNeitherInteriorNorBorderEntity(e))
100 template<
class MessageBuffer,
class EntityType>
101 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
105 auto& data = ranks_[this->index(e)];
106 if (this->isNeitherInteriorNorBorderEntity(e))
110 std::vector<std::size_t>& ranks_;
119 class InteriorBorderGatherScatter
120 :
public BaseGatherScatter
121 ,
public Dune::CommDataHandleIF<InteriorBorderGatherScatter, std::size_t>
124 using DataType = std::size_t;
125 using BaseGatherScatter::contains;
126 using BaseGatherScatter::fixedSize;
127 using BaseGatherScatter::size;
129 InteriorBorderGatherScatter(std::vector<std::size_t>& ranks,
const DofMapper& mapper)
130 : BaseGatherScatter(mapper)
137 template<
class MessageBuffer,
class EntityType>
138 void gather(MessageBuffer& buff,
const EntityType& e)
const
140 auto& data = ranks_[this->index(e)];
141 if (this->isNeitherInteriorNorBorderEntity(e))
149 template<
class MessageBuffer,
class EntityType>
150 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
154 auto& data = ranks_[this->index(e)];
160 data = this->isNeitherInteriorNorBorderEntity(e) ? x : min(data, x);
163 std::vector<std::size_t>& ranks_;
170 struct NeighbourGatherScatter
171 :
public BaseGatherScatter
172 ,
public Dune::CommDataHandleIF<NeighbourGatherScatter, int>
174 using DataType = int;
175 using BaseGatherScatter::contains;
176 using BaseGatherScatter::fixedSize;
177 using BaseGatherScatter::size;
179 NeighbourGatherScatter(
const DofMapper& mapper,
int rank, std::set<int>& neighbours)
180 : BaseGatherScatter(mapper)
182 , 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)
222 template<
class MessageBuffer,
class EntityType>
223 void gather(MessageBuffer& buff, EntityType& e)
const
229 template<
class MessageBuffer,
class EntityType>
230 void scatter(MessageBuffer& buff,
const EntityType &e, std::size_t n)
234 auto& data = shared_[this->index(e)];
238 std::vector<int>& shared_;
245 template<
typename GlobalIndex>
246 struct GlobalIndexGatherScatter
247 :
public BaseGatherScatter
248 ,
public Dune::CommDataHandleIF<GlobalIndexGatherScatter<GlobalIndex>, GlobalIndex>
250 using DataType = GlobalIndex;
251 using BaseGatherScatter::contains;
252 using BaseGatherScatter::fixedSize;
253 using BaseGatherScatter::size;
255 GlobalIndexGatherScatter(std::vector<GlobalIndex>& globalIndices,
const DofMapper& mapper)
256 : BaseGatherScatter(mapper)
257 , globalIndices_(globalIndices)
260 template<
class MessageBuffer,
class EntityType>
261 void gather(MessageBuffer& buff,
const EntityType& e)
const
263 buff.write(globalIndices_[this->index(e)]);
266 template<
class MessageBuffer,
class EntityType>
267 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
272 DataType& data = globalIndices_[this->index(e)];
276 std::vector<GlobalIndex>& globalIndices_;
282 : gridView_(gridView), mapper_(mapper)
284 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Traits::Grid, dofCodim>::v)
285 initGhostsAndOwners_();
287 DUNE_THROW(Dune::InvalidStateException,
288 "Cannot initialize parallel helper for a grid that cannot communicate codim-" << dofCodim <<
"-entities."
293 {
return isGhost_[i] == ghostMarker_; }
296 {
return isOwned_[i] == 1; }
312 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Traits::Grid, dofCodim>::v)
314 if (gridView_.comm().size() <= 1)
316 comm.remoteIndices().template rebuild<false>();
321 std::vector<int> isShared(mapper_.size(),
false);
322 SharedGatherScatter sgs(isShared, mapper_);
323 gridView_.communicate(sgs, Dune::All_All_Interface, Dune::ForwardCommunication);
326 using GlobalIndex =
typename Comm::ParallelIndexSet::GlobalIndex;
327 GlobalIndex count = 0;
328 for (std::size_t i = 0; i < isShared.size(); ++i)
329 if (isShared[i] && isOwned_[i] == 1)
332 std::vector<GlobalIndex> counts(gridView_.comm().size());
333 gridView_.comm().allgather(&count, 1, counts.data());
336 const int rank = gridView_.comm().rank();
337 auto start = std::accumulate(counts.begin(), counts.begin() + rank, GlobalIndex(0));
340 std::vector<GlobalIndex> globalIndices(mapper_.size(), std::numeric_limits<GlobalIndex>::max());
341 for (std::size_t i = 0; i < globalIndices.size(); ++i)
343 if (isOwned_[i] == 1 && isShared[i])
345 globalIndices[i] = start;
351 GlobalIndexGatherScatter<GlobalIndex> gigs(globalIndices, mapper_);
352 gridView_.communicate(gigs, Dune::All_All_Interface, Dune::ForwardCommunication);
355 resizeAndFillIndexSet_(comm, globalIndices);
358 std::set<int> neighbours;
359 NeighbourGatherScatter ngs(mapper_, gridView_.comm().rank(), neighbours);
360 gridView_.communicate(ngs, Dune::All_All_Interface, Dune::ForwardCommunication);
361 comm.remoteIndices().setNeighbours(neighbours);
363 comm.remoteIndices().template rebuild<false>();
366 DUNE_THROW(Dune::InvalidStateException,
367 "Cannot build parallel index set for a grid that cannot communicate codim-" << dofCodim <<
"-entities."
377 {
return gridView_; }
388 void initGhostsAndOwners_()
390 const auto rank = gridView_.comm().rank();
391 isOwned_.assign(mapper_.size(), rank);
394 GhostGatherScatter ggs(isOwned_, mapper_);
396 if (gridView_.comm().size() > 1)
397 gridView_.communicate(ggs, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
405 InteriorBorderGatherScatter dh(isOwned_, mapper_);
407 if (gridView_.comm().size() > 1)
408 gridView_.communicate(dh, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication);
411 for (
auto& v : isOwned_)
412 v = (v == rank) ? 1 : 0;
415 template<
class Comm,
class GlobalIndices>
416 void resizeAndFillIndexSet_(Comm& comm,
const GlobalIndices& globalIndices)
const
418 comm.indexSet().beginResize();
422 for (std::size_t localIndex = 0; localIndex < globalIndices.size(); ++localIndex)
424 const auto globalIndex = globalIndices[localIndex];
425 if (globalIndex != std::numeric_limits<typename GlobalIndices::value_type>::max())
427 const bool isOwned = isOwned_[localIndex] > 0;
428 const auto attr = getAttribute_(comm, isOwned, isGhost(localIndex));
429 using LocalIndex =
typename Comm::ParallelIndexSet::LocalIndex;
430 comm.indexSet().add(globalIndex, LocalIndex{localIndex, attr});
434 comm.indexSet().endResize();
438 Dune::OwnerOverlapCopyAttributeSet::AttributeSet
439 getAttribute_(
const Comm& comm,
const bool isOwned,
const bool isGhost)
const
442 return Dune::OwnerOverlapCopyAttributeSet::owner;
443 else if (isGhost && (comm.category() == Dune::SolverCategory::nonoverlapping) )
444 return Dune::OwnerOverlapCopyAttributeSet::overlap;
446 return Dune::OwnerOverlapCopyAttributeSet::copy;
449 const GridView gridView_;
450 const DofMapper& mapper_;
452 std::vector<std::size_t> isOwned_;
454 std::vector<std::size_t> isGhost_;
467template<
class LinearSolverTraits>
474template<
class Gr
idView,
class DofMapper,
int dofCodim>
479 : gridView_(gridView), mapper_(mapper)
483 template<
class Block,
class Alloc>
486 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Traits::Grid, dofCodim>::v)
489 if (gridView_.comm().size() > 1)
490 gridView_.communicate(gs, Dune::InteriorBorder_InteriorBorder_Interface,
491 Dune::ForwardCommunication);
494 DUNE_THROW(Dune::InvalidStateException,
"Cannot call makeNonOverlappingConsistent for a grid that cannot communicate codim-" << dofCodim <<
"-entities.");
498 template<
class Block,
class Alloc>
501 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Traits::Grid, dofCodim>::v)
505 for (
const auto& element : elements(gridView_))
506 if (element.partitionType() == Dune::OverlapEntity)
507 v[gridView_.indexSet().index(element)] = 0;
509 if (gridView_.comm().size() > 1)
512 gridView_.communicate(gs, Dune::Overlap_All_Interface,
513 Dune::ForwardCommunication);
517 DUNE_THROW(Dune::InvalidStateException,
"Cannot call makeNonOverlappingConsistent for a grid that cannot communicate codim-" << dofCodim <<
"-entities.");
521 template<
class... Blocks>
524 DUNE_THROW(Dune::NotImplemented,
"makeNonOverlappingConsistent for Dune::MultiTypeBlockVector");
528 const GridView gridView_;
529 const DofMapper& mapper_;
540template<
class Matrix,
class GridView,
541 class RowDofMapper,
int rowDofCodim>
544 using IdType =
typename GridView::Traits::Grid::Traits::GlobalIdSet::IdType;
567 template<
class ColIsGhostFunc>
568 struct MatrixPatternExchange
569 :
public Dune::CommDataHandleIF<MatrixPatternExchange<ColIsGhostFunc>, IdType>
572 using DataType = IdType;
584 MatrixPatternExchange(
const RowDofMapper& rowEntityMapper,
585 const std::map<IdType,int>& globalToLocal,
586 const std::map<int,IdType>& localToGlobal,
588 std::vector<std::set<int>>& sparsityPattern,
589 const ColIsGhostFunc& isGhostColumDof)
590 : rowEntityMapper_(rowEntityMapper), idToIndex_(globalToLocal), indexToID_(localToGlobal)
591 , sparsityPattern_(sparsityPattern), A_(A), isGhostColumDof_(isGhostColumDof)
593 sparsityPattern_.resize(A.N());
599 bool contains (
int dim,
int codim)
const
600 {
return (codim == rowDofCodim); }
603 bool fixedSize(
int dim,
int codim)
const
609 template<
class EntityType>
610 std::size_t size(EntityType& e)
const
612 const auto rowIdx = rowEntityMapper_.index(e);
616 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
617 if (indexToID_.count(colIt.index()))
626 template<
class MessageBuffer,
class EntityType>
627 void gather(MessageBuffer& buff,
const EntityType& e)
const
629 const auto rowIdx = rowEntityMapper_.index(e);
632 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
633 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
634 buff.write(it->second);
640 template<
class MessageBuffer,
class EntityType>
641 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
643 const auto rowIdx = rowEntityMapper_.index(e);
644 for (std::size_t k = 0; k < n; k++)
651 if (
const auto it = idToIndex_.find(
id); it != idToIndex_.end())
653 const auto colIdx = it->second;
656 if (!isGhostColumDof_(colIdx))
658 sparsityPattern_[rowIdx].insert(colIdx);
664 const RowDofMapper& rowEntityMapper_;
665 const std::map<IdType, int>& idToIndex_;
666 const std::map<int, IdType>& indexToID_;
667 std::vector<std::set<int>>& sparsityPattern_;
669 const ColIsGhostFunc& isGhostColumDof_;
677 typename Matrix::block_type second;
681 struct MatrixEntryExchange
682 :
public Dune::CommDataHandleIF<MatrixEntryExchange, MatrixEntry>
685 using DataType = MatrixEntry;
687 MatrixEntryExchange(
const RowDofMapper& rowEntityMapper,
688 const std::map<IdType, int>& globalToLocal,
689 const std::map<int, IdType>& localToGlobal,
691 : rowEntityMapper_(rowEntityMapper), idToIndex_(globalToLocal), indexToID_(localToGlobal), A_(A)
697 bool contains(
int dim,
int codim)
const
698 {
return (codim == rowDofCodim); }
701 bool fixedSize(
int dim,
int codim)
const
707 template<
class EntityType>
708 std::size_t size(EntityType& e)
const
710 const auto rowIdx = rowEntityMapper_.index(e);
712 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
713 if (indexToID_.count(colIt.index()))
722 template<
class MessageBuffer,
class EntityType>
723 void gather(MessageBuffer& buff,
const EntityType& e)
const
725 const auto rowIdx = rowEntityMapper_.index(e);
727 for (
auto colIt = A_[rowIdx].begin(); colIt != A_[rowIdx].end(); ++colIt)
728 if (
auto it = indexToID_.find(colIt.index()); it != indexToID_.end())
729 buff.write(MatrixEntry{ it->second, *colIt });
735 template<
class MessageBuffer,
class EntityType>
736 void scatter(MessageBuffer& buff,
const EntityType& e, std::size_t n)
738 const auto rowIdx = rowEntityMapper_.index(e);
739 for (std::size_t k = 0; k < n; k++)
743 const auto& [colDofID, matrixBlock] = m;
746 if (
auto it = idToIndex_.find(colDofID); it != idToIndex_.end())
747 if (A_[rowIdx].find(it->second) != A_[rowIdx].end())
748 A_[rowIdx][it->second] += matrixBlock;
753 const RowDofMapper& rowEntityMapper_;
754 const std::map<IdType, int>& idToIndex_;
755 const std::map<int, IdType>& indexToID_;
763 : gridView_(gridView), mapper_(mapper)
768 std::vector<bool> handledDof(gridView_.size(rowDofCodim),
false);
769 for (
const auto& element : elements(gridView_))
771 for (
int i = 0; i < element.subEntities(rowDofCodim); ++i)
773 const auto entity = element.template subEntity<rowDofCodim>(i);
774 if (entity.partitionType() == Dune::BorderEntity)
776 const auto localRowIdx = mapper_.index(entity);
777 if (!handledDof[localRowIdx])
779 IdType dofIdxGlobal = gridView_.grid().globalIdSet().id(entity);
780 idToIndex_.emplace(dofIdxGlobal, localRowIdx);
781 indexToID_.emplace(localRowIdx, dofIdxGlobal);
793 template<
class IsGhostFunc>
796 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
798 if (gridView_.comm().size() <= 1)
802 Matrix matrixAsAssembled(A);
805 std::size_t numNonZeroEntries = 0;
806 std::vector<std::set<int>> sparsityPattern;
807 MatrixPatternExchange<IsGhostFunc> dataHandle(mapper_, idToIndex_, indexToID_, A, sparsityPattern, isGhost);
808 gridView_.communicate(
809 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
813 for (
auto rowIt = A.begin(); rowIt != A.end(); ++rowIt)
815 const auto colEndIt = A[rowIt.index()].end();
816 for (
auto colIt = rowIt->begin(); colIt != colEndIt; ++colIt)
817 if (!sparsityPattern[rowIt.index()].count(colIt.index()))
818 sparsityPattern[rowIt.index()].insert(colIt.index());
820 numNonZeroEntries += sparsityPattern[rowIt.index()].size();
824 A.setSize(matrixAsAssembled.N(), matrixAsAssembled.M(), numNonZeroEntries);
825 A.setBuildMode(Matrix::row_wise);
826 auto citer = A.createbegin();
827 for (
auto i = sparsityPattern.begin(), end = sparsityPattern.end(); i!=end; ++i, ++citer)
828 for (
auto si = i->begin(), send = i->end(); si!=send; ++si)
833 const auto rowEndIt = matrixAsAssembled.end();
834 for (
auto rowIt = matrixAsAssembled.begin(); rowIt != rowEndIt; ++rowIt)
835 for (
auto colIt = matrixAsAssembled[rowIt.index()].begin(); colIt != matrixAsAssembled[rowIt.index()].end(); ++colIt)
836 A[rowIt.index()][colIt.index()] = *colIt;
842 DUNE_THROW(Dune::InvalidStateException,
"Cannot call extendMatrix for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities.");
860 if constexpr (Dune::Capabilities::canCommunicate<typename GridView::Grid, rowDofCodim>::v)
862 if (gridView_.comm().size() <= 1)
865 MatrixEntryExchange dataHandle(mapper_, idToIndex_, indexToID_, A);
866 gridView_.communicate(
867 dataHandle, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication
871 DUNE_THROW(Dune::InvalidStateException,
872 "Cannot call sumEntries for a grid that cannot communicate codim-" << rowDofCodim <<
"-entities."
877 const GridView gridView_;
878 const RowDofMapper& mapper_;
879 std::map<IdType, int> idToIndex_;
880 std::map<int, IdType> indexToID_;
888 class Matrix,
class ParallelHelper>
891 if constexpr (ParallelTraits::isNonOverlapping)
895 using GridView =
typename LinearSolverTraits::GridView;
896 using DofMapper =
typename LinearSolverTraits::DofMapper;
897 static constexpr int dofCodim = LinearSolverTraits::dofCodim;
899 matrixHelper.
extendMatrix(A, [&pHelper](
auto idx){
return pHelper.isGhost(idx); });
908 class Vector,
class ParallelHelper>
911 if constexpr (ParallelTraits::isNonOverlapping)
915 using GridView =
typename LinearSolverTraits::GridView;
916 using DofMapper =
typename LinearSolverTraits::DofMapper;
917 static constexpr int dofCodim = LinearSolverTraits::dofCodim;
927 class Matrix,
class Vector,
class ParallelHelper>
930 prepareMatrixParallel<LinearSolverTraits, ParallelTraits>(A, pHelper);
931 prepareVectorParallel<LinearSolverTraits, ParallelTraits>(b, pHelper);
938 class Matrix,
class Vector,
class ParallelHelper>
940 std::shared_ptr<typename ParallelTraits::Comm>& comm,
941 std::shared_ptr<typename ParallelTraits::LinearOperator>& fop,
942 std::shared_ptr<typename ParallelTraits::ScalarProduct>& sp,
943 ParallelHelper& pHelper)
945 prepareLinearAlgebraParallel<LinearSolverTraits, ParallelTraits>(A, b, pHelper);
946 const auto category = ParallelTraits::isNonOverlapping ?
947 Dune::SolverCategory::nonoverlapping : Dune::SolverCategory::overlapping;
949 comm = std::make_shared<typename ParallelTraits::Comm>(pHelper.gridView().comm(), category);
950 pHelper.createParallelIndexSet(*comm);
951 fop = std::make_shared<typename ParallelTraits::LinearOperator>(A, *comm);
952 sp = std::make_shared<typename ParallelTraits::ScalarProduct>(*comm);
const DofMapper & dofMapper() const
Return the dofMapper.
Definition: parallelhelpers.hh:372
ParallelISTLHelperImpl(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:281
bool isOwned(std::size_t i) const
Definition: parallelhelpers.hh:295
const GridView & gridView() const
Return the gridView.
Definition: parallelhelpers.hh:376
bool isGhost(std::size_t i) const
Definition: parallelhelpers.hh:292
void createParallelIndexSet(Comm &comm) const
Creates a parallel index set for a communicator.
Definition: parallelhelpers.hh:310
Definition: parallelhelpers.hh:29
Helper class for adding up matrix entries for border entities.
Definition: parallelhelpers.hh:543
ParallelMatrixHelper(const GridView &gridView, const RowDofMapper &mapper)
Definition: parallelhelpers.hh:762
void sumEntries(Matrix &A)
Sums up the entries corresponding to border entities (usually vertices or faces)
Definition: parallelhelpers.hh:858
void extendMatrix(Matrix &A, const IsGhostFunc &isGhost)
communicates values for the sparsity pattern of the new matrix.
Definition: parallelhelpers.hh:794
Definition: parallelhelpers.hh:476
void makeNonOverlappingConsistent(Dune::MultiTypeBlockVector< Blocks... > &v) const
Make a vector consistent for non-overlapping domain decomposition methods.
Definition: parallelhelpers.hh:522
ParallelVectorHelper(const GridView &gridView, const DofMapper &mapper)
Definition: parallelhelpers.hh:478
void makeOverlappingConsistent(Dune::BlockVector< Block, Alloc > &v) const
Make a vector consistent for overlapping domain decomposition methods.
Definition: parallelhelpers.hh:499
void makeNonOverlappingConsistent(Dune::BlockVector< Block, Alloc > &v) const
Make a vector consistent for non-overlapping domain decomposition methods.
Definition: parallelhelpers.hh:484
A data handle class to exchange entries of a vector.
Definition: vectorcommdatahandle.hh:66
Definition: variablesbackend.hh:34
dune-grid capabilities compatibility layer
Definition: cvfelocalresidual.hh:28
void prepareMatrixParallel(Matrix &A, ParallelHelper &pHelper)
Prepare a matrix for parallel solvers.
Definition: parallelhelpers.hh:889
void prepareLinearAlgebraParallel(Matrix &A, Vector &b, ParallelHelper &pHelper)
Prepare linear algebra variables for parallel solvers.
Definition: parallelhelpers.hh:928
LinearSolverTraitsImpl< GridGeometry, typename GridGeometry::DiscretizationMethod > LinearSolverTraits
The type traits required for using the IstlFactoryBackend.
Definition: linearsolvertraits.hh:37
void prepareVectorParallel(Vector &b, ParallelHelper &pHelper)
Prepare a vector for parallel solvers.
Definition: parallelhelpers.hh:909
The implementation is specialized for the different discretizations.
Definition: linearsolvertraits.hh:31
Contains a class to exchange entries of a vector.