Reputation: 21
So I have a vector of x-coordinates and a vector of y-coordinates and I need the second derivative at each x. There is no function tht I can write the y coordinates as therefore I don't think I can use forwarddiff.jl, finitdifferences.jl etc.
Thank you so much,
Henry
I have tried both BSplinekit.jl and Inteprolations.jl but this is linked to a long coupled ODE equation therefore the errors in the ends or centre of these methods seem to accumulate and after 1000 iterations lead to very eroneous results. Is there a possibilty that I could somehow use one of the function methods such as forwarddiff by having a package generate an 'exact' function from my results. If you need any data, please ask.
My result from Interpolations.jl after 2370-ish cycles (should be a straight line on 100) right now
My result from BSplineKit.jl after 1000-ish cycles
The code that I am using is as follows:
function Heatconductivity(κrt,Tel,Tph,zgrid)
S=Interpolations.interpolate(zgrid,Tel,Gridded(Linear()))
dS=only.(gradient.(Ref(S),zgrid))
Q=dS.*kappa_linear(κrt,Tel,Tph)
Qint=Interpolations.interpolate(zgrid,Q,Gridded(Linear()))
dQ=only.(gradient.(Ref(Qint),zgrid))
dQ=dQ.*-1
end
Where Tel is a vector of temperatures at depths into a material given by zgrid. I need the second derivative of the change in temperature with respect to position which currently I am getting from Interpolations.jl. I have tried multiple alogrithms for the interpolation but not seem to yield much improved results.
The output then is fed as part of a ODE that updates the temperature at each time step so I can't write an algebraic expression for dTel/dz.
Upvotes: 1
Views: 82
Reputation: 18227
This is not the most accurate solution, but it may offer a quick stop-gap:
function d2f(x,y)
h = diff(x)
d2 = @. (2*(y[3:end] + h[2:end]/h[1:end-1]*y[1:end-2] - (1+h[2:end]/h[1:end-1])*y[2:end-1])/(h[2:end]*h[1:end-1]*(1+h[2:end]/h[1:end-1])))
return d2
end
It is based on this old-ish paper: A simple finite-difference grid with non-constant intervals / Hilding Sundqvist & George Veronis (1970).
The returned vector is the second derivatives at points of x
except for the endpoints (i.e. x[1]
and x[end]
).
It isn't a full interpolation method, but perhaps it is enough for your use-case.
Testing:
julia> x = [1.0:0.1:2.0...];
julia> y = x.^2;
julia> d2f(x,y)
9-element Vector{Float64}:
2.000000000000005
2.000000000000001
2.000000000000005
2.000000000000001
2.0000000000000426
1.9999999999999605
2.0000000000000453
1.9999999999999605
1.9999999999999563
Indeed the second derivative of x^2
is 2
.
Upvotes: 1