Skip to content

Commit 1480575

Browse files
Merge pull request #1067 from ParamThakkar123/DynamicalODE
DynamicalODE Changes
2 parents 435b05e + 5535ed2 commit 1480575

File tree

4 files changed

+115
-102
lines changed

4 files changed

+115
-102
lines changed

benchmarks/DynamicalODE/Henon-Heiles_energy_conservation_benchmark.jmd

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ end
5252
const oop_q0 = @SVector [0.1, 0.]
5353
const oop_p0 = @SVector [0., 0.5]
5454

55-
function hamilton(du,u,p,t)
55+
function hamilton(du, u, p, t)
5656
dq, q = @views u[3:4], du[3:4]
5757
dp, p = @views u[1:2], du[1:2]
5858

@@ -64,20 +64,20 @@ function hamilton(du,u,p,t)
6464
end
6565

6666
function g(resid, u, p)
67-
resid[1] = H([u[1],u[2]], [u[3],u[4]], nothing) - E
67+
resid[1] = H([u[1], u[2]], [u[3], u[4]], nothing) - E
6868
resid[2:4] .= 0
6969
end
7070

71-
const cb = ManifoldProjection(g, nlopts=Dict(:ftol=>1e-13))
71+
const cb = ManifoldProjection(g, nlopts=Dict(:ftol => 1e-13))
7272

7373
const E = H(iip_p0, iip_q0, nothing)
7474
```
7575

7676
For the comparison we will use the following function
7777

7878
```julia
79-
energy_err(sol) = map(i->H([sol[1,i], sol[2,i]], [sol[3,i], sol[4,i]], nothing)-E, 1:length(sol.u))
80-
abs_energy_err(sol) = [abs.(H([sol[1,j], sol[2,j]], [sol[3,j], sol[4,j]], nothing) - E) for j=1:length(sol.u)]
79+
energy_err(sol) = map(i -> H([sol[1, i], sol[2, i]], [sol[3, i], sol[4, i]], nothing) - E, 1:length(sol.u))
80+
abs_energy_err(sol) = [abs.(H([sol[1, j], sol[2, j]], [sol[3, j], sol[4, j]], nothing) - E) for j=1:length(sol.u)]
8181

8282
function compare(mode=:inplace, all=true, plt=nothing; tmax=1e2)
8383
if mode == :inplace
@@ -100,23 +100,21 @@ function compare(mode=:inplace, all=true, plt=nothing; tmax=1e2)
100100
GC.gc()
101101
(mode == :inplace && all) && @time sol6 = solve(prob_linear, TaylorMethod(50), abstol=1e-20)
102102

103-
(mode == :inplace && all) && println("Vern9 + ManifoldProjection max energy error:\t"*
104-
"$(maximum(abs_energy_err(sol1)))\tin\t$(length(sol1.u))\tsteps.")
103+
(mode == :inplace && all) && println("Vern9 + ManifoldProjection max energy error:\t" * "$(maximum(abs_energy_err(sol1)))\tin\t$(length(sol1.u))\tsteps.")
105104
println("KahanLi8 max energy error:\t\t\t$(maximum(abs_energy_err(sol2)))\tin\t$(length(sol2.u))\tsteps.")
106105
println("SofSpa10 max energy error:\t\t\t$(maximum(abs_energy_err(sol3)))\tin\t$(length(sol3.u))\tsteps.")
107106
println("Vern9 max energy error:\t\t\t\t$(maximum(abs_energy_err(sol4)))\tin\t$(length(sol4.u))\tsteps.")
108107
println("DPRKN12 max energy error:\t\t\t$(maximum(abs_energy_err(sol5)))\tin\t$(length(sol5.u))\tsteps.")
109-
(mode == :inplace && all) && println("TaylorMethod max energy error:\t\t\t$(maximum(abs_energy_err(sol6)))"*
110-
"\tin\t$(length(sol6.u))\tsteps.")
108+
(mode == :inplace && all) && println("TaylorMethod max energy error:\t\t\t$(maximum(abs_energy_err(sol6)))\tin\t$(length(sol6.u))\tsteps.")
111109

