Two things here. First of all, I think it’s much more sane to just use a callable struct here, rather than embedding the anonymous function into the struct. That will give you a single source of truth on the parameters. But that doesn’t fix the issue. The issue was x -> get_tmp(t2.gparam,x)
, the x
you’re passing in was 1.5
, so it was never a dual number. You need to make sure get_tmp
is triggered by the duals, so you need to pass it p
so that way it knows when it’s differentiating.
So a fixed version is:
using DiffEqBase: get_tmp, dualcache, DiffCache
using ForwardDiff
mutable struct Modelparameters{T,chunk_size}
gparam::DiffCache{Array{T,1},Array{ForwardDiff.Dual{nothing,T,chunk_size},1}}
end
function (t2::Modelparameters)(x,p=nothing)
if p !== nothing
tmp = get_tmp(t2.gparam,p)
tmp .= p
else
tmp = get_tmp(t2.gparam,x)
end
tmp[1]*(x-1)^tmp[2]
end
using ForwardDiff
using DiffEqBase: get_tmp, dualcache
function init()
t1 = dualcache([1.5e-6, 1.5])
t2 = Modelparameters(t1)
return t2
end
t2 = init()
result1 = t2(2)
newp = [2e-6, 1.5]
changeparams!(t2, newp)
result2 = t2(2)
f = p -> t2(1.5,p)
f2 = p -> p[1]*(1.5-1)^p[2]
result3 = f([5e-6, 1.5])
result4 = f2([5e-6, 1.5])
gradient1 = ForwardDiff.gradient(f, [5e-6, 1.5])
gradient2 = ForwardDiff.gradient(f2, [5e-6, 1.5])