Flow123d  JS_before_hm-887-g601087d
mixed.hh
Go to the documentation of this file.
1 /*
2  * mixed.hh
3  *
4  * Created on: Apr 8, 2019
5  * Author: jb
6  */
7 
8 #ifndef SRC_TOOLS_MIXED_HH_
9 #define SRC_TOOLS_MIXED_HH_
10 
11 #include <tuple>
12 #include <memory>
13 #include <iostream>
14 #include <type_traits>
15 
16 const int __spacedim = 3;
17 
18 /// A dimension index type.
19 using IntDim = unsigned int;
20 
21 /// Auxiliary class to resolve dimension dependent templates.
22 /// This allow automatic template resolution without specifying template argument explicitly which
23 /// often requires usage of the ugly template keyword before the method call.
24 template <IntDim I>
25 struct Dim {};
26 
27 
28 /**
29  * Implement literals> '0_d', '1_d', ...
30  * constexpr literal '_d' magic
31  *
32  * See: https://arne-mertz.de/2016/10/modern-c-features-user-defined-literals/
33  */
34 template <char... Digits>
35 constexpr std::size_t parse_dim()
36 {
37  // convert to array
38  char digits[] = {Digits...};
39  // take and convert just a single digit
40  // TODO: assert for number of digits
41  return digits[0] - '0';
42 }
43 
44 template <char... Digits>
45 auto operator"" _d()
46 {
47  return Dim<parse_dim<Digits...>()>{};
48 }
49 
50 
51 
52 /***
53  * Basic tuple types.
54  */
55 
56 template<template<IntDim ...> class T>
57 using _MixedBase0 = std::tuple<T<0>, T<1>, T<2>, T<3>>;
58 
59 template<template<IntDim ...> class T>
60 using _MixedBase1 = std::tuple<T<1>, T<2>, T<3>>;
61 
62 
63 template< template<IntDim ...> class T, int lower_dim=0>
64 class Mixed : public _MixedBase0<T> {
65 /**
66  * Template to simplify storing and passing tuples of instances of dimension parametrized templates.
67  * Currently instances for dim = 0,1,2,3 are created. We assume spacedim=3.
68  * Usage:
69  *
70  * fe_order = 10;
71  * auto gauss = Mixed<QGauss>(q_order); // template <int dim> class QGauss;
72  * auto mapping = MixedSpaceDim<Mapping>(); // template <int dim, int spacedim> class Mapping;
73  * ...
74  * fe_values = FEValues<dim>(mapping[Dim<dim>{}], gauss[Dim<dim>{}], ...)
75  *
76  * or
77  *
78  * fe_values = FEValues<dim>(mapping[0_d], gauss[0_d], ...)
79  * fe_values = FEValues<dim>(mapping[1_d], gauss[1_d], ...)
80  * ...
81  *
82  * All parameters of the Mixed<T>(...) constructor are forwarder (by value) to the T(...) constructor for every dimension.
83  * Only forwarding by value is supported due to problems with MixedPtr.
84  * Can not resolve copy constructor correctly.
85  *
86  */
87 public:
88  template < template<IntDim...> class TT>
89  Mixed(const Mixed<TT> &other)
90  : _MixedBase0<T>(
91  T<0>( (other[0_d]) ),
92  T<1>( (other[1_d]) ),
93  T<2>( (other[2_d]) ),
94  T<3>( (other[3_d]) ) )
95  { static_assert(std::is_convertible<TT<0>, T<0>>::value, "Non-convertible types!"); }
96 
97  Mixed(const T<0> &p0,const T<1> &p1,const T<2> &p2,const T<3> &p3)
98  : _MixedBase0<T>(p0, p1, p2, p3)
99  {}
100 
101  Mixed(T<0> &&p0, T<1> &&p1, T<2> &&p2, T<3> &&p3)
102  : _MixedBase0<T>(p0, p1, p2, p3)
103  {}
104 
105 
106  template<typename... Args>
107  Mixed(Args... args)
108  : _MixedBase0<T>(
109  T<0>(std::forward<Args>(args)...),
110  T<1>(std::forward<Args>(args)...),
111  T<2>(std::forward<Args>(args)...),
112  T<3>(std::forward<Args>(args)...))
113  {}
114 
115  /**
116  * Beautiful index/like access inspired by:
117  * https://arne-mertz.de/2017/03/tuple-compile-time-access/
118  */
119  template <IntDim i_dim>
120  T<i_dim> & operator[](Dim<i_dim>)
121  {
122  return std::get<i_dim>(*this);
123  }
124 
125  template <IntDim i_dim>
126  const T<i_dim> & operator[](Dim<i_dim>) const
127  {
128  return std::get<i_dim>(*this);
129  }
130 
131  /**
132  * Conversion operator for inner type conversions.
133  */
134  template< template<IntDim...> class TParent, typename std::enable_if<std::is_convertible<TParent<0>, T<0>>::value, T<0> >::type >
135  operator Mixed<TParent> () const {
136  //ASSERT(std::is_base_of<TParent, T>::value);
137  return Mixed<TParent>(
138  TParent<0>(this->operator[](0_d)),
139  TParent<1>(this->operator[](1_d)),
140  TParent<2>(this->operator[](2_d)),
141  TParent<3>(this->operator[](3_d)));
142  }
143 
144  // Possible collective methods must be implemented in MixedPtr childs.
145 };
146 
147 
148 
149 
150 template< template<IntDim ...> class T>
151 class Mixed<T, 1> : public _MixedBase1<T> {
152 /**
153  * Explicit specialization for tuple containing just 1,2,3.
154  * TODO: implement generic Mixed with the lower_dim parameter.
155  *
156  */
157 public:
158  template < template<IntDim...> class TT>
159  Mixed(const Mixed<TT, 1> &other)
160  : _MixedBase1<T>(
161  T<1>(other[1_d] ),
162  T<2>(other[2_d] ),
163  T<3>(other[3_d] ) )
164  { static_assert(std::is_convertible<TT<1>, T<1>>::value, "Non-convertible types!"); }
165 
166  Mixed(const T<1> &p1,const T<2> &p2,const T<3> &p3)
167  : _MixedBase1<T>( p1, p2, p3)
168  {}
169 
170  Mixed( T<1> &&p1, T<2> &&p2, T<3> &&p3)
171  : _MixedBase1<T>(p1, p2, p3)
172  {}
173 
174 
175  template<typename... Args>
176  Mixed(Args... args)
177  : _MixedBase1<T>(
178  T<1>(std::forward<Args>(args)...),
179  T<2>(std::forward<Args>(args)...),
180  T<3>(std::forward<Args>(args)...))
181  {}
182 
183 
184  /**
185  * Beautiful index/like access insired by:
186  * https://arne-mertz.de/2017/03/tuple-compile-time-access/
187  */
188  template <IntDim i_dim>
189  T<i_dim> & operator[](Dim<i_dim>)
190  {
191  return std::get<i_dim-1>(*this);
192  }
193 
194  template <IntDim i_dim>
195  const T<i_dim> & operator[](Dim<i_dim>) const
196  {
197  return std::get<i_dim-1>(*this);
198  }
199 
200  template< template<IntDim...> class TParent, typename std::enable_if<std::is_convertible<TParent<1>, T<1>>::value, T<1> >::type >
201  operator Mixed<TParent> () const {
202  //ASSERT(std::is_base_of<TParent, T>::value);
203  return Mixed<TParent>(
204  TParent<1>(this->operator[](1_d)),
205  TParent<2>(this->operator[](2_d)),
206  TParent<3>(this->operator[](3_d)));
207  }
208 
209  // Possible collective methods must be implemented in MixedPtr childs.
210 };
211 
212 
213 
214 
215 //template< template<Dim, Dim> class T>
216 //struct FixSpaceDim {
217 ///**
218 // * Partial template resolution (parameter binding).
219 // * See implementation of MixedSpaceDim for the usage. Can be used for
220 // * possible child classes of the Mixed template.
221 // */
222 //public:
223 // template<Dim dim>
224 // using type = T<dim, __spacedim>;
225 //};
226 //
227 //
228 //template< template<Dim, Dim> class T>
229 //using MixedSpaceDim = Mixed< FixSpaceDim<T>::template type >;
230 
231 
232 
233 
234 
235 
236 template<template<IntDim...> class T>
237 using _MixedPtrBase0 = std::tuple<
238  std::shared_ptr<T<0>>, std::shared_ptr<T<1>>,
239  std::shared_ptr<T<2>>, std::shared_ptr<T<3>>>;
240 
241 template<template<IntDim...> class T>
242 using _MixedPtrBase1 = std::tuple< std::shared_ptr<T<1>>,
243  std::shared_ptr<T<2>>, std::shared_ptr<T<3>>>;
244 
245 
246 template< template<IntDim...> class T, int lower_dim=0>
247 class MixedPtr : public _MixedPtrBase0<T> {
248 /**
249  * Similar to the mixed template but storing and providing shared pointers to the inner type.
250  * Usage:
251  *
252  * fe_order = 10;
253  * auto gauss = MixedPtr<QGauss>(q_order); // template <int dim> class QGauss;
254  * auto mapping = MixedSpaceDimPtr<Mapping>(); // template <int dim, int spacedim> class Mapping;
255  * ...
256  * fe_values = FEValues<dim>(*mapping[Dim<dim>{}], *gauss[Dim<dim>{}], ...)
257  *
258  * All parameters of the Mixed<T>(...) constructor are forwarder (by value) to the T(...) constructor for every dimension.
259  * Only forwarding by value is supported due to problems with MixedPtr.
260  * We are unable to give precedence to the copy constructor over the prefect forwarding constructor MixedPtr(Args&& ...).
261  */
262 public:
263  template <IntDim dim>
264  using TPtr = std::shared_ptr<T<dim>>;
265 
266  template < template<IntDim...> class TT>
267  MixedPtr(const MixedPtr<TT> &other)
268  : _MixedPtrBase0<T>(
269  other[0_d],
270  other[1_d],
271  other[2_d],
272  other[3_d])
273  {}
274 
276  : _MixedPtrBase0<T>(p0, p1, p2, p3)
277  {}
278 
279  template<typename... Args>
280  MixedPtr(Args... args)
281  : _MixedPtrBase0<T>(
282  std::make_shared<T<0>>(std::forward<Args>(args)...),
283  std::make_shared<T<1>>(std::forward<Args>(args)...),
284  std::make_shared<T<2>>(std::forward<Args>(args)...),
285  std::make_shared<T<3>>(std::forward<Args>(args)...))
286  {}
287 
288 
289 
290  /**
291  * Beautiful index/like access insired by:
292  * https://arne-mertz.de/2017/03/tuple-compile-time-access/
293  */
294  template <IntDim i_dim>
295  std::shared_ptr<T<i_dim>> operator[](Dim<i_dim>)
296  {
297  return std::get<i_dim>(*this);
298  }
299 
300  template <IntDim i_dim>
301  const std::shared_ptr<T<i_dim>> operator[](Dim<i_dim>) const
302  {
303  return std::get<i_dim>(*this);
304  }
305 
307  return Mixed<T>(
308  *(this->operator[](0_d)),
309  *(this->operator[](1_d)),
310  *(this->operator[](2_d)),
311  *(this->operator[](3_d)));
312  }
313 
314  // Possible collective methods must be implemented in MixedPtr childs.
315 
316 };
317 
318 
319 template< template<IntDim...> class T>
320 class MixedPtr<T, 1> : public _MixedPtrBase1<T> {
321 /**
322  * Similar to MixedPtr.
323  * TODO: make generic implementation.
324  */
325 public:
326  template <IntDim dim>
327  using TPtr = std::shared_ptr<T<dim>>;
328 
329  template < template<IntDim...> class TT>
330  MixedPtr(const MixedPtr<TT, 1> &other)
331  : _MixedPtrBase1<T>(
332  other[1_d],
333  other[2_d],
334  other[3_d])
335  {}
336 
338  : _MixedPtrBase1<T>(p1, p2, p3)
339  {}
340 
341  template<typename... Args>
342  MixedPtr(Args... args)
343  : _MixedPtrBase1<T>(
344  std::make_shared<T<1>>(std::forward<Args>(args)...),
345  std::make_shared<T<2>>(std::forward<Args>(args)...),
346  std::make_shared<T<3>>(std::forward<Args>(args)...))
347  {}
348 
349 
350 
351  /**
352  * Beautiful index/like access insired by:
353  * https://arne-mertz.de/2017/03/tuple-compile-time-access/
354  */
355  template <IntDim i_dim>
356  std::shared_ptr<T<i_dim>> operator[](Dim<i_dim>)
357  {
358  return std::get<i_dim-1>(*this);
359  }
360 
361  template <IntDim i_dim>
362  const std::shared_ptr<T<i_dim>> operator[](Dim<i_dim>) const
363  {
364  return std::get<i_dim-1>(*this);
365  }
366 
367 
369  return Mixed<T, 1>(
370  *(this->operator[](1_d)),
371  *(this->operator[](2_d)),
372  *(this->operator[](3_d)));
373  }
374 
375  // Possible collective methods must be implemented in MixedPtr childs.
376 
377 };
378 
379 //template< template<Dim, Dim> class T>
380 //using MixedSpaceDimPtr = MixedPtr< FixSpaceDim<T>::template type >;
381 
382 
383 
384 //template< template <int> class Fn, class ...Args>
385 //auto dim_switch(Dim dim, Args&&... args) -> decltype( builder.makeObject() )
386 //{
387 // switch (dim)
388 // {
389 // case 0:
390 // return Fn<0>(std::forward<Args>(args)...);
391 // case 0:
392 // return Fn<1>(std::forward<Args>(args)...);
393 // case 0:
394 // return Fn<2>(std::forward<Args>(args)...);
395 // case 0:
396 // return Fn<3>(std::forward<Args>(args)...);
397 // }
398 //
399 //}
400 
401 
402 #endif /* SRC_TOOLS_MIXED_HH_ */
Mixed(Args...args)
Definition: mixed.hh:107
Definition: mixed.hh:25
const std::shared_ptr< T< i_dim > > operator[](Dim< i_dim >) const
Definition: mixed.hh:301
T< i_dim > & operator[](Dim< i_dim >)
Definition: mixed.hh:120
Mixed(const T< 0 > &p0, const T< 1 > &p1, const T< 2 > &p2, const T< 3 > &p3)
Definition: mixed.hh:97
Mixed(const Mixed< TT, 1 > &other)
Definition: mixed.hh:159
std::tuple< T< 1 >, T< 2 >, T< 3 >> _MixedBase1
Definition: mixed.hh:60
std::shared_ptr< T< i_dim > > operator[](Dim< i_dim >)
Definition: mixed.hh:295
std::shared_ptr< T< i_dim > > operator[](Dim< i_dim >)
Definition: mixed.hh:356
const T< i_dim > & operator[](Dim< i_dim >) const
Definition: mixed.hh:126
std::tuple< T< 0 >, T< 1 >, T< 2 >, T< 3 >> _MixedBase0
Definition: mixed.hh:57
std::tuple< std::shared_ptr< T< 0 >>, std::shared_ptr< T< 1 >>, std::shared_ptr< T< 2 >>, std::shared_ptr< T< 3 >>> _MixedPtrBase0
Definition: mixed.hh:239
static constexpr bool value
Definition: json.hpp:87
const T< i_dim > & operator[](Dim< i_dim >) const
Definition: mixed.hh:195
UnitSI operator*(const UnitSI &a, const UnitSI &b)
Product of two units.
Definition: unit_si.cc:235
const int __spacedim
Definition: mixed.hh:16
MixedPtr(TPtr< 0 > p0, TPtr< 1 > p1, TPtr< 2 > p2, TPtr< 3 > p3)
Definition: mixed.hh:275
MixedPtr(Args...args)
Definition: mixed.hh:280
T< i_dim > & operator[](Dim< i_dim >)
Definition: mixed.hh:189
Mixed(const T< 1 > &p1, const T< 2 > &p2, const T< 3 > &p3)
Definition: mixed.hh:166
unsigned int IntDim
A dimension index type.
Definition: mixed.hh:19
Definition: mixed.hh:64
Mixed(T< 1 > &&p1, T< 2 > &&p2, T< 3 > &&p3)
Definition: mixed.hh:170
std::tuple< std::shared_ptr< T< 1 >>, std::shared_ptr< T< 2 >>, std::shared_ptr< T< 3 >>> _MixedPtrBase1
Definition: mixed.hh:243
std::shared_ptr< T< dim >> TPtr
Definition: mixed.hh:327
MixedPtr(Args...args)
Definition: mixed.hh:342
constexpr std::size_t parse_dim()
Definition: mixed.hh:35
const std::shared_ptr< T< i_dim > > operator[](Dim< i_dim >) const
Definition: mixed.hh:362
MixedPtr(const MixedPtr< TT, 1 > &other)
Definition: mixed.hh:330
std::shared_ptr< DimAssembly< dim >> TPtr
Definition: mixed.hh:264
Mixed(const Mixed< TT > &other)
Definition: mixed.hh:89
MixedPtr(TPtr< 1 > p1, TPtr< 2 > p2, TPtr< 3 > p3)
Definition: mixed.hh:337
Mixed(Args...args)
Definition: mixed.hh:176
Mixed(T< 0 > &&p0, T< 1 > &&p1, T< 2 > &&p2, T< 3 > &&p3)
Definition: mixed.hh:101
MixedPtr(const MixedPtr< TT > &other)
Definition: mixed.hh:267