112110
if plt === nothing
113111
plt = plot(xlabel="t", ylabel="Energy error")
114112
end
115113
(mode == :inplace && all) && plot!(sol1.t, energy_err(sol1), label="Vern9 + ManifoldProjection")
116-
plot!(sol2.t, energy_err(sol2), label="KahanLi8", ls=mode==:inplace ? :solid : :dash)
117-
plot!(sol3.t, energy_err(sol3), label="SofSpa10", ls=mode==:inplace ? :solid : :dash)
118-
plot!(sol4.t, energy_err(sol4), label="Vern9", ls=mode==:inplace ? :solid : :dash)
119-
plot!(sol5.t, energy_err(sol5), label="DPRKN12", ls=mode==:inplace ? :solid : :dash)
114+
plot!(sol2.t, energy_err(sol2), label="KahanLi8", ls=mode == :inplace ? :solid : :dash)
115+
plot!(sol3.t, energy_err(sol3), label="SofSpa10", ls=mode == :inplace ? :solid : :dash)
116+
plot!(sol4.t, energy_err(sol4), label="Vern9", ls=mode == :inplace ? :solid : :dash)
117+
plot!(sol5.t, energy_err(sol5), label="DPRKN12", ls=mode == :inplace ? :solid : :dash)
120118
(mode == :inplace && all) && plot!(sol6.t, energy_err(sol6), label="TaylorMethod")
121119

