16#ifndef dealii_symmetric_tensor_h
17#define dealii_symmetric_tensor_h
33template <
int rank,
int dim,
typename Number =
double>
47template <
int dim,
typename Number =
double>
80template <
int dim,
typename Number =
double>
122template <
int dim,
typename Number =
double>
127template <
int dim,
typename Number>
131template <
int dim,
typename Number>
144template <
int dim2,
typename Number>
158template <
int dim,
typename Number>
176template <
int dim,
typename Number>
188 template <
int rank,
int dim,
typename T,
typename U>
194 std::complex<typename ProductType<T, U>::type>>;
197 template <
int rank,
int dim,
typename T,
typename U>
204 std::complex<typename ProductType<T, U>::type>>;
207 template <
typename T,
int rank,
int dim,
typename U>
213 std::complex<typename ProductType<T, U>::type>>;
216 template <
int rank,
int dim,
typename T,
typename U>
223 std::complex<typename ProductType<T, U>::type>>;
231 namespace SymmetricTensorImplementation
237 template <
int rank,
int dim,
typename Number>
245 namespace SymmetricTensorAccessors
257 const unsigned int position)
279 const unsigned int position)
291 return {previous_indices[0],
296 return {previous_indices[0],
301 return {previous_indices[0],
337 template <
int dim,
typename Number,
typename OtherNumber>
357 template <
int rank,
int dim,
typename Number>
363 template <
int dim,
typename Number>
370 static const unsigned int n_independent_components =
371 (dim * dim + dim) / 2;
384 template <
int dim,
typename Number>
392 static const unsigned int n_rank2_components = (dim * dim + dim) / 2;
397 static const unsigned int n_independent_components =
398 (n_rank2_components *
416 template <
int rank,
int dim,
bool constness,
typename Number>
425 template <
int rank,
int dim,
typename Number>
439 template <
int rank,
int dim,
typename Number>
480 template <
int rank,
int dim,
bool constness,
int P,
typename Number>
546 template <
int,
int,
typename>
547 friend class ::SymmetricTensor;
548 template <
int,
int,
bool,
int,
typename>
550 friend class ::SymmetricTensor<rank, dim, Number>;
563 template <
int rank,
int dim,
bool constness,
typename Number>
632 template <
int,
int,
typename>
633 friend class ::SymmetricTensor;
634 template <
int,
int,
bool,
int,
typename>
636 friend class ::SymmetricTensor<rank, dim, Number>;
637 friend class SymmetricTensorAccessors::
638 Accessor<rank, dim, constness, 2, Number>;
717template <int rank_, int dim, typename Number>
721 static_assert(
rank_ % 2 == 0,
"A SymmetricTensor must have even rank!");
731 static constexpr unsigned int dimension = dim;
736 static const unsigned int rank =
rank_;
743 static constexpr unsigned int n_independent_components =
767 template <
typename OtherNumber>
793 template <
typename OtherNumber>
852 template <
typename OtherNumber>
890 template <
typename OtherNumber>
897 template <
typename OtherNumber>
905 template <
typename OtherNumber>
912 template <
typename OtherNumber>
975 template <
typename OtherNumber>
977 double_contraction_result<rank_, 2, dim, Number, OtherNumber>::type
984 template <
typename OtherNumber>
986 double_contraction_result<rank_, 4, dim, Number, OtherNumber>::type
1000 constexpr const Number &
1008 constexpr internal::SymmetricTensorAccessors::
1009 Accessor<
rank_, dim,
true,
rank_ - 1, Number>
1017 constexpr internal::SymmetricTensorAccessors::
1018 Accessor<
rank_, dim,
false,
rank_ - 1, Number>
1027 constexpr const Number &
1046 constexpr const Number &
1118 template <
class Archive>
1142 template <
int,
int,
typename>
1146 template <
int dim2,
typename Number2>
1150 template <
int dim2,
typename Number2>
1154 template <
int dim2,
typename Number2>
1158 template <
int dim2,
typename Number2>
1162 template <
int dim2,
typename Number2>
1166 template <
int dim2,
typename Number2>
1173 Inverse<2, dim, Number>;
1176 Inverse<4, dim, Number>;
1187template <int rank, int dim, typename Number>
1190template <int rank_, int dim, typename Number>
1196 namespace SymmetricTensorAccessors
1198 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1200 Accessor<rank_, dim, constness, P, Number>::Accessor(
1201 tensor_type & tensor,
1204 , previous_indices(previous_indices)
1209 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1212 Accessor<rank_, dim, constness, P, Number>::operator[](
1213 const unsigned int i)
1216 tensor, merge(previous_indices, i,
rank_ - P));
1221 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
1224 Accessor<rank_, dim, constness, P, Number>::operator[](
1225 const unsigned int i)
const
1228 tensor,
merge(previous_indices, i,
rank_ - P));
1233 template <
int rank_,
int dim,
bool constness,
typename Number>
1235 Accessor<rank_, dim, constness, 1, Number>::Accessor(
1236 tensor_type & tensor,
1239 , previous_indices(previous_indices)
1244 template <
int rank_,
int dim,
bool constness,
typename Number>
1246 typename Accessor<rank_, dim, constness, 1, Number>::reference
1247 Accessor<rank_, dim, constness, 1, Number>::operator[](
1248 const unsigned int i)
1250 return tensor(
merge(previous_indices, i,
rank_ - 1));
1254 template <
int rank_,
int dim,
bool constness,
typename Number>
1256 typename Accessor<rank_, dim, constness, 1, Number>::reference
1257 Accessor<rank_, dim, constness, 1, Number>::operator[](
1258 const unsigned int i)
const
1260 return tensor(
merge(previous_indices, i,
rank_ - 1));
1267template <
int rank_,
int dim,
typename Number>
1268template <
typename OtherNumber>
1273 static_assert(rank == 2,
"This function is only implemented for rank==2");
1274 for (
unsigned int d = 0;
d < dim; ++
d)
1275 for (
unsigned int e = 0;
e <
d; ++
e)
1276 Assert(t[d][e] == t[e][d],
1277 ExcMessage(
"The incoming Tensor must be exactly symmetric."));
1279 for (
unsigned int d = 0;
d < dim; ++
d)
1282 for (
unsigned int d = 0, c = 0;
d < dim; ++
d)
1283 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1284 data[dim + c] = t[d][e];
1289template <
int rank_,
int dim,
typename Number>
1290template <
typename OtherNumber>
1299template <
int rank_,
int dim,
typename Number>
1302 const Number (&array)[n_independent_components])
1307 Assert(
sizeof(
typename base_tensor_type::array_type) ==
sizeof(array),
1313template <
int rank_,
int dim,
typename Number>
1314template <
typename OtherNumber>
1326template <
int rank_,
int dim,
typename Number>
1332 ExcMessage(
"Only assignment with zero is allowed"));
1343 namespace SymmetricTensorImplementation
1345 template <
int dim,
typename Number>
1346 constexpr inline DEAL_II_ALWAYS_INLINE ::Tensor<2, dim, Number>
1352 for (
unsigned int d = 0;
d < dim; ++
d)
1353 t[d][d] = s.access_raw_entry(d);
1356 for (
unsigned int d = 0, c = 0;
d < dim; ++
d)
1357 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
1359 t[
d][
e] = s.access_raw_entry(dim + c);
1360 t[
e][
d] = s.access_raw_entry(dim + c);
1366 template <
int dim,
typename Number>
1375 for (
unsigned int i = 0; i < dim; ++i)
1376 for (
unsigned int j = i;
j < dim; ++
j)
1377 for (
unsigned int k = 0;
k < dim; ++
k)
1378 for (
unsigned int l =
k;
l < dim; ++
l)
1388 template <
typename Number>
1389 struct Inverse<2, 1, Number>
1397 tmp[0][0] = 1.0 / t[0][0];
1404 template <
typename Number>
1405 struct Inverse<2, 2, Number>
1431 template <
typename Number>
1432 struct Inverse<2, 3, Number>
1498 template <
typename Number>
1499 struct Inverse<4, 1, Number>
1505 tmp.
data[0][0] = 1.0 / t.data[0][0];
1511 template <
typename Number>
1512 struct Inverse<4, 2, Number>
1541 const Number
t4 = t.
data[0][0] * t.data[1][1],
1542 t6 = t.
data[0][0] * t.data[1][2],
1543 t8 = t.
data[0][1] * t.data[1][0],
1544 t00 = t.
data[0][2] * t.data[1][0],
1545 t01 = t.
data[0][1] * t.data[2][0],
1546 t04 = t.
data[0][2] * t.data[2][0],
1551 (t.data[1][1] * t.data[2][2] - t.data[1][2] * t.data[2][1]) *
t07;
1553 -(t.data[0][1] * t.data[2][2] - t.data[0][2] * t.data[2][1]) *
t07;
1555 -(-t.data[0][1] * t.data[1][2] + t.data[0][2] * t.data[1][1]) *
t07;
1557 -(t.data[1][0] * t.data[2][2] - t.data[1][2] * t.data[2][0]) *
t07;
1558 tmp.
data[1][1] = (t.data[0][0] * t.data[2][2] -
t04) *
t07;
1561 -(-t.data[1][0] * t.data[2][1] + t.data[1][1] * t.data[2][0]) *
t07;
1562 tmp.
data[2][1] = -(t.data[0][0] * t.data[2][1] -
t01) *
t07;
1567 tmp.
data[2][0] /= 2;
1568 tmp.
data[2][1] /= 2;
1569 tmp.
data[0][2] /= 2;
1570 tmp.
data[1][2] /= 2;
1571 tmp.
data[2][2] /= 4;
1578 template <
typename Number>
1579 struct Inverse<4, 3, Number>
1592 const unsigned int N = 6;
1598 for (
unsigned int i = 0; i < N; ++i)
1605 for (
unsigned int i = 0; i < N; ++i)
1608 for (
unsigned int j = 0;
j < N; ++
j)
1614 for (
unsigned int i =
j + 1; i < N; ++i)
1623 ExcMessage(
"This tensor seems to be noninvertible"));
1628 for (
unsigned int k = 0;
k < N; ++
k)
1631 std::swap(p[
j], p[r]);
1635 const Number
hr = 1. / tmp.
data[
j][
j];
1637 for (
unsigned int k = 0;
k < N; ++
k)
1641 for (
unsigned int i = 0; i < N; ++i)
1648 for (
unsigned int i = 0; i < N; ++i)
1658 for (
unsigned int i = 0; i < N; ++i)
1660 for (
unsigned int k = 0;
k < N; ++
k)
1662 for (
unsigned int k = 0;
k < N; ++
k)
1668 for (
unsigned int i = 3; i < 6; ++i)
1669 for (
unsigned int j = 0;
j < 3; ++
j)
1670 tmp.
data[i][
j] /= 2;
1672 for (
unsigned int i = 0; i < 3; ++i)
1673 for (
unsigned int j = 3;
j < 6; ++
j)
1674 tmp.
data[i][
j] /= 2;
1676 for (
unsigned int i = 3; i < 6; ++i)
1677 for (
unsigned int j = 3;
j < 6; ++
j)
1678 tmp.
data[i][
j] /= 4;
1689template <
int rank_,
int dim,
typename Number>
1694 return internal::SymmetricTensorImplementation::convert_to_tensor(*
this);
1699template <
int rank_,
int dim,
typename Number>
1709template <
int rank_,
int dim,
typename Number>
1719template <
int rank_,
int dim,
typename Number>
1720template <
typename OtherNumber>
1732template <
int rank_,
int dim,
typename Number>
1733template <
typename OtherNumber>
1745template <
int rank_,
int dim,
typename Number>
1746template <
typename OtherNumber>
1757template <
int rank_,
int dim,
typename Number>
1758template <
typename OtherNumber>
1769template <
int rank_,
int dim,
typename Number>
1781template <
int rank_,
int dim,
typename Number>
1790template <
int rank_,
int dim,
typename Number>
1803 template <
int dim,
typename Number,
typename OtherNumber = Number>
1805 typename SymmetricTensorAccessors::
1806 double_contraction_result<2, 2, dim, Number, OtherNumber>::type
1808 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1809 base_tensor_type &data,
1813 using result_type =
typename SymmetricTensorAccessors::
1814 double_contraction_result<2, 2, dim, Number, OtherNumber>::type;
1819 return data[0] *
sdata[0];
1824 result_type
sum = data[dim] *
sdata[dim];
1825 for (
unsigned int d = dim + 1;
d < (dim * (dim + 1) / 2); ++
d)
1826 sum += data[d] *
sdata[d];
1830 for (
unsigned int d = 0;
d < dim; ++
d)
1831 sum += data[d] *
sdata[d];
1838 template <
int dim,
typename Number,
typename OtherNumber = Number>
1840 typename SymmetricTensorAccessors::
1841 double_contraction_result<4, 2, dim, Number, OtherNumber>::type
1843 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1844 base_tensor_type &data,
1848 using result_type =
typename SymmetricTensorAccessors::
1849 double_contraction_result<4, 2, dim, Number, OtherNumber>::type;
1850 using value_type =
typename SymmetricTensorAccessors::
1851 double_contraction_result<4, 2, dim, Number, OtherNumber>::value_type;
1853 const unsigned int data_dim = SymmetricTensorAccessors::
1854 StorageType<2, dim, value_type>::n_independent_components;
1856 for (
unsigned int i = 0; i <
data_dim; ++i)
1859 return result_type(tmp);
1864 template <
int dim,
typename Number,
typename OtherNumber = Number>
1866 typename SymmetricTensorAccessors::StorageType<
1869 typename SymmetricTensorAccessors::
1870 double_contraction_result<2, 4, dim, Number, OtherNumber>::value_type>
::
1873 const typename SymmetricTensorAccessors::StorageType<2, dim, Number>::
1874 base_tensor_type &data,
1878 using value_type =
typename SymmetricTensorAccessors::
1879 double_contraction_result<2, 4, dim, Number, OtherNumber>::value_type;
1880 using base_tensor_type =
typename SymmetricTensorAccessors::
1881 StorageType<2, dim, value_type>::base_tensor_type;
1883 base_tensor_type tmp;
1884 for (
unsigned int i = 0; i < tmp.dimension; ++i)
1887 value_type
sum = data[dim] *
sdata[dim][i];
1888 for (
unsigned int d = dim + 1;
d < (dim * (dim + 1) / 2); ++
d)
1889 sum += data[d] *
sdata[d][i];
1893 for (
unsigned int d = 0;
d < dim; ++
d)
1894 sum += data[d] *
sdata[d][i];
1902 template <
int dim,
typename Number,
typename OtherNumber = Number>
1904 typename SymmetricTensorAccessors::StorageType<
1907 typename SymmetricTensorAccessors::
1908 double_contraction_result<4, 4, dim, Number, OtherNumber>::value_type>
::
1911 const typename SymmetricTensorAccessors::StorageType<4, dim, Number>::
1912 base_tensor_type &data,
1916 using value_type =
typename SymmetricTensorAccessors::
1917 double_contraction_result<4, 4, dim, Number, OtherNumber>::value_type;
1918 using base_tensor_type =
typename SymmetricTensorAccessors::
1919 StorageType<4, dim, value_type>::base_tensor_type;
1921 const unsigned int data_dim = SymmetricTensorAccessors::
1922 StorageType<2, dim, value_type>::n_independent_components;
1923 base_tensor_type tmp;
1924 for (
unsigned int i = 0; i <
data_dim; ++i)
1928 for (
unsigned int d = dim;
d < (dim * (dim + 1) / 2); ++
d)
1929 tmp[i][
j] += data[i][d] *
sdata[d][
j];
1930 tmp[i][
j] += tmp[i][
j];
1933 for (
unsigned int d = 0;
d < dim; ++
d)
1934 tmp[i][
j] += data[i][d] *
sdata[d][
j];
1943template <
int rank_,
int dim,
typename Number>
1944template <
typename OtherNumber>
1946 typename internal::SymmetricTensorAccessors::
1947 double_contraction_result<rank_, 2, dim, Number, OtherNumber>::type
1955 return internal::perform_double_contraction<dim, Number, OtherNumber>(
data,
1961template <
int rank_,
int dim,
typename Number>
1962template <
typename OtherNumber>
1964 typename internal::SymmetricTensorAccessors::
1965 double_contraction_result<rank_, 4, dim, Number, OtherNumber>::type
1969 typename internal::SymmetricTensorAccessors::
1970 double_contraction_result<rank_, 4, dim, Number, OtherNumber>::type tmp;
1972 internal::perform_double_contraction<dim, Number, OtherNumber>(
data,
1989 template <
int dim,
typename Number>
1992 typename SymmetricTensorAccessors::
1993 StorageType<2, dim, Number>::base_tensor_type &data)
2001 if (indices[0] == indices[1])
2002 return data[indices[0]];
2009 Assert(((indices[0] == 1) && (indices[1] == 0)) ||
2010 ((indices[0] == 0) && (indices[1] == 1)),
2019 for (
unsigned int d = 0, c = 0;
d < dim; ++
d)
2020 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2022 return data[dim + c];
2036 template <
int dim,
typename Number>
2039 const typename SymmetricTensorAccessors::
2040 StorageType<2, dim, Number>::base_tensor_type &data)
2048 if (indices[0] == indices[1])
2049 return data[indices[0]];
2056 Assert(((indices[0] == 1) && (indices[1] == 0)) ||
2057 ((indices[0] == 0) && (indices[1] == 1)),
2066 for (
unsigned int d = 0, c = 0;
d < dim; ++
d)
2067 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2069 return data[dim + c];
2083 template <
int dim,
typename Number>
2084 constexpr inline Number &
2086 typename SymmetricTensorAccessors::
2087 StorageType<4, dim, Number>::base_tensor_type &data)
2101 constexpr std::size_t
base_index[2][2] = {{0, 2}, {2, 1}};
2102 return data[
base_index[indices[0]][indices[1]]]
2112 constexpr std::size_t
base_index[3][3] = {{0, 3, 4},
2115 return data[
base_index[indices[0]][indices[1]]]
2131 template <
int dim,
typename Number>
2134 const typename SymmetricTensorAccessors::
2135 StorageType<4, dim, Number>::base_tensor_type &data)
2149 constexpr std::size_t
base_index[2][2] = {{0, 2}, {2, 1}};
2150 return data[
base_index[indices[0]][indices[1]]]
2160 constexpr std::size_t
base_index[3][3] = {{0, 3, 4},
2163 return data[
base_index[indices[0]][indices[1]]]
2182template <
int rank_,
int dim,
typename Number>
2187 for (
unsigned int r = 0; r < rank; ++r)
2189 return internal::symmetric_tensor_access<dim, Number>(indices,
data);
2194template <
int rank_,
int dim,
typename Number>
2199 for (
unsigned int r = 0; r < rank; ++r)
2201 return internal::symmetric_tensor_access<dim, Number>(indices,
data);
2208 namespace SymmetricTensorImplementation
2210 template <
int rank_>
2213 const std::integral_constant<int, 2> &)
2219 template <
int rank_>
2222 const std::integral_constant<int, 4> &)
2233template <
int rank_,
int dim,
typename Number>
2235 SymmetricTensorAccessors::Accessor<
rank_, dim,
true,
rank_ - 1, Number>
2238 return internal::SymmetricTensorAccessors::
2239 Accessor<
rank_, dim,
true,
rank_ - 1, Number>(
2241 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2242 rank_>(row, std::integral_constant<int, rank_>()));
2247template <
int rank_,
int dim,
typename Number>
2249 SymmetricTensorAccessors::Accessor<
rank_, dim,
false,
rank_ - 1, Number>
2252 return internal::SymmetricTensorAccessors::
2253 Accessor<
rank_, dim,
false,
rank_ - 1, Number>(
2255 internal::SymmetricTensorImplementation::get_partially_filled_indices<
2256 rank_>(row, std::integral_constant<int, rank_>()));
2261template <
int rank_,
int dim,
typename Number>
2266 return operator()(indices);
2271template <
int rank_,
int dim,
typename Number>
2276 return operator()(indices);
2281template <
int rank_,
int dim,
typename Number>
2285 return std::addressof(this->access_raw_entry(0));
2290template <
int rank_,
int dim,
typename Number>
2291inline const Number *
2294 return std::addressof(this->access_raw_entry(0));
2299template <
int rank_,
int dim,
typename Number>
2303 return begin_raw() + n_independent_components;
2308template <
int rank_,
int dim,
typename Number>
2309inline const Number *
2312 return begin_raw() + n_independent_components;
2319 namespace SymmetricTensorImplementation
2321 template <
int dim,
typename Number>
2322 constexpr unsigned int
2324 const unsigned int index)
2330 template <
int dim,
typename Number>
2333 const unsigned int index)
2344template <
int rank_,
int dim,
typename Number>
2347 const unsigned int index)
const
2350 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this,
2356template <
int rank_,
int dim,
typename Number>
2361 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this,
2369 template <
int dim,
typename Number>
2372 StorageType<2, dim, Number>::base_tensor_type &data)
2399 for (
unsigned int d = 0;
d < dim; ++
d)
2402 for (
unsigned int d = dim;
d < (dim * dim + dim) / 2; ++
d)
2406 return sqrt(return_value);
2413 template <
int dim,
typename Number>
2416 StorageType<4, dim, Number>::base_tensor_type &data)
2430 const unsigned int n_independent_components = data.dimension;
2432 for (
unsigned int i = 0; i < dim; ++i)
2433 for (
unsigned int j = 0;
j < dim; ++
j)
2436 for (
unsigned int i = 0; i < dim; ++i)
2437 for (
unsigned int j = dim;
j < n_independent_components; ++
j)
2440 for (
unsigned int i = dim; i < n_independent_components; ++i)
2441 for (
unsigned int j = 0;
j < dim; ++
j)
2444 for (
unsigned int i = dim; i < n_independent_components; ++i)
2445 for (
unsigned int j = dim;
j < n_independent_components; ++
j)
2449 return sqrt(return_value);
2458template <
int rank_,
int dim,
typename Number>
2462 return internal::compute_norm<dim, Number>(
data);
2469 namespace SymmetricTensorImplementation
2492 constexpr unsigned int table[2][2] = {{0, 2}, {2, 1}};
2493 return table[indices[0]][indices[1]];
2498 constexpr unsigned int table[3][3] = {{0, 3, 4},
2501 return table[indices[0]][indices[1]];
2506 constexpr unsigned int table[4][4] = {{0, 4, 5, 6},
2510 return table[indices[0]][indices[1]];
2516 if (indices[0] == indices[1])
2522 for (
unsigned int d = 0, c = 0;
d < dim; ++
d)
2523 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2540 template <
int dim,
int rank_>
2541 constexpr inline unsigned int
2552template <
int rank_,
int dim,
typename Number>
2557 return internal::SymmetricTensorImplementation::component_to_unrolled_index<
2565 namespace SymmetricTensorImplementation
2577 const std::integral_constant<int, 2> &)
2615 for (
unsigned int d = 0, c = dim;
d < dim; ++
d)
2616 for (
unsigned int e = d + 1;
e < dim; ++
e, ++c)
2634 template <
int dim,
int rank_>
2635 constexpr inline std::enable_if_t<rank_ != 2, TableIndices<rank_>>
2637 const std::integral_constant<int, rank_> &)
2646 n_independent_components));
2654template <
int rank_,
int dim,
typename Number>
2657 const unsigned int i)
2659 return internal::SymmetricTensorImplementation::unrolled_to_component_indices<
2660 dim>(i, std::integral_constant<int, rank_>());
2665template <
int rank_,
int dim,
typename Number>
2666template <
class Archive>
2691template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2716template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2736template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2753template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2770template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2787template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2798template <
int dim,
typename Number>
2814 return (tmp + tmp + t.
data[0] * t.
data[1] * t.
data[2] -
2838template <
int dim,
typename Number>
2847template <
int dim,
typename Number>
2851 Number t = d.
data[0];
2852 for (
unsigned int i = 1; i < dim; ++i)
2869template <
int dim,
typename Number>
2888template <
typename Number>
2915template <
typename Number>
2919 return t[0][0] * t[1][1] - t[0][1] * t[0][1];
2932template <
typename Number>
2936 return (t[0][0] * t[1][1] + t[1][1] * t[2][2] + t[2][2] * t[0][0] -
2937 t[0][1] * t[0][1] - t[0][2] * t[0][2] - t[1][2] * t[1][2]);
2949template <
typename Number>
2950std::array<Number, 1>
2977template <
typename Number>
2978std::array<Number, 2>
3005template <
typename Number>
3006std::array<Number, 3>
3013 namespace SymmetricTensorImplementation
3052 template <
int dim,
typename Number>
3056 std::array<Number, dim> & d,
3057 std::array<Number, dim - 1> & e);
3100 template <
int dim,
typename Number>
3101 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3145 template <
int dim,
typename Number>
3146 std::array<std::pair<Number, Tensor<1, dim, Number>>, dim>
3164 template <
typename Number>
3165 std::array<std::pair<Number, Tensor<1, 2, Number>>, 2>
3202 template <
typename Number>
3203 std::array<std::pair<Number, Tensor<1, 3, Number>>, 3>
3210 template <
int dim,
typename Number>
3217 return lhs.first >
rhs.first;
3320template <
int dim,
typename Number>
3321std::array<std::pair<Number, Tensor<1, dim, Number>>,
3322 std::integral_constant<int, dim>::value>
3337template <
int rank_,
int dim,
typename Number>
3346template <
int dim,
typename Number>
3355 for (
unsigned int i = 0; i < dim; ++i)
3363template <
int dim,
typename Number>
3384 for (
unsigned int d = 0; d < dim; ++d)
3392template <
int dim,
typename Number>
3399 for (
unsigned int i = 0; i < dim; ++i)
3400 for (
unsigned int j = 0;
j < dim; ++
j)
3409 for (
unsigned int i = dim;
3420template <
int dim,
typename Number>
3428 for (
unsigned int i = 0; i < dim; ++i)
3436 for (
unsigned int i = dim;
3456template <
int dim,
typename Number>
3476template <
int dim,
typename Number>
3507template <
int dim,
typename Number>
3515 for (
unsigned int i = 0; i < dim; ++i)
3516 for (
unsigned int j = i;
j < dim; ++
j)
3517 for (
unsigned int k = 0;
k < dim; ++
k)
3518 for (
unsigned int l =
k; l < dim; ++l)
3519 tmp[i][
j][
k][l] =
t1[i][
j] *
t2[
k][l];
3533template <
int dim,
typename Number>
3539 for (
unsigned int d = 0; d < dim; ++d)
3543 for (
unsigned int d = 0; d < dim; ++d)
3544 for (
unsigned int e = d + 1; e < dim; ++e)
3558template <
int rank_,
int dim,
typename Number>
3577template <
int rank_,
int dim,
typename Number>
3611template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3640template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3650 return (t * factor);
3660template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3683template <
int rank_,
int dim>
3700template <
int rank_,
int dim>
3716template <
int rank_,
int dim>
3734template <
int dim,
typename Number,
typename OtherNumber>
3756template <
int dim,
typename Number,
typename OtherNumber>
3764 for (
unsigned int i = 0; i < dim; ++i)
3765 for (
unsigned int j = 0;
j < dim; ++
j)
3766 s +=
t1[i][
j] *
t2[i][
j];
3783template <
int dim,
typename Number,
typename OtherNumber>
3789 return scalar_product(
t2,
t1);
3807template <
typename Number,
typename OtherNumber>
3814 tmp[0][0] = t[0][0][0][0] * s[0][0];
3833template <
typename Number,
typename OtherNumber>
3840 tmp[0][0] = t[0][0][0][0] * s[0][0];
3859template <
typename Number,
typename OtherNumber>
3866 const unsigned int dim = 2;
3868 for (
unsigned int i = 0; i < dim; ++i)
3869 for (
unsigned int j = i;
j < dim; ++
j)
3870 tmp[i][
j] = t[i][
j][0][0] * s[0][0] + t[i][
j][1][1] * s[1][1] +
3871 2 * t[i][
j][0][1] * s[0][1];
3890template <
typename Number,
typename OtherNumber>
3897 const unsigned int dim = 2;
3899 for (
unsigned int i = 0; i < dim; ++i)
3900 for (
unsigned int j = i;
j < dim; ++
j)
3901 tmp[i][
j] = s[0][0] * t[0][0][i][
j] * +s[1][1] * t[1][1][i][
j] +
3902 2 * s[0][1] * t[0][1][i][
j];
3921template <
typename Number,
typename OtherNumber>
3928 const unsigned int dim = 3;
3930 for (
unsigned int i = 0; i < dim; ++i)
3931 for (
unsigned int j = i;
j < dim; ++
j)
3932 tmp[i][
j] = t[i][
j][0][0] * s[0][0] + t[i][
j][1][1] * s[1][1] +
3933 t[i][
j][2][2] * s[2][2] + 2 * t[i][
j][0][1] * s[0][1] +
3934 2 * t[i][
j][0][2] * s[0][2] + 2 * t[i][
j][1][2] * s[1][2];
3953template <
typename Number,
typename OtherNumber>
3960 const unsigned int dim = 3;
3962 for (
unsigned int i = 0; i < dim; ++i)
3963 for (
unsigned int j = i;
j < dim; ++
j)
3964 tmp[i][
j] = s[0][0] * t[0][0][i][
j] + s[1][1] * t[1][1][i][
j] +
3965 s[2][2] * t[2][2][i][
j] + 2 * s[0][1] * t[0][1][i][
j] +
3966 2 * s[0][2] * t[0][2][i][
j] + 2 * s[1][2] * t[1][2][i][
j];
3977template <
int dim,
typename Number,
typename OtherNumber>
3985 for (
unsigned int i = 0; i < dim; ++i)
3986 for (
unsigned int j = 0;
j < dim; ++
j)
3998template <
int dim,
typename Number,
typename OtherNumber>
4092template <
int dim,
typename Number>
4093inline std::ostream &
4101 for (
unsigned int i = 0; i < dim; ++i)
4102 for (
unsigned int j = 0;
j < dim; ++
j)
4119template <
int dim,
typename Number>
4120inline std::ostream &
4128 for (
unsigned int i = 0; i < dim; ++i)
4129 for (
unsigned int j = 0;
j < dim; ++
j)
4130 for (
unsigned int k = 0;
k < dim; ++
k)
4131 for (
unsigned int l = 0; l < dim; ++l)
4132 tt[i][
j][
k][l] = t[i][
j][
k][l];
value_type * data() const noexcept
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
DEAL_II_HOST constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, Number > transpose(const SymmetricTensor< rank_, dim, Number > &t)
DEAL_II_HOST constexpr internal::SymmetricTensorAccessors::Accessor< rank_, dim, false, rank_ - 1, Number > operator[](const unsigned int row)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/(const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
DEAL_II_HOST 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 DEAL_II_HOST constexpr std::size_t memory_consumption()
DEAL_II_HOST constexpr SymmetricTensor & operator/=(const OtherNumber &factor)
DEAL_II_HOST 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)
DEAL_II_HOST constexpr Number third_invariant(const SymmetricTensor< 2, dim, Number > &t)
DEAL_II_HOST constexpr Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator*(const SymmetricTensor< 2, dim, Number > &src1, const Tensor< 1, dim, OtherNumber > &src2)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, typename ProductType< OtherNumber, typename EnableIfScalar< Number >::type >::type > operator*(const Number &factor, const SymmetricTensor< rank_, dim, OtherNumber > &t)
DEAL_II_HOST constexpr Number & operator[](const TableIndices< rank_ > &indices)
std::array< Number, 2 > eigenvalues(const SymmetricTensor< 2, 2, Number > &T)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
void serialize(Archive &ar, const unsigned int version)
const Number * begin_raw() const
const Number * end_raw() const
DEAL_II_HOST constexpr Number first_invariant(const SymmetricTensor< 2, dim, Number > &t)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)
DEAL_II_HOST constexpr const Number & operator()(const TableIndices< rank_ > &indices) const
typename base_tensor_descriptor::base_tensor_type base_tensor_type
DEAL_II_HOST constexpr SymmetricTensor(const SymmetricTensor< rank_, dim, OtherNumber > &initializer)
DEAL_II_HOST constexpr ProductType< Number, OtherNumber >::type scalar_product(const Tensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
DEAL_II_HOST constexpr SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim > operator/(const SymmetricTensor< rank_, dim > &t, const double factor)
DEAL_II_HOST constexpr bool operator==(const SymmetricTensor &) const
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
DEAL_II_HOST constexpr const Number & access_raw_entry(const unsigned int unrolled_index) const
DEAL_II_HOST constexpr Number & operator()(const TableIndices< rank_ > &indices)
DEAL_II_HOST constexpr SymmetricTensor & operator*=(const OtherNumber &factor)
DEAL_II_HOST constexpr ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
DEAL_II_HOST constexpr SymmetricTensor(const Number(&array)[n_independent_components])
DEAL_II_HOST constexpr bool operator!=(const SymmetricTensor &) const
DEAL_II_HOST constexpr SymmetricTensor & operator=(const Number &d)
DEAL_II_HOST constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const Tensor< rank_, dim, OtherNumber > &right)
DEAL_II_HOST constexpr SymmetricTensor operator-() const
DEAL_II_HOST constexpr ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const Tensor< 2, dim, OtherNumber > &t2)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
DEAL_II_HOST constexpr Number & access_raw_entry(const unsigned int unrolled_index)
DEAL_II_HOST constexpr Tensor< 1, dim, typename ProductType< Number, OtherNumber >::type > operator*(const Tensor< 1, dim, Number > &src1, const SymmetricTensor< 2, dim, OtherNumber > &src2)
DEAL_II_HOST constexpr Number trace(const SymmetricTensor< 2, dim2, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim > operator*(const SymmetricTensor< rank_, dim > &t, const double factor)
SymmetricTensor(const Tensor< 2, dim, OtherNumber > &t)
DEAL_II_HOST 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)
DEAL_II_HOST 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)
DEAL_II_HOST constexpr internal::SymmetricTensorAccessors::double_contraction_result< rank_, 2, dim, Number, OtherNumber >::type operator*(const SymmetricTensor< 2, dim, OtherNumber > &s) const
static DEAL_II_HOST constexpr unsigned int component_to_unrolled_index(const TableIndices< rank_ > &indices)
DEAL_II_HOST 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)
DEAL_II_HOST constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const Tensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
DEAL_II_HOST 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)
static DEAL_II_HOST constexpr TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
DEAL_II_HOST constexpr SymmetricTensor< 4, dim, Number > deviator_tensor()
DEAL_II_HOST constexpr SymmetricTensor & operator-=(const SymmetricTensor< rank_, dim, OtherNumber > &)
DEAL_II_HOST 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)
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)
DEAL_II_HOST constexpr void clear()
DEAL_II_HOST constexpr SymmetricTensor< 4, dim, Number > identity_tensor()
DEAL_II_HOST constexpr SymmetricTensor< 4, dim, Number > invert(const SymmetricTensor< 4, dim, Number > &t)
DEAL_II_HOST 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)
DEAL_II_HOST constexpr Number second_invariant(const SymmetricTensor< 2, 2, Number > &t)
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim, Number > operator*(const Number &factor, const SymmetricTensor< rank_, dim, Number > &t)
DEAL_II_HOST constexpr numbers::NumberTraits< Number >::real_type norm() const
DEAL_II_HOST constexpr internal::SymmetricTensorAccessors::double_contraction_result< rank_, 4, dim, Number, OtherNumber >::type operator*(const SymmetricTensor< 4, dim, OtherNumber > &s) const
DEAL_II_HOST constexpr SymmetricTensor & operator=(const SymmetricTensor< rank_, dim, OtherNumber > &rhs)
DEAL_II_HOST constexpr SymmetricTensor()=default
DEAL_II_HOST constexpr Number second_invariant(const SymmetricTensor< 2, 3, Number > &t)
DEAL_II_HOST constexpr Number second_invariant(const SymmetricTensor< 2, 1, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &)
DEAL_II_HOST constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const Tensor< rank_, dim, OtherNumber > &right)
DEAL_II_HOST constexpr SymmetricTensor & operator+=(const SymmetricTensor< rank_, dim, OtherNumber > &)
DEAL_II_HOST constexpr const Number & operator[](const TableIndices< rank_ > &indices) const
DEAL_II_HOST constexpr Tensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const Tensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()
DEAL_II_HOST constexpr SymmetricTensor< rank_, dim > operator*(const double factor, const SymmetricTensor< rank_, dim > &t)
std::array< Number, 3 > eigenvalues(const SymmetricTensor< 2, 3, Number > &T)
DEAL_II_HOST constexpr internal::SymmetricTensorAccessors::Accessor< rank_, dim, true, rank_ - 1, Number > operator[](const unsigned int row) const
typename AccessorTypes< rank, dim, constness, Number >::reference reference
const TableIndices< rank > previous_indices
typename AccessorTypes< rank, dim, constness, Number >::tensor_type tensor_type
DEAL_II_HOST constexpr Accessor(tensor_type &tensor, const TableIndices< rank > &previous_indices)
DEAL_II_HOST constexpr reference operator[](const unsigned int)
DEAL_II_HOST constexpr reference operator[](const unsigned int) const
DEAL_II_HOST constexpr Accessor(const Accessor &)=default
DEAL_II_HOST constexpr Accessor< rank, dim, constness, P - 1, Number > operator[](const unsigned int i) const
const TableIndices< rank > previous_indices
typename AccessorTypes< rank, dim, constness, Number >::tensor_type tensor_type
DEAL_II_HOST constexpr Accessor(tensor_type &tensor, const TableIndices< rank > &previous_indices)
DEAL_II_HOST constexpr Accessor< rank, dim, constness, P - 1, Number > operator[](const unsigned int i)
typename AccessorTypes< rank, dim, constness, Number >::reference reference
DEAL_II_HOST constexpr Accessor(const Accessor &)=default
#define DEAL_II_ALWAYS_INLINE
#define DEAL_II_DEPRECATED
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_CONSTEXPR
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcIndexRange(std::size_t arg1, std::size_t arg2, std::size_t arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
LogStream & operator<<(LogStream &log, const T &t)
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)
T sum(const T &t, const MPI_Comm mpi_communicator)
DEAL_II_HOST 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 bool value_is_zero(const Number &value)
static const unsigned int invalid_unsigned_int
::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< typename std::decay< T >::type, typename std::decay< U >::type >::type type
static constexpr DEAL_II_HOST_DEVICE_ALWAYS_INLINE 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)
DEAL_II_HOST constexpr Number determinant(const SymmetricTensor< 2, dim, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &)
DEAL_II_HOST constexpr Number trace(const SymmetricTensor< 2, dim2, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< 4, dim, Number > deviator_tensor()
DEAL_II_HOST constexpr SymmetricTensor< 4, dim, Number > identity_tensor()
SymmetricTensorEigenvectorMethod
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &)
DEAL_II_HOST constexpr SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()