Reference documentation for deal.II version Git aba33d3846 2022-01-19 21:43:57 -0500
\(\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 =
204  std::is_same<typename T::value_type, Number>::value;
205  };
206 
207  // We need to have a separate declaration for static const members
208  template <typename T, typename Number>
210 
211 
212  //
213  // type-traits for Matrix-Free
214  //
215  // similar to type traits in FEEvaluation, below we add type-traits
216  // to distinguish between vectors that provide different interface for
217  // operations like update_ghost_values(), compress(), etc.
218  // see internal::has_local_element in fe_evaluation.h that documents
219  // how those type traits work.
220 
221  // a helper type-trait that leverage SFINAE to figure out if type T has
222  // void T::update_ghost_values_start(const uint) const
223  template <typename T>
224  struct has_update_ghost_values_start
225  {
226  private:
227  static bool
228  detect(...);
229 
230  template <typename U>
231  static decltype(std::declval<U const>().update_ghost_values_start(0))
232  detect(const U &);
233 
234  public:
235  static const bool value =
236  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
237  };
238 
239  // We need to have a separate declaration for static const members
240  template <typename T>
241  const bool has_update_ghost_values_start<T>::value;
242 
243 
244 
245  // a helper type-trait that leverage SFINAE to figure out if type T has
246  // void T:: compress_start(const uint, VectorOperation::values)
247  template <typename T>
248  struct has_compress_start
249  {
250  private:
251  static bool
252  detect(...);
253 
254  template <typename U>
255  static decltype(std::declval<U>().compress_start(0, VectorOperation::add))
256  detect(const U &);
257 
258  public:
259  static const bool value =
260  !std::is_same<bool, decltype(detect(std::declval<T>()))>::value;
261  };
262 
263  // We need to have a separate declaration for static const members
264  template <typename T>
265  const bool has_compress_start<T>::value;
266 
267 
268 
269  // type trait for vector T to see if
270  // we do a custom data exchange route.
271  // We assume that if both begin() and local_element()
272  // exist, then begin() + offset == local_element(offset)
273  template <typename T>
274  struct has_exchange_on_subset
275  {
276  static const bool value = has_begin<T>::value &&
279  };
280 
281  // We need to have a separate declaration for static const members
282  template <typename T>
284 
285 
286 
287  // a helper type-trait that leverage SFINAE to figure out if type T has
288  // T::communication_block_size
289  template <typename T>
290  struct has_communication_block_size
291  {
292  private:
293  static void
294  detect(...);
295 
296  template <typename U>
297  static decltype(U::communication_block_size)
298  detect(const U &);
299 
300  public:
301  static const bool value =
302  !std::is_same<void, decltype(detect(std::declval<T>()))>::value;
303  };
304 
305  // We need to have a separate declaration for static const members
306  template <typename T>
308 
309 
310 
311  // type trait for vector T to see if
312  // we need to do any data exchange for this vector type at all.
313  // is_serial_vector<> would have been enough, but in some circumstances
314  // (like calculation of diagonals for matrix-free operators)
315  // a dummy InVector == unsigned int is provided.
316  // Thus we have to treat this case as well.
317  template <typename T>
318  struct is_serial_or_dummy
319  {
320  private:
321  // catches all cases including unsigned int
322  static void
323  detect(...);
324 
325  // catches serial vectors
326  template <
327  typename U,
328  typename std::enable_if<is_serial_vector<U>::value, U>::type * = nullptr>
329  static void
330  detect(const U &);
331 
332  // catches parallel vectors
333  template <
334  typename U,
335  typename std::enable_if<!is_serial_vector<U>::value, U>::type * = nullptr>
336  static bool
337  detect(const U &);
338 
339  public:
340  static const bool value =
341  std::is_same<void, decltype(detect(std::declval<T>()))>::value;
342  };
343 
344  // We need to have a separate declaration for static const members
345  template <typename T>
346  const bool is_serial_or_dummy<T>::value;
347 
348 
349 } // namespace internal
350 #endif
351 
353 
354 #endif
STL namespace.
static const char U
static const char T
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:407
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:406
VectorType::value_type * begin(VectorType &V)