16 #ifndef dealii_symmetric_tensor_h 17 #define dealii_symmetric_tensor_h 20 #include <deal.II/base/numbers.h> 21 #include <deal.II/base/table_indices.h> 22 #include <deal.II/base/template_constraints.h> 23 #include <deal.II/base/tensor.h> 29 DEAL_II_NAMESPACE_OPEN
31 template <
int rank,
int dim,
typename Number =
double>
34 template <
int dim,
typename Number>
38 template <
int dim,
typename Number>
42 template <
int dim,
typename Number>
46 template <
int dim,
typename Number>
50 template <
int dim,
typename Number>
54 template <
int dim2,
typename Number>
58 template <
int dim,
typename Number>
62 template <
int dim,
typename Number>
74 namespace SymmetricTensorImplementation
80 template <
int rank,
int dim,
typename Number>
88 namespace SymmetricTensorAccessors
98 const unsigned int new_index,
99 const unsigned int position)
119 const unsigned int new_index,
120 const unsigned int position)
164 typename OtherNumber = Number>
167 using value_type =
typename ProductType<Number, OtherNumber>::type;
181 template <
int dim,
typename Number,
typename OtherNumber>
184 using type =
typename ProductType<Number, OtherNumber>::type;
201 template <
int rank,
int dim,
typename Number>
207 template <
int dim,
typename Number>
214 static const unsigned int n_independent_components =
215 (dim * dim + dim) / 2;
228 template <
int dim,
typename Number>
236 static const unsigned int n_rank2_components = (dim * dim + dim) / 2;
241 static const unsigned int n_independent_components =
242 (n_rank2_components *
260 template <
int rank,
int dim,
bool constness,
typename Number>
269 template <
int rank,
int dim,
typename Number>
272 using tensor_type = const ::SymmetricTensor<rank, dim, Number>;
274 using reference = Number;
283 template <
int rank,
int dim,
typename Number>
288 using reference = Number &;
326 template <
int rank,
int dim,
bool constness,
int P,
typename Number>
362 Accessor(
const Accessor &) =
default;
368 Accessor<rank, dim, constness, P - 1, Number>
369 operator[](
const unsigned int i);
374 Accessor<rank, dim, constness, P - 1, Number>
375 operator[](
const unsigned int i)
const;
388 template <
int,
int,
typename>
389 friend class ::SymmetricTensor;
390 template <
int,
int,
bool,
int,
typename>
391 friend class Accessor;
392 #ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG 393 friend class ::SymmetricTensor<rank, dim, Number>;
394 friend class Accessor<rank, dim, constness, P + 1, Number>;
409 template <
int rank,
int dim,
bool constness,
typename Number>
410 class Accessor<rank, dim, constness, 1, Number>
453 Accessor(
const Accessor &) =
default;
459 reference operator[](
const unsigned int);
464 reference operator[](
const unsigned int)
const;
477 template <
int,
int,
typename>
478 friend class ::SymmetricTensor;
479 template <
int,
int,
bool,
int,
typename>
480 friend class SymmetricTensorAccessors::Accessor;
481 #ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG 482 friend class ::SymmetricTensor<rank, dim, Number>;
483 friend class SymmetricTensorAccessors::
484 Accessor<rank, dim, constness, 2, Number>;
555 template <int rank_, int dim, typename Number>
559 static_assert(rank_ % 2 == 0,
"A SymmetricTensor must have even rank!");
569 static const unsigned int dimension = dim;
574 static const unsigned int rank = rank_;
581 static constexpr
unsigned int n_independent_components =
583 n_independent_components;
600 template <
typename OtherNumber>
625 template <
typename OtherNumber>
660 template <
typename OtherNumber>
671 operator=(
const Number &d);
694 template <
typename OtherNumber>
701 template <
typename OtherNumber>
709 template <
typename OtherNumber>
711 operator*=(
const OtherNumber &factor);
716 template <
typename OtherNumber>
718 operator/=(
const OtherNumber &factor);
750 template <
typename OtherNumber>
759 template <
typename OtherNumber>
780 internal::SymmetricTensorAccessors::
781 Accessor<rank_, dim,
true, rank_ - 1, Number>
782 operator[](
const unsigned int row)
const;
788 internal::SymmetricTensorAccessors::
789 Accessor<rank_, dim,
false, rank_ - 1, Number>
790 operator[](
const unsigned int row);
812 access_raw_entry(
const unsigned int unrolled_index)
const;
820 access_raw_entry(
const unsigned int unrolled_index);
850 unrolled_to_component_indices(
const unsigned int i);
872 memory_consumption();
878 template <
class Archive>
880 serialize(Archive &ar,
const unsigned int version);
902 template <
int,
int,
typename>
908 template <
int dim2,
typename Number2>
912 template <
int dim2,
typename Number2>
916 template <
int dim2,
typename Number2>
920 template <
int dim2,
typename Number2>
924 template <
int dim2,
typename Number2>
928 template <
int dim2,
typename Number2>
937 Inverse<2, dim, Number>;
940 Inverse<4, dim, Number>;
950 template <int rank, int dim, typename Number>
953 template <int rank_, int dim, typename Number>
954 constexpr unsigned int
959 namespace SymmetricTensorAccessors
961 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
962 Accessor<rank_, dim, constness, P, Number>::Accessor(
963 tensor_type & tensor,
966 , previous_indices(previous_indices)
971 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
972 Accessor<rank_, dim, constness, P - 1, Number>
973 Accessor<rank_, dim, constness, P, Number>::
974 operator[](
const unsigned int i)
976 return Accessor<rank_, dim, constness, P - 1, Number>(
977 tensor,
merge(previous_indices, i, rank_ - P));
982 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
983 Accessor<rank_, dim, constness, P - 1, Number>
984 Accessor<rank_, dim, constness, P, Number>::
985 operator[](
const unsigned int i)
const 987 return Accessor<rank_, dim, constness, P - 1, Number>(
988 tensor,
merge(previous_indices, i, rank_ - P));
993 template <
int rank_,
int dim,
bool constness,
typename Number>
994 Accessor<rank_, dim, constness, 1, Number>::Accessor(
995 tensor_type & tensor,
998 , previous_indices(previous_indices)
1003 template <
int rank_,
int dim,
bool constness,
typename Number>
1004 typename Accessor<rank_, dim, constness, 1, Number>::reference
1005 Accessor<rank_, dim, constness, 1, Number>::
1006 operator[](
const unsigned int i)
1008 return tensor(
merge(previous_indices, i, rank_ - 1));
1012 template <
int rank_,
int dim,
bool constness,
typename Number>
1013 typename Accessor<rank_, dim, constness, 1, Number>::reference
1014 Accessor<rank_, dim, constness, 1, Number>::
1015 operator[](
const unsigned int i)
const 1017 return tensor(
merge(previous_indices, i, rank_ - 1));
1024 template <
int rank_,
int dim,
typename Number>
1029 for (
unsigned int i = 0; i < base_tensor_type::dimension; ++i)
1034 template <
int rank_,
int dim,
typename Number>
1035 template <
typename OtherNumber>
1064 for (
unsigned int d = 0; d < dim; ++d)
1065 for (
unsigned int e = 0; e < d; ++e)
1068 for (
unsigned int d = 0; d < dim; ++d)
1071 for (
unsigned int d = 0, c = 0; d < dim; ++d)
1072 for (
unsigned int e = d + 1; e < dim; ++e, ++c)
1073 data[dim + c] = t[d][e];
1079 template <
int rank_,
int dim,
typename Number>
1080 template <
typename OtherNumber>
1084 for (
unsigned int i = 0; i < base_tensor_type::dimension; ++i)
1087 initializer.
data[i]);
1092 template <
int rank_,
int dim,
typename Number>
1094 const Number (&array)[n_independent_components])
1096 *reinterpret_cast<const typename base_tensor_type::array_type *>(array))
1099 Assert(
sizeof(
typename base_tensor_type::array_type) ==
sizeof(array),
1105 template <
int rank_,
int dim,
typename Number>
1106 template <
typename OtherNumber>
1111 for (
unsigned int i = 0; i < base_tensor_type::dimension; ++i)
1112 data[i] = t.
data[i];
1118 template <
int rank_,
int dim,
typename Number>
1123 ExcMessage(
"Only assignment with zero is allowed"));
1134 namespace SymmetricTensorImplementation
1136 template <
int dim,
typename Number>
1137 inline DEAL_II_ALWAYS_INLINE ::Tensor<2, dim, Number>
1138 convert_to_tensor(const ::SymmetricTensor<2, dim, Number> &s)
1143 for (
unsigned int d = 0; d < dim; ++d)
1144 t[d][d] = s.access_raw_entry(d);
1147 for (
unsigned int d = 0, c = 0; d < dim; ++d)
1148 for (
unsigned int e = d + 1; e < dim; ++e, ++c)
1150 t[d][e] = s.access_raw_entry(dim + c);
1151 t[e][d] = s.access_raw_entry(dim + c);
1157 template <
int dim,
typename Number>
1159 convert_to_tensor(const ::SymmetricTensor<4, dim, Number> &st)
1166 for (
unsigned int i = 0; i < dim; ++i)
1167 for (
unsigned int j = i; j < dim; ++j)
1168 for (
unsigned int k = 0; k < dim; ++k)
1169 for (
unsigned int l = k; l < dim; ++l)
1179 template <
typename Number>
1180 struct Inverse<2, 1, Number>
1182 static inline ::SymmetricTensor<2, 1, Number>
1183 value(const ::SymmetricTensor<2, 1, Number> &t)
1187 tmp[0][0] = 1.0 / t[0][0];
1194 template <
typename Number>
1195 struct Inverse<2, 2, Number>
1197 static inline ::SymmetricTensor<2, 2, Number>
1198 value(const ::SymmetricTensor<2, 2, Number> &t)
1208 const Number inv_det_t =
1209 1.0 / (t[idx_00] * t[idx_11] - t[idx_01] * t[idx_01]);
1210 tmp[idx_00] = t[idx_11];
1211 tmp[idx_01] = -t[idx_01];
1212 tmp[idx_11] = t[idx_00];
1220 template <
typename Number>
1221 struct Inverse<2, 3, Number>
1223 static ::SymmetricTensor<2, 3, Number>
1224 value(const ::SymmetricTensor<2, 3, Number> &t)
1251 const Number inv_det_t =
1252 1.0 / (t[idx_00] * t[idx_11] * t[idx_22] -
1253 t[idx_00] * t[idx_12] * t[idx_12] -
1254 t[idx_01] * t[idx_01] * t[idx_22] +
1255 2.0 * t[idx_01] * t[idx_02] * t[idx_12] -
1256 t[idx_02] * t[idx_02] * t[idx_11]);
1257 tmp[idx_00] = t[idx_11] * t[idx_22] - t[idx_12] * t[idx_12];
1258 tmp[idx_01] = -t[idx_01] * t[idx_22] + t[idx_02] * t[idx_12];
1259 tmp[idx_02] = t[idx_01] * t[idx_12] - t[idx_02] * t[idx_11];
1260 tmp[idx_11] = t[idx_00] * t[idx_22] - t[idx_02] * t[idx_02];
1261 tmp[idx_12] = -t[idx_00] * t[idx_12] + t[idx_01] * t[idx_02];
1262 tmp[idx_22] = t[idx_00] * t[idx_11] - t[idx_01] * t[idx_01];
1270 template <
typename Number>
1271 struct Inverse<4, 1, Number>
1273 static inline ::SymmetricTensor<4, 1, Number>
1274 value(const ::SymmetricTensor<4, 1, Number> &t)
1277 tmp.
data[0][0] = 1.0 / t.data[0][0];
1283 template <
typename Number>
1284 struct Inverse<4, 2, Number>
1286 static inline ::SymmetricTensor<4, 2, Number>
1287 value(const ::SymmetricTensor<4, 2, Number> &t)
1313 const Number t4 = t.data[0][0] * t.data[1][1],
1314 t6 = t.data[0][0] * t.data[1][2],
1315 t8 = t.data[0][1] * t.data[1][0],
1316 t00 = t.data[0][2] * t.data[1][0],
1317 t01 = t.data[0][1] * t.data[2][0],
1318 t04 = t.data[0][2] * t.data[2][0],
1319 t07 = 1.0 / (t4 * t.data[2][2] - t6 * t.data[2][1] -
1320 t8 * t.data[2][2] + t00 * t.data[2][1] +
1321 t01 * t.data[1][2] - t04 * t.data[1][1]);
1323 (t.data[1][1] * t.data[2][2] - t.data[1][2] * t.data[2][1]) * t07;
1325 -(t.data[0][1] * t.data[2][2] - t.data[0][2] * t.data[2][1]) * t07;
1327 -(-t.data[0][1] * t.data[1][2] + t.data[0][2] * t.data[1][1]) * t07;
1329 -(t.data[1][0] * t.data[2][2] - t.data[1][2] * t.data[2][0]) * t07;
1330 tmp.
data[1][1] = (t.data[0][0] * t.data[2][2] - t04) * t07;
1331 tmp.
data[1][2] = -(t6 - t00) * t07;
1333 -(-t.data[1][0] * t.data[2][1] + t.data[1][1] * t.data[2][0]) * t07;
1334 tmp.
data[2][1] = -(t.data[0][0] * t.data[2][1] - t01) * t07;
1335 tmp.
data[2][2] = (t4 - t8) * t07;
1339 tmp.
data[2][0] /= 2;
1340 tmp.
data[2][1] /= 2;
1341 tmp.
data[0][2] /= 2;
1342 tmp.
data[1][2] /= 2;
1343 tmp.
data[2][2] /= 4;
1350 template <
typename Number>
1351 struct Inverse<4, 3, Number>
1353 static ::SymmetricTensor<4, 3, Number>
1354 value(const ::SymmetricTensor<4, 3, Number> &t)
1364 const unsigned int N = 6;
1370 for (
unsigned int i = 0; i < N; ++i)
1371 diagonal_sum += std::fabs(tmp.
data[i][i]);
1372 const Number typical_diagonal_element =
1373 diagonal_sum /
static_cast<double>(N);
1374 (void)typical_diagonal_element;
1377 for (
unsigned int i = 0; i < N; ++i)
1380 for (
unsigned int j = 0; j < N; ++j)
1384 Number max = std::fabs(tmp.
data[j][j]);
1386 for (
unsigned int i = j + 1; i < N; ++i)
1387 if (std::fabs(tmp.
data[i][j]) > max)
1389 max = std::fabs(tmp.
data[i][j]);
1394 Assert(max > 1.e-16 * typical_diagonal_element,
1395 ExcMessage(
"This tensor seems to be noninvertible"));
1400 for (
unsigned int k = 0; k < N; ++k)
1407 const Number hr = 1. / tmp.
data[j][j];
1408 tmp.
data[j][j] = hr;
1409 for (
unsigned int k = 0; k < N; ++k)
1413 for (
unsigned int i = 0; i < N; ++i)
1417 tmp.
data[i][k] -= tmp.
data[i][j] * tmp.
data[j][k] * hr;
1420 for (
unsigned int i = 0; i < N; ++i)
1422 tmp.
data[i][j] *= hr;
1423 tmp.
data[j][i] *= -hr;
1425 tmp.
data[j][j] = hr;
1430 for (
unsigned int i = 0; i < N; ++i)
1432 for (
unsigned int k = 0; k < N; ++k)
1433 hv[p[k]] = tmp.
data[i][k];
1434 for (
unsigned int k = 0; k < N; ++k)
1435 tmp.
data[i][k] = hv[k];
1440 for (
unsigned int i = 3; i < 6; ++i)
1441 for (
unsigned int j = 0; j < 3; ++j)
1442 tmp.
data[i][j] /= 2;
1444 for (
unsigned int i = 0; i < 3; ++i)
1445 for (
unsigned int j = 3; j < 6; ++j)
1446 tmp.
data[i][j] /= 2;
1448 for (
unsigned int i = 3; i < 6; ++i)
1449 for (
unsigned int j = 3; j < 6; ++j)
1450 tmp.
data[i][j] /= 4;
1461 template <
int rank_,
int dim,
typename Number>
1465 return internal::SymmetricTensorImplementation::convert_to_tensor(*
this);
1470 template <
int rank_,
int dim,
typename Number>
1475 return data == t.
data;
1480 template <
int rank_,
int dim,
typename Number>
1485 return data != t.
data;
1490 template <
int rank_,
int dim,
typename Number>
1491 template <
typename OtherNumber>
1502 template <
int rank_,
int dim,
typename Number>
1503 template <
typename OtherNumber>
1514 template <
int rank_,
int dim,
typename Number>
1515 template <
typename OtherNumber>
1525 template <
int rank_,
int dim,
typename Number>
1526 template <
typename OtherNumber>
1536 template <
int rank_,
int dim,
typename Number>
1547 template <
int rank_,
int dim,
typename Number>
1548 inline DEAL_II_ALWAYS_INLINE
void 1556 template <
int rank_,
int dim,
typename Number>
1569 template <
int dim,
typename Number,
typename OtherNumber = Number>
1570 inline DEAL_II_ALWAYS_INLINE
typename SymmetricTensorAccessors::
1571 double_contraction_result<2, 2, dim, Number, OtherNumber>::type
1572 perform_double_contraction(
1573 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1575 const typename SymmetricTensorAccessors::
1576 StorageType<2, dim, OtherNumber>::base_tensor_type &sdata)
1578 using result_type =
typename SymmetricTensorAccessors::
1579 double_contraction_result<2, 2, dim, Number, OtherNumber>::type;
1584 return data[0] * sdata[0];
1589 result_type sum = data[dim] * sdata[dim];
1590 for (
unsigned int d = dim + 1; d < (dim * (dim + 1) / 2); ++d)
1591 sum += data[d] * sdata[d];
1595 for (
unsigned int d = 0; d < dim; ++d)
1596 sum += data[d] * sdata[d];
1603 template <
int dim,
typename Number,
typename OtherNumber = Number>
1604 inline typename SymmetricTensorAccessors::
1605 double_contraction_result<4, 2, dim, Number, OtherNumber>::type
1606 perform_double_contraction(
1607 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1609 const typename SymmetricTensorAccessors::
1610 StorageType<2, dim, OtherNumber>::base_tensor_type &sdata)
1612 using result_type =
typename SymmetricTensorAccessors::
1613 double_contraction_result<4, 2, dim, Number, OtherNumber>::type;
1614 using value_type =
typename SymmetricTensorAccessors::
1615 double_contraction_result<4, 2, dim, Number, OtherNumber>::value_type;
1617 const unsigned int data_dim = SymmetricTensorAccessors::
1618 StorageType<2, dim, value_type>::n_independent_components;
1619 value_type tmp[data_dim];
1620 for (
unsigned int i = 0; i < data_dim; ++i)
1622 perform_double_contraction<dim, Number, OtherNumber>(data[i], sdata);
1623 return result_type(tmp);
1628 template <
int dim,
typename Number,
typename OtherNumber = Number>
1629 inline typename SymmetricTensorAccessors::StorageType<
1632 typename SymmetricTensorAccessors::
1633 double_contraction_result<2, 4, dim, Number, OtherNumber>::value_type>
:: 1635 perform_double_contraction(
1636 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1638 const typename SymmetricTensorAccessors::
1639 StorageType<4, dim, OtherNumber>::base_tensor_type &sdata)
1641 using value_type =
typename SymmetricTensorAccessors::
1642 double_contraction_result<2, 4, dim, Number, OtherNumber>::value_type;
1644 StorageType<2, dim, value_type>::base_tensor_type;
1647 for (
unsigned int i = 0; i < tmp.dimension; ++i)
1650 value_type sum = data[dim] * sdata[dim][i];
1651 for (
unsigned int d = dim + 1; d < (dim * (dim + 1) / 2); ++d)
1652 sum += data[d] * sdata[d][i];
1656 for (
unsigned int d = 0; d < dim; ++d)
1657 sum += data[d] * sdata[d][i];
1665 template <
int dim,
typename Number,
typename OtherNumber = Number>
1666 inline typename SymmetricTensorAccessors::StorageType<
1669 typename SymmetricTensorAccessors::
1670 double_contraction_result<4, 4, dim, Number, OtherNumber>::value_type>
:: 1672 perform_double_contraction(
1673 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1675 const typename SymmetricTensorAccessors::
1676 StorageType<4, dim, OtherNumber>::base_tensor_type &sdata)
1678 using value_type =
typename SymmetricTensorAccessors::
1679 double_contraction_result<4, 4, dim, Number, OtherNumber>::value_type;
1681 StorageType<4, dim, value_type>::base_tensor_type;
1683 const unsigned int data_dim = SymmetricTensorAccessors::
1684 StorageType<2, dim, value_type>::n_independent_components;
1686 for (
unsigned int i = 0; i < data_dim; ++i)
1687 for (
unsigned int j = 0; j < data_dim; ++j)
1690 for (
unsigned int d = dim; d < (dim * (dim + 1) / 2); ++d)
1691 tmp[i][j] += data[i][d] * sdata[d][j];
1692 tmp[i][j] += tmp[i][j];
1695 for (
unsigned int d = 0; d < dim; ++d)
1696 tmp[i][j] += data[i][d] * sdata[d][j];
1705 template <
int rank_,
int dim,
typename Number>
1706 template <
typename OtherNumber>
1716 return internal::perform_double_contraction<dim, Number, OtherNumber>(data,
1722 template <
int rank_,
int dim,
typename Number>
1723 template <
typename OtherNumber>
1732 internal::perform_double_contraction<dim, Number, OtherNumber>(data,
1749 template <
int dim,
typename Number>
1752 typename SymmetricTensorAccessors::
1753 StorageType<2, dim, Number>::base_tensor_type &data)
1761 if (indices[0] == indices[1])
1762 return data[indices[0]];
1769 Assert(((indices[0] == 1) && (indices[1] == 0)) ||
1770 ((indices[0] == 0) && (indices[1] == 1)),
1778 sorted_indices.
sort();
1780 for (
unsigned int d = 0, c = 0; d < dim; ++d)
1781 for (
unsigned int e = d + 1; e < dim; ++e, ++c)
1782 if ((sorted_indices[0] == d) && (sorted_indices[1] == e))
1783 return data[dim + c];
1788 static Number dummy_but_referenceable = Number();
1789 return dummy_but_referenceable;
1794 template <
int dim,
typename Number>
1795 inline const Number &
1797 const typename SymmetricTensorAccessors::
1798 StorageType<2, dim, Number>::base_tensor_type &data)
1806 if (indices[0] == indices[1])
1807 return data[indices[0]];
1814 Assert(((indices[0] == 1) && (indices[1] == 0)) ||
1815 ((indices[0] == 0) && (indices[1] == 1)),
1823 sorted_indices.
sort();
1825 for (
unsigned int d = 0, c = 0; d < dim; ++d)
1826 for (
unsigned int e = d + 1; e < dim; ++e, ++c)
1827 if ((sorted_indices[0] == d) && (sorted_indices[1] == e))
1828 return data[dim + c];
1833 static Number dummy_but_referenceable = Number();
1834 return dummy_but_referenceable;
1839 template <
int dim,
typename Number>
1842 typename SymmetricTensorAccessors::
1843 StorageType<4, dim, Number>::base_tensor_type &data)
1861 unsigned int base_index[2];
1862 if ((indices[0] == 0) && (indices[1] == 0))
1864 else if ((indices[0] == 1) && (indices[1] == 1))
1869 if ((indices[2] == 0) && (indices[3] == 0))
1871 else if ((indices[2] == 1) && (indices[3] == 1))
1876 return data[base_index[0]][base_index[1]];
1890 unsigned int base_index[2];
1891 if ((indices[0] == 0) && (indices[1] == 0))
1893 else if ((indices[0] == 1) && (indices[1] == 1))
1895 else if ((indices[0] == 2) && (indices[1] == 2))
1897 else if (((indices[0] == 0) && (indices[1] == 1)) ||
1898 ((indices[0] == 1) && (indices[1] == 0)))
1900 else if (((indices[0] == 0) && (indices[1] == 2)) ||
1901 ((indices[0] == 2) && (indices[1] == 0)))
1905 Assert(((indices[0] == 1) && (indices[1] == 2)) ||
1906 ((indices[0] == 2) && (indices[1] == 1)),
1911 if ((indices[2] == 0) && (indices[3] == 0))
1913 else if ((indices[2] == 1) && (indices[3] == 1))
1915 else if ((indices[2] == 2) && (indices[3] == 2))
1917 else if (((indices[2] == 0) && (indices[3] == 1)) ||
1918 ((indices[2] == 1) && (indices[3] == 0)))
1920 else if (((indices[2] == 0) && (indices[3] == 2)) ||
1921 ((indices[2] == 2) && (indices[3] == 0)))
1925 Assert(((indices[2] == 1) && (indices[3] == 2)) ||
1926 ((indices[2] == 2) && (indices[3] == 1)),
1931 return data[base_index[0]][base_index[1]];
1938 static Number dummy;
1943 template <
int dim,
typename Number>
1944 inline const Number &
1946 const typename SymmetricTensorAccessors::
1947 StorageType<4, dim, Number>::base_tensor_type &data)
1965 unsigned int base_index[2];
1966 if ((indices[0] == 0) && (indices[1] == 0))
1968 else if ((indices[0] == 1) && (indices[1] == 1))
1973 if ((indices[2] == 0) && (indices[3] == 0))
1975 else if ((indices[2] == 1) && (indices[3] == 1))
1980 return data[base_index[0]][base_index[1]];
1994 unsigned int base_index[2];
1995 if ((indices[0] == 0) && (indices[1] == 0))
1997 else if ((indices[0] == 1) && (indices[1] == 1))
1999 else if ((indices[0] == 2) && (indices[1] == 2))
2001 else if (((indices[0] == 0) && (indices[1] == 1)) ||
2002 ((indices[0] == 1) && (indices[1] == 0)))
2004 else if (((indices[0] == 0) && (indices[1] == 2)) ||
2005 ((indices[0] == 2) && (indices[1] == 0)))
2009 Assert(((indices[0] == 1) && (indices[1] == 2)) ||
2010 ((indices[0] == 2) && (indices[1] == 1)),
2015 if ((indices[2] == 0) && (indices[3] == 0))
2017 else if ((indices[2] == 1) && (indices[3] == 1))
2019 else if ((indices[2] == 2) && (indices[3] == 2))
2021 else if (((indices[2] == 0) && (indices[3] == 1)) ||
2022 ((indices[2] == 1) && (indices[3] == 0)))
2024 else if (((indices[2] == 0) && (indices[3] == 2)) ||
2025 ((indices[2] == 2) && (indices[3] == 0)))
2029 Assert(((indices[2] == 1) && (indices[3] == 2)) ||
2030 ((indices[2] == 2) && (indices[3] == 1)),
2035 return data[base_index[0]][base_index[1]];
2042 static Number dummy;
2050 template <
int rank_,
int dim,
typename Number>
2055 for (
unsigned int r = 0; r < rank; ++r)
2057 return internal::symmetric_tensor_access<dim, Number>(indices, data);
2062 template <
int rank_,
int dim,
typename Number>
2063 inline const Number &
2067 for (
unsigned int r = 0; r < rank; ++r)
2069 return internal::symmetric_tensor_access<dim, Number>(indices, data);
2076 namespace SymmetricTensorImplementation
2078 template <
int rank_>
2080 get_partially_filled_indices(
const unsigned int row,
2081 const std::integral_constant<int, 2> &)
2087 template <
int rank_>
2089 get_partially_filled_indices(
const unsigned int row,
2090 const std::integral_constant<int, 4> &)
2101 template <
int rank_,
int dim,
typename Number>
2102 internal::SymmetricTensorAccessors::
2103 Accessor<rank_, dim,
true, rank_ - 1, Number>
2107 return internal::SymmetricTensorAccessors::
2108 Accessor<rank_, dim,
true, rank_ - 1, Number>(
2110 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2111 rank_>(row, std::integral_constant<int, rank_>()));
2116 template <
int rank_,
int dim,
typename Number>
2117 internal::SymmetricTensorAccessors::
2118 Accessor<rank_, dim,
false, rank_ - 1, Number>
2121 return internal::SymmetricTensorAccessors::
2122 Accessor<rank_, dim,
false, rank_ - 1, Number>(
2124 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2125 rank_>(row, std::integral_constant<int, rank_>()));
2130 template <
int rank_,
int dim,
typename Number>
2134 return operator()(indices);
2139 template <
int rank_,
int dim,
typename Number>
2143 return operator()(indices);
2148 template <
int rank_,
int dim,
typename Number>
2152 return std::addressof(this->access_raw_entry(0));
2157 template <
int rank_,
int dim,
typename Number>
2158 inline const Number *
2161 return std::addressof(this->access_raw_entry(0));
2166 template <
int rank_,
int dim,
typename Number>
2170 return begin_raw() + n_independent_components;
2175 template <
int rank_,
int dim,
typename Number>
2176 inline const Number *
2179 return begin_raw() + n_independent_components;
2186 namespace SymmetricTensorImplementation
2188 template <
int dim,
typename Number>
2190 entry_to_indices(const ::SymmetricTensor<2, dim, Number> &,
2191 const unsigned int index)
2197 template <
int dim,
typename Number>
2199 entry_to_indices(const ::SymmetricTensor<4, dim, Number> &,
2200 const unsigned int index)
2211 template <
int rank_,
int dim,
typename Number>
2212 inline const Number &
2214 const unsigned int index)
const 2217 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this,
2223 template <
int rank_,
int dim,
typename Number>
2228 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this,
2236 template <
int dim,
typename Number>
2238 compute_norm(
const typename SymmetricTensorAccessors::
2239 StorageType<2, dim, Number>::base_tensor_type &data)
2266 for (
unsigned int d = 0; d < dim; ++d)
2269 for (
unsigned int d = dim; d < (dim * dim + dim) / 2; ++d)
2273 return std::sqrt(return_value);
2280 template <
int dim,
typename Number>
2282 compute_norm(
const typename SymmetricTensorAccessors::
2283 StorageType<4, dim, Number>::base_tensor_type &data)
2295 const unsigned int n_independent_components = data.dimension;
2297 for (
unsigned int i = 0; i < dim; ++i)
2298 for (
unsigned int j = 0; j < dim; ++j)
2301 for (
unsigned int i = 0; i < dim; ++i)
2302 for (
unsigned int j = dim; j < n_independent_components; ++j)
2305 for (
unsigned int i = dim; i < n_independent_components; ++i)
2306 for (
unsigned int j = 0; j < dim; ++j)
2309 for (
unsigned int i = dim; i < n_independent_components; ++i)
2310 for (
unsigned int j = dim; j < n_independent_components; ++j)
2314 return std::sqrt(return_value);
2323 template <
int rank_,
int dim,
typename Number>
2327 return internal::compute_norm<dim, Number>(data);
2334 namespace SymmetricTensorImplementation
2357 static const unsigned int table[2][2] = {{0, 2}, {2, 1}};
2358 return table[indices[0]][indices[1]];
2363 static const unsigned int table[3][3] = {{0, 3, 4},
2366 return table[indices[0]][indices[1]];
2371 static const unsigned int table[4][4] = {{0, 4, 5, 6},
2375 return table[indices[0]][indices[1]];
2381 if (indices[0] == indices[1])
2385 sorted_indices.
sort();
2387 for (
unsigned int d = 0, c = 0; d < dim; ++d)
2388 for (
unsigned int e = d + 1; e < dim; ++e, ++c)
2389 if ((sorted_indices[0] == d) && (sorted_indices[1] == e))
2405 template <
int dim,
int rank_>
2417 template <
int rank_,
int dim,
typename Number>
2422 return internal::SymmetricTensorImplementation::component_to_unrolled_index<
2430 namespace SymmetricTensorImplementation
2441 unrolled_to_component_indices(
const unsigned int i,
2442 const std::integral_constant<int, 2> &)
2480 for (
unsigned int d = 0, c = 0; d < dim; ++d)
2481 for (
unsigned int e = d + 1; e < dim; ++e, ++c)
2499 template <
int dim,
int rank_>
2501 unrolled_to_component_indices(
const unsigned int i,
2502 const std::integral_constant<int, rank_> &)
2511 n_independent_components));
2519 template <
int rank_,
int dim,
typename Number>
2522 const unsigned int i)
2524 return internal::SymmetricTensorImplementation::unrolled_to_component_indices<
2525 dim>(i, std::integral_constant<int, rank_>());
2530 template <
int rank_,
int dim,
typename Number>
2531 template <
class Archive>
2556 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2559 typename ProductType<Number, OtherNumber>::type>
2582 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2585 typename ProductType<Number, OtherNumber>::type>
2603 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2619 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2635 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2651 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2674 template <
int dim,
typename Number>
2690 return (tmp + tmp + t.
data[0] * t.
data[1] * t.
data[2] -
2712 template <
int dim,
typename Number>
2728 template <
int dim,
typename Number>
2732 Number t = d.
data[0];
2733 for (
unsigned int i = 1; i < dim; ++i)
2748 template <
int dim,
typename Number>
2768 template <
typename Number>
2796 template <
typename Number>
2800 return t[0][0] * t[1][1] - t[0][1] * t[0][1];
2814 template <
typename Number>
2818 return (t[0][0] * t[1][1] + t[1][1] * t[2][2] + t[2][2] * t[0][0] -
2819 t[0][1] * t[0][1] - t[0][2] * t[0][2] - t[1][2] * t[1][2]);
2832 template <
typename Number>
2833 std::array<Number, 1>
2861 template <
typename Number>
2862 std::array<Number, 2>
2889 template <
typename Number>
2890 std::array<Number, 3>
2897 namespace SymmetricTensorImplementation
2938 template <
int dim,
typename Number>
2942 std::array<Number, dim> & d,
2943 std::array<Number, dim - 1> & e);
2988 template <
int dim,
typename Number>
2989 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3035 template <
int dim,
typename Number>
3036 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3056 template <
typename Number>
3057 std::array<std::pair<Number, Tensor<1, 2, Number>>, 2>
3058 hybrid(const ::SymmetricTensor<2, 2, Number> &A);
3096 template <
typename Number>
3097 std::array<std::pair<Number, Tensor<1, 3, Number>>, 3>
3098 hybrid(const ::SymmetricTensor<2, 3, Number> &A);
3104 template <
int dim,
typename Number>
3107 using EigValsVecs = std::pair<Number, Tensor<1, dim, Number>>;
3109 operator()(
const EigValsVecs &lhs,
const EigValsVecs &rhs)
3111 return lhs.first > rhs.first;
3215 template <
int dim,
typename Number>
3216 std::array<std::pair<Number, Tensor<1, dim, Number>>,
3217 std::integral_constant<int, dim>::value>
3233 template <
int rank_,
int dim,
typename Number>
3251 template <
int dim,
typename Number>
3258 const Number tr =
trace(t) / dim;
3259 for (
unsigned int i = 0; i < dim; ++i)
3274 template <
int dim,
typename Number>
3293 for (
unsigned int d = 0; d < dim; ++d)
3313 return unit_symmetric_tensor<dim, double>();
3332 template <
int dim,
typename Number>
3339 for (
unsigned int i = 0; i < dim; ++i)
3340 for (
unsigned int j = 0; j < dim; ++j)
3341 tmp.
data[i][j] = (i == j ? 1 : 0) - 1. / dim;
3348 for (
unsigned int i = dim;
3349 i < internal::SymmetricTensorAccessors::StorageType<4, dim, Number>::
3352 tmp.
data[i][i] = 0.5;
3377 return deviator_tensor<dim, double>();
3404 template <
int dim,
typename Number>
3411 for (
unsigned int i = 0; i < dim; ++i)
3419 for (
unsigned int i = dim;
3420 i < internal::SymmetricTensorAccessors::StorageType<4, dim, Number>::
3423 tmp.
data[i][i] = 0.5;
3455 return identity_tensor<dim, double>();
3470 template <
int dim,
typename Number>
3491 template <
int dim,
typename Number>
3515 template <
int dim,
typename Number>
3523 for (
unsigned int i = 0; i < dim; ++i)
3524 for (
unsigned int j = i; j < dim; ++j)
3525 for (
unsigned int k = 0; k < dim; ++k)
3526 for (
unsigned int l = k; l < dim; ++l)
3527 tmp[i][j][k][l] = t1[i][j] * t2[k][l];
3542 template <
int dim,
typename Number>
3546 Number array[(dim * dim + dim) / 2];
3547 for (
unsigned int d = 0; d < dim; ++d)
3549 for (
unsigned int d = 0, c = 0; d < dim; ++d)
3550 for (
unsigned int e = d + 1; e < dim; ++e, ++c)
3551 array[dim + c] = (t[d][e] + t[e][d]) * 0.5;
3564 template <
int rank_,
int dim,
typename Number>
3582 template <
int rank_,
int dim,
typename Number>
3617 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3624 const OtherNumber & factor)
3631 using product_type =
typename ProductType<Number, OtherNumber>::type;
3640 product_type new_factor;
3641 new_factor = factor;
3656 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3666 return (t * factor);
3676 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3683 const OtherNumber & factor)
3699 template <
int rank_,
int dim>
3716 template <
int rank_,
int dim>
3732 template <
int rank_,
int dim>
3750 template <
int dim,
typename Number,
typename OtherNumber>
3751 inline typename ProductType<Number, OtherNumber>::type
3768 template <
int dim,
typename Number,
typename OtherNumber>
3769 inline typename ProductType<Number, OtherNumber>::type
3774 typename ProductType<Number, OtherNumber>::type>::value(0.0);
3775 for (
unsigned int i = 0; i < dim; ++i)
3776 for (
unsigned int j = 0; j < dim; ++j)
3777 s += t1[i][j] * t2[i][j];
3791 template <
int dim,
typename Number,
typename OtherNumber>
3792 inline typename ProductType<Number, OtherNumber>::type
3815 template <
typename Number,
typename OtherNumber>
3817 SymmetricTensor<2, 1,
typename ProductType<Number, OtherNumber>::type> &tmp,
3821 tmp[0][0] = t[0][0][0][0] * s[0][0];
3841 template <
typename Number,
typename OtherNumber>
3843 SymmetricTensor<2, 1,
typename ProductType<Number, OtherNumber>::type> &tmp,
3847 tmp[0][0] = t[0][0][0][0] * s[0][0];
3866 template <
typename Number,
typename OtherNumber>
3868 SymmetricTensor<2, 2,
typename ProductType<Number, OtherNumber>::type> &tmp,
3872 const unsigned int dim = 2;
3874 for (
unsigned int i = 0; i < dim; ++i)
3875 for (
unsigned int j = i; j < dim; ++j)
3876 tmp[i][j] = t[i][j][0][0] * s[0][0] + t[i][j][1][1] * s[1][1] +
3877 2 * t[i][j][0][1] * s[0][1];
3897 template <
typename Number,
typename OtherNumber>
3899 SymmetricTensor<2, 2,
typename ProductType<Number, OtherNumber>::type> &tmp,
3903 const unsigned int dim = 2;
3905 for (
unsigned int i = 0; i < dim; ++i)
3906 for (
unsigned int j = i; j < dim; ++j)
3907 tmp[i][j] = s[0][0] * t[0][0][i][j] * +s[1][1] * t[1][1][i][j] +
3908 2 * s[0][1] * t[0][1][i][j];
3928 template <
typename Number,
typename OtherNumber>
3930 SymmetricTensor<2, 3,
typename ProductType<Number, OtherNumber>::type> &tmp,
3934 const unsigned int dim = 3;
3936 for (
unsigned int i = 0; i < dim; ++i)
3937 for (
unsigned int j = i; j < dim; ++j)
3938 tmp[i][j] = t[i][j][0][0] * s[0][0] + t[i][j][1][1] * s[1][1] +
3939 t[i][j][2][2] * s[2][2] + 2 * t[i][j][0][1] * s[0][1] +
3940 2 * t[i][j][0][2] * s[0][2] + 2 * t[i][j][1][2] * s[1][2];
3960 template <
typename Number,
typename OtherNumber>
3962 SymmetricTensor<2, 3,
typename ProductType<Number, OtherNumber>::type> &tmp,
3966 const unsigned int dim = 3;
3968 for (
unsigned int i = 0; i < dim; ++i)
3969 for (
unsigned int j = i; j < dim; ++j)
3970 tmp[i][j] = s[0][0] * t[0][0][i][j] + s[1][1] * t[1][1][i][j] +
3971 s[2][2] * t[2][2][i][j] + 2 * s[0][1] * t[0][1][i][j] +
3972 2 * s[0][2] * t[0][2][i][j] + 2 * s[1][2] * t[1][2][i][j];
3984 template <
int dim,
typename Number,
typename OtherNumber>
3990 for (
unsigned int i = 0; i < dim; ++i)
3991 for (
unsigned int j = 0; j < dim; ++j)
3992 dest[i] += src1[i][j] * src2[j];
4004 template <
int dim,
typename Number,
typename OtherNumber>
4035 template <
int rank_1,
4039 typename OtherNumber>
4040 inline DEAL_II_ALWAYS_INLINE
4041 typename Tensor<rank_1 + rank_2 - 2,
4043 typename ProductType<Number, OtherNumber>::type>::tensor_type
4047 typename Tensor<rank_1 + rank_2 - 2,
4049 typename ProductType<Number, OtherNumber>::type>::tensor_type
4077 template <
int rank_1,
4081 typename OtherNumber>
4082 inline DEAL_II_ALWAYS_INLINE
4083 typename Tensor<rank_1 + rank_2 - 2,
4085 typename ProductType<Number, OtherNumber>::type>::tensor_type
4089 typename Tensor<rank_1 + rank_2 - 2,
4091 typename ProductType<Number, OtherNumber>::type>::tensor_type
4108 template <
int dim,
typename Number>
4109 inline std::ostream &
4110 operator<<(std::ostream &out, const SymmetricTensor<2, dim, Number> &t)
4117 for (
unsigned int i = 0; i < dim; ++i)
4118 for (
unsigned int j = 0; j < dim; ++j)
4135 template <
int dim,
typename Number>
4136 inline std::ostream &
4137 operator<<(std::ostream &out, const SymmetricTensor<4, dim, Number> &t)
4144 for (
unsigned int i = 0; i < dim; ++i)
4145 for (
unsigned int j = 0; j < dim; ++j)
4146 for (
unsigned int k = 0; k < dim; ++k)
4147 for (
unsigned int l = 0; l < dim; ++l)
4148 tt[i][j][k][l] = t[i][j][k][l];
4154 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
Number determinant(const SymmetricTensor< 2, dim, Number > &)
static unsigned int component_to_unrolled_index(const TableIndices< rank_ > &indices)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, std::integral_constant< int, dim >::value > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)
SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/(const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)
SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
Number trace(const SymmetricTensor< 2, dim, Number > &d)
bool value_is_zero(const Number &value)
void double_contract(SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 1, Number > &t, const SymmetricTensor< 2, 1, OtherNumber > &s)
#define AssertIndexRange(index, range)
SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
SymmetricTensor< 4, dim, Number > deviator_tensor()
Number third_invariant(const SymmetricTensor< 2, dim, Number > &t)
internal::SymmetricTensorAccessors::Accessor< rank_, dim, true, rank_-1, Number > operator[](const unsigned int row) const
bool operator==(const SymmetricTensor &) const
SymmetricTensor & operator=(const SymmetricTensor< rank_, dim, OtherNumber > &rhs)
static std::size_t memory_consumption()
numbers::NumberTraits< Number >::real_type norm() const
static real_type abs(const number &x)
SymmetricTensorEigenvectorMethod
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
SymmetricTensor & operator/=(const OtherNumber &factor)
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
static TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
static::ExceptionBase & ExcMessage(std::string arg1)
const Number & access_raw_entry(const unsigned int unrolled_index) const
TableIndices< 4 > merge(const TableIndices< 4 > &previous_indices, const unsigned int new_index, const unsigned int position)
typename base_tensor_descriptor::base_tensor_type base_tensor_type
#define Assert(cond, exc)
SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &t)
Number trace(const SymmetricTensor< 2, dim, Number > &d)
void serialize(Archive &ar, const unsigned int version)
Number first_invariant(const SymmetricTensor< 2, dim, Number > &t)
std::array< std::pair< Number, Tensor< 1, 2, Number > >, 2 > hybrid(const ::SymmetricTensor< 2, 2, Number > &A)
SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
Number & operator()(const TableIndices< rank_ > &indices)
void swap(Vector< Number > &u, Vector< Number > &v)
internal::SymmetricTensorAccessors::double_contraction_result< rank_, 2, dim, Number, OtherNumber >::type operator*(const SymmetricTensor< 2, dim, OtherNumber > &s) const
Number determinant(const SymmetricTensor< 2, dim, Number > &t)
SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > ql_implicit_shifts(const ::SymmetricTensor< 2, dim, Number > &A)
SymmetricTensor & operator*=(const OtherNumber &factor)
SymmetricTensor & operator+=(const SymmetricTensor< rank_, dim, OtherNumber > &)
bool operator!=(const SymmetricTensor &) const
static::ExceptionBase & ExcNotImplemented()
SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()
ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
void tridiagonalize(const ::SymmetricTensor< 2, dim, Number > &A,::Tensor< 2, dim, Number > &Q, std::array< Number, dim > &d, std::array< Number, dim-1 > &e)
SymmetricTensor< 4, dim, Number > identity_tensor()
Number second_invariant(const SymmetricTensor< 2, 1, Number > &)
SymmetricTensor & operator-=(const SymmetricTensor< rank_, dim, OtherNumber > &)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > jacobi(::SymmetricTensor< 2, dim, Number > A)
SymmetricTensor operator-() const
static::ExceptionBase & ExcInternalError()