AMDiS 2.10
The Adaptive Multi-Dimensional Simulation Toolbox
ParallelIndexSet.hpp
1#pragma once
2
3#include <cassert>
4#include <vector>
5
6#include <dune/common/timer.hh>
7
8#include <amdis/Output.hpp>
9#include <amdis/linearalgebra/AttributeSet.hpp>
10
11#if HAVE_MPI
12#include <dune/grid/common/gridenums.hh>
13#include <dune/grid/common/partitionset.hh>
14
15#include <amdis/Environment.hpp>
16#include <amdis/functions/GlobalIdSet.hpp>
17#include <amdis/utility/UniqueBorderPartition.hpp>
18#endif
19
20namespace AMDiS
21{
23 template <class Basis, class PIS>
24 inline void buildParallelIndexSet(Basis const& basis, PIS& parallelIndexSet)
25 {
26 Dune::Timer t;
27 using Attribute = typename AttributeSet<PIS>::type;
28 using GI = typename PIS::GlobalIndex;
29 using LI = typename PIS::LocalIndex;
30
31 auto const& gv = basis.gridView();
32
33#if HAVE_MPI
34 if (gv.comm().size() > 1) // parallel indexset
35 {
36 auto lv = basis.localView();
37
38 // make disjoint partition of border entities
39 using GridView = typename Basis::GridView;
40 using Grid = typename GridView::Grid;
41 using DataHandle = UniqueBorderPartition<Grid>;
42 DataHandle borderEntities(gv.comm().rank(), gv.grid());
43 for (int i = 0; i < borderEntities.numIterations(); ++i) {
44 gv.communicate(borderEntities,
45 Dune::InterfaceType::InteriorBorder_All_Interface,
46 Dune::CommunicationDirection::ForwardCommunication);
47 }
48
49 std::vector<bool> visited(basis.dimension(), false);
50 GlobalBasisIdSet<Basis> dofIdSet(basis);
51 parallelIndexSet.beginResize();
52 for (auto const& e : elements(gv))
53 {
54 lv.bind(e);
55 dofIdSet.bind(e);
56 for (std::size_t i = 0; i < dofIdSet.size(); ++i)
57 {
58 auto localIndex = lv.index(i);
59 if (!visited[localIndex]) {
60 auto globalId = dofIdSet.id(i);
61 using PType = Dune::PartitionType;
62 PType pt = dofIdSet.partitionType(i);
63 switch (pt)
64 {
65 case PType::InteriorEntity:
66 parallelIndexSet.add(globalId, LI(localIndex, Attribute::owner, true));
67 break;
68 case PType::BorderEntity:
69 if (borderEntities.contains(dofIdSet.entityId(i)))
70 parallelIndexSet.add(globalId, LI(localIndex, Attribute::owner, true));
71 else
72 parallelIndexSet.add(globalId, LI(localIndex, Attribute::overlap, true));
73 break;
74 case PType::OverlapEntity:
75 parallelIndexSet.add(globalId, LI(localIndex, Attribute::overlap, true));
76 break;
77 case PType::FrontEntity:
78 case PType::GhostEntity:
79 parallelIndexSet.add(globalId, LI(localIndex, Attribute::copy, true));
80 break;
81 default:
82 error_exit("Unknown partition type.");
83 }
84
85 visited[localIndex] = true;
86 }
87 }
88 dofIdSet.unbind();
89 lv.unbind();
90 }
91 parallelIndexSet.endResize();
92 }
93 else // sequential indexset
94#endif // HAVE_MPI
95 {
96 parallelIndexSet.beginResize();
97 for (std::size_t localIndex = 0; localIndex < basis.dimension(); ++localIndex)
98 {
99 GI globalId{std::size_t(localIndex)};
100 parallelIndexSet.add(globalId, LI(localIndex, Attribute::owner, true));
101 }
102 parallelIndexSet.endResize();
103 }
104 // test that all indices are inserted into the indexset
105 assert(parallelIndexSet.size() == basis.dimension());
106
107 info(2, "build ParallelIndexSet needed {} seconds", t.elapsed());
108 }
109
110} // end namespace AMDiS