I solved a system of differential equations (van der Pol equations) using DifferentialEquations.
I would like to export the solution. To do this I used convert(Array,sol), however, the converted solution is not the same as the solution I get by sol.
See the code below for more explanation:
using DifferentialEquations
using Plots
function fun(du,u,p,t)
du[1] = u[2]
du[2] = 1000*(1-u[1]^2)*u[2]-u[1]
end
u0 = [2.0,0.0]
tspan = (0.0,3000.0)
prob = ODEProblem(fun,u0,tspan)
sol = solve(prob)
a = convert(Array,sol)#Here I tried to convert the solution to an array
plot(a[1,:])
plot(sol,vars = 1)
a = convert(Array,sol)
plot(a[1,:]) returns:
plot(sol,vars = 1) returns:
The converted solution is the same as what is contained in sol. The problem lies in the fact that the step size for the variable in the x axis (here it is time) is not uniform. So only plotting using plot(a[1,:]) is not enough. We must provide at what time the solution has the value it has. Using plot(sol.t,a[1,:]) plot the right answer.
Related
I got an apparently quite common Julia error when trying to use AD with forward.diff. The error messages vary a bit (sometimes matching function name sometimes Float64)
MethodError: no method matching logL_multinom(::Vector{ForwardDiff.Dual{ForwardDiff.Tag{typeof(logL_multinom), Real}, Real, 7}})
My goal: Transform a probability vector to be unbounded (θ -> y), do some stuff (namely HMC sampling) and transform back to the simplex space whenever the unnormalized posterior (logL_multinom()) is evaluated. DA should be used to overome problems for later, more complex, models than this.
Unfortunately, neither the Julia documentation, not the solutions from other questions helped me figure the particular problem out. Especially, it seems to work when I do the first transformation (y -> z) outside of the function, but the first transformation is a 1-to-1 mapping via logistic and should not cause any harm to differentiation.
Here is an MWE:
using LinearAlgebra
using ForwardDiff
using Base
function logL_multinom(y)
# transform to constrained
K = length(y)+1
k = collect(1:(K-1))
# inverse logit:
z = 1 ./ (1 .+ exp.(-y .- log.(K .- k))) # if this is outside, it works
θ = zeros(eltype(y),K) ; x_cumsum = zeros(eltype(y),K-1)
typeof(θ)
for i in k
x_cumsum[i] = 1-sum(θ)
θ[i] = (x_cumsum[i]) * z[i]
end
θ[K] = x_cumsum[K-1] - θ[K-1]
#log_dens_correction = sum( log(z*(1-z)*x_cumsum) )
dot(colSums, log.(θ))
end
colSums = [835, 52, 1634, 3469, 3053, 2507, 2279, 1115]
y0 = [-0.8904013824298864, -0.8196709647741431, -0.2676845405543302, 0.31688184351556026, -0.870860684394019,0.15187821053559714,0.39888119498547964]
logL_multinom(y0)
∇L = y -> ForwardDiff.gradient(logL_multinom,y)
∇L(y0)
Thanks a lot and especially some further readings/ explanations for the problem are appreciated since I'll be working with it moreoften :D
Edit: I tried to convert the input and any intermediate variable into Real / arrays of these, but nothing helped so far.
I've trying to use DifferentialEquations.jl from Julia. I managed to get it working but I'd like know how to generate output at specific time points. The docs aren't clear on this and I've not found a single example that does this. The code I'm currently using is from the tutorial:
using DifferentialEquations
using Plots
function lorenz(du,u,p,t)
du[1] = 10.0*(u[2]-u[1])
du[2] = u[1]*(28.0-u[3]) - u[2]
du[3] = u[1]*u[2] - (8/3)*u[3]
end
u0 = [1.0;0.0;0.0]
tspan = (0.0,100.0)
prob = ODEProblem(lorenz,u0,tspan)
sol = solve(prob)
plot(sol,vars=(1,2,3))
Currently it generates 1287 points, and I've no idea how it decides that. My question is what if I wanted to generate 20 points between the span 0 to 100?
The ODE tutorial section on "Controlling the Solvers" demonstrates using saveat for this purpose. The demonstration is:
sol = solve(prob,reltol=1e-6,saveat=0.1)
which will save at 0.0, 0.1, ... in your example. Right below that it is noted that:
More generally, saveat can be any collection of time points to save at.
So for example, we can use save at to save only at t=30, 60, and 78 as follows:
sol = solve(prob,saveat=[30.0,60.0,78.0])
These examples should put you in the right direction. For more details, see the Output Controls section of the documentation.
I am new to Julia, I would like to solve this system:
where k1 and k2 are constant parameters. However, I=0 when y,0 or Ky otherwise, where k is a constant value.
I followed the tutorial about ODE. The question is, how to solve this piecewise differential equation in DifferentialEquations.jl?
Answered on the OP's cross post on Julia Discourse; copied here for completeness.
Here is a (mildly) interesting example $x''+x'+x=\pm p_1$ where the sign of $p_1$ changes when a switching manifold is encountered at $x=p_2$. To make things more interesting, consider hysteresis in the switching manifold such that $p_2\mapsto -p_2$ whenever the switching manifold is crossed.
The code is relatively straightforward; the StaticArrays/SVector/MVector can be ignored, they are only for speed.
using OrdinaryDiffEq
using StaticArrays
f(x, p, t) = SVector(x[2], -x[2]-x[1]+p[1]) # x'' + x' + x = ±p₁
h(u, t, integrator) = u[1]-integrator.p[2] # switching surface x = ±p₂;
g(integrator) = (integrator.p .= -integrator.p) # impact map (p₁, p₂) = -(p₁, p₂)
prob = ODEProblem(f, # RHS
SVector(0.0, 1.0), # initial value
(0.0, 100.0), # time interval
MVector(1.0, 1.0)) # parameters
cb = ContinuousCallback(h, g)
sol = solve(prob, Vern6(), callback=cb, dtmax=0.1)
Then plot sol[2,:] against sol[1,:] to see the phase plane - a nice non-smooth limit cycle in this case.
Note that if you try to use interpolation of the resulting solution (i.e., sol(t)) you need to be very careful around the points that have a discontinuous derivative as the interpolant goes a little awry. That's why I've used dtmax=0.1 to get a smoother solution output in this case. (I'm probably not using the most appropriate integrator either but it's the one that I was using in a previous piece of code that I copied-and-pasted.)
I'm quite new to Julia and I'm currently learning how to solve differential equations with it. I tried to run a simple pre-made code by Christopher Rackauckas, but I got an error. The code can be found here. I will also write it here:
using DifferentialEquations
alpha = 0.5 #Setting alpha to 1/2
f(y,t) = alpha*y
u0 = 1.5
prob = ODEProblem(f,u0)
timespan = [0,1] # Solve from time = 0 to time = 1
sol = solve(prob,timespan) # Solves the ODE
using Plots
plot(sol) # Plots the solution using Plots.jl
And the error I'm getting looks like this:
LoadError: MethodError: no methof matching DiffEqBase.ODEProblem{uType,tType,isinplace,FC;MM}(::#f, ::Float64)
I also tried to run other similar codes and even removed the DifferentialEquations.jl -package and then reinstalled it, but nothing changed.
Anyone more experienced having an idea what I might be doing wrong?
The issue is that blog post is from quite a long time ago. Or at least, DifferentialEquations 1.0 had a few breaking changes in this part. You should use the tutorial instead, which fixes this example to the newest version. The solution is:
using DifferentialEquations
alpha = 0.5 #Setting alpha to 1/2
f(y,t) = alpha*y
u0 = 1.5
tspan = (0.0,1.0) # Solve from time = 0 to time = 1
prob = ODEProblem(f,u0,tspan)
sol = solve(prob) # Solves the ODE
using Plots
plot(sol) # Plots the solution using Plots.jl
But now that I know people are still looking at that old post, I updated its syntax to be correct.
I have a julia code:
using DifferentialEquations
using Plots
using ParameterizedFunctions
plotly()
lorenz = #ode_def Lorenz begin
dx = σ*(y-x)
dy = ρ*x-y-x*z
dz = x*y-β*z
end σ = 10. β = 8./3. ρ => 28.
u0 = [1., 5., 10.]
tspan = (0., 2.)
prob = ODEProblem(lorenz, u0, tspan)
sol = solve(prob,save_timeseries=true)
plot(sol,vars=(:x,:y,:z))
Which results in:
next plot
How can i animate this plot such that it would work either from REPL and jupyter?
For DifferentialEquations.jl, there is a built-in animation function which can handle this. Unfortunately, I realized that I forgot to put it in the last release. When it's released, the syntax will be (simplifying your code a little bit):
using DifferentialEquations
using Plots
using ParameterizedFunctions
pyplot()
lorenz = #ode_def Lorenz begin
dx = σ*(y-x)
dy = ρ*x-y-x*z
dz = x*y-β*z
end σ = 10. β = 8./3. ρ => 28.
u0 = [1., 5., 10.]
tspan = (0., 2.)
prob = ODEProblem(lorenz, u0, tspan)
sol = solve(prob)
animate(sol,vars=(:x,:y,:z),xlims=(-20,20),ylims=(-15,20),zlims=(10,40))
A few things: animate can take any of the normal plot commands. However, it at each frame it plots from the beginning to the ith step, which means you may need to manually set the axis to make them not shift around. Another thing to note is that I switched backends to PyPlot. The Plotly backend cannot do animations. Maybe PlotlyJS can? The animation function is documented here.
Using that command will be by far the easiest way, but you can do it "more manually" using the integrator interface. Essentially, you can just plot each step interval using this and get to the same place in the end. You'd have to use Plots.jl's animation interface.
Edit: If you Pkg.update() this should now work.