Reference documentation for deal.II version 9.3.2
\(\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 
22 #include <deal.II/base/numbers.h>
26 #include <deal.II/base/utilities.h>
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
42 template <typename ElementType, typename MemorySpace>
43 class ArrayView;
44 template <int dim, typename Number>
45 class Point;
46 template <int rank_, int dim, typename Number = double>
47 class Tensor;
48 template <typename Number>
49 class Vector;
50 template <typename number>
51 class FullMatrix;
52 namespace Differentiation
53 {
54  namespace SD
55  {
56  class Expression;
57  }
58 } // namespace Differentiation
59 #endif
60 
61 
91 template <int dim, typename Number>
92 class Tensor<0, dim, Number>
93 {
94 public:
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
158  Tensor(const Tensor<0, dim, OtherNumber> &initializer);
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 &
250  operator=(const Tensor<0, dim, Number> &rhs);
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 
326  constexpr DEAL_II_CUDA_HOST_DEV Tensor
327  operator-() const;
328 
341  constexpr void
342  clear();
343 
349  real_type
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 
376 private:
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 
470 template <int rank_, int dim, typename Number>
471 class Tensor
472 {
473 public:
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 
511  using array_type =
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
657  constexpr Tensor<rank_, dim, Number> &
659 
663  constexpr Tensor<rank_, dim, Number> &
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 
723  constexpr DEAL_II_CUDA_HOST_DEV Tensor
724  operator-() const;
725 
738  constexpr void
739  clear();
740 
750  norm() const;
751 
758  constexpr DEAL_II_CUDA_HOST_DEV
760  norm_square() const;
761 
769  template <typename OtherNumber>
770  void
771  unroll(Vector<OtherNumber> &result) const;
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 
810 private:
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
847 namespace 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> &
890  value(const Tensor<rank, dim, T> &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 
909 template <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 
919 template <int dim, typename Number>
920 template <typename OtherNumber>
922  Tensor<0, dim, Number>::Tensor(const OtherNumber &initializer)
923  : value(internal::NumberType<Number>::value(initializer))
924 {}
925 
926 
927 
928 template <int dim, typename Number>
929 template <typename OtherNumber>
932  : Tensor{p.value}
933 {}
934 
935 
936 # ifdef DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG
937 template <int dim, typename Number>
940  : value{other.value}
941 {}
942 
943 
944 
945 template <int dim, typename Number>
948  : value{std::move(other.value)}
949 {}
950 # endif
951 
952 
953 template <int dim, typename Number>
954 inline Number *
956 {
957  return std::addressof(value);
958 }
959 
960 
961 
962 template <int dim, typename Number>
963 inline const Number *
965 {
966  return std::addressof(value);
967 }
968 
969 
970 
971 template <int dim, typename Number>
972 inline Number *
974 {
976 }
977 
978 
979 
980 template <int dim, typename Number>
981 const Number *
983 {
985 }
986 
987 
988 
989 template <int dim, typename Number>
990 constexpr 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 
1002 template <int dim, typename Number>
1003 constexpr 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 
1015 template <int dim, typename Number>
1016 template <typename OtherNumber>
1017 constexpr inline DEAL_II_ALWAYS_INLINE
1020 {
1022  return *this;
1023 }
1024 
1025 
1026 # if defined(__INTEL_COMPILER) || defined(DEAL_II_DELETED_MOVE_CONSTRUCTOR_BUG)
1027 template <int dim, typename Number>
1028 constexpr 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
1038 template <int dim, typename Number>
1041 {
1042  value = std::move(other.value);
1043  return *this;
1044 }
1045 # endif
1046 
1047 
1048 
1049 template <int dim, typename Number>
1050 template <typename OtherNumber>
1051 constexpr inline DEAL_II_ALWAYS_INLINE
1053  Tensor<0, dim, Number>::operator=(const OtherNumber &d)
1054 {
1056  return *this;
1057 }
1058 
1059 
1060 template <int dim, typename Number>
1061 template <typename OtherNumber>
1062 constexpr 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 
1077 template <int dim, typename Number>
1078 template <typename OtherNumber>
1079 constexpr bool
1081 {
1082  return !((*this) == p);
1083 }
1084 
1085 
1086 template <int dim, typename Number>
1087 template <typename OtherNumber>
1088 constexpr inline DEAL_II_ALWAYS_INLINE
1091 {
1092  value += p.value;
1093  return *this;
1094 }
1095 
1096 
1097 template <int dim, typename Number>
1098 template <typename OtherNumber>
1099 constexpr inline DEAL_II_ALWAYS_INLINE
1102 {
1103  value -= p.value;
1104  return *this;
1105 }
1106 
1107 
1108 
1109 namespace 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 
1133 template <int dim, typename Number>
1134 template <typename OtherNumber>
1135 constexpr 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 
1145 template <int dim, typename Number>
1146 template <typename OtherNumber>
1148 Tensor<0, dim, Number>::operator/=(const OtherNumber &s)
1149 {
1150  value /= s;
1151  return *this;
1152 }
1153 
1154 
1155 template <int dim, typename Number>
1158 {
1159  return -value;
1160 }
1161 
1162 
1163 template <int dim, typename Number>
1166 {
1167  Assert(dim != 0,
1168  ExcMessage("Cannot access an object of type Tensor<0,0,Number>"));
1169  return numbers::NumberTraits<Number>::abs(value);
1170 }
1171 
1172 
1173 template <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 
1187 template <int dim, typename Number>
1188 template <typename OtherNumber>
1189 inline 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 
1200 template <int dim, typename Number>
1201 constexpr inline void
1203 {
1204  // Some auto-differentiable numbers need explicit
1205  // zero initialization.
1207 }
1208 
1209 
1210 template <int dim, typename Number>
1211 template <class Archive>
1212 inline void
1213 Tensor<0, dim, Number>::serialize(Archive &ar, const unsigned int)
1214 {
1215  ar &value;
1216 }
1217 
1218 
1219 template <int dim, typename Number>
1221 
1222 
1223 /*-------------------- Inline functions: Tensor<rank,dim> --------------------*/
1224 
1225 template <int rank_, int dim, typename Number>
1226 template <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 
1238 template <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 
1248 template <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 
1256 template <int rank_, int dim, typename Number>
1257 template <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 
1270 template <int rank_, int dim, typename Number>
1271 template <typename OtherNumber>
1274  const Tensor<rank_, dim, OtherNumber> &initializer)
1275  : Tensor(initializer, std::make_index_sequence<dim>{})
1276 {}
1277 
1278 
1279 
1280 template <int rank_, int dim, typename Number>
1281 template <typename OtherNumber>
1282 constexpr 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 
1290 template <int rank_, int dim, typename Number>
1291 template <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
1300 template <int rank_, int dim, typename Number>
1301 constexpr DEAL_II_ALWAYS_INLINE
1303 {
1304  for (unsigned int i = 0; i < dim; ++i)
1305  values[i] = other.values[i];
1306 }
1307 
1308 
1309 
1310 template <int rank_, int dim, typename Number>
1311 constexpr 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 
1320 namespace 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 
1372 template <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 
1382 template <int rank_, int dim, typename Number>
1383 constexpr 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 
1395 template <int rank_, int dim, typename Number>
1396 constexpr 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 
1410 template <int rank_, int dim, typename Number>
1411 constexpr inline DEAL_II_ALWAYS_INLINE Number &Tensor<rank_, dim, 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 
1424 template <int rank_, int dim, typename Number>
1425 inline Number *
1427 {
1428  return std::addressof(
1429  this->operator[](this->unrolled_to_component_indices(0)));
1430 }
1431 
1432 
1433 
1434 template <int rank_, int dim, typename Number>
1435 inline const Number *
1437 {
1438  return std::addressof(
1439  this->operator[](this->unrolled_to_component_indices(0)));
1440 }
1441 
1442 
1443 
1444 template <int rank_, int dim, typename Number>
1445 inline Number *
1447 {
1448  return begin_raw() + n_independent_components;
1449 }
1450 
1451 
1452 
1453 template <int rank_, int dim, typename Number>
1454 inline const Number *
1456 {
1457  return begin_raw() + n_independent_components;
1458 }
1459 
1460 
1461 
1462 template <int rank_, int dim, typename Number>
1463 template <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 
1476 template <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
1490 template <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 
1501 template <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 
1513 template <int rank_, int dim, typename Number>
1514 template <typename OtherNumber>
1515 constexpr 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
1531 template <>
1532 template <>
1533 constexpr inline bool
1535 {
1536  return true;
1537 }
1538 
1539 
1540 template <int rank_, int dim, typename Number>
1541 template <typename OtherNumber>
1542 constexpr bool
1545 {
1546  return !((*this) == p);
1547 }
1548 
1549 
1550 template <int rank_, int dim, typename Number>
1551 template <typename OtherNumber>
1552 constexpr 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 
1563 template <int rank_, int dim, typename Number>
1564 template <typename OtherNumber>
1565 constexpr 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 
1576 template <int rank_, int dim, typename Number>
1577 template <typename OtherNumber>
1578 constexpr 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 
1588 namespace 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 
1633 template <int rank_, int dim, typename Number>
1634 template <typename OtherNumber>
1635 constexpr inline DEAL_II_ALWAYS_INLINE
1637  Tensor<rank_, dim, Number>::operator/=(const OtherNumber &s)
1638 {
1640  return *this;
1641 }
1642 
1643 
1644 template <int rank_, int dim, typename Number>
1645 constexpr 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 
1658 template <int rank_, int dim, typename Number>
1661 {
1662  return std::sqrt(norm_square());
1663 }
1664 
1665 
1666 template <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 
1680 template <int rank_, int dim, typename Number>
1681 template <typename OtherNumber>
1682 inline 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 
1693 template <int rank_, int dim, typename Number>
1694 template <typename OtherNumber>
1695 inline 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 
1704 template <int rank_, int dim, typename Number>
1705 constexpr 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 
1718 namespace 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 
1757 template <int rank_, int dim, typename Number>
1758 constexpr 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 
1777 template <int rank_, int dim, typename Number>
1778 constexpr inline void
1780 {
1781  for (unsigned int i = 0; i < dim; ++i)
1783 }
1784 
1785 
1786 template <int rank_, int dim, typename Number>
1787 constexpr std::size_t
1789 {
1790  return sizeof(Tensor<rank_, dim, Number>);
1791 }
1792 
1793 
1794 template <int rank_, int dim, typename Number>
1795 template <class Archive>
1796 inline void
1797 Tensor<rank_, dim, Number>::serialize(Archive &ar, const unsigned int)
1798 {
1799  ar &values;
1800 }
1801 
1802 
1803 template <int rank_, int dim, typename Number>
1805 
1806 #endif // DOXYGEN
1807 
1808 /* ----------------- Non-member functions operating on tensors. ------------ */
1809 
1814 
1822 template <int rank_, int dim, typename Number>
1823 inline std::ostream &
1824 operator<<(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 
1843 template <int dim, typename Number>
1844 inline std::ostream &
1845 operator<<(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 
1869 template <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 
1889 template <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 
1909 template <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 
1927 template <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 
1946 template <int dim, typename Number, typename OtherNumber>
1950  const Tensor<0, dim, OtherNumber> &q)
1951 {
1952  return static_cast<const Number &>(p) + static_cast<const OtherNumber &>(q);
1953 }
1954 
1955 
1963 template <int dim, typename Number, typename OtherNumber>
1967  const Tensor<0, dim, OtherNumber> &q)
1968 {
1969  return static_cast<const Number &>(p) - static_cast<const OtherNumber &>(q);
1970 }
1971 
1972 
1985 template <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 
2013 template <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 
2026 namespace 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<
2036  typename ProductType<Number, OtherNumber>::type>::value,
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<
2058  typename ProductType<Number, OtherNumber>::type>::value,
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 
2084 template <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 
2105 template <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 
2129 template <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 
2149 template <int dim, typename Number, typename OtherNumber>
2150 inline constexpr DEAL_II_ALWAYS_INLINE
2153  const Tensor<0, dim, OtherNumber> &src2)
2154 {
2156 
2157  tmp *= src2;
2158 
2159  return tmp;
2160 }
2161 
2178 template <int rank, int dim, typename Number, typename OtherNumber>
2179 inline constexpr DEAL_II_ALWAYS_INLINE
2182  const Tensor<rank, dim, OtherNumber> &src2)
2183 {
2185 
2186  for (unsigned int i = 0; i < dim; ++i)
2187  tmp[i] = schur_product(Tensor<rank - 1, dim, Number>(src1[i]),
2189 
2190  return tmp;
2191 }
2192 
2194 
2198 
2199 
2222 template <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>
2228 constexpr 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,
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 
2277 template <int index_1,
2278  int index_2,
2279  int rank_1,
2280  int rank_2,
2281  int dim,
2282  typename Number,
2283  typename OtherNumber>
2284 constexpr 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,
2314  result{};
2315  TensorAccessors::contract<1, rank_1, rank_2, dim>(result, reord_01, reord_02);
2316  return result;
2317 }
2318 
2319 
2350 template <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>
2359 constexpr 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,
2412  ReorderedIndexView<index_2, rank_2, const Tensor<rank_2, dim, OtherNumber>>>
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,
2421  result{};
2422  TensorAccessors::contract<2, rank_1, rank_2, dim>(result, reord_3, reord_4);
2423  return result;
2424 }
2425 
2426 
2439 template <int rank, int dim, typename Number, typename OtherNumber>
2440 constexpr inline DEAL_II_ALWAYS_INLINE
2443  const Tensor<rank, dim, OtherNumber> &right)
2444 {
2445  typename ProductType<Number, OtherNumber>::type result{};
2446  TensorAccessors::contract<rank, rank, rank, dim>(result, left, right);
2447  return result;
2448 }
2449 
2450 
2468 template <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>
2477 constexpr 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 
2501 template <int rank_1,
2502  int rank_2,
2503  int dim,
2504  typename Number,
2505  typename OtherNumber>
2506 constexpr inline DEAL_II_ALWAYS_INLINE
2510 {
2511  typename Tensor<rank_1 + rank_2,
2512  dim,
2514  result{};
2515  TensorAccessors::contract<0, rank_1, rank_2, dim>(result, src1, src2);
2516  return result;
2517 }
2518 
2519 
2521 
2525 
2526 
2537 template <int dim, typename Number>
2540 {
2541  Assert(dim == 2, ExcInternalError());
2542 
2543  Tensor<1, dim, Number> result;
2544 
2545  result[0] = src[1];
2546  result[1] = -src[0];
2547 
2548  return result;
2549 }
2550 
2551 
2561 template <int dim, typename Number1, typename Number2>
2562 constexpr 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 
2596 template <int dim, typename Number>
2597 constexpr 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 
2624 template <typename Number>
2625 constexpr DEAL_II_ALWAYS_INLINE Number
2627 {
2628  return t[0][0];
2629 }
2630 
2636 template <typename Number>
2637 constexpr 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 
2649 template <typename Number>
2650 constexpr 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 
2670 template <int dim, typename Number>
2671 constexpr 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 
2689 template <int dim, typename Number>
2690 constexpr 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
2698  AssertThrow(false, ExcNotImplemented());
2699 
2700  return Tensor<2, dim, Number>(return_tensor);
2701 }
2702 
2703 
2704 #ifndef DOXYGEN
2705 
2706 template <typename Number>
2708  invert(const Tensor<2, 1, Number> &t)
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 
2718 template <typename Number>
2720  invert(const Tensor<2, 2, Number> &t)
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 
2736 template <typename Number>
2738  invert(const Tensor<2, 3, Number> &t)
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 
2776 template <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 
2807 template <int dim, typename Number>
2808 constexpr Tensor<2, dim, Number>
2810 {
2811  return determinant(t) * invert(t);
2812 }
2813 
2814 
2828 template <int dim, typename Number>
2829 constexpr Tensor<2, dim, Number>
2831 {
2832  return transpose(adjugate(t));
2833 }
2834 
2835 
2899 template <int dim, typename Number>
2902 
2903 
2911 template <int dim, typename Number>
2912 inline 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 
2937 template <int dim, typename Number>
2938 inline 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
2965 template <int dim>
2966 inline 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 
2983 template <int dim>
2984 inline 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
Definition: point.h:111
const Number * begin_raw() const
constexpr Tensor & operator+=(const Tensor< 0, dim, OtherNumber > &rhs)
void serialize(Archive &ar, const unsigned int version)
constexpr Tensor & operator*=(const OtherNumber &factor)
constexpr Tensor(const Tensor< 0, dim, OtherNumber > &initializer)
constexpr Tensor(const OtherNumber &initializer)
constexpr void clear()
constexpr real_type norm_square() const
constexpr Tensor & operator-=(const Tensor< 0, dim, OtherNumber > &rhs)
const Number * end_raw() const
constexpr bool operator!=(const Tensor< 0, dim, OtherNumber > &rhs) 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 OtherNumber &factor)
constexpr Tensor operator-() const
constexpr Tensor & operator=(const OtherNumber &d)
void unroll_recursion(Vector< OtherNumber > &result, unsigned int &start_index) const
Definition: tensor.h:472
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< 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 Tensor & operator+=(const Tensor< rank_, dim, OtherNumber > &)
constexpr Tensor & operator-=(const Tensor< rank_, dim, OtherNumber > &)
constexpr Tensor & operator*=(const OtherNumber &factor)
static constexpr TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
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
static constexpr unsigned int rank
Definition: tensor.h:491
constexpr Number determinant(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2598
constexpr Tensor< rank_1+rank_2 - 4, dim, typename ProductType< 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
constexpr const Number & operator[](const TableIndices< rank_ > &indices) const
constexpr Tensor(const Tensor< rank_, dim, OtherNumber > &initializer)
constexpr const value_type & operator[](const unsigned int i) const
constexpr void clear()
void unroll(Vector< OtherNumber > &result) const
constexpr Number & operator[](const TableIndices< rank_ > &indices)
constexpr Tensor & operator=(const Tensor< rank_, dim, OtherNumber > &rhs)
constexpr Tensor(const Tensor< 1, dim, Tensor< rank_ - 1, dim, OtherNumber >> &initializer)
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
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
Number * end_raw()
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 numbers::NumberTraits< Number >::real_type norm_square() const
const Number * begin_raw() const
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
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
constexpr Tensor< rank_1+rank_2 - 2, dim, typename ProductType< 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 & operator/=(const OtherNumber &factor)
static constexpr unsigned int dimension
Definition: tensor.h:486
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()
Number * begin_raw()
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
void unroll_recursion(Vector< OtherNumber > &result, unsigned int &start_index) const
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 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
constexpr Tensor & operator=(const Number &d)
Tensor< rank_, dim, Number > tensor_type
Definition: tensor.h:808
constexpr value_type & operator[](const unsigned int i)
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
const Number * end_raw() 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: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 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
constexpr ProductType< T1, typename ProductType< 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
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
numbers::NumberTraits< Number >::real_type norm() const
Definition: vector.h:110
#define DEAL_II_ALWAYS_INLINE
Definition: config.h:97
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:396
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:397
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcScalarAssignmentOnlyForZeroValue()
#define Assert(cond, exc)
Definition: exceptions.h:1465
static ::ExceptionBase & ExcNotImplemented()
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1622
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
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)
T sum(const T &t, const MPI_Comm &mpi_communicator)
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
#define DEAL_II_CUDA_HOST_DEV
Definition: numbers.h:34
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
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
constexpr Tensor< 2, dim, Number > cofactor(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2830
constexpr Tensor< 2, dim, Number > adjugate(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2809
constexpr Tensor< 2, dim, Number > transpose(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2778
constexpr Number determinant(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2598
Number linfty_norm(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2939
Number l1_norm(const Tensor< 2, dim, Number > &t)
Definition: tensor.h:2913
constexpr Tensor< 2, dim, Number > invert(const Tensor< 2, dim, Number > &)
Definition: tensor.h:2691