DUNE-FUNCTIONS (2.8)

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>
11#include <dune/common/reservedvector.hh>
12#include <dune/common/typeutilities.hh>
13#include <dune/common/hybridutilities.hh>
14#include <dune/common/tupleutility.hh>
15#include <dune/common/tuplevector.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
26namespace Dune {
27namespace 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
52template<class MI, class IMS, class... SPB>
54{
55public:
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
72
73protected:
74 static const std::size_t children = sizeof...(SPB);
75
76 using ChildIndices = std::make_index_sequence<children>;
77
78public:
79
81 using Node = CompositeBasisNode<typename SPB::Node...>;
82
84 using IndexSet = Impl::DefaultNodeIndexSet<CompositePreBasis>;
85
87 using MultiIndex = MI;
88
90 using SizePrefix = Dune::ReservedVector<size_type, MultiIndex::max_size()>;
91
97 template<class... SFArgs,
98 disableCopyMove<CompositePreBasis, SFArgs...> = 0,
99 enableIfConstructible<std::tuple<SPB...>, SFArgs...> = 0>
100 CompositePreBasis(SFArgs&&... sfArgs) :
101 subPreBases_(std::forward<SFArgs>(sfArgs)...)
102 {
103 Hybrid::forEach(subPreBases_, [&](const auto& subPreBasis){
104 static_assert(models<Concept::PreBasis<GridView>, std::decay_t<decltype(subPreBasis)>>(), "Subprebases passed to CompositePreBasis does not model the PreBasis concept.");
105 });
106 }
107
110 {
111 Hybrid::forEach(ChildIndices(), [&](auto i) {
112 this->subPreBasis(i).initializeIndices();
113 });
114 }
115
117 const GridView& gridView() const
118 {
119 return std::get<0>(subPreBases_).gridView();
120 }
121
123 void update(const GridView& gv)
124 {
125 Hybrid::forEach(ChildIndices(), [&](auto i) {
126 this->subPreBasis(i).update(gv);
127 });
128 }
129
134 {
135 auto node = Node{};
136 Hybrid::forEach(ChildIndices(), [&](auto i) {
137 node.setChild(this->subPreBasis(i).makeNode(), i);
138 });
139 return node;
140 }
141
149 [[deprecated("Warning: The IndexSet typedef and the makeIndexSet method are deprecated. "\
150 "As a replacement use the indices() method of the PreBasis directly.")]]
152 {
153 return IndexSet{*this};
154 }
155
158 {
159 return size({});
160 }
161
163 size_type size(const SizePrefix& prefix) const
164 {
165 return size(prefix, IndexMergingStrategy{});
166 }
167
168private:
169
171 {
172 if (prefix.size() == 0)
173 return children;
174
175 return Hybrid::switchCases(ChildIndices(), prefix[0], [&] (auto i) {
176 typename SubPreBasis<i>::SizePrefix subPrefix;
177 for(std::size_t i=1; i<prefix.size(); ++i)
178 subPrefix.push_back(prefix[i]);
179 return this->subPreBasis(i).size(subPrefix);
180 }, []() {
181 return size_type(0);
182 });
183 }
184
185 size_type size(const SizePrefix& prefix, BasisFactory::FlatLexicographic) const
186 {
187 size_type result = 0;
188 if (prefix.size() == 0)
189 Hybrid::forEach(ChildIndices(), [&](auto i) {
190 result += this->subPreBasis(i).size();
191 });
192 else {
193 size_type shiftedFirstDigit = prefix[0];
194 staticFindInRange<0, children>([&](auto i) {
195 auto firstDigitSize = this->subPreBasis(i).size();
196 if (shiftedFirstDigit < firstDigitSize)
197 {
198 typename SubPreBasis<i>::SizePrefix subPrefix;
199 subPrefix.push_back(shiftedFirstDigit);
200 for(std::size_t i=1; i<prefix.size(); ++i)
201 subPrefix.push_back(prefix[i]);
202 result = this->subPreBasis(i).size(subPrefix);
203 return true;
204 }
205 shiftedFirstDigit -= firstDigitSize;
206 return false;
207 });
208 }
209 return result;
210 }
211
212public:
213
216 {
217 size_type r=0;
218 // Accumulate dimension() for all subprebases
219 Hybrid::forEach(ChildIndices(), [&](auto i) {
220 r += this->subPreBasis(i).dimension();
221 });
222 return r;
223 }
224
227 {
228 size_type r=0;
229 // Accumulate maxNodeSize() for all subprebases
230 Hybrid::forEach(ChildIndices(), [&](auto i) {
231 r += this->subPreBasis(i).maxNodeSize();
232 });
233 return r;
234 }
235
237 template<std::size_t i>
238 const SubPreBasis<i>& subPreBasis(Dune::index_constant<i> = {}) const
239 {
240 return std::get<i>(subPreBases_);
241 }
242
244 template<std::size_t i>
245 SubPreBasis<i>& subPreBasis(Dune::index_constant<i> = {})
246 {
247 return std::get<i>(subPreBases_);
248 }
249
251 template<typename It>
252 It indices(const Node& node, It it) const
253 {
254 return indices(node, it, IndexMergingStrategy{});
255 }
256
257private:
258
259 template<typename It>
260 It indices(const Node& node, It multiIndices, BasisFactory::FlatLexicographic) const
261 {
262 size_type firstComponentOffset = 0;
263 // Loop over all children
264 Hybrid::forEach(ChildIndices(), [&](auto child){
265 size_type subTreeSize = node.child(child).size();
266 // Fill indices for current child into index buffer starting from current
267 // buffer position and shift first index component of any index for current
268 // child by suitable offset to get lexicographic indices.
269 Impl::preBasisIndices(subPreBasis(child), node.child(child), multiIndices);
270 for (std::size_t i = 0; i<subTreeSize; ++i)
271 multiIndices[i][0] += firstComponentOffset;
272 // Increment offset by the size for first index component of the current child
273 firstComponentOffset += subPreBasis(child).size({});
274 // Increment buffer iterator by the number of indices processed for current child
275 multiIndices += subTreeSize;
276 });
277 return multiIndices;
278 }
279
280 static void multiIndexPushFront(MultiIndex& M, size_type M0)
281 {
282 M.resize(M.size()+1);
283 for(std::size_t i=M.size()-1; i>0; --i)
284 M[i] = M[i-1];
285 M[0] = M0;
286 }
287
288 template<typename It>
289 It indices(const Node& node, It multiIndices, BasisFactory::BlockedLexicographic) const
290 {
291 // Loop over all children
292 Hybrid::forEach(ChildIndices(), [&](auto child){
293 size_type subTreeSize = node.child(child).size();
294 // Fill indices for current child into index buffer starting from current position
295 Impl::preBasisIndices(subPreBasis(child), node.child(child), multiIndices);
296 // Insert child index before first component of all indices of current child.
297 for (std::size_t i = 0; i<subTreeSize; ++i)
298 this->multiIndexPushFront(multiIndices[i], child);
299 // Increment buffer iterator by the number of indices processed for current child
300 multiIndices += subTreeSize;
301 });
302 return multiIndices;
303 }
304
305 std::tuple<SPB...> subPreBases_;
306};
307
308
309
310namespace BasisFactory {
311
312namespace Imp {
313
314template<class ST0>
315constexpr std::size_t maxHelper(ST0&& i0)
316{
317 return i0;
318}
319
320template<class ST0, class... ST>
321constexpr std::size_t maxHelper(ST0&& i0, ST&&... i)
322{
323 return (i0 > maxHelper(i...)) ? i0 : maxHelper(i...);
324}
325
326template<class IndexMergingStrategy, class... ChildPreBasisFactory>
327class CompositePreBasisFactory
328{
329 static const bool isBlocked = std::is_same<IndexMergingStrategy,BlockedLexicographic>::value or std::is_same<IndexMergingStrategy,BlockedInterleaved>::value;
330
331 static const std::size_t maxChildIndexSize = maxHelper(ChildPreBasisFactory::requiredMultiIndexSize...);
332
333 template<class MultiIndex, class GridView, class... ChildPreBasis>
334 auto makePreBasisFromChildPreBases(const GridView&, ChildPreBasis&&... childPreBasis) const
335 {
336 return CompositePreBasis<MultiIndex, IndexMergingStrategy, std::decay_t<ChildPreBasis>...>(std::forward<ChildPreBasis>(childPreBasis)...);
337 }
338
339public:
340
341 static const std::size_t requiredMultiIndexSize = isBlocked ? (maxChildIndexSize+1) : maxChildIndexSize;
342
343 CompositePreBasisFactory(const ChildPreBasisFactory&... childPreBasisFactory) :
344 childPreBasisFactories_(childPreBasisFactory...)
345 {}
346
347 CompositePreBasisFactory(ChildPreBasisFactory&&... childPreBasisFactory) :
348 childPreBasisFactories_(std::move(childPreBasisFactory)...)
349 {}
350
351 template<class MultiIndex, class GridView>
352 auto makePreBasis(const GridView& gridView) const
353 {
354 // Use std::apply to unpack the tuple childPreBasisFactories_
355 return std::apply([&](const auto&... childPreBasisFactory) {
356 return this->makePreBasisFromChildPreBases<MultiIndex>(gridView, childPreBasisFactory.template makePreBasis<MultiIndex>(gridView)...);
357 }, childPreBasisFactories_);
358 }
359
360private:
361 std::tuple<ChildPreBasisFactory...> childPreBasisFactories_;
362};
363
364} // end namespace BasisFactory::Imp
365
366
367
378template<
379 typename... Args,
380 std::enable_if_t<Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
381auto composite(Args&&... args)
382{
383 // We have to separate the last entry which is the IndexMergingStrategy
384 // and the preceding ones, which are the ChildPreBasisFactories
385
386 using ArgTuple = std::tuple<std::decay_t<Args>...>;
387
388 // Compute number of children and index of the IndexMergingStrategy argument
389 constexpr std::size_t children = Dune::SizeOf<Args...>::value-1;
390
391 // Use last type as IndexMergingStrategy
392 using IndexMergingStrategy = std::tuple_element_t<children, ArgTuple>;
393
394 // Index sequence for all but the last entry for partial tuple unpacking
395 auto childIndices = std::make_index_sequence<children>{};
396
397 // Unpack tuple only for those entries related to children
398 return applyPartial([](auto&&... childPreBasisFactory){
399 return Imp::CompositePreBasisFactory<IndexMergingStrategy, std::decay_t<decltype(childPreBasisFactory)>...>(std::forward<decltype(childPreBasisFactory)>(childPreBasisFactory)...);
400 },
401 std::forward_as_tuple(std::forward<Args>(args)...),
402 childIndices);
403}
404
416template<
417 typename... Args,
418 std::enable_if_t<not Concept::isIndexMergingStrategy<typename LastType<Args...>::type>(),int> = 0>
419auto composite(Args&&... args)
420{
421 return Imp::CompositePreBasisFactory<BasisFactory::BlockedLexicographic, std::decay_t<Args>...>(std::forward<Args>(args)...);
422}
423
424} // end namespace BasisFactory
425
426// Backward compatibility
427namespace BasisBuilder {
428
429 using namespace BasisFactory;
430
431}
432
433
434
435} // end namespace Functions
436} // end namespace Dune
437
438
439#endif // DUNE_FUNCTIONS_FUNCTIONSPACEBASES_COMPOSITEBASIS_HH
A pre-basis for composite bases.
Definition: compositebasis.hh:54
typename std::tuple_element_t< 0, SubPreBases >::GridView GridView
The grid view that the FE basis is defined on.
Definition: compositebasis.hh:65
Node makeNode() const
Create tree node.
Definition: compositebasis.hh:133
size_type size() const
Same as size(prefix) with empty prefix.
Definition: compositebasis.hh:157
Dune::ReservedVector< size_type, MultiIndex::max_size()> SizePrefix
Type used for prefixes handed to the size() method.
Definition: compositebasis.hh:90
size_type dimension() const
Get the total dimension of the space spanned by this basis.
Definition: compositebasis.hh:215
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:238
std::size_t size_type
Type used for indices and size information.
Definition: compositebasis.hh:68
size_type size(const SizePrefix &prefix) const
Return number of possible values for next position in multi index.
Definition: compositebasis.hh:163
IndexSet makeIndexSet() const
Create tree node index set.
Definition: compositebasis.hh:151
void update(const GridView &gv)
Update the stored grid view, to be called if the grid has changed.
Definition: compositebasis.hh:123
CompositePreBasis(SFArgs &&... sfArgs)
Constructor for given child pre-basis objects.
Definition: compositebasis.hh:100
Impl::DefaultNodeIndexSet< CompositePreBasis > IndexSet
Type of created tree node index set.
Definition: compositebasis.hh:84
IMS IndexMergingStrategy
Strategy used to merge the global indices of the child pre-bases.
Definition: compositebasis.hh:71
std::tuple_element_t< i, SubPreBases > SubPreBasis
Export individual child pre-bases by index.
Definition: compositebasis.hh:62
MI MultiIndex
Type used for global numbering of the basis vectors.
Definition: compositebasis.hh:87
size_type maxNodeSize() const
Get the maximal number of DOFs associated to node for any element.
Definition: compositebasis.hh:226
SubPreBasis< i > & subPreBasis(Dune::index_constant< i >={})
Mutable access to the stored prebasis of the factor in the power space.
Definition: compositebasis.hh:245
CompositeBasisNode< typename SPB::Node... > Node
Template mapping root tree path to type of created tree node.
Definition: compositebasis.hh:81
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:252
std::tuple< SPB... > SubPreBases
Tuple of child pre-bases.
Definition: compositebasis.hh:58
void initializeIndices()
Initialize the global indices.
Definition: compositebasis.hh:109
const GridView & gridView() const
Obtain the grid view that the basis is defined on.
Definition: compositebasis.hh:117
auto composite(Args &&... args)
Create a factory builder that can build a CompositePreBasis.
Definition: compositebasis.hh:381
typename std::enable_if< std::is_constructible< T, Args... >::value, int >::type enableIfConstructible
Helper to constrain forwarding constructors.
Definition: type_traits.hh:26
Definition: polynomial.hh:10
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)