dune-functions  2.5.0
powerbasis.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_FUNCTIONS_FUNCTIONSPACEBASES_POWERBASIS_HH
4 #define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_POWERBASIS_HH
5 
6 #include <dune/common/reservedvector.hh>
7 #include <dune/common/typeutilities.hh>
8 
9 #include <dune/typetree/powernode.hh>
10 #include <dune/typetree/utility.hh>
11 
16 
17 
18 
19 namespace Dune {
20 namespace Functions {
21 
22 
23 // *****************************************************************************
24 // This is the reusable part of the power bases. It contains
25 //
26 // PowerNodeFactory
27 // PowerNodeIndexSet
28 //
29 // The factory allows to create the others and is the owner of possible shared
30 // state. These components do _not_ depend on the global basis or index
31 // set and can be used without a global basis.
32 // *****************************************************************************
33 
34 template<class MI, class TP, class IMS, class SF, std::size_t C>
36 
37 
38 
50 template<class MI, class IMS, class SF, std::size_t C>
52 {
53  static const std::size_t children = C;
54 
55  template<class, class, class, class, std::size_t>
56  friend class PowerNodeIndexSet;
57 
58 public:
59 
61  using SubFactory = SF;
62 
64  using GridView = typename SF::GridView;
65 
67  using size_type = std::size_t;
68 
70  using IndexMergingStrategy = IMS;
71 
72  template<class TP>
73  using SubNode = typename SubFactory::template Node<decltype(TypeTree::push_back(TP(), 0))>;
74 
75  template<class TP>
76  using SubIndexSet = typename SubFactory::template IndexSet<decltype(TypeTree::push_back(TP(), 0))>;
77 
79  template<class TP>
81 
83  template<class TP>
85 
87  using MultiIndex = MI;
88 
90  using SizePrefix = Dune::ReservedVector<size_type, SubFactory::SizePrefix::max_size()+1>;
91 
92 private:
93 
94  using SubMultiIndex = MI;
95 
96 public:
97 
103  template<class... SFArgs,
104  disableCopyMove<PowerNodeFactory, SFArgs...> = 0,
105  enableIfConstructible<SubFactory, SFArgs...> = 0>
106  PowerNodeFactory(SFArgs&&... sfArgs) :
107  subFactory_(std::forward<SFArgs>(sfArgs)...)
108  {}
109 
112  {
113  subFactory_.initializeIndices();
114  }
115 
117  const GridView& gridView() const
118  {
119  return subFactory_.gridView();
120  }
121 
123  void update(const GridView& gv)
124  {
125  subFactory_.update(gv);
126  }
127 
138  template<class TP>
139  Node<TP> node(const TP& tp) const
140  {
141  auto node = Node<TP>(tp);
142  for (std::size_t i=0; i<children; ++i)
143  node.setChild(i, subFactory_.node(TypeTree::push_back(tp, i)));
144  return node;
145  }
146 
156  template<class TP>
158  {
159  return IndexSet<TP>{*this};
160  }
161 
163  size_type size() const
164  {
165  return size({});
166  }
167 
169  size_type size(const SizePrefix& prefix) const
170  {
171  return size(prefix, IndexMergingStrategy{});
172  }
173 
174 private:
175 
177  {
178  // The root index size is the root index size of a single subnode
179  // multiplied by the number of subnodes because we enumerate all
180  // child indices in a row.
181  if (prefix.size() == 0)
182  return children*subFactory_.size({});
183 
184  // The first prefix entry refers to one of the (root index size)
185  // subindex trees. Hence we have to first compute the corresponding
186  // prefix entry for a single subnode subnode. The we can append
187  // the other prefix entries unmodified, because the index tree
188  // looks the same after the first level.
189  typename SubFactory::SizePrefix subPrefix;
190  subPrefix.push_back(prefix[0] / children);
191  for(std::size_t i=1; i<prefix.size(); ++i)
192  subPrefix.push_back(prefix[i]);
193  return subFactory_.size(subPrefix);
194  }
195 
197  {
198  // The size at the index tree root is the size of at the index tree
199  // root of a single subnode multiplied by the number of subnodes
200  // because we enumerate all child indices in a row.
201  if (prefix.size() == 0)
202  return children*subFactory_.size({});
203 
204  // The first prefix entry refers to one of the (root index size)
205  // subindex trees. Hence we have to first compute the corresponding
206  // prefix entry for a single subnode subnode. The we can append
207  // the other prefix entries unmodified, because the index tree
208  // looks the same after the first level.
209  typename SubFactory::SizePrefix subPrefix;
210  subPrefix.push_back(prefix[0] % children);
211  for(std::size_t i=1; i<prefix.size(); ++i)
212  subPrefix.push_back(prefix[i]);
213  return subFactory_.size(subPrefix);
214  }
215 
217  {
218  if (prefix.size() == 0)
219  return children;
220  typename SubFactory::SizePrefix subPrefix;
221  for(std::size_t i=1; i<prefix.size(); ++i)
222  subPrefix.push_back(prefix[i]);
223  return subFactory_.size(subPrefix);
224  }
225 
227  {
228  if (prefix.size() == 0)
229  return subFactory_.size();
230 
231  typename SubFactory::SizePrefix subPrefix;
232  for(std::size_t i=0; i<prefix.size()-1; ++i)
233  subPrefix.push_back(prefix[i]);
234 
235  size_type r = subFactory_.size(subPrefix);
236  if (r==0)
237  return 0;
238  subPrefix.push_back(prefix.back());
239  r = subFactory_.size(subPrefix);
240  if (r==0)
241  return children;
242  return r;
243  }
244 
245 public:
246 
249  {
250  return subFactory_.dimension() * children;
251  }
252 
255  {
256  return subFactory_.maxNodeSize() * children;
257  }
258 
259 protected:
260  SubFactory subFactory_;
261 };
262 
263 
264 
265 template<class MI, class TP, class IMS, class SF, std::size_t C>
266 class PowerNodeIndexSet
267 {
268  static const std::size_t children = C;
269 
270 public:
271 
272  using SubFactory = SF;
273 
275  using GridView = typename SF::GridView;
276  using size_type = std::size_t;
277  using IndexMergingStrategy = IMS;
278 
280  using MultiIndex = MI;
281 
283 
284  using Node = typename NodeFactory::template Node<TP>;
285 
286  using SubTreePath = typename TypeTree::Child<Node,0>::TreePath;
287 
288  using SubNodeIndexSet = typename NodeFactory::SubFactory::template IndexSet<SubTreePath>;
289 
290  PowerNodeIndexSet(const NodeFactory & nodeFactory) :
291  nodeFactory_(&nodeFactory),
292  subNodeIndexSet_(nodeFactory_->subFactory_.template indexSet<SubTreePath>())
293  {}
294 
295  void bind(const Node& node)
296  {
297  using namespace TypeTree::Indices;
298  node_ = &node;
299  subNodeIndexSet_.bind(node.child(_0));
300  }
301 
302  void unbind()
303  {
304  node_ = nullptr;
305  subNodeIndexSet_.unbind();
306  }
307 
308  size_type size() const
309  {
310  return node_->size();
311  }
312 
313  MultiIndex index(const size_type& localIndex) const
314  {
315  return index(localIndex, IndexMergingStrategy{});
316  }
317 
318 
320  {
321  using namespace Dune::TypeTree::Indices;
322  size_type subTreeSize = node_->child(_0).size();
323  size_type subLocalIndex = localIndex % subTreeSize;
324  size_type component = localIndex / subTreeSize;
325 
326  MultiIndex mi = subNodeIndexSet_.index(subLocalIndex);
327  mi[0] = mi[0]*children+component;
328 
329  return mi;
330  }
331 
333  {
334  using namespace Dune::TypeTree::Indices;
335  size_type subTreeSize = node_->child(_0).size();
336  size_type subLocalIndex = localIndex % subTreeSize;
337  size_type component = localIndex / subTreeSize;
338 
339  size_type firstLevelSize = nodeFactory_->subFactory_.size({});
340 
341  MultiIndex mi = subNodeIndexSet_.index(subLocalIndex);
342  mi[0] += component*firstLevelSize;
343 
344  return mi;
345  }
346 
348  {
349  using namespace Dune::TypeTree::Indices;
350  size_type subTreeSize = node_->child(_0).size();
351  size_type subLocalIndex = localIndex % subTreeSize;
352  size_type component = localIndex / subTreeSize;
353 
354  auto subTreeMi = subNodeIndexSet_.index(subLocalIndex);
355 
356  MultiIndex mi;
357  mi.push_back(component);
358  for(std::size_t i=0; i<subTreeMi.size(); ++i)
359  mi.push_back(subTreeMi[i]);
360  return mi;
361  }
362 
364  {
365  using namespace Dune::TypeTree::Indices;
366  size_type subTreeSize = node_->child(_0).size();
367  size_type subLocalIndex = localIndex % subTreeSize;
368  size_type component = localIndex / subTreeSize;
369 
370  auto subTreeMi = subNodeIndexSet_.index(subLocalIndex);
371 
372  MultiIndex mi;
373  for(std::size_t i=0; i<subTreeMi.size(); ++i)
374  mi.push_back(subTreeMi[i]);
375  mi.push_back(component);
376  return mi;
377  }
378 
379 private:
380  const NodeFactory* nodeFactory_;
381  SubNodeIndexSet subNodeIndexSet_;
382  const Node* node_;
383 };
384 
385 
386 
387 namespace BasisBuilder {
388 
389 namespace Imp {
390 
391 template<std::size_t k, class IndexMergingStrategy, class SubFactoryTag>
393 {
394  static const bool isBlocked = std::is_same<IndexMergingStrategy,BlockedLexicographic>::value or std::is_same<IndexMergingStrategy,LeafBlockedInterleaved>::value;
395 
396  static const std::size_t requiredMultiIndexSize=SubFactoryTag::requiredMultiIndexSize + (std::size_t)(isBlocked);
397 
398  template<class MultiIndex, class GridView>
399  auto build(const GridView& gridView)
400  -> PowerNodeFactory<MultiIndex, IndexMergingStrategy, decltype(SubFactoryTag().template build<MultiIndex, GridView>(std::declval<GridView>())), k>
401  {
402  return {SubFactoryTag().template build<MultiIndex, GridView>(gridView)};
403  }
404 };
405 
406 } // end namespace BasisBuilder::Imp
407 
408 
409 
422 template<std::size_t k, class SubFactoryTag, class IndexMergingStrategy>
424  power(SubFactoryTag&& tag, const IndexMergingStrategy& ims)
425 {
426  return{};
427 }
428 
439 template<std::size_t k, class SubFactoryTag>
441  power(SubFactoryTag&& tag)
442 {
443  return{};
444 }
445 
446 } // end namespace BasisBuilder
447 
448 
449 
450 } // end namespace Functions
451 } // end namespace Dune
452 
453 
454 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_POWERBASIS_HH
A factory for power bases.
Definition: powerbasis.hh:51
Definition: nodes.hh:209
MultiIndex index(const size_type &localIndex) const
Definition: powerbasis.hh:313
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: powerbasis.hh:87
PowerNodeIndexSet(const NodeFactory &nodeFactory)
Definition: powerbasis.hh:290
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: powerbasis.hh:254
size_type size() const
Definition: powerbasis.hh:308
Lexicographic merging of direct children without blocking.
Definition: basistags.hh:61
MultiIndex index(const size_type &localIndex, BasisBuilder::FlatInterleaved) const
Definition: powerbasis.hh:319
SF SubFactory
Definition: powerbasis.hh:272
Imp::PowerNodeFactoryBuilder< k, LeafBlockedInterleaved, SubFactoryTag > power(SubFactoryTag &&tag)
Create a factory builder that can build a PowerNodeFactory.
Definition: powerbasis.hh:441
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: powerbasis.hh:123
Lexicographic merging of direct children with blocking (i.e. creating one block per direct child)...
Definition: basistags.hh:95
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: powerbasis.hh:70
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: powerbasis.hh:248
typename SF::GridView GridView
The grid view that the FE space is defined on.
Definition: powerbasis.hh:275
Definition: powerbasis.hh:35
Definition: polynomial.hh:7
typename std::enable_if< std::is_constructible< T, Args... >::value, int >::type enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:26
MultiIndex index(const size_type &localIndex, BasisBuilder::FlatLexicographic) const
Definition: powerbasis.hh:332
PowerNodeFactory(SFArgs &&... sfArgs)
Constructor for given child factory objects.
Definition: powerbasis.hh:106
IMS IndexMergingStrategy
Definition: powerbasis.hh:277
size_type size() const
Same as size(prefix) with empty prefix.
Definition: powerbasis.hh:163
void unbind()
Definition: powerbasis.hh:302
void initializeIndices()
Initialize the global indices.
Definition: powerbasis.hh:111
SF SubFactory
The child factory.
Definition: powerbasis.hh:61
IndexSet< TP > indexSet() const
Create tree node index set with given root tree path.
Definition: powerbasis.hh:157
STL namespace.
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: powerbasis.hh:280
MultiIndex index(const size_type &localIndex, BasisBuilder::BlockedLexicographic) const
Definition: powerbasis.hh:347
MultiIndex index(const size_type &localIndex, BasisBuilder::LeafBlockedInterleaved) const
Definition: powerbasis.hh:363
typename NodeFactory::SubFactory::template IndexSet< SubTreePath > SubNodeIndexSet
Definition: powerbasis.hh:288
SubFactory subFactory_
Definition: powerbasis.hh:260
void bind(const Node &node)
Definition: powerbasis.hh:295
auto build(const GridView &gridView) -> PowerNodeFactory< MultiIndex, IndexMergingStrategy, decltype(SubFactoryTag().template build< MultiIndex, GridView >(std::declval< GridView >())), k >
Definition: powerbasis.hh:399
typename SubFactory::template IndexSet< decltype(TypeTree::push_back(TP(), 0))> SubIndexSet
Definition: powerbasis.hh:76
std::size_t size_type
Type used for indices and size information.
Definition: powerbasis.hh:67
typename NodeFactory::template Node< TP > Node
Definition: powerbasis.hh:284
typename SF::GridView GridView
The grid view that the FE basis is defined on.
Definition: powerbasis.hh:64
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: powerbasis.hh:117
Interleaved merging of direct children without blocking.
Definition: basistags.hh:78
Dune::ReservedVector< size_type, SubFactory::SizePrefix::max_size()+1 > SizePrefix
Type used for prefixes handed to the size() method.
Definition: powerbasis.hh:90
typename SubFactory::template Node< decltype(TypeTree::push_back(TP(), 0))> SubNode
Definition: powerbasis.hh:73
Node< TP > node(const TP &tp) const
Create tree node with given root tree path.
Definition: powerbasis.hh:139
typename TypeTree::Child< Node, 0 >::TreePath SubTreePath
Definition: powerbasis.hh:286
Interleaved merging of direct children with blocking (i.e. creating blocks at the leaves containing o...
Definition: basistags.hh:112
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: powerbasis.hh:169
std::size_t size_type
Definition: powerbasis.hh:276