15#ifndef dealii_differentiation_sd_symengine_tensor_operations_h
16#define dealii_differentiation_sd_symengine_tensor_operations_h
20#ifdef DEAL_II_WITH_SYMENGINE
84 template <
int rank,
int dim>
107 template <
int rank,
int dim>
155 template <
int rank,
int dim>
180 template <
int rank,
int dim>
183 const std::string &symbol,
202 template <
int rank,
int dim>
215 template <
int rank,
int dim>
229 template <
int rank,
int dim>
243 template <
int rank,
int dim>
257 template <
int rank,
int dim>
271 template <
int rank,
int dim>
286 template <
int rank,
int dim>
302 template <
int rank,
int dim>
317 template <
int rank_1,
int rank_2,
int dim>
334 template <
int rank_1,
int rank_2,
int dim>
349 template <
int rank_1,
int rank_2,
int dim>
364 template <
int rank_1,
int rank_2,
int dim>
400 template <
bool ignore_invalid_symbols =
false,
401 typename ValueType = double,
404 typename SymbolicType>
433 template <
bool ignore_invalid_symbols =
false,
434 typename ValueType = double,
437 typename SymbolicType>
463 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
490 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
525 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
552 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
591 template <
bool ignore_invalid_symbols =
false,
594 typename ExpressionType,
627 template <
bool ignore_invalid_symbols =
false,
630 typename ExpressionType,
664 template <
int rank,
int dim>
688 template <
int rank,
int dim>
719 template <
typename ValueType,
int rank,
int dim>
751 template <
typename ValueType,
int rank,
int dim>
779 make_rank_4_tensor_indices(
const unsigned int idx_i,
780 const unsigned int idx_j)
793 template <
int rank_1,
int rank_2>
799 for (
unsigned int i = 0; i < rank_1; ++i)
800 indices_out[i] = indices_1[i];
801 for (
unsigned int j = 0; j < rank_2; ++j)
802 indices_out[rank_1 + j] = indices_2[j];
823 template <
int rank,
int dim,
typename ValueType>
832 template <
int rank,
int dim,
typename ValueType>
838 rank == 0 || rank == 2,
839 "Querying symmetric component for non rank-2 symmetric tensor index is not allowed.");
844 template <
int dim,
typename ValueType>
849 return table_indices[0] != table_indices[1];
854 typename ValueType = Expression,
855 template <
int,
int,
typename>
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>
870 TensorType<rank, dim, ValueType>
871 scalar_diff_tensor(
const ValueType &func,
872 const TensorType<rank, dim, ValueType> &op)
874 TensorType<rank, dim, ValueType> out;
875 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
878 out.unrolled_to_component_indices(i));
881 if (is_symmetric_component(indices, op))
891 typename ValueType = Expression,
892 template <
int,
int,
typename>
894 TensorType<rank, dim, ValueType>
895 tensor_diff_tensor(
const TensorType<0, dim, ValueType> &func,
896 const TensorType<rank, dim, ValueType> &op)
898 TensorType<rank, dim, ValueType> out;
899 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
902 out.unrolled_to_component_indices(i));
905 if (is_symmetric_component(indices, op))
914 typename ValueType = Expression,
915 template <
int,
int,
typename>
917 TensorType<rank, dim, ValueType>
918 tensor_diff_scalar(
const TensorType<rank, dim, ValueType> &funcs,
921 TensorType<rank, dim, ValueType> out;
922 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
925 out.unrolled_to_component_indices(i));
935 typename ValueType = Expression,
936 template <
int,
int,
typename>
938 TensorType<rank, dim, ValueType>
939 tensor_diff_tensor(
const TensorType<rank, dim, ValueType> &funcs,
940 const TensorType<0, dim, ValueType> &op)
942 TensorType<rank, dim, ValueType> out;
943 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
946 out.unrolled_to_component_indices(i));
954 template <
int rank_1,
957 typename ValueType = Expression,
958 template <
int,
int,
typename>
960 TensorType<rank_1 + rank_2, dim, ValueType>
961 tensor_diff_tensor(
const TensorType<rank_1, dim, ValueType> &funcs,
962 const TensorType<rank_2, dim, ValueType> &op)
964 TensorType<rank_1 + rank_2, dim, ValueType> out;
965 for (
unsigned int i = 0; i < funcs.n_independent_components; ++i)
968 funcs.unrolled_to_component_indices(i));
969 for (
unsigned int j = 0; j < op.n_independent_components; ++j)
972 op.unrolled_to_component_indices(j));
974 concatenate_indices(indices_i, indices_j);
979 if (is_symmetric_component(indices_j, op))
980 out[indices_out] *= 0.5;
991 template <
int rank_1,
994 typename ValueType = Expression,
995 template <
int,
int,
typename>
997 template <
int,
int,
typename>
1000 tensor_diff_tensor(
const TensorType_1<rank_1, dim, ValueType> &funcs,
1001 const TensorType_2<rank_2, dim, ValueType> &op)
1004 for (
unsigned int i = 0; i < funcs.n_independent_components; ++i)
1007 funcs.unrolled_to_component_indices(i));
1008 for (
unsigned int j = 0; j < op.n_independent_components; ++j)
1011 op.unrolled_to_component_indices(j));
1013 concatenate_indices(indices_i, indices_j);
1018 if (is_symmetric_component(indices_j, op))
1019 out[indices_out] *= 0.5;
1023 TensorType_1<rank_1, dim, ValueType>,
1027 concatenate_indices(transpose_indices(indices_i),
1029 out[indices_out_t] = out[indices_out];
1031 else if (std::is_same_v<
1032 TensorType_2<rank_2, dim, ValueType>,
1037 concatenate_indices(indices_i,
1038 transpose_indices(indices_j));
1039 out[indices_out_t] = out[indices_out];
1046 "Expect mixed tensor differentiation to have at least "
1047 "one component stemming from a symmetric tensor."));
1057 template <
int rank,
int dim>
1062 return internal::scalar_diff_tensor(func, op);
1066 template <
int rank,
int dim>
1071 return internal::scalar_diff_tensor(func, op);
1075 template <
int rank,
int dim>
1080 return internal::scalar_diff_tensor(func, op);
1084 template <
int rank,
int dim>
1091 const Expression tmp = func;
1092 return internal::scalar_diff_tensor(tmp, op);
1096 template <
int rank,
int dim>
1099 const Expression &op)
1101 return internal::tensor_diff_scalar(symbol_tensor, op);
1105 template <
int rank,
int dim>
1110 return internal::tensor_diff_scalar(symbol_tensor, op);
1114 template <
int rank,
int dim>
1117 const Expression &op)
1119 return internal::tensor_diff_scalar(symbol_tensor, op);
1123 template <
int rank,
int dim>
1128 return internal::tensor_diff_scalar(symbol_tensor, op);
1132 template <
int rank_1,
int rank_2,
int dim>
1137 return internal::tensor_diff_tensor(symbol_tensor, op);
1141 template <
int rank_1,
int rank_2,
int dim>
1146 return internal::tensor_diff_tensor(symbol_tensor, op);
1150 template <
int rank_1,
int rank_2,
int dim>
1155 return internal::tensor_diff_tensor(symbol_tensor, op);
1159 template <
int rank_1,
int rank_2,
int dim>
1164 return internal::tensor_diff_tensor(symbol_tensor, op);
1173 template <
typename SymbolicType,
1177 template <
int,
int,
typename>
1180 set_tensor_value_in_symbol_map(
1182 const TensorType<rank, dim, SymbolicType> &symbol_tensor,
1183 const TensorType<rank, dim, ValueType> &value_tensor)
1185 TensorType<rank, dim, Expression> out;
1186 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1189 out.unrolled_to_component_indices(i));
1191 symbol_tensor[indices],
1192 value_tensor[indices]);
1197 template <
typename SymbolicType,
typename ValueType,
int dim>
1199 set_tensor_value_in_symbol_map(
1205 for (
unsigned int i = 0;
1206 i < SymmetricTensor<2, dim>::n_independent_components;
1208 for (
unsigned int j = 0;
1209 j < SymmetricTensor<2, dim>::n_independent_components;
1213 make_rank_4_tensor_indices<dim>(i, j);
1215 symbol_tensor[indices],
1216 value_tensor[indices]);
1222 template <
bool ignore_invalid_symbols,
1226 typename SymbolicType>
1232 add_to_substitution_map<ignore_invalid_symbols>(
1237 template <
bool ignore_invalid_symbols,
1241 typename SymbolicType>
1248 add_to_substitution_map<ignore_invalid_symbols>(
1253 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
1260 internal::set_tensor_value_in_symbol_map(substitution_map,
1266 template <
int rank,
int dim,
typename SymbolicType,
typename ValueType>
1273 internal::set_tensor_value_in_symbol_map(substitution_map,
1282 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
1294 template <
int rank,
int dim,
typename ExpressionType,
typename ValueType>
1313 typename ExpressionType,
1315 template <
int,
int,
typename>
1317 std::vector<std::pair<ExpressionType, ValueType>>
1318 make_tensor_entries_for_substitution_map(
1319 const TensorType<rank, dim, ExpressionType> &symbol_tensor,
1320 const TensorType<rank, dim, ValueType> &value_tensor)
1322 std::vector<std::pair<ExpressionType, ValueType>> symbol_values;
1323 for (
unsigned int i = 0; i < symbol_tensor.n_independent_components;
1327 symbol_tensor.unrolled_to_component_indices(i));
1328 symbol_values.push_back(
1329 std::make_pair(symbol_tensor[indices], value_tensor[indices]));
1331 return symbol_values;
1335 template <
int dim,
typename ExpressionType,
typename ValueType>
1336 std::vector<std::pair<ExpressionType, ValueType>>
1337 make_tensor_entries_for_substitution_map(
1341 const ExpressionType &expression = symbol_tensor;
1342 const ValueType &
value = value_tensor;
1343 return {std::make_pair(expression, value)};
1347 template <
int dim,
typename ExpressionType,
typename ValueType>
1348 std::vector<std::pair<ExpressionType, ValueType>>
1349 make_tensor_entries_for_substitution_map(
1353 std::vector<std::pair<ExpressionType, ValueType>> symbol_values;
1354 for (
unsigned int i = 0;
1355 i < SymmetricTensor<2, dim>::n_independent_components;
1357 for (
unsigned int j = 0;
1358 j < SymmetricTensor<2, dim>::n_independent_components;
1362 make_rank_4_tensor_indices<dim>(i, j);
1363 symbol_values.push_back(
1364 std::make_pair(symbol_tensor[indices], value_tensor[indices]));
1366 return symbol_values;
1371 template <
bool ignore_invalid_symbols,
1374 typename ExpressionType,
1382 add_to_substitution_map<ignore_invalid_symbols>(
1384 internal::make_tensor_entries_for_substitution_map(symbol_tensor,
1389 template <
bool ignore_invalid_symbols,
1392 typename ExpressionType,
1400 add_to_substitution_map<ignore_invalid_symbols>(
1402 internal::make_tensor_entries_for_substitution_map(symbol_tensor,
1414 template <
int,
int,
typename>
1416 TensorType<rank, dim, Expression>
1418 const TensorType<rank, dim, Expression> &expression_tensor,
1421 TensorType<rank, dim, Expression> out;
1422 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1425 out.unrolled_to_component_indices(i));
1427 substitute(expression_tensor[indices], substitution_map);
1438 const Expression &expression = expression_tensor;
1439 return substitute(expression, substitution_map);
1450 for (
unsigned int i = 0;
1451 i < SymmetricTensor<2, dim>::n_independent_components;
1453 for (
unsigned int j = 0;
1454 j < SymmetricTensor<2, dim>::n_independent_components;
1458 make_rank_4_tensor_indices<dim>(i, j);
1460 substitute(expression_tensor[indices], substitution_map);
1466 template <
typename ValueType,
1469 template <
int,
int,
typename>
1471 TensorType<rank, dim, ValueType>
1472 substitute_and_evaluate_tensor(
1473 const TensorType<rank, dim, Expression> &expression_tensor,
1476 TensorType<rank, dim, ValueType> out;
1477 for (
unsigned int i = 0; i < out.n_independent_components; ++i)
1480 out.unrolled_to_component_indices(i));
1482 substitute_and_evaluate<ValueType>(expression_tensor[indices],
1489 template <
typename ValueType,
int dim>
1491 substitute_and_evaluate_tensor(
1495 const Expression &expression = expression_tensor;
1496 return substitute_and_evaluate<ValueType>(expression, substitution_map);
1500 template <
typename ValueType,
int dim>
1502 substitute_and_evaluate_tensor(
1507 for (
unsigned int i = 0;
1508 i < SymmetricTensor<2, dim>::n_independent_components;
1510 for (
unsigned int j = 0;
1511 j < SymmetricTensor<2, dim>::n_independent_components;
1515 make_rank_4_tensor_indices<dim>(i, j);
1517 substitute_and_evaluate<ValueType>(expression_tensor[indices],
1525 template <
int rank,
int dim>
1530 return internal::substitute_tensor(expression_tensor, substitution_map);
1534 template <
int rank,
int dim>
1539 return internal::substitute_tensor(expression_tensor, substitution_map);
1543 template <
typename ValueType,
int rank,
int dim>
1549 return internal::substitute_and_evaluate_tensor<ValueType>(
1550 expression_tensor, substitution_map);
1554 template <
typename ValueType,
int rank,
int dim>
1560 return internal::substitute_and_evaluate_tensor<ValueType>(
1561 expression_tensor, substitution_map);
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
void set_value_in_symbol_map(types::substitution_map &substitution_map, const SymEngine::RCP< const SymEngine::Basic > &symbol, const SymEngine::RCP< const SymEngine::Basic > &value)
std::map< SD::Expression, SD::Expression, internal::ExpressionKeyLess > substitution_map
Tensor< rank, dim, Expression > make_tensor_of_symbols(const std::string &symbol)
Expression differentiate(const Expression &f, const Expression &x)
ValueType substitute_and_evaluate(const Expression &expression, const types::substitution_map &substitution_map)
SymmetricTensor< rank, dim, Expression > make_symmetric_tensor_of_symbols(const std::string &symbol)
Tensor< 1, dim, Expression > make_vector_of_symbolic_functions(const std::string &symbol, const types::substitution_map &arguments)
void set_value_in_symbol_map(types::substitution_map &substitution_map, const Expression &symbol, const Expression &value)
SymmetricTensor< rank, dim, Expression > make_symmetric_tensor_of_symbolic_functions(const std::string &symbol, const types::substitution_map &arguments)
void add_to_symbol_map(types::substitution_map &symbol_map, const Expression &symbol)
Tensor< 1, dim, Expression > make_vector_of_symbols(const std::string &symbol)
void add_to_substitution_map(types::substitution_map &substitution_map, const Expression &symbol, const Expression &value)
Expression substitute(const Expression &expression, const types::substitution_map &substitution_map)
Tensor< rank, dim, Expression > make_tensor_of_symbolic_functions(const std::string &symbol, const types::substitution_map &arguments)
types::substitution_map make_substitution_map(const Expression &symbol, const Expression &value)