I’m trying to use OrdinaryDiffEqLinear.jl 's the state-independent Magnus solvers to solve non-autonomous Linear ODEs.
To confirm the usage, I’m trying to solve
where \alpha is a constant (fixed as 0.1).
Its exact solution may be given by
I cannot reproduce the exact solution.
Here is my code:
using OrdinaryDiffEq
using Plots
alpha = 0.1; t0 = 0.0; t1 = 1.0; dt = 0.01
tspan = (t0, t1)
u0 = ones(2) # initial condition
A0 = [0.0 1.0; 0.0 0.0] # time-independent part
function update_func(A, u, p, t)
A[1, 2] = -alpha * t
A[2, 1] = alpha * t
end
# Magnus solver
A = MatrixOperator(A0; update_func)
prob = ODEProblem(A, u0, tspan)
sol = solve(prob, MagnusGL8(); dt)
plot(sol, label=["u[1] (magnus)" "u[2] (magnus)"])
# exact solutions
F(t0,t1) = alpha * (t1^2 - t0^2) / 2
u_exact1(t) = cos(F(t0, t)) * u0[1] - sin(F(t0, t)) * u0[2]
u_exact2(t) = sin(F(t0, t)) * u0[1] + cos(F(t0, t)) * u0[2]
plot!(sol.t, u_exact1.(sol.t), label="u[1] (exact)")
plot!(sol.t, u_exact2.(sol.t), label="u[2] (exact)")
# autonomous solver
prob = ODEProblem(MatrixOperator(A0), u0, tspan)
sol = solve(prob, LinearExponential())
plot!(sol, label=["u[1] (exponential)" "u[2] (exponential)"], color=[:lightblue :orange], alpha=0.8, linestyle=:dash, lw=3)
Here are the obtained results.
magnus
is obtained by the Magnus solver (here isMagnusGL8()
).exact
is obtained by hand. The formula is shown above.exponential
is obtained by exponentiation. This is a solver for autonomous cases.
Although magnus
and exact
are expected to behave similarly, it’s actually magnus
and exponential
that do.
This suggests that update_func
may not be passed correctly to the solver.
If I’m misusing it, please let me know how to pass it correctly.
Julia v1.11.4
OrdinaryDiffEqLinear v1.1.0