3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
amgparallelhelpers.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
25#ifndef DUMUX_AMGPARALLELHELPERS_HH
26#define DUMUX_AMGPARALLELHELPERS_HH
27
28#include <dune/common/version.hh>
29#include <dune/geometry/dimension.hh>
30#include <dune/grid/common/datahandleif.hh>
31#include <dune/grid/common/partitionset.hh>
32#include <dune/istl/owneroverlapcopy.hh>
33#include <dune/istl/paamg/pinfo.hh>
34
35namespace Dumux {
36
42// operator that resets result to zero at constrained DOFS
43template<class GridView, class AmgTraits>
45{
46 using DofMapper = typename AmgTraits::DofMapper;
47 enum { dofCodim = AmgTraits::dofCodim };
48
49 class BaseGatherScatter
50 {
51 public:
52 BaseGatherScatter(const DofMapper& mapper)
53 : mapper_(mapper) {}
54
55 template<class EntityType>
56 int index(const EntityType& e) const
57 { return mapper_.index(e); }
58
59 private:
60 const DofMapper& mapper_;
61 };
62
66 template<class V>
67 class ConsistencyBoxGatherScatter
68 : public BaseGatherScatter,
69 public Dune::CommDataHandleIF<ConsistencyBoxGatherScatter<V>,typename V::block_type>
70 {
71 public:
72 using DataType = typename V::block_type;
73
74 ConsistencyBoxGatherScatter(V& container, const DofMapper& mapper)
75 : BaseGatherScatter(mapper), container_(container)
76 {}
77
78 bool contains(int dim, int codim) const
79 {
80 return dofCodim==codim;
81 }
82
83 bool fixedsize(int dim, int codim) const
84 {
85 return true;
86 }
87
88 template<class EntityType>
89 size_t size (EntityType& e) const
90 {
91 return 1;
92 }
93
94 template<class MessageBuffer, class EntityType>
95 void gather (MessageBuffer& buff, const EntityType& e) const
96 {
97 buff.write(container_[this->index(e)]);
98 }
99
100 template<class MessageBuffer, class EntityType>
101 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
102 {
103 typename V::block_type block;
104 buff.read(block);
105 container_[this->index(e)]+=block;
106 }
107 private:
108 V& container_;
109 };
110
111
118 class GhostGatherScatter
119 : public BaseGatherScatter,
120 public Dune::CommDataHandleIF<GhostGatherScatter,std::size_t>
121 {
122 public:
123 using DataType = std::size_t;
124
125 GhostGatherScatter(std::vector<std::size_t>& ranks, const DofMapper& mapper)
126 : BaseGatherScatter(mapper), ranks_(ranks)
127 {}
128
129
130 bool contains(int dim, int codim) const
131 {
132 return dofCodim==codim;
133 }
134
135 bool fixedsize(int dim, int codim) const
136 {
137 return true;
138 }
139
140 template<class EntityType>
141 size_t size (EntityType& e) const
142 {
143 return 1;
144 }
145
146 template<class MessageBuffer, class EntityType>
147 void gather (MessageBuffer& buff, const EntityType& e) const
148 {
149 std::size_t& data= ranks_[this->index(e)];
150 if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity)
151 data = (1<<24);
152 buff.write(data);
153 }
154
155 template<class MessageBuffer, class EntityType>
156 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
157 {
158 std::size_t x;
159 std::size_t& data = ranks_[this->index(e)];
160 buff.read(x);
161 if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity)
162 data= (1<<24);
163 }
164 private:
165 std::vector<std::size_t>& ranks_;
166 };
167
174 class InteriorBorderGatherScatter
175 : public BaseGatherScatter,
176 public Dune::CommDataHandleIF<InteriorBorderGatherScatter,std::size_t>
177 {
178 public:
179 using DataType = std::size_t;
180
181 InteriorBorderGatherScatter(std::vector<std::size_t>& ranks, const DofMapper& mapper)
182 : BaseGatherScatter(mapper), ranks_(ranks)
183 {}
184
185
186 bool contains(int dim, int codim) const
187 {
188 return dofCodim==codim;
189 }
190
191 bool fixedsize(int dim, int codim) const
192 {
193 return true;
194
195 }
196
197 template<class EntityType>
198 size_t size (EntityType& e) const
199 {
200 return 1;
201 }
202
203 template<class MessageBuffer, class EntityType>
204 void gather (MessageBuffer& buff, const EntityType& e) const
205 {
206
207 std::size_t& data = ranks_[this->index(e)];
208 if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity)
209 data = (1<<24);
210 buff.write(data);
211 }
212
213 template<class MessageBuffer, class EntityType>
214 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
215 {
216 using std::min;
217 std::size_t x;
218 std::size_t& data = ranks_[this->index(e)];
219 buff.read(x);
220 if (e.partitionType()!=Dune::InteriorEntity && e.partitionType()!=Dune::BorderEntity)
221 data = x;
222 else
223 data = min(data,x);
224 }
225 private:
226 std::vector<std::size_t>& ranks_;
227 };
228
233 struct NeighbourGatherScatter
234 : public BaseGatherScatter,
235 public Dune::CommDataHandleIF<NeighbourGatherScatter,int>
236 {
237 using DataType = int;
238
239 NeighbourGatherScatter(const DofMapper& mapper, int rank_, std::set<int>& neighbours_)
240 : BaseGatherScatter(mapper), myrank(rank_), neighbours(neighbours_)
241 {}
242
243
244 bool contains(int dim, int codim) const
245 {
246 return dofCodim==codim;
247 }
248
249 bool fixedsize(int dim, int codim) const
250 {
251 return true;
252 }
253
254 template<class EntityType>
255 size_t size (EntityType& e) const
256 {
257 return 1;
258 }
259
260 template<class MessageBuffer, class EntityType>
261 void gather (MessageBuffer& buff, const EntityType &e) const
262 {
263 buff.write(myrank);
264 }
265
266 template<class MessageBuffer, class EntityType>
267 void scatter (MessageBuffer& buff, const EntityType &e, size_t n)
268 {
269 int x;
270 buff.read(x);
271 neighbours.insert(x);
272 }
273 int myrank;
274 std::set<int>& neighbours;
275 };
276
277
282 struct SharedGatherScatter
283 : public BaseGatherScatter,
284 public Dune::CommDataHandleIF<SharedGatherScatter,int>
285 {
286 using DataType = int;
287
288 SharedGatherScatter(std::vector<int>& shared, const DofMapper& mapper)
289 : BaseGatherScatter(mapper), shared_(shared)
290 {}
291
292 bool contains(int dim, int codim) const
293 {
294 return dofCodim==codim;
295 }
296
297 bool fixedsize(int dim, int codim) const
298 {
299 return true;
300
301 }
302
303 template<class EntityType>
304 size_t size (EntityType& e) const
305 {
306 return 1;
307 }
308
309 template<class MessageBuffer, class EntityType>
310 void gather (MessageBuffer& buff, EntityType& e) const
311 {
312 int data=true;
313 buff.write(data);
314 }
315
316 template<class MessageBuffer, class EntityType>
317 void scatter (MessageBuffer& buff, const EntityType &e, size_t n)
318 {
319 int x;
320 buff.read(x);
321 int& data= shared_[this->index(e)];
322 data = data || x;
323 }
324 private:
325 std::vector<int>& shared_;
326 };
327
332 template<typename GI>
333 struct GlobalIndexGatherScatter
334 : public BaseGatherScatter,
335 public Dune::CommDataHandleIF<GlobalIndexGatherScatter<GI>, GI>
336 {
337 using DataType = GI;
338 GlobalIndexGatherScatter(std::vector<GI>& gindices, const DofMapper& mapper)
339 : BaseGatherScatter(mapper), gindices_(gindices)
340 {}
341
342 bool contains(int dim, int codim) const
343 {
344 return dofCodim==codim;
345 }
346
347 bool fixedsize(int dim, int codim) const
348 {
349 return true;
350 }
351
352 template<class EntityType>
353 size_t size (EntityType& e) const
354 {
355 return 1;
356 }
357
358 template<class MessageBuffer, class EntityType>
359 void gather (MessageBuffer& buff, const EntityType& e) const
360 {
361 buff.write(gindices_[this->index(e)]);
362 }
363
364 template<class MessageBuffer, class EntityType>
365 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
366 {
367 using std::min;
368 DataType x;
369 buff.read(x);
370 gindices_[this->index(e)] = min(gindices_[this->index(e)], x);
371 }
372 private:
373 std::vector<GI>& gindices_;
374 };
375
376public:
377
378 ParallelISTLHelper (const GridView& gridView, const DofMapper& mapper, int verbose=1)
379 : gridView_(gridView), mapper_(mapper), verbose_(verbose), initialized_(false)
380 {}
381
382 // \brief Initializes the markers for ghosts and owners with the correct size and values.
383 //
385 {
386 owner_.resize(mapper_.size(),
387 gridView_.comm().rank());
388 isGhost_.resize(mapper_.size(),0.0);
389 // find out about ghosts
390 GhostGatherScatter ggs(owner_, mapper_);
391
392 if (gridView_.comm().size()>1)
393 gridView_.communicate(ggs, Dune::InteriorBorder_All_Interface, Dune::ForwardCommunication);
394
395 isGhost_ = owner_;
396
397 // partition interior/border
398 InteriorBorderGatherScatter dh(owner_, mapper_);
399
400 if (gridView_.comm().size()>1)
401 gridView_.communicate(dh, Dune::InteriorBorder_InteriorBorder_Interface, Dune::ForwardCommunication);
402
403 // convert vector into mask vector
404 for (auto& v : owner_)
405 v = (v == gridView_.comm().rank()) ? 1.0 : 0.0;
406
407 initialized_=true;
408 }
409
410 // keep only DOFs assigned to this processor
411 template<typename W>
412 void mask (W& w) const
413 {
414 auto v1=w.begin();
415
416 for(auto v2=owner_.begin(), vend=owner_.end(); v2!=vend; ++v1, ++v2)
417 v1*=v2;
418 }
419
420 // access to mask vector
421 double mask (std::size_t i) const
422 {
423 return owner_[i];
424 }
425
426 // access to ghost vector
427 std::size_t ghost (std::size_t i) const
428 {
429 return isGhost_[i];
430 }
431
432 // \brief Make a vector of the box model consistent.
433 template<typename B, typename A>
434 void makeNonOverlappingConsistent(Dune::BlockVector<B,A>& v)
435 {
436#if HAVE_MPI
437 ConsistencyBoxGatherScatter<Dune::BlockVector<B,A> > gs(v, mapper_);
438 if (gridView_.comm().size() > 1)
439 gridView_.communicate(gs, Dune::InteriorBorder_InteriorBorder_Interface,
440 Dune::ForwardCommunication);
441#endif
442 }
443
444
445#if HAVE_MPI
446
456 template<typename MatrixType, typename Comm>
457 void createIndexSetAndProjectForAMG(MatrixType& m, Comm& c);
458#endif
459
461 const DofMapper& dofMapper() const
462 { return mapper_; }
463
465 const GridView& gridView() const
466 { return gridView_; }
467
468private:
469 const GridView gridView_;
470 const DofMapper& mapper_;
471 std::vector<std::size_t> owner_;
472 std::vector<std::size_t> isGhost_;
473 int verbose_;
474 bool initialized_;
475
476}; // class ParallelISTLHelper
477
484template<class GridView, class AmgTraits>
486{
487 using Matrix = typename AmgTraits::MType;
488 enum { dim = GridView::dimension };
489 enum { dofCodim = AmgTraits::dofCodim };
490 using Grid = typename GridView::Traits::Grid;
491 using BlockType = typename Matrix::block_type;
492 using IDS = typename Grid::Traits::GlobalIdSet;
493 using IdType = typename IDS::IdType;
494 using RowIterator = typename Matrix::RowIterator;
495 using ColIterator = typename Matrix::ColIterator;
496 using DofMapper = typename AmgTraits::DofMapper;
497
498public:
503 EntityExchanger(const GridView& gridView, const DofMapper& mapper)
504 : gridView_(gridView), mapper_(mapper)
505 {
506 gid2Index_.clear();
507 index2GID_.clear();
508
509 for (const auto& entity : entities(gridView_, Dune::Codim<dofCodim>()))
510 {
511 if (entity.partitionType() == Dune::BorderEntity)
512 {
513 int localIdx = mapper_.index(entity);
514 IdType dofIdxGlobal = gridView_.grid().globalIdSet().id(entity);
515
516 std::pair<IdType, int> g2iPair(dofIdxGlobal, localIdx);
517 gid2Index_.insert(g2iPair);
518
519 std::pair<int, IdType> i2gPair(localIdx, dofIdxGlobal);
520 index2GID_.insert(i2gPair);
521 }
522 }
523 }
524
547 : public Dune::CommDataHandleIF<MatPatternExchange, IdType>
548 {
549 using RowIterator = typename Matrix::RowIterator;
550 using ColIterator = typename Matrix::ColIterator;
551 public:
553 using DataType = IdType;
554
562 MatPatternExchange (const DofMapper& mapper,
563 const std::map<IdType,int>& g2i,
564 const std::map<int,IdType>& i2g, Matrix& A,
566 : mapper_(mapper), gid2Index_(g2i), index2GID_(i2g),
567 sparsity_(A.N()), A_(A), helper_(helper)
568 {}
569
573 bool contains (int dim, int codim) const
574 {
575 return (codim==dofCodim);
576 }
577
581 bool fixedsize (int dim, int codim) const
582 {
583 return false;
584 }
585
589 template<class EntityType>
590 size_t size (EntityType& e) const
591 {
592 int i = mapper_.index(e);
593 int n = 0;
594 for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j)
595 {
596 typename std::map<int,IdType>::const_iterator it = index2GID_.find(j.index());
597 if (it != index2GID_.end())
598 n++;
599 }
600
601 return n;
602 }
603
607 template<class MessageBuffer, class EntityType>
608 void gather (MessageBuffer& buff, const EntityType& e) const
609 {
610 int i = mapper_.index(e);
611 for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j)
612 {
613 typename std::map<int,IdType>::const_iterator it=index2GID_.find(j.index());
614 if (it != index2GID_.end())
615 buff.write(it->second);
616 }
617
618 }
619
623 template<class MessageBuffer, class EntityType>
624 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
625 {
626 int i = mapper_.index(e);
627 for (size_t k = 0; k < n; k++)
628 {
629 IdType id;
630 buff.read(id);
631 // only add entries corresponding to border entities
632 typename std::map<IdType,int>::const_iterator it = gid2Index_.find(id);
633 if (it != gid2Index_.end()
634 && sparsity_[i].find(it->second) == sparsity_[i].end()
635 && helper_.ghost(it->second) != 1<<24)
636 sparsity_[i].insert(it->second);
637 }
638 }
639
644 std::vector<std::set<int> >& sparsity ()
645 {
646 return sparsity_;
647 }
648
649 private:
650 const DofMapper& mapper_;
651 const std::map<IdType,int>& gid2Index_;
652 const std::map<int,IdType>& index2GID_;
653 std::vector<std::set<int> > sparsity_;
654 Matrix& A_;
656
657 }; // class MatPatternExchange
658
660 struct MatEntry
661 {
662 IdType first;
663 BlockType second;
664 MatEntry (const IdType& f, const BlockType& s) : first(f), second(s) {}
666 };
667
670 : public Dune::CommDataHandleIF<MatEntryExchange,MatEntry>
671 {
672 using RowIterator = typename Matrix::RowIterator;
673 using ColIterator = typename Matrix::ColIterator;
674 public:
677
685 MatEntryExchange (const DofMapper& mapper, const std::map<IdType,int>& g2i,
686 const std::map<int,IdType>& i2g,
687 Matrix& A)
688 : mapper_(mapper), gid2Index_(g2i), index2GID_(i2g), A_(A)
689 {}
690
694 bool contains (int dim, int codim) const
695 {
696 return (codim==dofCodim);
697 }
698
702 bool fixedsize (int dim, int codim) const
703 {
704 return false;
705 }
706
710 template<class EntityType>
711 size_t size (EntityType& e) const
712 {
713 int i = mapper_.index(e);
714 int n = 0;
715 for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j)
716 {
717 typename std::map<int,IdType>::const_iterator it = index2GID_.find(j.index());
718 if (it != index2GID_.end())
719 n++;
720 }
721
722 return n;
723 }
724
728 template<class MessageBuffer, class EntityType>
729 void gather (MessageBuffer& buff, const EntityType& e) const
730 {
731 int i = mapper_.index(e);
732 for (ColIterator j = A_[i].begin(); j != A_[i].end(); ++j)
733 {
734 typename std::map<int,IdType>::const_iterator it=index2GID_.find(j.index());
735 if (it != index2GID_.end())
736 buff.write(MatEntry(it->second,*j));
737 }
738
739 }
740
744 template<class MessageBuffer, class EntityType>
745 void scatter (MessageBuffer& buff, const EntityType& e, size_t n)
746 {
747 int i = mapper_.index(e);
748 for (size_t k = 0; k < n; k++)
749 {
750 MatEntry m;
751 buff.read(m);
752 // only add entries corresponding to border entities
753 typename std::map<IdType,int>::const_iterator it = gid2Index_.find(m.first);
754 if (it != gid2Index_.end())
755 if (A_[i].find(it->second) != A_[i].end())
756 A_[i][it->second] += m.second;
757 }
758 }
759
760 private:
761 const DofMapper& mapper_;
762 const std::map<IdType,int>& gid2Index_;
763 const std::map<int,IdType>& index2GID_;
764 Matrix& A_;
765
766 }; // class MatEntryExchange
767
774 {
775 if (gridView_.comm().size() > 1)
776 {
777 Matrix tmp(A);
778 std::size_t nnz=0;
779 // get entries from other processes
780 MatPatternExchange datahandle(mapper_, gid2Index_, index2GID_, A, helper);
781 gridView_.communicate(datahandle, Dune::InteriorBorder_InteriorBorder_Interface,
782 Dune::ForwardCommunication);
783 std::vector<std::set<int> >& sparsity = datahandle.sparsity();
784 // add own entries, count number of nonzeros
785 for (RowIterator i = A.begin(); i != A.end(); ++i)
786 {
787 for (ColIterator j = A[i.index()].begin(); j != A[i.index()].end(); ++j)
788 {
789 if (sparsity[i.index()].find(j.index()) == sparsity[i.index()].end())
790 {
791 sparsity[i.index()].insert(j.index());
792 }
793 }
794 nnz += sparsity[i.index()].size();
795 }
796
797 A.setSize(tmp.N(), tmp.N(), nnz);
798 A.setBuildMode(Matrix::row_wise);
799 typename Matrix::CreateIterator citer = A.createbegin();
800 using Iter = typename std::vector<std::set<int> >::const_iterator;
801 for (Iter i = sparsity.begin(), end = sparsity.end(); i!=end; ++i, ++citer)
802 {
803 using SIter = typename std::set<int>::const_iterator;
804 for (SIter si = i->begin(), send = i->end(); si!=send; ++si)
805 citer.insert(*si);
806 }
807
808 // set matrix old values
809 A = 0;
810 for (RowIterator i = tmp.begin(); i != tmp.end(); ++i)
811 for (ColIterator j = tmp[i.index()].begin(); j != tmp[i.index()].end(); ++j)
812 A[i.index()][j.index()] = tmp[i.index()][j.index()];
813 }
814 }
815
820 void sumEntries (Matrix& A)
821 {
822 if (gridView_.comm().size() > 1)
823 {
824 MatEntryExchange datahandle(mapper_, gid2Index_, index2GID_, A);
825 gridView_.communicate(datahandle, Dune::InteriorBorder_InteriorBorder_Interface,
826 Dune::ForwardCommunication);
827 }
828 }
829
830#if HAVE_MPI
835 void getExtendedMatrix (Matrix& A) const;
836#endif
837
838private:
839 const GridView gridView_;
840 const DofMapper& mapper_;
841 std::map<IdType, int> gid2Index_;
842 std::map<int, IdType> index2GID_;
843
844}; // class EntityExchanger
845
846// methods that only exist if MPI is available
847#if HAVE_MPI
848template<class GridView, class AmgTraits>
850{
851 if (gridView_.comm().size() > 1)
852 {
853 Matrix tmp(A);
854 std::size_t nnz = 0;
855 // get entries from other processes
856 MatPatternExchange datahandle(mapper_, gid2Index_, index2GID_, A, *this);
857 gridView_.communicate(datahandle, Dune::InteriorBorder_InteriorBorder_Interface,
858 Dune::ForwardCommunication);
859 std::vector<std::set<int> >& sparsity = datahandle.sparsity();
860
861 // add own entries, count number of nonzeros
862 for (RowIterator i = A.begin(); i != A.end(); ++i)
863 {
864 for (ColIterator j = A[i.index()].begin(); j != A[i.index()].end(); ++j)
865 {
866 if (sparsity[i.index()].find(j.index()) == sparsity[i.index()].end())
867 sparsity[i.index()].insert(j.index());
868 }
869 nnz += sparsity[i.index()].size();
870 }
871
872 A.setSize(tmp.N(), tmp.N(), nnz);
873 A.setBuildMode(Matrix::row_wise);
874 typename Matrix::CreateIterator citer = A.createbegin();
875 using Iter = typename std::vector<std::set<int> >::const_iterator;
876 for (Iter i = sparsity.begin(), end = sparsity.end(); i!=end; ++i, ++citer){
877 using SIter = typename std::set<int>::const_iterator;
878 for (SIter si = i->begin(), send = i->end(); si!=send; ++si)
879 citer.insert(*si);
880 }
881
882 // set matrix old values
883 A = 0;
884 for (RowIterator i = tmp.begin(); i != tmp.end(); ++i)
885 for (ColIterator j = tmp[i.index()].begin(); j != tmp[i.index()].end(); ++j)
886 A[i.index()][j.index()] = tmp[i.index()][j.index()];
887
888 sumEntries(A);
889 }
890
891} // EntityExchanger::getExtendedMatrix
892
893template<class GridView, class AmgTraits>
894template<typename MatrixType, typename Comm>
896{
897 if(!initialized_)
898 {
899 // This is the first time this function is called.
900 // Therefore we need to initialize the marker vectors for ghosts and
901 // owned dofs
902 initGhostsAndOwners();
903 }
904
905 // First find out which dofs we share with other processors
906 std::vector<int> sharedDofs(mapper_.size(), false);
907
908 SharedGatherScatter sgs(sharedDofs, mapper_);
909
910 if (gridView_.comm().size() > 1)
911 gridView_.communicate(sgs, Dune::All_All_Interface,
912 Dune::ForwardCommunication);
913
914 // Count shared dofs that we own
915 using GlobalIndex = typename Comm::ParallelIndexSet::GlobalIndex;
916 GlobalIndex count = 0;
917 auto owned = owner_.begin();
918
919 for (auto v=sharedDofs.begin(), vend=sharedDofs.end(); v != vend; ++v, ++owned)
920 if(*v && *owned==1)
921 ++count;
922
923 Dune::dverb << gridView_.comm().rank() << ": shared count is " << count.touint()
924 << std::endl;
925
926 std::vector<GlobalIndex> counts(gridView_.comm().size());
927 gridView_.comm().allgather(&count, 1, &(counts[0]));
928
929 // Compute start index start_p = \sum_{i=0}^{i<p} counts_i
930 GlobalIndex start = 0;
931 for (int i = 0; i < gridView_.comm().rank(); ++i)
932 start = start + counts[i];
933
934 std::vector<GlobalIndex> scalarIndices(mapper_.size(),
935 std::numeric_limits<GlobalIndex>::max());
936
937 auto shared = sharedDofs.begin();
938 auto index = scalarIndices.begin();
939
940 for (auto i=owner_.begin(), iend=owner_.end(); i!=iend; ++i, ++shared, ++index)
941 {
942 if(*i==1 && *shared)
943 {
944 *index=start;
945 ++start;
946 }
947 }
948
949 // publish global indices for the shared DOFS to other processors.
950 GlobalIndexGatherScatter<GlobalIndex> gigs(scalarIndices, mapper_);
951 if (gridView_.comm().size()>1)
952 gridView_.communicate(gigs, Dune::All_All_Interface,
953 Dune::ForwardCommunication);
954
955
956 // Setup the index set
957 comm.indexSet().beginResize();
958 index = scalarIndices.begin();
959 auto ghost = isGhost_.begin();
960
961 for (auto i=owner_.begin(), iend=owner_.end(); i!=iend; ++i, ++ghost, ++index)
962 {
963 Dune::OwnerOverlapCopyAttributeSet::AttributeSet attr;
964 if (*index!=std::numeric_limits<GlobalIndex>::max())
965 {
966 // global index exist in index set
967 if (*i>0)
968 {
969 // This dof is managed by us.
970 attr = Dune::OwnerOverlapCopyAttributeSet::owner;
971 }
972#if DUNE_VERSION_GTE(DUNE_ISTL, 2, 7)
973 else if ( *ghost==(1<<24) && ( comm.category() ==
974 static_cast<int>(Dune::SolverCategory::nonoverlapping)) )
975#else
976 else if ( *ghost==(1<<24) && ( comm.getSolverCategory() ==
977 static_cast<int>(Dune::SolverCategory::nonoverlapping)) )
978#endif
979 {
980 //use attribute overlap for ghosts in novlp grids
981 attr = Dune::OwnerOverlapCopyAttributeSet::overlap;
982 }
983 else
984 {
985 attr = Dune::OwnerOverlapCopyAttributeSet::copy;
986 }
987 comm.indexSet().add(*index, typename Comm::ParallelIndexSet::LocalIndex(i-owner_.begin(), attr));
988 }
989 }
990 comm.indexSet().endResize();
991
992 // Compute neighbours using communication
993 std::set<int> neighbours;
994 NeighbourGatherScatter ngs(mapper_, gridView_.comm().rank(),
995 neighbours);
996
997 if (gridView_.comm().size() > 1)
998 gridView_.communicate(ngs, Dune::All_All_Interface,
999 Dune::ForwardCommunication);
1000
1001 comm.remoteIndices().setNeighbours(neighbours);
1002 comm.remoteIndices().template rebuild<false>();
1003
1004} // ParallelISTLHelper::createIndexSetAndProjectForAMG
1005
1006#endif // HAVE_MPI
1007
1022template<class GridView, class AmgTraits, bool isParallel>
1024{
1025 using DofMapper = typename AmgTraits::DofMapper;
1027 using Comm = typename AmgTraits::Comm;
1028 using LinearOperator = typename AmgTraits::LinearOperator;
1029 using ScalarProduct = typename AmgTraits::ScalarProduct;
1030
1031 template<class Matrix, class Vector>
1032 static void prepareLinearAlgebra(Matrix& A, Vector& b,
1033 int& rank,
1034 std::shared_ptr<Comm>& comm,
1035 std::shared_ptr<LinearOperator>& fop,
1036 std::shared_ptr<ScalarProduct>& sp,
1037 ParallelHelper& pHelper,
1038 const bool firstCall)
1039 {
1040 comm = std::make_shared<Comm>();
1041 fop = std::make_shared<LinearOperator>(A);
1042 sp = std::make_shared<ScalarProduct>();
1043 }
1044};
1045
1046#if HAVE_MPI
1050template<class GridView, class AmgTraits>
1051struct LinearAlgebraPreparator<GridView, AmgTraits, true>
1052{
1053 using DofMapper = typename AmgTraits::DofMapper;
1055 using Comm = typename AmgTraits::Comm;
1056 using LinearOperator = typename AmgTraits::LinearOperator;
1057 using ScalarProduct = typename AmgTraits::ScalarProduct;
1058
1059 template<class Matrix, class Vector>
1060 static void prepareLinearAlgebra(Matrix& A, Vector& b,
1061 int& rank,
1062 std::shared_ptr<Comm>& comm,
1063 std::shared_ptr<LinearOperator>& fop,
1064 std::shared_ptr<ScalarProduct>& sp,
1065 ParallelHelper& pHelper,
1066 const bool firstCall)
1067 {
1068 Dune::SolverCategory::Category category = AmgTraits::isNonOverlapping ?
1069 Dune::SolverCategory::nonoverlapping : Dune::SolverCategory::overlapping;
1070
1071 if(AmgTraits::isNonOverlapping && firstCall)
1072 {
1073 pHelper.initGhostsAndOwners();
1074 }
1075
1076 comm = std::make_shared<Comm>(pHelper.gridView().comm(), category);
1077
1078 if(AmgTraits::isNonOverlapping)
1079 {
1080 // extend the matrix pattern such that it is usable for AMG
1081 EntityExchanger<GridView, AmgTraits> exchanger(pHelper.gridView(), pHelper.dofMapper());
1082 exchanger.getExtendedMatrix(A, pHelper);
1083 exchanger.sumEntries(A);
1084 }
1085 pHelper.createIndexSetAndProjectForAMG(A, *comm);
1086
1087 fop = std::make_shared<LinearOperator>(A, *comm);
1088 sp = std::make_shared<ScalarProduct>(*comm);
1089 rank = comm->communicator().rank();
1090
1091 // Make rhs consistent
1092 if(AmgTraits::isNonOverlapping)
1093 {
1095 }
1096 }
1097
1098}; // parallel LinearAlgebraPreparator
1099
1100#endif // HAVE_MPI
1101
1102} // end namespace Dumux
1103
1104#endif // DUMUX_AMGPARALLELHELPERS_HH
int start(int argc, char **argv, void(*usage)(const char *, const std::string &))
Provides a main function with error handling.
Definition: start.hh:127
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
A parallel helper class providing a nonoverlapping decomposition of all degrees of freedom.
Definition: amgparallelhelpers.hh:45
const GridView & gridView() const
Return the gridView.
Definition: amgparallelhelpers.hh:465
void createIndexSetAndProjectForAMG(MatrixType &m, Comm &c)
Creates a matrix suitable for parallel AMG and the parallel information.
Definition: amgparallelhelpers.hh:895
const DofMapper & dofMapper() const
Return the dofMapper.
Definition: amgparallelhelpers.hh:461
std::size_t ghost(std::size_t i) const
Definition: amgparallelhelpers.hh:427
ParallelISTLHelper(const GridView &gridView, const DofMapper &mapper, int verbose=1)
Definition: amgparallelhelpers.hh:378
double mask(std::size_t i) const
Definition: amgparallelhelpers.hh:421
void initGhostsAndOwners()
Definition: amgparallelhelpers.hh:384
void makeNonOverlappingConsistent(Dune::BlockVector< B, A > &v)
Definition: amgparallelhelpers.hh:434
void mask(W &w) const
Definition: amgparallelhelpers.hh:412
Helper class for adding up matrix entries on border.
Definition: amgparallelhelpers.hh:486
void sumEntries(Matrix &A)
Sums up the entries corresponding to border vertices.
Definition: amgparallelhelpers.hh:820
void getExtendedMatrix(Matrix &A, const ParallelISTLHelper< GridView, AmgTraits > &helper)
communicates values for the sparsity pattern of the new matrix.
Definition: amgparallelhelpers.hh:773
EntityExchanger(const GridView &gridView, const DofMapper &mapper)
Constructor. Sets up the local to global relations.
Definition: amgparallelhelpers.hh:503
A DataHandle class to exchange matrix sparsity patterns.
Definition: amgparallelhelpers.hh:548
bool contains(int dim, int codim) const
Returns true if data for given valid codim should be communicated.
Definition: amgparallelhelpers.hh:573
MatPatternExchange(const DofMapper &mapper, const std::map< IdType, int > &g2i, const std::map< int, IdType > &i2g, Matrix &A, const ParallelISTLHelper< GridView, AmgTraits > &helper)
Constructor.
Definition: amgparallelhelpers.hh:562
bool fixedsize(int dim, int codim) const
Returns true if size of data per entity of given dim and codim is a constant.
Definition: amgparallelhelpers.hh:581
std::vector< std::set< int > > & sparsity()
Get the communicated sparsity pattern.
Definition: amgparallelhelpers.hh:644
void gather(MessageBuffer &buff, const EntityType &e) const
Pack data from user to message buffer.
Definition: amgparallelhelpers.hh:608
void scatter(MessageBuffer &buff, const EntityType &e, size_t n)
Unpack data from message buffer to user.
Definition: amgparallelhelpers.hh:624
size_t size(EntityType &e) const
How many objects of type DataType have to be sent for a given entity.
Definition: amgparallelhelpers.hh:590
IdType DataType
Export type of data for message buffer.
Definition: amgparallelhelpers.hh:553
Local matrix blocks associated with the global id set.
Definition: amgparallelhelpers.hh:661
MatEntry(const IdType &f, const BlockType &s)
Definition: amgparallelhelpers.hh:664
MatEntry()
Definition: amgparallelhelpers.hh:665
IdType first
Definition: amgparallelhelpers.hh:662
BlockType second
Definition: amgparallelhelpers.hh:663
A DataHandle class to exchange matrix entries.
Definition: amgparallelhelpers.hh:671
void scatter(MessageBuffer &buff, const EntityType &e, size_t n)
Unpack data from message buffer to user.
Definition: amgparallelhelpers.hh:745
bool contains(int dim, int codim) const
Returns true if data for given valid codim should be communicated.
Definition: amgparallelhelpers.hh:694
size_t size(EntityType &e) const
How many objects of type DataType have to be sent for a given entity.
Definition: amgparallelhelpers.hh:711
bool fixedsize(int dim, int codim) const
Returns true if size of data per entity of given dim and codim is a constant.
Definition: amgparallelhelpers.hh:702
MatEntryExchange(const DofMapper &mapper, const std::map< IdType, int > &g2i, const std::map< int, IdType > &i2g, Matrix &A)
Constructor.
Definition: amgparallelhelpers.hh:685
void gather(MessageBuffer &buff, const EntityType &e) const
Pack data from user to message buffer.
Definition: amgparallelhelpers.hh:729
Prepare the linear algebra member variables.
Definition: amgparallelhelpers.hh:1024
static void prepareLinearAlgebra(Matrix &A, Vector &b, int &rank, std::shared_ptr< Comm > &comm, std::shared_ptr< LinearOperator > &fop, std::shared_ptr< ScalarProduct > &sp, ParallelHelper &pHelper, const bool firstCall)
Definition: amgparallelhelpers.hh:1032
typename AmgTraits::Comm Comm
Definition: amgparallelhelpers.hh:1027
typename AmgTraits::DofMapper DofMapper
Definition: amgparallelhelpers.hh:1025
typename AmgTraits::ScalarProduct ScalarProduct
Definition: amgparallelhelpers.hh:1029
typename AmgTraits::LinearOperator LinearOperator
Definition: amgparallelhelpers.hh:1028
static void prepareLinearAlgebra(Matrix &A, Vector &b, int &rank, std::shared_ptr< Comm > &comm, std::shared_ptr< LinearOperator > &fop, std::shared_ptr< ScalarProduct > &sp, ParallelHelper &pHelper, const bool firstCall)
Definition: amgparallelhelpers.hh:1060
typename AmgTraits::DofMapper DofMapper
Definition: amgparallelhelpers.hh:1053
typename AmgTraits::Comm Comm
Definition: amgparallelhelpers.hh:1055
typename AmgTraits::ScalarProduct ScalarProduct
Definition: amgparallelhelpers.hh:1057
typename AmgTraits::LinearOperator LinearOperator
Definition: amgparallelhelpers.hh:1056
The implementation is specialized for the different discretizations.
Definition: amgtraits.hh:71