122120
return plt
@@ -205,4 +203,4 @@ The benchmarks were performed on a machine with
205203
```julia, echo = false
206204
using SciMLBenchmarks
207205
SciMLBenchmarks.bench_footer(WEAVE_ARGS[:folder],WEAVE_ARGS[:file])
208-
```
206+
```

benchmarks/DynamicalODE/Manifest.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2345,4 +2345,4 @@ version = "3.5.0+0"
23452345
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"]
23462346
git-tree-sha1 = "9c304562909ab2bab0262639bd4f444d7bc2be37"
23472347
uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd"
2348-
version = "1.4.1+1"
2348+
version = "1.4.1+1"

benchmarks/DynamicalODE/Project.toml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1414
TaylorIntegration = "92b13dbe-c966-51a2-8445-caca9f8a7d42"
1515

1616
[compat]
17-
DiffEqCallbacks = "3"
18-
DiffEqPhysics = "3.2"
19-
Elliptic = "1.0"
20-
OrdinaryDiffEq = "6"
21-
ParameterizedFunctions = "5.3"
22-
Plots = "1.4"
23-
PyPlot = "2.9"
24-
SciMLBenchmarks = "0.1"
25-
StaticArrays = "1.0"
26-
Statistics = "1"
17+
DiffEqCallbacks = "2.13, 3, 4"
18+
DiffEqPhysics = "3.15.0"
19+
Elliptic = "1.0.1"
20+
OrdinaryDiffEq = "6.89.0"
21+
ParameterizedFunctions = "5.17.0"
22+
Plots = "2.0.0"
23+
PyPlot = "2.11.5"
24+
SciMLBenchmarks = "0.1.3"
25+
StaticArrays = "1.9.7"
26+
Statistics = "1.11.1"
27+
TaylorIntegration = "0.16.1"

benchmarks/DynamicalODE/single_pendulums.jmd

Lines changed: 91 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -48,107 +48,116 @@ sol2tqp(sol) = (sol.t, sol2q(sol), sol2p(sol))
4848
#
4949
sn(u, k) = Jacobi.sn(u, k^2) # the Jacobian sn function
5050

51-
# Use PyPlot.
51+
# Use Plot.
5252
#
53-
using PyPlot
53+
using Plots
5454

55+
# Define the color list
5556
colorlist = [
5657
"#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
5758
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf",
5859
]
5960
cc(k) = colorlist[mod1(k, length(colorlist))]
6061

61-
# plot the sulution of a Hamiltonian problem
62-
#
62+
# Function to plot the solution of a Hamiltonian problem
6363
function plotsol(sol::ODESolution)
6464
local t, q, p
6565
t, q, p = sol2tqp(sol)
6666
local d = size(q)[2]
67+
p1 = plot(title="Solution", xlabel="t", grid=:on)
6768
for j in 1:d
6869
j_str = d > 1 ? "[$j]" : ""
69-
plot(t, q[:,j], color=cc(2j-1), label="q$(j_str)", lw=1)
70-
plot(t, p[:,j], color=cc(2j), label="p$(j_str)", lw=1, ls="--")
70+
plot!(p1, t, q[:, j], color=cc(2j-1), label="q$(j_str)", linewidth=1)
71+
plot!(p1, t, p[:, j], color=cc(2j), label="p$(j_str)", linewidth=1, linestyle=:dash)
7172
end
72-
grid(ls=":")
73-
xlabel("t")
74-
legend()
73+
return p1
7574
end
7675

77-
# plot the solution of a Hamiltonian problem on the 2D phase space
78-
#
76+
# Function to plot the solution on the 2D phase space
7977
function plotsol2(sol::ODESolution)
8078
local t, q, p
8179
t, q, p = sol2tqp(sol)
8280
local d = size(q)[2]
81+
p2 = plot(title="Phase Space", xlabel="q", ylabel="p", grid=:on)
8382
for j in 1:d
8483
j_str = d > 1 ? "[$j]" : ""
85-
plot(q[:,j], p[:,j], color=cc(j), label="(q$(j_str),p$(j_str))", lw=1)
84+
plot!(p2, q[:, j], p[:, j], color=cc(j), label="(q$(j_str), p$(j_str))", linewidth=1)
8685
end
87-
grid(ls=":")
88-
xlabel("q")
89-
ylabel("p")
90-
legend()
86+
return p2
9187
end
9288

93-
# plot the energy of a Hamiltonian problem
94-
#
89+
# Function to plot the energy of a Hamiltonian problem
9590
function plotenergy(H, sol::ODESolution)
9691
local t, q, p
9792
t, q, p = sol2tqp(sol)
9893
local energy = [H(q[i,:], p[i,:], nothing) for i in 1:size(q)[1]]
99-
plot(t, energy, label="energy", color="red", lw=1)
100-
grid(ls=":")
101-
xlabel("t")
102-
legend()
103-
local stdenergy_str = @sprintf("%.3e", std(energy))
104-
title(" std(energy) = $stdenergy_str", fontsize=10)
94+
p3 = plot(t, energy, label="energy", color="red", linewidth=1, xlabel="t", title="Energy", grid=:on)
95+
stdenergy_str = @sprintf("%.3e", std(energy))
96+
title!("std(energy) = $stdenergy_str", fontsize=10)
97+
return p3
10598
end
10699

107-
# plot the numerical and exact solutions of a single pendulum
108-
#
109-
# Warning: Assume q(0) = 0, p(0) = 2k. (for the sake of laziness)
110-
#
100+
# Function to compare the numerical and exact solutions of a single pendulum
111101
function plotcomparison(k, sol::ODESolution)
112102
local t, q, p
113103
t, q, p = sol2tqp(sol)
114-
local y = sin.(q/2)
115-
local y_exact = k*sn.(t, k) # the exact solution
116-
117-
plot(t, y, label="numerical", lw=1)
118-
plot(t, y_exact, label="exact", lw=1, ls="--")
119-
grid(ls=":")
120-
xlabel("t")
121-
ylabel("y = sin(q(t)/2)")
122-
legend()
123-
local error_str = @sprintf("%.3e", maximum(abs.(y - y_exact)))
124-
title("maximum(abs(numerical - exact)) = $error_str", fontsize=10)
104+
local y = sin.(q / 2)
105+
local y_exact = k * sn.(t, k) # the exact solution
106+
107+
p4 = plot(t, y, label="numerical", linewidth=1, grid=:on, xlabel="t", ylabel="y = sin(q(t)/2)", title="Comparison")
108+
plot!(p4, t, y_exact, label="exact", linewidth=1, linestyle=:dash)
109+
error_str = @sprintf("%.3e", maximum(abs.(y - y_exact)))
110+
title!("maximum(abs(numerical - exact)) = $error_str", fontsize=10)
111+
return p4
125112
end
126113

127-
# plot solution and energy
128-
#
114+
# Plot solution and energy
129115
function plotsolenergy(H, integrator, Δt, sol::ODESolution)
130-
local integrator_str = replace("$integrator", r"^[^.]*\." => "")
116+
integrator_str = replace("$integrator", r"^[^.]*\\." => "")
131117

132-
figure(figsize=(10,8))
118+
p1 = plotsol(sol)
119+
p2 = plotsol2(sol)
120+
p3 = plotenergy(H, sol)
133121

134-
subplot2grid((21,20), ( 1, 0), rowspan=10, colspan=10)
135-
plotsol(sol)
122+
suptitle = "===== $integrator_str, Δt = $Δt ====="
123+
plot(p1, p2, p3, layout=(3, 1), title=suptitle)
124+
end
136125

137-
subplot2grid((21,20), ( 1,10), rowspan=10, colspan=10)
138-
plotsol2(sol)
126+
# Solve a single pendulum
127+
function singlependulum(k, integrator, Δt; t0 = 0.0, t1 = 100.0)
128+
H(p, q, params) = p[1]^2 / 2 - cos(q[1]) + 1
129+
q0 = [0.0]
130+
p0 = [2k]
131+
prob = HamiltonianProblem(H, p0, q0, (t0, t1))
139132

140-
subplot2grid((21,20), (11, 0), rowspan=10, colspan=10)
141-
plotenergy(H, sol)
133+
integrator_str = replace("$integrator", r"^[^.]*\\." => "")
134+
@printf("%-25s", "$integrator_str:")
135+
sol = solve(prob, integrator, dt=Δt)
136+
@time sol = solve(prob, integrator, dt=Δt)
142137

143-
suptitle("===== $integrator_str, Δt = $Δt =====")
138+
sleep(0.1)
139+
140+
p1 = plotsol(sol)
141+
p2 = plotsol2(sol)
142+
p3 = plotenergy(H, sol)
143+
p4 = plotcomparison(k, sol)
144+
145+
suptitle = "===== $integrator_str, Δt = $Δt ====="
146+
plot(p1, p2, p3, p4, layout=(2, 2), title=suptitle)
144147
end
148+
```
149+
150+
## Tests
151+
152+
```julia
153+
# Single pendulum
154+
using Plots
155+
using OrdinaryDiffEq
145156

146-
# Solve a single pendulum
147-
#
148157
function singlependulum(k, integrator, Δt; t0 = 0.0, t1 = 100.0)
149-
local H(p,q,params) = p[1]^2/2 - cos(q[1]) + 1
150-
local q0 = [0.0]
151-
local p0 = [2k]
158+
local H(p, q, params) = p[1]^2 / 2 - cos(q[1]) + 1 # Hamiltonian for single pendulum
159+
local q0 = [0.0] # Initial position
160+
local p0 = [2k] # Initial momentum
152161
local prob = HamiltonianProblem(H, p0, q0, (t0, t1))
153162

154163
local integrator_str = replace("$integrator", r"^[^.]*\." => "")
@@ -157,28 +166,17 @@ function singlependulum(k, integrator, Δt; t0 = 0.0, t1 = 100.0)
157166
@time local sol = solve(prob, integrator, dt=Δt)
158167

159168
sleep(0.1)
160-
figure(figsize=(10,8))
161-
162-
subplot2grid((21,20), ( 1, 0), rowspan=10, colspan=10)
163-
plotsol(sol)
164-
165-
subplot2grid((21,20), ( 1,10), rowspan=10, colspan=10)
166-
plotsol2(sol)
167-
168-
subplot2grid((21,20), (11, 0), rowspan=10, colspan=10)
169-
plotenergy(H, sol)
170169

171-
subplot2grid((21,20), (11,10), rowspan=10, colspan=10)
172-
plotcomparison(k, sol)
170+
# Create plots using Plots.jl
171+
p1 = plot(sol.t, map(x -> x[1], sol.u), label="Position", title="Position vs Time")
172+
p2 = plot(sol.t, map(x -> x[2], sol.u), label="Momentum", title="Momentum vs Time")
173+
p3 = plot(sol.t, map(p -> H(p[1], p[2], nothing), sol.u), label="Energy", title="Energy vs Time")
174+
p4 = plot(sol.t, map(x -> x[1] - k, sol.u), label="Comparison", title="Comparison Plot")
173175

174-
suptitle("===== $integrator_str, Δt = $Δt =====")
176+
# Combine all plots in a layout
177+
layout = @layout [a b; c d]
178+
plot(p1, p2, p3, p4, layout=layout, size=(1000, 800), title="===== $integrator_str, Δt = $Δt =====")
175179
end
176-
```
177-
178-
## Tests
179-
180-
```julia
181-
# Single pendulum
182180

183181
k = rand()
184182
integrator = VelocityVerlet()
@@ -189,8 +187,24 @@ singlependulum(k, integrator, Δt, t0=-20.0, t1=20.0)
189187
```julia
190188
# Two single pendulums
191189

