3#ifndef DUNE_PDELAB_ORDERING_INTERLEAVEDORDERING_HH
4#define DUNE_PDELAB_ORDERING_INTERLEAVEDORDERING_HH
9#include <dune/typetree/compositenode.hh>
10#include <dune/typetree/powernode.hh>
14#include <dune/pdelab/gridfunctionspace/tags.hh>
15#include <dune/pdelab/ordering/utility.hh>
16#include <dune/pdelab/ordering/orderingbase.hh>
24 namespace interleaved_ordering {
27 template<
typename DI,
typename CI,
typename Node>
29 :
public OrderingBase<DI,CI>
32 typedef OrderingBase<DI,CI> BaseT;
36 typedef typename OrderingBase<DI,CI>::Traits Traits;
40 static const bool consume_tree_index =
true;
48 Base(Node& node,
bool container_blocked,
const OrderingTag& ordering_tag,
typename BaseT::GFSData* gfs_data)
49 : BaseT(node,container_blocked,ordering_tag.offsets(),gfs_data,nullptr)
54 if (node.degree() + 1 != ordering_tag.
offsets().size())
56 "Invalid block structure for InterleavedOrdering: "
57 << node.degree() <<
" children, but "
58 << (ordering_tag.
offsets().size() - 1) <<
" block sizes.");
61 template<
typename ItIn,
typename ItOut>
62 void map_lfs_indices(
const ItIn begin,
const ItIn end, ItOut out)
const
64 typedef typename Traits::SizeType size_type;
65 if (this->_container_blocked)
67 for (ItIn in = begin; in != end; ++in, ++out)
69 size_type child_index = in->treeIndex().back();
70 size_type child_block_offset = this->_child_block_merge_offsets[child_index];
71 size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
72 size_type index = out->back();
73 size_type block_index = index / child_block_size;
74 size_type offset = index % child_block_size;
75 size_type block_offset = child_block_offset + offset;
76 out->back() = block_offset;
77 out->push_back(block_index);
82 for (ItIn in = begin; in != end; ++in, ++out)
84 size_type child_index = in->treeIndex().back();
85 size_type child_block_offset = this->_child_block_merge_offsets[child_index];
86 size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
87 size_type block_size = this->_child_block_merge_offsets.back();
88 size_type index = out->back();
89 size_type block_index = index / child_block_size;
90 size_type offset = index % child_block_size;
91 size_type block_offset = child_block_offset + offset;
92 out->back() = block_index * block_size + block_offset;
97 template<
typename CIOutIterator,
typename DIOutIterator = DummyDOFIndexIterator>
98 typename Traits::SizeType
99 extract_entity_indices(
const typename Traits::DOFIndex::EntityIndex& ei,
100 typename Traits::SizeType child_index,
101 CIOutIterator ci_out,
const CIOutIterator ci_end)
const
103 typedef typename Traits::SizeType size_type;
104 if (this->_container_blocked)
106 for (; ci_out != ci_end; ++ci_out)
108 size_type child_block_offset = this->_child_block_merge_offsets[child_index];
109 size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
110 size_type index = ci_out->back();
111 size_type block_index = index / child_block_size;
112 size_type offset = index % child_block_size;
113 size_type block_offset = child_block_offset + offset;
114 ci_out->back() = block_offset;
115 ci_out->push_back(block_index);
120 for (; ci_out != ci_end; ++ci_out)
122 size_type child_block_offset = this->_child_block_merge_offsets[child_index];
123 size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
124 size_type block_size = this->_child_block_merge_offsets.back();
125 size_type index = ci_out->back();
126 size_type block_index = index / child_block_size;
127 size_type offset =index % child_block_size;
128 ci_out->back() = block_index * block_size + child_block_offset + offset;
138 typename Traits::SizeType size(
typename Traits::ContainerIndex suffix)
const
140 if (suffix.size() == 0)
141 return this->_block_count;
144 const auto& block_size = this->_child_block_merge_offsets.back();
150 if (this->containerBlocked()) {
151 block_index = suffix.back();
152 if (suffix.size() == 1) {
153 assert(block_index < this->_block_count);
157 block_offset = suffix.back();
158 assert(block_offset < block_size);
160 block_index = suffix.back() / block_size;
161 assert(block_index < this->_block_count);
162 block_offset = suffix.back() % block_size;
164 assert(block_index < this->_child_block_offsets.back());
166 const auto& merge_begin = std::begin(this->_child_block_merge_offsets);
167 const auto& merge_end = std::end(this->_child_block_merge_offsets);
169 auto child_block_offset_it = std::prev(std::upper_bound(merge_begin, merge_end, block_offset));
171 std::size_t child_index = std::distance(merge_begin, child_block_offset_it);
173 auto child_block_offset = *child_block_offset_it;
175 auto child_block_size = *std::next(child_block_offset_it) - child_block_offset;
178 suffix.back() = child_block_size * block_index + block_offset;
181 assert(node().
degree() > child_index);
182 if constexpr (Node::isPower)
183 return node().child(child_index).size(suffix);
185 typename Traits::SizeType _size;
188 if (i == child_index)
189 _size = node().
child(i).size(suffix);
197 const Node& node()
const {
return static_cast<const Node&
>(*this); }
198 Node& node() {
return static_cast<Node&
>(*this); }
204 template<
typename DI,
typename CI,
typename Child, std::
size_t k>
205 class PowerInterleavedOrdering
206 :
public TypeTree::PowerNode<Child, k>
207 ,
public interleaved_ordering::Base<DI,
209 PowerInterleavedOrdering<DI,CI,Child,k>
212 typedef TypeTree::PowerNode<Child, k> Node;
214 typedef interleaved_ordering::Base<DI,
216 PowerInterleavedOrdering<DI,CI,Child,k>
230 PowerInterleavedOrdering(
bool container_blocked,
const InterleavedOrderingTag& ordering_tag,
const typename Node::NodeStorage& children,
typename Base::GFSData* gfs_data)
232 , Base(*this,container_blocked,ordering_tag,gfs_data)
237 for (std::size_t i = 0; i < k; ++i)
239 this->
child(i).update();
244 std::string name()
const {
return "PowerInterleavedOrdering"; }
248 template<
typename GFS,
typename Transformation>
249 struct power_gfs_to_interleaved_ordering_descriptor
252 static const bool recursive =
true;
254 template<
typename TC>
258 typedef PowerInterleavedOrdering<
259 typename Transformation::DOFIndex,
260 typename Transformation::ContainerIndex,
262 TypeTree::StaticDegree<GFS>::value
265 typedef std::shared_ptr<type> storage_type;
269 template<
typename TC>
270 static typename result<TC>::type transform(
const GFS& gfs,
const Transformation& t,
const std::array<std::shared_ptr<TC>,TypeTree::StaticDegree<GFS>::value>& children)
272 return typename result<TC>::type(gfs.backend().blocked(gfs),gfs.orderingTag(),children,
const_cast<GFS*
>(&gfs));
275 template<
typename TC>
276 static typename result<TC>::storage_type transform_storage(std::shared_ptr<const GFS> gfs,
const Transformation& t,
const std::array<std::shared_ptr<TC>,TypeTree::StaticDegree<GFS>::value>& children)
278 return std::make_shared<typename result<TC>::type>(gfs->backend().blocked(*gfs),gfs->orderingTag(),children,
const_cast<GFS*
>(gfs.get()));
283 template<
typename GFS,
typename Transformation>
284 power_gfs_to_interleaved_ordering_descriptor<GFS,Transformation>
285 register_power_gfs_to_ordering_descriptor(GFS*,Transformation*,InterleavedOrderingTag*);
289 template<
typename DI,
typename CI,
typename... Children>
290 class CompositeInterleavedOrdering :
291 public TypeTree::CompositeNode<Children...>,
292 public interleaved_ordering::Base<DI,
294 CompositeInterleavedOrdering<
301 typedef TypeTree::CompositeNode<Children...> Node;
303 typedef interleaved_ordering::Base<
306 CompositeInterleavedOrdering<
323 CompositeInterleavedOrdering(
bool backend_blocked,
const InterleavedOrderingTag& ordering_tag,
typename Base::GFSData* gfs_data, std::shared_ptr<Children>... children)
325 , Base(*this,backend_blocked,ordering_tag,gfs_data)
328 std::string name()
const {
return "CompositeInterleavedOrdering"; }
337 template<
typename GFS,
typename Transformation>
338 struct composite_gfs_to_interleaved_ordering_descriptor
341 static const bool recursive =
true;
343 template<
typename... TC>
347 typedef CompositeInterleavedOrdering<
348 typename Transformation::DOFIndex,
349 typename Transformation::ContainerIndex,
353 typedef std::shared_ptr<type> storage_type;
357 template<
typename... TC>
358 static typename result<TC...>::type transform(
const GFS& gfs,
const Transformation& t, std::shared_ptr<TC>... children)
360 return typename result<TC...>::type(gfs.backend().blocked(gfs),gfs.orderingTag(),
const_cast<GFS*
>(&gfs),children...);
363 template<
typename... TC>
364 static typename result<TC...>::storage_type transform_storage(std::shared_ptr<const GFS> gfs,
const Transformation& t, std::shared_ptr<TC>... children)
366 return std::make_shared<
typename result<TC...>::type>(gfs->backend().blocked(*gfs),gfs.orderingTag(),
const_cast<GFS*
>(gfs.get()),children...);
371 template<
typename GFS,
typename Transformation>
372 composite_gfs_to_interleaved_ordering_descriptor<GFS,Transformation>
373 register_composite_gfs_to_ordering_descriptor(GFS*,Transformation*,InterleavedOrderingTag*);
Error related to the logical structure of an Ordering.
Definition: exceptions.hh:46
Interface for merging index spaces.
Definition: interleavedordering.hh:30
Base(Node &node, bool container_blocked, const OrderingTag &ordering_tag, typename BaseT::GFSData *gfs_data)
Construct ordering object.
Definition: interleavedordering.hh:48
std::array< std::shared_ptr< Child >, k > NodeStorage
The type used for storing the children.
Definition: powernode.hh:77
PDELab-specific exceptions.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:79
void applyToTree(Tree &&tree, Visitor &&visitor)
Apply visitor to TypeTree.
Definition: traversal.hh:239
Dune namespace.
Definition: alignedallocator.hh:13
Indicate interleaved ordering of the unknowns of non-leaf grid function spaces according to a given b...
Definition: tags.hh:79
const std::vector< std::size_t > & offsets() const
Returns a list of offsets for the child blocks.
Definition: tags.hh:115