Dune Core Modules (2.9.0)

compositebasis.hh
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/apply.hh>
10 #include <dune/common/hybridutilities.hh>
13 #include <dune/common/hybridutilities.hh>
16 
17 #include <dune/functions/common/staticforloop.hh>
18 #include <dune/functions/common/type_traits.hh>
19 #include <dune/functions/common/utility.hh>
20 #include <dune/functions/functionspacebases/basistags.hh>
21 #include <dune/functions/functionspacebases/nodes.hh>
22 #include <dune/functions/functionspacebases/concepts.hh>
23 #include <dune/functions/functionspacebases/defaultglobalbasis.hh>
24 
25 
26 namespace Dune {
27 namespace Functions {
28 
29 // *****************************************************************************
30 // This is the reusable part of the composite bases. It contains
31 //
32 // CompositePreBasis
33 //
34 // The pre-basis allows to create the others and is the owner of possible shared
35 // state. These components do _not_ depend on the global basis and local view
36 // and can be used without a global basis.
37 // *****************************************************************************
38 
39 
51 template<class IMS, class... SPB>
53 {
54  static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
55 public:
56 
58  using SubPreBases = std::tuple<SPB...>;
59 
61  template<std::size_t i>
62  using SubPreBasis = std::tuple_element_t<i, SubPreBases>;
63 
65  using GridView = typename std::tuple_element_t<0, SubPreBases>::GridView;
66 
68  using size_type = std::size_t;
69 
71  using IndexMergingStrategy = IMS;
72 
73 protected:
74  static const std::size_t children = sizeof...(SPB);
75 
76  using ChildIndices = std::make_index_sequence<children>;
77 
78 public:
79 
81  using Node = CompositeBasisNode<typename SPB::Node...>;
82 
83  static constexpr size_type maxMultiIndexSize = std::max({SPB::maxMultiIndexSize...}) + isBlocked;
84  static constexpr size_type minMultiIndexSize = std::min({SPB::minMultiIndexSize...}) + isBlocked;
85  static constexpr size_type multiIndexBufferSize = std::max({SPB::multiIndexBufferSize...}) + isBlocked;
86 
92  template<class... SFArgs,
93  disableCopyMove<CompositePreBasis, SFArgs...> = 0,
94  enableIfConstructible<std::tuple<SPB...>, SFArgs...> = 0>
95  CompositePreBasis(SFArgs&&... sfArgs) :
96  subPreBases_(std::forward<SFArgs>(sfArgs)...)
97  {
98  Hybrid::forEach(subPreBases_, [&](const auto& subPreBasis){
99  static_assert(models<Concept::PreBasis<GridView>, std::decay_t<decltype(subPreBasis)>>(), "Subprebases passed to CompositePreBasis does not model the PreBasis concept.");
100  });
101  }
102 
109  template<class GV,
110  std::enable_if_t<std::conjunction_v<
111  std::bool_constant<(children > 1)>, // Avoid ambiguous constructor if there's only one child
112  std::is_same<GV, GridView>,
113  std::is_constructible<SPB, GridView>...
114  >, int> = 0>
115  CompositePreBasis(const GV& gv) :
116  subPreBases_(SPB(gv)...)
117  {
118  Hybrid::forEach(subPreBases_, [&](const auto& subPreBasis){
119  static_assert(models<Concept::PreBasis<GridView>, std::decay_t<decltype(subPreBasis)>>(), "Subprebases passed to CompositePreBasis does not model the PreBasis concept.");
120  });
121  }
122 
125  {
126  Hybrid::forEach(ChildIndices(), [&](auto i) {
127  this->subPreBasis(i).initializeIndices();
128  });
129  }
130 
132  const GridView& gridView() const
133  {
134  return std::get<0>(subPreBases_).gridView();
135  }
136 
138  void update(const GridView& gv)
139  {
140  Hybrid::forEach(ChildIndices(), [&](auto i) {
141  this->subPreBasis(i).update(gv);
142  });
143  }
144 
148  Node makeNode() const
149  {
150  auto node = Node{};
151  Hybrid::forEach(ChildIndices(), [&](auto i) {
152  node.setChild(this->subPreBasis(i).makeNode(), i);
153  });
154  return node;
155  }
156 
158  size_type size() const
159  {
161  }
162 
164  template<class SizePrefix>
165  size_type size(const SizePrefix& prefix) const
166  {
167  return size(prefix, IndexMergingStrategy{});
168  }
169 
170 private:
171 
172  template<class SizePrefix>
173  size_type size(const SizePrefix& prefix, BasisFactory::BlockedLexicographic) const
174  {
175  if (prefix.size() == 0)
176  return children;
177 
178  return Hybrid::switchCases(ChildIndices(), prefix[0], [&] (auto i) {
179  SizePrefix subPrefix;
180  for(std::size_t i=1; i<prefix.size(); ++i)
181  subPrefix.push_back(prefix[i]);
182  return this->subPreBasis(i).size(subPrefix);
183  }, []() {
184  return size_type(0);
185  });
186  }
187 
188  template<class SizePrefix>
189  size_type size(const SizePrefix& prefix, BasisFactory::FlatLexicographic) const
190  {
191  size_type result = 0;
192  if (prefix.size() == 0)
193  Hybrid::forEach(ChildIndices(), [&](auto i) {
194  result += this->subPreBasis(i).size();
195  });
196  else {
197  size_type shiftedFirstDigit = prefix[0];
198  staticFindInRange<0, children>([&](auto i) {
199  auto firstDigitSize = this->subPreBasis(i).size();
200  if (shiftedFirstDigit < firstDigitSize)
201  {
202  SizePrefix subPrefix;
203  subPrefix.push_back(shiftedFirstDigit);
204  for(std::size_t i=1; i<prefix.size(); ++i)
205  subPrefix.push_back(prefix[i]);
206  result = this->subPreBasis(i).size(subPrefix);
207  return true;
208  }
209  shiftedFirstDigit -= firstDigitSize;
210  return false;
211  });
212  }
213  return result;
214  }
215 
216 public:
217 
220  {
221  size_type r=0;
222  // Accumulate dimension() for all subprebases
223  Hybrid::forEach(ChildIndices(), [&](auto i) {
224  r += this->subPreBasis(i).dimension();
225  });
226  return r;
227  }
228 
231  {
232  size_type r=0;
233  // Accumulate maxNodeSize() for all subprebases
234  Hybrid::forEach(ChildIndices(), [&](auto i) {
235  r += this->subPreBasis(i).maxNodeSize();
236  });
237  return r;
238  }
239 
241  template<std::size_t i>
243  {
244  return std::get<i>(subPreBases_);
245  }
246 
248  template<std::size_t i>
250  {
251  return std::get<i>(subPreBases_);
252  }
253 
255  template<typename It>
256  It indices(const Node& node, It it) const
257  {
258  return indices(node, it, IndexMergingStrategy{});
259  }
260 
261 private:
262 
263  template<typename It>
264  It indices(const Node& node, It multiIndices, BasisFactory::FlatLexicographic) const
265  {
266  size_type firstComponentOffset = 0;
267  // Loop over all children
268  Hybrid::forEach(ChildIndices(), [&](auto child){
269  size_type subTreeSize = node.child(child).size();
270  // Fill indices for current child into index buffer starting from current
271  // buffer position and shift first index component of any index for current
272  // child by suitable offset to get lexicographic indices.
273  subPreBasis(child).indices(node.child(child), multiIndices);
274  for (std::size_t i = 0; i<subTreeSize; ++i)
275  multiIndices[i][0] += firstComponentOffset;
276  // Increment offset by the size for first index component of the current child
277  firstComponentOffset += subPreBasis(child).size();
278  // Increment buffer iterator by the number of indices processed for current child
279  multiIndices += subTreeSize;
280  });
281  return multiIndices;
282  }
283 
284  template<class MultiIndex>
285  static void multiIndexPushFront(MultiIndex& M, size_type M0)
286  {
287  M.resize(M.size()+1);
288  for(std::size_t i=M.size()-1; i>0; --i)
289  M[i] = M[i-1];
290  M[0] = M0;
291  }
292 
293  template<typename It>
294  It indices(const Node& node, It multiIndices, BasisFactory::BlockedLexicographic) const
295  {
296  // Loop over all children
297  Hybrid::forEach(ChildIndices(), [&](auto child){
298  size_type subTreeSize = node.child(child).size();
299  // Fill indices for current child into index buffer starting from current position
300  subPreBasis(child).indices(node.child(child), multiIndices);
301  // Insert child index before first component of all indices of current child.
302  for (std::size_t i = 0; i<subTreeSize; ++i)
303  this->multiIndexPushFront(multiIndices[i], child);
304  // Increment buffer iterator by the number of indices processed for current child
305  multiIndices += subTreeSize;
306  });
307  return multiIndices;
308  }
309 
310  std::tuple<SPB...> subPreBases_;
311 };
312 
313 
314 
315 namespace BasisFactory {
316 
317 namespace Imp {
318 
319 template<class IndexMergingStrategy, class... ChildPreBasisFactory>
320 class CompositePreBasisFactory
321 {
322 
323  template<class GridView, class... ChildPreBasis>
324  auto makePreBasisFromChildPreBases(const GridView&, ChildPreBasis&&... childPreBasis) const
325  {
326  return CompositePreBasis<IndexMergingStrategy, std::decay_t<ChildPreBasis>...>(std::forward<ChildPreBasis>(childPreBasis)...);
327  }
328 
329 public:
330 
331  CompositePreBasisFactory(const ChildPreBasisFactory&... childPreBasisFactory) :
332  childPreBasisFactories_(childPreBasisFactory...)
333  {}
334 
335  CompositePreBasisFactory(ChildPreBasisFactory&&... childPreBasisFactory) :
336  childPreBasisFactories_(std::move(childPreBasisFactory)...)
337  {}
338 
339  template<class GridView>
340  auto operator()(const GridView& gridView) const
341  {
342  // Use std::apply to unpack the tuple childPreBasisFactories_
343  return std::apply([&](const auto&... childPreBasisFactory) {
344  return this->makePreBasisFromChildPreBases(gridView, childPreBasisFactory(gridView)...);
345  }, childPreBasisFactories_);
346  }
347 
348 private:
349  std::tuple<ChildPreBasisFactory...> childPreBasisFactories_;
350 };
351 
352 } // end namespace BasisFactory::Imp
353 
354 
355 
366 template<
367  typename... Args,
368  std::enable_if_t<Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
369 auto composite(Args&&... args)
370 {
371  // We have to separate the last entry which is the IndexMergingStrategy
372  // and the preceding ones, which are the ChildPreBasisFactories
373 
374  using ArgTuple = std::tuple<std::decay_t<Args>...>;
375 
376  // Compute number of children and index of the IndexMergingStrategy argument
377  constexpr std::size_t children = Dune::SizeOf<Args...>::value-1;
378 
379  // Use last type as IndexMergingStrategy
380  using IndexMergingStrategy = std::tuple_element_t<children, ArgTuple>;
381 
382  // Index sequence for all but the last entry for partial tuple unpacking
383  auto childIndices = std::make_index_sequence<children>{};
384 
385  // Unpack tuple only for those entries related to children
386  return applyPartial([](auto&&... childPreBasisFactory){
387  return Imp::CompositePreBasisFactory<IndexMergingStrategy, std::decay_t<decltype(childPreBasisFactory)>...>(std::forward<decltype(childPreBasisFactory)>(childPreBasisFactory)...);
388  },
389  std::forward_as_tuple(std::forward<Args>(args)...),
390  childIndices);
391 }
392 
404 template<
405  typename... Args,
406  std::enable_if_t<not Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
407 auto composite(Args&&... args)
408 {
409  return Imp::CompositePreBasisFactory<BasisFactory::BlockedLexicographic, std::decay_t<Args>...>(std::forward<Args>(args)...);
410 }
411 
412 } // end namespace BasisFactory
413 
414 // Backward compatibility
415 namespace BasisBuilder {
416 
417  using namespace BasisFactory;
418 
419 }
420 
421 
422 
423 } // end namespace Functions
424 } // end namespace Dune
425 
426 
427 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
A pre-basis for composite bases.
Definition: compositebasis.hh:53
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child pre-bases.
Definition: compositebasis.hh:71
SubPreBasis< i > & subPreBasis(Dune::index_constant< i >={})
Mutable access to the stored prebasis of the factor in the power space.
Definition: compositebasis.hh:249
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: compositebasis.hh:230
std::size_t size_type
Type used for indices and size information.
Definition: compositebasis.hh:68
CompositeBasisNode< typename SPB::Node... > Node
Template mapping root tree path to type of created tree node.
Definition: compositebasis.hh:81
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: compositebasis.hh:165
CompositePreBasis(SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: compositebasis.hh:95
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: compositebasis.hh:219
CompositePreBasis(const GV &gv)
Constructor for given GridView.
Definition: compositebasis.hh:115
It indices(const Node &node, It it) const
Maps from subtree index set [0..size-1] to a globally unique multi index in global basis.
Definition: compositebasis.hh:256
size_type size() const
Same as size(prefix) with empty prefix.
Definition: compositebasis.hh:158
typename std::tuple_element_t< 0, SubPreBases >::GridView GridView
The grid view that the FE basis is defined on.
Definition: compositebasis.hh:65
std::tuple< SPB... > SubPreBases
Tuple of child pre-bases.
Definition: compositebasis.hh:58
Node makeNode() const
Create tree node.
Definition: compositebasis.hh:148
void initializeIndices()
Initialize the global indices.
Definition: compositebasis.hh:124
std::tuple_element_t< i, SubPreBases > SubPreBasis
Export individual child pre-bases by index.
Definition: compositebasis.hh:62
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:242
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: compositebasis.hh:138
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: compositebasis.hh:132
A Vector class with statically reserved memory.
Definition: reservedvector.hh:47
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:30
constexpr auto models()
Check if concept is modeled by given types.
Definition: concept.hh:184
auto composite(Args &&... args)
Create a factory builder that can build a CompositePreBasis.
Definition: compositebasis.hh:369
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:268
constexpr decltype(auto) switchCases(const Cases &cases, const Value &value, Branches &&branches, ElseBranch &&elseBranch)
Switch statement.
Definition: hybridutilities.hh:461
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:89
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:81
ImplementationDefined child(Node &&node, Indices... indices)
Extracts the child of a node given by a sequence of compile-time and run-time indices.
Definition: childextraction.hh:126
std::enable_if_t< not Impl::disableCopyMoveHelper< This, T... >::value, int > disableCopyMove
Helper to disable constructor as copy and move constructor.
Definition: typeutilities.hh:45
typename std::enable_if< std::is_constructible< T, Args... >::value, int >::type enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:26
decltype(auto) applyPartial(F &&f, ArgTuple &&args, std::integer_sequence< I, i... >)
Apply function with arguments from a given tuple.
Definition: tupleutility.hh:42
Dune namespace.
Definition: alignedallocator.hh:13
An stl-compliant random-access container which stores everything on the stack.
Lexicographic merging of direct children with blocking (i.e. creating one block per direct child).
Definition: basistags.hh:148
Lexicographic merging of direct children without blocking.
Definition: basistags.hh:80
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:44
Get last entry of type list.
Definition: utility.hh:222
Compute size of variadic type list.
Definition: typetraits.hh:404
Contains utility classes which can be used with std::tuple.
Provides the TupleVector class that augments std::tuple by operator[].
Utilities for type computations, constraining overloads, ...
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 1, 22:29, 2024)