192-
H(q,p,param) = sum(p.^2/2 .- cos.(q) .+ 1)
193-
q0 = pi*rand(2)
190+
using Plots
191+
using OrdinaryDiffEq
192+
193+
function plotsolenergy(H, integrator, Δt, sol::ODESolution)
194+
local integrator_str = replace("$integrator", r"^[^.]*\." => "")
195+
196+
# Create plots using Plots.jl
197+
p1 = plot(sol, label="Position", title="Position vs Time")
198+
p2 = plot(sol, label="Momentum", title="Momentum vs Time")
199+
p3 = plot(sol.t, map(p -> H(p[2], p[3], nothing), sol.u), label="Energy", title="Energy vs Time")
200+
201+
# Combine all plots in a layout
202+
layout = @layout [a b; c]
203+
plot(p1, p2, p3, layout=layout, size=(1000, 800), title="===== $integrator_str, Δt = $Δt =====")
204+
end
205+
206+
H(q, p, param) = sum(p.^2 / 2 .- cos.(q) .+ 1)
207+
q0 = pi * rand(2)
194208
p0 = zeros(2)
195209
t0, t1 = -20.0, 20.0
196210
prob = HamiltonianProblem(H, q0, p0, (t0, t1))
@@ -257,4 +271,4 @@ singlependulum(k, SymplecticEuler(), Δt)
257271
```julia, echo = false
258272
using SciMLBenchmarks
259273
SciMLBenchmarks.bench_footer(WEAVE_ARGS[:folder],WEAVE_ARGS[:file])
260-
```
274+
```

0 commit comments

Comments
 (0)