AMDiS 2.11-git
The Adaptive Multi-Dimensional Simulation Toolbox
 
Loading...
Searching...
No Matches
GlobalIdSet.hpp
1#pragma once
2
3#include <ostream>
4#include <tuple>
5#include <utility>
6#include <vector>
7
8#include <dune/common/exceptions.hh>
9#include <dune/common/hybridutilities.hh>
10#include <dune/common/version.hh>
11#include <dune/common/typetree/nodeconcepts.hh>
12#include <dune/functions/functionspacebases/nodes.hh>
13#include <dune/functions/functionspacebases/lagrangebasis.hh>
14#include <dune/functions/functionspacebases/lagrangedgbasis.hh>
15#include <dune/grid/common/gridenums.hh>
16#include <dune/localfunctions/common/localkey.hh>
17
18#include <amdis/Output.hpp>
19#include <amdis/common/Apply.hpp>
20#include <amdis/common/ConceptsBase.hpp>
21#include <amdis/common/ForEach.hpp>
22#include <amdis/common/TupleUtility.hpp>
23#include <amdis/typetree/NodeTags.hpp>
24#include <amdis/utility/Twist.hpp>
25
26
27namespace AMDiS
28{
29 // forward declaration
30 template <class PreBasis, class TP,
31 class NodeTag = AMDiS::NodeTag_t<typename PreBasis::Node>>
32 class NodeIdSet;
33
35
39 template <class EntityIdType>
40 class GlobalIdType : public std::pair<EntityIdType, std::size_t>
41 {
42 using Super = std::pair<EntityIdType, std::size_t>;
43
44 public:
45 GlobalIdType(std::size_t i = 0)
46 : Super(EntityIdType{}, i)
47 {}
48
49 using Super::Super;
50
53 {
54 ++this->second;
55 return *this;
56 }
57
58 // Add to the second index only
59 GlobalIdType operator+(std::size_t shift) const
60 {
61 return GlobalIdType{this->first, this->second + shift};
62 }
63
64 friend std::ostream& operator<<(std::ostream& os, GlobalIdType const& id)
65 {
66 os << "(" << id.first << "," << id.second << ")";
67 return os;
68 }
69 };
70
71 template <class Basis>
72 using GlobalIdType_t
73 = GlobalIdType<typename Basis::GridView::Grid::GlobalIdSet::IdType>;
74
75
77
97 template <class GB, class = std::void_t<> >
99 {
100 public:
101 using GlobalBasis = GB;
102 using Tree = typename GB::LocalView::Tree;
103 using size_type = std::size_t;
104
105 using GridView = typename GlobalBasis::GridView;
106 using Grid = typename GridView::Grid;
107 using Element = typename GridView::template Codim<0>::Entity;
108 using EntityIdType = typename Grid::GlobalIdSet::IdType;
109 using PartitionType = Dune::PartitionType;
111
112 using PreBasis = typename GlobalBasis::PreBasis;
113 using TreePath = typename GlobalBasis::PrefixPath;
116
117 public:
118 GlobalBasisIdSet(GlobalBasis const& globalBasis)
119 : tree_(globalBasis.localView().tree())
120 , nodeIdSet_(globalBasis.gridView())
121 , twist_(globalBasis.gridView().grid().globalIdSet())
122 {
123 initializeTree(tree_);
124 }
125
127
132 void bind(Element const& element)
133 {
134 bindTree(tree_, element);
135 nodeIdSet_.bind(tree_);
136 twist_.bind(element);
137 data_.resize(size());
138 nodeIdSet_.fillIn(twist_, data_.begin());
139 }
140
142 void unbind()
143 {
144 nodeIdSet_.unbind();
145 }
146
148 size_type size() const
149 {
150 return tree_.size();
151 }
152
155 IdType id(size_type i) const
156 {
157 assert( i < data_.size() );
158 return data_[i].first;
159 }
160
163 EntityIdType entityId(size_type i) const
164 {
165 return id(i).first;
166 }
167
170 PartitionType partitionType(size_type i) const
171 {
172 assert( i < data_.size() );
173 return data_[i].second;
174 }
175
176 protected:
177 Tree tree_;
178 NodeIdSet nodeIdSet_;
179 Twist twist_;
180 using Data = std::pair<IdType, PartitionType>;
181 std::vector<Data> data_;
182 };
183
184
185 // Specialization for SubspaceBasis
186 template <class Basis>
187 class GlobalBasisIdSet<Basis, std::void_t<typename Basis::RootBasis>>
188 : public GlobalBasisIdSet<typename Basis::RootBasis>
189 {
190 public:
191 GlobalBasisIdSet(Basis const& basis)
193 {}
194 };
195
196
197 template <class PB, class TP, class NodeTag>
199 {
200 public:
201 using PreBasis = PB;
202 using Node = typename PreBasis::Node;
203 using GridView = typename PreBasis::GridView;
204 using size_type = std::size_t;
205
206 static_assert(Dune::TypeTree::Concept::LeafTreeNode<Node>, "Generic NodeIdSet implemented for LeafNodes only. Provide a specialization for your node!");
207
208 private:
209 static constexpr int dim = GridView::template Codim<0>::Entity::mydimension;
210
211 public:
212 NodeIdSet(GridView const& gridView)
213 : gridView_(gridView)
214 , sizes_{}
215 {}
216
218 void bind(const Node& node)
219 {
220 node_ = &node;
221 size_ = node_->finiteElement().size();
222
223 std::fill(std::begin(sizes_), std::end(sizes_), 0u);
224 for (size_type i = 0; i < size_ ; ++i) {
225 Dune::LocalKey const& localKey = node_->finiteElement().localCoefficients().localKey(i);
226 sizes_[localKey.codim()]++;
227 }
228 auto refElem = Dune::referenceElement<double,GridView::dimension>(node_->element().type());
229 for (size_type c = 0; c <= GridView::dimension ; ++c)
230 sizes_[c] /= refElem.size(c);
231 }
232
234 void unbind()
235 {
236 node_ = nullptr;
237 }
238
240 size_type size() const
241 {
242 return size_;
243 }
244
246 template <class Twist, class It>
247 It fillIn(Twist const& twist, It it, size_type shift = 0) const
248 {
249 assert(node_ != nullptr);
250 const auto& gridIdSet = gridView_.grid().globalIdSet();
251
252 for (size_type i = 0; i < size_ ; ++i, ++it) {
253 Dune::LocalKey localKey = node_->finiteElement().localCoefficients().localKey(i);
254 unsigned int s = localKey.subEntity();
255 unsigned int c = localKey.codim();
256 it->first = {gridIdSet.subId(node_->element(), s, c), shift + twist.get(localKey,sizes_[c])};
257
258 it->second = Dune::Hybrid::switchCases(std::make_index_sequence<dim+1>{}, c,
259 [&](auto codim) { return node_->element().template subEntity<codim>(s).partitionType(); },
260 [&]() {
261 error_exit("Invalid codimension c = {}", c);
262 return Dune::PartitionType{};
263 });
264 }
265
266 return it;
267 }
268
269 protected:
270 GridView gridView_;
271 const Node* node_ = nullptr;
272 size_type size_ = 0;
273 std::array<unsigned int,GridView::dimension+1> sizes_;
274 };
275
276
277 // Specialization for DynamicPowerBasis
278 template <class PreBasis, class TP>
279 class NodeIdSet<PreBasis, TP, AMDiS::DynamicPowerNodeTag>
280 {
281 public:
282 using Node = typename PreBasis::Node;
283 using GridView = typename PreBasis::GridView;
284 using size_type = std::size_t;
285
286 protected:
287 using SubPreBasis = typename PreBasis::SubPreBasis;
288 using SubTreePath = decltype(Dune::TypeTree::push_back(std::declval<TP>(), std::size_t(0)));
290
291 public:
292 NodeIdSet(GridView const& gridView)
293 : subIds_(gridView)
294 {}
295
297 void bind(const Node& node)
298 {
299 node_ = &node;
300 subIds_.bind(node.child(0));
301 }
302
304 void unbind()
305 {
306 node_ = nullptr;
307 subIds_.unbind();
308 }
309
311 size_type size() const
312 {
313 return node_->size();
314 }
315
317 template <class Twist, class It>
318 It fillIn(Twist const& twist, It it, size_type shift = 0) const
319 {
320 assert(node_ != nullptr);
321 for (std::size_t child = 0; child < node_->degree(); ++child)
322 {
323 size_type subTreeSize = subIds_.size();
324 it = subIds_.fillIn(twist, it, shift);
325 shift += subTreeSize;
326 }
327 return it;
328 }
329
330 protected:
331 SubNodeIdSet subIds_;
332 const Node* node_ = nullptr;
333 };
334
335
336 // Specialization for PowerBasis
337 template <class PreBasis, class TP>
338 class NodeIdSet<PreBasis, TP, AMDiS::PowerNodeTag>
339 : public NodeIdSet<PreBasis, TP, AMDiS::DynamicPowerNodeTag>
340 {
342 public:
343 using Super::Super;
344 };
345
346
347 // Specialization for CompositePreBasis
348 template <class PreBasis, class TP>
349 class NodeIdSet<PreBasis, TP, AMDiS::CompositeNodeTag>
350 {
351 public:
352 using Node = typename PreBasis::Node;
353 using GridView = typename PreBasis::GridView;
354 using size_type = std::size_t;
355
356 protected:
357 static const std::size_t children = Node::degree();
358 using ChildIndices = std::make_index_sequence<children>;
359
360 // The I'th SubPreBasis
361 template <std::size_t I>
362 using SubPreBasis = typename PreBasis::template SubPreBasis<I>;
363
364 template <std::size_t I>
365 using SubTreePath = decltype(Dune::TypeTree::push_back(std::declval<TP>(), Dune::index_constant<I>{}));
366
367 template <std::size_t I>
368 using SubNodeIdSet = NodeIdSet<SubPreBasis<I>, SubTreePath<I>>;
369
370 // A tuple of NodeIdSets for the SubPreBases
371 using IdsTuple = IndexMapTuple_t<std::make_index_sequence<children>, SubNodeIdSet>;
372
373 public:
374 NodeIdSet(GridView const& gridView)
375 : idsTuple_(Ranges::applyIndices<children>([&](auto... i) {
376 return std::make_tuple(SubNodeIdSet<VALUE(i)>(gridView)...);
377 }))
378 {}
379
381 void bind(const Node& node)
382 {
383 node_ = &node;
384 Ranges::forIndices<0,children>([&](auto i) {
385 std::get<VALUE(i)>(idsTuple_).bind(node.child(i));
386 });
387 }
388
390 void unbind()
391 {
392 node_ = nullptr;
393 Ranges::forEach(idsTuple_, [](auto& ids) {
394 ids.unbind();
395 });
396 }
397
399 size_type size() const
400 {
401 return node_->size();
402 }
403
405 template <class Twist, class It>
406 It fillIn(Twist const& twist, It it, size_type shift = 0) const
407 {
408 assert(node_ != nullptr);
409 Ranges::forEach(idsTuple_, [&](auto const& ids)
410 {
411 size_type subTreeSize = ids.size();
412 it = ids.fillIn(twist, it, shift);
413 shift += subTreeSize;
414 });
415 return it;
416 }
417
418 private:
419 IdsTuple idsTuple_;
420 const Node* node_ = nullptr;
421 };
422
423
424 template <class GV, int k, class TP>
425 class NodeIdSet<Dune::Functions::LagrangeDGPreBasis<GV, k>, TP>
426 {
427 public:
428 using PreBasis = Dune::Functions::LagrangeDGPreBasis<GV, k>;
429 using Node = typename PreBasis::Node;
430 using GridView = typename PreBasis::GridView;
431 using size_type = std::size_t;
432
433 NodeIdSet(GridView const& gridView)
434 : gridView_(gridView)
435 {}
436
438 void bind(const Node& node)
439 {
440 node_ = &node;
441 size_ = node_->finiteElement().size();
442 }
443
445 void unbind()
446 {
447 node_ = nullptr;
448 }
449
451 size_type size() const
452 {
453 return size_;
454 }
455
457 template <class Twist, class It>
458 It fillIn(Twist const& /*twist*/, It it, size_type shift = 0) const
459 {
460 assert(node_ != nullptr);
461 const auto& gridIdSet = gridView_.grid().globalIdSet();
462 auto elementId = gridIdSet.id(node_->element());
463
464 for (size_type i = 0; i < size_; ++i, ++it)
465 {
466 it->first = {elementId, shift + i};
467 it->second = node_->element().partitionType();
468 }
469
470 return it;
471 }
472
473 protected:
474 GridView gridView_;
475 const Node* node_ = nullptr;
476 size_type size_ = 0;
477 };
478
479
480} // end namespace AMDiS
Provide global ids for all DOFs in a global basis.
Definition GlobalIdSet.hpp:99
EntityIdType entityId(size_type i) const
Return the global unique ID of the entity associated to the ith DOF on the currently bound element in...
Definition GlobalIdSet.hpp:163
size_type size() const
The number of DOFs on the current element in the basis tree.
Definition GlobalIdSet.hpp:148
PartitionType partitionType(size_type i) const
Return the partition type of the ith DOF on the currently bound element in the basis tree.
Definition GlobalIdSet.hpp:170
void bind(Element const &element)
Bind the IdSet to a grid element.
Definition GlobalIdSet.hpp:132
IdType id(size_type i) const
Return the global unique ID of the ith DOF on the currently bound element in the basis tree.
Definition GlobalIdSet.hpp:155
void unbind()
unbind from the element
Definition GlobalIdSet.hpp:142
PB PreBasis
Pre-basis providing the implementation details.
Definition GlobalBasis.hpp:53
typename PreBasis::GridView GridView
The grid view that the FE space is defined on.
Definition GlobalBasis.hpp:56
Type of a global IDs used to represent DOFs uniquely.
Definition GlobalIdSet.hpp:41
GlobalIdType & operator++()
Increment the second index only.
Definition GlobalIdSet.hpp:52
size_type size() const
Number of DOFs in this node.
Definition GlobalIdSet.hpp:399
void bind(const Node &node)
Bind the idset to a tree node.
Definition GlobalIdSet.hpp:381
It fillIn(Twist const &twist, It it, size_type shift=0) const
Maps from subtree index set [0..size-1] to a globally unique id in global basis.
Definition GlobalIdSet.hpp:406
void unbind()
Unbind the idset.
Definition GlobalIdSet.hpp:390
size_type size() const
Number of DOFs in this node.
Definition GlobalIdSet.hpp:311
void bind(const Node &node)
Bind the idset to a tree node.
Definition GlobalIdSet.hpp:297
It fillIn(Twist const &twist, It it, size_type shift=0) const
Maps from subtree index set [0..size-1] to a globally unique id in global basis.
Definition GlobalIdSet.hpp:318
void unbind()
Unbind the idset.
Definition GlobalIdSet.hpp:304
size_type size() const
Number of DOFs in this node.
Definition GlobalIdSet.hpp:240
void bind(const Node &node)
Bind the idset to a tree node.
Definition GlobalIdSet.hpp:218
It fillIn(Twist const &twist, It it, size_type shift=0) const
Maps from subtree index set [0..size-1] to a globally unique id in global basis.
Definition GlobalIdSet.hpp:247
void unbind()
Unbind the idset.
Definition GlobalIdSet.hpp:234
void bind(Element const &element)
Bind the twist to a codim-0 element. Calculates the global ids of all the element vertices.
Definition Twist.hpp:29
unsigned int get(Dune::LocalKey const &localKey, unsigned int size) const
Get the permutated local dof index, living on a subEntity of the bound element.
Definition Twist.hpp:48
Definition NodeTags.hpp:12
Definition NodeTags.hpp:10
Definition NodeTags.hpp:11