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 
20 namespace 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
Definition: AdaptBase.hpp:6