Dune Core Modules (2.9.0)

powerbasis.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_POWERBASIS_HH
4 #define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_POWERBASIS_HH
5 
8 #include <dune/common/indices.hh>
9 
10 #include <dune/functions/common/utility.hh>
11 #include <dune/functions/common/type_traits.hh>
12 #include <dune/functions/functionspacebases/basistags.hh>
13 #include <dune/functions/functionspacebases/nodes.hh>
14 #include <dune/functions/functionspacebases/concepts.hh>
15 #include <dune/functions/functionspacebases/defaultglobalbasis.hh>
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 // PowerPreBasis
27 //
28 // The pre-basis allows to create the others and is the owner of possible shared
29 // state. These components do _not_ depend on the global basis and local view
30 // and can be used without a global basis.
31 // *****************************************************************************
32 
43 template<class IMS, class SPB, std::size_t C>
45 {
46  static const std::size_t children = C;
47  static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
48 
49 public:
50 
52  using SubPreBasis = SPB;
53 
55  using GridView = typename SPB::GridView;
56 
58  using size_type = std::size_t;
59 
61  using IndexMergingStrategy = IMS;
62 
63  using SubNode = typename SubPreBasis::Node;
64 
66  using Node = PowerBasisNode<SubNode, children>;
67 
68  static constexpr size_type maxMultiIndexSize = SubPreBasis::maxMultiIndexSize + isBlocked;
69  static constexpr size_type minMultiIndexSize = SubPreBasis::minMultiIndexSize + isBlocked;
70  static constexpr size_type multiIndexBufferSize = SubPreBasis::multiIndexBufferSize + isBlocked;
71 
77  template<class... SFArgs,
78  disableCopyMove<PowerPreBasis, SFArgs...> = 0,
79  enableIfConstructible<SubPreBasis, SFArgs...> = 0>
80  PowerPreBasis(SFArgs&&... sfArgs) :
81  subPreBasis_(std::forward<SFArgs>(sfArgs)...)
82  {
83  static_assert(models<Concept::PreBasis<GridView>, SubPreBasis>(), "Subprebasis passed to PowerPreBasis does not model the PreBasis concept.");
84  }
85 
88  {
89  subPreBasis_.initializeIndices();
90  }
91 
93  const GridView& gridView() const
94  {
95  return subPreBasis_.gridView();
96  }
97 
99  void update(const GridView& gv)
100  {
101  subPreBasis_.update(gv);
102  }
103 
107  Node makeNode() const
108  {
109  auto node = Node{};
110  for (std::size_t i=0; i<children; ++i)
111  node.setChild(i, subPreBasis_.makeNode());
112  return node;
113  }
114 
116  size_type size() const
117  {
119  }
120 
122 
123  template<class SizePrefix>
124  size_type size(const SizePrefix& prefix) const
125  {
126  return size(prefix, IndexMergingStrategy{});
127  }
128 
129 private:
130 
131  template<class SizePrefix>
132  size_type size(const SizePrefix& prefix, BasisFactory::FlatInterleaved) const
133  {
134  // The root index size is the root index size of a single subnode
135  // multiplied by the number of subnodes because we enumerate all
136  // child indices in a row.
137  if (prefix.size() == 0)
138  return children*subPreBasis_.size();
139 
140  // The first prefix entry refers to one of the (root index size)
141  // subindex trees. Hence we have to first compute the corresponding
142  // prefix entry for a single subnode subnode. The we can append
143  // the other prefix entries unmodified, because the index tree
144  // looks the same after the first level.
145  SizePrefix subPrefix;
146  subPrefix.push_back(prefix[0] / children);
147  for(std::size_t i=1; i<prefix.size(); ++i)
148  subPrefix.push_back(prefix[i]);
149  return subPreBasis_.size(subPrefix);
150  }
151 
152  template<class SizePrefix>
153  size_type size(const SizePrefix& prefix, BasisFactory::FlatLexicographic) const
154  {
155  // The size at the index tree root is the size of at the index tree
156  // root of a single subnode multiplied by the number of subnodes
157  // because we enumerate all child indices in a row.
158  if (prefix.size() == 0)
159  return children*subPreBasis_.size();
160 
161  // The first prefix entry refers to one of the (root index size)
162  // subindex trees. Hence we have to first compute the corresponding
163  // prefix entry for a single subnode subnode. The we can append
164  // the other prefix entries unmodified, because the index tree
165  // looks the same after the first level.
166  SizePrefix subPrefix;
167  subPrefix.push_back(prefix[0] % children);
168  for(std::size_t i=1; i<prefix.size(); ++i)
169  subPrefix.push_back(prefix[i]);
170  return subPreBasis_.size(subPrefix);
171  }
172 
173  template<class SizePrefix>
174  size_type size(const SizePrefix& prefix, BasisFactory::BlockedLexicographic) const
175  {
176  if (prefix.size() == 0)
177  return children;
178  SizePrefix subPrefix;
179  for(std::size_t i=1; i<prefix.size(); ++i)
180  subPrefix.push_back(prefix[i]);
181  return subPreBasis_.size(subPrefix);
182  }
183 
184  template<class SizePrefix>
185  size_type size(const SizePrefix& prefix, BasisFactory::BlockedInterleaved) const
186  {
187  if (prefix.size() == 0)
188  return subPreBasis_.size();
189 
190  SizePrefix subPrefix;
191  for(std::size_t i=0; i<prefix.size()-1; ++i)
192  subPrefix.push_back(prefix[i]);
193 
194  size_type r = subPreBasis_.size(subPrefix);
195  if (r==0)
196  return 0;
197  subPrefix.push_back(prefix.back());
198  r = subPreBasis_.size(subPrefix);
199  if (r==0)
200  return children;
201  return r;
202  }
203 
204 public:
205 
208  {
209  return subPreBasis_.dimension() * children;
210  }
211 
214  {
215  return subPreBasis_.maxNodeSize() * children;
216  }
217 
219  const SubPreBasis& subPreBasis() const
220  {
221  return subPreBasis_;
222  }
223 
226  {
227  return subPreBasis_;
228  }
229 
231  template<typename It>
232  It indices(const Node& node, It it) const
233  {
234  return indices(node, it, IndexMergingStrategy{});
235  }
236 
237 private:
238 
239  template<typename It>
240  It indices(const Node& node, It multiIndices, BasisFactory::FlatInterleaved) const
241  {
242  using namespace Dune::Indices;
243  size_type subTreeSize = node.child(_0).size();
244  // Fill indices for first child at the beginning.
245  auto next = subPreBasis().indices(node.child(_0), multiIndices);
246  // Multiply first component of all indices for first child by
247  // number of children to stretch the index range for interleaving.
248  for (std::size_t i = 0; i<subTreeSize; ++i)
249  multiIndices[i][0] *= children;
250  for (std::size_t child = 1; child<children; ++child)
251  {
252  for (std::size_t i = 0; i<subTreeSize; ++i)
253  {
254  // Copy indices from first child for all other children
255  // and shift them by child index to interleave indices.
256  // multiIndices[child*subTreeSize+i] = multiIndices[i];
257  // multiIndices[child*subTreeSize+i][0] = multiIndices[i][0]+child;
258  (*next) = multiIndices[i];
259  (*next)[0] = multiIndices[i][0]+child;
260  ++next;
261  }
262  }
263  return next;
264  }
265 
266  template<typename It>
267  It indices(const Node& node, It multiIndices, BasisFactory::FlatLexicographic) const
268  {
269  using namespace Dune::Indices;
270  size_type subTreeSize = node.child(_0).size();
271  size_type firstIndexEntrySize = subPreBasis().size();
272  // Fill indices for first child at the beginning.
273  auto next = subPreBasis().indices(node.child(_0), multiIndices);
274  for (std::size_t child = 1; child<children; ++child)
275  {
276  for (std::size_t i = 0; i<subTreeSize; ++i)
277  {
278  // Copy indices from first child for all other children
279  // and shift them by suitable offset to get lexicographic indices.
280  // multiIndices[child*subTreeSize+i] = multiIndices[i];
281  // multiIndices[child*subTreeSize+i][0] += child*firstIndexEntrySize;
282  (*next) = multiIndices[i];
283  (*next)[0] += child*firstIndexEntrySize;
284  ++next;
285  }
286  }
287  return next;
288  }
289 
290  template<class MultiIndex>
291  static void multiIndexPushFront(MultiIndex& M, size_type M0)
292  {
293  M.resize(M.size()+1);
294  for(std::size_t i=M.size()-1; i>0; --i)
295  M[i] = M[i-1];
296  M[0] = M0;
297  }
298 
299  template<typename It>
300  It indices(const Node& node, It multiIndices, BasisFactory::BlockedLexicographic) const
301  {
302  using namespace Dune::Indices;
303  size_type subTreeSize = node.child(_0).size();
304  // Fill indices for first child at the beginning.
305  auto next = subPreBasis().indices(node.child(_0), multiIndices);
306  // Insert 0 before first component of all indices for first child.
307  for (std::size_t i = 0; i<subTreeSize; ++i)
308  multiIndexPushFront(multiIndices[i], 0);
309  for (std::size_t child = 1; child<children; ++child)
310  {
311  for (std::size_t i = 0; i<subTreeSize; ++i)
312  {
313  // Copy indices from first child for all other children and overwrite
314  // zero in first component as inserted above by child index.
315  // multiIndices[child*subTreeSize+i] = multiIndices[i];
316  // multiIndices[child*subTreeSize+i][0] = child;
317  (*next) = multiIndices[i];
318  (*next)[0] = child;
319  ++next;
320  }
321  }
322  return next;
323  }
324 
325  template<typename It>
326  It indices(const Node& node, It multiIndices, BasisFactory::BlockedInterleaved) const
327  {
328  using namespace Dune::Indices;
329  size_type subTreeSize = node.child(_0).size();
330  // Fill indices for first child at the beginning.
331  auto next = subPreBasis().indices(node.child(_0), multiIndices);
332  // Append 0 after last component of all indices for first child.
333  for (std::size_t i = 0; i<subTreeSize; ++i)
334  multiIndices[i].push_back(0);
335  for (std::size_t child = 1; child<children; ++child)
336  {
337  for (std::size_t i = 0; i<subTreeSize; ++i)
338  {
339  // Copy indices from first child for all other children and overwrite
340  // zero in last component as appended above by child index.
341  (*next) = multiIndices[i];
342  (*next).back() = child;
343  ++next;
344  }
345  }
346  return next;
347  }
348 
349  SubPreBasis subPreBasis_;
350 };
351 
352 
353 
354 namespace BasisFactory {
355 
368 template<std::size_t k, class ChildPreBasisFactory, class IndexMergingStrategy>
369 auto power(ChildPreBasisFactory&& childPreBasisFactory, const IndexMergingStrategy&)
370 {
371  return [childPreBasisFactory](const auto& gridView) {
372  auto childPreBasis = childPreBasisFactory(gridView);
374  };
375 }
376 
387 template<std::size_t k, class ChildPreBasisFactory>
388 auto power(ChildPreBasisFactory&& childPreBasisFactory)
389 {
390  return [childPreBasisFactory](const auto& gridView) {
391  auto childPreBasis = childPreBasisFactory(gridView);
392  return PowerPreBasis<BlockedInterleaved, decltype(childPreBasis), k>(std::move(childPreBasis));
393  };
394 }
395 
396 } // end namespace BasisFactory
397 
398 // Backward compatibility
399 namespace BasisBuilder {
400 
401  using namespace BasisFactory;
402 
403 }
404 
405 
406 } // end namespace Functions
407 } // end namespace Dune
408 
409 
410 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_POWERBASIS_HH
A pre-basis for power bases.
Definition: powerbasis.hh:45
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: powerbasis.hh:207
std::size_t size_type
Type used for indices and size information.
Definition: powerbasis.hh:58
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: powerbasis.hh:61
PowerBasisNode< SubNode, children > Node
Template mapping root tree path to type of created tree node.
Definition: powerbasis.hh:66
typename SPB::GridView GridView
The grid view that the FE basis is defined on.
Definition: powerbasis.hh:55
SPB SubPreBasis
The child pre-basis.
Definition: powerbasis.hh:52
SubPreBasis & subPreBasis()
Mutable access to the stored prebasis of the factor in the power space.
Definition: powerbasis.hh:225
void initializeIndices()
Initialize the global indices.
Definition: powerbasis.hh:87
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: powerbasis.hh:93
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: powerbasis.hh:99
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: powerbasis.hh:232
PowerPreBasis(SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: powerbasis.hh:80
const SubPreBasis & subPreBasis() const
Const access to the stored prebasis of the factor in the power space.
Definition: powerbasis.hh:219
size_type size() const
Same as size(prefix) with empty prefix.
Definition: powerbasis.hh:116
Node makeNode() const
Create tree node.
Definition: powerbasis.hh:107
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: powerbasis.hh:213
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: powerbasis.hh:124
A Vector class with statically reserved memory.
Definition: reservedvector.hh:47
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:53
constexpr auto models()
Check if concept is modeled by given types.
Definition: concept.hh:184
constexpr HybridTreePath< T..., std::size_t > push_back(const HybridTreePath< T... > &tp, std::size_t i)
Appends a run time index to a HybridTreePath.
Definition: treepath.hh:281
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
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:51
Dune namespace.
Definition: alignedallocator.hh:13
constexpr Base power(Base m, Exponent p)
Power method for integer exponents.
Definition: math.hh:75
An stl-compliant random-access container which stores everything on the stack.
Interleaved merging of direct children without blocking.
Definition: basistags.hh:114
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:44
Utilities for type computations, constraining overloads, ...
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)