dune-functions  2.7.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/std/apply.hh>
11 #include <dune/common/hybridutilities.hh>
12 #include <dune/common/reservedvector.hh>
13 #include <dune/common/typeutilities.hh>
14 #include <dune/common/hybridutilities.hh>
15 #include <dune/common/tupleutility.hh>
16 #include <dune/common/tuplevector.hh>
17 
18 #include <dune/typetree/compositenode.hh>
19 #include <dune/typetree/utility.hh>
20 
27 
28 
29 namespace Dune {
30 namespace Functions {
31 
32 // *****************************************************************************
33 // This is the reusable part of the composite bases. It contains
34 //
35 // CompositePreBasis
36 // CompositeNodeIndexSet
37 //
38 // The pre-basis allows to create the others and is the owner of possible shared
39 // state. These components do _not_ depend on the global basis or index
40 // set and can be used without a global basis.
41 // *****************************************************************************
42 
43 
44 template<class PB, class IMS>
46 
59 template<class MI, class IMS, class... SPB>
61 {
62 public:
63 
65  using SubPreBases = std::tuple<SPB...>;
66 
68  template<std::size_t i>
69  using SubPreBasis = std::tuple_element_t<i, SubPreBases>;
70 
72  using GridView = typename std::tuple_element_t<0, SubPreBases>::GridView;
73 
75  using size_type = std::size_t;
76 
78  using IndexMergingStrategy = IMS;
79 
80 protected:
81  static const std::size_t children = sizeof...(SPB);
82 
83  template<class, class>
84  friend class CompositeNodeIndexSet;
85 
86  using ChildIndices = std::make_index_sequence<children>;
87 
88  template<class Indices>
89  struct Types;
90 
91  template<std::size_t... indices>
92  struct Types<Dune::Std::index_sequence<indices...>>
93  {
94  template<std::size_t i>
95  using SubNode = typename std::tuple_element_t<i, SubPreBases>::Node;
96 
97  template<std::size_t i>
98  using SubIndexSet = typename std::tuple_element_t<i, SubPreBases>::IndexSet;
99 
100  using SubIndexSets = std::tuple<SubIndexSet<indices>...>;
101 
103  };
104 
106 
107 public:
108 
110  using Node = typename Types<ChildIndices>::Node;
111 
114 
116  using MultiIndex = MI;
117 
119  using SizePrefix = Dune::ReservedVector<size_type, MultiIndex::max_size()>;
120 
126  template<class... SFArgs,
127  disableCopyMove<CompositePreBasis, SFArgs...> = 0,
128  enableIfConstructible<std::tuple<SPB...>, SFArgs...> = 0>
129  CompositePreBasis(SFArgs&&... sfArgs) :
130  subPreBases_(std::forward<SFArgs>(sfArgs)...)
131  {
132  Hybrid::forEach(subPreBases_, [&](const auto& subPreBasis){
133  static_assert(models<Concept::PreBasis<GridView>, std::decay_t<decltype(subPreBasis)>>(), "Subprebases passed to CompositePreBasis does not model the PreBasis concept.");
134  });
135  }
136 
139  {
140  Hybrid::forEach(ChildIndices(), [&](auto i) {
141  this->subPreBasis(i).initializeIndices();
142  });
143  }
144 
146  const GridView& gridView() const
147  {
148  return std::get<0>(subPreBases_).gridView();
149  }
150 
152  void update(const GridView& gv)
153  {
154  Hybrid::forEach(ChildIndices(), [&](auto i) {
155  this->subPreBasis(i).update(gv);
156  });
157  }
158 
162  Node makeNode() const
163  {
164  auto node = Node{};
165  Hybrid::forEach(ChildIndices(), [&](auto i) {
166  node.setChild(this->subPreBasis(i).makeNode(), i);
167  });
168  return node;
169  }
170 
178  {
179  return IndexSet{*this,
180  unpackIntegerSequence([&](auto... i) {
181  return std::make_tuple(this->subPreBasis(i).makeIndexSet()...);
182  }, ChildIndices())};
183  }
184 
186  size_type size() const
187  {
188  return size({});
189  }
190 
192  size_type size(const SizePrefix& prefix) const
193  {
194  return size(prefix, IndexMergingStrategy{});
195  }
196 
197 private:
198 
200  {
201  if (prefix.size() == 0)
202  return children;
203 
204  return Hybrid::switchCases(ChildIndices(), prefix[0], [&] (auto i) {
205  typename SubPreBasis<i>::SizePrefix subPrefix;
206  for(std::size_t i=1; i<prefix.size(); ++i)
207  subPrefix.push_back(prefix[i]);
208  return this->subPreBasis(i).size(subPrefix);
209  }, []() {
210  return size_type(0);
211  });
212  }
213 
214  size_type size(const SizePrefix& prefix, BasisFactory::FlatLexicographic) const
215  {
216  size_type result = 0;
217  if (prefix.size() == 0)
218  Hybrid::forEach(ChildIndices(), [&](auto i) {
219  result += this->subPreBasis(i).size();
220  });
221  else {
222  size_type shiftedFirstDigit = prefix[0];
223  staticFindInRange<0, children>([&](auto i) {
224  auto firstDigitSize = this->subPreBasis(i).size();
225  if (shiftedFirstDigit < firstDigitSize)
226  {
227  typename SubPreBasis<i>::SizePrefix subPrefix;
228  subPrefix.push_back(shiftedFirstDigit);
229  for(std::size_t i=1; i<prefix.size(); ++i)
230  subPrefix.push_back(prefix[i]);
231  result = this->subPreBasis(i).size(subPrefix);
232  return true;
233  }
234  shiftedFirstDigit -= firstDigitSize;
235  return false;
236  });
237  }
238  return result;
239  }
240 
241 public:
242 
245  {
246  size_type r=0;
247  // Accumulate dimension() for all subprebases
248  Hybrid::forEach(ChildIndices(), [&](auto i) {
249  r += this->subPreBasis(i).dimension();
250  });
251  return r;
252  }
253 
256  {
257  size_type r=0;
258  // Accumulate maxNodeSize() for all subprebases
259  Hybrid::forEach(ChildIndices(), [&](auto i) {
260  r += this->subPreBasis(i).maxNodeSize();
261  });
262  return r;
263  }
264 
266  template<std::size_t i>
267  const SubPreBasis<i>& subPreBasis(Dune::index_constant<i> = {}) const
268  {
269  return std::get<i>(subPreBases_);
270  }
271 
273  template<std::size_t i>
274  SubPreBasis<i>& subPreBasis(Dune::index_constant<i> = {})
275  {
276  return std::get<i>(subPreBases_);
277  }
278 
279 private:
280  std::tuple<SPB...> subPreBases_;
281 };
282 
283 
284 
285 template<class PB, class IMS>
286 class CompositeNodeIndexSet
287 {
288 public:
289 
290  using size_type = std::size_t;
291  using PreBasis = PB;
292  using MultiIndex = typename PreBasis::MultiIndex;
293  using Node = typename PreBasis::Node;
294 
295 protected:
296 
297  using IndexMergingStrategy = IMS;
298  using SubIndexSets = typename PreBasis::SubIndexSets;
299  using ChildIndices = typename PreBasis::ChildIndices;
300 
301 public:
302 
303  CompositeNodeIndexSet(const PreBasis & preBasis, SubIndexSets&& subNodeIndexSets) :
304  preBasis_(&preBasis),
305  subNodeIndexSetTuple_(std::move(subNodeIndexSets)),
306  node_(nullptr)
307  {}
308 
309  void bind(const Node& node)
310  {
311  node_ = &node;
312  Hybrid::forEach(ChildIndices(), [&](auto i) {
313  Hybrid::elementAt(subNodeIndexSetTuple_, i).bind(node.child(i));
314  });
315  }
316 
317  void unbind()
318  {
319  node_ = nullptr;
320  Hybrid::forEach(ChildIndices(), [&](auto i) {
321  Hybrid::elementAt(subNodeIndexSetTuple_, i).unbind();
322  });
323  }
324 
325  size_type size() const
326  {
327  return node_->size();
328  }
329 
331  template<typename It>
332  It indices(It it) const
333  {
334  return indices(it, IndexMergingStrategy{});
335  }
336 
337  template<typename It>
338  It indices(It multiIndices, BasisFactory::FlatLexicographic) const
339  {
340  size_type firstComponentOffset = 0;
341  // Loop over all children
342  Hybrid::forEach(ChildIndices(), [&](auto child){
343  const auto& subNodeIndexSet = Hybrid::elementAt(subNodeIndexSetTuple_, child);
344  const auto& subPreBasis = preBasis_->subPreBasis(child);
345  size_type subTreeSize = subNodeIndexSet.size();
346  // Fill indices for current child into index buffer starting from current
347  // buffer position and shift first index component of any index for current
348  // child by suitable offset to get lexicographic indices.
349  subNodeIndexSet.indices(multiIndices);
350  for (std::size_t i = 0; i<subTreeSize; ++i)
351  multiIndices[i][0] += firstComponentOffset;
352  // Increment offset by the size for first index component of the current child
353  firstComponentOffset += subPreBasis.size({});
354  // Increment buffer iterator by the number of indices processed for current child
355  multiIndices += subTreeSize;
356  });
357  return multiIndices;
358  }
359 
361  {
362  M.resize(M.size()+1);
363  for(std::size_t i=M.size()-1; i>0; --i)
364  M[i] = M[i-1];
365  M[0] = M0;
366  }
367 
368  template<typename It>
369  It indices(It multiIndices, BasisFactory::BlockedLexicographic) const
370  {
371  // Loop over all children
372  Hybrid::forEach(ChildIndices(), [&](auto child){
373  const auto& subNodeIndexSet = Hybrid::elementAt(subNodeIndexSetTuple_, child);
374  size_type subTreeSize = subNodeIndexSet.size();
375  // Fill indices for current child into index buffer starting from current position
376  subNodeIndexSet.indices(multiIndices);
377  // Insert child index before first component of all indices of current child.
378  for (std::size_t i = 0; i<subTreeSize; ++i)
379  this->multiIndexPushFront(multiIndices[i], child);
380  // Increment buffer iterator by the number of indices processed for current child
381  multiIndices += subTreeSize;
382  });
383  return multiIndices;
384  }
385 
386 private:
387  const PreBasis* preBasis_;
388  SubIndexSets subNodeIndexSetTuple_;
389  const Node* node_;
390 };
391 
392 
393 
394 namespace BasisFactory {
395 
396 namespace Imp {
397 
398 template<class ST0>
399 constexpr std::size_t maxHelper(ST0&& i0)
400 {
401  return i0;
402 }
403 
404 template<class ST0, class... ST>
405 constexpr std::size_t maxHelper(ST0&& i0, ST&&... i)
406 {
407  return (i0 > maxHelper(i...)) ? i0 : maxHelper(i...);
408 }
409 
410 template<class IndexMergingStrategy, class... ChildPreBasisFactory>
411 class CompositePreBasisFactory
412 {
413  static const bool isBlocked = std::is_same<IndexMergingStrategy,BlockedLexicographic>::value or std::is_same<IndexMergingStrategy,BlockedInterleaved>::value;
414 
415  static const std::size_t maxChildIndexSize = maxHelper(ChildPreBasisFactory::requiredMultiIndexSize...);
416 
417  template<class MultiIndex, class GridView, class... ChildPreBasis>
418  auto makePreBasisFromChildPreBases(const GridView&, ChildPreBasis&&... childPreBasis) const
419  {
420  return CompositePreBasis<MultiIndex, IndexMergingStrategy, std::decay_t<ChildPreBasis>...>(std::forward<ChildPreBasis>(childPreBasis)...);
421  }
422 
423 public:
424 
425  static const std::size_t requiredMultiIndexSize = isBlocked ? (maxChildIndexSize+1) : maxChildIndexSize;
426 
427  CompositePreBasisFactory(const ChildPreBasisFactory&... childPreBasisFactory) :
428  childPreBasisFactories_(childPreBasisFactory...)
429  {}
430 
431  CompositePreBasisFactory(ChildPreBasisFactory&&... childPreBasisFactory) :
432  childPreBasisFactories_(std::move(childPreBasisFactory)...)
433  {}
434 
435  template<class MultiIndex, class GridView>
436  auto makePreBasis(const GridView& gridView) const
437  {
438  // Use Std::apply to unpack the tuple childPreBasisFactories_
439  return Std::apply([&](const auto&... childPreBasisFactory) {
440  return this->makePreBasisFromChildPreBases<MultiIndex>(gridView, childPreBasisFactory.template makePreBasis<MultiIndex>(gridView)...);
441  }, childPreBasisFactories_);
442  }
443 
444 private:
445  std::tuple<ChildPreBasisFactory...> childPreBasisFactories_;
446 };
447 
448 } // end namespace BasisFactory::Imp
449 
450 
451 
462 template<
463  typename... Args,
464  std::enable_if_t<Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
465 auto composite(Args&&... args)
466 {
467  // We have to separate the last entry which is the IndexMergingStrategy
468  // and the preceding ones, which are the ChildPreBasisFactories
469 
470  using ArgTuple = std::tuple<std::decay_t<Args>...>;
471 
472  // Compute number of children and index of the IndexMergingStrategy argument
473  constexpr std::size_t children = Dune::SizeOf<Args...>::value-1;
474 
475  // Use last type as IndexMergingStrategy
476  using IndexMergingStrategy = std::tuple_element_t<children, ArgTuple>;
477 
478  // Index sequence for all but the last entry for partial tuple unpacking
479  auto childIndices = std::make_index_sequence<children>{};
480 
481  // Unpack tuple only for those entries related to children
482  return applyPartial([](auto&&... childPreBasisFactory){
483  return Imp::CompositePreBasisFactory<IndexMergingStrategy, std::decay_t<decltype(childPreBasisFactory)>...>(std::forward<decltype(childPreBasisFactory)>(childPreBasisFactory)...);
484  },
485  std::forward_as_tuple(std::forward<Args>(args)...),
486  childIndices);
487 }
488 
500 template<
501  typename... Args,
502  std::enable_if_t<not Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
503 auto composite(Args&&... args)
504 {
505  return Imp::CompositePreBasisFactory<BasisFactory::BlockedLexicographic, std::decay_t<Args>...>(std::forward<Args>(args)...);
506 }
507 
508 } // end namespace BasisFactory
509 
510 // Backward compatibility
511 namespace BasisBuilder {
512 
513  using namespace BasisFactory;
514 
515 }
516 
517 
518 
519 } // end namespace Functions
520 } // end namespace Dune
521 
522 
523 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
Dune::Functions::CompositePreBasis::size
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: compositebasis.hh:192
Dune::Functions::CompositePreBasis::SubPreBasis
std::tuple_element_t< i, SubPreBases > SubPreBasis
Export individual child pre-bases by index.
Definition: compositebasis.hh:69
Dune::Functions::CompositePreBasis::Types
Definition: compositebasis.hh:89
Dune::Functions::BasisFactory::BlockedLexicographic
Lexicographic merging of direct children with blocking (i.e. creating one block per direct child).
Definition: basistags.hh:146
basistags.hh
Dune::Functions::CompositePreBasis::SubIndexSets
typename Types< ChildIndices >::SubIndexSets SubIndexSets
Definition: compositebasis.hh:105
Dune::Functions::CompositePreBasis::SubPreBases
std::tuple< SPB... > SubPreBases
Tuple of child pre-bases.
Definition: compositebasis.hh:65
Dune::Functions::CompositePreBasis::Types< Dune::Std::index_sequence< indices... > >::SubIndexSets
std::tuple< SubIndexSet< indices >... > SubIndexSets
Definition: compositebasis.hh:100
Dune::Functions::CompositePreBasis::makeNode
Node makeNode() const
Create tree node.
Definition: compositebasis.hh:162
Dune::Functions::BasisFactory::composite
auto composite(Args &&... args)
Create a factory builder that can build a CompositePreBasis.
Definition: compositebasis.hh:465
Dune::Functions::CompositePreBasis::ChildIndices
std::make_index_sequence< children > ChildIndices
Definition: compositebasis.hh:86
Dune::Functions::CompositePreBasis
A pre-basis for composite bases.
Definition: compositebasis.hh:60
staticforloop.hh
Dune::Functions::BasisFactory::IndexMergingStrategy
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:44
Dune::Functions::CompositePreBasis::maxNodeSize
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: compositebasis.hh:255
Dune::Functions::CompositeNodeIndexSet::SubIndexSets
typename PreBasis::SubIndexSets SubIndexSets
Definition: compositebasis.hh:298
Dune::Functions::CompositePreBasis::Node
typename Types< ChildIndices >::Node Node
Template mapping root tree path to type of created tree node.
Definition: compositebasis.hh:110
Dune::Functions::CompositePreBasis::SizePrefix
Dune::ReservedVector< size_type, MultiIndex::max_size()> SizePrefix
Type used for prefixes handed to the size() method.
Definition: compositebasis.hh:119
Dune::Functions::CompositePreBasis::dimension
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: compositebasis.hh:244
Dune::Functions::CompositePreBasis::makeIndexSet
IndexSet makeIndexSet() const
Create tree node index set.
Definition: compositebasis.hh:177
Dune::Functions::CompositePreBasis::subPreBasis
const SubPreBasis< i > & subPreBasis(Dune::index_constant< i >={}) const
Const access to the stored prebasis of the factor in the power space.
Definition: compositebasis.hh:267
Dune::Functions::CompositeNodeIndexSet::Node
typename PreBasis::Node Node
Definition: compositebasis.hh:293
Dune::Functions::CompositeNodeIndexSet::bind
void bind(const Node &node)
Definition: compositebasis.hh:309
Dune::Functions::CompositeNodeIndexSet::MultiIndex
typename PreBasis::MultiIndex MultiIndex
Definition: compositebasis.hh:292
Dune::Functions::CompositeNodeIndexSet::size
size_type size() const
Definition: compositebasis.hh:325
Dune::Functions::CompositeNodeIndexSet::IndexMergingStrategy
IMS IndexMergingStrategy
Definition: compositebasis.hh:297
Dune::Functions::CompositePreBasis::update
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: compositebasis.hh:152
Dune::Functions::CompositePreBasis::CompositePreBasis
CompositePreBasis(SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: compositebasis.hh:129
Dune::Functions::CompositePreBasis::IndexMergingStrategy
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child pre-bases.
Definition: compositebasis.hh:78
Dune::Functions::CompositeNodeIndexSet::unbind
void unbind()
Definition: compositebasis.hh:317
Dune::Functions::enableIfConstructible
typename std::enable_if< std::is_constructible< T, Args... >::value, int >::type enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:26
Dune::Functions::LastType
Get last entry of type list.
Definition: utility.hh:221
Dune::Functions::CompositePreBasis::gridView
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: compositebasis.hh:146
Dune::Functions::CompositeNodeIndexSet::indices
It indices(It multiIndices, BasisFactory::BlockedLexicographic) const
Definition: compositebasis.hh:369
nodes.hh
Dune::Functions::CompositeNodeIndexSet::indices
It indices(It it) const
Maps from subtree index set [0..size-1] to a globally unique multi index in global basis.
Definition: compositebasis.hh:332
Dune::Functions::CompositePreBasis::initializeIndices
void initializeIndices()
Initialize the global indices.
Definition: compositebasis.hh:138
Dune
Definition: polynomial.hh:10
Dune::Functions::CompositeNodeIndexSet::PreBasis
PB PreBasis
Definition: compositebasis.hh:291
Dune::Functions::CompositePreBasis::size
size_type size() const
Same as size(prefix) with empty prefix.
Definition: compositebasis.hh:186
Dune::Functions::Concept::PreBasis
Definition: functionspacebases/concepts.hh:143
Dune::Functions::CompositePreBasis::Types< Dune::Std::index_sequence< indices... > >::SubNode
typename std::tuple_element_t< i, SubPreBases >::Node SubNode
Definition: compositebasis.hh:95
Dune::Functions::CompositePreBasis::MultiIndex
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: compositebasis.hh:116
Dune::Functions::CompositeNodeIndexSet::size_type
std::size_t size_type
Definition: compositebasis.hh:290
Dune::Functions::CompositeNodeIndexSet::ChildIndices
typename PreBasis::ChildIndices ChildIndices
Definition: compositebasis.hh:299
Dune::Functions::CompositeNodeIndexSet::indices
It indices(It multiIndices, BasisFactory::FlatLexicographic) const
Definition: compositebasis.hh:338
Dune::Functions::CompositeNodeIndexSet::multiIndexPushFront
static void multiIndexPushFront(MultiIndex &M, size_type M0)
Definition: compositebasis.hh:360
Dune::Functions::CompositeNodeIndexSet
Definition: compositebasis.hh:45
Dune::Functions::BasisFactory::FlatLexicographic
Lexicographic merging of direct children without blocking.
Definition: basistags.hh:78
Dune::Functions::CompositeBasisNode
Definition: nodes.hh:212
Dune::Functions::CompositePreBasis::size_type
std::size_t size_type
Type used for indices and size information.
Definition: compositebasis.hh:75
Dune::Functions::Concept::isIndexMergingStrategy
static constexpr bool isIndexMergingStrategy()
Definition: basistags.hh:23
utility.hh
Dune::Functions::CompositePreBasis::subPreBasis
SubPreBasis< i > & subPreBasis(Dune::index_constant< i >={})
Mutable access to the stored prebasis of the factor in the power space.
Definition: compositebasis.hh:274
Dune::Functions::CompositePreBasis::children
static const std::size_t children
Definition: compositebasis.hh:81
Dune::Functions::CompositePreBasis::GridView
typename std::tuple_element_t< 0, SubPreBases >::GridView GridView
The grid view that the FE basis is defined on.
Definition: compositebasis.hh:72
type_traits.hh
Dune::Functions::CompositePreBasis::Types< Dune::Std::index_sequence< indices... > >::SubIndexSet
typename std::tuple_element_t< i, SubPreBases >::IndexSet SubIndexSet
Definition: compositebasis.hh:98
concepts.hh
Dune::Functions::CompositeNodeIndexSet::CompositeNodeIndexSet
CompositeNodeIndexSet(const PreBasis &preBasis, SubIndexSets &&subNodeIndexSets)
Definition: compositebasis.hh:303