16 #ifndef dealii_physics_notation_h
17 #define dealii_physics_notation_h
29 #include <type_traits>
296 <<
"The number of rows in the input matrix is " << arg1
297 <<
", but needs to be either " << arg2 <<
" or " << arg3
309 <<
"The number of rows in the input matrix is " << arg1
310 <<
", but needs to be either " << arg2 <<
"," << arg3
311 <<
", or " << arg4 <<
".");
321 <<
"The number of columns in the input matrix is " << arg1
322 <<
", but needs to be either " << arg2 <<
" or " << arg3
334 <<
"The number of columns in the input matrix is " << arg1
335 <<
", but needs to be either " << arg2 <<
"," << arg3
336 <<
", or " << arg4 <<
".");
349 template <
typename Number>
359 template <
int dim,
typename Number>
369 template <
int dim,
typename Number>
379 template <
int dim,
typename Number>
390 template <
int dim,
typename Number>
400 template <
typename Number>
410 template <
int dim,
typename Number>
420 template <
int dim,
typename Number>
430 template <
int dim,
typename Number>
444 template <
int dim,
typename Number>
494 template <
int dim,
typename Number>
506 template <
int dim,
typename Number>
520 template <
typename Number>
522 to_tensor(
const Vector<Number> &vec, Number &s);
528 template <
int dim,
typename Number>
536 template <
int dim,
typename Number>
544 template <
int dim,
typename Number>
552 template <
int dim,
typename Number>
560 template <
typename Number>
568 template <
int dim,
typename Number>
576 template <
int dim,
typename Number>
584 template <
int dim,
typename Number>
592 template <
int dim,
typename Number>
607 template <
int dim,
typename Number>
615 template <
int dim,
typename Number>
623 template <
int dim,
typename Number>
633 template <
typename TensorType,
typename Number>
642 template <
typename TensorType,
typename Number>
675 std::pair<unsigned int, unsigned int>
676 indices_from_component(
const unsigned int component_n,
681 std::pair<unsigned int, unsigned int>
682 indices_from_component(
const unsigned int component_n,
const bool)
685 return std::pair<unsigned int, unsigned int>();
690 inline std::pair<unsigned int, unsigned int>
691 indices_from_component<1>(
const unsigned int component_n,
const bool)
695 return std::make_pair(0u, 0u);
700 inline std::pair<unsigned int, unsigned int>
701 indices_from_component<2>(
const unsigned int component_n,
720 static const unsigned int indices[4][2] = {{0, 0},
724 return std::make_pair(indices[component_n][0],
725 indices[component_n][1]);
730 inline std::pair<unsigned int, unsigned int>
731 indices_from_component<3>(
const unsigned int component_n,
750 static const unsigned int indices[9][2] = {{0, 0},
759 return std::make_pair(indices[component_n][0],
760 indices[component_n][1]);
770 vector_component_factor(
const unsigned int component_i,
776 if (component_i < dim)
789 matrix_component_factor(
const unsigned int component_i,
790 const unsigned int component_j,
798 if (component_i < dim && component_j < dim)
800 else if (component_i >= dim && component_j >= dim)
810 template <
typename Number>
814 Vector<Number> out(1);
815 const unsigned int n_rows = out.size();
816 for (
unsigned int r = 0; r < n_rows; ++r)
822 template <
int dim,
typename Number>
826 return to_vector(s.operator
const Number &());
830 template <
int dim,
typename Number>
835 const unsigned int n_rows = out.size();
836 for (
unsigned int r = 0; r < n_rows; ++r)
838 const std::pair<unsigned int, unsigned int> indices =
839 internal::indices_from_component<dim>(r,
false);
841 const unsigned int i = indices.first;
848 template <
int dim,
typename Number>
853 const unsigned int n_rows = out.size();
854 for (
unsigned int r = 0; r < n_rows; ++r)
856 const std::pair<unsigned int, unsigned int> indices =
857 internal::indices_from_component<dim>(r,
false);
860 const unsigned int i = indices.first;
861 const unsigned int j = indices.second;
868 template <
int dim,
typename Number>
873 const unsigned int n_rows = out.size();
874 for (
unsigned int r = 0; r < n_rows; ++r)
876 const std::pair<unsigned int, unsigned int> indices =
877 internal::indices_from_component<dim>(r,
true);
881 const unsigned int i = indices.first;
882 const unsigned int j = indices.second;
884 const double factor =
885 internal::vector_component_factor<dim>(r,
true);
887 out(r) = factor * st[i][j];
893 template <
typename Number>
903 template <
int dim,
typename Number>
907 return to_matrix(s.operator
const Number &());
911 template <
int dim,
typename Number>
916 const unsigned int n_rows = out.m();
917 const unsigned int n_cols = out.n();
918 for (
unsigned int r = 0; r < n_rows; ++r)
920 const std::pair<unsigned int, unsigned int> indices =
921 internal::indices_from_component<dim>(r,
false);
923 const unsigned int i = indices.first;
925 for (
unsigned int c = 0; c < n_cols; ++c)
935 template <
int dim,
typename Number>
940 const unsigned int n_rows = out.m();
941 const unsigned int n_cols = out.n();
942 for (
unsigned int r = 0; r < n_rows; ++r)
944 const std::pair<unsigned int, unsigned int> indices_i =
945 internal::indices_from_component<dim>(r,
false);
948 const unsigned int i = indices_i.first;
950 for (
unsigned int c = 0; c < n_cols; ++c)
952 const std::pair<unsigned int, unsigned int> indices_j =
953 internal::indices_from_component<dim>(c,
false);
956 const unsigned int j = indices_j.second;
965 template <
int dim,
typename Number>
975 template <
typename TensorType>
976 struct is_rank_2_symmetric_tensor : std::false_type
979 template <
int dim,
typename Number>
994 (SubTensor1::dimension == dim && SubTensor2::dimension == dim),
995 "Sub-tensor spatial dimension is different from those of the input tensor.");
998 (SubTensor1::rank == 2 && SubTensor2::rank == 1) ||
999 (SubTensor1::rank == 1 && SubTensor2::rank == 2),
1000 "Cannot build a rank 3 tensor from the given combination of sub-tensors.");
1003 SubTensor2::n_independent_components);
1004 const unsigned int n_rows = out.m();
1005 const unsigned int n_cols = out.n();
1007 if (SubTensor1::rank == 2 && SubTensor2::rank == 1)
1009 const bool subtensor_is_rank_2_symmetric_tensor =
1012 for (
unsigned int r = 0; r < n_rows; ++r)
1014 const std::pair<unsigned int, unsigned int> indices_ij =
1015 internal::indices_from_component<dim>(
1016 r, subtensor_is_rank_2_symmetric_tensor);
1019 if (subtensor_is_rank_2_symmetric_tensor)
1021 Assert(indices_ij.second >= indices_ij.first,
1024 const unsigned int i = indices_ij.first;
1025 const unsigned int j = indices_ij.second;
1027 const double factor = internal::vector_component_factor<dim>(
1028 r, subtensor_is_rank_2_symmetric_tensor);
1030 for (
unsigned int c = 0; c < n_cols; ++c)
1032 const std::pair<unsigned int, unsigned int> indices_k =
1033 internal::indices_from_component<dim>(c,
false);
1035 const unsigned int k = indices_k.first;
1037 if (subtensor_is_rank_2_symmetric_tensor)
1038 out(r, c) = factor * t[i][j][k];
1040 out(r, c) = t[i][j][k];
1044 else if (SubTensor1::rank == 1 && SubTensor2::rank == 2)
1046 const bool subtensor_is_rank_2_symmetric_tensor =
1049 for (
unsigned int r = 0; r < n_rows; ++r)
1051 const std::pair<unsigned int, unsigned int> indices_k =
1052 internal::indices_from_component<dim>(r,
false);
1054 const unsigned int k = indices_k.first;
1056 for (
unsigned int c = 0; c < n_cols; ++c)
1058 const std::pair<unsigned int, unsigned int> indices_ij =
1059 internal::indices_from_component<dim>(
1060 c, subtensor_is_rank_2_symmetric_tensor);
1063 if (subtensor_is_rank_2_symmetric_tensor)
1065 Assert(indices_ij.second >= indices_ij.first,
1068 const unsigned int i = indices_ij.first;
1069 const unsigned int j = indices_ij.second;
1071 if (subtensor_is_rank_2_symmetric_tensor)
1073 const double factor =
1074 internal::vector_component_factor<dim>(
1075 c, subtensor_is_rank_2_symmetric_tensor);
1076 out(r, c) = factor * t[k][i][j];
1079 out(r, c) = t[k][i][j];
1092 template <
int dim,
typename Number>
1099 const unsigned int n_rows = out.m();
1100 const unsigned int n_cols = out.n();
1101 for (
unsigned int r = 0; r < n_rows; ++r)
1103 const std::pair<unsigned int, unsigned int> indices_ij =
1104 internal::indices_from_component<dim>(r,
false);
1107 const unsigned int i = indices_ij.first;
1108 const unsigned int j = indices_ij.second;
1110 for (
unsigned int c = 0; c < n_cols; ++c)
1112 const std::pair<unsigned int, unsigned int> indices_kl =
1113 internal::indices_from_component<dim>(c,
false);
1116 const unsigned int k = indices_kl.first;
1117 const unsigned int l = indices_kl.second;
1119 out(r, c) = t[i][j][k][
l];
1126 template <
int dim,
typename Number>
1133 const unsigned int n_rows = out.m();
1134 const unsigned int n_cols = out.n();
1135 for (
unsigned int r = 0; r < n_rows; ++r)
1137 const std::pair<unsigned int, unsigned int> indices_ij =
1138 internal::indices_from_component<dim>(r,
true);
1142 const unsigned int i = indices_ij.first;
1143 const unsigned int j = indices_ij.second;
1145 for (
unsigned int c = 0; c < n_cols; ++c)
1147 const std::pair<unsigned int, unsigned int> indices_kl =
1148 internal::indices_from_component<dim>(c,
true);
1151 Assert(indices_kl.second >= indices_kl.first,
1153 const unsigned int k = indices_kl.first;
1154 const unsigned int l = indices_kl.second;
1156 const double factor =
1157 internal::matrix_component_factor<dim>(r, c,
true);
1159 out(r, c) = factor * st[i][j][k][
l];
1166 template <
typename Number>
1168 to_tensor(
const Vector<Number> &vec, Number &s)
1175 template <
int dim,
typename Number>
1179 return to_tensor(vec, s.operator Number &());
1183 template <
int dim,
typename Number>
1189 const unsigned int n_rows = vec.size();
1190 for (
unsigned int r = 0; r < n_rows; ++r)
1192 const std::pair<unsigned int, unsigned int> indices =
1193 internal::indices_from_component<dim>(r,
false);
1195 const unsigned int i = indices.first;
1201 template <
int dim,
typename Number>
1207 const unsigned int n_rows = vec.size();
1208 for (
unsigned int r = 0; r < n_rows; ++r)
1210 const std::pair<unsigned int, unsigned int> indices =
1211 internal::indices_from_component<dim>(r,
false);
1214 const unsigned int i = indices.first;
1215 const unsigned int j = indices.second;
1221 template <
int dim,
typename Number>
1227 const unsigned int n_rows = vec.size();
1228 for (
unsigned int r = 0; r < n_rows; ++r)
1230 const std::pair<unsigned int, unsigned int> indices =
1231 internal::indices_from_component<dim>(r,
true);
1235 const unsigned int i = indices.first;
1236 const unsigned int j = indices.second;
1238 const double inv_factor =
1239 1.0 / internal::vector_component_factor<dim>(r,
true);
1241 st[i][j] = inv_factor * vec(r);
1246 template <
typename Number>
1258 template <
int dim,
typename Number>
1262 return to_tensor(mtrx, s.operator Number &());
1266 template <
int dim,
typename Number>
1276 const unsigned int n_rows = mtrx.
m();
1277 const unsigned int n_cols = mtrx.
n();
1278 for (
unsigned int r = 0; r < n_rows; ++r)
1280 const std::pair<unsigned int, unsigned int> indices =
1281 internal::indices_from_component<dim>(r,
false);
1284 const unsigned int i = indices.first;
1286 for (
unsigned int c = 0; c < n_cols; ++c)
1295 template <
int dim,
typename Number>
1305 const unsigned int n_rows = mtrx.
m();
1306 const unsigned int n_cols = mtrx.
n();
1307 for (
unsigned int r = 0; r < n_rows; ++r)
1309 const std::pair<unsigned int, unsigned int> indices_i =
1310 internal::indices_from_component<dim>(r,
false);
1313 const unsigned int i = indices_i.first;
1315 for (
unsigned int c = 0; c < n_cols; ++c)
1317 const std::pair<unsigned int, unsigned int> indices_j =
1318 internal::indices_from_component<dim>(c,
false);
1321 const unsigned int j = indices_j.second;
1323 t[i][j] = mtrx(r, c);
1329 template <
int dim,
typename Number>
1351 "The entries stored inside the matrix were not symmetric"));
1355 template <
int dim,
typename Number>
1380 const unsigned int n_rows = mtrx.
m();
1381 const unsigned int n_cols = mtrx.
n();
1393 const bool subtensor_is_rank_2_symmetric_tensor =
1397 for (
unsigned int r = 0; r < n_rows; ++r)
1399 const std::pair<unsigned int, unsigned int> indices_ij =
1400 internal::indices_from_component<dim>(
1401 r, subtensor_is_rank_2_symmetric_tensor);
1404 if (subtensor_is_rank_2_symmetric_tensor)
1406 Assert(indices_ij.second >= indices_ij.first,
1409 const unsigned int i = indices_ij.first;
1410 const unsigned int j = indices_ij.second;
1412 const double inv_factor =
1413 1.0 / internal::vector_component_factor<dim>(
1414 r, subtensor_is_rank_2_symmetric_tensor);
1416 for (
unsigned int c = 0; c < n_cols; ++c)
1418 const std::pair<unsigned int, unsigned int> indices_k =
1419 internal::indices_from_component<dim>(c,
false);
1421 const unsigned int k = indices_k.first;
1423 if (subtensor_is_rank_2_symmetric_tensor)
1425 t[i][j][k] = inv_factor * mtrx(r, c);
1426 t[j][i][k] = t[i][j][k];
1429 t[i][j][k] = mtrx(r, c);
1448 const bool subtensor_is_rank_2_symmetric_tensor =
1452 for (
unsigned int r = 0; r < n_rows; ++r)
1454 const std::pair<unsigned int, unsigned int> indices_k =
1455 internal::indices_from_component<dim>(r,
false);
1457 const unsigned int k = indices_k.first;
1459 for (
unsigned int c = 0; c < n_cols; ++c)
1461 const std::pair<unsigned int, unsigned int> indices_ij =
1462 internal::indices_from_component<dim>(
1463 c, subtensor_is_rank_2_symmetric_tensor);
1466 if (subtensor_is_rank_2_symmetric_tensor)
1468 Assert(indices_ij.second >= indices_ij.first,
1471 const unsigned int i = indices_ij.first;
1472 const unsigned int j = indices_ij.second;
1474 if (subtensor_is_rank_2_symmetric_tensor)
1476 const double inv_factor =
1477 1.0 / internal::vector_component_factor<dim>(
1478 c, subtensor_is_rank_2_symmetric_tensor);
1479 t[k][i][j] = inv_factor * mtrx(r, c);
1480 t[k][j][i] = t[k][i][j];
1483 t[k][i][j] = mtrx(r, c);
1490 template <
int dim,
typename Number>
1504 const unsigned int n_rows = mtrx.
m();
1505 const unsigned int n_cols = mtrx.
n();
1506 for (
unsigned int r = 0; r < n_rows; ++r)
1508 const std::pair<unsigned int, unsigned int> indices_ij =
1509 internal::indices_from_component<dim>(r,
false);
1512 const unsigned int i = indices_ij.first;
1513 const unsigned int j = indices_ij.second;
1515 for (
unsigned int c = 0; c < n_cols; ++c)
1517 const std::pair<unsigned int, unsigned int> indices_kl =
1518 internal::indices_from_component<dim>(c,
false);
1521 const unsigned int k = indices_kl.first;
1522 const unsigned int l = indices_kl.second;
1524 t[i][j][k][
l] = mtrx(r, c);
1530 template <
int dim,
typename Number>
1549 const unsigned int n_rows = mtrx.
m();
1550 const unsigned int n_cols = mtrx.
n();
1551 for (
unsigned int r = 0; r < n_rows; ++r)
1553 const std::pair<unsigned int, unsigned int> indices_ij =
1554 internal::indices_from_component<dim>(r,
false);
1557 const unsigned int i = indices_ij.first;
1558 const unsigned int j = indices_ij.second;
1560 for (
unsigned int c = 0; c < n_cols; ++c)
1562 const std::pair<unsigned int, unsigned int> indices_kl =
1563 internal::indices_from_component<dim>(c,
false);
1566 const unsigned int k = indices_kl.first;
1567 const unsigned int l = indices_kl.second;
1569 const double inv_factor =
1570 1.0 / internal::matrix_component_factor<dim>(r, c,
true);
1572 st[i][j][k][
l] = inv_factor * mtrx(r, c);
1578 template <
typename TensorType,
typename Number>
1588 template <
typename TensorType,
typename Number>