Julia newbie here.
I solve a convection diffusion reaction problem in tow variables where the reaction term is replaced with an ANN with two inputs and one output. This should be trained against measured data c_true
.
Defining the problem is no issue, I use a centered finite difference scheme made with BandedMatrices.jl and stitch everything together in odesys:
using BandedMatrices, DiffEqFlux, Flux, Optim, OrdinaryDiffEq, DiffEqSensitivity, Plots, DelimitedFiles
#c_true = readdlm("onedatacol.txt")
c_true=rand(400,1)
tend = 200
tspan = (0.0,tend)
D = 1.66e-6
v = .0166667
#IC/BC
câ‚€ = zeros(2*100,1)
câ‚€[1] = 0.34
## FUNS
function centraldifference(n)
Δ = 1/(n-1) # spacing between grid points
l, u = (1,1) # lower and upper bandwidths
A = BandedMatrix{Float64}(undef, (n,n), (l,u)) #intialize the banded matrix
A[band(0)] .= -2*D/Δ^2 # set the diagonal band
A[band(1)] .= D/Δ^2-v/(2*Δ) # set the super-diagonal band
A[band(-1)] .= D/Δ^2+v/(2*Δ) # set the sub-diagonal band
A[1,1:2] .= 0 #left BC
A[n,n] = -D/Δ^2+-v/(2*Δ) #right BC
A[n,n-1] = D/Δ^2+v/(2*Δ)
return A
end
ann = FastChain(FastDense(2,16,tanh), FastDense(16,16,tanh), FastDense(16,1))
annpars = initial_params(ann)
function rhs(c,q,annpars)
return ann([c'; q'],annpars)'
end
odesyspars = annpars
function odesys(dc,c,odesyspars,t)
npoints=100;
dc[npoints+1:2*npoints] = rhs(c[1:npoints],c[npoints+1:2*npoints],odesyspars)
dc[1:100] = centraldifference(npoints)*c[1:npoints] + dc[npoints+1:2*npoints] # dc[1:npoints].= centraldifference(npoints)*c does not work, why?
end
The system solves like a charm and also the loss function returns a value
prob = ODEProblem(odesys, câ‚€, tspan,odesyspars)
sol = solve(prob,KenCarp4(),sensealg=BacksolveAdjoint(checkpointing=true),saveat=0.5:0.5:tend)
#
#plot(sol)
#
θ = annpars
#
function predict_mod(θ)
return solve(prob,KenCarp4(),c₀=c₀,odesyspars=θ,reltol=1e-8,abstol=1e-8,sensealg=BacksolveAdjoint(checkpointing=true),saveat=0.5:0.5:tend)
end
#
function loss(θ)
sol = predict_mod(θ)
if any((s.retcode != :Success for s in sol))
return Inf
else
return sum(abs2, Array(sol)[100,1,:].-c_true)
end
end
l = loss(θ)
If I throw everything into sciml_train however:
cb = function (θ,l)
println(l)
return false
end
cb(θ,l)
res = DiffEqFlux.sciml_train(loss, θ, ADAM(0.01), cb = cb,maxiters=200)
I get a very obscure “ambiguous multiplication” error I really do not understand nor see what’s going wrong at all nor understand the possible fix:
ERROR: LoadError: MethodError: *(::BandedMatrix{Float64,Array{Float64,2},Base.OneTo{Int64}}, ::ReverseDiff.TrackedArray{Float64,Float64,1,Array{Float64,1},Array{Float64,1}}) is ambiguous. Candidates:
*(A::ArrayLayouts.LayoutArray{T,2} where T, B::AbstractArray{T,1} where T) in ArrayLayouts at /Users/someuser/.julia/packages/ArrayLayouts/x9nhz/src/muladd.jl:462
*(x::AbstractArray{T,2} where T, y::ReverseDiff.TrackedArray{V,D,1,VA,DA} where DA where VA) where {V, D} in ReverseDiff at /Users/someuser/.julia/packages/ReverseDiff/Thhqg/src/derivatives/linalg/arithmetic.jl:214
Possible fix, define
*(::ArrayLayouts.LayoutArray{T,2} where T, ::ReverseDiff.TrackedArray{V,D,1,VA,DA} where DA where VA) where {V, D}
Thanks for any help/inputs in advance.
Edit: formatting