]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add functions to perform SD tensor differentation
authorJean-Paul Pelteret <jppelteret@gmail.com>
Mon, 22 Apr 2019 07:59:18 +0000 (09:59 +0200)
committerJean-Paul Pelteret <jppelteret@gmail.com>
Tue, 23 Apr 2019 15:50:17 +0000 (17:50 +0200)
include/deal.II/differentiation/sd/symengine_tensor_operations.h

index d8ba72018094aa3f6c25923b624ac90696cd6afa..b14f120eafe558ebc007636a65b8110caf7bdad7 100644 (file)
@@ -185,9 +185,574 @@ namespace Differentiation
 
     //@}
 
+    /**
+     * @name Symbolic differentiation
+     */
+    //@{
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * scalar @p f with respect to the tensor @p T.
+     *
+     * @param[in] f A scalar symbolic function or (dependent) expression.
+     * @param[in] T A tensor of symbolic (independent) variables.
+     * @return The tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial f}{\partial \mathbf{T}}$.
+     */
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Expression &f, const Tensor<rank, dim, Expression> &T);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * scalar @p f with respect to the symmetric tensor @p S.
+     *
+     * @param[in] f A scalar symbolic function or (dependent) expression.
+     * @param[in] S A symmetric tensor of symbolic (independent) variables.
+     * @return The symmetric tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial f}{\partial \mathbf{S}}$.
+     */
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const Expression &                            f,
+                  const SymmetricTensor<rank, dim, Expression> &S);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * rank-0 tensor (or scalar) @p f with respect to the tensor @p T.
+     *
+     * @param[in] f A rank-0 tensor symbolic function or (dependent) expression.
+     * @param[in] T A tensor of symbolic (independent) variables.
+     * @return The tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial f}{\partial \mathbf{T}}$.
+     */
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Tensor<0, dim, Expression> &   f,
+                  const Tensor<rank, dim, Expression> &T);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * rank-0 tensor (or scalar) @p f with respect to the symmetric tensor @p S.
+     *
+     * @param[in] f A rank-0 tensor symbolic function or (dependent) expression.
+     * @param[in] S A symmetric tensor of symbolic (independent) variables.
+     * @return The symmetric tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial f}{\partial \mathbf{S}}$.
+     */
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const Tensor<0, dim, Expression> &            f,
+                  const SymmetricTensor<rank, dim, Expression> &S);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * tensor @p T with respect to the scalar @p x.
+     *
+     * @param[in] T A tensor of symbolic functions or (dependent) expressions.
+     * @param[in] x A scalar symbolic (independent) variable.
+     * @return The tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial \mathbf{T}}{\partial x}$.
+     */
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Tensor<rank, dim, Expression> &T, const Expression &x);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * symmetric tensor @p S with respect to the scalar @p x.
+     *
+     * @param[in] S A symmetric tensor of symbolic functions or (dependent)
+     *            expressions.
+     * @param[in] x A scalar symbolic (independent) variable.
+     * @return The symmetric tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial \mathbf{S}}{\partial x}$.
+     */
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const SymmetricTensor<rank, dim, Expression> &S,
+                  const Expression &                            x);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * tensor @p T with respect to the rank-0 tensor @p x.
+     *
+     * @param[in] T A tensor of symbolic functions or (dependent) expressions.
+     * @param[in] x A rank-0 tensor symbolic symbolic (independent) variable.
+     * @return The tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial \mathbf{T}}{\partial x}$.
+     */
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Tensor<rank, dim, Expression> &T,
+                  const Tensor<0, dim, Expression> &   x);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * symmetric tensor @p S with respect to the rank-0 tensor @p x.
+     *
+     * @param[in] S A symmetric tensor of symbolic functions or (dependent)
+     *            expressions.
+     * @param[in] x A rank-0 tensor symbolic symbolic (independent) variable.
+     * @return The symmetric tensor of symbolic functions or expressions representing
+     *         the result $\frac{\partial \mathbf{S}}{\partial x}$.
+     */
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const SymmetricTensor<rank, dim, Expression> &S,
+                  const Tensor<0, dim, Expression> &            x);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * tensor @p T1 with respect to the tensor @p T2.
+     *
+     * @param[in] T1 A tensor of symbolic functions or (dependent) expressions.
+     * @param[in] T2 A tensor symbolic symbolic (independent) variables.
+     * @return The tensor of symbolic functions or variables representing
+     *         the result $\frac{\partial \mathbf{T}_{1}}{\partial
+     * \mathbf{T}_{2}}$.
+     */
+    template <int rank_1, int rank_2, int dim>
+    Tensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const Tensor<rank_1, dim, Expression> &T1,
+                  const Tensor<rank_2, dim, Expression> &T2);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * symmetric tensor @p S1 with respect to the symmetric tensor @p S2.
+     *
+     * @param[in] S1 A symmetric tensor of symbolic functions or (dependent)
+     *            expressions.
+     * @param[in] S2 A symmetric tensor symbolic symbolic (independent)
+     *            variables.
+     * @return The symmetric tensor of symbolic functions or variables representing
+     *         the result $\frac{\partial \mathbf{S}_{1}}{\partial
+     * \mathbf{S}_{2}}$.
+     */
+    template <int rank_1, int rank_2, int dim>
+    SymmetricTensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const SymmetricTensor<rank_1, dim, Expression> &S1,
+                  const SymmetricTensor<rank_2, dim, Expression> &S2);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * tensor @p T with respect to the symmetric tensor @p S.
+     *
+     * @param[in] T A tensor of symbolic functions or (dependent) expressions.
+     * @param[in] S A symmetric tensor symbolic symbolic (independent)
+     *            variables.
+     * @return The tensor of symbolic functions or variables representing
+     *         the result $\frac{\partial \mathbf{T}}{\partial \mathbf{S}}$.
+     */
+    template <int rank_1, int rank_2, int dim>
+    Tensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const Tensor<rank_1, dim, Expression> &         T,
+                  const SymmetricTensor<rank_2, dim, Expression> &S);
+
+    /**
+     * Return the symbolic result of computing the partial derivative of the
+     * symmetric tensor @p S with respect to the tensor @p T.
+     *
+     * @param[in] S A symmetric tensor of symbolic functions or (dependent)
+     *            expressions.
+     * @param[in] T A tensor symbolic symbolic (independent) variables.
+     * @return The tensor of symbolic functions or variables representing
+     *         the result $\frac{\partial \mathbf{S}}{\partial \mathbf{T}}$.
+     */
+    template <int rank_1, int rank_2, int dim>
+    Tensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const SymmetricTensor<rank_1, dim, Expression> &S,
+                  const Tensor<rank_2, dim, Expression> &         T);
+
+    //@}
+
+  } // namespace SD
+} // namespace Differentiation
+
+
+/* -------------------- inline and template functions ------------------ */
+
+
+#  ifndef DOXYGEN
+
+namespace Differentiation
+{
+  namespace SD
+  {
+    // --- Symbolic differentiation ---
+
+
+    namespace internal
+    {
+      template <int rank_1, int rank_2>
+      TableIndices<rank_1 + rank_2>
+      concatenate_indices(const TableIndices<rank_1> &indices_1,
+                          const TableIndices<rank_2> &indices_2)
+      {
+        TableIndices<rank_1 + rank_2> indices_out;
+        for (unsigned int i = 0; i < rank_1; ++i)
+          indices_out[i] = indices_1[i];
+        for (unsigned int j = 0; j < rank_2; ++j)
+          indices_out[rank_1 + j] = indices_2[j];
+        return indices_out;
+      }
+
+
+      template <int rank>
+      TableIndices<rank>
+      transpose_indices(const TableIndices<rank> &indices)
+      {
+        return indices;
+      }
+
+
+      template <>
+      inline TableIndices<2>
+      transpose_indices(const TableIndices<2> &indices)
+      {
+        return TableIndices<2>(indices[1], indices[0]);
+      }
+
+
+      template <int rank, int dim, typename ValueType>
+      bool
+      is_symmetric_component(const TableIndices<rank> &,
+                             const Tensor<rank, dim, ValueType> &)
+      {
+        return false;
+      }
+
+
+      template <int rank, int dim, typename ValueType>
+      bool
+      is_symmetric_component(const TableIndices<rank> &,
+                             const SymmetricTensor<rank, dim, ValueType> &)
+      {
+        static_assert(
+          rank == 0 || rank == 2,
+          "Querying symmetric component for non rank-2 symmetric tensor index is not allowed.");
+        return false;
+      }
+
+
+      template <int dim, typename ValueType>
+      bool
+      is_symmetric_component(const TableIndices<2> &table_indices,
+                             const SymmetricTensor<2, dim, ValueType> &)
+      {
+        return table_indices[0] != table_indices[1];
+      }
+
+
+      template <int dim,
+                typename ValueType = Expression,
+                template <int, int, typename> class TensorType>
+      TensorType<0, dim, ValueType>
+      scalar_diff_tensor(const ValueType &                    func,
+                         const TensorType<0, dim, ValueType> &op)
+      {
+        return differentiate(func, op);
+      }
+
+
+      template <int rank,
+                int dim,
+                typename ValueType = Expression,
+                template <int, int, typename> class TensorType>
+      TensorType<rank, dim, ValueType>
+      scalar_diff_tensor(const ValueType &                       func,
+                         const TensorType<rank, dim, ValueType> &op)
+      {
+        TensorType<rank, dim, ValueType> out;
+        for (unsigned int i = 0; i < out.n_independent_components; ++i)
+          {
+            const TableIndices<rank> indices(
+              out.unrolled_to_component_indices(i));
+            out[indices] = differentiate(func, op[indices]);
+
+            if (is_symmetric_component(indices, op))
+              out[indices] *= 0.5;
+          }
+        return out;
+      }
+
+
+      // Specialization for rank-0 tensor
+      template <int rank,
+                int dim,
+                typename ValueType = Expression,
+                template <int, int, typename> class TensorType>
+      TensorType<rank, dim, ValueType>
+      tensor_diff_tensor(const TensorType<0, dim, ValueType> &   func,
+                         const TensorType<rank, dim, ValueType> &op)
+      {
+        TensorType<rank, dim, ValueType> out;
+        for (unsigned int i = 0; i < out.n_independent_components; ++i)
+          {
+            const TableIndices<rank> indices(
+              out.unrolled_to_component_indices(i));
+            out[indices] = differentiate(func, op[indices]);
+
+            if (is_symmetric_component(indices, op))
+              out[indices] *= 0.5;
+          }
+        return out;
+      }
+
+
+      template <int rank,
+                int dim,
+                typename ValueType = Expression,
+                template <int, int, typename> class TensorType>
+      TensorType<rank, dim, ValueType>
+      tensor_diff_scalar(const TensorType<rank, dim, ValueType> &funcs,
+                         const ValueType &                       op)
+      {
+        TensorType<rank, dim, ValueType> out;
+        for (unsigned int i = 0; i < out.n_independent_components; ++i)
+          {
+            const TableIndices<rank> indices(
+              out.unrolled_to_component_indices(i));
+            out[indices] = differentiate(funcs[indices], op);
+          }
+        return out;
+      }
+
+
+      // Specialization for rank-0 tensor
+      template <int rank,
+                int dim,
+                typename ValueType = Expression,
+                template <int, int, typename> class TensorType>
+      TensorType<rank, dim, ValueType>
+      tensor_diff_tensor(const TensorType<rank, dim, ValueType> &funcs,
+                         const TensorType<0, dim, ValueType> &   op)
+      {
+        TensorType<rank, dim, ValueType> out;
+        for (unsigned int i = 0; i < out.n_independent_components; ++i)
+          {
+            const TableIndices<rank> indices(
+              out.unrolled_to_component_indices(i));
+            out[indices] = differentiate(funcs[indices], op);
+          }
+        return out;
+      }
+
+
+      // For either symmetric or normal tensors
+      template <int rank_1,
+                int rank_2,
+                int dim,
+                typename ValueType = Expression,
+                template <int, int, typename> class TensorType>
+      TensorType<rank_1 + rank_2, dim, ValueType>
+      tensor_diff_tensor(const TensorType<rank_1, dim, ValueType> &funcs,
+                         const TensorType<rank_2, dim, ValueType> &op)
+      {
+        TensorType<rank_1 + rank_2, dim, ValueType> out;
+        for (unsigned int i = 0; i < funcs.n_independent_components; ++i)
+          {
+            const TableIndices<rank_1> indices_i(
+              funcs.unrolled_to_component_indices(i));
+            for (unsigned int j = 0; j < op.n_independent_components; ++j)
+              {
+                const TableIndices<rank_2> indices_j(
+                  op.unrolled_to_component_indices(j));
+                const TableIndices<rank_1 + rank_2> indices_out =
+                  concatenate_indices(indices_i, indices_j);
+
+                out[indices_out] =
+                  differentiate(funcs[indices_i], op[indices_j]);
+
+                if (is_symmetric_component(indices_j, op))
+                  out[indices_out] *= 0.5;
+              }
+          }
+        return out;
+      }
+
+
+      // For mixed symmetric/standard tensors
+      // The return type is always a standard tensor, since we cannot be sure
+      // that any symmetries exist in either the function tensor or the
+      // differential operator.
+      template <int rank_1,
+                int rank_2,
+                int dim,
+                typename ValueType = Expression,
+                template <int, int, typename> class TensorType_1,
+                template <int, int, typename> class TensorType_2>
+      Tensor<rank_1 + rank_2, dim, ValueType>
+      tensor_diff_tensor(const TensorType_1<rank_1, dim, ValueType> &funcs,
+                         const TensorType_2<rank_2, dim, ValueType> &op)
+      {
+        Tensor<rank_1 + rank_2, dim, ValueType> out;
+        for (unsigned int i = 0; i < funcs.n_independent_components; ++i)
+          {
+            const TableIndices<rank_1> indices_i(
+              funcs.unrolled_to_component_indices(i));
+            for (unsigned int j = 0; j < op.n_independent_components; ++j)
+              {
+                const TableIndices<rank_2> indices_j(
+                  op.unrolled_to_component_indices(j));
+                const TableIndices<rank_1 + rank_2> indices_out =
+                  concatenate_indices(indices_i, indices_j);
+
+                out[indices_out] =
+                  differentiate(funcs[indices_i], op[indices_j]);
+
+                if (is_symmetric_component(indices_j, op))
+                  out[indices_out] *= 0.5;
+
+                // TODO: Implement for SymmetricTensor<4,dim,...>
+                if (std::is_same<TensorType_1<rank_1, dim, ValueType>,
+                                 SymmetricTensor<2, dim, ValueType>>::
+                      value) // Symmetric function
+                  {
+                    const TableIndices<rank_1 + rank_2> indices_out_t =
+                      concatenate_indices(transpose_indices(indices_i),
+                                          indices_j);
+                    out[indices_out_t] = out[indices_out];
+                  }
+                else if (std::is_same<TensorType_2<rank_2, dim, ValueType>,
+                                      SymmetricTensor<2, dim, ValueType>>::
+                           value) // Symmetric operator
+                  {
+                    const TableIndices<rank_1 + rank_2> indices_out_t =
+                      concatenate_indices(indices_i,
+                                          transpose_indices(indices_j));
+                    out[indices_out_t] = out[indices_out];
+                  }
+                else
+                  {
+                    Assert(
+                      false,
+                      ExcMessage(
+                        "Expect mixed tensor differentiation to have at least "
+                        "one component stemming from a symmetric tensor."));
+                  }
+              }
+          }
+        return out;
+      }
+
+    } // namespace internal
+
+
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Expression &                   func,
+                  const Tensor<rank, dim, Expression> &op)
+    {
+      return internal::scalar_diff_tensor(func, op);
+    }
+
+
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const Expression &                            func,
+                  const SymmetricTensor<rank, dim, Expression> &op)
+    {
+      return internal::scalar_diff_tensor(func, op);
+    }
+
+
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Tensor<0, dim, Expression> &   func,
+                  const Tensor<rank, dim, Expression> &op)
+    {
+      return internal::scalar_diff_tensor(func, op);
+    }
+
+
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const Tensor<0, dim, Expression> &            func,
+                  const SymmetricTensor<rank, dim, Expression> &op)
+    {
+      // Ensure that this returns a symmetric tensor by
+      // invoking the scalar value function
+      const Expression tmp = func;
+      return internal::scalar_diff_tensor(tmp, op);
+    }
+
+
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Tensor<rank, dim, Expression> &symbol_tensor,
+                  const Expression &                   op)
+    {
+      return internal::tensor_diff_scalar(symbol_tensor, op);
+    }
+
+
+    template <int rank, int dim>
+    Tensor<rank, dim, Expression>
+    differentiate(const Tensor<rank, dim, Expression> &symbol_tensor,
+                  const Tensor<0, dim, Expression> &   op)
+    {
+      return internal::tensor_diff_scalar(symbol_tensor, op);
+    }
+
+
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const SymmetricTensor<rank, dim, Expression> &symbol_tensor,
+                  const Expression &                            op)
+    {
+      return internal::tensor_diff_scalar(symbol_tensor, op);
+    }
+
+
+    template <int rank, int dim>
+    SymmetricTensor<rank, dim, Expression>
+    differentiate(const SymmetricTensor<rank, dim, Expression> &symbol_tensor,
+                  const Tensor<0, dim, Expression> &            op)
+    {
+      return internal::tensor_diff_scalar(symbol_tensor, op);
+    }
+
+
+    template <int rank_1, int rank_2, int dim>
+    Tensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const Tensor<rank_1, dim, Expression> &symbol_tensor,
+                  const Tensor<rank_2, dim, Expression> &op)
+    {
+      return internal::tensor_diff_tensor(symbol_tensor, op);
+    }
+
+
+    template <int rank_1, int rank_2, int dim>
+    SymmetricTensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const SymmetricTensor<rank_1, dim, Expression> &symbol_tensor,
+                  const SymmetricTensor<rank_2, dim, Expression> &op)
+    {
+      return internal::tensor_diff_tensor(symbol_tensor, op);
+    }
+
+
+    template <int rank_1, int rank_2, int dim>
+    Tensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const Tensor<rank_1, dim, Expression> &         symbol_tensor,
+                  const SymmetricTensor<rank_2, dim, Expression> &op)
+    {
+      return internal::tensor_diff_tensor(symbol_tensor, op);
+    }
+
+
+    template <int rank_1, int rank_2, int dim>
+    Tensor<rank_1 + rank_2, dim, Expression>
+    differentiate(const SymmetricTensor<rank_1, dim, Expression> &symbol_tensor,
+                  const Tensor<rank_2, dim, Expression> &         op)
+    {
+      return internal::tensor_diff_tensor(symbol_tensor, op);
+    }
+
   } // namespace SD
 } // namespace Differentiation
 
+#  endif // DOXYGEN
 
 DEAL_II_NAMESPACE_CLOSE
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.