16 #ifndef dealii_symmetric_tensor_h 17 #define dealii_symmetric_tensor_h 20 #include <deal.II/base/tensor.h> 21 #include <deal.II/base/numbers.h> 22 #include <deal.II/base/table_indices.h> 23 #include <deal.II/base/template_constraints.h> 29 DEAL_II_NAMESPACE_OPEN
31 template <
int rank,
int dim,
typename Number=
double>
class SymmetricTensor;
33 template <
int dim,
typename Number>
36 template <
int dim,
typename Number>
39 template <
int dim,
typename Number>
42 template <
int dim,
typename Number>
45 template <
int dim,
typename Number>
48 template <
int dim2,
typename Number> Number
51 template <
int dim,
typename Number>
54 template <
int dim,
typename Number>
65 namespace SymmetricTensorImplementation
71 template <
int rank,
int dim,
typename Number>
79 namespace SymmetricTensorAccessors
89 const unsigned int new_index,
90 const unsigned int position)
110 const unsigned int new_index,
111 const unsigned int position)
151 template <
int rank1,
int rank2,
int dim,
typename Number,
typename OtherNumber = Number>
154 typedef typename ProductType<Number,OtherNumber>::type value_type;
155 typedef ::SymmetricTensor<rank1+rank2-4,dim,value_type>
type;
167 template <
int dim,
typename Number,
typename OtherNumber>
170 typedef typename ProductType<Number,OtherNumber>::type type;
187 template <
int rank,
int dim,
typename Number>
193 template <
int dim,
typename Number>
200 static const unsigned int 201 n_independent_components = (dim*dim + dim)/2;
214 template <
int dim,
typename Number>
222 static const unsigned int 223 n_rank2_components = (dim*dim + dim)/2;
228 static const unsigned int 229 n_independent_components = (n_rank2_components *
247 template <
int rank,
int dim,
bool constness,
typename Number>
256 template <
int rank,
int dim,
typename Number>
259 typedef const ::SymmetricTensor<rank,dim,Number>
tensor_type;
261 typedef Number reference;
270 template <
int rank,
int dim,
typename Number>
273 typedef ::SymmetricTensor<rank,dim,Number>
tensor_type;
275 typedef Number &reference;
313 template <
int rank,
int dim,
bool constness,
int P,
typename Number>
342 Accessor (tensor_type &tensor,
348 Accessor (
const Accessor &) =
default;
355 Accessor<rank,dim,constness,P-1,Number> operator [] (
const unsigned int i);
360 Accessor<rank,dim,constness,P-1,Number> operator [] (
const unsigned int i)
const;
373 template <
int,
int,
typename>
friend class ::SymmetricTensor;
374 template <
int,
int,
bool,
int,
typename>
375 friend class Accessor;
376 # ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG 377 friend class ::SymmetricTensor<rank,dim,Number>;
378 friend class Accessor<rank,dim,constness,P+1,Number>;
393 template <
int rank,
int dim,
bool constness,
typename Number>
394 class Accessor<rank,dim,constness,1,Number>
400 typedef typename AccessorTypes<rank,dim,constness,Number>::reference reference;
401 typedef typename AccessorTypes<rank,dim,constness,Number>::tensor_type tensor_type;
425 Accessor (tensor_type &tensor,
431 Accessor () =
delete;
436 Accessor (
const Accessor &) =
default;
443 reference operator [] (
const unsigned int);
448 reference operator [] (
const unsigned int)
const;
461 template <
int,
int,
typename>
friend class ::SymmetricTensor;
462 template <
int,
int,
bool,
int,
typename>
463 friend class SymmetricTensorAccessors::Accessor;
464 # ifndef DEAL_II_TEMPL_SPEC_FRIEND_BUG 465 friend class ::SymmetricTensor<rank,dim,Number>;
466 friend class SymmetricTensorAccessors::Accessor<rank,dim,constness,2,Number>;
537 template <
int rank_,
int dim,
typename Number>
541 static_assert(rank_%2==0,
"A SymmetricTensor must have even rank!");
556 static const unsigned int rank = rank_;
582 template <
typename OtherNumber>
608 template <
typename OtherNumber>
642 template <
typename OtherNumber>
672 template <
typename OtherNumber>
678 template <
typename OtherNumber>
685 template <
typename OtherNumber>
691 template <
typename OtherNumber>
723 template <
typename OtherNumber>
731 template <
typename OtherNumber>
749 internal::SymmetricTensorAccessors::Accessor<rank_,dim,
true,rank_-1,Number>
756 internal::SymmetricTensorAccessors::Accessor<rank_,dim,
false,rank_-1,Number>
847 template <
class Archive>
848 void serialize(Archive &ar,
const unsigned int version);
876 template <
int dim2,
typename Number2>
879 template <
int dim2,
typename Number2>
882 template <
int dim2,
typename Number2>
886 template <
int dim2,
typename Number2>
889 template <
int dim2,
typename Number2>
892 template <
int dim2,
typename Number2>
912 namespace SymmetricTensorAccessors
914 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
915 Accessor<rank_,dim,constness,P,Number>::
916 Accessor (tensor_type &tensor,
920 previous_indices (previous_indices)
925 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
926 Accessor<rank_,dim,constness,P-1,Number>
927 Accessor<rank_,dim,constness,P,Number>::operator[] (
const unsigned int i)
929 return Accessor<rank_,dim,constness,P-1,Number> (tensor,
930 merge (previous_indices, i, rank_-P));
935 template <
int rank_,
int dim,
bool constness,
int P,
typename Number>
936 Accessor<rank_,dim,constness,P-1,Number>
937 Accessor<rank_,dim,constness,P,Number>::operator[] (
const unsigned int i)
const 939 return Accessor<rank_,dim,constness,P-1,Number> (tensor,
940 merge (previous_indices, i, rank_-P));
945 template <
int rank_,
int dim,
bool constness,
typename Number>
946 Accessor<rank_,dim,constness,1,Number>::
947 Accessor (tensor_type &tensor,
951 previous_indices (previous_indices)
956 template <
int rank_,
int dim,
bool constness,
typename Number>
957 typename Accessor<rank_,dim,constness,1,Number>::reference
958 Accessor<rank_,dim,constness,1,Number>::operator[] (
const unsigned int i)
960 return tensor(
merge (previous_indices, i, rank_-1));
964 template <
int rank_,
int dim,
bool constness,
typename Number>
965 typename Accessor<rank_,dim,constness,1,Number>::reference
966 Accessor<rank_,dim,constness,1,Number>::operator[] (
const unsigned int i)
const 968 return tensor(
merge (previous_indices, i, rank_-1));
975 template <
int rank_,
int dim,
typename Number>
981 for (
unsigned int i=0; i<base_tensor_type::dimension; ++i)
986 template <
int rank_,
int dim,
typename Number>
987 template <
typename OtherNumber>
1016 for (
unsigned int d=0;
d<dim; ++
d)
1017 for (
unsigned int e=0;
e<
d; ++
e)
1020 for (
unsigned int d=0;
d<dim; ++
d)
1023 for (
unsigned int d=0, c=0;
d<dim; ++
d)
1024 for (
unsigned int e=d+1;
e<dim; ++
e, ++c)
1025 data[dim+c] = t[d][e];
1031 template <
int rank_,
int dim,
typename Number>
1032 template <
typename OtherNumber>
1037 for (
unsigned int i=0; i<base_tensor_type::dimension; ++i)
1044 template <
int rank_,
int dim,
typename Number>
1048 data (*reinterpret_cast<const typename base_tensor_type::array_type *>(array))
1051 Assert (
sizeof(
typename base_tensor_type::array_type)
1058 template <
int rank_,
int dim,
typename Number>
1059 template <
typename OtherNumber>
1064 for (
unsigned int i=0; i<base_tensor_type::dimension; ++i)
1065 data[i] = t.
data[i];
1071 template <
int rank_,
int dim,
typename Number>
1087 namespace SymmetricTensorImplementation
1089 template <
int dim,
typename Number>
1090 inline DEAL_II_ALWAYS_INLINE
1091 ::Tensor<2,dim,Number>
1092 convert_to_tensor (const ::SymmetricTensor<2,dim,Number> &s)
1097 for (
unsigned int d=0;
d<dim; ++
d)
1101 for (
unsigned int d=0, c=0;
d<dim; ++
d)
1102 for (
unsigned int e=d+1;
e<dim; ++
e, ++c)
1104 t[
d][
e] = s.access_raw_entry(dim+c);
1105 t[
e][
d] = s.access_raw_entry(dim+c);
1111 template <
int dim,
typename Number>
1113 convert_to_tensor (const ::SymmetricTensor<4,dim,Number> &st)
1120 for (
unsigned int i=0; i<dim; ++i)
1121 for (
unsigned int j=i; j<dim; ++j)
1122 for (
unsigned int k=0; k<dim; ++k)
1123 for (
unsigned int l=k;
l<dim; ++
l)
1134 template <
typename Number>
1135 struct Inverse<2,1,Number>
1137 static inline ::SymmetricTensor<2,1,Number>
1138 value (const ::SymmetricTensor<2,1,Number> &t)
1142 tmp[0][0] = 1.0/t[0][0];
1149 template <
typename Number>
1150 struct Inverse<2,2,Number>
1152 static inline ::SymmetricTensor<2,2,Number>
1153 value (const ::SymmetricTensor<2,2,Number> &t)
1163 const Number inv_det_t
1164 = 1.0/(t[idx_00]*t[idx_11]
1165 - t[idx_01]*t[idx_01]);
1166 tmp[idx_00] = t[idx_11];
1167 tmp[idx_01] = -t[idx_01];
1168 tmp[idx_11] = t[idx_00];
1176 template <
typename Number>
1177 struct Inverse<2,3,Number>
1179 static ::SymmetricTensor<2,3,Number>
1180 value (const ::SymmetricTensor<2,3,Number> &t)
1200 const Number inv_det_t
1201 = 1.0/(t[idx_00]*t[idx_11]*t[idx_22]
1202 - t[idx_00]*t[idx_12]*t[idx_12]
1203 - t[idx_01]*t[idx_01]*t[idx_22]
1204 + 2.0*t[idx_01]*t[idx_02]*t[idx_12]
1205 - t[idx_02]*t[idx_02]*t[idx_11]);
1206 tmp[idx_00] = t[idx_11]*t[idx_22] - t[idx_12]*t[idx_12];
1207 tmp[idx_01] = -t[idx_01]*t[idx_22] + t[idx_02]*t[idx_12];
1208 tmp[idx_02] = t[idx_01]*t[idx_12] - t[idx_02]*t[idx_11];
1209 tmp[idx_11] = t[idx_00]*t[idx_22] - t[idx_02]*t[idx_02];
1210 tmp[idx_12] = -t[idx_00]*t[idx_12] + t[idx_01]*t[idx_02];
1211 tmp[idx_22] = t[idx_00]*t[idx_11] - t[idx_01]*t[idx_01];
1219 template <
typename Number>
1220 struct Inverse<4,1,Number>
1222 static inline ::SymmetricTensor<4,1,Number>
1223 value (const ::SymmetricTensor<4,1,Number> &t)
1226 tmp.
data[0][0] = 1.0/t.data[0][0];
1232 template <
typename Number>
1233 struct Inverse<4,2,Number>
1235 static inline ::SymmetricTensor<4,2,Number>
1236 value (const ::SymmetricTensor<4,2,Number> &t)
1262 const Number t4 = t.
data[0][0]*t.data[1][1],
1263 t6 = t.data[0][0]*t.data[1][2],
1264 t8 = t.data[0][1]*t.data[1][0],
1265 t00 = t.data[0][2]*t.data[1][0],
1266 t01 = t.data[0][1]*t.data[2][0],
1267 t04 = t.data[0][2]*t.data[2][0],
1268 t07 = 1.0/(t4*t.data[2][2]-t6*t.data[2][1]-
1269 t8*t.data[2][2]+t00*t.data[2][1]+
1270 t01*t.data[1][2]-t04*t.data[1][1]);
1271 tmp.
data[0][0] = (t.data[1][1]*t.data[2][2]-t.data[1][2]*t.data[2][1])*t07;
1272 tmp.
data[0][1] = -(t.data[0][1]*t.data[2][2]-t.data[0][2]*t.data[2][1])*t07;
1273 tmp.
data[0][2] = -(-t.data[0][1]*t.data[1][2]+t.data[0][2]*t.data[1][1])*t07;
1274 tmp.
data[1][0] = -(t.data[1][0]*t.data[2][2]-t.data[1][2]*t.data[2][0])*t07;
1275 tmp.
data[1][1] = (t.data[0][0]*t.data[2][2]-t04)*t07;
1276 tmp.
data[1][2] = -(t6-t00)*t07;
1277 tmp.
data[2][0] = -(-t.data[1][0]*t.data[2][1]+t.data[1][1]*t.data[2][0])*t07;
1278 tmp.
data[2][1] = -(t.data[0][0]*t.data[2][1]-t01)*t07;
1279 tmp.
data[2][2] = (t4-t8)*t07;
1283 tmp.
data[2][0] /= 2;
1284 tmp.
data[2][1] /= 2;
1285 tmp.
data[0][2] /= 2;
1286 tmp.
data[1][2] /= 2;
1287 tmp.
data[2][2] /= 4;
1294 template <
typename Number>
1295 struct Inverse<4,3,Number>
1297 static ::SymmetricTensor<4,3,Number>
1298 value (const ::SymmetricTensor<4,3,Number> &t)
1308 const unsigned int N = 6;
1314 for (
unsigned int i=0; i<N; ++i)
1315 diagonal_sum += std::fabs(tmp.
data[i][i]);
1316 const Number typical_diagonal_element = diagonal_sum/
static_cast<double>(N);
1317 (void)typical_diagonal_element;
1320 for (
unsigned int i=0; i<N; ++i)
1323 for (
unsigned int j=0; j<N; ++j)
1327 Number
max = std::fabs(tmp.
data[j][j]);
1329 for (
unsigned int i=j+1; i<N; ++i)
1330 if (std::fabs(tmp.
data[i][j]) > max)
1332 max = std::fabs(tmp.
data[i][j]);
1337 Assert(max > 1.e-16*typical_diagonal_element,
1338 ExcMessage(
"This tensor seems to be noninvertible"));
1343 for (
unsigned int k=0; k<N; ++k)
1350 const Number hr = 1./tmp.
data[j][j];
1351 tmp.
data[j][j] = hr;
1352 for (
unsigned int k=0; k<N; ++k)
1355 for (
unsigned int i=0; i<N; ++i)
1361 for (
unsigned int i=0; i<N; ++i)
1363 tmp.
data[i][j] *= hr;
1364 tmp.
data[j][i] *= -hr;
1366 tmp.
data[j][j] = hr;
1371 for (
unsigned int i=0; i<N; ++i)
1373 for (
unsigned int k=0; k<N; ++k)
1374 hv[p[k]] = tmp.
data[i][k];
1375 for (
unsigned int k=0; k<N; ++k)
1376 tmp.
data[i][k] = hv[k];
1381 for (
unsigned int i=3; i<6; ++i)
1382 for (
unsigned int j=0; j<3; ++j)
1383 tmp.
data[i][j] /= 2;
1385 for (
unsigned int i=0; i<3; ++i)
1386 for (
unsigned int j=3; j<6; ++j)
1387 tmp.
data[i][j] /= 2;
1389 for (
unsigned int i=3; i<6; ++i)
1390 for (
unsigned int j=3; j<6; ++j)
1391 tmp.
data[i][j] /= 4;
1402 template <
int rank_,
int dim,
typename Number>
1403 inline DEAL_II_ALWAYS_INLINE
1407 return internal::SymmetricTensorImplementation::convert_to_tensor (*
this);
1412 template <
int rank_,
int dim,
typename Number>
1418 return data == t.
data;
1423 template <
int rank_,
int dim,
typename Number>
1429 return data != t.
data;
1434 template <
int rank_,
int dim,
typename Number>
1435 template <
typename OtherNumber>
1436 inline DEAL_II_ALWAYS_INLINE
1447 template <
int rank_,
int dim,
typename Number>
1448 template <
typename OtherNumber>
1449 inline DEAL_II_ALWAYS_INLINE
1460 template <
int rank_,
int dim,
typename Number>
1461 template <
typename OtherNumber>
1462 inline DEAL_II_ALWAYS_INLINE
1472 template <
int rank_,
int dim,
typename Number>
1473 template <
typename OtherNumber>
1474 inline DEAL_II_ALWAYS_INLINE
1484 template <
int rank_,
int dim,
typename Number>
1485 inline DEAL_II_ALWAYS_INLINE
1496 template <
int rank_,
int dim,
typename Number>
1497 inline DEAL_II_ALWAYS_INLINE
1506 template <
int rank_,
int dim,
typename Number>
1521 template <
int dim,
typename Number,
typename OtherNumber = Number>
1522 inline DEAL_II_ALWAYS_INLINE
1523 typename SymmetricTensorAccessors::double_contraction_result<2,2,dim,Number,OtherNumber>::type
1525 const typename SymmetricTensorAccessors::StorageType<2,dim,OtherNumber>::base_tensor_type &sdata)
1527 typedef typename SymmetricTensorAccessors::double_contraction_result<2,2,dim,Number,OtherNumber>::type result_type;
1532 return data[0] * sdata[0];
1537 result_type
sum = data[dim] * sdata[dim];
1538 for (
unsigned int d=dim+1;
d<(dim*(dim+1)/2); ++
d)
1539 sum += data[d] * sdata[d];
1543 for (
unsigned int d=0;
d<dim; ++
d)
1544 sum += data[d] * sdata[d];
1551 template <
int dim,
typename Number,
typename OtherNumber = Number>
1553 typename SymmetricTensorAccessors::double_contraction_result<4,2,dim,Number,OtherNumber>::type
1555 const typename SymmetricTensorAccessors::StorageType<2,dim,OtherNumber>::base_tensor_type &sdata)
1557 typedef typename SymmetricTensorAccessors::double_contraction_result<4,2,dim,Number,OtherNumber>::type result_type;
1558 typedef typename SymmetricTensorAccessors::double_contraction_result<4,2,dim,Number,OtherNumber>::value_type value_type;
1560 const unsigned int data_dim =
1561 SymmetricTensorAccessors::StorageType<2,dim,value_type>::n_independent_components;
1562 value_type tmp [data_dim];
1563 for (
unsigned int i=0; i<data_dim; ++i)
1564 tmp[i] = perform_double_contraction<dim,Number,OtherNumber>(data[i], sdata);
1565 return result_type(tmp);
1570 template <
int dim,
typename Number,
typename OtherNumber = Number>
1572 typename SymmetricTensorAccessors::StorageType<2,dim,
1573 typename SymmetricTensorAccessors::double_contraction_result<2,4,dim,Number,OtherNumber>::value_type
1576 const typename SymmetricTensorAccessors::StorageType<4,dim,OtherNumber>::base_tensor_type &sdata)
1578 typedef typename SymmetricTensorAccessors::double_contraction_result<2,4,dim,Number,OtherNumber>::value_type value_type;
1579 typedef typename SymmetricTensorAccessors::StorageType<2,dim,value_type>::base_tensor_type base_tensor_type;
1581 base_tensor_type tmp;
1582 for (
unsigned int i=0; i<tmp.dimension; ++i)
1585 value_type
sum = data[dim] * sdata[dim][i];
1586 for (
unsigned int d=dim+1;
d<(dim*(dim+1)/2); ++
d)
1587 sum += data[d] * sdata[d][i];
1591 for (
unsigned int d=0;
d<dim; ++
d)
1592 sum += data[d] * sdata[d][i];
1600 template <
int dim,
typename Number,
typename OtherNumber = Number>
1602 typename SymmetricTensorAccessors::StorageType<4,dim,
1603 typename SymmetricTensorAccessors::double_contraction_result<4,4,dim,Number,OtherNumber>::value_type
1606 const typename SymmetricTensorAccessors::StorageType<4,dim,OtherNumber>::base_tensor_type &sdata)
1608 typedef typename SymmetricTensorAccessors::double_contraction_result<4,4,dim,Number,OtherNumber>::value_type value_type;
1609 typedef typename SymmetricTensorAccessors::StorageType<4,dim,value_type>::base_tensor_type base_tensor_type;
1611 const unsigned int data_dim =
1612 SymmetricTensorAccessors::StorageType<2,dim,value_type>::n_independent_components;
1613 base_tensor_type tmp;
1614 for (
unsigned int i=0; i<data_dim; ++i)
1615 for (
unsigned int j=0; j<data_dim; ++j)
1618 for (
unsigned int d=dim;
d<(dim*(dim+1)/2); ++
d)
1619 tmp[i][j] += data[i][d] * sdata[d][j];
1620 tmp[i][j] += tmp[i][j];
1623 for (
unsigned int d=0;
d<dim; ++
d)
1624 tmp[i][j] += data[i][d] * sdata[d][j];
1633 template <
int rank_,
int dim,
typename Number>
1634 template <
typename OtherNumber>
1635 inline DEAL_II_ALWAYS_INLINE
1643 return internal::perform_double_contraction<dim,Number,OtherNumber> (data, s.
data);
1648 template <
int rank_,
int dim,
typename Number>
1649 template <
typename OtherNumber>
1654 typename internal::SymmetricTensorAccessors::
1655 double_contraction_result<rank_,4,dim,Number,OtherNumber>::type tmp;
1656 tmp.
data = internal::perform_double_contraction<dim,Number,OtherNumber> (data,s.
data);
1672 template <
int dim,
typename Number>
1684 if (indices[0] == indices[1])
1685 return data[indices[0]];
1692 Assert (((indices[0]==1) && (indices[1]==0)) ||
1693 ((indices[0]==0) && (indices[1]==1)),
1701 sorted_indices.sort ();
1703 for (
unsigned int d=0, c=0;
d<dim; ++
d)
1704 for (
unsigned int e=d+1;
e<dim; ++
e, ++c)
1705 if ((sorted_indices[0]==d) && (sorted_indices[1]==e))
1711 static Number dummy_but_referenceable = Number();
1712 return dummy_but_referenceable;
1717 template <
int dim,
typename Number>
1729 if (indices[0] == indices[1])
1730 return data[indices[0]];
1737 Assert (((indices[0]==1) && (indices[1]==0)) ||
1738 ((indices[0]==0) && (indices[1]==1)),
1746 sorted_indices.sort ();
1748 for (
unsigned int d=0, c=0;
d<dim; ++
d)
1749 for (
unsigned int e=d+1;
e<dim; ++
e, ++c)
1750 if ((sorted_indices[0]==d) && (sorted_indices[1]==e))
1756 static Number dummy_but_referenceable = Number();
1757 return dummy_but_referenceable;
1762 template <
int dim,
typename Number>
1784 unsigned int base_index[2] ;
1785 if ((indices[0] == 0) && (indices[1] == 0))
1787 else if ((indices[0] == 1) && (indices[1] == 1))
1792 if ((indices[2] == 0) && (indices[3] == 0))
1794 else if ((indices[2] == 1) && (indices[3] == 1))
1799 return data[base_index[0]][base_index[1]];
1813 unsigned int base_index[2] ;
1814 if ((indices[0] == 0) && (indices[1] == 0))
1816 else if ((indices[0] == 1) && (indices[1] == 1))
1818 else if ((indices[0] == 2) && (indices[1] == 2))
1820 else if (((indices[0] == 0) && (indices[1] == 1)) ||
1821 ((indices[0] == 1) && (indices[1] == 0)))
1823 else if (((indices[0] == 0) && (indices[1] == 2)) ||
1824 ((indices[0] == 2) && (indices[1] == 0)))
1828 Assert (((indices[0] == 1) && (indices[1] == 2)) ||
1829 ((indices[0] == 2) && (indices[1] == 1)),
1834 if ((indices[2] == 0) && (indices[3] == 0))
1836 else if ((indices[2] == 1) && (indices[3] == 1))
1838 else if ((indices[2] == 2) && (indices[3] == 2))
1840 else if (((indices[2] == 0) && (indices[3] == 1)) ||
1841 ((indices[2] == 1) && (indices[3] == 0)))
1843 else if (((indices[2] == 0) && (indices[3] == 2)) ||
1844 ((indices[2] == 2) && (indices[3] == 0)))
1848 Assert (((indices[2] == 1) && (indices[3] == 2)) ||
1849 ((indices[2] == 2) && (indices[3] == 1)),
1854 return data[base_index[0]][base_index[1]];
1861 static Number dummy;
1866 template <
int dim,
typename Number>
1888 unsigned int base_index[2] ;
1889 if ((indices[0] == 0) && (indices[1] == 0))
1891 else if ((indices[0] == 1) && (indices[1] == 1))
1896 if ((indices[2] == 0) && (indices[3] == 0))
1898 else if ((indices[2] == 1) && (indices[3] == 1))
1903 return data[base_index[0]][base_index[1]];
1917 unsigned int base_index[2] ;
1918 if ((indices[0] == 0) && (indices[1] == 0))
1920 else if ((indices[0] == 1) && (indices[1] == 1))
1922 else if ((indices[0] == 2) && (indices[1] == 2))
1924 else if (((indices[0] == 0) && (indices[1] == 1)) ||
1925 ((indices[0] == 1) && (indices[1] == 0)))
1927 else if (((indices[0] == 0) && (indices[1] == 2)) ||
1928 ((indices[0] == 2) && (indices[1] == 0)))
1932 Assert (((indices[0] == 1) && (indices[1] == 2)) ||
1933 ((indices[0] == 2) && (indices[1] == 1)),
1938 if ((indices[2] == 0) && (indices[3] == 0))
1940 else if ((indices[2] == 1) && (indices[3] == 1))
1942 else if ((indices[2] == 2) && (indices[3] == 2))
1944 else if (((indices[2] == 0) && (indices[3] == 1)) ||
1945 ((indices[2] == 1) && (indices[3] == 0)))
1947 else if (((indices[2] == 0) && (indices[3] == 2)) ||
1948 ((indices[2] == 2) && (indices[3] == 0)))
1952 Assert (((indices[2] == 1) && (indices[3] == 2)) ||
1953 ((indices[2] == 2) && (indices[3] == 1)),
1958 return data[base_index[0]][base_index[1]];
1965 static Number dummy;
1973 template <
int rank_,
int dim,
typename Number>
1978 for (
unsigned int r=0; r<rank; ++r)
1980 return internal::symmetric_tensor_access<dim,Number> (indices, data);
1985 template <
int rank_,
int dim,
typename Number>
1991 for (
unsigned int r=0; r<rank; ++r)
1993 return internal::symmetric_tensor_access<dim,Number> (indices, data);
2000 namespace SymmetricTensorImplementation
2002 template <
int rank_>
2004 get_partially_filled_indices (
const unsigned int row,
2005 const std::integral_constant<int, 2> &)
2013 template <
int rank_>
2015 get_partially_filled_indices (
const unsigned int row,
2016 const std::integral_constant<int, 4> &)
2028 template <
int rank_,
int dim,
typename Number>
2029 internal::SymmetricTensorAccessors::Accessor<rank_,dim,
true,rank_-1,Number>
2033 internal::SymmetricTensorAccessors::
2034 Accessor<rank_,dim,
true,rank_-1,Number> (*
this,
2035 internal::SymmetricTensorImplementation::get_partially_filled_indices<rank_> (row,
2036 std::integral_constant<int, rank_>()));
2041 template <
int rank_,
int dim,
typename Number>
2042 internal::SymmetricTensorAccessors::Accessor<rank_,dim,
false,rank_-1,Number>
2046 internal::SymmetricTensorAccessors::
2047 Accessor<rank_,dim,
false,rank_-1,Number> (*
this,
2048 internal::SymmetricTensorImplementation::get_partially_filled_indices<rank_> (row,
2049 std::integral_constant<int, rank_>()));
2054 template <
int rank_,
int dim,
typename Number>
2059 return operator()(indices);
2064 template <
int rank_,
int dim,
typename Number>
2069 return operator()(indices);
2074 template <
int rank_,
int dim,
typename Number>
2079 return std::addressof(this->access_raw_entry(0));
2084 template <
int rank_,
int dim,
typename Number>
2089 return std::addressof(this->access_raw_entry(0));
2094 template <
int rank_,
int dim,
typename Number>
2099 return begin_raw()+n_independent_components;
2104 template <
int rank_,
int dim,
typename Number>
2109 return begin_raw()+n_independent_components;
2116 namespace SymmetricTensorImplementation
2118 template <
int dim,
typename Number>
2120 entry_to_indices (const ::SymmetricTensor<2,dim,Number> &,
2121 const unsigned int index)
2127 template <
int dim,
typename Number>
2129 entry_to_indices (const ::SymmetricTensor<4,dim,Number> &,
2130 const unsigned int index)
2142 template <
int rank_,
int dim,
typename Number>
2148 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this, index)];
2153 template <
int rank_,
int dim,
typename Number>
2159 return data[internal::SymmetricTensorImplementation::entry_to_indices(*
this, index)];
2166 template <
int dim,
typename Number>
2194 for (
unsigned int d=0;
d<dim; ++
d)
2196 for (
unsigned int d=dim;
d<(dim*dim+dim)/2; ++
d)
2199 return std::sqrt(return_value);
2206 template <
int dim,
typename Number>
2221 const unsigned int n_independent_components = data.dimension;
2223 for (
unsigned int i=0; i<dim; ++i)
2224 for (
unsigned int j=0; j<dim; ++j)
2226 for (
unsigned int i=0; i<dim; ++i)
2227 for (
unsigned int j=dim; j<n_independent_components; ++j)
2229 for (
unsigned int i=dim; i<n_independent_components; ++i)
2230 for (
unsigned int j=0; j<dim; ++j)
2232 for (
unsigned int i=dim; i<n_independent_components; ++i)
2233 for (
unsigned int j=dim; j<n_independent_components; ++j)
2236 return std::sqrt(return_value);
2245 template <
int rank_,
int dim,
typename Number>
2250 return internal::compute_norm<dim,Number> (data);
2257 namespace SymmetricTensorImplementation
2269 component_to_unrolled_index
2284 static const unsigned int table[2][2] = {{0, 2},
2287 return table[indices[0]][indices[1]];
2292 static const unsigned int table[3][3] = {{0, 3, 4},
2296 return table[indices[0]][indices[1]];
2301 static const unsigned int table[4][4] = {{0, 4, 5, 6},
2306 return table[indices[0]][indices[1]];
2312 if (indices[0] == indices[1])
2316 sorted_indices.sort ();
2318 for (
unsigned int d=0, c=0;
d<dim; ++
d)
2319 for (
unsigned int e=d+1;
e<dim; ++
e, ++c)
2320 if ((sorted_indices[0]==d) && (sorted_indices[1]==e))
2336 template <
int dim,
int rank_>
2339 component_to_unrolled_index
2351 template <
int rank_,
int dim,
typename Number>
2357 return internal::SymmetricTensorImplementation::component_to_unrolled_index<dim> (indices);
2364 namespace SymmetricTensorImplementation
2378 unrolled_to_component_indices
2379 (
const unsigned int i,
2380 const std::integral_constant<int, 2> &)
2420 for (
unsigned int d=0, c=0;
d<dim; ++
d)
2421 for (
unsigned int e=d+1;
e<dim; ++
e, ++c)
2439 template <
int dim,
int rank_>
2442 unrolled_to_component_indices
2443 (
const unsigned int i,
2444 const std::integral_constant<int, rank_> &)
2457 template <
int rank_,
int dim,
typename Number>
2461 (
const unsigned int i)
2464 internal::SymmetricTensorImplementation::unrolled_to_component_indices<dim> (i,
2465 std::integral_constant<int, rank_>());
2470 template <
int rank_,
int dim,
typename Number>
2471 template <
class Archive>
2497 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2521 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2540 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2557 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2574 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2591 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
2615 template <
int dim,
typename Number>
2654 template <
int dim,
typename Number>
2670 template <
int dim,
typename Number>
2673 Number t = d.data[0];
2674 for (
unsigned int i=1; i<dim; ++i)
2689 template <
int dim,
typename Number>
2709 template <
typename Number>
2738 template <
typename Number>
2742 return t[0][0]*t[1][1] - t[0][1]*t[0][1];
2756 template <
typename Number>
2760 return (t[0][0]*t[1][1] + t[1][1]*t[2][2] + t[2][2]*t[0][0]
2761 - t[0][1]*t[0][1] - t[0][2]*t[0][2] - t[1][2]*t[1][2]);
2774 template <
typename Number>
2775 std::array<Number,1>
2801 template <
typename Number>
2802 std::array<Number,2>
2826 template <
typename Number>
2827 std::array<Number,3>
2834 namespace SymmetricTensorImplementation
2872 template <
int dim,
typename Number>
2876 std::array<Number,dim> &d,
2877 std::array<Number,dim-1> &e);
2919 template <
int dim,
typename Number>
2920 std::array<std::pair<Number, Tensor<1,dim,Number> >,dim>
2963 template <
int dim,
typename Number>
2964 std::array<std::pair<Number, Tensor<1,dim,Number> >,dim>
2984 template <
typename Number>
2985 std::array<std::pair<Number, Tensor<1,2,Number> >,2>
2986 hybrid (const ::SymmetricTensor<2,2,Number> &A);
3022 template <
typename Number>
3023 std::array<std::pair<Number, Tensor<1,3,Number> >,3>
3024 hybrid (const ::SymmetricTensor<2,3,Number> &A);
3033 template <
int dim,
typename Number>
3034 struct SortEigenValuesVectors
3036 typedef std::pair<Number, Tensor<1,dim,Number> > EigValsVecs;
3037 bool operator() (
const EigValsVecs &lhs,
3038 const EigValsVecs &rhs)
3040 return lhs.first > rhs.first;
3142 template <
int dim,
typename Number>
3143 std::array<std::pair<Number, Tensor<1,dim,Number> >,std::integral_constant<int, dim>::value>
3158 template <
int rank_,
int dim,
typename Number>
3177 template <
int dim,
typename Number>
3185 const Number tr =
trace(t) / dim;
3186 for (
unsigned int i=0; i<dim; ++i)
3201 template <
int dim,
typename Number>
3221 for (
unsigned int d=0; d<dim; ++d)
3242 return unit_symmetric_tensor<dim,double>();
3261 template <
int dim,
typename Number>
3269 for (
unsigned int i=0; i<dim; ++i)
3270 for (
unsigned int j=0; j<dim; ++j)
3271 tmp.
data[i][j] = (i==j ? 1 : 0) - 1./dim;
3278 for (
unsigned int i=dim;
3279 i<internal::SymmetricTensorAccessors::StorageType<4,dim,Number>::n_rank2_components;
3281 tmp.
data[i][i] = 0.5;
3307 return deviator_tensor<dim,double>();
3334 template <
int dim,
typename Number>
3342 for (
unsigned int i=0; i<dim; ++i)
3350 for (
unsigned int i=dim;
3351 i<internal::SymmetricTensorAccessors::StorageType<4,dim,Number>::n_rank2_components;
3353 tmp.
data[i][i] = 0.5;
3386 return identity_tensor<dim,double>();
3401 template <
int dim,
typename Number>
3422 template <
int dim,
typename Number>
3446 template <
int dim,
typename Number>
3455 for (
unsigned int i=0; i<dim; ++i)
3456 for (
unsigned int j=i; j<dim; ++j)
3457 for (
unsigned int k=0; k<dim; ++k)
3458 for (
unsigned int l=k; l<dim; ++l)
3459 tmp[i][j][k][l] = t1[i][j] * t2[k][l];
3474 template <
int dim,
typename Number>
3479 Number array[(dim*dim+dim)/2];
3480 for (
unsigned int d=0; d<dim; ++d)
3482 for (
unsigned int d=0, c=0; d<dim; ++d)
3483 for (
unsigned int e=d+1; e<dim; ++e, ++c)
3484 array[dim+c] = (t[d][e]+t[e][d])*0.5;
3497 template <
int rank_,
int dim,
typename Number>
3501 const Number &factor)
3517 template <
int rank_,
int dim,
typename Number>
3554 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3558 const OtherNumber &factor)
3565 typedef typename ProductType<Number,OtherNumber>::type product_type;
3574 product_type new_factor;
3575 new_factor = factor;
3590 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3607 template <
int rank_,
int dim,
typename Number,
typename OtherNumber>
3611 const OtherNumber &factor)
3626 template <
int rank_,
int dim>
3630 const double factor)
3645 template <
int rank_,
int dim>
3663 template <
int rank_,
int dim>
3667 const double factor)
3683 template <
int dim,
typename Number,
typename OtherNumber>
3685 typename ProductType<Number, OtherNumber>::type
3702 template <
int dim,
typename Number,
typename OtherNumber>
3704 typename ProductType<Number, OtherNumber>::type
3709 for (
unsigned int i=0; i<dim; ++i)
3710 for (
unsigned int j=0; j<dim; ++j)
3711 s += t1[i][j] * t2[i][j];
3725 template <
int dim,
typename Number,
typename OtherNumber>
3727 typename ProductType<Number, OtherNumber>::type
3750 template <
typename Number,
typename OtherNumber>
3757 tmp[0][0] = t[0][0][0][0] * s[0][0];
3777 template <
typename Number,
typename OtherNumber>
3784 tmp[0][0] = t[0][0][0][0] * s[0][0];
3803 template <
typename Number,
typename OtherNumber>
3810 const unsigned int dim = 2;
3812 for (
unsigned int i=0; i<dim; ++i)
3813 for (
unsigned int j=i; j<dim; ++j)
3814 tmp[i][j] = t[i][j][0][0] * s[0][0] +
3815 t[i][j][1][1] * s[1][1] +
3816 2 * t[i][j][0][1] * s[0][1];
3836 template <
typename Number,
typename OtherNumber>
3843 const unsigned int dim = 2;
3845 for (
unsigned int i=0; i<dim; ++i)
3846 for (
unsigned int j=i; j<dim; ++j)
3847 tmp[i][j] = s[0][0] * t[0][0][i][j] * +
3848 s[1][1] * t[1][1][i][j] +
3849 2 * s[0][1] * t[0][1][i][j];
3869 template <
typename Number,
typename OtherNumber>
3876 const unsigned int dim = 3;
3878 for (
unsigned int i=0; i<dim; ++i)
3879 for (
unsigned int j=i; j<dim; ++j)
3880 tmp[i][j] = t[i][j][0][0] * s[0][0] +
3881 t[i][j][1][1] * s[1][1] +
3882 t[i][j][2][2] * s[2][2] +
3883 2 * t[i][j][0][1] * s[0][1] +
3884 2 * t[i][j][0][2] * s[0][2] +
3885 2 * t[i][j][1][2] * s[1][2];
3905 template <
typename Number,
typename OtherNumber>
3912 const unsigned int dim = 3;
3914 for (
unsigned int i=0; i<dim; ++i)
3915 for (
unsigned int j=i; j<dim; ++j)
3916 tmp[i][j] = s[0][0] * t[0][0][i][j] +
3917 s[1][1] * t[1][1][i][j] +
3918 s[2][2] * t[2][2][i][j] +
3919 2 * s[0][1] * t[0][1][i][j] +
3920 2 * s[0][2] * t[0][2][i][j] +
3921 2 * s[1][2] * t[1][2][i][j];
3933 template <
int dim,
typename Number,
typename OtherNumber>
3939 for (
unsigned int i=0; i<dim; ++i)
3940 for (
unsigned int j=0; j<dim; ++j)
3941 dest[i] += src1[i][j] * src2[j];
3953 template <
int dim,
typename Number,
typename OtherNumber>
3984 template <
int rank_1,
int rank_2,
int dim,
3985 typename Number,
typename OtherNumber>
3986 inline DEAL_II_ALWAYS_INLINE
3987 typename Tensor<rank_1 + rank_2 - 2, dim,
typename ProductType<Number, OtherNumber>::type>::tensor_type
3991 typename Tensor<rank_1 + rank_2 - 2, dim,
typename ProductType<Number, OtherNumber>::type>::tensor_type result;
4018 template <
int rank_1,
int rank_2,
int dim,
4019 typename Number,
typename OtherNumber>
4020 inline DEAL_II_ALWAYS_INLINE
4021 typename Tensor<rank_1 + rank_2 - 2, dim,
typename ProductType<Number, OtherNumber>::type>::tensor_type
4025 typename Tensor<rank_1 + rank_2 - 2, dim,
typename ProductType<Number, OtherNumber>::type>::tensor_type result;
4041 template <
int dim,
typename Number>
4051 for (
unsigned int i=0; i<dim; ++i)
4052 for (
unsigned int j=0; j<dim; ++j)
4069 template <
int dim,
typename Number>
4079 for (
unsigned int i=0; i<dim; ++i)
4080 for (
unsigned int j=0; j<dim; ++j)
4081 for (
unsigned int k=0; k<dim; ++k)
4082 for (
unsigned int l=0; l<dim; ++l)
4083 tt[i][j][k][l] = t[i][j][k][l];
4089 DEAL_II_NAMESPACE_CLOSE
friend SymmetricTensor< 4, dim2, Number2 > identity_tensor()
SymmetricTensor< rank_, dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator/(const SymmetricTensor< rank_, dim, Number > &t, const OtherNumber &factor)
Tensor< 2, n_rank2_components, Number > base_tensor_type
static const unsigned int invalid_unsigned_int
static unsigned int component_to_unrolled_index(const TableIndices< rank_ > &indices)
SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
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)
static const unsigned int n_independent_components
SymmetricTensor< 2, dim, Number > symmetrize(const Tensor< 2, dim, Number > &t)
bool value_is_zero(const Number &value)
void double_contract(SymmetricTensor< 2, 1, typename ProductType< Number, OtherNumber >::type > &tmp, const SymmetricTensor< 4, 1, Number > &t, const SymmetricTensor< 2, 1, OtherNumber > &s)
#define AssertIndexRange(index, range)
SymmetricTensor< 4, dim, Number > deviator_tensor()
TableIndices< 2 > merge(const TableIndices< 2 > &previous_indices, const unsigned int new_index, const unsigned int position)
SymmetricTensor & operator=(const SymmetricTensor< rank_, dim, OtherNumber > &rhs)
static std::size_t memory_consumption()
static real_type abs(const number &x)
SymmetricTensorEigenvectorMethod
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator+(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
internal::SymmetricTensorAccessors::StorageType< rank_, dim, Number > base_tensor_descriptor
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
SymmetricTensor & operator/=(const OtherNumber &factor)
static TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
internal::SymmetricTensorAccessors::double_contraction_result< rank_, 2, dim, Number, OtherNumber >::type operator*(const SymmetricTensor< 2, dim, OtherNumber > &s) const
static const unsigned int dimension
SymmetricTensor< rank_, dim, typename ProductType< Number, OtherNumber >::type > operator-(const SymmetricTensor< rank_, dim, Number > &left, const SymmetricTensor< rank_, dim, OtherNumber > &right)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > ql_implicit_shifts(const ::SymmetricTensor< 2, dim, Number > &A)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > jacobi(::SymmetricTensor< 2, dim, Number > A)
static ::ExceptionBase & ExcMessage(std::string arg1)
void tridiagonalize(const ::SymmetricTensor< 2, dim, Number > &A, ::Tensor< 2, dim, Number > &Q, std::array< Number, dim > &d, std::array< Number, dim-1 > &e)
TableIndices< 4 > merge(const TableIndices< 4 > &previous_indices, const unsigned int new_index, const unsigned int position)
Number first_invariant(const SymmetricTensor< 2, dim, Number > &t)
const Number & access_raw_entry(const unsigned int unrolled_index) const
base_tensor_descriptor::base_tensor_type base_tensor_type
friend Number2 trace(const SymmetricTensor< 2, dim2, Number2 > &d)
static const unsigned int rank
bool operator!=(const SymmetricTensor &) const
T sum(const T &t, const MPI_Comm &mpi_communicator)
#define Assert(cond, exc)
SymmetricTensor< 2, dim, Number > deviator(const SymmetricTensor< 2, dim, Number > &t)
Number trace(const SymmetricTensor< 2, dim, Number > &d)
void serialize(Archive &ar, const unsigned int version)
friend SymmetricTensor< 2, dim2, Number2 > unit_symmetric_tensor()
SymmetricTensor< 4, dim, Number > outer_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, Number > &t2)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
ProductType< Number, OtherNumber >::type scalar_product(const SymmetricTensor< 2, dim, Number > &t1, const SymmetricTensor< 2, dim, OtherNumber > &t2)
Number & operator()(const TableIndices< rank_ > &indices)
std::array< std::pair< Number, Tensor< 1, 2, Number > >, 2 > hybrid(const ::SymmetricTensor< 2, 2, Number > &A)
void swap(Vector< Number > &u, Vector< Number > &v)
OutputOperator< VectorType > & operator<<(OutputOperator< VectorType > &out, unsigned int step)
Number determinant(const SymmetricTensor< 2, dim, Number > &t)
SymmetricTensor operator-() const
SymmetricTensor & operator*=(const OtherNumber &factor)
SymmetricTensor & operator+=(const SymmetricTensor< rank_, dim, OtherNumber > &)
Number third_invariant(const SymmetricTensor< 2, dim, Number > &t)
Tensor< 1, n_independent_components, Number > base_tensor_type
static ::ExceptionBase & ExcNotImplemented()
bool operator==(const SymmetricTensor &) const
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
SymmetricTensor< 2, dim, Number > unit_symmetric_tensor()
friend SymmetricTensor< 4, dim2, Number2 > deviator_tensor()
Point< dim, typename ProductType< Number, typename EnableIfScalar< OtherNumber >::type >::type > operator*(const OtherNumber) const
internal::SymmetricTensorAccessors::Accessor< rank_, dim, true, rank_-1, Number > operator[](const unsigned int row) const
T max(const T &t, const MPI_Comm &mpi_communicator)
SymmetricTensor< 4, dim, Number > identity_tensor()
Number second_invariant(const SymmetricTensor< 2, 1, Number > &)
SymmetricTensor & operator-=(const SymmetricTensor< rank_, dim, OtherNumber > &)
numbers::NumberTraits< Number >::real_type norm() const
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
static ::ExceptionBase & ExcInternalError()