Reference documentation for deal.II version 9.3.0
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
type_traits.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2019 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #ifndef dealii_matrix_free_type_traits_h
18 #define dealii_matrix_free_type_traits_h
19 
20 // various type-traits used exclusively within the matrix-free framework
21 
22 #include <deal.II/base/config.h>
23 
25 
27 
28 
30 
31 #ifndef DOXYGEN
32 namespace internal
33 {
34  //
35  // type traits for FEEvaluation
36  //
37 
38  // a helper type-trait that leverage SFINAE to figure out if type T has
39  // ... T::local_element() const
40  template <typename T>
41  struct has_local_element
42  {
43  private:
44  // this will work always.
45  // we let it be void as we know T::local_element() (if exists) should
46  // certainly return something
47  static void
48  detect(...);
49 
50  // this detecter will work only if we have "... T::local_element() const"
51  // and its return type will be the same as local_element(),
52  // that we expect to be T::value_type
53  template <typename U>
54  static decltype(std::declval<U const>().local_element(0))
55  detect(const U &);
56 
57  public:
58  // finally here we check if our detector has non-void return type
59  // T::value_type. This will happen if compiler can use second detector,
60  // otherwise SFINAE let it work with the more general first one that is void
61  static const bool value =
62  !std::is_same<void, decltype(detect(std::declval<T>()))>::value;
63  };
64 
65  // We need to have a separate declaration for static const members
66  template <typename T>
67  const bool has_local_element<T>::value;
68 
69 
70 
71  // a helper type-trait that leverage SFINAE to figure out if type T has
72  // void T::add_local_element(const uint, const typename T::value_type)
73  template <typename T>
74  struct has_add_local_element
75  {
76  private:
77  static int
78  detect(...);
79 
80  template <typename U>
81  static decltype(
82  std::declval<U>().add_local_element(0, typename T::value_type()))
83  detect(const U &);
84 
85  public:
86  static const bool value =
87  !std::is_same<int, decltype(detect(std::declval<T>()))>::value;
88  };
89 
90  // We need to have a separate declaration for static const members
91  template <typename T>
92  const bool has_add_local_element<T>::value;
93 
94 
95 
96  // a helper type-trait that leverage SFINAE to figure out if type T has
97  // void T::set_local_element(const uint, const typename T::value_type)
98  template <typename T>
99  struct has_set_local_element
100  {
101  private:
102  static int
103  detect(...);
104 
105  template <typename U>
106  static decltype(
107  std::declval<U>().set_local_element(0, typename T::value_type()))
108  detect(const U &);
109 
110  public:
111  static const bool value =
112  !std::is_same<int, decltype(detect(std::declval<T>()))>::value;
113  };
114 
115  // We need to have a separate declaration for static const members
116  template <typename T>
117  const bool has_set_local_element<T>::value;
118 
119 
120 
121  // same as above to check
122  // bool T::partitioners_are_compatible(const Utilities::MPI::Partitioner &)
123  // const
124  template <typename T>
125  struct has_partitioners_are_compatible
126  {
127  private:
128  static void
129  detect(...);
130 
131  template <typename U>
132  static decltype(std::declval<U const>().partitioners_are_compatible(
133  std::declval<Utilities::MPI::Partitioner>()))
134  detect(const U &);
135 
136  public:
137  static const bool value =
138  std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
139  };
140 
141  // We need to have a separate declaration for static const members
142  template <typename T>
143  const bool has_partitioners_are_compatible<T>::value;
144 
145 
146  // same as above to check
147  // ... T::begin() const
148  template <typename T>
149  struct has_begin
150  {
151  private:
152  static void
153  detect(...);
154 
155  template <typename U>
156  static decltype(std::declval<U const>().begin())
157  detect(const U &);
158 
159  public:
160  static const bool value =
161  !std::is_same<void, decltype(detect(std::declval<T>()))>::value;
162  };
163 
164  // We need to have a separate declaration for static const members
165  template <typename T>
166  const bool has_begin<T>::value;
167 
168 
169  // same as above to check
170  // ... T::shared_vector_data() const
171  template <typename T>
172  struct has_shared_vector_data
173  {
174  private:
175  static void
176  detect(...);
177 
178  template <typename U>
179  static decltype(std::declval<U const>().shared_vector_data())
180  detect(const U &);
181 
182  public:
183  static const bool value =
184  !std::is_same<void, decltype(detect(std::declval<T>()))>::value;
185  };
186 
187  // We need to have a separate declaration for static const members
188  template <typename T>
189  const bool has_shared_vector_data<T>::value;
190 
191 
192  // type trait for vector T and Number to see if
193  // we can do vectorized load/save.
194  // for VectorReader and VectorDistributorLocalToGlobal we assume that
195  // if both begin() and local_element()
196  // exist, then begin() + offset == local_element(offset)
197  template <typename T, typename Number>
198  struct is_vectorizable
199  {
200  static const bool value =
203  std::is_same<typename T::value_type, Number>::value;
204  };
205 
206  // We need to have a separate declaration for static const members
207  template <typename T, typename Number>
209 
210 
211  //
212  // type-traits for Matrix-Free
213  //
214  // similar to type traits in FEEvaluation, below we add type-traits
215  // to distinguish between vectors that provide different interface for
216  // operations like update_ghost_values(), compress(), etc.
217  // see internal::has_local_element in fe_evaluation.h that documents
218  // how those type traits work.
219 
220  // a helper type-trait that leverage SFINAE to figure out if type T has
221  // void T::update_ghost_values_start(const uint) const
222  template <typename T>
223  struct has_update_ghost_values_start
224  {
225  private:
226  static bool
227  detect(...);
228 
229  template <typename U>
230  static decltype(std::declval<U const>().update_ghost_values_start(0))
231  detect(const U &);
232 
233  public:
234  static const bool value =
235  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
236  };
237 
238  // We need to have a separate declaration for static const members
239  template <typename T>
240  const bool has_update_ghost_values_start<T>::value;
241 
242 
243 
244  // a helper type-trait that leverage SFINAE to figure out if type T has
245  // void T:: compress_start(const uint, VectorOperation::values)
246  template <typename T>
247  struct has_compress_start
248  {
249  private:
250  static bool
251  detect(...);
252 
253  template <typename U>
254  static decltype(std::declval<U>().compress_start(0, VectorOperation::add))
255  detect(const U &);
256 
257  public:
258  static const bool value =
259  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
260  };
261 
262  // We need to have a separate declaration for static const members
263  template <typename T>
264  const bool has_compress_start<T>::value;
265 
266 
267 
268  // type trait for vector T to see if
269  // we do a custom data exchange route.
270  // We assume that if both begin() and local_element()
271  // exist, then begin() + offset == local_element(offset)
272  template <typename T>
273  struct has_exchange_on_subset
274  {
275  static const bool value =
277  };
278 
279  // We need to have a separate declaration for static const members
280  template <typename T>
282 
283 
284 
285  // a helper type-trait that leverage SFINAE to figure out if type T has
286  // T::communication_block_size
287  template <typename T>
288  struct has_communication_block_size
289  {
290  private:
291  static void
292  detect(...);
293 
294  template <typename U>
295  static decltype(U::communication_block_size)
296  detect(const U &);
297 
298  public:
299  static const bool value =
300  !std::is_same<void, decltype(detect(std::declval<T>()))>::value;
301  };
302 
303  // We need to have a separate declaration for static const members
304  template <typename T>
306 
307 
308 
309  // type trait for vector T to see if
310  // we need to do any data exchange for this vector type at all.
311  // is_serial_vector<> would have been enough, but in some circumstances
312  // (like calculation of diagonals for matrix-free operators)
313  // a dummy InVector == unsigned int is provided.
314  // Thus we have to treat this case as well.
315  template <typename T>
316  struct is_serial_or_dummy
317  {
318  private:
319  // catches all cases including unsigned int
320  static void
321  detect(...);
322 
323  // catches serial vectors
324  template <
325  typename U,
326  typename std::enable_if<is_serial_vector<U>::value, U>::type * = nullptr>
327  static void
328  detect(const U &);
329 
330  // catches parallel vectors
331  template <
332  typename U,
333  typename std::enable_if<!is_serial_vector<U>::value, U>::type * = nullptr>
334  static bool
335  detect(const U &);
336 
337  public:
338  static const bool value =
339  std::is_same<void, decltype(detect(std::declval<T>()))>::value;
340  };
341 
342  // We need to have a separate declaration for static const members
343  template <typename T>
344  const bool is_serial_or_dummy<T>::value;
345 
346 
347 } // namespace internal
348 #endif
349 
351 
352 #endif
STL namespace.
static const char U
static const char T
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:395
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:394
VectorType::value_type * begin(VectorType &V)