Reference documentation for deal.II version 9.3.3
\(\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
32namespace 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 =
201 has_begin<T>::value &&
202 (has_local_element<T>::value || is_serial_vector<T>::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>
208 const bool is_vectorizable<T, Number>::value;
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 =
276 has_begin<T>::value && has_local_element<T>::value;
277 };
278
279 // We need to have a separate declaration for static const members
280 template <typename T>
281 const bool has_exchange_on_subset<T>::value;
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>
305 const bool has_communication_block_size<T>::value;
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
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
static const char U