dune-functions  2.5.0
compositebasis.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_COMPOSITEBASIS_HH
4 #define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
5 
6 #include <tuple>
7 #include <utility>
8 
9 #include <dune/common/std/utility.hh>
10 #include <dune/common/hybridutilities.hh>
11 #include <dune/common/reservedvector.hh>
12 #include <dune/common/typeutilities.hh>
13 #include <dune/common/hybridutilities.hh>
14 
15 #include <dune/typetree/compositenode.hh>
16 #include <dune/typetree/utility.hh>
17 
21 
22 
23 
24 namespace Dune {
25 namespace Functions {
26 
27 namespace Imp {
28 
29  template<typename... T>
30  struct SizeOf
31  : public std::integral_constant<std::size_t,sizeof...(T)>
32  {};
33 
34  template<typename... T>
35  using index_sequence_for = std::make_index_sequence<SizeOf<T...>{}>;
36 }
37 
38 // *****************************************************************************
39 // This is the reusable part of the composite bases. It contains
40 //
41 // CompositeNodeFactory
42 // CompositeNodeIndexSet
43 //
44 // The factory allows to create the others and is the owner of possible shared
45 // state. These components do _not_ depend on the global basis or index
46 // set and can be used without a global basis.
47 // *****************************************************************************
48 
49 
50 template<class MI, class TP, class IT, class... SF>
52 
65 template<class MI, class IMS, class... SF>
67 {
68 public:
69 
71  using SubFactories = std::tuple<SF...>;
72 
74  using GridView = typename std::tuple_element<0, SubFactories>::type::GridView;
75 
77  using size_type = std::size_t;
78 
80  using IndexMergingStrategy = IMS;
81 
82 protected:
83  static const std::size_t children = sizeof...(SF);
84 
85  template<class, class, class, class...>
86  friend class CompositeNodeIndexSet;
87 
89 
90  template<class TP>
91  struct FixedTP
92  {
93 
94  template<class I>
95  using IndexToSubTreePath = decltype(TypeTree::push_back(TP(), I()));
96 
98 
99  template<class F, class SubTP>
100  using FactoryToSubNode = typename F::template Node<SubTP>;
101 
103 
104  template<class F, class SubTP>
105  using FactoryToSubIndexSet = typename F::template IndexSet<SubTP>;
106 
108 
109  template<class... N>
111 
113  };
114 
115 
116 public:
117 
119  template<std::size_t k>
120  using SubFactory = typename std::tuple_element<k, std::tuple<SF...>>::type;
121 
123  template<class TP>
124  using Node = typename FixedTP<TP>::Node;
125 
127  template<class TP>
128  using IndexSet = CompositeNodeIndexSet<MI, TP, IMS, SF...>;
129 
131  using MultiIndex = MI;
132 
134  using SizePrefix = Dune::ReservedVector<size_type, MultiIndex::max_size()+1>;
135 
141  template<class... SFArgs,
142  disableCopyMove<CompositeNodeFactory, SFArgs...> = 0,
143  enableIfConstructible<std::tuple<SF...>, SFArgs...> = 0>
144  CompositeNodeFactory(SFArgs&&... sfArgs) :
145  subFactories_(std::forward<SFArgs>(sfArgs)...)
146  {
147  }
148 
151  {
152  using namespace Dune::Hybrid;
153  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
154  elementAt(subFactories_, i).initializeIndices();
155  });
156  }
157 
159  const GridView& gridView() const
160  {
161  return std::get<0>(subFactories_).gridView();
162  }
163 
165  void update(const GridView& gv)
166  {
167  using namespace Dune::Hybrid;
168  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
169  elementAt(subFactories_, i).update(gv);
170  });
171  }
172 
183  template<class TP>
184  Node<TP> node(const TP& tp) const
185  {
186  auto node = Node<TP>(tp);
187  using namespace Dune::Hybrid;
188  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
189  node.setChild( elementAt(subFactories_, i).node(TypeTree::push_back(tp, i)), i);
190  });
191  return node;
192  }
193 
203  template<class TP>
205  {
206  return IndexSet<TP>{*this};
207  }
208 
210  size_type size() const
211  {
212  return size({});
213  }
214 
216  size_type size(const SizePrefix& prefix) const
217  {
218  return size(prefix, IndexMergingStrategy{});
219  }
220 
221 private:
222 
223  size_type size(const SizePrefix& prefix, BasisBuilder::BlockedLexicographic) const
224  {
225  if (prefix.size() == 0)
226  return children;
227 
228  return Hybrid::switchCases(std::make_index_sequence<children>(), prefix[0], [&] (auto i) {
229  const auto& subFactory = std::get<i.value>(subFactories_);
230  typename std::decay<decltype(subFactory)>::type::SizePrefix subPrefix;
231  for(std::size_t i=1; i<prefix.size(); ++i)
232  subPrefix.push_back(prefix[i]);
233  return subFactory.size(subPrefix);
234  }, []() {
235  return size_type(0);
236  });
237  }
238 
239  struct Lambda_size_flat_sizeInSubtree
240  {
241  template<class I, class SFT>
242  size_type operator()(const I&, const SFT& subFactories, const SizePrefix& prefix, size_type& shiftedFirst, size_type& r)
243  {
244  using SubFactory = typename std::tuple_element<I::value, SFT>::type;
245  const SubFactory& subFactory = std::get<I::value>(subFactories);
246  if (shiftedFirst < subFactory.size())
247  {
248  typename SubFactory::SizePrefix subPrefix;
249  subPrefix.push_back(shiftedFirst);
250  for(std::size_t i=1; i<prefix.size(); ++i)
251  subPrefix.push_back(prefix[i]);
252  r = subFactory.size(subPrefix);
253  return true;
254  }
255  shiftedFirst -= subFactory.size();
256  return false;
257  }
258  };
259 
260  size_type size(const SizePrefix& prefix, BasisBuilder::FlatLexicographic) const
261  {
262  size_type r = 0;
263  using namespace Dune::Hybrid;
264  if (prefix.size() == 0)
265  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
266  r += elementAt(subFactories_, i).size();
267  });
268  else {
269  size_type shiftedFirst = prefix[0];
270  staticFindInRange<0, sizeof...(SF)>(Lambda_size_flat_sizeInSubtree(), subFactories_, prefix, shiftedFirst, r);
271  }
272  return r;
273  }
274 
275 public:
276 
279  {
280  size_type r=0;
281  // Accumulate dimension() for all subfactories
282  using namespace Dune::Hybrid;
283  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
284  r += elementAt(subFactories_, i).dimension();
285  });
286  return r;
287  }
288 
291  {
292  size_type r=0;
293  // Accumulate maxNodeSize() for all subfactories
294  using namespace Dune::Hybrid;
295  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
296  r += elementAt(subFactories_, i).maxNodeSize();
297  });
298  return r;
299  }
300 
301 protected:
302  std::tuple<SF...> subFactories_;
303 };
304 
305 
306 
307 template<class MI, class TP, class IMS, class... SF>
309 {
310  static const std::size_t children = sizeof...(SF);
311 
312 public:
313 
314  template<std::size_t k>
315  using SubFactory = typename std::tuple_element<k, std::tuple<SF...>>::type;
316 
318  using size_type = std::size_t;
319  using IndexMergingStrategy = IMS;
320 
322  using MultiIndex = MI;
323 
324  using NodeFactory = CompositeNodeFactory<MI, IMS, SF...>;
325 
326  using Node = typename NodeFactory::template Node<TP>;
327 
328  using SubTreePaths = typename NodeFactory::template FixedTP<TP>::SubTreePaths;
329  using SubIndexSets = typename NodeFactory::template FixedTP<TP>::SubIndexSets;
330 
331 
333  {
334  // transform a single (factory,subTreePath) pair to subIndexSet
335  template<class Factory, class SubTP>
336  auto operator()(const Factory& factory, const SubTP& subTP)
337  ->decltype(factory.template indexSet<SubTP>())
338  {
339  return factory.template indexSet<SubTP>();
340  }
341  };
342 
343  CompositeNodeIndexSet(const NodeFactory & nodeFactory) :
344  nodeFactory_(&nodeFactory),
345  subNodeIndexSetTuple_(transformTuple(Lambda_FactoryToSubIndexSet(), nodeFactory_->subFactories_, SubTreePaths()))
346  {}
347 
348  void bind(const Node& node)
349  {
350  node_ = &node;
351  using namespace Dune::Hybrid;
352  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
353  elementAt(subNodeIndexSetTuple_, i).bind(node.child(i));
354  });
355  }
356 
357  void unbind()
358  {
359  node_ = nullptr;
360  using namespace Dune::Hybrid;
361  forEach(Dune::Std::make_index_sequence<children>(), [&](auto i) {
362  elementAt(subNodeIndexSetTuple_, i).unbind();
363  });
364  }
365 
366  size_type size() const
367  {
368  return node_->size();
369  }
370 
371  MultiIndex index(size_type localIndex) const
372  {
373  return index(localIndex, IndexMergingStrategy{});
374  }
375 
377  {
378  template<class I, class SNIT, class SFT>
379  bool operator()(const I& i, SNIT& subNodeIndexSetTuple, const SFT& subFactories, size_type localIndex, size_type& rootOffset, MultiIndex& multiIndex)
380  {
381  const auto& subNodeIndexSet = std::get<I::value>(subNodeIndexSetTuple);
382  size_type size = subNodeIndexSet.size();
383  if (localIndex < size)
384  {
385  multiIndex = subNodeIndexSet.index(localIndex);
386  multiIndex[0] += rootOffset;
387  return true;
388  }
389  localIndex -= size;
390  rootOffset += std::get<I::value>(subFactories).size();
391  return false;
392  }
393  };
394 
396  {
397  size_type shiftedLocalIndex = localIndex;
398  size_type rootOffset = 0;
399  MultiIndex mi;
400  staticFindInRange<0, sizeof...(SF)>(Lambda_index_flat(), subNodeIndexSetTuple_, nodeFactory_->subFactories_, shiftedLocalIndex, rootOffset, mi);
401  return mi;
402  }
403 
405  {
406  template<class I, class SNIT>
407  bool operator()(const I& i, SNIT& subNodeIndexSetTuple, size_type& localIndex, size_type& component, MultiIndex& multiIndex)
408  {
409  const auto& subNodeIndexSet = std::get<I::value>(subNodeIndexSetTuple);
410  size_type size = subNodeIndexSet.size();
411  if (localIndex < size)
412  {
413  multiIndex = subNodeIndexSet.index(localIndex);
414  component = i;
415  return true;
416  }
417  localIndex -= size;
418  return false;
419  }
420  };
421 
423  {
424  size_type shiftedLocalIndex = localIndex;
425  size_type component = 0;
426  MultiIndex mi;
427  staticFindInRange<0, sizeof...(SF)>(Lambda_index(), subNodeIndexSetTuple_, shiftedLocalIndex, component, mi);
428  mi.resize(mi.size()+1);
429 
430  for(std::size_t i=mi.size()-1; i>0; --i)
431  mi[i] = mi[i-1];
432  mi[0] = component;
433  return mi;
434  }
435 
436 private:
437  const NodeFactory* nodeFactory_;
438  SubIndexSets subNodeIndexSetTuple_;
439  const Node* node_;
440 };
441 
442 
443 
444 namespace BasisBuilder {
445 
446 namespace Imp {
447 
448 template<class ST0>
449 constexpr std::size_t maxHelper(ST0&& i0)
450 {
451  return i0;
452 }
453 
454 template<class ST0, class... ST>
455 constexpr std::size_t maxHelper(ST0&& i0, ST&&... i)
456 {
457  return (i0 > maxHelper(i...)) ? i0 : maxHelper(i...);
458 }
459 
460 template<class IndexTag, class... SubFactoryTags>
462 {
463  static const bool isBlocked = std::is_same<IndexTag,BlockedLexicographic>::value or std::is_same<IndexTag,LeafBlockedInterleaved>::value;
464 
465  static const std::size_t requiredMultiIndexSize=maxHelper(SubFactoryTags::requiredMultiIndexSize...) + (std::size_t)(isBlocked);
466 
467  template<class MultiIndex, class GridView>
468  auto build(const GridView& gridView)
469  -> CompositeNodeFactory<MultiIndex, IndexTag, decltype(SubFactoryTags().template build<MultiIndex, GridView>(gridView))...>
470  {
471  return {SubFactoryTags().template build<MultiIndex, GridView>(gridView)...};
472  }
473 };
474 
475 template<class... Args>
476 auto compositeImp(std::tuple<Args...>)
478 {
479  return {};
480 }
481 
482 } // end namespace BasisBuilder::Imp
483 
484 
485 
496 template<
497  typename... Args,
498  std::enable_if_t<Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
499 auto composite(Args&&... args)
500 {
502 }
503 
515 template<
516  typename... Args,
517  std::enable_if_t<not Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
518 auto composite(Args&&... args)
519 {
520  return Imp::compositeImp(std::tuple<BasisBuilder::BlockedLexicographic,Args...>{});
521 }
522 
523 } // end namespace BasisBuilder
524 
525 
526 
527 } // end namespace Functions
528 } // end namespace Dune
529 
530 
531 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
A factory for composite bases.
Definition: compositebasis.hh:66
friend class CompositeNodeIndexSet
Definition: compositebasis.hh:86
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: compositebasis.hh:159
std::tuple< SF... > SubFactories
Tuple of child factories.
Definition: compositebasis.hh:71
MultiIndex index(size_type localIndex) const
Definition: compositebasis.hh:371
MultiIndex index(const size_type &localIndex, BasisBuilder::BlockedLexicographic) const
Definition: compositebasis.hh:422
Node< TP > node(const TP &tp) const
Create tree node with given root tree path.
Definition: compositebasis.hh:184
ExpandTuple< SubNodesToNode, SubNodes > Node
Definition: compositebasis.hh:112
Lexicographic merging of direct children without blocking.
Definition: basistags.hh:61
typename SubFactory< 0 >::GridView GridView
Definition: compositebasis.hh:317
typename NodeFactory::template Node< TP > Node
Definition: compositebasis.hh:326
CompositeNodeFactory(SFArgs &&... sfArgs)
Constructor for given child factory objects.
Definition: compositebasis.hh:144
Get last entry of type list.
Definition: utility.hh:218
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: compositebasis.hh:278
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: compositebasis.hh:165
Lexicographic merging of direct children with blocking (i.e. creating one block per direct child)...
Definition: basistags.hh:95
auto compositeImp(std::tuple< Args... >) -> Imp::CompositeNodeFactoryBuilder< Args... >
Definition: compositebasis.hh:476
bool operator()(const I &i, SNIT &subNodeIndexSetTuple, const SFT &subFactories, size_type localIndex, size_type &rootOffset, MultiIndex &multiIndex)
Definition: compositebasis.hh:379
Dune::ReservedVector< size_type, MultiIndex::max_size()+1 > SizePrefix
Type used for prefixes handed to the size() method.
Definition: compositebasis.hh:134
void initializeIndices()
Initialize the global indices.
Definition: compositebasis.hh:150
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
constexpr std::size_t maxHelper(ST0 &&i0, ST &&... i)
Definition: compositebasis.hh:455
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: compositebasis.hh:322
TransformTuple< IndexToSubTreePath, ChildIndexTuple > SubTreePaths
Definition: compositebasis.hh:97
MultiIndex index(const size_type &localIndex, BasisBuilder::FlatLexicographic) const
Definition: compositebasis.hh:395
bool operator()(const I &i, SNIT &subNodeIndexSetTuple, size_type &localIndex, size_type &component, MultiIndex &multiIndex)
Definition: compositebasis.hh:407
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: compositebasis.hh:216
std::make_index_sequence< SizeOf< T... >{}> index_sequence_for
Definition: compositebasis.hh:35
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: compositebasis.hh:131
Definition: compositebasis.hh:30
IntegerSequenceTuple< Imp::index_sequence_for< SF... >> ChildIndexTuple
Definition: compositebasis.hh:88
Definition: nodes.hh:232
std::size_t size_type
Type used for indices and size information.
Definition: compositebasis.hh:77
auto operator()(const Factory &factory, const SubTP &subTP) -> decltype(factory.template indexSet< SubTP >())
Definition: compositebasis.hh:336
static constexpr bool isIndexMergingStrategy()
Definition: basistags.hh:23
decltype(TypeTree::push_back(TP(), I())) IndexToSubTreePath
Definition: compositebasis.hh:95
auto transformTuple(F &&f, const std::tuple< T... > &tuple) -> decltype(Imp::transformTupleHelper(std::forward< F >(f), tuple, std::index_sequence_for< T... >
Transform tuple value using a functor.
Definition: utility.hh:162
TransformTuple< FactoryToSubNode, SubFactories, SubTreePaths > SubNodes
Definition: compositebasis.hh:102
STL namespace.
auto composite(Args &&... args)
Create a factory builder that can build a CompositeNodeFactory.
Definition: compositebasis.hh:499
typename Imp::ExpandTupleHelper< T, ArgTuple >::Type ExpandTuple
Expand tuple arguments as template arguments.
Definition: utility.hh:91
IndexSet< TP > indexSet() const
Create tree node index set with given root tree path.
Definition: compositebasis.hh:204
typename Imp::IntegerSequenceTupleHelper< IntegerSequence >::Type IntegerSequenceTuple
Transform integer_sequence<I,k...> to tuple<integral_constant<I,k>...>
Definition: utility.hh:208
void staticFindInRange(F &&f, Args &&... args)
Static find loop.
Definition: staticforloop.hh:56
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: compositebasis.hh:80
Definition: compositebasis.hh:51
typename std::tuple_element< k, std::tuple< SF... >>::type SubFactory
Template mapping index of child to its factory type.
Definition: compositebasis.hh:120
TransformTuple< FactoryToSubIndexSet, SubFactories, SubTreePaths > SubIndexSets
Definition: compositebasis.hh:107
std::size_t size_type
Definition: compositebasis.hh:318
IMS IndexMergingStrategy
Definition: compositebasis.hh:319
typename F::template IndexSet< SubTP > FactoryToSubIndexSet
Definition: compositebasis.hh:105
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: compositebasis.hh:290
typename F::template Node< SubTP > FactoryToSubNode
Definition: compositebasis.hh:100
size_type size() const
Definition: compositebasis.hh:366
std::tuple< SF... > subFactories_
Definition: compositebasis.hh:302
void unbind()
Definition: compositebasis.hh:357
typename Imp::RotateHelper< std::tuple< T... >, std::make_index_sequence< sizeof...(T) -1 >>::type type
Definition: utility.hh:249
typename FixedTP< TP >::Node Node
Template mapping root tree path to type of created tree node.
Definition: compositebasis.hh:124
auto build(const GridView &gridView) -> CompositeNodeFactory< MultiIndex, IndexTag, decltype(SubFactoryTags().template build< MultiIndex, GridView >(gridView))... >
Definition: compositebasis.hh:468
typename std::tuple_element< k, std::tuple< SF... >>::type SubFactory
Definition: compositebasis.hh:315
CompositeNodeIndexSet(const NodeFactory &nodeFactory)
Definition: compositebasis.hh:343
typename NodeFactory::template FixedTP< TP >::SubTreePaths SubTreePaths
Definition: compositebasis.hh:328
typename std::tuple_element< 0, SubFactories >::type::GridView GridView
The grid view that the FE basis is defined on.
Definition: compositebasis.hh:74
size_type size() const
Same as size(prefix) with empty prefix.
Definition: compositebasis.hh:210
Definition: compositebasis.hh:91
void bind(const Node &node)
Definition: compositebasis.hh:348
typename Imp::TransformTupleHelper< F, Tuples... >::Type TransformTuple
Transform tuple types argument using type-functor.
Definition: utility.hh:128
typename NodeFactory::template FixedTP< TP >::SubIndexSets SubIndexSets
Definition: compositebasis.hh:329