16 #ifndef dealii_symmetric_tensor_h 17 #define dealii_symmetric_tensor_h 35 template <
int rank,
int dim,
typename Number =
double>
39 template <
int dim,
typename Number>
43 template <
int dim,
typename Number>
47 template <
int dim,
typename Number>
51 template <
int dim,
typename Number>
55 template <
int dim,
typename Number>
59 template <
int dim2,
typename Number>
63 template <
int dim,
typename Number>
67 template <
int dim,
typename Number>
80 template <
int rank,
int dim,
typename T,
typename U>
86 std::complex<typename ProductType<T, U>::type>>;
89 template <
int rank,
int dim,
typename T,
typename U>
96 std::complex<typename ProductType<T, U>::type>>;
99 template <
typename T,
int rank,
int dim,
typename U>
105 std::complex<typename ProductType<T, U>::type>>;
108 template <
int rank,
int dim,
typename T,
typename U>
115 std::complex<typename ProductType<T, U>::type>>;
123 namespace SymmetricTensorImplementation
129 template <
int rank,
int dim,
typename Number>
137 namespace SymmetricTensorAccessors
147 const unsigned int new_index,
148 const unsigned int position)
155 return {previous_indices[0], new_index};
168 const unsigned int new_index,
169 const unsigned int position)
179 numbers::invalid_unsigned_int};
181 return {previous_indices[0],
184 numbers::invalid_unsigned_int};
186 return {previous_indices[0],
189 numbers::invalid_unsigned_int};
191 return {previous_indices[0],
214 typename OtherNumber = Number>
231 template <
int dim,
typename Number,
typename OtherNumber>
251 template <
int rank,
int dim,
typename Number>
257 template <
int dim,
typename Number>
264 static const unsigned int n_independent_components =
265 (dim * dim + dim) / 2;
278 template <
int dim,
typename Number>
286 static const unsigned int n_rank2_components = (dim * dim + dim) / 2;
291 static const unsigned int n_independent_components =
292 (n_rank2_components *
310 template <
int rank,
int dim,
bool constness,
typename Number>
319 template <
int rank,
int dim,
typename Number>
333 template <
int rank,
int dim,
typename Number>
376 template <
int rank,
int dim,
bool constness,
int P,
typename Number>
421 operator[](
const unsigned int i);
426 constexpr
Accessor<rank, dim, constness, P - 1, Number>
427 operator[](
const unsigned int i)
const;
438 template <
int,
int,
typename>
439 friend class ::SymmetricTensor;
440 template <
int,
int,
bool,
int,
typename>
442 #ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG 443 friend class ::SymmetricTensor<rank, dim, Number>;
444 friend class Accessor<rank, dim, constness, P + 1, Number>;
459 template <
int rank,
int dim,
bool constness,
typename Number>
511 constexpr
reference operator[](
const unsigned int)
const;
522 template <
int,
int,
typename>
523 friend class ::SymmetricTensor;
524 template <
int,
int,
bool,
int,
typename>
526 #ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG 527 friend class ::SymmetricTensor<rank, dim, Number>;
528 friend class SymmetricTensorAccessors::
610 template <int rank_, int dim, typename Number>
614 static_assert(rank_ % 2 == 0,
"A SymmetricTensor must have even rank!");
624 static const unsigned int dimension = dim;
629 static const unsigned int rank = rank_;
636 static constexpr
unsigned int n_independent_components =
638 n_independent_components;
659 template <
typename OtherNumber>
685 template <
typename OtherNumber>
720 template <
typename OtherNumber>
731 operator=(
const Number &
d);
754 template <
typename OtherNumber>
761 template <
typename OtherNumber>
769 template <
typename OtherNumber>
771 operator*=(
const OtherNumber &factor);
776 template <
typename OtherNumber>
778 operator/=(
const OtherNumber &factor);
812 template <
typename OtherNumber>
821 template <
typename OtherNumber>
842 constexpr internal::SymmetricTensorAccessors::
843 Accessor<rank_, dim,
true, rank_ - 1, Number>
844 operator[](
const unsigned int row)
const;
851 Accessor<rank_, dim,
false, rank_ - 1, Number>
852 operator[](
const unsigned int row);
875 access_raw_entry(
const unsigned int unrolled_index)
const;
884 access_raw_entry(
const unsigned int unrolled_index);
905 static constexpr
unsigned int 914 unrolled_to_component_indices(
const unsigned int i);
935 static constexpr std::size_t
942 template <
class Archive>
944 serialize(Archive &ar,
const unsigned int version);
964 template <
int,
int,
typename>
968 template <
int dim2,
typename Number2>
972 template <
int dim2,
typename Number2>
976 template <
int dim2,
typename Number2>
980 template <
int dim2,
typename Number2>
984 template <
int dim2,
typename Number2>
988 template <
int dim2,
typename Number2>
995 Inverse<2, dim, Number>;
998 Inverse<4, dim, Number>;
1008 template <int rank, int dim, typename Number>
1011 template <int rank_, int dim, typename Number>
1012 constexpr unsigned
int 1017 namespace SymmetricTensorAccessors
1019 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1022 tensor_type & tensor,
1025 , previous_indices(previous_indices)
1030 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1032 Accessor<rank_, dim, constness, P - 1, Number>
1033 Accessor<rank_, dim, constness, P, Number>::
1034 operator[](
const unsigned int i)
1036 return Accessor<rank_, dim, constness, P - 1, Number>(
1037 tensor,
merge(previous_indices, i, rank_ - P));
1042 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1044 Accessor<rank_, dim, constness, P - 1, Number>
1045 Accessor<rank_, dim, constness, P, Number>::
1046 operator[](
const unsigned int i)
const 1048 return Accessor<rank_, dim, constness, P - 1, Number>(
1049 tensor,
merge(previous_indices, i, rank_ - P));
1054 template <
int rank_,
int dim,
bool constness,
typename Number>
1057 tensor_type & tensor,
1060 , previous_indices(previous_indices)
1065 template <
int rank_,
int dim,
bool constness,
typename Number>
1067 typename Accessor<rank_, dim, constness, 1, Number>::reference
1068 Accessor<rank_, dim, constness, 1, Number>::
1069 operator[](
const unsigned int i)
1071 return tensor(
merge(previous_indices, i, rank_ - 1));
1075 template <
int rank_,
int dim,
bool constness,
typename Number>
1077 typename Accessor<rank_, dim, constness, 1, Number>::reference
1078 Accessor<rank_, dim, constness, 1, Number>::
1079 operator[](
const unsigned int i)
const 1081 return tensor(
merge(previous_indices, i, rank_ - 1));
1088 template <
int rank_,
int dim,
typename Number>
1089 template <
typename OtherNumber>
1094 static_assert(rank == 2,
"This function is only implemented for rank==2");
1095 for (
unsigned int d = 0;
d < dim; ++
d)
1096 for (
unsigned int e = 0;
e <
d; ++
e)
1098 ExcMessage(
"The incoming Tensor must be exactly symmetric."));
1100 for (
unsigned int d = 0; d < dim; ++
d)
1103 for (
unsigned int d = 0, c = 0; d < dim; ++
d)
1104 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1105 data[dim + c] = t[d][
e];
1110 template <
int rank_,
int dim,
typename Number>
1111 template <
typename OtherNumber>
1115 : data(initializer.
data)
1120 template <
int rank_,
int dim,
typename Number>
1123 const Number (&array)[n_independent_components])
1125 *reinterpret_cast<const typename base_tensor_type::array_type *>(array))
1128 Assert(
sizeof(
typename base_tensor_type::array_type) ==
sizeof(array),
1134 template <
int rank_,
int dim,
typename Number>
1135 template <
typename OtherNumber>
1147 template <
int rank_,
int dim,
typename Number>
1153 ExcMessage(
"Only assignment with zero is allowed"));
1164 namespace SymmetricTensorImplementation
1166 template <
int dim,
typename Number>
1168 ::Tensor<2, dim, Number>
1169 convert_to_tensor(const ::SymmetricTensor<2, dim, Number> &s)
1174 for (
unsigned int d = 0; d < dim; ++
d)
1175 t[d][d] = s.access_raw_entry(d);
1178 for (
unsigned int d = 0, c = 0; d < dim; ++
d)
1179 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1181 t[
d][
e] = s.access_raw_entry(dim + c);
1182 t[
e][
d] = s.access_raw_entry(dim + c);
1188 template <
int dim,
typename Number>
1189 DEAL_II_CONSTEXPR ::Tensor<4, dim, Number>
1190 convert_to_tensor(const ::SymmetricTensor<4, dim, Number> &st)
1197 for (
unsigned int i = 0; i < dim; ++i)
1198 for (
unsigned int j = i; j < dim; ++j)
1199 for (
unsigned int k = 0; k < dim; ++k)
1200 for (
unsigned int l = k;
l < dim; ++
l)
1210 template <
typename Number>
1211 struct Inverse<2, 1, Number>
1214 ::SymmetricTensor<2, 1, Number>
1215 value(const ::SymmetricTensor<2, 1, Number> &t)
1219 tmp[0][0] = 1.0 / t[0][0];
1226 template <
typename Number>
1227 struct Inverse<2, 2, Number>
1230 ::SymmetricTensor<2, 2, Number>
1231 value(const ::SymmetricTensor<2, 2, Number> &t)
1241 const Number inv_det_t =
1242 1.0 / (t[idx_00] * t[idx_11] - t[idx_01] * t[idx_01]);
1243 tmp[idx_00] = t[idx_11];
1244 tmp[idx_01] = -t[idx_01];
1245 tmp[idx_11] = t[idx_00];
1253 template <
typename Number>
1254 struct Inverse<2, 3, Number>
1257 value(const ::SymmetricTensor<2, 3, Number> &t)
1301 const Number inv_det_t =
1302 1.0 / (t[idx_00] * t[idx_11] * t[idx_22] -
1303 t[idx_00] * t[idx_12] * t[idx_12] -
1304 t[idx_01] * t[idx_01] * t[idx_22] +
1305 2.0 * t[idx_01] * t[idx_02] * t[idx_12] -
1306 t[idx_02] * t[idx_02] * t[idx_11]);
1307 tmp[idx_00] = t[idx_11] * t[idx_22] - t[idx_12] * t[idx_12];
1308 tmp[idx_01] = -t[idx_01] * t[idx_22] + t[idx_02] * t[idx_12];
1309 tmp[idx_02] = t[idx_01] * t[idx_12] - t[idx_02] * t[idx_11];
1310 tmp[idx_11] = t[idx_00] * t[idx_22] - t[idx_02] * t[idx_02];
1311 tmp[idx_12] = -t[idx_00] * t[idx_12] + t[idx_01] * t[idx_02];
1312 tmp[idx_22] = t[idx_00] * t[idx_11] - t[idx_01] * t[idx_01];
1320 template <
typename Number>
1321 struct Inverse<4, 1, Number>
1324 value(const ::SymmetricTensor<4, 1, Number> &t)
1327 tmp.
data[0][0] = 1.0 / t.data[0][0];
1333 template <
typename Number>
1334 struct Inverse<4, 2, Number>
1337 value(const ::SymmetricTensor<4, 2, Number> &t)
1363 const Number t4 = t.data[0][0] * t.data[1][1],
1364 t6 = t.data[0][0] * t.data[1][2],
1365 t8 = t.data[0][1] * t.data[1][0],
1366 t00 = t.data[0][2] * t.data[1][0],
1367 t01 = t.data[0][1] * t.data[2][0],
1368 t04 = t.data[0][2] * t.data[2][0],
1369 t07 = 1.0 / (t4 * t.data[2][2] - t6 * t.data[2][1] -
1370 t8 * t.data[2][2] + t00 * t.data[2][1] +
1371 t01 * t.data[1][2] - t04 * t.data[1][1]);
1373 (t.data[1][1] * t.data[2][2] - t.data[1][2] * t.data[2][1]) * t07;
1375 -(t.data[0][1] * t.data[2][2] - t.data[0][2] * t.data[2][1]) * t07;
1377 -(-t.data[0][1] * t.data[1][2] + t.data[0][2] * t.data[1][1]) * t07;
1379 -(t.data[1][0] * t.data[2][2] - t.data[1][2] * t.data[2][0]) * t07;
1380 tmp.
data[1][1] = (t.data[0][0] * t.data[2][2] - t04) * t07;
1381 tmp.
data[1][2] = -(t6 - t00) * t07;
1383 -(-t.data[1][0] * t.data[2][1] + t.data[1][1] * t.data[2][0]) * t07;
1384 tmp.
data[2][1] = -(t.data[0][0] * t.data[2][1] - t01) * t07;
1385 tmp.
data[2][2] = (t4 - t8) * t07;
1389 tmp.
data[2][0] /= 2;
1390 tmp.
data[2][1] /= 2;
1391 tmp.
data[0][2] /= 2;
1392 tmp.
data[1][2] /= 2;
1393 tmp.
data[2][2] /= 4;
1400 template <
typename Number>
1401 struct Inverse<4, 3, Number>
1403 static ::SymmetricTensor<4, 3, Number>
1404 value(const ::SymmetricTensor<4, 3, Number> &t)
1414 const unsigned int N = 6;
1420 for (
unsigned int i = 0; i <
N; ++i)
1422 const Number typical_diagonal_element =
1423 diagonal_sum /
static_cast<double>(
N);
1424 (void)typical_diagonal_element;
1427 for (
unsigned int i = 0; i <
N; ++i)
1430 for (
unsigned int j = 0; j <
N; ++j)
1436 for (
unsigned int i = j + 1; i <
N; ++i)
1444 Assert(max > 1.
e-16 * typical_diagonal_element,
1445 ExcMessage(
"This tensor seems to be noninvertible"));
1450 for (
unsigned int k = 0; k <
N; ++k)
1457 const Number hr = 1. / tmp.
data[j][j];
1458 tmp.
data[j][j] = hr;
1459 for (
unsigned int k = 0; k <
N; ++k)
1463 for (
unsigned int i = 0; i <
N; ++i)
1467 tmp.
data[i][k] -= tmp.
data[i][j] * tmp.
data[j][k] * hr;
1470 for (
unsigned int i = 0; i <
N; ++i)
1472 tmp.
data[i][j] *= hr;
1473 tmp.
data[j][i] *= -hr;
1475 tmp.
data[j][j] = hr;
1480 for (
unsigned int i = 0; i <
N; ++i)
1482 for (
unsigned int k = 0; k <
N; ++k)
1483 hv[p[k]] = tmp.
data[i][k];
1484 for (
unsigned int k = 0; k <
N; ++k)
1485 tmp.
data[i][k] = hv[k];
1490 for (
unsigned int i = 3; i < 6; ++i)
1491 for (
unsigned int j = 0; j < 3; ++j)
1492 tmp.
data[i][j] /= 2;
1494 for (
unsigned int i = 0; i < 3; ++i)
1495 for (
unsigned int j = 3; j < 6; ++j)
1496 tmp.
data[i][j] /= 2;
1498 for (
unsigned int i = 3; i < 6; ++i)
1499 for (
unsigned int j = 3; j < 6; ++j)
1500 tmp.
data[i][j] /= 4;
1511 template <
int rank_,
int dim,
typename Number>
1515 return internal::SymmetricTensorImplementation::convert_to_tensor(*
this);
1520 template <
int rank_,
int dim,
typename Number>
1525 return data == t.
data;
1530 template <
int rank_,
int dim,
typename Number>
1535 return data != t.
data;
1540 template <
int rank_,
int dim,
typename Number>
1541 template <
typename OtherNumber>
1553 template <
int rank_,
int dim,
typename Number>
1554 template <
typename OtherNumber>
1566 template <
int rank_,
int dim,
typename Number>
1567 template <
typename OtherNumber>
1578 template <
int rank_,
int dim,
typename Number>
1579 template <
typename OtherNumber>
1590 template <
int rank_,
int dim,
typename Number>
1602 template <
int rank_,
int dim,
typename Number>
1611 template <
int rank_,
int dim,
typename Number>
1612 constexpr std::size_t
1624 template <
int dim,
typename Number,
typename OtherNumber = Number>
1628 perform_double_contraction(
1629 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1631 const typename SymmetricTensorAccessors::
1632 StorageType<2, dim, OtherNumber>::base_tensor_type &sdata)
1640 return data[0] * sdata[0];
1645 result_type
sum = data[dim] * sdata[dim];
1646 for (
unsigned int d = dim + 1; d < (dim * (dim + 1) / 2); ++
d)
1647 sum += data[d] * sdata[d];
1651 for (
unsigned int d = 0; d < dim; ++
d)
1652 sum += data[d] * sdata[d];
1659 template <
int dim,
typename Number,
typename OtherNumber = Number>
1663 perform_double_contraction(
1664 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1666 const typename SymmetricTensorAccessors::
1667 StorageType<2, dim, OtherNumber>::base_tensor_type &sdata)
1674 const unsigned int data_dim = SymmetricTensorAccessors::
1675 StorageType<2, dim, value_type>::n_independent_components;
1676 value_type tmp[data_dim]{};
1677 for (
unsigned int i = 0; i < data_dim; ++i)
1679 perform_double_contraction<dim, Number, OtherNumber>(data[i], sdata);
1680 return result_type(tmp);
1685 template <
int dim,
typename Number,
typename OtherNumber = Number>
1687 typename SymmetricTensorAccessors::StorageType<
1693 perform_double_contraction(
1694 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1696 const typename SymmetricTensorAccessors::
1697 StorageType<4, dim, OtherNumber>::base_tensor_type &sdata)
1702 StorageType<2, dim, value_type>::base_tensor_type;
1705 for (
unsigned int i = 0; i < tmp.dimension; ++i)
1708 value_type
sum = data[dim] * sdata[dim][i];
1709 for (
unsigned int d = dim + 1; d < (dim * (dim + 1) / 2); ++
d)
1710 sum += data[d] * sdata[d][i];
1714 for (
unsigned int d = 0; d < dim; ++
d)
1715 sum += data[d] * sdata[d][i];
1723 template <
int dim,
typename Number,
typename OtherNumber = Number>
1725 typename SymmetricTensorAccessors::StorageType<
1731 perform_double_contraction(
1732 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1734 const typename SymmetricTensorAccessors::
1735 StorageType<4, dim, OtherNumber>::base_tensor_type &sdata)
1740 StorageType<4, dim, value_type>::base_tensor_type;
1742 const unsigned int data_dim = SymmetricTensorAccessors::
1743 StorageType<2, dim, value_type>::n_independent_components;
1745 for (
unsigned int i = 0; i < data_dim; ++i)
1746 for (
unsigned int j = 0; j < data_dim; ++j)
1749 for (
unsigned int d = dim; d < (dim * (dim + 1) / 2); ++
d)
1750 tmp[i][j] += data[i][d] * sdata[d][j];
1751 tmp[i][j] += tmp[i][j];
1754 for (
unsigned int d = 0; d < dim; ++
d)
1755 tmp[i][j] += data[i][d] * sdata[d][j];
1764 template <
int rank_,
int dim,
typename Number>
1765 template <
typename OtherNumber>
1776 return internal::perform_double_contraction<dim, Number, OtherNumber>(data,
1782 template <
int rank_,
int dim,
typename Number>
1783 template <
typename OtherNumber>
1792 internal::perform_double_contraction<dim, Number, OtherNumber>(data,
1815 template <
typename Type>
1816 struct Uninitialized
1821 template <
typename Type>
1824 template <
int dim,
typename Number>
1827 typename SymmetricTensorAccessors::
1828 StorageType<2, dim, Number>::base_tensor_type &data)
1836 if (indices[0] == indices[1])
1837 return data[indices[0]];
1844 Assert(((indices[0] == 1) && (indices[1] == 0)) ||
1845 ((indices[0] == 0) && (indices[1] == 1)),
1854 for (
unsigned int d = 0, c = 0; d < dim; ++
d)
1855 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1856 if ((sorted_indices[0] == d) && (sorted_indices[1] ==
e))
1857 return data[dim + c];
1870 template <
int dim,
typename Number>
1873 const typename SymmetricTensorAccessors::
1874 StorageType<2, dim, Number>::base_tensor_type &data)
1882 if (indices[0] == indices[1])
1883 return data[indices[0]];
1890 Assert(((indices[0] == 1) && (indices[1] == 0)) ||
1891 ((indices[0] == 0) && (indices[1] == 1)),
1900 for (
unsigned int d = 0, c = 0; d < dim; ++
d)
1901 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1902 if ((sorted_indices[0] == d) && (sorted_indices[1] ==
e))
1903 return data[dim + c];
1916 template <
int dim,
typename Number>
1919 typename SymmetricTensorAccessors::
1920 StorageType<4, dim, Number>::base_tensor_type &data)
1934 constexpr std::size_t base_index[2][2] = {{0, 2}, {2, 1}};
1935 return data[base_index[indices[0]][indices[1]]]
1936 [base_index[indices[2]][indices[3]]];
1945 constexpr std::size_t base_index[3][3] = {{0, 3, 4},
1948 return data[base_index[indices[0]][indices[1]]]
1949 [base_index[indices[2]][indices[3]]];
1963 template <
int dim,
typename Number>
1966 const typename SymmetricTensorAccessors::
1967 StorageType<4, dim, Number>::base_tensor_type &data)
1981 constexpr std::size_t base_index[2][2] = {{0, 2}, {2, 1}};
1982 return data[base_index[indices[0]][indices[1]]]
1983 [base_index[indices[2]][indices[3]]];
1992 constexpr std::size_t base_index[3][3] = {{0, 3, 4},
1995 return data[base_index[indices[0]][indices[1]]]
1996 [base_index[indices[2]][indices[3]]];
2013 template <
int rank_,
int dim,
typename Number>
2018 for (
unsigned int r = 0; r < rank; ++r)
2020 return internal::symmetric_tensor_access<dim, Number>(indices, data);
2025 template <
int rank_,
int dim,
typename Number>
2030 for (
unsigned int r = 0; r < rank; ++r)
2032 return internal::symmetric_tensor_access<dim, Number>(indices, data);
2039 namespace SymmetricTensorImplementation
2041 template <
int rank_>
2043 get_partially_filled_indices(
const unsigned int row,
2044 const std::integral_constant<int, 2> &)
2050 template <
int rank_>
2052 get_partially_filled_indices(
const unsigned int row,
2053 const std::integral_constant<int, 4> &)
2064 template <
int rank_,
int dim,
typename Number>
2066 Accessor<rank_, dim,
true, rank_ - 1, Number>
2070 return internal::SymmetricTensorAccessors::
2071 Accessor<rank_, dim,
true, rank_ - 1, Number>(
2073 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2074 rank_>(row, std::integral_constant<int, rank_>()));
2079 template <
int rank_,
int dim,
typename Number>
2084 return internal::SymmetricTensorAccessors::
2085 Accessor<rank_, dim,
false, rank_ - 1, Number>(
2087 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2088 rank_>(row, std::integral_constant<int, rank_>()));
2093 template <
int rank_,
int dim,
typename Number>
2098 return operator()(indices);
2103 template <
int rank_,
int dim,
typename Number>
2108 return operator()(indices);
2113 template <
int rank_,
int dim,
typename Number>
2117 return std::addressof(this->access_raw_entry(0));
2122 template <
int rank_,
int dim,
typename Number>
2123 inline const Number *
2126 return std::addressof(this->access_raw_entry(0));
2131 template <
int rank_,
int dim,
typename Number>
2135 return begin_raw() + n_independent_components;
2140 template <
int rank_,
int dim,
typename Number>
2141 inline const Number *
2144 return begin_raw() + n_independent_components;
2151 namespace SymmetricTensorImplementation
2153 template <
int dim,
typename Number>
2154 constexpr
unsigned int 2155 entry_to_indices(const ::SymmetricTensor<2, dim, Number> &,
2156 const unsigned int index)
2162 template <
int dim,
typename Number>
2163 constexpr ::TableIndices<2>
2164 entry_to_indices(const ::SymmetricTensor<4, dim, Number> &,
2165 const unsigned int index)
2176 template <
int rank_,
int dim,
typename Number>
2179 const unsigned int index)
const 2182 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this,
2188 template <
int rank_,
int dim,
typename Number>
2193 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this,
2201 template <
int dim,
typename Number>
2203 compute_norm(
const typename SymmetricTensorAccessors::
2204 StorageType<2, dim, Number>::base_tensor_type &data)
2231 for (
unsigned int d = 0; d < dim; ++
d)
2234 for (
unsigned int d = dim; d < (dim * dim + dim) / 2; ++
d)
2238 return std::sqrt(return_value);
2245 template <
int dim,
typename Number>
2247 compute_norm(
const typename SymmetricTensorAccessors::
2248 StorageType<4, dim, Number>::base_tensor_type &data)
2260 const unsigned int n_independent_components = data.dimension;
2262 for (
unsigned int i = 0; i < dim; ++i)
2263 for (
unsigned int j = 0; j < dim; ++j)
2266 for (
unsigned int i = 0; i < dim; ++i)
2267 for (
unsigned int j = dim; j < n_independent_components; ++j)
2270 for (
unsigned int i = dim; i < n_independent_components; ++i)
2271 for (
unsigned int j = 0; j < dim; ++j)
2274 for (
unsigned int i = dim; i < n_independent_components; ++i)
2275 for (
unsigned int j = dim; j < n_independent_components; ++j)
2279 return std::sqrt(return_value);
2288 template <
int rank_,
int dim,
typename Number>
2292 return internal::compute_norm<dim, Number>(data);
2299 namespace SymmetricTensorImplementation
2322 constexpr
unsigned int table[2][2] = {{0, 2}, {2, 1}};
2323 return table[indices[0]][indices[1]];
2328 constexpr
unsigned int table[3][3] = {{0, 3, 4},
2331 return table[indices[0]][indices[1]];
2336 constexpr
unsigned int table[4][4] = {{0, 4, 5, 6},
2340 return table[indices[0]][indices[1]];
2346 if (indices[0] == indices[1])
2350 sorted_indices.
sort();
2352 for (
unsigned int d = 0, c = 0; d < dim; ++
d)
2353 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2354 if ((sorted_indices[0] == d) && (sorted_indices[1] ==
e))
2370 template <
int dim,
int rank_>
2382 template <
int rank_,
int dim,
typename Number>
2383 constexpr
unsigned int 2387 return internal::SymmetricTensorImplementation::component_to_unrolled_index<
2395 namespace SymmetricTensorImplementation
2406 unrolled_to_component_indices(
const unsigned int i,
2407 const std::integral_constant<int, 2> &)
2445 for (
unsigned int d = 0, c = 0; d < dim; ++
d)
2446 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2464 template <
int dim,
int rank_>
2466 typename std::enable_if<rank_ != 2, TableIndices<rank_>>
::type 2467 unrolled_to_component_indices(
const unsigned int i,
2468 const std::integral_constant<int, rank_> &)
2477 n_independent_components));
2485 template <
int rank_,
int dim,
typename Number>
2488 const unsigned int i)
2490 return internal::SymmetricTensorImplementation::unrolled_to_component_indices<
2491 dim>(i, std::integral_constant<int, rank_>());
2496 template <
int rank_,
int dim,
typename Number>
2497 template <
class Archive>
2522 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2547 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2567 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2584 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2601 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2618 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2643 template <
int dim,
typename Number>
2659 return (tmp + tmp + t.
data[0] * t.
data[1] * t.
data[2] -
2684 template <
int dim,
typename Number>
2703 template <
int dim,
typename Number>
2707 Number t = d.
data[0];
2708 for (
unsigned int i = 1; i < dim; ++i)
2726 template <
int dim,
typename Number>
2746 template <
typename Number>
2774 template <
typename Number>
2778 return t[0][0] * t[1][1] - t[0][1] * t[0][1];
2792 template <
typename Number>
2796 return (t[0][0] * t[1][1] + t[1][1] * t[2][2] + t[2][2] * t[0][0] -
2797 t[0][1] * t[0][1] - t[0][2] * t[0][2] - t[1][2] * t[1][2]);
2810 template <
typename Number>
2811 std::array<Number, 1>
2839 template <
typename Number>
2840 std::array<Number, 2>
2868 template <
typename Number>
2869 std::array<Number, 3>
2876 namespace SymmetricTensorImplementation
2917 template <
int dim,
typename Number>
2921 std::array<Number, dim> & d,
2922 std::array<Number, dim - 1> &
e);
2967 template <
int dim,
typename Number>
2968 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
2969 ql_implicit_shifts(const ::SymmetricTensor<2, dim, Number> &A);
3014 template <
int dim,
typename Number>
3015 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3035 template <
typename Number>
3036 std::array<std::pair<Number, Tensor<1, 2, Number>>, 2>
3037 hybrid(const ::SymmetricTensor<2, 2, Number> &A);
3075 template <
typename Number>
3076 std::array<std::pair<Number, Tensor<1, 3, Number>>, 3>
3077 hybrid(const ::SymmetricTensor<2, 3, Number> &A);
3083 template <
int dim,
typename Number>
3090 return lhs.first > rhs.first;
3194 template <
int dim,
typename Number>
3195 std::array<std::pair<Number, Tensor<1, dim, Number>>,
3212 template <
int rank_,
int dim,
typename Number>
3232 template <
int dim,
typename Number>
3239 const Number tr =
trace(t) / dim;
3240 for (
unsigned int i = 0; i < dim; ++i)
3255 template <
int dim,
typename Number>
3275 for (
unsigned int d = 0; d < dim; ++
d)
3295 return unit_symmetric_tensor<dim, double>();
3329 template <
int dim,
typename Number>
3336 for (
unsigned int i = 0; i < dim; ++i)
3337 for (
unsigned int j = 0; j < dim; ++j)
3346 for (
unsigned int i = dim;
3347 i < internal::SymmetricTensorAccessors::StorageType<4, dim, Number>::
3369 return deviator_tensor<dim, double>();
3412 template <
int dim,
typename Number>
3419 for (
unsigned int i = 0; i < dim; ++i)
3427 for (
unsigned int i = dim;
3428 i < internal::SymmetricTensorAccessors::StorageType<4, dim, Number>::
3450 return identity_tensor<dim, double>();
3465 template <
int dim,
typename Number>
3486 template <
int dim,
typename Number>
3518 template <
int dim,
typename Number>
3526 for (
unsigned int i = 0; i < dim; ++i)
3527 for (
unsigned int j = i; j < dim; ++j)
3528 for (
unsigned int k = 0; k < dim; ++k)
3529 for (
unsigned int l = k;
l < dim; ++
l)
3530 tmp[i][j][k][
l] = t1[i][j] * t2[k][
l];
3545 template <
int dim,
typename Number>
3550 for (
unsigned int d = 0; d < dim; ++
d)
3551 result[d][d] = t[d][d];
3554 for (
unsigned int d = 0; d < dim; ++
d)
3555 for (
unsigned int e = d + 1;
e < dim; ++
e)
3556 result[d][
e] = (t[d][
e] + t[
e][d]) * half;
3569 template <
int rank_,
int dim,
typename Number>
3588 template <
int rank_,
int dim,
typename Number>
3623 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3630 const OtherNumber & factor)
3653 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3663 return (t * factor);
3673 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3680 const OtherNumber & factor)
3696 template <
int rank_,
int dim>
3713 template <
int rank_,
int dim>
3729 template <
int rank_,
int dim>
3747 template <
int dim,
typename Number,
typename OtherNumber>
3769 template <
int dim,
typename Number,
typename OtherNumber>
3777 for (
unsigned int i = 0; i < dim; ++i)
3778 for (
unsigned int j = 0; j < dim; ++j)
3779 s += t1[i][j] * t2[i][j];
3797 template <
int dim,
typename Number,
typename OtherNumber>
3821 template <
typename Number,
typename OtherNumber>
3827 tmp[0][0] = t[0][0][0][0] * s[0][0];
3847 template <
typename Number,
typename OtherNumber>
3853 tmp[0][0] = t[0][0][0][0] * s[0][0];
3873 template <
typename Number,
typename OtherNumber>
3879 const unsigned int dim = 2;
3881 for (
unsigned int i = 0; i < dim; ++i)
3882 for (
unsigned int j = i; j < dim; ++j)
3883 tmp[i][j] = t[i][j][0][0] * s[0][0] + t[i][j][1][1] * s[1][1] +
3884 2 * t[i][j][0][1] * s[0][1];
3904 template <
typename Number,
typename OtherNumber>
3910 const unsigned int dim = 2;
3912 for (
unsigned int i = 0; i < dim; ++i)
3913 for (
unsigned int j = i; j < dim; ++j)
3914 tmp[i][j] = s[0][0] * t[0][0][i][j] * +s[1][1] * t[1][1][i][j] +
3915 2 * s[0][1] * t[0][1][i][j];
3935 template <
typename Number,
typename OtherNumber>
3941 const unsigned int dim = 3;
3943 for (
unsigned int i = 0; i < dim; ++i)
3944 for (
unsigned int j = i; j < dim; ++j)
3945 tmp[i][j] = t[i][j][0][0] * s[0][0] + t[i][j][1][1] * s[1][1] +
3946 t[i][j][2][2] * s[2][2] + 2 * t[i][j][0][1] * s[0][1] +
3947 2 * t[i][j][0][2] * s[0][2] + 2 * t[i][j][1][2] * s[1][2];
3967 template <
typename Number,
typename OtherNumber>
3973 const unsigned int dim = 3;
3975 for (
unsigned int i = 0; i < dim; ++i)
3976 for (
unsigned int j = i; j < dim; ++j)
3977 tmp[i][j] = s[0][0] * t[0][0][i][j] + s[1][1] * t[1][1][i][j] +
3978 s[2][2] * t[2][2][i][j] + 2 * s[0][1] * t[0][1][i][j] +
3979 2 * s[0][2] * t[0][2][i][j] + 2 * s[1][2] * t[1][2][i][j];
3991 template <
int dim,
typename Number,
typename OtherNumber>
3998 for (
unsigned int i = 0; i < dim; ++i)
3999 for (
unsigned int j = 0; j < dim; ++j)
4000 dest[i] += src1[i][j] * src2[j];
4012 template <
int dim,
typename Number,
typename OtherNumber>
4043 template <
int rank_1,
4047 typename OtherNumber>
4049 typename Tensor<rank_1 + rank_2 - 2,
4080 template <
int rank_1,
4084 typename OtherNumber>
4086 typename Tensor<rank_1 + rank_2 - 2,
4106 template <
int dim,
typename Number>
4107 inline std::ostream &
4108 operator<<(std::ostream &out, const SymmetricTensor<2, dim, Number> &t)
4115 for (
unsigned int i = 0; i < dim; ++i)
4116 for (
unsigned int j = 0; j < dim; ++j)
4133 template <
int dim,
typename Number>
4134 inline std::ostream &
4135 operator<<(std::ostream &out, const SymmetricTensor<4, dim, Number> &t)
4142 for (
unsigned int i = 0; i < dim; ++i)
4143 for (
unsigned int j = 0; j < dim; ++j)
4144 for (
unsigned int k = 0; k < dim; ++k)
4145 for (
unsigned int l = 0;
l < dim; ++
l)
4146 tt[i][j][k][
l] = t[i][j][k][
l];
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
static const unsigned int invalid_unsigned_int
constexpr internal::SymmetricTensorAccessors::double_contraction_result< rank_, 2, dim, Number, OtherNumber >::type operator*(const SymmetricTensor< 2, dim, OtherNumber > &s) const
typename AccessorTypes< rank, dim, constness, Number >::tensor_type tensor_type
static constexpr 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)
constexpr SymmetricTensor operator-() const
constexpr SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &t)
static constexpr const T & value(const T &t)
constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
typename internal::ProductTypeImpl< typename std::decay< T >::type, typename std::decay< U >::type >::type type
constexpr SymmetricTensor & operator-=(const SymmetricTensor< rank_, dim, OtherNumber > &)
constexpr SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
constexpr numbers::NumberTraits< Number >::real_type norm() const
bool operator!=(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
#define AssertIndexRange(index, range)
typename AccessorTypes< rank, dim, constness, Number >::reference reference
static constexpr TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
double norm(const FEValuesBase< dim > &fe, const ArrayView< const std::vector< Tensor< 1, dim >>> &Du)
constexpr bool operator==(const SymmetricTensor &) const
static real_type abs(const number &x)
constexpr SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
SymmetricTensorEigenvectorMethod
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
bool operator==(const AlignedVector< T > &lhs, const AlignedVector< T > &rhs)
constexpr const Number & access_raw_entry(const unsigned int unrolled_index) const
const TableIndices< rank > previous_indices
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
constexpr SymmetricTensor & operator+=(const SymmetricTensor< rank_, dim, OtherNumber > &)
constexpr SymmetricTensor & operator/=(const OtherNumber &factor)
typename AccessorTypes< rank, dim, constness, Number >::tensor_type tensor_type
constexpr SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
typename ProductType< Number, OtherNumber >::type type
constexpr internal::SymmetricTensorAccessors::Accessor< rank_, dim, true, rank_ - 1, Number > operator[](const unsigned int row) const
static ::ExceptionBase & ExcMessage(std::string arg1)
constexpr bool operator!=(const SymmetricTensor &) const
constexpr SymmetricTensor()=default
typename base_tensor_descriptor::base_tensor_type base_tensor_type
T sum(const T &t, const MPI_Comm &mpi_communicator)
#define Assert(cond, exc)
std::pair< Number, Tensor< 1, dim, Number > > EigValsVecs
bool operator()(const EigValsVecs &lhs, const EigValsVecs &rhs)
constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
constexpr Number trace(const SymmetricTensor< 2, dim, Number > &d)
constexpr TableIndices< 4 > merge(const TableIndices< 4 > &previous_indices, const unsigned int new_index, const unsigned int position)
constexpr SymmetricTensor< 4, dim, Number > identity_tensor()
const TableIndices< rank > previous_indices
#define DEAL_II_NAMESPACE_CLOSE
typename ProductType< Number, OtherNumber >::type value_type
constexpr SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
void serialize(Archive &ar, const unsigned int version)
void tridiagonalize(const ::SymmetricTensor< 2, dim, Number > &A, ::Tensor< 2, dim, Number > &Q, std::array< Number, dim > &d, std::array< Number, dim - 1 > &e)
#define DEAL_II_ALWAYS_INLINE
typename AccessorTypes< rank, dim, constness, Number >::reference reference
constexpr void double_contract(SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 1, Number > &t, const SymmetricTensor< 2, 1, OtherNumber > &s)
constexpr Number second_invariant(const SymmetricTensor< 2, 1, Number > &)
Expression fabs(const Expression &x)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &t)
MatrixTableIterators::Accessor< TransposeTable< T >, Constness, MatrixTableIterators::Storage::column_major > Accessor
::SymmetricTensor< rank1+rank2 - 4, dim, value_type > type
constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/(const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)
static constexpr std::size_t memory_consumption()
void swap(MemorySpaceData< Number, MemorySpace > &, MemorySpaceData< Number, MemorySpace > &)
constexpr Number first_invariant(const SymmetricTensor< 2, dim, Number > &t)
constexpr SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()
#define DEAL_II_NAMESPACE_OPEN
T min(const T &t, const MPI_Comm &mpi_communicator)
constexpr bool value_is_zero(const Number &value)
decltype(std::declval< T >() *std::declval< U >()) type
constexpr ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
constexpr Number trace(const SymmetricTensor< 2, dim2, Number > &)
static ::ExceptionBase & ExcNotImplemented()
constexpr Number & operator()(const TableIndices< rank_ > &indices)
constexpr Number third_invariant(const SymmetricTensor< 2, dim, Number > &t)
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 4, dim, Number > deviator_tensor()
constexpr SymmetricTensor & operator*=(const OtherNumber &factor)
T max(const T &t, const MPI_Comm &mpi_communicator)
#define DEAL_II_CONSTEXPR
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
static ::ExceptionBase & ExcInternalError()
constexpr SymmetricTensor & operator=(const SymmetricTensor< rank_, dim, OtherNumber > &rhs)