DUNE-FUNCTIONS (unstable)

dynamicpowerbasis.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_DYNAMICPOWERBASIS_HH
4 #define DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
5 
6 #include <dune/common/reservedvector.hh>
7 #include <dune/common/typeutilities.hh>
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/containerdescriptors.hh>
14 #include <dune/functions/functionspacebases/nodes.hh>
15 #include <dune/functions/functionspacebases/concepts.hh>
16 
17 
18 
19 namespace Dune {
20 namespace Functions {
21 
22 
23 // *****************************************************************************
24 // This is the reusable part of the dynamic power bases. It contains
25 //
26 // DynamicPowerPreBasis
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 
42 template<class IMS, class SPB>
44 {
45  static const bool isBlocked = std::is_same_v<IMS,BasisFactory::BlockedLexicographic> or std::is_same_v<IMS,BasisFactory::BlockedInterleaved>;
46 
47 public:
48 
50  using SubPreBasis = SPB;
51 
53  using GridView = typename SPB::GridView;
54 
56  using size_type = std::size_t;
57 
59  using IndexMergingStrategy = IMS;
60 
62  using Node = DynamicPowerBasisNode<typename SubPreBasis::Node>;
63 
64  static constexpr size_type maxMultiIndexSize = SubPreBasis::maxMultiIndexSize + isBlocked;
65  static constexpr size_type minMultiIndexSize = SubPreBasis::minMultiIndexSize + isBlocked;
66  static constexpr size_type multiIndexBufferSize = SubPreBasis::multiIndexBufferSize + isBlocked;
67 
73  template<class... SFArgs,
74  disableCopyMove<DynamicPowerPreBasis, SFArgs...> = 0,
75  enableIfConstructible<SubPreBasis, SFArgs...> = 0>
76  explicit DynamicPowerPreBasis(std::size_t c, SFArgs&&... sfArgs) :
77  children_(c),
78  subPreBasis_(std::forward<SFArgs>(sfArgs)...)
79  {
80  static_assert(models<Concept::PreBasis<GridView>, SubPreBasis>(), "Subprebasis passed to DynamicPowerPreBasis does not model the PreBasis concept.");
81  }
82 
85  {
86  subPreBasis_.initializeIndices();
87  }
88 
90  const GridView& gridView() const
91  {
92  return subPreBasis_.gridView();
93  }
94 
96  void update(const GridView& gv)
97  {
98  subPreBasis_.update(gv);
99  }
100 
104  Node makeNode() const
105  {
106  auto node = Node{children_};
107  for (std::size_t i=0; i<children_; ++i)
108  node.setChild(i, subPreBasis_.makeNode());
109  return node;
110  }
111 
112  std::size_t children() const
113  {
114  return children_;
115  }
116 
118  size_type size() const
119  {
120  return size(Dune::ReservedVector<size_type, multiIndexBufferSize>{});
121  }
122 
124  template<class SizePrefix>
125  size_type size(const SizePrefix& prefix) const
126  {
127  return sizeImpl(prefix, children_, IndexMergingStrategy{});
128  }
129 
130 protected:
131 
132  template<class SizePrefix, class Children>
133  size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatInterleaved) const
134  {
135  // The root index size is the root index size of a single subnode
136  // multiplied by the number of subnodes, because we enumerate all
137  // child indices in a row.
138  if (prefix.size() == 0)
139  return children*subPreBasis_.size();
140 
141  // The FlatInterleaved index merging strategy only changes the first
142  // index digit. Hence, we have to reconstruct the corresponding digit
143  // for the subtree and can then return the corresponding size of the subtree.
144  prefix[0] = prefix[0] / children;
145  return subPreBasis_.size(prefix);
146  }
147 
148  template<class SizePrefix, class Children>
149  size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::FlatLexicographic) const
150  {
151  // The size at the index tree root is the size of at the index tree
152  // root of a single subnode multiplied by the number of subnodes,
153  // because we enumerate all child indices in a row.
154  if (prefix.size() == 0)
155  return children*subPreBasis_.size();
156 
157  // The first prefix entry refers to one of the (root index size)
158  // subindex trees. Hence, we have to first compute the corresponding
159  // prefix entry for a single subnode subnode. Then we can append
160  // the other prefix entries unmodified, because the index tree
161  // looks the same after the first level.
162 
163  // The FlatLexicographic index merging strategy only changes the first
164  // index digit. Hence, we have to reconstruct the corresponding digit
165  // for the subtree and can then return the corresponding size of the subtree.
166  prefix[0] = prefix[0] % subPreBasis_.size();
167  return subPreBasis_.size(prefix);
168  }
169 
170  template<class MultiIndex>
171  static void multiIndexPopFront(MultiIndex& M)
172  {
173  for(std::size_t i=0; i<M.size()-1; ++i)
174  M[i] = M[i+1];
175  M.resize(M.size()-1);
176  }
177 
178  template<class SizePrefix, class Children>
179  size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedLexicographic) const
180  {
181  if (prefix.size() == 0)
182  return children;
183  multiIndexPopFront(prefix);
184  return subPreBasis_.size(prefix);
185  }
186 
187  template<class SizePrefix, class Children>
188  size_type sizeImpl(SizePrefix prefix, Children children, BasisFactory::BlockedInterleaved) const
189  {
190  if (prefix.size() == 0)
191  return subPreBasis_.size();
192 
193  // Remember last index, remove it and check if the remaining
194  // prefix refers to a leaf in the subPreBasis index tree.
195  // If yes, then the full prefix must also refer to a
196  // leaf in the merged index tree. If not, then restore the full
197  // prefix and proceed.
198  auto tail = prefix.back();
199  prefix.pop_back();
200  if (subPreBasis_.size(prefix) == 0)
201  return 0;
202  prefix.push_back(tail);
203 
204  // Now check if the full prefix refers to a leaf in the subPreBasis
205  // index tree.
206  // If yes, then it has exactly 'children' appended children in the subtree.
207  // If not, then the index tree looks the same in the merged subtree and we
208  // can forward the result.
209  auto subSize = subPreBasis_.size(prefix);
210  if (subSize == 0)
211  return children;
212  return subSize;
213  }
214 
215 public:
216 
219  {
220  return subPreBasis_.dimension() * children_;
221  }
222 
225  {
226  return subPreBasis_.maxNodeSize() * children_;
227  }
228 
230  const SubPreBasis& subPreBasis() const
231  {
232  return subPreBasis_;
233  }
234 
237  {
238  return subPreBasis_;
239  }
240 
242  template<class NodeType, typename It,
243  std::enable_if_t<NodeType::isPower, int> = 0>
244  It indices(const NodeType& node, It it) const
245  {
246  return indicesImpl(node, it, children_, IndexMergingStrategy{});
247  }
248 
250  auto containerDescriptor() const
251  {
252  return containerDescriptorImpl(children_);
253  }
254 
255 protected:
256 
257  template<class NodeType, typename It, class Children>
258  It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::FlatInterleaved) const
259  {
260  using namespace Dune::Indices;
261  size_type subTreeSize = node.child(_0).size();
262  // Fill indices for first child at the beginning.
263  auto next = subPreBasis().indices(node.child(_0), multiIndices);
264  // Multiply first component of all indices for first child by
265  // number of children to stretch the index range for interleaving.
266  for (std::size_t i = 0; i<subTreeSize; ++i)
267  multiIndices[i][0] *= children;
268  for (std::size_t child = 1; child<children; ++child)
269  {
270  for (std::size_t i = 0; i<subTreeSize; ++i)
271  {
272  // Copy indices from first child for all other children
273  // and shift them by child index to interleave indices.
274  // multiIndices[child*subTreeSize+i] = multiIndices[i];
275  // multiIndices[child*subTreeSize+i][0] = multiIndices[i][0]+child;
276  (*next) = multiIndices[i];
277  (*next)[0] = multiIndices[i][0]+child;
278  ++next;
279  }
280  }
281  return next;
282  }
283 
284  template<class NodeType, typename It, class Children>
285  It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::FlatLexicographic) const
286  {
287  using namespace Dune::Indices;
288  size_type subTreeSize = node.child(_0).size();
289  size_type firstIndexEntrySize = subPreBasis().size();
290  // Fill indices for first child at the beginning.
291  auto next = subPreBasis().indices(node.child(_0), multiIndices);
292  for (std::size_t child = 1; child<children_; ++child)
293  {
294  for (std::size_t i = 0; i<subTreeSize; ++i)
295  {
296  // Copy indices from first child for all other children
297  // and shift them by suitable offset to get lexicographic indices.
298  // multiIndices[child*subTreeSize+i] = multiIndices[i];
299  // multiIndices[child*subTreeSize+i][0] += child*firstIndexEntrySize;
300  (*next) = multiIndices[i];
301  (*next)[0] += child*firstIndexEntrySize;
302  ++next;
303  }
304  }
305  return next;
306  }
307 
308  template<class MultiIndex>
309  static void multiIndexPushFront(MultiIndex& M, size_type M0)
310  {
311  M.resize(M.size()+1);
312  for(std::size_t i=M.size()-1; i>0; --i)
313  M[i] = M[i-1];
314  M[0] = M0;
315  }
316 
317  template<class NodeType, typename It, class Children>
318  It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedLexicographic) const
319  {
320  using namespace Dune::Indices;
321  size_type subTreeSize = node.child(_0).size();
322  // Fill indices for first child at the beginning.
323  auto next = subPreBasis().indices(node.child(_0), multiIndices);
324  // Insert 0 before first component of all indices for first child.
325  for (std::size_t i = 0; i<subTreeSize; ++i)
326  multiIndexPushFront(multiIndices[i], 0);
327  for (std::size_t child = 1; child<children_; ++child)
328  {
329  for (std::size_t i = 0; i<subTreeSize; ++i)
330  {
331  // Copy indices from first child for all other children and overwrite
332  // zero in first component as inserted above by child index.
333  // multiIndices[child*subTreeSize+i] = multiIndices[i];
334  // multiIndices[child*subTreeSize+i][0] = child;
335  (*next) = multiIndices[i];
336  (*next)[0] = child;
337  ++next;
338  }
339  }
340  return next;
341  }
342 
343  template<class NodeType, typename It, class Children>
344  It indicesImpl(const NodeType& node, It multiIndices, Children children, BasisFactory::BlockedInterleaved) const
345  {
346  using namespace Dune::Indices;
347  size_type subTreeSize = node.child(_0).size();
348  // Fill indices for first child at the beginning.
349  auto next = subPreBasis().indices(node.child(_0), multiIndices);
350  // Append 0 after last component of all indices for first child.
351  for (std::size_t i = 0; i<subTreeSize; ++i)
352  multiIndices[i].push_back(0);
353  for (std::size_t child = 1; child<children_; ++child)
354  {
355  for (std::size_t i = 0; i<subTreeSize; ++i)
356  {
357  // Copy indices from first child for all other children and overwrite
358  // zero in last component as appended above by child index.
359  (*next) = multiIndices[i];
360  (*next).back() = child;
361  ++next;
362  }
363  }
364  return next;
365  }
366 
367  template<class Children>
368  auto containerDescriptorImpl(Children children) const
369  {
370  auto subTree = Dune::Functions::containerDescriptor(subPreBasis_);
371  if constexpr(std::is_same_v<IMS, BasisFactory::FlatInterleaved>)
372  return ContainerDescriptors::Unknown{}; // Not yet implemented
373  else if constexpr(std::is_same_v<IMS, BasisFactory::FlatLexicographic>)
374  return ContainerDescriptors::Unknown{}; // Not yet implemented
375  else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedLexicographic>)
376  return ContainerDescriptors::makeUniformDescriptor(children,std::move(subTree));
377  else if constexpr(std::is_same_v<IMS, BasisFactory::BlockedInterleaved>)
378  return ContainerDescriptors::Unknown{}; // Not yet implemented
379  else
380  return ContainerDescriptors::Unknown{};
381  }
382 
383 protected:
384  std::size_t children_;
385  SubPreBasis subPreBasis_;
386 };
387 
388 
389 
390 namespace BasisFactory {
391 
404 template<class ChildPreBasisFactory, class IndexMergingStrategy>
405 auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k, const IndexMergingStrategy&)
406 {
407  return [childPreBasisFactory,k](const auto& gridView) {
408  auto childPreBasis = childPreBasisFactory(gridView);
410  };
411 }
412 
423 template<class ChildPreBasisFactory>
424 auto power(ChildPreBasisFactory&& childPreBasisFactory, std::size_t k)
425 {
426  return [childPreBasisFactory,k](const auto& gridView) {
427  auto childPreBasis = childPreBasisFactory(gridView);
429  };
430 }
431 
432 } // end namespace BasisFactory
433 
434 } // end namespace Functions
435 } // end namespace Dune
436 
437 
438 #endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_DYNAMICPOWERBASIS_HH
A pre-basis for dynamic power bases.
Definition: dynamicpowerbasis.hh:44
std::size_t size_type
Type used for indices and size information.
Definition: dynamicpowerbasis.hh:56
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child factories.
Definition: dynamicpowerbasis.hh:59
DynamicPowerPreBasis(std::size_t c, SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: dynamicpowerbasis.hh:76
SubPreBasis & subPreBasis()
Mutable access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:236
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: dynamicpowerbasis.hh:218
It indices(const NodeType &node, It it) const
Maps from subtree index set [0..size-1] to a globally unique multi index in global basis.
Definition: dynamicpowerbasis.hh:244
void initializeIndices()
Initialize the global indices.
Definition: dynamicpowerbasis.hh:84
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: dynamicpowerbasis.hh:96
auto containerDescriptor() const
Return the associated container descriptor.
Definition: dynamicpowerbasis.hh:250
size_type size() const
Same as size(prefix) with empty prefix.
Definition: dynamicpowerbasis.hh:118
SPB SubPreBasis
The child pre-basis.
Definition: dynamicpowerbasis.hh:50
Node makeNode() const
Create tree node.
Definition: dynamicpowerbasis.hh:104
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: dynamicpowerbasis.hh:224
const SubPreBasis & subPreBasis() const
Const access to the stored prebasis of the factor in the power space.
Definition: dynamicpowerbasis.hh:230
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: dynamicpowerbasis.hh:90
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: dynamicpowerbasis.hh:125
DynamicPowerBasisNode< typename SubPreBasis::Node > Node
Template mapping root tree path to type of created tree node.
Definition: dynamicpowerbasis.hh:62
typename SPB::GridView GridView
The grid view that the FE basis is defined on.
Definition: dynamicpowerbasis.hh:53
auto power(ChildPreBasisFactory &&childPreBasisFactory, std::size_t k)
Create a factory builder that can build a PowerPreBasis.
Definition: dynamicpowerbasis.hh:424
std::enable_if_t< std::is_constructible_v< T, Args... >, int > enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:27
Definition: polynomial.hh:13
Interleaved merging of direct children without blocking.
Definition: basistags.hh:114
Base class for index merging strategies to simplify detection.
Definition: basistags.hh:44
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)