libMesh
tensor_tools.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #ifndef LIBMESH_TENSOR_TOOLS_H
21 #define LIBMESH_TENSOR_TOOLS_H
22 
23 // Local includes
24 #include "libmesh/libmesh_common.h"
25 #include "libmesh/compare_types.h"
26 
27 #ifdef LIBMESH_HAVE_METAPHYSICL
28 #include "metaphysicl/dualnumber_decl.h"
29 #endif
30 
31 namespace libMesh
32 {
33 // Forward declarations
34 template <typename T> class TypeVector;
35 template <typename T> class VectorValue;
36 template <typename T> class TypeTensor;
37 template <typename T> class TensorValue;
38 template <unsigned int N, typename T> class TypeNTensor;
39 
40 namespace TensorTools
41 {
42 // Any tensor-rank-independent code will need to include
43 // tensor_tools.h, so we define a product/dot-product here, starting
44 // with the generic case to apply to scalars.
45 // Vector specializations will follow.
46 
47 template <typename T, typename T2>
48 inline
50  typename CompareTypes<T, T2>::supertype>::type
51 inner_product(const T & a, const T2& b)
52 { return a * b; }
53 
54 template <typename T, typename T2>
55 inline
58 { return a * b; }
59 
60 template <typename T, typename T2>
61 inline
64 { return a.contract(b); }
65 
66 template <unsigned int N, typename T, typename T2>
67 inline
70 { return a.contract(b); }
71 
72 template<typename T>
73 inline
74 auto norm(const T & a) -> decltype(std::abs(a))
75 { return std::abs(a); }
76 
77 template<typename T>
78 inline
79 T norm(std::complex<T> a) { return std::abs(a); }
80 
81 template <typename T>
82 inline
83 auto norm(const TypeVector<T> & a) -> decltype(TensorTools::norm(T()))
84 {return std::sqrt(a.norm_sq());}
85 
86 template <typename T>
87 inline
88 auto norm(const VectorValue<T> & a) -> decltype(TensorTools::norm(T()))
89 {return std::sqrt(a.norm_sq());}
90 
91 template <typename T>
92 inline
93 auto norm(const TypeTensor<T> & a) -> decltype(TensorTools::norm(T()))
94 {return std::sqrt(a.norm_sq());}
95 
96 template <typename T>
97 inline
98 auto norm(const TensorValue<T> & a) -> decltype(TensorTools::norm(T()))
99 {return std::sqrt(a.norm_sq());}
100 
101 
102 template<typename T>
103 inline
104 auto norm_sq(const T & a) -> decltype(std::norm(a))
105 { return std::norm(a); }
106 
107 template<typename T>
108 inline
109 T norm_sq(std::complex<T> a) { return std::norm(a); }
110 
111 template <typename T>
112 inline
113 auto norm_sq(const TypeVector<T> & a) -> decltype(std::norm(T()))
114 {return a.norm_sq();}
115 
116 template <typename T>
117 inline
118 auto norm_sq(const VectorValue<T> & a) -> decltype(std::norm(T()))
119 {return a.norm_sq();}
120 
121 template <typename T>
122 inline
123 auto norm_sq(const TypeTensor<T> & a) -> decltype(std::norm(T()))
124 {return a.norm_sq();}
125 
126 template <typename T>
127 inline
128 auto norm_sq(const TensorValue<T> & a) -> decltype(std::norm(T()))
129 {return a.norm_sq();}
130 
131 
132 template<typename T>
133 inline
134 bool is_zero(const T & a){ return a.is_zero();}
135 
136 // Any tensor-rank-independent code will need to include
137 // tensor_tools.h, so we define rank-increasing and real-to-number type
138 // conversion functions here, starting with the generic case to apply
139 // to scalars.
140 // Tensor(and higher?) specializations will go in the tensor
141 // header(s).
142 template <typename T>
144 {
146 };
147 
148 template <typename T>
150 {
152 };
153 
154 
155 template <typename T>
157 {
159 };
160 
161 template <typename T>
163 {
165 };
166 
167 
168 template <typename T>
170 {
172 };
173 
174 template <unsigned int N, typename T>
176 {
178 };
179 
180 
181 // Also need rank-decreasing case
182 template <typename T>
184 {
185  // The default case is typically an error, but for simpler
186  // templated code we need it to be compatible with Number
187  // operations...
188  typedef T type;
189 };
190 
191 template <typename T>
193 {
194  typedef T type;
195 };
196 
197 template <typename T>
199 {
200  typedef T type;
201 };
202 
203 template <typename T>
205 {
207 };
208 
209 template <typename T>
211 {
213 };
214 
215 template <unsigned int N, typename T>
217 {
218  typedef TypeNTensor<N-1,T> type;
219 };
220 
221 // Handle the complex-valued case
222 template <typename T>
224 {
225 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
226  typedef std::complex<T> type;
227 #else
228  typedef T type;
229 #endif
230 };
231 
232 template <typename T>
233 struct MakeNumber<std::complex<T>>
234 {
235  // Should this be a compile-time error? we shouldn't need to make numbers out of
236  // numbers, but then again having the typedef below enables more generic
237  // programming
238  typedef std::complex<T> type;
239 };
240 
241 
242 template <typename T>
244 {
246 };
247 
248 template <typename T>
250 {
252 };
253 
254 template <typename T>
256 {
258 };
259 
260 template <typename T>
262 {
264 };
265 
266 template <unsigned int N, typename T>
268 {
269 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
271 #else
273 #endif
274 };
275 
276 // A utility for determining real-valued (e.g. shape function)
277 // types from corresponding complex-valued types
278 template <typename T>
279 struct MakeReal
280 {
281  typedef T type;
282 };
283 
284 template <typename T>
285 struct MakeReal<std::complex<T>>
286 {
287  typedef T type;
288 };
289 
290 template <typename T>
292 {
294 };
295 
296 template <typename T>
298 {
300 };
301 
302 template <typename T>
304 {
306 };
307 
308 template <typename T>
310 {
312 };
313 
314 template <unsigned int N, typename T>
315 struct MakeReal<TypeNTensor<N,T>>
316 {
318 };
319 
320 // Needed for ExactSolution to compile
322 
325 
329 
332 
335 
339 
344 template <typename T>
346 {
347  static constexpr bool value = false;
348 };
349 
350 template <typename T>
352 {
353  static constexpr bool value = true;
354 };
355 
356 template <typename T>
358 {
359  static constexpr bool value = true;
360 };
361 
362 template <typename T>
364 {
365  static constexpr bool value = true;
366 };
367 
368 template <typename T>
370 {
371  static constexpr bool value = true;
372 };
373 
374 template <unsigned int N, typename T>
376 {
377  static constexpr bool value = true;
378 };
379 
380 template <typename T, typename enable = void> struct MakeBaseNumber {};
381 
382 template <typename T>
383 struct MakeBaseNumber<T, typename std::enable_if<ScalarTraits<T>::value>::type> {
384  typedef typename MakeNumber<T>::type type;
385 };
386 
387 template <template <typename> class Wrapper, typename T>
389  Wrapper<T>,
390  typename std::enable_if<MathWrapperTraits<Wrapper<T>>::value>::type> {
391  typedef typename MakeBaseNumber<T>::type type;
392 };
393 
394 template <typename T, typename Enable = void>
396 {
397  static_assert(always_false<T>,
398  "Instantiating the generic template of TensorTraits. You must specialize "
399  "TensorTraits for your type.");
400  static constexpr unsigned char rank = 0;
401 };
402 
403 template <typename T>
404 struct TensorTraits<T, typename std::enable_if<ScalarTraits<T>::value>::type>
405 {
406  static constexpr unsigned char rank = 0;
407 };
408 
409 template <typename T>
411 {
412  static constexpr unsigned char rank = 1;
413 };
414 
415 template <typename T>
417 {
418  static constexpr unsigned char rank = 1;
419 };
420 
421 template <typename T>
423 {
424  static constexpr unsigned char rank = 2;
425 };
426 
427 template <typename T>
429 {
430  static constexpr unsigned char rank = 2;
431 };
432 
433 template <typename T, unsigned int N>
435 {
436  static constexpr unsigned char rank = static_cast<unsigned char>(N);
437 };
438 
439 }//namespace TensorTools
440 
441 }//namespace libMesh
442 
443 #endif // LIBMESH_TENSOR_TOOLS_H
Number div_from_grad(const VectorValue< Number > &grad)
Dummy. Divergence of a scalar not defined, but is needed for ExactSolution to compile.
Definition: tensor_tools.C:54
TypeTensor< typename MakeNumber< T >::type > type
Definition: tensor_tools.h:263
bool is_zero(const T &a)
Definition: tensor_tools.h:134
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
Definition: type_vector.h:53
The libMesh namespace provides an interface to certain functionality in the library.
TypeVector< typename MakeNumber< T >::type > type
Definition: tensor_tools.h:245
TypeTensor< typename MakeReal< T >::type > type
Definition: tensor_tools.h:311
This class defines a tensor in LIBMESH_DIM dimensional space of type T.
Definition: tensor_tools.h:36
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
Definition: type_vector.h:57
TypeVector< typename MakeReal< T >::type > type
Definition: tensor_tools.h:293
TypeTensor< typename MakeReal< T >::type > type
Definition: tensor_tools.h:305
VectorValue< typename MakeReal< T >::type > type
Definition: tensor_tools.h:299
This class defines a vector in LIBMESH_DIM dimensional space of type T.
Definition: tensor_tools.h:34
auto norm(const T &a) -> decltype(std::abs(a))
Definition: tensor_tools.h:74
TypeNTensor< N, typename MakeReal< T >::type > type
Definition: tensor_tools.h:317
CompareTypes< T, T2 >::supertype contract(const TypeTensor< T2 > &) const
Multiply 2 tensors together to return a scalar, i.e.
Definition: type_tensor.h:1268
This class will eventually define a rank-N tensor in LIBMESH_DIM dimensional space of type T...
Definition: tensor_tools.h:38
auto norm_sq(const T &a) -> decltype(std::norm(a))
Definition: tensor_tools.h:104
TypeTensor< typename MakeNumber< T >::type > type
Definition: tensor_tools.h:257
VectorValue< typename MakeNumber< T >::type > type
Definition: tensor_tools.h:251
static constexpr unsigned char rank
Definition: tensor_tools.h:400
This helper structure is used to determine whether a template class is one of our mathematical struct...
Definition: tensor_tools.h:345
ADRealEigenVector< T, D, asd > norm(const ADRealEigenVector< T, D, asd > &)
Definition: type_vector.h:49
boostcopy::enable_if_c< ScalarTraits< T >::value &&ScalarTraits< T2 >::value, typename CompareTypes< T, T2 >::supertype >::type inner_product(const T &a, const T2 &b)
Definition: tensor_tools.h:51
Number curl_from_grad(const VectorValue< Number > &)
Definition: tensor_tools.C:28
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.
CompareTypes< T, T2 >::supertype contract(const TypeNTensor< N, T2 > &) const
Multiply 2 tensors together to return a scalar, i.e.