Ferrite-FEM / Ferrite-FEM/Tensors.jl

Inserting a known derivative: function needs to exclude dual numbers

Aperta
#179 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
Julia
Stelle
182
Fork
40
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

I ran into the following problem today:
```julia
function tensor_exp(A::SymmetricTensor{2})
E = eigen(A)
A_exp = zero(A)
for (i, λ) in enumerate(E.values)
N = E.vectors[:,i]
A_exp += exp(λ) * N ⊗ N
end
return A_exp
end

tensor_exp_gradient(A::AbstractTensor{2}) = tensor_exp(A), tensor_exp(A)

@implement_gradient tensor_exp tensor_exp_gradient
```

```julia
julia> A = rand(SymmetricTensor{2,3}) + one(SymmetricTensor{2,3})
julia> gradient(tensor_exp, A)

ERROR: MethodError: no method matching precision(::Type{ForwardDiff.Dual{ForwardDiff.Tag{typeof(tensor_exp), SymmetricTensor{2, 3, Float64, 6}}, Float64, 6}})
Closest candidates are:
precision(::Type{Float16}) at C:\Users\auth\AppData\Local\Programs\Julia-1.7.2\share\julia\base\float.jl:686
precision(::Type{Float32}) at C:\Users\auth\AppData\Local\Programs\Julia-1.7.2\share\julia\base\float.jl:687
precision(::Type{Float64}) at C:\Users\auth\AppData\Local\Programs\Julia-1.7.2\share\julia\base\float.jl:688
...
Stacktrace:
[1] eigen(R::SymmetricTensor{2, 3, ForwardDiff.Dual{ForwardDiff.Tag{typeof(tensor_exp), SymmetricTensor{2, 3, Float64, 6}}, Float64, 6}, 6})
@ Tensors C:\Users\auth\.julia\packages\Tensors\fjqpn\src\eigen.jl:137
[2] tensor_exp(A::SymmetricTensor{2, 3, ForwardDiff.Dual{ForwardDiff.Tag{typeof(tensor_exp), SymmetricTensor{2, 3, Float64, 6}}, Float64, 6}, 6})
@ Main c:\Users\auth\OneDrive - Chalmers\Documents\courses\Phd courses\Computational nonlinear mechanics\computer assignments\cass3\tensor_log_exp.jl:29
[3] gradient(f::typeof(tensor_exp), v::SymmetricTensor{2, 3, Float64, 6})
@ Tensors C:\Users\auth\.julia\packages\Tensors\fjqpn\src\automatic_differentiation.jl:455
[4] top-level scope
@ REPL[6]:1
```
The problem here is that we run into the `tensor_exp` function with dual numbers (instead of using `tensor_exp_gradient`).
Looking at the methods of `tensor_exp`, we can see why:
```julia
julia> methods(tensor_exp)
# 2 methods for generic function "tensor_exp":
[1] tensor_exp(A::SymmetricTensor{2}) in Main at c:\Users\auth\OneDrive - Chalmers\Documents\courses\Phd courses\Computational nonlinear mechanics\computer assignments\cass3\tensor_log_exp.jl:28
[2] tensor_exp(x::Union{ForwardDiff.Dual, AbstractTensor{<:Any, <:Any, <:ForwardDiff.Dual}}) in Main at C:\Users\auth\.julia\packages\Tensors\fjqpn\src\automatic_differentiation.jl:253
```
The original `tensor_exp` is more specific than the one defined for Dual numbers by `@implement_gradient`. The solution could be to not allow dual numbers in the original function at all, e.g. by
```julia
function tensor_exp(A::SymmetricTensor{2,dim,Float64}) where dim
```
(This is of course not so nice if one doesn't own this function. )

Perhaps there is a better solution than specifying the number type of the Tensor. In case there isn't we should probably add a hint about it to the docs.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.