Ferrite-FEM / Ferrite-FEM/Tensors.jl
`gradient` fails for `SymmetricTensor`-valued functions of a `Vec`
- Dominant language
- Julia
- Stars
- 182
- Forks
- 40
- PR merge metrics
- No merged PRs in 30d
Description
Tensors v1.17.1, Julia 1.12.6.
`Tensors.gradient` supports functions of a `Vec` returning a scalar, a `Vec`, and a
(non-symmetric) `Tensor{2}` — but a `SymmetricTensor{2}`-valued function throws a
`MethodError` in `makemixed`.
## MWE
```julia
using Tensors
# Vec-valued: works
fv(x::Vec{2}) = Vec((x[1] * x[2], x[2]^2))
Tensors.gradient(fv, Vec((0.5, 0.5))) # 2×2 Tensor{2}, OK
# Tensor{2}-valued: works (returns a third order tensor)
ft(x::Vec{2}) = Tensor{2, 2}((x[1], x[1] * x[2], x[2], x[2]^2))
Tensors.gradient(ft, Vec((0.5, 0.5))) # 2×2×2 Tensor{3}, OK
# SymmetricTensor{2}-valued: throws
fs(x::Vec{2}) = SymmetricTensor{2, 2}((x[1], x[1] * x[2], x[2]^2))
Tensors.gradient(fs, Vec((0.5, 0.5)))
```
Output of the last call:
```
ERROR: MethodError: no method matching makemixed(::SymmetricTensor{2, 2, ForwardDiff.Dual{ForwardDiff.Tag{typeof(fs), Vec{2, Float64}}, Float64, 2}, 3})
The function `makemixed` exists, but no method is defined for this combination of argument types.
Closest candidates are:
makemixed(!Matched::Tensor{1, dim}) where dim
@ Tensors ~/.julia/packages/Tensors/XcYSK/src/mixed_tensors.jl:22
...
```
## Expected behavior
Return the gradient as a full third order tensor (`Tensor{3, dim}` /
`MixedTensor3{dim, dim, rdim}`), i.e. the same result type as for the equivalent
`Tensor{2}`-valued function — there is no minor-symmetric third order tensor type,
so dropping the symmetry in the result is the natural choice (the value's symmetry
just makes `∂A[i,j]/∂x ≡ ∂A[j,i]/∂x`).
## Why it matters (context)
Ferrite PR [#1418](https://github.com/Ferrite-FEM/Ferrite.jl/pull/1418) introduces
`TensorInterpolation{TB}` for tensor-valued interpolations (e.g. Regge, HHJ,
Arnold–Winther elements with `TB = SymmetricTensor{2, dim}`). Ferrite's
`FunctionValues` precomputes reference gradients via
`reference_shape_gradient_and_value`, whose generic fallback uses
`Tensors.gradient` — which hits this error for any standalone
`SymmetricTensor`-valued interpolation. The workaround (used both by #1418 for
`TensorizedInterpolation` and by our Regge experiment in this directory) is to
define the reference gradients analytically per interpolation.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.