13#ifndef dealii_symmetric_tensor_h
14#define dealii_symmetric_tensor_h
27#if DEAL_II_KOKKOS_VERSION_GTE(4, 3, 0)
28# include <Kokkos_Swap.hpp>
37template <
int rank,
int dim,
typename Number =
double>
51template <
int dim,
typename Number =
double>
112template <
int dim,
typename Number =
double>
154template <
int dim,
typename Number =
double>
159template <
int dim,
typename Number>
164template <
int dim,
typename Number>
178template <
int dim2,
typename Number>
220template <
int dim,
typename Number>
238template <
int dim,
typename Number>
250 template <
int rank,
int dim,
typename T,
typename U>
256 std::complex<typename ProductType<T, U>::type>>;
259 template <
int rank,
int dim,
typename T,
typename U>
266 std::complex<typename ProductType<T, U>::type>>;
269 template <
typename T,
int rank,
int dim,
typename U>
275 std::complex<typename ProductType<T, U>::type>>;
278 template <
int rank,
int dim,
typename T,
typename U>
285 std::complex<typename ProductType<T, U>::type>>;
293 namespace SymmetricTensorImplementation
299 template <
int rank,
int dim,
typename Number>
307 namespace SymmetricTensorAccessors
318 const unsigned int new_index,
319 const unsigned int position)
326 return {previous_indices[0], new_index};
340 const unsigned int new_index,
341 const unsigned int position)
353 return {previous_indices[0],
358 return {previous_indices[0],
363 return {previous_indices[0],
384 typename OtherNumber = Number>
399 template <
int dim,
typename Number,
typename OtherNumber>
419 template <
int rank,
int dim,
typename Number>
425 template <
int dim,
typename Number>
432 static const unsigned int n_independent_components =
433 (dim * dim + dim) / 2;
446 template <
int dim,
typename Number>
454 static const unsigned int n_rank2_components = (dim * dim + dim) / 2;
459 static const unsigned int n_independent_components =
460 (n_rank2_components *
478 template <
int rank,
int dim,
bool constness,
typename Number>
487 template <
int rank,
int dim,
typename Number>
501 template <
int rank,
int dim,
typename Number>
542 template <
int rank,
int dim,
bool constness,
int P,
typename Number>
589 constexpr Accessor<rank, dim, constness, P - 1, Number>
596 constexpr Accessor<rank, dim, constness, P - 1, Number>
608 template <
int,
int,
typename>
609 friend class ::SymmetricTensor;
610 template <
int,
int,
bool,
int,
typename>
612 friend class ::SymmetricTensor<rank, dim, Number>;
613 friend class Accessor<rank, dim, constness, P + 1, Number>;
625 template <
int rank,
int dim,
bool constness,
typename Number>
694 template <
int,
int,
typename>
695 friend class ::SymmetricTensor;
696 template <
int,
int,
bool,
int,
typename>
698 friend class ::SymmetricTensor<rank, dim, Number>;
699 friend class SymmetricTensorAccessors::
700 Accessor<rank, dim, constness, 2, Number>;
779template <int rank_, int dim, typename Number>
783 static_assert(rank_ % 2 == 0,
"A SymmetricTensor must have even rank!");
793 static constexpr unsigned int dimension = dim;
798 static const unsigned int rank = rank_;
805 static constexpr unsigned int n_independent_components =
807 n_independent_components;
829 template <
typename OtherNumber>
856 template <
typename OtherNumber>
866 template <
typename OtherNumber>
904 template <
typename OtherNumber>
911 template <
typename OtherNumber>
919 template <
typename OtherNumber>
926 template <
typename OtherNumber>
989 template <
typename OtherNumber>
991 typename internal::SymmetricTensorAccessors::
992 double_contraction_result<rank_, 2, dim, Number, OtherNumber>::type
999 template <
typename OtherNumber>
1001 typename internal::SymmetricTensorAccessors::
1002 double_contraction_result<rank_, 4, dim, Number, OtherNumber>::type
1016 constexpr const Number &
1024 constexpr internal::SymmetricTensorAccessors::
1025 Accessor<rank_, dim,
true, rank_ - 1, Number>
1033 constexpr internal::SymmetricTensorAccessors::
1034 Accessor<rank_, dim,
false, rank_ - 1, Number>
1043 constexpr const Number &
1062 constexpr const Number &
1134 template <
class Archive>
1158 template <
int,
int,
typename>
1162 template <
int dim2,
typename Number2>
1166 template <
int dim2,
typename Number2>
1170 template <
int dim2,
typename Number2>
1174 template <
int dim2,
typename Number2>
1178 template <
int dim2,
typename Number2>
1182 template <
int dim2,
typename Number2>
1189 Inverse<2, dim, Number>;
1192 Inverse<4, dim, Number>;
1203template <int rank, int dim, typename Number>
1206template <int rank_, int dim, typename Number>
1207constexpr unsigned
int
1212 namespace SymmetricTensorAccessors
1214 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1216 Accessor<rank_, dim, constness, P, Number>::Accessor(
1217 tensor_type &tensor,
1220 , previous_indices(previous_indices)
1225 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1227 Accessor<rank_, dim, constness, P - 1, Number>
1228 Accessor<rank_, dim, constness, P, Number>::operator[](
1229 const unsigned int i)
1231 return Accessor<rank_, dim, constness, P - 1, Number>(
1232 tensor, merge(previous_indices, i, rank_ - P));
1237 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1239 Accessor<rank_, dim, constness, P - 1,
Number>
1240 Accessor<rank_, dim, constness, P, Number>::operator[](
1241 const unsigned int i)
const
1243 return Accessor<rank_, dim, constness, P - 1,
Number>(
1244 tensor,
merge(previous_indices, i, rank_ - P));
1249 template <
int rank_,
int dim,
bool constness,
typename Number>
1251 Accessor<rank_, dim, constness, 1, Number>::Accessor(
1252 tensor_type &tensor,
1255 , previous_indices(previous_indices)
1260 template <
int rank_,
int dim,
bool constness,
typename Number>
1262 typename Accessor<rank_, dim, constness, 1, Number>::reference
1263 Accessor<rank_, dim, constness, 1, Number>::operator[](
1264 const unsigned int i)
1266 return tensor(
merge(previous_indices, i, rank_ - 1));
1270 template <
int rank_,
int dim,
bool constness,
typename Number>
1272 typename Accessor<rank_, dim, constness, 1, Number>::reference
1273 Accessor<rank_, dim, constness, 1, Number>::operator[](
1274 const unsigned int i)
const
1276 return tensor(
merge(previous_indices, i, rank_ - 1));
1283template <
int rank_,
int dim,
typename Number>
1284template <
typename OtherNumber>
1289 static_assert(rank == 2,
"This function is only implemented for rank==2");
1290 for (
unsigned int d = 0;
d < dim; ++
d)
1291 for (
unsigned int e = 0;
e <
d; ++
e)
1292 Assert(t[d][e] == t[e][d],
1293 ExcMessage(
"The incoming Tensor must be exactly symmetric."));
1295 for (
unsigned int d = 0;
d < dim; ++
d)
1298 for (
unsigned int d = 0, c = 0;
d < dim; ++
d)
1299 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1300 data[dim + c] = t[d][e];
1305template <
int rank_,
int dim,
typename Number>
1306template <
typename OtherNumber>
1315template <
int rank_,
int dim,
typename Number>
1318 const Number (&array)[n_independent_components])
1320 *reinterpret_cast<
const typename base_tensor_type::array_type *>(array))
1323 static_assert(
sizeof(
typename base_tensor_type::array_type) ==
sizeof(array));
1328template <
int rank_,
int dim,
typename Number>
1329template <
typename OtherNumber>
1341template <
int rank_,
int dim,
typename Number>
1347 ExcMessage(
"Only assignment with zero is allowed"));
1358 namespace SymmetricTensorImplementation
1360 template <
int dim,
typename Number>
1361 constexpr inline DEAL_II_ALWAYS_INLINE ::Tensor<2, dim, Number>
1362 convert_to_tensor(const ::SymmetricTensor<2, dim, Number> &s)
1367 for (
unsigned int d = 0;
d < dim; ++
d)
1368 t[d][d] = s.access_raw_entry(d);
1371 for (
unsigned int d = 0, c = 0;
d < dim; ++
d)
1372 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1374 t[
d][
e] = s.access_raw_entry(dim + c);
1375 t[
e][
d] = s.access_raw_entry(dim + c);
1381 template <
int dim,
typename Number>
1382 constexpr ::Tensor<4, dim, Number>
1383 convert_to_tensor(const ::SymmetricTensor<4, dim, Number> &st)
1390 for (
unsigned int i = 0; i < dim; ++i)
1391 for (
unsigned int j = i; j < dim; ++j)
1392 for (
unsigned int k = 0; k < dim; ++k)
1393 for (
unsigned int l = k;
l < dim; ++
l)
1403 template <
typename Number>
1404 struct Inverse<2, 1,
Number>
1407 ::SymmetricTensor<2, 1, Number>
1408 value(const ::SymmetricTensor<2, 1, Number> &t)
1412 tmp[0][0] = 1.0 / t[0][0];
1419 template <
typename Number>
1420 struct Inverse<2, 2,
Number>
1423 ::SymmetricTensor<2, 2, Number>
1424 value(const ::SymmetricTensor<2, 2, Number> &t)
1435 1.0 / (t[idx_00] * t[idx_11] - t[idx_01] * t[idx_01]);
1436 tmp[idx_00] = t[idx_11];
1437 tmp[idx_01] = -t[idx_01];
1438 tmp[idx_11] = t[idx_00];
1446 template <
typename Number>
1447 struct Inverse<2, 3,
Number>
1450 value(const ::SymmetricTensor<2, 3, Number> &t)
1495 1.0 / (t[idx_00] * t[idx_11] * t[idx_22] -
1496 t[idx_00] * t[idx_12] * t[idx_12] -
1497 t[idx_01] * t[idx_01] * t[idx_22] +
1498 2.0 * t[idx_01] * t[idx_02] * t[idx_12] -
1499 t[idx_02] * t[idx_02] * t[idx_11]);
1500 tmp[idx_00] = t[idx_11] * t[idx_22] - t[idx_12] * t[idx_12];
1501 tmp[idx_01] = -t[idx_01] * t[idx_22] + t[idx_02] * t[idx_12];
1502 tmp[idx_02] = t[idx_01] * t[idx_12] - t[idx_02] * t[idx_11];
1503 tmp[idx_11] = t[idx_00] * t[idx_22] - t[idx_02] * t[idx_02];
1504 tmp[idx_12] = -t[idx_00] * t[idx_12] + t[idx_01] * t[idx_02];
1505 tmp[idx_22] = t[idx_00] * t[idx_11] - t[idx_01] * t[idx_01];
1513 template <
typename Number>
1514 struct Inverse<4, 1,
Number>
1517 SymmetricTensor<4, 1, Number>
1518 value(const ::SymmetricTensor<4, 1, Number> &t)
1521 tmp.
data[0][0] = 1.0 / t.data[0][0];
1527 template <
typename Number>
1528 struct Inverse<4, 2,
Number>
1531 SymmetricTensor<4, 2, Number>
1532 value(const ::SymmetricTensor<4, 2, Number> &t)
1558 const Number t4 = t.data[0][0] * t.data[1][1],
1559 t6 = t.data[0][0] * t.data[1][2],
1560 t8 = t.data[0][1] * t.data[1][0],
1561 t00 = t.data[0][2] * t.data[1][0],
1562 t01 = t.data[0][1] * t.data[2][0],
1563 t04 = t.data[0][2] * t.data[2][0],
1564 t07 = 1.0 / (t4 * t.data[2][2] - t6 * t.data[2][1] -
1565 t8 * t.data[2][2] + t00 * t.data[2][1] +
1566 t01 * t.data[1][2] - t04 * t.data[1][1]);
1568 (t.data[1][1] * t.data[2][2] - t.data[1][2] * t.data[2][1]) * t07;
1570 -(t.data[0][1] * t.data[2][2] - t.data[0][2] * t.data[2][1]) * t07;
1572 -(-t.data[0][1] * t.data[1][2] + t.data[0][2] * t.data[1][1]) * t07;
1574 -(t.data[1][0] * t.data[2][2] - t.data[1][2] * t.data[2][0]) * t07;
1575 tmp.
data[1][1] = (t.data[0][0] * t.data[2][2] - t04) * t07;
1576 tmp.
data[1][2] = -(t6 - t00) * t07;
1578 -(-t.data[1][0] * t.data[2][1] + t.data[1][1] * t.data[2][0]) * t07;
1579 tmp.
data[2][1] = -(t.data[0][0] * t.data[2][1] - t01) * t07;
1580 tmp.
data[2][2] = (t4 - t8) * t07;
1584 tmp.
data[2][0] /= 2;
1585 tmp.
data[2][1] /= 2;
1586 tmp.
data[0][2] /= 2;
1587 tmp.
data[1][2] /= 2;
1588 tmp.
data[2][2] /= 4;
1600 template <
class NumberType>
1602 device_swap(NumberType &x, NumberType &y)
noexcept
1604 if constexpr (std::is_same_v<NumberType, double> ||
1605 std::is_same_v<NumberType, float> ||
1606 std::is_same_v<NumberType, unsigned int>)
1608# if DEAL_II_KOKKOS_VERSION_GTE(4, 3, 0)
1609 Kokkos::kokkos_swap(x, y);
1622 template <
typename Number>
1623 struct Inverse<4, 3,
Number>
1626 value(const ::SymmetricTensor<4, 3, Number> &t)
1636 const unsigned int N = 6;
1642 for (
unsigned int i = 0; i <
N; ++i)
1644 const Number typical_diagonal_element =
1645 diagonal_sum /
static_cast<double>(
N);
1646 (void)typical_diagonal_element;
1649 for (
unsigned int i = 0; i <
N; ++i)
1652 for (
unsigned int j = 0; j <
N; ++j)
1658 for (
unsigned int i = j + 1; i <
N; ++i)
1666 Assert(max > 1.e-16 * typical_diagonal_element,
1667 ExcMessage(
"This tensor seems to be noninvertible"));
1672 for (
unsigned int k = 0; k <
N; ++k)
1673 device_swap(tmp.
data[j][k], tmp.
data[r][k]);
1675 device_swap(p[j], p[r]);
1680 tmp.
data[j][j] = hr;
1681 for (
unsigned int k = 0; k <
N; ++k)
1685 for (
unsigned int i = 0; i <
N; ++i)
1689 tmp.
data[i][k] -= tmp.
data[i][j] * tmp.
data[j][k] * hr;
1692 for (
unsigned int i = 0; i <
N; ++i)
1694 tmp.
data[i][j] *= hr;
1695 tmp.
data[j][i] *= -hr;
1697 tmp.
data[j][j] = hr;
1702 for (
unsigned int i = 0; i <
N; ++i)
1704 for (
unsigned int k = 0; k <
N; ++k)
1705 hv[p[k]] = tmp.
data[i][k];
1706 for (
unsigned int k = 0; k <
N; ++k)
1707 tmp.
data[i][k] = hv[k];
1712 for (
unsigned int i = 3; i < 6; ++i)
1713 for (
unsigned int j = 0; j < 3; ++j)
1714 tmp.
data[i][j] /= 2;
1716 for (
unsigned int i = 0; i < 3; ++i)
1717 for (
unsigned int j = 3; j < 6; ++j)
1718 tmp.
data[i][j] /= 2;
1720 for (
unsigned int i = 3; i < 6; ++i)
1721 for (
unsigned int j = 3; j < 6; ++j)
1722 tmp.
data[i][j] /= 4;
1733template <
int rank_,
int dim,
typename Number>
1738 return internal::SymmetricTensorImplementation::convert_to_tensor(*
this);
1743template <
int rank_,
int dim,
typename Number>
1753template <
int rank_,
int dim,
typename Number>
1763template <
int rank_,
int dim,
typename Number>
1764template <
typename OtherNumber>
1776template <
int rank_,
int dim,
typename Number>
1777template <
typename OtherNumber>
1789template <
int rank_,
int dim,
typename Number>
1790template <
typename OtherNumber>
1801template <
int rank_,
int dim,
typename Number>
1802template <
typename OtherNumber>
1813template <
int rank_,
int dim,
typename Number>
1825template <
int rank_,
int dim,
typename Number>
1834template <
int rank_,
int dim,
typename Number>
1850 template <
int dim,
typename Number,
typename OtherNumber = Number>
1852 typename SymmetricTensorAccessors::
1853 double_contraction_result<2, 2, dim, Number, OtherNumber>::type
1854 perform_double_contraction(
1855 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1856 base_tensor_type &
data,
1857 const typename SymmetricTensorAccessors::
1858 StorageType<2, dim, OtherNumber>::base_tensor_type &sdata)
1860 using result_type =
typename SymmetricTensorAccessors::
1861 double_contraction_result<2, 2, dim, Number, OtherNumber>::type;
1866 return data[0] * sdata[0];
1874 result_type
sum =
data[dim] * sdata[dim];
1875 for (
unsigned int d = dim + 1;
d < (dim * (dim + 1) / 2); ++
d)
1876 sum +=
data[d] * sdata[d];
1880 for (
unsigned int d = 0;
d < dim; ++
d)
1881 sum +=
data[d] * sdata[d];
1892 template <
int dim,
typename Number,
typename OtherNumber = Number>
1894 typename SymmetricTensorAccessors::
1895 double_contraction_result<4, 2, dim, Number, OtherNumber>::type
1896 perform_double_contraction(
1897 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1898 base_tensor_type &
data,
1899 const typename SymmetricTensorAccessors::
1900 StorageType<2, dim, OtherNumber>::base_tensor_type &sdata)
1902 using result_type =
typename SymmetricTensorAccessors::
1903 double_contraction_result<4, 2, dim, Number, OtherNumber>::type;
1904 using value_type =
typename SymmetricTensorAccessors::
1905 double_contraction_result<4, 2, dim, Number, OtherNumber>::value_type;
1907 const unsigned int data_dim = SymmetricTensorAccessors::
1908 StorageType<2, dim, value_type>::n_independent_components;
1910 for (
unsigned int i = 0; i < data_dim; ++i)
1912 perform_double_contraction<dim, Number, OtherNumber>(
data[i], sdata);
1913 return result_type(tmp);
1922 template <
int dim,
typename Number,
typename OtherNumber = Number>
1924 typename SymmetricTensorAccessors::StorageType<
1927 typename SymmetricTensorAccessors::
1928 double_contraction_result<2, 4, dim, Number, OtherNumber>::value_type>::
1930 perform_double_contraction(
1931 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1932 base_tensor_type &
data,
1933 const typename SymmetricTensorAccessors::
1934 StorageType<4, dim, OtherNumber>::base_tensor_type &sdata)
1936 using value_type =
typename SymmetricTensorAccessors::
1937 double_contraction_result<2, 4, dim, Number, OtherNumber>::value_type;
1938 using base_tensor_type =
typename SymmetricTensorAccessors::
1939 StorageType<2, dim, value_type>::base_tensor_type;
1941 base_tensor_type tmp;
1942 for (
unsigned int i = 0; i < tmp.dimension; ++i)
1950 for (
unsigned int d = dim + 1;
d < (dim * (dim + 1) / 2); ++
d)
1951 sum +=
data[d] * sdata[d][i];
1955 for (
unsigned int d = 0;
d < dim; ++
d)
1956 sum +=
data[d] * sdata[d][i];
1967 template <
int dim,
typename Number,
typename OtherNumber = Number>
1969 typename SymmetricTensorAccessors::StorageType<
1972 typename SymmetricTensorAccessors::
1973 double_contraction_result<4, 4, dim, Number, OtherNumber>::value_type>::
1975 perform_double_contraction(
1976 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1977 base_tensor_type &
data,
1978 const typename SymmetricTensorAccessors::
1979 StorageType<4, dim, OtherNumber>::base_tensor_type &sdata)
1981 using value_type =
typename SymmetricTensorAccessors::
1982 double_contraction_result<4, 4, dim, Number, OtherNumber>::value_type;
1983 using base_tensor_type =
typename SymmetricTensorAccessors::
1984 StorageType<4, dim, value_type>::base_tensor_type;
1986 const unsigned int data_dim = SymmetricTensorAccessors::
1987 StorageType<2, dim, value_type>::n_independent_components;
1988 base_tensor_type tmp;
1989 for (
unsigned int i = 0; i < data_dim; ++i)
1990 for (
unsigned int j = 0; j < data_dim; ++j)
1993 for (
unsigned int d = dim;
d < (dim * (dim + 1) / 2); ++
d)
1994 tmp[i][j] +=
data[i][d] * sdata[d][j];
1995 tmp[i][j] += tmp[i][j];
1998 for (
unsigned int d = 0;
d < dim; ++
d)
1999 tmp[i][j] +=
data[i][d] * sdata[d][j];
2008template <
int rank_,
int dim,
typename Number>
2009template <
typename OtherNumber>
2011 typename internal::SymmetricTensorAccessors::
2012 double_contraction_result<rank_, 2, dim, Number, OtherNumber>::type
2018 return internal::perform_double_contraction<dim, Number, OtherNumber>(
data,
2024template <
int rank_,
int dim,
typename Number>
2025template <
typename OtherNumber>
2027 typename internal::SymmetricTensorAccessors::
2028 double_contraction_result<rank_, 4, dim, Number, OtherNumber>::type
2032 typename internal::SymmetricTensorAccessors::
2033 double_contraction_result<rank_, 4, dim, Number, OtherNumber>::type tmp;
2035 internal::perform_double_contraction<dim, Number, OtherNumber>(
data,
2052 namespace SymmetricTensorImplementation
2075 constexpr unsigned int table[2][2] = {{0, 2}, {2, 1}};
2076 return table[indices[0]][indices[1]];
2086 const unsigned int i = indices[0];
2087 const unsigned int j = indices[1];
2090 constexpr unsigned int table[3] = {0, 3, 4};
2095 constexpr unsigned int table[3] = {3, 1, 5};
2100 constexpr unsigned int table[3] = {4, 5, 2};
2106 constexpr unsigned int table[4][4] = {{0, 4, 5, 6},
2110 return table[indices[0]][indices[1]];
2115 if (indices[0] == indices[1])
2126 for (
unsigned int d = 0;
d < dim; ++
d)
2127 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2128 if ((sorted_indices[0] == d) && (sorted_indices[1] == e))
2144 template <
int dim,
int rank_>
2154 template <
int dim,
typename Number>
2157 typename SymmetricTensorAccessors::
2158 StorageType<2, dim,
Number>::base_tensor_type &
data)
2160 return data[SymmetricTensorImplementation::component_to_unrolled_index<dim>(
2166 template <
int dim,
typename Number>
2169 symmetric_tensor_access(
2171 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
2172 base_tensor_type &
data)
2174 return data[SymmetricTensorImplementation::component_to_unrolled_index<dim>(
2180 template <
int dim,
typename Number>
2183 typename SymmetricTensorAccessors::
2184 StorageType<4, dim,
Number>::base_tensor_type &
data)
2198 constexpr std::size_t base_index[2][2] = {{0, 2}, {2, 1}};
2199 return data[base_index[indices[0]][indices[1]]]
2200 [base_index[indices[2]][indices[3]]];
2209 constexpr std::size_t base_index[3][3] = {{0, 3, 4},
2212 return data[base_index[indices[0]][indices[1]]]
2213 [base_index[indices[2]][indices[3]]];
2228 template <
int dim,
typename Number>
2231 symmetric_tensor_access(
2233 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
2234 base_tensor_type &
data)
2248 constexpr std::size_t base_index[2][2] = {{0, 2}, {2, 1}};
2249 return data[base_index[indices[0]][indices[1]]]
2250 [base_index[indices[2]][indices[3]]];
2259 constexpr std::size_t base_index[3][3] = {{0, 3, 4},
2262 return data[base_index[indices[0]][indices[1]]]
2263 [base_index[indices[2]][indices[3]]];
2281template <
int rank_,
int dim,
typename Number>
2286 for (
unsigned int r = 0; r < rank; ++r)
2288 return internal::symmetric_tensor_access<dim, Number>(indices,
data);
2293template <
int rank_,
int dim,
typename Number>
2298 for (
unsigned int r = 0; r < rank; ++r)
2300 return internal::symmetric_tensor_access<dim, Number>(indices,
data);
2307 namespace SymmetricTensorImplementation
2309 template <
int rank_>
2311 get_partially_filled_indices(
const unsigned int row,
2312 const std::integral_constant<int, 2> &)
2318 template <
int rank_>
2320 get_partially_filled_indices(
const unsigned int row,
2321 const std::integral_constant<int, 4> &)
2332template <
int rank_,
int dim,
typename Number>
2334 SymmetricTensorAccessors::Accessor<rank_, dim,
true, rank_ - 1,
Number>
2337 return internal::SymmetricTensorAccessors::
2338 Accessor<rank_, dim,
true, rank_ - 1,
Number>(
2340 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2341 rank_>(row, std::integral_constant<int, rank_>()));
2346template <
int rank_,
int dim,
typename Number>
2348 SymmetricTensorAccessors::Accessor<rank_, dim,
false, rank_ - 1,
Number>
2351 return internal::SymmetricTensorAccessors::
2352 Accessor<rank_, dim,
false, rank_ - 1,
Number>(
2354 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2355 rank_>(row, std::integral_constant<int, rank_>()));
2360template <
int rank_,
int dim,
typename Number>
2370template <
int rank_,
int dim,
typename Number>
2380template <
int rank_,
int dim,
typename Number>
2383 const unsigned int index)
const
2386 constexpr unsigned int my_n_independent_components = n_independent_components;
2389 if constexpr (rank == 2)
2392 return data[
decltype(
data)::unrolled_to_component_indices(index)];
2397template <
int rank_,
int dim,
typename Number>
2402 constexpr unsigned int my_n_independent_components = n_independent_components;
2405 if constexpr (rank == 2)
2408 return data[
decltype(
data)::unrolled_to_component_indices(index)];
2415 template <
int dim,
typename Number>
2417 compute_norm(
const typename SymmetricTensorAccessors::
2418 StorageType<2, dim,
Number>::base_tensor_type &
data)
2445 for (
unsigned int d = 0;
d < dim; ++
d)
2448 for (
unsigned int d = dim;
d < (dim * dim + dim) / 2; ++
d)
2452 return sqrt(return_value);
2459 template <
int dim,
typename Number>
2461 compute_norm(
const typename SymmetricTensorAccessors::
2462 StorageType<4, dim,
Number>::base_tensor_type &
data)
2476 const unsigned int n_independent_components =
data.dimension;
2478 for (
unsigned int i = 0; i < dim; ++i)
2479 for (
unsigned int j = 0; j < dim; ++j)
2482 for (
unsigned int i = 0; i < dim; ++i)
2483 for (
unsigned int j = dim; j < n_independent_components; ++j)
2486 for (
unsigned int i = dim; i < n_independent_components; ++i)
2487 for (
unsigned int j = 0; j < dim; ++j)
2490 for (
unsigned int i = dim; i < n_independent_components; ++i)
2491 for (
unsigned int j = dim; j < n_independent_components; ++j)
2495 return sqrt(return_value);
2504template <
int rank_,
int dim,
typename Number>
2508 return internal::compute_norm<dim, Number>(
data);
2513template <
int rank_,
int dim,
typename Number>
2518 return internal::SymmetricTensorImplementation::component_to_unrolled_index<
2526 namespace SymmetricTensorImplementation
2538 const std::integral_constant<int, 2> &)
2576 for (
unsigned int d = 0, c = dim;
d < dim; ++
d)
2577 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2595 template <
int dim,
int rank_>
2596 constexpr inline std::enable_if_t<rank_ != 2, TableIndices<rank_>>
2598 const std::integral_constant<int, rank_> &)
2607 n_independent_components));
2615template <
int rank_,
int dim,
typename Number>
2618 const unsigned int i)
2620 return internal::SymmetricTensorImplementation::unrolled_to_component_indices<
2621 dim>(i, std::integral_constant<int, rank_>());
2626template <
int rank_,
int dim,
typename Number>
2627template <
class Archive>
2652template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2677template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2697template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2714template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2731template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2748template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2759template <
int dim,
typename Number>
2775 return (tmp + tmp + t.
data[0] * t.
data[1] * t.
data[2] -
2799template <
int dim,
typename Number>
2808template <
int dim,
typename Number>
2812 Number t = d.data[0];
2813 for (
unsigned int i = 1; i < dim; ++i)
2830template <
int dim,
typename Number>
2849template <
typename Number>
2876template <
typename Number>
2880 return t[0][0] * t[1][1] - t[0][1] * t[0][1];
2893template <
typename Number>
2897 return (t[0][0] * t[1][1] + t[1][1] * t[2][2] + t[2][2] * t[0][0] -
2898 t[0][1] * t[0][1] - t[0][2] * t[0][2] - t[1][2] * t[1][2]);
2910template <
typename Number>
2911std::array<Number, 1>
2938template <
typename Number>
2939std::array<Number, 2>
2966template <
typename Number>
2967std::array<Number, 3>
2974 namespace SymmetricTensorImplementation
2987 template <
int dim,
typename Number>
2991 std::array<Number, dim> &d,
2992 std::array<Number, dim - 1> &e);
3009 template <
int dim,
typename Number>
3010 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3028 template <
int dim,
typename Number>
3029 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3047 template <
typename Number>
3048 std::array<std::pair<Number, Tensor<1, 2, Number>>, 2>
3049 hybrid(const ::SymmetricTensor<2, 2, Number> &A);
3067 template <
typename Number>
3068 std::array<std::pair<Number, Tensor<1, 3, Number>>, 3>
3069 hybrid(const ::SymmetricTensor<2, 3, Number> &A);
3075 template <
int dim,
typename Number>
3082 return lhs.first > rhs.first;
3149template <
int dim,
typename Number>
3150std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3165template <
int rank_,
int dim,
typename Number>
3175template <
int dim,
typename Number>
3184 for (
unsigned int i = 0; i < dim; ++i)
3192template <
int dim,
typename Number>
3213 for (
unsigned int d = 0; d < dim; ++d)
3221template <
int dim,
typename Number>
3228 for (
unsigned int i = 0; i < dim; ++i)
3229 for (
unsigned int j = 0; j < dim; ++j)
3238 for (
unsigned int i = dim;
3239 i < internal::SymmetricTensorAccessors::StorageType<4, dim, Number>::
3249template <
int dim,
typename Number>
3257 for (
unsigned int i = 0; i < dim; ++i)
3265 for (
unsigned int i = dim;
3266 i < internal::SymmetricTensorAccessors::StorageType<4, dim, Number>::
3285template <
int dim,
typename Number>
3306template <
int dim,
typename Number>
3337template <
int dim,
typename Number>
3345 for (
unsigned int i = 0; i < dim; ++i)
3346 for (
unsigned int j = i; j < dim; ++j)
3347 for (
unsigned int k = 0; k < dim; ++k)
3348 for (
unsigned int l = k; l < dim; ++l)
3349 tmp[i][j][k][l] = t1[i][j] * t2[k][l];
3379template <
int dim,
typename Number>
3385 const std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3389 positive_negative_tensors;
3391 auto &[positive_part_tensor, negative_part_tensor] =
3392 positive_negative_tensors;
3394 positive_part_tensor = 0;
3395 for (
unsigned int i = 0; i < dim; ++i)
3396 if (eigen_system[i].
first > 0)
3397 positive_part_tensor += eigen_system[i].first *
3399 eigen_system[i].
second));
3401 negative_part_tensor = 0;
3402 for (
unsigned int i = 0; i < dim; ++i)
3403 if (eigen_system[i].
first < 0)
3404 negative_part_tensor += eigen_system[i].first *
3406 eigen_system[i].
second));
3408 return positive_negative_tensors;
3443template <
int dim,
typename Number>
3444std::tuple<SymmetricTensor<2, dim, Number>,
3453 auto heaviside_function{[](
const double x) {
3454 if (std::fabs(x) < 1.0e-16)
3462 std::tuple<SymmetricTensor<2, dim, Number>,
3466 positive_negative_tensors_projectors;
3468 auto &[positive_part_tensor,
3469 negative_part_tensor,
3471 negative_projector] = positive_negative_tensors_projectors;
3473 const std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3476 positive_part_tensor = 0;
3477 for (
unsigned int i = 0; i < dim; ++i)
3478 if (eigen_system[i].
first > 0)
3479 positive_part_tensor += eigen_system[i].first *
3481 eigen_system[i].
second));
3483 negative_part_tensor = 0;
3484 for (
unsigned int i = 0; i < dim; ++i)
3485 if (eigen_system[i].
first < 0)
3486 negative_part_tensor += eigen_system[i].first *
3488 eigen_system[i].
second));
3490 std::array<SymmetricTensor<2, dim, Number>, dim> M;
3491 for (
unsigned int a = 0; a < dim; ++a)
3495 std::array<SymmetricTensor<4, dim, Number>, dim> Q;
3496 for (
unsigned int a = 0; a < dim; ++a)
3499 std::array<std::array<SymmetricTensor<4, dim, Number>, dim>, dim> G;
3500 for (
unsigned int a = 0; a < dim; ++a)
3501 for (
unsigned int b = 0; b < dim; ++b)
3502 for (
unsigned int i = 0; i < dim; ++i)
3503 for (
unsigned int j = 0; j < dim; ++j)
3504 for (
unsigned int k = 0; k < dim; ++k)
3505 for (
unsigned int l = 0; l < dim; ++l)
3506 G[a][b][i][j][k][l] =
3507 M[a][i][k] * M[b][j][l] + M[a][i][l] * M[b][j][k];
3510 positive_projector = 0;
3511 for (
unsigned int a = 0; a < dim; ++a)
3513 double lambda_a = eigen_system[a].first;
3514 positive_projector += heaviside_function(lambda_a) * Q[a];
3515 for (
unsigned int b = 0; b < dim; ++b)
3519 double lambda_b = eigen_system[b].first;
3522 if (std::fabs(lambda_a - lambda_b) > 1.0e-12)
3523 v_ab = (std::fmax(lambda_a, 0.0) - std::fmax(lambda_b, 0.0)) /
3524 (lambda_a - lambda_b);
3526 v_ab = 0.5 * (heaviside_function(lambda_a) +
3527 heaviside_function(lambda_b));
3529 positive_projector += 0.5 * v_ab * 0.5 * (G[a][b] + G[b][a]);
3535 negative_projector = 0;
3536 for (
unsigned int a = 0; a < dim; ++a)
3538 double lambda_a = eigen_system[a].first;
3539 negative_projector += heaviside_function(-lambda_a) * Q[a];
3540 for (
unsigned int b = 0; b < dim; ++b)
3544 double lambda_b = eigen_system[b].first;
3547 if (std::fabs(lambda_a - lambda_b) > 1.0e-12)
3548 v_ab = (std::fmin(lambda_a, 0.0) - std::fmin(lambda_b, 0.0)) /
3549 (lambda_a - lambda_b);
3551 v_ab = 0.5 * (heaviside_function(-lambda_a) +
3552 heaviside_function(-lambda_b));
3554 negative_projector += 0.5 * v_ab * 0.5 * (G[a][b] + G[b][a]);
3559 return positive_negative_tensors_projectors;
3569template <
int dim,
typename Number>
3575 for (
unsigned int d = 0; d < dim; ++d)
3576 result[d][d] = t[d][d];
3579 for (
unsigned int d = 0; d < dim; ++d)
3580 for (
unsigned int e = d + 1; e < dim; ++e)
3581 result[d][e] = (t[d][e] + t[e][d]) * half;
3598template <
int dim,
typename Number>
3608 for (
unsigned int i = 0; i < dim; ++i)
3609 for (
unsigned int j = 0; j < dim; ++j)
3610 for (
unsigned int k = 0; k < dim; ++k)
3611 for (
unsigned int l = 0; l < dim; ++l)
3613 if (i != j && k == l)
3616 result[i][j][k][k] = (t[i][j][k][k] + t[j][i][k][k]) * half;
3618 else if (i == j && k != l)
3621 result[i][i][k][l] = (t[i][i][k][l] + t[i][i][l][k]) * half;
3623 else if (i != j && k != l)
3626 result[i][j][k][l] = (t[i][j][k][l] + t[j][i][k][l] +
3627 t[i][j][l][k] + t[j][i][l][k]) *
3633 result[i][j][k][l] = t[i][j][k][l];
3641 for (
unsigned int i = 0; i < dim; ++i)
3642 for (
unsigned int j = i; j < dim; ++j)
3643 for (
unsigned int k = 0; k < dim; ++k)
3644 for (
unsigned int l = k; l < dim; ++l)
3645 result[i][j][k][l] = (t[i][j][k][l] + t[k][l][i][j]) * half;
3659template <
int rank_,
int dim,
typename Number>
3678template <
int rank_,
int dim,
typename Number>
3713template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3720 const OtherNumber &factor)
3742template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3752 return (t * factor);
3762template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3769 const OtherNumber &factor)
3785template <
int rank_,
int dim>
3803template <
int rank_,
int dim>
3820template <
int rank_,
int dim>
3838template <
int dim,
typename Number,
typename OtherNumber>
3860template <
int dim,
typename Number,
typename OtherNumber>
3868 for (
unsigned int i = 0; i < dim; ++i)
3869 for (
unsigned int j = 0; j < dim; ++j)
3870 s += t1[i][j] * t2[i][j];
3887template <
int dim,
typename Number,
typename OtherNumber>
3893 return scalar_product(t2, t1);
3911template <
typename Number,
typename OtherNumber>
3918 tmp[0][0] = t[0][0][0][0] * s[0][0];
3937template <
typename Number,
typename OtherNumber>
3944 tmp[0][0] = t[0][0][0][0] * s[0][0];
3963template <
typename Number,
typename OtherNumber>
3970 const unsigned int dim = 2;
3972 for (
unsigned int i = 0; i < dim; ++i)
3973 for (
unsigned int j = i; j < dim; ++j)
3974 tmp[i][j] = t[i][j][0][0] * s[0][0] + t[i][j][1][1] * s[1][1] +
3975 2 * t[i][j][0][1] * s[0][1];
3994template <
typename Number,
typename OtherNumber>
4001 const unsigned int dim = 2;
4003 for (
unsigned int i = 0; i < dim; ++i)
4004 for (
unsigned int j = i; j < dim; ++j)
4005 tmp[i][j] = s[0][0] * t[0][0][i][j] * +s[1][1] * t[1][1][i][j] +
4006 2 * s[0][1] * t[0][1][i][j];
4025template <
typename Number,
typename OtherNumber>
4032 const unsigned int dim = 3;
4034 for (
unsigned int i = 0; i < dim; ++i)
4035 for (
unsigned int j = i; j < dim; ++j)
4036 tmp[i][j] = t[i][j][0][0] * s[0][0] + t[i][j][1][1] * s[1][1] +
4037 t[i][j][2][2] * s[2][2] + 2 * t[i][j][0][1] * s[0][1] +
4038 2 * t[i][j][0][2] * s[0][2] + 2 * t[i][j][1][2] * s[1][2];
4057template <
typename Number,
typename OtherNumber>
4064 const unsigned int dim = 3;
4066 for (
unsigned int i = 0; i < dim; ++i)
4067 for (
unsigned int j = i; j < dim; ++j)
4068 tmp[i][j] = s[0][0] * t[0][0][i][j] + s[1][1] * t[1][1][i][j] +
4069 s[2][2] * t[2][2][i][j] + 2 * s[0][1] * t[0][1][i][j] +
4070 2 * s[0][2] * t[0][2][i][j] + 2 * s[1][2] * t[1][2][i][j];
4081template <
int dim,
typename Number,
typename OtherNumber>
4090 for (
unsigned int i = 0; i < dim; ++i)
4092 dest[i] = src1[i][0] * src2[0];
4093 for (
unsigned int j = 1; j < dim; ++j)
4094 dest[i] += src1[i][j] * src2[j];
4106template <
int dim,
typename Number,
typename OtherNumber>
4139template <
int rank_1,
4143 typename OtherNumber>
4145 typename Tensor<rank_1 + rank_2 - 2,
4175template <
int rank_1,
4179 typename OtherNumber>
4181 typename Tensor<rank_1 + rank_2 - 2,
4201template <
int dim,
typename Number>
4202inline std::ostream &
4210 for (
unsigned int i = 0; i < dim; ++i)
4211 for (
unsigned int j = 0; j < dim; ++j)
4228template <
int dim,
typename Number>
4229inline std::ostream &
4237 for (
unsigned int i = 0; i < dim; ++i)
4238 for (
unsigned int j = 0; j < dim; ++j)
4239 for (
unsigned int k = 0; k < dim; ++k)
4240 for (
unsigned int l = 0; l < dim; ++l)
4241 tt[i][j][k][l] = t[i][j][k][l];
* * Point< dim > operator()(const Point< dim > &p) const *
constexpr SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &)
constexpr bool operator==(const SymmetricTensor &) const
constexpr Number first_invariant(const SymmetricTensor< 2, dim, Number > &t)
constexpr void double_contract(SymmetricTensor< 2, 2, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 2, 2, Number > &s, const SymmetricTensor< 4, 2, OtherNumber > &t)
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 ProductType< Number, OtherNumber >::type scalar_product(const Tensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
std::pair< SymmetricTensor< 2, dim, Number >, SymmetricTensor< 2, dim, Number > > positive_negative_split(const SymmetricTensor< 2, dim, Number > &original_tensor)
constexpr SymmetricTensor< 4, dim, Number > invert(const SymmetricTensor< 4, dim, Number > &t)
constexpr SymmetricTensor< rank_, dim > operator*(const SymmetricTensor< rank_, dim > &t, const double factor)
constexpr Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator*(const SymmetricTensor< 2, dim, Number > &src1, const Tensor< 1, dim, OtherNumber > &src2)
constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
constexpr SymmetricTensor(const Number(&array)[n_independent_components])
constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const Tensor< rank_, dim, OtherNumber > &right)
constexpr void double_contract(SymmetricTensor< 2, 2, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 2, Number > &t, const SymmetricTensor< 2, 2, OtherNumber > &s)
static constexpr unsigned int component_to_unrolled_index(const TableIndices< rank_ > &indices)
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
constexpr Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator*(const Tensor< 1, dim, Number > &src1, const SymmetricTensor< 2, dim, OtherNumber > &src2)
std::array< Number, 2 > eigenvalues(const SymmetricTensor< 2, 2, Number > &T)
void serialize(Archive &ar, const unsigned int version)
constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const Tensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
constexpr Number trace(const SymmetricTensor< 2, dim2, Number > &)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
std::tuple< SymmetricTensor< 2, dim, Number >, SymmetricTensor< 2, dim, Number >, SymmetricTensor< 4, dim, Number >, SymmetricTensor< 4, dim, Number > > positive_negative_projectors(const SymmetricTensor< 2, dim, Number > &original_tensor)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)
constexpr internal::SymmetricTensorAccessors::Accessor< rank_, dim, false, rank_ - 1, Number > operator[](const unsigned int row)
typename base_tensor_descriptor::base_tensor_type base_tensor_type
constexpr const Number & operator()(const TableIndices< rank_ > &indices) const
constexpr SymmetricTensor< 4, dim, Number > deviator_tensor()
constexpr bool operator!=(const SymmetricTensor &) const
constexpr Number & operator[](const TableIndices< rank_ > &indices)
constexpr void double_contract(SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 2, 1, Number > &s, const SymmetricTensor< 4, 1, OtherNumber > &t)
constexpr SymmetricTensor< rank_, dim, typename ProductType< OtherNumber, typename EnableIfScalar< Number >::type >::type > operator*(const Number &factor, const SymmetricTensor< rank_, dim, OtherNumber > &t)
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()
constexpr ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const Tensor< 2, dim, OtherNumber > &t2)
constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const Tensor< rank_, dim, OtherNumber > &right)
constexpr const Number & operator[](const TableIndices< rank_ > &indices) const
constexpr SymmetricTensor & operator=(const Number &d)
SymmetricTensor(const Tensor< 2, dim, OtherNumber > &t)
static constexpr TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
constexpr SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
constexpr Number & access_raw_entry(const unsigned int unrolled_index)
constexpr numbers::NumberTraits< Number >::real_type norm() const
constexpr SymmetricTensor operator-() const
constexpr internal::SymmetricTensorAccessors::double_contraction_result< rank_, 2, dim, Number, OtherNumber >::type operator*(const SymmetricTensor< 2, dim, OtherNumber > &s) const
constexpr SymmetricTensor()=default
constexpr Number second_invariant(const SymmetricTensor< 2, 1, Number > &)
constexpr Number third_invariant(const SymmetricTensor< 2, dim, Number > &t)
constexpr SymmetricTensor(const SymmetricTensor< rank_, dim, OtherNumber > &initializer)
constexpr SymmetricTensor & operator-=(const SymmetricTensor< rank_, dim, OtherNumber > &)
constexpr SymmetricTensor< rank_, dim, Number > operator*(const Number &factor, const SymmetricTensor< rank_, dim, Number > &t)
constexpr Tensor< rank_1+rank_2-2, dim, typenameProductType< Number, OtherNumber >::type >::tensor_type operator*(const Tensor< rank_1, dim, Number > &src1, const SymmetricTensor< rank_2, dim, OtherNumber > &src2)
constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)
constexpr Tensor< rank_1+rank_2-2, dim, typenameProductType< Number, OtherNumber >::type >::tensor_type operator*(const SymmetricTensor< rank_1, dim, Number > &src1, const Tensor< rank_2, dim, OtherNumber > &src2)
constexpr ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
constexpr SymmetricTensor< 4, dim, Number > identity_tensor()
constexpr void double_contract(SymmetricTensor< 2, 3, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 3, Number > &t, const SymmetricTensor< 2, 3, OtherNumber > &s)
constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
constexpr Number second_invariant(const SymmetricTensor< 2, 3, Number > &t)
constexpr SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
constexpr const Number & access_raw_entry(const unsigned int unrolled_index) const
constexpr SymmetricTensor & operator=(const SymmetricTensor< rank_, dim, OtherNumber > &rhs)
constexpr SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
constexpr SymmetricTensor< 4, dim, Number > symmetrize(const Tensor< 4, dim, Number > &t, const bool major_symmetry)
constexpr SymmetricTensor< rank_, dim > operator*(const double factor, const SymmetricTensor< rank_, dim > &t)
constexpr SymmetricTensor & operator/=(const OtherNumber &factor)
constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const Tensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
constexpr Number second_invariant(const SymmetricTensor< 2, 2, Number > &t)
constexpr SymmetricTensor & operator+=(const SymmetricTensor< rank_, dim, OtherNumber > &)
constexpr SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()
constexpr internal::SymmetricTensorAccessors::double_contraction_result< rank_, 4, dim, Number, OtherNumber >::type operator*(const SymmetricTensor< 4, dim, OtherNumber > &s) const
constexpr SymmetricTensor< rank_, dim > operator/(const SymmetricTensor< rank_, dim > &t, const double factor)
std::array< Number, 3 > eigenvalues(const SymmetricTensor< 2, 3, Number > &T)
constexpr internal::SymmetricTensorAccessors::Accessor< rank_, dim, true, rank_ - 1, Number > operator[](const unsigned int row) const
constexpr void double_contract(SymmetricTensor< 2, 3, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 2, 3, Number > &s, const SymmetricTensor< 4, 3, OtherNumber > &t)
constexpr SymmetricTensor & operator*=(const OtherNumber &factor)
constexpr Number & operator()(const TableIndices< rank_ > &indices)
typename AccessorTypes< rank, dim, constness, Number >::reference reference
constexpr reference operator[](const unsigned int) const
const TableIndices< rank > previous_indices
constexpr Accessor(tensor_type &tensor, const TableIndices< rank > &previous_indices)
constexpr reference operator[](const unsigned int)
typename AccessorTypes< rank, dim, constness, Number >::tensor_type tensor_type
DEAL_II_HOST constexpr Accessor(const Accessor &)=default
const TableIndices< rank > previous_indices
typename AccessorTypes< rank, dim, constness, Number >::tensor_type tensor_type
constexpr Accessor< rank, dim, constness, P - 1, Number > operator[](const unsigned int i)
constexpr Accessor(tensor_type &tensor, const TableIndices< rank > &previous_indices)
typename AccessorTypes< rank, dim, constness, Number >::reference reference
constexpr Accessor< rank, dim, constness, P - 1, Number > operator[](const unsigned int i) const
DEAL_II_HOST constexpr Accessor(const Accessor &)=default
#define DEAL_II_ALWAYS_INLINE
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_HOST_DEVICE
#define DEAL_II_CONSTEXPR
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcIndexRange(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< index_type > data
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
* * * RotationFunction< dim, Number >::RotationFunction Number(dim)
* * * * std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters const
T sum(const T &t, const MPI_Comm mpi_communicator)
constexpr TableIndices< 2 > merge(const TableIndices< 2 > &previous_indices, const unsigned int new_index, const unsigned int position)
void tridiagonalize(const ::SymmetricTensor< 2, dim, Number > &A, ::Tensor< 2, dim, Number > &Q, std::array< Number, dim > &d, std::array< Number, dim - 1 > &e)
constexpr unsigned int invalid_unsigned_int
constexpr bool value_is_zero(const Number &value)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
typename internal::ProductTypeImpl< std::decay_t< T >, std::decay_t< U > >::type type
static constexpr const T & value(const T &t)
typename ProductType< Number, OtherNumber >::type type
typename ProductType< Number, OtherNumber >::type value_type
std::pair< Number, Tensor< 1, dim, Number > > EigValsVecs
bool operator()(const EigValsVecs &lhs, const EigValsVecs &rhs)
static real_type abs(const number &x)
constexpr SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
constexpr Number trace(const SymmetricTensor< 2, dim2, Number > &)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)
constexpr SymmetricTensor< 4, dim, Number > deviator_tensor()
constexpr SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
constexpr SymmetricTensor< 4, dim, Number > identity_tensor()
SymmetricTensorEigenvectorMethod
constexpr SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()