dune-pdelab  2.0.0
interleavedordering.hh
Go to the documentation of this file.
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_PDELAB_ORDERING_INTERLEAVEDORDERING_HH
4 #define DUNE_PDELAB_ORDERING_INTERLEAVEDORDERING_HH
5 
6 #include <string>
7 
8 #include <dune/typetree/compositenodemacros.hh>
9 #include <dune/typetree/powernode.hh>
10 
12 
16 
17 namespace Dune {
18  namespace PDELab {
19 
22 
23  namespace interleaved_ordering {
24 
26  template<typename DI, typename CI, typename Node>
27  class Base
28  : public OrderingBase<DI,CI>
29  {
30 
31  typedef OrderingBase<DI,CI> BaseT;
32 
33  public:
34 
36 
38 
39  static const bool consume_tree_index = true;
40 
42 
47  Base(Node& node, bool container_blocked, const OrderingTag& ordering_tag, typename BaseT::GFSData* gfs_data)
48  : BaseT(node,container_blocked,ordering_tag.offsets(),gfs_data,nullptr)
49  {
50  // This check looks a little weird, but there is always one offset more than
51  // there are blocks (the first offsets is 0, and the last one is the "offset
52  // beyond the end" to encode the size of the final child).
53  if (node.CHILDREN != ordering_tag.offsets().size() - 1)
54  DUNE_THROW(OrderingStructureError,
55  "Invalid block structure for InterleavedOrdering: "
56  << node.CHILDREN << " children, but "
57  << (ordering_tag.offsets().size() - 1) << " block sizes.");
58  }
59 
60  template<typename ItIn, typename ItOut>
61  void map_lfs_indices(const ItIn begin, const ItIn end, ItOut out) const
62  {
63  typedef typename Traits::SizeType size_type;
64  if (this->_container_blocked)
65  {
66  for (ItIn in = begin; in != end; ++in, ++out)
67  {
68  size_type child_index = in->treeIndex().back();
69  size_type child_block_offset = this->_child_block_merge_offsets[child_index];
70  size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
71  size_type index = out->back();
72  size_type block_index = index / child_block_size;
73  size_type offset = index % child_block_size;
74  out->back() = child_block_offset + offset;
75  out->push_back(block_index);
76  }
77  }
78  else
79  {
80  for (ItIn in = begin; in != end; ++in, ++out)
81  {
82  size_type child_index = in->treeIndex().back();
83  size_type child_block_offset = this->_child_block_merge_offsets[child_index];
84  size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
85  size_type block_size = this->_child_block_merge_offsets.back();
86  size_type index = out->back();
87  size_type block_index = index / child_block_size;
88  size_type offset = index % child_block_size;
89  out->back() = block_index * block_size + child_block_offset + offset;
90  }
91  }
92  }
93 
94  template<typename CIOutIterator, typename DIOutIterator = DummyDOFIndexIterator>
95  typename Traits::SizeType
96  extract_entity_indices(const typename Traits::DOFIndex::EntityIndex& ei,
97  typename Traits::SizeType child_index,
98  CIOutIterator ci_out, const CIOutIterator ci_end) const
99  {
100  typedef typename Traits::SizeType size_type;
101  if (this->_container_blocked)
102  {
103  for (; ci_out != ci_end; ++ci_out)
104  {
105  size_type child_block_offset = this->_child_block_merge_offsets[child_index];
106  size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
107  size_type index = ci_out->back();
108  size_type block_index = index / child_block_size;
109  size_type offset =index % child_block_size;
110  ci_out->back() = child_block_offset + offset;
111  ci_out->push_back(block_index);
112  }
113  }
114  else
115  {
116  for (; ci_out != ci_end; ++ci_out)
117  {
118  size_type child_block_offset = this->_child_block_merge_offsets[child_index];
119  size_type child_block_size = this->_child_block_merge_offsets[child_index + 1] - child_block_offset;
120  size_type block_size = this->_child_block_merge_offsets.back();
121  size_type index = ci_out->back();
122  size_type block_index = index / child_block_size;
123  size_type offset =index % child_block_size;
124  ci_out->back() = block_index * block_size + child_block_offset + offset;
125  }
126  }
127 
128  // The return value is not used for non-leaf orderings.
129  return 0;
130  }
131 
132  };
133 
134  } // namespace interleaved_ordering
135 
136 
137  template<typename DI, typename CI, typename Child, std::size_t k>
139  : public TypeTree::PowerNode<Child, k>
140  , public interleaved_ordering::Base<DI,
141  CI,
142  PowerInterleavedOrdering<DI,CI,Child,k>
143  >
144  {
145  typedef TypeTree::PowerNode<Child, k> Node;
146 
147  typedef interleaved_ordering::Base<DI,
148  CI,
150  > Base;
151 
152  public:
153 
155 
163  PowerInterleavedOrdering(bool container_blocked, const InterleavedOrderingTag& ordering_tag, const typename Node::NodeStorage& children, typename Base::GFSData* gfs_data)
164  : Node(children)
165  , Base(*this,container_blocked,ordering_tag,gfs_data)
166  {}
167 
168  void update()
169  {
170  for (std::size_t i = 0; i < Node::CHILDREN; ++i)
171  {
172  this->child(i).update();
173  }
174  Base::update();
175  }
176 
177  std::string name() const { return "PowerInterleavedOrdering"; }
178  };
179 
180 
181  template<typename GFS, typename Transformation>
183  {
184 
185  static const bool recursive = true;
186 
187  template<typename TC>
188  struct result
189  {
190 
191  typedef PowerInterleavedOrdering<
192  typename Transformation::DOFIndex,
193  typename Transformation::ContainerIndex,
194  TC,
195  GFS::CHILDREN
196  > type;
197 
198  typedef shared_ptr<type> storage_type;
199 
200  };
201 
202  template<typename TC>
203  static typename result<TC>::type transform(const GFS& gfs, const Transformation& t, const array<shared_ptr<TC>,GFS::CHILDREN>& children)
204  {
205  return typename result<TC>::type(gfs.backend().blocked(gfs),gfs.orderingTag(),children,const_cast<GFS*>(&gfs));
206  }
207 
208  template<typename TC>
209  static typename result<TC>::storage_type transform_storage(shared_ptr<const GFS> gfs, const Transformation& t, const array<shared_ptr<TC>,GFS::CHILDREN>& children)
210  {
211  return make_shared<typename result<TC>::type>(gfs->backend().blocked(*gfs),gfs->orderingTag(),children,const_cast<GFS*>(gfs.get()));
212  }
213 
214  };
215 
216  template<typename GFS, typename Transformation>
217  power_gfs_to_interleaved_ordering_descriptor<GFS,Transformation>
218  register_power_gfs_to_ordering_descriptor(GFS*,Transformation*,InterleavedOrderingTag*);
219 
220 
221 
222  template<typename DI, typename CI, DUNE_TYPETREE_COMPOSITENODE_TEMPLATE_CHILDREN>
224  public DUNE_TYPETREE_COMPOSITENODE_BASETYPE,
225  public interleaved_ordering::Base<DI,
226  CI,
227  CompositeInterleavedOrdering<
228  DI,
229  CI,
230  DUNE_TYPETREE_COMPOSITENODE_CHILDTYPES
231  >
232  >
233  {
234  typedef DUNE_TYPETREE_COMPOSITENODE_BASETYPE Node;
235 
237  DI,
238  CI,
240  DI,
241  CI,
242  DUNE_TYPETREE_COMPOSITENODE_CHILDTYPES
243  >
244  > Base;
245 
246  public:
248 
256  CompositeInterleavedOrdering(bool backend_blocked, const InterleavedOrderingTag& ordering_tag, typename Base::GFSData* gfs_data, DUNE_TYPETREE_COMPOSITENODE_STORAGE_CONSTRUCTOR_SIGNATURE)
257  : Node(DUNE_TYPETREE_COMPOSITENODE_CHILDVARIABLES)
258  , Base(*this,backend_blocked,ordering_tag,gfs_data)
259  { }
260 
261  std::string name() const { return "CompositeInterleavedOrdering"; }
262 
263  void update()
264  {
265  TypeTree::applyToTree(*this,ordering::update_direct_children());
266  Base::update();
267  }
268  };
269 
270 #if HAVE_VARIADIC_TEMPLATES
271 
272  template<typename GFS, typename Transformation>
273  struct composite_gfs_to_interleaved_ordering_descriptor
274  {
275 
276  static const bool recursive = true;
277 
278  template<typename... TC>
279  struct result
280  {
281 
282  typedef CompositeInterleavedOrdering<
283  typename Transformation::DOFIndex,
284  typename Transformation::ContainerIndex,
285  TC...
286  > type;
287 
288  typedef shared_ptr<type> storage_type;
289 
290  };
291 
292  template<typename... TC>
293  static typename result<TC...>::type transform(const GFS& gfs, const Transformation& t, shared_ptr<TC>... children)
294  {
295  return typename result<TC...>::type(gfs.backend().blocked(gfs),gfs.orderingTag(),const_cast<GFS*>(&gfs),children...);
296  }
297 
298  template<typename... TC>
299  static typename result<TC...>::storage_type transform_storage(shared_ptr<const GFS> gfs, const Transformation& t, shared_ptr<TC>... children)
300  {
301  return make_shared<typename result<TC...>::type>(gfs->backend().blocked(*gfs),gfs.orderingTag(),const_cast<GFS*>(gfs.get()),children...);
302  }
303 
304  };
305 
306 #else // HAVE_VARIADIC_TEMPLATES
307 
309  template<typename GFS, typename Transformation>
311  {
312 
313  static const bool recursive = true;
314 
315  template<typename TC0,
316  typename TC1,
317  typename TC2,
318  typename TC3,
319  typename TC4,
320  typename TC5,
321  typename TC6,
322  typename TC7,
323  typename TC8,
324  typename TC9>
325  struct result
326  {
327  // TODO: FIXME - this has not been changed to new interface yet!
328  typedef CompositeInterleavedOrdering<typename Transformation::GridFunctionSpace::Traits::SizeType,
329  TC0,TC1,TC2,TC3,TC4,TC5,TC6,TC7,TC8,TC9> type;
330  typedef shared_ptr<type> storage_type;
331  };
332 
333  template<typename TC0,
334  typename TC1,
335  typename TC2,
336  typename TC3,
337  typename TC4,
338  typename TC5,
339  typename TC6,
340  typename TC7,
341  typename TC8,
342  typename TC9>
344  transform(const GFSNode& gfs,
345  const Transformation& t,
346  shared_ptr<TC0> c0,
347  shared_ptr<TC1> c1,
348  shared_ptr<TC2> c2,
349  shared_ptr<TC3> c3,
350  shared_ptr<TC4> c4,
351  shared_ptr<TC5> c5,
352  shared_ptr<TC6> c6,
353  shared_ptr<TC7> c7,
354  shared_ptr<TC8> c8,
355  shared_ptr<TC9> c9)
356  {
357  return typename result<TC0,TC1,TC2,TC3,TC4,TC5,TC6,TC7,TC8,TC9>::type(gfs.backend().blocked(gfs),gfs.orderingTag(),c0,c1,c2,c3,c4,c5,c6,c7,c8,c9);
358  }
359 
360  template<typename TC0,
361  typename TC1,
362  typename TC2,
363  typename TC3,
364  typename TC4,
365  typename TC5,
366  typename TC6,
367  typename TC7,
368  typename TC8,
369  typename TC9>
370  static typename result<TC0,TC1,TC2,TC3,TC4,TC5,TC6,TC7,TC8,TC9>::storage_type
371  transform_storage(shared_ptr<const GFSNode> gfs,
372  const Transformation& t,
373  shared_ptr<TC0> c0,
374  shared_ptr<TC1> c1,
375  shared_ptr<TC2> c2,
376  shared_ptr<TC3> c3,
377  shared_ptr<TC4> c4,
378  shared_ptr<TC5> c5,
379  shared_ptr<TC6> c6,
380  shared_ptr<TC7> c7,
381  shared_ptr<TC8> c8,
382  shared_ptr<TC9> c9)
383  {
384  return make_shared<typename result<TC0,TC1,TC2,TC3,TC4,TC5,TC6,TC7,TC8,TC9>::type>(gfs->backend().blocked(*gfs),gfs->orderingTag(),c0,c1,c2,c3,c4,c5,c6,c7,c8,c9);
385  }
386 
387  };
388 
389 #endif // HAVE_VARIADIC_TEMPLATES
390 
391  template<typename GFS, typename Transformation>
392  composite_gfs_to_interleaved_ordering_descriptor<GFS,Transformation>
393  register_composite_gfs_to_ordering_descriptor(GFS*,Transformation*,InterleavedOrderingTag*);
394 
396  } // namespace PDELab
397 } // namespace Dune
398 
399 #endif // DUNE_PDELAB_ORDERING_LEXICOGRAPHICORDERING_HH
Traits::SizeType extract_entity_indices(const typename Traits::DOFIndex::EntityIndex &ei, typename Traits::SizeType child_index, CIOutIterator ci_out, const CIOutIterator ci_end) const
Definition: interleavedordering.hh:96
PowerInterleavedOrdering< typename Transformation::DOFIndex, typename Transformation::ContainerIndex, TC, GFS::CHILDREN > type
Definition: interleavedordering.hh:196
shared_ptr< type > storage_type
Definition: interleavedordering.hh:330
static result< TC >::type transform(const GFS &gfs, const Transformation &t, const array< shared_ptr< TC >, GFS::CHILDREN > &children)
Definition: interleavedordering.hh:203
Definition: interleavedordering.hh:223
std::string name() const
Definition: interleavedordering.hh:177
DI::size_type SizeType
Definition: ordering/utility.hh:201
Interface for merging index spaces.
Definition: interleavedordering.hh:27
Definition: interleavedordering.hh:138
PDELab-specific exceptions.
static const bool recursive
Definition: interleavedordering.hh:185
static const bool recursive
Definition: interleavedordering.hh:313
composite_gfs_to_entityblocked_ordering_descriptor< GFS, Transformation > register_composite_gfs_to_ordering_descriptor(GFS *, Transformation *, EntityBlockedOrderingTag *)
power_gfs_to_entityblocked_ordering_descriptor< GFS, Transformation > register_power_gfs_to_ordering_descriptor(GFS *, Transformation *, EntityBlockedOrderingTag *)
Definition: orderingbase.hh:22
void map_lfs_indices(const ItIn begin, const ItIn end, ItOut out) const
Definition: interleavedordering.hh:61
PowerInterleavedOrdering(bool container_blocked, const InterleavedOrderingTag &ordering_tag, const typename Node::NodeStorage &children, typename Base::GFSData *gfs_data)
Construct ordering object.
Definition: interleavedordering.hh:163
void update()
Definition: interleavedordering.hh:263
static const bool consume_tree_index
Definition: interleavedordering.hh:39
Node transformation descriptor for CompositeGridFunctionSpace -> LexicographicOrdering (without varia...
Definition: interleavedordering.hh:310
OrderingBase< DI, CI >::Traits Traits
Definition: interleavedordering.hh:35
Definition: ordering/utility.hh:186
const std::size_t offset
Definition: localfunctionspace.hh:74
static result< TC >::storage_type transform_storage(shared_ptr< const GFS > gfs, const Transformation &t, const array< shared_ptr< TC >, GFS::CHILDREN > &children)
Definition: interleavedordering.hh:209
Indicate interleaved ordering of the unknowns of non-leaf grid function spaces according to a given b...
Definition: gridfunctionspace/tags.hh:74
InterleavedOrderingTag OrderingTag
Definition: interleavedordering.hh:37
std::vector< typename Traits::SizeType > _child_block_merge_offsets
Definition: orderingbase.hh:283
static result< TC0, TC1, TC2, TC3, TC4, TC5, TC6, TC7, TC8, TC9 >::type transform(const GFSNode &gfs, const Transformation &t, shared_ptr< TC0 > c0, shared_ptr< TC1 > c1, shared_ptr< TC2 > c2, shared_ptr< TC3 > c3, shared_ptr< TC4 > c4, shared_ptr< TC5 > c5, shared_ptr< TC6 > c6, shared_ptr< TC7 > c7, shared_ptr< TC8 > c8, shared_ptr< TC9 > c9)
Definition: interleavedordering.hh:344
static result< TC0, TC1, TC2, TC3, TC4, TC5, TC6, TC7, TC8, TC9 >::storage_type transform_storage(shared_ptr< const GFSNode > gfs, const Transformation &t, shared_ptr< TC0 > c0, shared_ptr< TC1 > c1, shared_ptr< TC2 > c2, shared_ptr< TC3 > c3, shared_ptr< TC4 > c4, shared_ptr< TC5 > c5, shared_ptr< TC6 > c6, shared_ptr< TC7 > c7, shared_ptr< TC8 > c8, shared_ptr< TC9 > c9)
Definition: interleavedordering.hh:371
std::string name() const
Definition: interleavedordering.hh:261
Error related to the logical structure of an Ordering.
Definition: exceptions.hh:44
void update()
Definition: orderingbase.hh:100
CompositeInterleavedOrdering< typename Transformation::GridFunctionSpace::Traits::SizeType, TC0, TC1, TC2, TC3, TC4, TC5, TC6, TC7, TC8, TC9 > type
Definition: interleavedordering.hh:329
void update()
Definition: interleavedordering.hh:168
shared_ptr< type > storage_type
Definition: interleavedordering.hh:198
const bool _container_blocked
Definition: orderingbase.hh:275
CompositeInterleavedOrdering(bool backend_blocked, const InterleavedOrderingTag &ordering_tag, typename Base::GFSData *gfs_data, DUNE_TYPETREE_COMPOSITENODE_STORAGE_CONSTRUCTOR_SIGNATURE)
Construct ordering object.
Definition: interleavedordering.hh:256
Dune::PDELab::impl::GridFunctionSpaceOrderingData< typename Traits::SizeType > GFSData
Definition: orderingbase.hh:35
Base(Node &node, bool container_blocked, const OrderingTag &ordering_tag, typename BaseT::GFSData *gfs_data)
Construct ordering object.
Definition: interleavedordering.hh:47
const std::vector< std::size_t > & offsets() const
Returns a list of offsets for the child blocks.
Definition: gridfunctionspace/tags.hh:115