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\}}\)
tensor.h
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 1998 - 2021 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#ifndef dealii_tensor_h
17#define dealii_tensor_h
18
19#include <deal.II/base/config.h>
20
27
28#ifdef DEAL_II_WITH_ADOLC
29# include <adolc/adouble.h> // Taped double
30#endif
31
32#include <cmath>
33#include <ostream>
34#include <utility>
35#include <vector>
36
37
39
40// Forward declarations:
41#ifndef DOXYGEN
42template <typename ElementType, typename MemorySpace>
43class ArrayView;
44template <int dim, typename Number>
45class Point;
46template <int rank_, int dim, typename Number = double>
47class Tensor;
48template <typename Number>
49class Vector;
50template <typename number>
51class FullMatrix;
52namespace Differentiation
53{
54 namespace SD
55 {
56 class Expression;
57 }
58} // namespace Differentiation
59#endif
60
61
91template <int dim, typename Number>
92class Tensor<0, dim, Number>
93{
94public:
95 static_assert(dim >= 0,
96 "Tensors must have a dimension greater than or equal to one.");
97
106 static constexpr unsigned int dimension = dim;
107
111 static constexpr unsigned int rank = 0;
112
116 static constexpr unsigned int n_independent_components = 1;
117
127
132 using value_type = Number;
133
139 using array_type = Number;
140
146 constexpr DEAL_II_CUDA_HOST_DEV
148
156 template <typename OtherNumber>
157 constexpr DEAL_II_CUDA_HOST_DEV
159
165 template <typename OtherNumber>
166 constexpr DEAL_II_CUDA_HOST_DEV
167 Tensor(const OtherNumber &initializer);
168
169#ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
173 constexpr DEAL_II_CUDA_HOST_DEV
174 Tensor(const Tensor<0, dim, Number> &other);
175
179 constexpr DEAL_II_CUDA_HOST_DEV
180 Tensor(Tensor<0, dim, Number> &&other) noexcept;
181#endif
182
186 Number *
188
192 const Number *
193 begin_raw() const;
194
198 Number *
200
205 const Number *
206 end_raw() const;
207
217 constexpr DEAL_II_CUDA_HOST_DEV operator Number &();
218
227 constexpr DEAL_II_CUDA_HOST_DEV operator const Number &() const;
228
236 template <typename OtherNumber>
237 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
239
240#if defined(__INTEL_COMPILER) || defined(DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG)
249 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
251#endif
252
253#ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
258 operator=(Tensor<0, dim, Number> &&other) noexcept;
259#endif
260
267 template <typename OtherNumber>
268 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
269 operator=(const OtherNumber &d);
270
274 template <typename OtherNumber>
275 constexpr bool
277
281 template <typename OtherNumber>
282 constexpr bool
284
290 template <typename OtherNumber>
291 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
293
299 template <typename OtherNumber>
300 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
302
308 template <typename OtherNumber>
309 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
310 operator*=(const OtherNumber &factor);
311
317 template <typename OtherNumber>
318 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
319 operator/=(const OtherNumber &factor);
320
327 operator-() const;
328
341 constexpr void
343
350 norm() const;
351
359 norm_square() const;
360
366 template <class Archive>
367 void
368 serialize(Archive &ar, const unsigned int version);
369
374 using tensor_type = Number;
375
376private:
380 Number value;
381
385 template <typename OtherNumber>
386 void
388 unsigned int & start_index) const;
389
390 // Allow an arbitrary Tensor to access the underlying values.
391 template <int, int, typename>
392 friend class Tensor;
393};
394
395
396
470template <int rank_, int dim, typename Number>
472{
473public:
474 static_assert(rank_ >= 1,
475 "Tensors must have a rank greater than or equal to one.");
476 static_assert(dim >= 0,
477 "Tensors must have a dimension greater than or equal to one.");
486 static constexpr unsigned int dimension = dim;
487
491 static constexpr unsigned int rank = rank_;
492
497 static constexpr unsigned int n_independent_components =
498 Tensor<rank_ - 1, dim>::n_independent_components * dim;
499
505 using value_type = typename Tensor<rank_ - 1, dim, Number>::tensor_type;
506
512 typename Tensor<rank_ - 1, dim, Number>::array_type[(dim != 0) ? dim : 1];
513
521
527 constexpr DEAL_II_CUDA_HOST_DEV explicit Tensor(
528 const array_type &initializer);
529
543 template <typename ElementType, typename MemorySpace>
544 constexpr DEAL_II_CUDA_HOST_DEV explicit Tensor(
545 const ArrayView<ElementType, MemorySpace> &initializer);
546
554 template <typename OtherNumber>
555 constexpr DEAL_II_CUDA_HOST_DEV
557
561 template <typename OtherNumber>
562 constexpr Tensor(
563 const Tensor<1, dim, Tensor<rank_ - 1, dim, OtherNumber>> &initializer);
564
568 template <typename OtherNumber>
569 constexpr
570 operator Tensor<1, dim, Tensor<rank_ - 1, dim, OtherNumber>>() const;
571
572#ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
576 constexpr Tensor(const Tensor<rank_, dim, Number> &);
577
581 constexpr Tensor(Tensor<rank_, dim, Number> &&) noexcept;
582#endif
583
589 constexpr DEAL_II_CUDA_HOST_DEV value_type &operator[](const unsigned int i);
590
596 constexpr DEAL_II_CUDA_HOST_DEV const value_type &
597 operator[](const unsigned int i) const;
598
602 constexpr const Number &operator[](const TableIndices<rank_> &indices) const;
603
607 constexpr Number &operator[](const TableIndices<rank_> &indices);
608
612 Number *
614
618 const Number *
619 begin_raw() const;
620
624 Number *
626
630 const Number *
631 end_raw() const;
632
640 template <typename OtherNumber>
641 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
643
650 constexpr Tensor &
651 operator=(const Number &d);
652
653#ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
659
665#endif
666
670 template <typename OtherNumber>
671 constexpr bool
673
677 template <typename OtherNumber>
678 constexpr bool
680
686 template <typename OtherNumber>
687 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
689
695 template <typename OtherNumber>
696 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
698
705 template <typename OtherNumber>
706 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
707 operator*=(const OtherNumber &factor);
708
714 template <typename OtherNumber>
715 constexpr DEAL_II_CUDA_HOST_DEV Tensor &
716 operator/=(const OtherNumber &factor);
717
724 operator-() const;
725
738 constexpr void
740
750 norm() const;
751
758 constexpr DEAL_II_CUDA_HOST_DEV
760 norm_square() const;
761
769 template <typename OtherNumber>
770 void
772
777 static constexpr unsigned int
779
785 static constexpr TableIndices<rank_>
786 unrolled_to_component_indices(const unsigned int i);
787
792 static constexpr std::size_t
794
800 template <class Archive>
801 void
802 serialize(Archive &ar, const unsigned int version);
803
809
810private:
814 Tensor<rank_ - 1, dim, Number> values[(dim != 0) ? dim : 1];
815 // ... avoid a compiler warning in case of dim == 0 and ensure that the
816 // array always has positive size.
817
821 template <typename OtherNumber>
822 void
824 unsigned int & start_index) const;
825
832 template <typename ArrayLike, std::size_t... Indices>
833 constexpr DEAL_II_CUDA_HOST_DEV
834 Tensor(const ArrayLike &initializer, std::index_sequence<Indices...>);
835
836 // Allow an arbitrary Tensor to access the underlying values.
837 template <int, int, typename>
838 friend class Tensor;
839
840 // Point is allowed access to the coordinates. This is supposed to improve
841 // speed.
842 friend class Point<dim, Number>;
843};
844
845
846#ifndef DOXYGEN
847namespace internal
848{
849 // Workaround: The following 4 overloads are necessary to be able to
850 // compile the library with Apple Clang 8 and older. We should remove
851 // these overloads again when we bump the minimal required version to
852 // something later than clang-3.6 / Apple Clang 6.3.
853 template <int rank, int dim, typename T, typename U>
854 struct ProductTypeImpl<Tensor<rank, dim, T>, std::complex<U>>
855 {
856 using type =
858 };
859
860 template <int rank, int dim, typename T, typename U>
861 struct ProductTypeImpl<Tensor<rank, dim, std::complex<T>>, std::complex<U>>
862 {
863 using type =
865 };
866
867 template <typename T, int rank, int dim, typename U>
868 struct ProductTypeImpl<std::complex<T>, Tensor<rank, dim, U>>
869 {
870 using type =
872 };
873
874 template <int rank, int dim, typename T, typename U>
875 struct ProductTypeImpl<std::complex<T>, Tensor<rank, dim, std::complex<U>>>
876 {
877 using type =
879 };
880 // end workaround
881
886 template <int rank, int dim, typename T>
887 struct NumberType<Tensor<rank, dim, T>>
888 {
889 static constexpr DEAL_II_ALWAYS_INLINE const Tensor<rank, dim, T> &
891 {
892 return t;
893 }
894
896 value(const T &t)
897 {
899 tmp = t;
900 return tmp;
901 }
902 };
903} // namespace internal
904
905
906/*---------------------- Inline functions: Tensor<0,dim> ---------------------*/
907
908
909template <int dim, typename Number>
912 // Some auto-differentiable numbers need explicit
913 // zero initialization such as adtl::adouble.
914 : Tensor{0.0}
915{}
916
917
918
919template <int dim, typename Number>
920template <typename OtherNumber>
922 Tensor<0, dim, Number>::Tensor(const OtherNumber &initializer)
923 : value(internal::NumberType<Number>::value(initializer))
924{}
925
926
927
928template <int dim, typename Number>
929template <typename OtherNumber>
932 : Tensor{p.value}
933{}
934
935
936# ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
937template <int dim, typename Number>
940 : value{other.value}
941{}
942
943
944
945template <int dim, typename Number>
948 : value{std::move(other.value)}
949{}
950# endif
951
952
953template <int dim, typename Number>
954inline Number *
956{
957 return std::addressof(value);
958}
959
960
961
962template <int dim, typename Number>
963inline const Number *
965{
966 return std::addressof(value);
967}
968
969
970
971template <int dim, typename Number>
972inline Number *
974{
976}
977
978
979
980template <int dim, typename Number>
981const Number *
983{
985}
986
987
988
989template <int dim, typename Number>
990constexpr inline DEAL_II_ALWAYS_INLINE
992{
993 // We cannot use Assert inside a CUDA kernel
994# ifndef __CUDA_ARCH__
995 Assert(dim != 0,
996 ExcMessage("Cannot access an object of type Tensor<0,0,Number>"));
997# endif
998 return value;
999}
1000
1001
1002template <int dim, typename Number>
1003constexpr inline DEAL_II_ALWAYS_INLINE
1005{
1006 // We cannot use Assert inside a CUDA kernel
1007# ifndef __CUDA_ARCH__
1008 Assert(dim != 0,
1009 ExcMessage("Cannot access an object of type Tensor<0,0,Number>"));
1010# endif
1011 return value;
1012}
1013
1014
1015template <int dim, typename Number>
1016template <typename OtherNumber>
1017constexpr inline DEAL_II_ALWAYS_INLINE
1020{
1022 return *this;
1023}
1024
1025
1026# if defined(__INTEL_COMPILER) || defined(DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG)
1027template <int dim, typename Number>
1028constexpr inline DEAL_II_ALWAYS_INLINE
1031{
1032 value = p.value;
1033 return *this;
1034}
1035# endif
1036
1037# ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
1038template <int dim, typename Number>
1041{
1042 value = std::move(other.value);
1043 return *this;
1044}
1045# endif
1046
1047
1048
1049template <int dim, typename Number>
1050template <typename OtherNumber>
1051constexpr inline DEAL_II_ALWAYS_INLINE
1053 Tensor<0, dim, Number>::operator=(const OtherNumber &d)
1054{
1056 return *this;
1057}
1058
1059
1060template <int dim, typename Number>
1061template <typename OtherNumber>
1062constexpr inline bool
1064{
1065# if defined(DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING)
1066 Assert(!(std::is_same<Number, adouble>::value ||
1067 std::is_same<OtherNumber, adouble>::value),
1068 ExcMessage(
1069 "The Tensor equality operator for ADOL-C taped numbers has not yet "
1070 "been extended to support advanced branching."));
1071# endif
1072
1073 return numbers::values_are_equal(value, p.value);
1074}
1075
1076
1077template <int dim, typename Number>
1078template <typename OtherNumber>
1079constexpr bool
1081{
1082 return !((*this) == p);
1083}
1084
1085
1086template <int dim, typename Number>
1087template <typename OtherNumber>
1088constexpr inline DEAL_II_ALWAYS_INLINE
1091{
1092 value += p.value;
1093 return *this;
1094}
1095
1096
1097template <int dim, typename Number>
1098template <typename OtherNumber>
1099constexpr inline DEAL_II_ALWAYS_INLINE
1102{
1103 value -= p.value;
1104 return *this;
1105}
1106
1107
1108
1109namespace internal
1110{
1111 namespace ComplexWorkaround
1112 {
1113 template <typename Number, typename OtherNumber>
1114 constexpr inline DEAL_II_ALWAYS_INLINE DEAL_II_CUDA_HOST_DEV void
1115 multiply_assign_scalar(Number &val, const OtherNumber &s)
1116 {
1117 val *= s;
1118 }
1119
1120# ifdef __CUDA_ARCH__
1121 template <typename Number, typename OtherNumber>
1122 constexpr inline DEAL_II_ALWAYS_INLINE DEAL_II_CUDA_HOST_DEV void
1123 multiply_assign_scalar(std::complex<Number> &, const OtherNumber &)
1124 {
1125 printf("This function is not implemented for std::complex<Number>!\n");
1126 assert(false);
1127 }
1128# endif
1129 } // namespace ComplexWorkaround
1130} // namespace internal
1131
1132
1133template <int dim, typename Number>
1134template <typename OtherNumber>
1135constexpr inline DEAL_II_ALWAYS_INLINE
1137 Tensor<0, dim, Number>::operator*=(const OtherNumber &s)
1138{
1139 internal::ComplexWorkaround::multiply_assign_scalar(value, s);
1140 return *this;
1141}
1142
1143
1144
1145template <int dim, typename Number>
1146template <typename OtherNumber>
1148Tensor<0, dim, Number>::operator/=(const OtherNumber &s)
1149{
1150 value /= s;
1151 return *this;
1152}
1153
1154
1155template <int dim, typename Number>
1158{
1159 return -value;
1160}
1161
1162
1163template <int dim, typename Number>
1166{
1167 Assert(dim != 0,
1168 ExcMessage("Cannot access an object of type Tensor<0,0,Number>"));
1170}
1171
1172
1173template <int dim, typename Number>
1177{
1178 // We cannot use Assert inside a CUDA kernel
1179# ifndef __CUDA_ARCH__
1180 Assert(dim != 0,
1181 ExcMessage("Cannot access an object of type Tensor<0,0,Number>"));
1182# endif
1184}
1185
1186
1187template <int dim, typename Number>
1188template <typename OtherNumber>
1189inline void
1191 unsigned int & index) const
1192{
1193 Assert(dim != 0,
1194 ExcMessage("Cannot unroll an object of type Tensor<0,0,Number>"));
1195 result[index] = value;
1196 ++index;
1197}
1198
1199
1200template <int dim, typename Number>
1201constexpr inline void
1203{
1204 // Some auto-differentiable numbers need explicit
1205 // zero initialization.
1207}
1208
1209
1210template <int dim, typename Number>
1211template <class Archive>
1212inline void
1213Tensor<0, dim, Number>::serialize(Archive &ar, const unsigned int)
1214{
1215 ar &value;
1216}
1217
1218
1219template <int dim, typename Number>
1221
1222
1223/*-------------------- Inline functions: Tensor<rank,dim> --------------------*/
1224
1225template <int rank_, int dim, typename Number>
1226template <typename ArrayLike, std::size_t... indices>
1228 Tensor<rank_, dim, Number>::Tensor(const ArrayLike &initializer,
1229 std::index_sequence<indices...>)
1230 : values{Tensor<rank_ - 1, dim, Number>(initializer[indices])...}
1231{
1232 static_assert(sizeof...(indices) == dim,
1233 "dim should match the number of indices");
1234}
1235
1236
1237
1238template <int rank_, int dim, typename Number>
1241 // We would like to use =default, but this causes compile errors with some
1242 // MSVC versions and internal compiler errors with -O1 in gcc 5.4.
1243 : values{}
1244{}
1245
1246
1247
1248template <int rank_, int dim, typename Number>
1250 Tensor<rank_, dim, Number>::Tensor(const array_type &initializer)
1251 : Tensor(initializer, std::make_index_sequence<dim>{})
1252{}
1253
1254
1255
1256template <int rank_, int dim, typename Number>
1257template <typename ElementType, typename MemorySpace>
1260 const ArrayView<ElementType, MemorySpace> &initializer)
1261{
1262 AssertDimension(initializer.size(), n_independent_components);
1263
1264 for (unsigned int i = 0; i < n_independent_components; ++i)
1265 (*this)[unrolled_to_component_indices(i)] = initializer[i];
1266}
1267
1268
1269
1270template <int rank_, int dim, typename Number>
1271template <typename OtherNumber>
1274 const Tensor<rank_, dim, OtherNumber> &initializer)
1275 : Tensor(initializer, std::make_index_sequence<dim>{})
1276{}
1277
1278
1279
1280template <int rank_, int dim, typename Number>
1281template <typename OtherNumber>
1282constexpr DEAL_II_ALWAYS_INLINE
1284 const Tensor<1, dim, Tensor<rank_ - 1, dim, OtherNumber>> &initializer)
1285 : Tensor(initializer, std::make_index_sequence<dim>{})
1286{}
1287
1288
1289
1290template <int rank_, int dim, typename Number>
1291template <typename OtherNumber>
1293 operator Tensor<1, dim, Tensor<rank_ - 1, dim, OtherNumber>>() const
1294{
1295 return Tensor<1, dim, Tensor<rank_ - 1, dim, Number>>(values);
1296}
1297
1298
1299# ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
1300template <int rank_, int dim, typename Number>
1301constexpr DEAL_II_ALWAYS_INLINE
1303{
1304 for (unsigned int i = 0; i < dim; ++i)
1305 values[i] = other.values[i];
1306}
1307
1308
1309
1310template <int rank_, int dim, typename Number>
1311constexpr DEAL_II_ALWAYS_INLINE
1313{
1314 for (unsigned int i = 0; i < dim; ++i)
1315 values[i] = other.values[i];
1316}
1317# endif
1318
1319
1320namespace internal
1321{
1322 namespace TensorSubscriptor
1323 {
1324 template <typename ArrayElementType, int dim>
1325 constexpr inline DEAL_II_ALWAYS_INLINE
1326 DEAL_II_CUDA_HOST_DEV ArrayElementType &
1327 subscript(ArrayElementType * values,
1328 const unsigned int i,
1329 std::integral_constant<int, dim>)
1330 {
1331 // We cannot use Assert in a CUDA kernel
1332# ifndef __CUDA_ARCH__
1333 AssertIndexRange(i, dim);
1334# endif
1335 return values[i];
1336 }
1337
1338 // The variables within this struct will be referenced in the next function.
1339 // It is a workaround that allows returning a reference to a static variable
1340 // while allowing constexpr evaluation of the function.
1341 // It has to be defined outside the function because constexpr functions
1342 // cannot define static variables
1343 template <typename ArrayElementType>
1344 struct Uninitialized
1345 {
1346 static ArrayElementType value;
1347 };
1348
1349 template <typename Type>
1350 Type Uninitialized<Type>::value;
1351
1352 template <typename ArrayElementType>
1353 constexpr inline DEAL_II_ALWAYS_INLINE
1354 DEAL_II_CUDA_HOST_DEV ArrayElementType &
1355 subscript(ArrayElementType *,
1356 const unsigned int,
1357 std::integral_constant<int, 0>)
1358 {
1359 // We cannot use Assert in a CUDA kernel
1360# ifndef __CUDA_ARCH__
1361 Assert(
1362 false,
1363 ExcMessage(
1364 "Cannot access elements of an object of type Tensor<rank,0,Number>."));
1365# endif
1366 return Uninitialized<ArrayElementType>::value;
1367 }
1368 } // namespace TensorSubscriptor
1369} // namespace internal
1370
1371
1372template <int rank_, int dim, typename Number>
1375 operator[](const unsigned int i)
1376{
1377 return ::internal::TensorSubscriptor::subscript(
1378 values, i, std::integral_constant<int, dim>());
1379}
1380
1381
1382template <int rank_, int dim, typename Number>
1383constexpr DEAL_II_ALWAYS_INLINE
1385 Tensor<rank_, dim, Number>::operator[](const unsigned int i) const
1386{
1387# ifndef DEAL_II_COMPILER_CUDA_AWARE
1388 AssertIndexRange(i, dim);
1389# endif
1390
1391 return values[i];
1392}
1393
1394
1395template <int rank_, int dim, typename Number>
1396constexpr inline DEAL_II_ALWAYS_INLINE const Number &
1398 operator[](const TableIndices<rank_> &indices) const
1399{
1400# ifndef DEAL_II_COMPILER_CUDA_AWARE
1401 Assert(dim != 0,
1402 ExcMessage("Cannot access an object of type Tensor<rank_,0,Number>"));
1403# endif
1404
1405 return TensorAccessors::extract<rank_>(*this, indices);
1406}
1407
1408
1409
1410template <int rank_, int dim, typename Number>
1412 operator[](const TableIndices<rank_> &indices)
1413{
1414# ifndef DEAL_II_COMPILER_CUDA_AWARE
1415 Assert(dim != 0,
1416 ExcMessage("Cannot access an object of type Tensor<rank_,0,Number>"));
1417# endif
1418
1419 return TensorAccessors::extract<rank_>(*this, indices);
1420}
1421
1422
1423
1424template <int rank_, int dim, typename Number>
1425inline Number *
1427{
1428 return std::addressof(
1429 this->operator[](this->unrolled_to_component_indices(0)));
1430}
1431
1432
1433
1434template <int rank_, int dim, typename Number>
1435inline const Number *
1437{
1438 return std::addressof(
1439 this->operator[](this->unrolled_to_component_indices(0)));
1440}
1441
1442
1443
1444template <int rank_, int dim, typename Number>
1445inline Number *
1447{
1448 return begin_raw() + n_independent_components;
1449}
1450
1451
1452
1453template <int rank_, int dim, typename Number>
1454inline const Number *
1456{
1457 return begin_raw() + n_independent_components;
1458}
1459
1460
1461
1462template <int rank_, int dim, typename Number>
1463template <typename OtherNumber>
1466{
1467 // The following loop could be written more concisely using std::copy, but
1468 // that function is only constexpr from C++20 on.
1469 for (unsigned int i = 0; i < dim; ++i)
1470 values[i] = t.values[i];
1471 return *this;
1472}
1473
1474
1475
1476template <int rank_, int dim, typename Number>
1479{
1481 (void)d;
1482
1483 for (unsigned int i = 0; i < dim; ++i)
1485 return *this;
1486}
1487
1488
1489# ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
1490template <int rank_, int dim, typename Number>
1493{
1494 for (unsigned int i = 0; i < dim; ++i)
1495 values[i] = other.values[i];
1496 return *this;
1497}
1498
1499
1500
1501template <int rank_, int dim, typename Number>
1504 operator=(Tensor<rank_, dim, Number> &&other) noexcept
1505{
1506 for (unsigned int i = 0; i < dim; ++i)
1507 values[i] = other.values[i];
1508 return *this;
1509}
1510# endif
1511
1512
1513template <int rank_, int dim, typename Number>
1514template <typename OtherNumber>
1515constexpr inline bool
1518{
1519 for (unsigned int i = 0; i < dim; ++i)
1520 if (values[i] != p.values[i])
1521 return false;
1522 return true;
1523}
1524
1525
1526// At some places in the library, we have Point<0> for formal reasons
1527// (e.g., we sometimes have Quadrature<dim-1> for faces, so we have
1528// Quadrature<0> for dim=1, and then we have Point<0>). To avoid warnings
1529// in the above function that the loop end check always fails, we
1530// implement this function here
1531template <>
1532template <>
1533constexpr inline bool
1535{
1536 return true;
1537}
1538
1539
1540template <int rank_, int dim, typename Number>
1541template <typename OtherNumber>
1542constexpr bool
1545{
1546 return !((*this) == p);
1547}
1548
1549
1550template <int rank_, int dim, typename Number>
1551template <typename OtherNumber>
1552constexpr inline DEAL_II_ALWAYS_INLINE
1556{
1557 for (unsigned int i = 0; i < dim; ++i)
1558 values[i] += p.values[i];
1559 return *this;
1560}
1561
1562
1563template <int rank_, int dim, typename Number>
1564template <typename OtherNumber>
1565constexpr inline DEAL_II_ALWAYS_INLINE
1569{
1570 for (unsigned int i = 0; i < dim; ++i)
1571 values[i] -= p.values[i];
1572 return *this;
1573}
1574
1575
1576template <int rank_, int dim, typename Number>
1577template <typename OtherNumber>
1578constexpr inline DEAL_II_ALWAYS_INLINE
1580 Tensor<rank_, dim, Number>::operator*=(const OtherNumber &s)
1581{
1582 for (unsigned int i = 0; i < dim; ++i)
1583 values[i] *= s;
1584 return *this;
1585}
1586
1587
1588namespace internal
1589{
1590 namespace TensorImplementation
1591 {
1592 template <int rank,
1593 int dim,
1594 typename Number,
1595 typename OtherNumber,
1596 typename std::enable_if<
1597 !std::is_integral<
1598 typename ProductType<Number, OtherNumber>::type>::value &&
1599 !std::is_same<Number, Differentiation::SD::Expression>::value,
1600 int>::type = 0>
1601 constexpr DEAL_II_CUDA_HOST_DEV inline DEAL_II_ALWAYS_INLINE void
1603 const OtherNumber &factor)
1604 {
1605 const Number inverse_factor = Number(1.) / factor;
1606 // recurse over the base objects
1607 for (unsigned int d = 0; d < dim; ++d)
1608 t[d] *= inverse_factor;
1609 }
1610
1611
1612 template <int rank,
1613 int dim,
1614 typename Number,
1615 typename OtherNumber,
1616 typename std::enable_if<
1617 std::is_integral<
1618 typename ProductType<Number, OtherNumber>::type>::value ||
1619 std::is_same<Number, Differentiation::SD::Expression>::value,
1620 int>::type = 0>
1621 constexpr DEAL_II_CUDA_HOST_DEV inline DEAL_II_ALWAYS_INLINE void
1623 const OtherNumber &factor)
1624 {
1625 // recurse over the base objects
1626 for (unsigned int d = 0; d < dim; ++d)
1627 t[d] /= factor;
1628 }
1629 } // namespace TensorImplementation
1630} // namespace internal
1631
1632
1633template <int rank_, int dim, typename Number>
1634template <typename OtherNumber>
1635constexpr inline DEAL_II_ALWAYS_INLINE
1637 Tensor<rank_, dim, Number>::operator/=(const OtherNumber &s)
1638{
1640 return *this;
1641}
1642
1643
1644template <int rank_, int dim, typename Number>
1645constexpr inline DEAL_II_ALWAYS_INLINE
1648{
1650
1651 for (unsigned int i = 0; i < dim; ++i)
1652 tmp.values[i] = -values[i];
1653
1654 return tmp;
1655}
1656
1657
1658template <int rank_, int dim, typename Number>
1661{
1662 return std::sqrt(norm_square());
1663}
1664
1665
1666template <int rank_, int dim, typename Number>
1670{
1672 typename numbers::NumberTraits<Number>::real_type>::value(0.0);
1673 for (unsigned int i = 0; i < dim; ++i)
1674 s += values[i].norm_square();
1675
1676 return s;
1677}
1678
1679
1680template <int rank_, int dim, typename Number>
1681template <typename OtherNumber>
1682inline void
1684{
1685 AssertDimension(result.size(),
1686 (Utilities::fixed_power<rank_, unsigned int>(dim)));
1687
1688 unsigned int index = 0;
1689 unroll_recursion(result, index);
1690}
1691
1692
1693template <int rank_, int dim, typename Number>
1694template <typename OtherNumber>
1695inline void
1697 unsigned int & index) const
1698{
1699 for (unsigned int i = 0; i < dim; ++i)
1700 values[i].unroll_recursion(result, index);
1701}
1702
1703
1704template <int rank_, int dim, typename Number>
1705constexpr inline unsigned int
1707 const TableIndices<rank_> &indices)
1708{
1709 unsigned int index = 0;
1710 for (int r = 0; r < rank_; ++r)
1711 index = index * dim + indices[r];
1712
1713 return index;
1714}
1715
1716
1717
1718namespace internal
1719{
1720 // unrolled_to_component_indices is instantiated from DataOut for dim==0
1721 // and rank=2. Make sure we don't have compiler warnings.
1722
1723 template <int dim>
1724 inline constexpr unsigned int
1725 mod(const unsigned int x)
1726 {
1727 return x % dim;
1728 }
1729
1730 template <>
1731 inline unsigned int
1732 mod<0>(const unsigned int x)
1733 {
1734 Assert(false, ExcInternalError());
1735 return x;
1736 }
1737
1738 template <int dim>
1739 inline constexpr unsigned int
1740 div(const unsigned int x)
1741 {
1742 return x / dim;
1743 }
1744
1745 template <>
1746 inline unsigned int
1747 div<0>(const unsigned int x)
1748 {
1749 Assert(false, ExcInternalError());
1750 return x;
1751 }
1752
1753} // namespace internal
1754
1755
1756
1757template <int rank_, int dim, typename Number>
1758constexpr inline TableIndices<rank_>
1760{
1761 AssertIndexRange(i, n_independent_components);
1762
1763 TableIndices<rank_> indices;
1764
1765 unsigned int remainder = i;
1766 for (int r = rank_ - 1; r >= 0; --r)
1767 {
1768 indices[r] = internal::mod<dim>(remainder);
1769 remainder = internal::div<dim>(remainder);
1770 }
1771 Assert(remainder == 0, ExcInternalError());
1772
1773 return indices;
1774}
1775
1776
1777template <int rank_, int dim, typename Number>
1778constexpr inline void
1780{
1781 for (unsigned int i = 0; i < dim; ++i)
1783}
1784
1785
1786template <int rank_, int dim, typename Number>
1787constexpr std::size_t
1789{
1790 return sizeof(Tensor<rank_, dim, Number>);
1791}
1792
1793
1794template <int rank_, int dim, typename Number>
1795template <class Archive>
1796inline void
1797Tensor<rank_, dim, Number>::serialize(Archive &ar, const unsigned int)
1798{
1799 ar &values;
1800}
1801
1802
1803template <int rank_, int dim, typename Number>
1805
1806#endif // DOXYGEN
1807
1808/* ----------------- Non-member functions operating on tensors. ------------ */
1809
1814
1822template <int rank_, int dim, typename Number>
1823inline std::ostream &
1824operator<<(std::ostream &out, const Tensor<rank_, dim, Number> &p)
1825{
1826 for (unsigned int i = 0; i < dim; ++i)
1827 {
1828 out << p[i];
1829 if (i != dim - 1)
1830 out << ' ';
1831 }
1832
1833 return out;
1834}
1835
1836
1843template <int dim, typename Number>
1844inline std::ostream &
1845operator<<(std::ostream &out, const Tensor<0, dim, Number> &p)
1846{
1847 out << static_cast<const Number &>(p);
1848 return out;
1849}
1850
1851
1853
1857
1858
1869template <int dim, typename Number, typename Other>
1872 operator*(const Other &object, const Tensor<0, dim, Number> &t)
1873{
1874 return object * static_cast<const Number &>(t);
1875}
1876
1877
1878
1889template <int dim, typename Number, typename Other>
1892 operator*(const Tensor<0, dim, Number> &t, const Other &object)
1893{
1894 return static_cast<const Number &>(t) * object;
1895}
1896
1897
1909template <int dim, typename Number, typename OtherNumber>
1913 const Tensor<0, dim, OtherNumber> &src2)
1914{
1915 return static_cast<const Number &>(src1) *
1916 static_cast<const OtherNumber &>(src2);
1917}
1918
1919
1927template <int dim, typename Number, typename OtherNumber>
1929 Tensor<0,
1930 dim,
1931 typename ProductType<Number,
1932 typename EnableIfScalar<OtherNumber>::type>::type>
1933 operator/(const Tensor<0, dim, Number> &t, const OtherNumber &factor)
1934{
1935 return static_cast<const Number &>(t) / factor;
1936}
1937
1938
1946template <int dim, typename Number, typename OtherNumber>
1951{
1952 return static_cast<const Number &>(p) + static_cast<const OtherNumber &>(q);
1953}
1954
1955
1963template <int dim, typename Number, typename OtherNumber>
1968{
1969 return static_cast<const Number &>(p) - static_cast<const OtherNumber &>(q);
1970}
1971
1972
1985template <int rank, int dim, typename Number, typename OtherNumber>
1987 Tensor<rank,
1988 dim,
1989 typename ProductType<Number,
1990 typename EnableIfScalar<OtherNumber>::type>::type>
1991 operator*(const Tensor<rank, dim, Number> &t, const OtherNumber &factor)
1992{
1993 // recurse over the base objects
1995 for (unsigned int d = 0; d < dim; ++d)
1996 tt[d] = t[d] * factor;
1997 return tt;
1998}
1999
2000
2013template <int rank, int dim, typename Number, typename OtherNumber>
2015 Tensor<rank,
2016 dim,
2018 OtherNumber>::type>
2019 operator*(const Number &factor, const Tensor<rank, dim, OtherNumber> &t)
2020{
2021 // simply forward to the operator above
2022 return t * factor;
2023}
2024
2025
2026namespace internal
2027{
2028 namespace TensorImplementation
2029 {
2030 template <int rank,
2031 int dim,
2032 typename Number,
2033 typename OtherNumber,
2034 typename std::enable_if<
2035 !std::is_integral<
2037 int>::type = 0>
2041 const OtherNumber & factor)
2042 {
2044 const Number inverse_factor = Number(1.) / factor;
2045 // recurse over the base objects
2046 for (unsigned int d = 0; d < dim; ++d)
2047 tt[d] = t[d] * inverse_factor;
2048 return tt;
2049 }
2050
2051
2052 template <int rank,
2053 int dim,
2054 typename Number,
2055 typename OtherNumber,
2056 typename std::enable_if<
2057 std::is_integral<
2059 int>::type = 0>
2063 const OtherNumber & factor)
2064 {
2066 // recurse over the base objects
2067 for (unsigned int d = 0; d < dim; ++d)
2068 tt[d] = t[d] / factor;
2069 return tt;
2070 }
2071 } // namespace TensorImplementation
2072} // namespace internal
2073
2074
2084template <int rank, int dim, typename Number, typename OtherNumber>
2086 Tensor<rank,
2087 dim,
2088 typename ProductType<Number,
2089 typename EnableIfScalar<OtherNumber>::type>::type>
2090 operator/(const Tensor<rank, dim, Number> &t, const OtherNumber &factor)
2091{
2093}
2094
2095
2105template <int rank, int dim, typename Number, typename OtherNumber>
2110{
2112
2113 for (unsigned int i = 0; i < dim; ++i)
2114 tmp[i] += q[i];
2115
2116 return tmp;
2117}
2118
2119
2129template <int rank, int dim, typename Number, typename OtherNumber>
2134{
2136
2137 for (unsigned int i = 0; i < dim; ++i)
2138 tmp[i] -= q[i];
2139
2140 return tmp;
2141}
2142
2149template <int dim, typename Number, typename OtherNumber>
2150inline constexpr DEAL_II_ALWAYS_INLINE
2153 const Tensor<0, dim, OtherNumber> &src2)
2154{
2156
2157 tmp *= src2;
2158
2159 return tmp;
2160}
2161
2178template <int rank, int dim, typename Number, typename OtherNumber>
2179inline constexpr DEAL_II_ALWAYS_INLINE
2183{
2185
2186 for (unsigned int i = 0; i < dim; ++i)
2189
2190 return tmp;
2191}
2192
2194
2198
2199
2222template <int rank_1,
2223 int rank_2,
2224 int dim,
2225 typename Number,
2226 typename OtherNumber,
2227 typename = typename std::enable_if<rank_1 >= 1 && rank_2 >= 1>::type>
2228constexpr inline DEAL_II_ALWAYS_INLINE
2229 typename Tensor<rank_1 + rank_2 - 2,
2230 dim,
2231 typename ProductType<Number, OtherNumber>::type>::tensor_type
2234{
2235 typename Tensor<rank_1 + rank_2 - 2,
2236 dim,
2237 typename ProductType<Number, OtherNumber>::type>::tensor_type
2238 result{};
2239
2240 TensorAccessors::internal::
2241 ReorderedIndexView<0, rank_2, const Tensor<rank_2, dim, OtherNumber>>
2242 reordered = TensorAccessors::reordered_index_view<0, rank_2>(src2);
2243 TensorAccessors::contract<1, rank_1, rank_2, dim>(result, src1, reordered);
2244
2245 return result;
2246}
2247
2248
2277template <int index_1,
2278 int index_2,
2279 int rank_1,
2280 int rank_2,
2281 int dim,
2282 typename Number,
2283 typename OtherNumber>
2284constexpr inline DEAL_II_ALWAYS_INLINE
2285 typename Tensor<rank_1 + rank_2 - 2,
2286 dim,
2287 typename ProductType<Number, OtherNumber>::type>::tensor_type
2290{
2291 Assert(0 <= index_1 && index_1 < rank_1,
2292 ExcMessage(
2293 "The specified index_1 must lie within the range [0,rank_1)"));
2294 Assert(0 <= index_2 && index_2 < rank_2,
2295 ExcMessage(
2296 "The specified index_2 must lie within the range [0,rank_2)"));
2297
2298 using namespace TensorAccessors;
2299 using namespace TensorAccessors::internal;
2300
2301 // Reorder index_1 to the end of src1:
2303 reord_01 = reordered_index_view<index_1, rank_1>(src1);
2304
2305 // Reorder index_2 to the end of src2:
2306 const ReorderedIndexView<index_2,
2307 rank_2,
2309 reord_02 = reordered_index_view<index_2, rank_2>(src2);
2310
2311 typename Tensor<rank_1 + rank_2 - 2,
2312 dim,
2313 typename ProductType<Number, OtherNumber>::type>::tensor_type
2314 result{};
2315 TensorAccessors::contract<1, rank_1, rank_2, dim>(result, reord_01, reord_02);
2316 return result;
2317}
2318
2319
2350template <int index_1,
2351 int index_2,
2352 int index_3,
2353 int index_4,
2354 int rank_1,
2355 int rank_2,
2356 int dim,
2357 typename Number,
2358 typename OtherNumber>
2359constexpr inline
2360 typename Tensor<rank_1 + rank_2 - 4,
2361 dim,
2362 typename ProductType<Number, OtherNumber>::type>::tensor_type
2365{
2366 Assert(0 <= index_1 && index_1 < rank_1,
2367 ExcMessage(
2368 "The specified index_1 must lie within the range [0,rank_1)"));
2369 Assert(0 <= index_3 && index_3 < rank_1,
2370 ExcMessage(
2371 "The specified index_3 must lie within the range [0,rank_1)"));
2372 Assert(index_1 != index_3,
2373 ExcMessage("index_1 and index_3 must not be the same"));
2374 Assert(0 <= index_2 && index_2 < rank_2,
2375 ExcMessage(
2376 "The specified index_2 must lie within the range [0,rank_2)"));
2377 Assert(0 <= index_4 && index_4 < rank_2,
2378 ExcMessage(
2379 "The specified index_4 must lie within the range [0,rank_2)"));
2380 Assert(index_2 != index_4,
2381 ExcMessage("index_2 and index_4 must not be the same"));
2382
2383 using namespace TensorAccessors;
2384 using namespace TensorAccessors::internal;
2385
2386 // Reorder index_1 to the end of src1:
2388 reord_1 = TensorAccessors::reordered_index_view<index_1, rank_1>(src1);
2389
2390 // Reorder index_2 to the end of src2:
2392 reord_2 = TensorAccessors::reordered_index_view<index_2, rank_2>(src2);
2393
2394 // Now, reorder index_3 to the end of src1. We have to make sure to
2395 // preserve the original ordering: index_1 has been removed. If
2396 // index_3 > index_1, we have to use (index_3 - 1) instead:
2398 (index_3 < index_1 ? index_3 : index_3 - 1),
2399 rank_1,
2400 ReorderedIndexView<index_1, rank_1, const Tensor<rank_1, dim, Number>>>
2401 reord_3 =
2402 TensorAccessors::reordered_index_view < index_3 < index_1 ? index_3 :
2403 index_3 - 1,
2404 rank_1 > (reord_1);
2405
2406 // Now, reorder index_4 to the end of src2. We have to make sure to
2407 // preserve the original ordering: index_2 has been removed. If
2408 // index_4 > index_2, we have to use (index_4 - 1) instead:
2410 (index_4 < index_2 ? index_4 : index_4 - 1),
2411 rank_2,
2413 reord_4 =
2414 TensorAccessors::reordered_index_view < index_4 < index_2 ? index_4 :
2415 index_4 - 1,
2416 rank_2 > (reord_2);
2417
2418 typename Tensor<rank_1 + rank_2 - 4,
2419 dim,
2420 typename ProductType<Number, OtherNumber>::type>::tensor_type
2421 result{};
2422 TensorAccessors::contract<2, rank_1, rank_2, dim>(result, reord_3, reord_4);
2423 return result;
2424}
2425
2426
2439template <int rank, int dim, typename Number, typename OtherNumber>
2440constexpr inline DEAL_II_ALWAYS_INLINE
2443 const Tensor<rank, dim, OtherNumber> &right)
2444{
2446 TensorAccessors::contract<rank, rank, rank, dim>(result, left, right);
2447 return result;
2448}
2449
2450
2468template <template <int, int, typename> class TensorT1,
2469 template <int, int, typename> class TensorT2,
2470 template <int, int, typename> class TensorT3,
2471 int rank_1,
2472 int rank_2,
2473 int dim,
2474 typename T1,
2475 typename T2,
2476 typename T3>
2477constexpr inline DEAL_II_ALWAYS_INLINE
2479 contract3(const TensorT1<rank_1, dim, T1> & left,
2480 const TensorT2<rank_1 + rank_2, dim, T2> &middle,
2481 const TensorT3<rank_2, dim, T3> & right)
2482{
2483 using return_type =
2485 return TensorAccessors::contract3<rank_1, rank_2, dim, return_type>(left,
2486 middle,
2487 right);
2488}
2489
2490
2501template <int rank_1,
2502 int rank_2,
2503 int dim,
2504 typename Number,
2505 typename OtherNumber>
2506constexpr inline DEAL_II_ALWAYS_INLINE
2510{
2511 typename Tensor<rank_1 + rank_2,
2512 dim,
2513 typename ProductType<Number, OtherNumber>::type>::tensor_type
2514 result{};
2515 TensorAccessors::contract<0, rank_1, rank_2, dim>(result, src1, src2);
2516 return result;
2517}
2518
2519
2521
2525
2526
2537template <int dim, typename Number>
2540{
2541 Assert(dim == 2, ExcInternalError());
2542
2544
2545 result[0] = src[1];
2546 result[1] = -src[0];
2547
2548 return result;
2549}
2550
2551
2561template <int dim, typename Number1, typename Number2>
2562constexpr inline DEAL_II_ALWAYS_INLINE
2565 const Tensor<1, dim, Number2> &src2)
2566{
2567 Assert(dim == 3, ExcInternalError());
2568
2570
2571 // avoid compiler warnings
2572 constexpr int s0 = 0 % dim;
2573 constexpr int s1 = 1 % dim;
2574 constexpr int s2 = 2 % dim;
2575
2576 result[s0] = src1[s1] * src2[s2] - src1[s2] * src2[s1];
2577 result[s1] = src1[s2] * src2[s0] - src1[s0] * src2[s2];
2578 result[s2] = src1[s0] * src2[s1] - src1[s1] * src2[s0];
2579
2580 return result;
2581}
2582
2583
2585
2589
2590
2596template <int dim, typename Number>
2597constexpr inline DEAL_II_ALWAYS_INLINE Number
2599{
2600 // Compute the determinant using the Laplace expansion of the
2601 // determinant. We expand along the last row.
2602 Number det = internal::NumberType<Number>::value(0.0);
2603
2604 for (unsigned int k = 0; k < dim; ++k)
2605 {
2606 Tensor<2, dim - 1, Number> minor;
2607 for (unsigned int i = 0; i < dim - 1; ++i)
2608 for (unsigned int j = 0; j < dim - 1; ++j)
2609 minor[i][j] = t[i][j < k ? j : j + 1];
2610
2611 const Number cofactor = ((k % 2 == 0) ? -1. : 1.) * determinant(minor);
2612
2613 det += t[dim - 1][k] * cofactor;
2614 }
2615
2616 return ((dim % 2 == 0) ? 1. : -1.) * det;
2617}
2618
2624template <typename Number>
2625constexpr DEAL_II_ALWAYS_INLINE Number
2627{
2628 return t[0][0];
2629}
2630
2636template <typename Number>
2637constexpr DEAL_II_ALWAYS_INLINE Number
2639{
2640 // hard-coded for efficiency reasons
2641 return t[0][0] * t[1][1] - t[1][0] * t[0][1];
2642}
2643
2649template <typename Number>
2650constexpr DEAL_II_ALWAYS_INLINE Number
2652{
2653 // hard-coded for efficiency reasons
2654 const Number C0 = internal::NumberType<Number>::value(t[1][1] * t[2][2]) -
2655 internal::NumberType<Number>::value(t[1][2] * t[2][1]);
2656 const Number C1 = internal::NumberType<Number>::value(t[1][2] * t[2][0]) -
2657 internal::NumberType<Number>::value(t[1][0] * t[2][2]);
2658 const Number C2 = internal::NumberType<Number>::value(t[1][0] * t[2][1]) -
2659 internal::NumberType<Number>::value(t[1][1] * t[2][0]);
2660 return t[0][0] * C0 + t[0][1] * C1 + t[0][2] * C2;
2661}
2662
2663
2670template <int dim, typename Number>
2671constexpr inline DEAL_II_ALWAYS_INLINE Number
2673{
2674 Number t = d[0][0];
2675 for (unsigned int i = 1; i < dim; ++i)
2676 t += d[i][i];
2677 return t;
2678}
2679
2680
2689template <int dim, typename Number>
2690constexpr inline Tensor<2, dim, Number>
2692{
2693 Number return_tensor[dim][dim];
2694
2695 // if desired, take over the
2696 // inversion of a 4x4 tensor
2697 // from the FullMatrix
2699
2700 return Tensor<2, dim, Number>(return_tensor);
2701}
2702
2703
2704#ifndef DOXYGEN
2705
2706template <typename Number>
2709{
2710 Tensor<2, 1, Number> return_tensor;
2711
2712 return_tensor[0][0] = internal::NumberType<Number>::value(1.0 / t[0][0]);
2713
2714 return return_tensor;
2715}
2716
2717
2718template <typename Number>
2721{
2722 Tensor<2, 2, Number> return_tensor;
2723
2724 const Number inv_det_t = internal::NumberType<Number>::value(
2725 1.0 / (t[0][0] * t[1][1] - t[1][0] * t[0][1]));
2726 return_tensor[0][0] = t[1][1];
2727 return_tensor[0][1] = -t[0][1];
2728 return_tensor[1][0] = -t[1][0];
2729 return_tensor[1][1] = t[0][0];
2730 return_tensor *= inv_det_t;
2731
2732 return return_tensor;
2733}
2734
2735
2736template <typename Number>
2739{
2740 Tensor<2, 3, Number> return_tensor;
2741
2742 return_tensor[0][0] = internal::NumberType<Number>::value(t[1][1] * t[2][2]) -
2743 internal::NumberType<Number>::value(t[1][2] * t[2][1]);
2744 return_tensor[0][1] = internal::NumberType<Number>::value(t[0][2] * t[2][1]) -
2745 internal::NumberType<Number>::value(t[0][1] * t[2][2]);
2746 return_tensor[0][2] = internal::NumberType<Number>::value(t[0][1] * t[1][2]) -
2747 internal::NumberType<Number>::value(t[0][2] * t[1][1]);
2748 return_tensor[1][0] = internal::NumberType<Number>::value(t[1][2] * t[2][0]) -
2749 internal::NumberType<Number>::value(t[1][0] * t[2][2]);
2750 return_tensor[1][1] = internal::NumberType<Number>::value(t[0][0] * t[2][2]) -
2751 internal::NumberType<Number>::value(t[0][2] * t[2][0]);
2752 return_tensor[1][2] = internal::NumberType<Number>::value(t[0][2] * t[1][0]) -
2753 internal::NumberType<Number>::value(t[0][0] * t[1][2]);
2754 return_tensor[2][0] = internal::NumberType<Number>::value(t[1][0] * t[2][1]) -
2755 internal::NumberType<Number>::value(t[1][1] * t[2][0]);
2756 return_tensor[2][1] = internal::NumberType<Number>::value(t[0][1] * t[2][0]) -
2757 internal::NumberType<Number>::value(t[0][0] * t[2][1]);
2758 return_tensor[2][2] = internal::NumberType<Number>::value(t[0][0] * t[1][1]) -
2759 internal::NumberType<Number>::value(t[0][1] * t[1][0]);
2760 const Number inv_det_t = internal::NumberType<Number>::value(
2761 1.0 / (t[0][0] * return_tensor[0][0] + t[0][1] * return_tensor[1][0] +
2762 t[0][2] * return_tensor[2][0]));
2763 return_tensor *= inv_det_t;
2764
2765 return return_tensor;
2766}
2767
2768#endif /* DOXYGEN */
2769
2770
2776template <int dim, typename Number>
2779{
2781 for (unsigned int i = 0; i < dim; ++i)
2782 {
2783 tt[i][i] = t[i][i];
2784 for (unsigned int j = i + 1; j < dim; ++j)
2785 {
2786 tt[i][j] = t[j][i];
2787 tt[j][i] = t[i][j];
2788 };
2789 }
2790 return tt;
2791}
2792
2793
2807template <int dim, typename Number>
2808constexpr Tensor<2, dim, Number>
2810{
2811 return determinant(t) * invert(t);
2812}
2813
2814
2828template <int dim, typename Number>
2829constexpr Tensor<2, dim, Number>
2831{
2832 return transpose(adjugate(t));
2833}
2834
2835
2899template <int dim, typename Number>
2902
2903
2911template <int dim, typename Number>
2912inline Number
2914{
2916 for (unsigned int j = 0; j < dim; ++j)
2917 {
2919 for (unsigned int i = 0; i < dim; ++i)
2920 sum += std::fabs(t[i][j]);
2921
2922 if (sum > max)
2923 max = sum;
2924 }
2925
2926 return max;
2927}
2928
2929
2937template <int dim, typename Number>
2938inline Number
2940{
2942 for (unsigned int i = 0; i < dim; ++i)
2943 {
2945 for (unsigned int j = 0; j < dim; ++j)
2946 sum += std::fabs(t[i][j]);
2947
2948 if (sum > max)
2949 max = sum;
2950 }
2951
2952 return max;
2953}
2954
2956
2957
2958#ifndef DOXYGEN
2959
2960
2961# ifdef DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING
2962
2963// Specialization of functions for ADOL-C number types when
2964// the advanced branching feature is used
2965template <int dim>
2966inline adouble
2968{
2970 for (unsigned int j = 0; j < dim; ++j)
2971 {
2973 for (unsigned int i = 0; i < dim; ++i)
2974 sum += std::fabs(t[i][j]);
2975
2976 condassign(max, (sum > max), sum, max);
2977 }
2978
2979 return max;
2980}
2981
2982
2983template <int dim>
2984inline adouble
2986{
2988 for (unsigned int i = 0; i < dim; ++i)
2989 {
2991 for (unsigned int j = 0; j < dim; ++j)
2992 sum += std::fabs(t[i][j]);
2993
2994 condassign(max, (sum > max), sum, max);
2995 }
2996
2997 return max;
2998}
2999
3000# endif // DEAL_II_ADOLC_WITH_ADVANCED_BRANCHING
3001
3002
3003#endif // DOXYGEN
3004
3006
3007#endif
OutputOperator< VectorType > & operator<<(OutputOperator< VectorType > &out, unsigned int step)
Definition: operator.h:165
std::size_t size() const
Definition: array_view.h:574
DerivativeForm< 1, spacedim, dim, Number > transpose(const DerivativeForm< 1, dim, spacedim, Number > &DF)
Definition: point.h:111
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
SymmetricTensor< rank, dim, Number > sum(const SymmetricTensor< rank, dim, Number > &local, const MPI_Comm &mpi_communicator)
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &t)
constexpr Tensor & operator*=(const OtherNumber &factor)
void serialize(Archive &ar, const unsigned int version)
constexpr Tensor & operator/=(const OtherNumber &factor)
const Number * end_raw() const
constexpr Tensor & operator-=(const Tensor< 0, dim, OtherNumber > &rhs)
constexpr Tensor(const Tensor< 0, dim, OtherNumber > &initializer)
constexpr Tensor(const OtherNumber &initializer)
constexpr void clear()
constexpr Tensor & operator=(const OtherNumber &d)
constexpr real_type norm_square() const
constexpr bool operator!=(const Tensor< 0, dim, OtherNumber > &rhs) const
constexpr Tensor & operator=(const Tensor< 0, dim, OtherNumber > &rhs)
const Number * begin_raw() const
real_type norm() const
constexpr Tensor & operator+=(const Tensor< 0, dim, OtherNumber > &rhs)
constexpr bool operator==(const Tensor< 0, dim, OtherNumber > &rhs) const
typename numbers::NumberTraits< Number >::real_type real_type
Definition: tensor.h:126
constexpr Tensor operator-() const
void unroll_recursion(Vector< OtherNumber > &result, unsigned int &start_index) const
Definition: tensor.h:472
constexpr Tensor & operator/=(const OtherNumber &factor)
constexpr Tensor(const ArrayView< ElementType, MemorySpace > &initializer)
constexpr Tensor< 2, dim, Number > cofactor(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2830
constexpr bool operator==(const Tensor< rank_, dim, OtherNumber > &) const
constexpr Tensor< rank, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/(const Tensor< rank, dim, Number > &t, const OtherNumber &factor)
Definition: tensor.h:2090
constexpr Tensor(const Tensor< 1, dim, Tensor< rank_ - 1, dim, OtherNumber > > &initializer)
constexpr Tensor< rank_1+rank_2, dim, typename ProductType< Number, OtherNumber >::type > outer_product(const Tensor< rank_1, dim, Number > &src1, const Tensor< rank_2, dim, OtherNumber > &src2)
Definition: tensor.h:2508
constexpr Tensor< 2, dim, Number > adjugate(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2809
typename Tensor< rank_ - 1, dim, Number >::array_type[(dim !=0) ? dim :1] array_type
Definition: tensor.h:512
constexpr const Number & operator[](const TableIndices< rank_ > &indices) const
constexpr ProductType< T1, typenameProductType< T2, T3 >::type >::type contract3(const TensorT1< rank_1, dim, T1 > &left, const TensorT2< rank_1+rank_2, dim, T2 > &middle, const TensorT3< rank_2, dim, T3 > &right)
Definition: tensor.h:2479
constexpr Tensor< 2, dim, Number > transpose(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2778
constexpr Tensor< 0, dim, typename ProductType< Number, OtherNumber >::type > operator-(const Tensor< 0, dim, Number > &p, const Tensor< 0, dim, OtherNumber > &q)
Definition: tensor.h:1966
constexpr Tensor< 0, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/(const Tensor< 0, dim, Number > &t, const OtherNumber &factor)
Definition: tensor.h:1933
Number * begin_raw()
static constexpr unsigned int rank
Definition: tensor.h:491
constexpr Number determinant(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2598
constexpr Tensor(const Tensor< rank_, dim, OtherNumber > &initializer)
numbers::NumberTraits< Number >::real_type norm() const
constexpr Tensor & operator-=(const Tensor< rank_, dim, OtherNumber > &)
constexpr void clear()
void unroll(Vector< OtherNumber > &result) const
static constexpr unsigned int component_to_unrolled_index(const TableIndices< rank_ > &indices)
constexpr ProductType< Number, OtherNumber >::type operator*(const Tensor< 0, dim, Number > &src1, const Tensor< 0, dim, OtherNumber > &src2)
Definition: tensor.h:1912
const Number * begin_raw() const
constexpr bool operator!=(const Tensor< rank_, dim, OtherNumber > &) const
constexpr ProductType< Number, OtherNumber >::type scalar_product(const Tensor< rank, dim, Number > &left, const Tensor< rank, dim, OtherNumber > &right)
Definition: tensor.h:2442
constexpr Tensor()
constexpr Tensor< 0, dim, typename ProductType< Number, OtherNumber >::type > schur_product(const Tensor< 0, dim, Number > &src1, const Tensor< 0, dim, OtherNumber > &src2)
Definition: tensor.h:2152
constexpr value_type & operator[](const unsigned int i)
Number * end_raw()
typename Tensor< rank_ - 1, dim, Number >::tensor_type value_type
Definition: tensor.h:505
friend class Tensor
Definition: tensor.h:838
constexpr Tensor< rank, dim, typename ProductType< Number, OtherNumber >::type > operator+(const Tensor< rank, dim, Number > &p, const Tensor< rank, dim, OtherNumber > &q)
Definition: tensor.h:2108
Number linfty_norm(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2939
constexpr ProductType< Other, Number >::type operator*(const Other &object, const Tensor< 0, dim, Number > &t)
Definition: tensor.h:1872
constexpr Tensor< rank_1+rank_2-4, dim, typenameProductType< Number, OtherNumber >::type >::tensor_type double_contract(const Tensor< rank_1, dim, Number > &src1, const Tensor< rank_2, dim, OtherNumber > &src2)
Definition: tensor.h:2363
Tensor< 2, dim, Number > project_onto_orthogonal_tensors(const Tensor< 2, dim, Number > &A)
Number l1_norm(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2913
constexpr Number trace(const Tensor< 2, dim, Number > &d)
Definition: tensor.h:2672
static constexpr unsigned int dimension
Definition: tensor.h:486
static constexpr TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
constexpr Tensor< 1, dim, Number > cross_product_2d(const Tensor< 1, dim, Number > &src)
Definition: tensor.h:2539
constexpr Tensor< rank, dim, typename ProductType< typename EnableIfScalar< Number >::type, OtherNumber >::type > operator*(const Number &factor, const Tensor< rank, dim, OtherNumber > &t)
Definition: tensor.h:2019
static constexpr std::size_t memory_consumption()
constexpr Tensor & operator=(const Number &d)
OtherNumber::type::tensor_type operator*(const Tensor< rank_1, dim, Number > &src1, const Tensor< rank_2, dim, OtherNumber > &src2)
Definition: tensor.h:2232
constexpr Number determinant(const Tensor< 2, 1, Number > &t)
Definition: tensor.h:2626
constexpr Tensor< 0, dim, typename ProductType< Number, OtherNumber >::type > operator+(const Tensor< 0, dim, Number > &p, const Tensor< 0, dim, OtherNumber > &q)
Definition: tensor.h:1949
constexpr Tensor & operator+=(const Tensor< rank_, dim, OtherNumber > &)
const Number * end_raw() const
void unroll_recursion(Vector< OtherNumber > &result, unsigned int &start_index) const
constexpr Number & operator[](const TableIndices< rank_ > &indices)
constexpr Tensor< rank, dim, typename ProductType< Number, OtherNumber >::type > schur_product(const Tensor< rank, dim, Number > &src1, const Tensor< rank, dim, OtherNumber > &src2)
Definition: tensor.h:2181
constexpr numbers::NumberTraits< Number >::real_type norm_square() const
constexpr Tensor< rank, dim, typename ProductType< Number, OtherNumber >::type > operator-(const Tensor< rank, dim, Number > &p, const Tensor< rank, dim, OtherNumber > &q)
Definition: tensor.h:2132
Tensor< rank_, dim, Number > tensor_type
Definition: tensor.h:808
constexpr ProductType< Number, Other >::type operator*(const Tensor< 0, dim, Number > &t, const Other &object)
Definition: tensor.h:1892
constexpr Tensor(const ArrayLike &initializer, std::index_sequence< Indices... >)
constexpr Number determinant(const Tensor< 2, 2, Number > &t)
Definition: tensor.h:2638
constexpr Tensor< rank_1+rank_2-2, dim, typenameProductType< Number, OtherNumber >::type >::tensor_type contract(const Tensor< rank_1, dim, Number > &src1, const Tensor< rank_2, dim, OtherNumber > &src2)
Definition: tensor.h:2288
constexpr Tensor< rank, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const Tensor< rank, dim, Number > &t, const OtherNumber &factor)
Definition: tensor.h:1991
constexpr Tensor< 2, dim, Number > invert(const Tensor< 2, dim, Number > &)
Definition: tensor.h:2691
void serialize(Archive &ar, const unsigned int version)
constexpr Tensor & operator*=(const OtherNumber &factor)
constexpr const value_type & operator[](const unsigned int i) const
constexpr Number determinant(const Tensor< 2, 3, Number > &t)
Definition: tensor.h:2651
constexpr Tensor(const array_type &initializer)
static constexpr unsigned int n_independent_components
Definition: tensor.h:497
constexpr Tensor operator-() const
Tensor< rank_ - 1, dim, Number > values[(dim !=0) ? dim :1]
Definition: tensor.h:814
constexpr Tensor< 1, dim, typename ProductType< Number1, Number2 >::type > cross_product_3d(const Tensor< 1, dim, Number1 > &src1, const Tensor< 1, dim, Number2 > &src2)
Definition: tensor.h:2564
constexpr Tensor & operator=(const Tensor< rank_, dim, OtherNumber > &rhs)
Definition: vector.h:110
VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &x, const ::VectorizedArray< Number, width > &y)
#define DEAL_II_ALWAYS_INLINE
Definition: config.h:100
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcScalarAssignmentOnlyForZeroValue()
#define Assert(cond, exc)
Definition: exceptions.h:1465
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1622
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1575
size_type size() const
Expression fabs(const Expression &x)
static const char A
static const char T
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
constexpr internal::ReorderedIndexView< index, rank, T > reordered_index_view(T &t)
constexpr Tensor< rank, dim, typename ProductType< Number, OtherNumber >::type > division_operator(const Tensor< rank, dim, Number > &t, const OtherNumber &factor)
Definition: tensor.h:2040
constexpr bool value_is_zero(const Number &value)
Definition: numbers.h:931
constexpr bool values_are_equal(const Number1 &value_1, const Number2 &value_2)
Definition: numbers.h:915
STL namespace.
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
#define DEAL_II_CUDA_HOST_DEV
Definition: numbers.h:34
typename internal::ProductTypeImpl< typename std::decay< T >::type, typename std::decay< U >::type >::type type
static constexpr const T & value(const T &t)
Definition: numbers.h:693
decltype(std::declval< T >() *std::declval< U >()) type
static constexpr std::enable_if< std::is_same< Dummy, number >::value &&is_cuda_compatible< Dummy >::value, real_type >::type abs_square(const number &x)
Definition: numbers.h:577
static real_type abs(const number &x)
Definition: numbers.h:599