Ferrite-FEM / Ferrite-FEM/Tensors.jl

`gradient` fails for `SymmetricTensor`-valued functions of a `Vec`

Open
#262 0 comments 0 reactions 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.