16 #ifndef dealii_differentiation_sd_symengine_tensor_operations_h
17 #define dealii_differentiation_sd_symengine_tensor_operations_h
21 #ifdef DEAL_II_WITH_SYMENGINE
85 template <
int rank,
int dim>
108 template <
int rank,
int dim>
156 template <
int rank,
int dim>
181 template <
int rank,
int dim>
184 const std::string & symbol,
203 template <
int rank,
int dim>
216 template <
int rank,
int dim>
230 template <
int rank,
int dim>
244 template <
int rank,
int dim>
258 template <
int rank,
int dim>
272 template <
int rank,
int dim>
275 const Expression & x);
287 template <
int rank,
int dim>
303 template <
int rank,
int dim>
318 template <
int rank_1,
int rank_2,
int dim>
335 template <
int rank_1,
int rank_2,
int dim>
350 template <
int rank_1,
int rank_2,
int dim>
365 template <
int rank_1,
int rank_2,
int dim>
401 template <
bool ignore_invalid_symbols =
false,
402 typename ValueType =
double,
405 typename SymbolicType>
434 template <
bool ignore_invalid_symbols =
false,
435 typename ValueType =
double,
438 typename SymbolicType>
464 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
491 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
526 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
553 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
592 template <
bool ignore_invalid_symbols =
false,
595 typename ExpressionType,
628 template <
bool ignore_invalid_symbols =
false,
631 typename ExpressionType,
665 template <
int rank,
int dim>
689 template <
int rank,
int dim>
720 template <
typename ValueType,
int rank,
int dim>
752 template <
typename ValueType,
int rank,
int dim>
780 make_rank_4_tensor_indices(
const unsigned int idx_i,
781 const unsigned int idx_j)
794 template <
int rank_1,
int rank_2>
800 for (
unsigned int i = 0; i < rank_1; ++i)
801 indices_out[i] = indices_1[i];
802 for (
unsigned int j = 0; j < rank_2; ++j)
803 indices_out[rank_1 + j] = indices_2[j];
824 template <
int rank,
int dim,
typename ValueType>
833 template <
int rank,
int dim,
typename ValueType>
839 rank == 0 || rank == 2,
840 "Querying symmetric component for non rank-2 symmetric tensor index is not allowed.");
845 template <
int dim,
typename ValueType>
850 return table_indices[0] != table_indices[1];
855 typename ValueType = Expression,
856 template <
int,
int,
typename>
class TensorType>
857 TensorType<0, dim, ValueType>
858 scalar_diff_tensor(
const ValueType & func,
859 const TensorType<0, dim, ValueType> &op)
867 typename ValueType = Expression,
868 template <
int,
int,
typename>
class TensorType>
869 TensorType<rank, dim, ValueType>
870 scalar_diff_tensor(
const ValueType & func,
871 const TensorType<rank, dim, ValueType> &op)
873 TensorType<rank, dim, ValueType> out;
874 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
877 out.unrolled_to_component_indices(i));
880 if (is_symmetric_component(indices, op))
890 typename ValueType = Expression,
891 template <
int,
int,
typename>
class TensorType>
892 TensorType<rank, dim, ValueType>
893 tensor_diff_tensor(
const TensorType<0, dim, ValueType> & func,
894 const TensorType<rank, dim, ValueType> &op)
896 TensorType<rank, dim, ValueType> out;
897 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
900 out.unrolled_to_component_indices(i));
903 if (is_symmetric_component(indices, op))
912 typename ValueType = Expression,
913 template <
int,
int,
typename>
class TensorType>
914 TensorType<rank, dim, ValueType>
915 tensor_diff_scalar(
const TensorType<rank, dim, ValueType> &funcs,
916 const ValueType & op)
918 TensorType<rank, dim, ValueType> out;
919 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
922 out.unrolled_to_component_indices(i));
932 typename ValueType = Expression,
933 template <
int,
int,
typename>
class TensorType>
934 TensorType<rank, dim, ValueType>
935 tensor_diff_tensor(
const TensorType<rank, dim, ValueType> &funcs,
936 const TensorType<0, dim, ValueType> & op)
938 TensorType<rank, dim, ValueType> out;
939 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
942 out.unrolled_to_component_indices(i));
950 template <
int rank_1,
953 typename ValueType = Expression,
954 template <
int,
int,
typename>
class TensorType>
955 TensorType<rank_1 + rank_2, dim, ValueType>
956 tensor_diff_tensor(
const TensorType<rank_1, dim, ValueType> &funcs,
957 const TensorType<rank_2, dim, ValueType> &op)
959 TensorType<rank_1 + rank_2, dim, ValueType> out;
960 for (
unsigned int i = 0; i < funcs.n_independent_components; ++i)
963 funcs.unrolled_to_component_indices(i));
964 for (
unsigned int j = 0; j < op.n_independent_components; ++j)
967 op.unrolled_to_component_indices(j));
969 concatenate_indices(indices_i, indices_j);
974 if (is_symmetric_component(indices_j, op))
975 out[indices_out] *= 0.5;
986 template <
int rank_1,
989 typename ValueType = Expression,
990 template <
int,
int,
typename>
class TensorType_1,
991 template <
int,
int,
typename>
class TensorType_2>
993 tensor_diff_tensor(
const TensorType_1<rank_1, dim, ValueType> &funcs,
994 const TensorType_2<rank_2, dim, ValueType> &op)
997 for (
unsigned int i = 0; i < funcs.n_independent_components; ++i)
1000 funcs.unrolled_to_component_indices(i));
1001 for (
unsigned int j = 0; j < op.n_independent_components; ++j)
1004 op.unrolled_to_component_indices(j));
1006 concatenate_indices(indices_i, indices_j);
1011 if (is_symmetric_component(indices_j, op))
1012 out[indices_out] *= 0.5;
1015 if (std::is_same<TensorType_1<rank_1, dim, ValueType>,
1020 concatenate_indices(transpose_indices(indices_i),
1022 out[indices_out_t] = out[indices_out];
1024 else if (std::is_same<TensorType_2<rank_2, dim, ValueType>,
1029 concatenate_indices(indices_i,
1030 transpose_indices(indices_j));
1031 out[indices_out_t] = out[indices_out];
1038 "Expect mixed tensor differentiation to have at least "
1039 "one component stemming from a symmetric tensor."));
1049 template <
int rank,
int dim>
1054 return internal::scalar_diff_tensor(func, op);
1058 template <
int rank,
int dim>
1063 return internal::scalar_diff_tensor(func, op);
1067 template <
int rank,
int dim>
1072 return internal::scalar_diff_tensor(func, op);
1076 template <
int rank,
int dim>
1083 const Expression tmp = func;
1084 return internal::scalar_diff_tensor(tmp, op);
1088 template <
int rank,
int dim>
1091 const Expression & op)
1093 return internal::tensor_diff_scalar(symbol_tensor, op);
1097 template <
int rank,
int dim>
1102 return internal::tensor_diff_scalar(symbol_tensor, op);
1106 template <
int rank,
int dim>
1109 const Expression & op)
1111 return internal::tensor_diff_scalar(symbol_tensor, op);
1115 template <
int rank,
int dim>
1120 return internal::tensor_diff_scalar(symbol_tensor, op);
1124 template <
int rank_1,
int rank_2,
int dim>
1129 return internal::tensor_diff_tensor(symbol_tensor, op);
1133 template <
int rank_1,
int rank_2,
int dim>
1138 return internal::tensor_diff_tensor(symbol_tensor, op);
1142 template <
int rank_1,
int rank_2,
int dim>
1147 return internal::tensor_diff_tensor(symbol_tensor, op);
1151 template <
int rank_1,
int rank_2,
int dim>
1156 return internal::tensor_diff_tensor(symbol_tensor, op);
1165 template <
typename SymbolicType,
1169 template <
int,
int,
typename>
class TensorType>
1171 set_tensor_value_in_symbol_map(
1173 const TensorType<rank, dim, SymbolicType> &symbol_tensor,
1174 const TensorType<rank, dim, ValueType> & value_tensor)
1176 TensorType<rank, dim, Expression> out;
1177 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1180 out.unrolled_to_component_indices(i));
1182 symbol_tensor[indices],
1183 value_tensor[indices]);
1188 template <
typename SymbolicType,
typename ValueType,
int dim>
1190 set_tensor_value_in_symbol_map(
1196 for (
unsigned int i = 0;
1197 i < SymmetricTensor<2, dim>::n_independent_components;
1199 for (
unsigned int j = 0;
1200 j < SymmetricTensor<2, dim>::n_independent_components;
1204 make_rank_4_tensor_indices<dim>(i, j);
1206 symbol_tensor[indices],
1207 value_tensor[indices]);
1213 template <
bool ignore_invalid_symbols,
1217 typename SymbolicType>
1223 add_to_substitution_map<ignore_invalid_symbols>(
1228 template <
bool ignore_invalid_symbols,
1232 typename SymbolicType>
1239 add_to_substitution_map<ignore_invalid_symbols>(
1244 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
1257 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
1273 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
1285 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
1304 typename ExpressionType,
1306 template <
int,
int,
typename>
class TensorType>
1307 std::vector<std::pair<ExpressionType, ValueType>>
1308 make_tensor_entries_for_substitution_map(
1309 const TensorType<rank, dim, ExpressionType> &symbol_tensor,
1310 const TensorType<rank, dim, ValueType> & value_tensor)
1312 std::vector<std::pair<ExpressionType, ValueType>> symbol_values;
1313 for (
unsigned int i = 0; i < symbol_tensor.n_independent_components;
1317 symbol_tensor.unrolled_to_component_indices(i));
1318 symbol_values.push_back(
1319 std::make_pair(symbol_tensor[indices], value_tensor[indices]));
1321 return symbol_values;
1325 template <
int dim,
typename ExpressionType,
typename ValueType>
1326 std::vector<std::pair<ExpressionType, ValueType>>
1327 make_tensor_entries_for_substitution_map(
1331 const ExpressionType &expression = symbol_tensor;
1332 const ValueType &
value = value_tensor;
1333 return {std::make_pair(expression,
value)};
1337 template <
int dim,
typename ExpressionType,
typename ValueType>
1338 std::vector<std::pair<ExpressionType, ValueType>>
1339 make_tensor_entries_for_substitution_map(
1343 std::vector<std::pair<ExpressionType, ValueType>> symbol_values;
1344 for (
unsigned int i = 0;
1345 i < SymmetricTensor<2, dim>::n_independent_components;
1347 for (
unsigned int j = 0;
1348 j < SymmetricTensor<2, dim>::n_independent_components;
1352 make_rank_4_tensor_indices<dim>(i, j);
1353 symbol_values.push_back(
1354 std::make_pair(symbol_tensor[indices], value_tensor[indices]));
1356 return symbol_values;
1361 template <
bool ignore_invalid_symbols,
1364 typename ExpressionType,
1372 add_to_substitution_map<ignore_invalid_symbols>(
1374 internal::make_tensor_entries_for_substitution_map(symbol_tensor,
1379 template <
bool ignore_invalid_symbols,
1382 typename ExpressionType,
1390 add_to_substitution_map<ignore_invalid_symbols>(
1392 internal::make_tensor_entries_for_substitution_map(symbol_tensor,
1404 template <
int,
int,
typename>
class TensorType>
1405 TensorType<rank, dim, Expression>
1407 const TensorType<rank, dim, Expression> &expression_tensor,
1410 TensorType<rank, dim, Expression> out;
1411 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1414 out.unrolled_to_component_indices(i));
1427 const Expression &expression = expression_tensor;
1439 for (
unsigned int i = 0;
1440 i < SymmetricTensor<2, dim>::n_independent_components;
1442 for (
unsigned int j = 0;
1443 j < SymmetricTensor<2, dim>::n_independent_components;
1447 make_rank_4_tensor_indices<dim>(i, j);
1455 template <
typename ValueType,
1458 template <
int,
int,
typename>
class TensorType>
1459 TensorType<rank, dim, ValueType>
1460 substitute_and_evaluate_tensor(
1461 const TensorType<rank, dim, Expression> &expression_tensor,
1464 TensorType<rank, dim, ValueType> out;
1465 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1468 out.unrolled_to_component_indices(i));
1470 substitute_and_evaluate<ValueType>(expression_tensor[indices],
1477 template <
typename ValueType,
int dim>
1479 substitute_and_evaluate_tensor(
1483 const Expression &expression = expression_tensor;
1488 template <
typename ValueType,
int dim>
1490 substitute_and_evaluate_tensor(
1495 for (
unsigned int i = 0;
1496 i < SymmetricTensor<2, dim>::n_independent_components;
1498 for (
unsigned int j = 0;
1499 j < SymmetricTensor<2, dim>::n_independent_components;
1503 make_rank_4_tensor_indices<dim>(i, j);
1505 substitute_and_evaluate<ValueType>(expression_tensor[indices],
1513 template <
int rank,
int dim>
1522 template <
int rank,
int dim>
1531 template <
typename ValueType,
int rank,
int dim>
1537 return internal::substitute_and_evaluate_tensor<ValueType>(
1542 template <
typename ValueType,
int rank,
int dim>
1548 return internal::substitute_and_evaluate_tensor<ValueType>(
1561 #endif // DEAL_II_WITH_SYMENGINE