@@ -20,7 +20,7 @@ abstol = 1e-5
2020function oscilatior!(du, u, p, t)
2121 ω = p[1 ]
2222 du[1 ] = u[2 ]
23- du[2 ] = - ω^ 2 * u[1 ]
23+ du[2 ] = - ω^ 2 * u[1 ]
2424 nothing
2525end
2626
@@ -36,14 +36,14 @@ function solution_derivative(t, u0, p)
3636 ω = p[1 ]
3737 A₀ = u0[2 ] / ω
3838 B₀ = u0[1 ]
39- return A₀ * ( t * cos(ω * t) - sin(ω * t)/ ω ) - B₀ * t * sin(ω * t)
39+ return A₀ * (t * cos(ω * t) - sin(ω * t) / ω ) - B₀ * t * sin(ω * t)
4040end
4141
4242# ######## Simple example of how to run the dynamcics ###########
4343
4444# Solve numerical problem
4545prob = ODEProblem(oscilatior!, u0, tspan, p)
46- sol = solve(prob, Tsit5(), reltol= reltol, abstol= abstol)
46+ sol = solve(prob, Tsit5(), reltol = reltol, abstol = abstol)
4747
4848u_final = sol. u[end ][1 ]
4949
@@ -65,17 +65,17 @@ function finitediff_solver(h, t, u0, p, reltol, abstol)
6565 tspan = (0.0 , t)
6666 # Forward model with -h
6767 prob₋ = ODEProblem(oscilatior!, u0, tspan, p₋)
68- sol₋ = solve(prob₋, Tsit5(), reltol= reltol, abstol= abstol)
68+ sol₋ = solve(prob₋, Tsit5(), reltol = reltol, abstol = abstol)
6969 # Forward model with +h
7070 prob₊ = ODEProblem(oscilatior!, u0, tspan, p₊)
71- sol₊ = solve(prob₊, Tsit5(), reltol= reltol, abstol= abstol)
71+ sol₊ = solve(prob₊, Tsit5(), reltol = reltol, abstol = abstol)
7272
73- return (sol₊. u[end ][1 ] - sol₋. u[end ][1 ]) / (2 h)
73+ return (sol₊. u[end ][1 ] - sol₋. u[end ][1 ]) / (2 h)
7474end
7575
7676# ######## Simulation with differerent stepsizes ###########
7777
78- stepsizes = 2.0 .^ collect(round(log2(eps(Float64))): 1 : 0 )
78+ stepsizes = 2.0 .^ collect(round(log2(eps(Float64))): 1 : 0 )
7979times = collect(t₀: 1.0 : t₁)
8080
8181# True derivative computend analytially
@@ -85,71 +85,85 @@ derivative_true = solution_derivative(t₁, u0, p)
8585# derivative_numerical = finitediff_numerical.(stepsizes, Ref(t₁), Ref(u0), Ref(p))
8686derivative_numerical = finitediff_numerical.(stepsizes, Ref(t₁), Ref(u0), Ref(p))
8787derivative_finitediff_exact = finitediff_numerical.(stepsizes, Ref(t₁), Ref(u0), Ref(p))
88- error_finitediff_exact = abs.((derivative_numerical .- derivative_true). / derivative_true)
88+ error_finitediff_exact = abs.((derivative_numerical .- derivative_true) ./ derivative_true)
8989
9090# Finite differences with solution from solver and low tolerance
91- derivative_solver_low = finitediff_solver.(stepsizes, Ref(t₁), Ref(u0), Ref(p), Ref(1e-6 ), Ref(1e-6 ))
92- error_finitediff_low = abs.((derivative_solver_low .- derivative_true). / derivative_true)
91+ derivative_solver_low = finitediff_solver.(
92+ stepsizes, Ref(t₁), Ref(u0), Ref(p), Ref(1e-6 ), Ref(1e-6 ))
93+ error_finitediff_low = abs.((derivative_solver_low .- derivative_true) ./ derivative_true)
9394
9495# Finite differences with solution from solver and high tolerance
95- derivative_solver_high = finitediff_solver.(stepsizes, Ref(t₁), Ref(u0), Ref(p), Ref(1e-12 ), Ref(1e-12 ))
96- error_finitediff_high = abs.((derivative_solver_high .- derivative_true). / derivative_true)
96+ derivative_solver_high = finitediff_solver.(
97+ stepsizes, Ref(t₁), Ref(u0), Ref(p), Ref(1e-12 ), Ref(1e-12 ))
98+ error_finitediff_high = abs.((derivative_solver_high .- derivative_true) ./ derivative_true)
9799
98100# Complex step differentiation with solution from solver and high tolerance
99101u0_complex = ComplexF64.(u0)
100102
101- derivative_complex_low = complexstep_differentiation.(Ref(x -> solve(ODEProblem(oscilatior!, u0_complex, tspan, [x]), Tsit5(), reltol= 1e-6 , abstol= 1e-6 ). u[end ][1 ]), Ref(p[1 ]), stepsizes)
103+ derivative_complex_low = complexstep_differentiation.(
104+ Ref(x -> solve(ODEProblem(oscilatior!, u0_complex, tspan, [x]), Tsit5(), reltol = 1e-6 , abstol = 1e-6 ). u[end ][1 ]),
105+ Ref(p[1 ]),
106+ stepsizes)
102107error_complex_low = abs.((derivative_true .- derivative_complex_low) ./ derivative_true)
103- derivative_complex_high = complexstep_differentiation.(Ref(x -> solve(ODEProblem(oscilatior!, u0_complex, tspan, [x]), Tsit5(), reltol= 1e-12 , abstol= 1e-12 ). u[end ][1 ]), Ref(p[1 ]), stepsizes)
108+ derivative_complex_high = complexstep_differentiation.(
109+ Ref(x -> solve(ODEProblem(oscilatior!, u0_complex, tspan, [x]), Tsit5(), reltol = 1e-12 , abstol = 1e-12 ). u[end ][1 ]),
110+ Ref(p[1 ]),
111+ stepsizes)
104112error_complex_high = abs.((derivative_true .- derivative_complex_high) ./ derivative_true)
105113
106114# Complex step Differentiation
107- derivative_complex_exact = ComplexDiff. derivative.(ω -> solution(t₁, u0, [ω]), p[1 ], stepsizes)
108- error_complex_exact = abs.((derivative_complex_exact .- derivative_true). / derivative_true)
115+ derivative_complex_exact = ComplexDiff. derivative.(
116+ ω -> solution(t₁, u0, [ω]), p[1 ], stepsizes)
117+ error_complex_exact = abs.((derivative_complex_exact .- derivative_true) ./ derivative_true)
109118
110119# Forward AD applied to numerical solver
111- derivative_AD_low = Zygote. gradient(p-> solve(ODEProblem(oscilatior!, u0, tspan, p), Tsit5(), reltol= 1e-6 , abstol= 1e-6 ). u[end ][1 ], p)[1 ][1 ]
120+ derivative_AD_low = Zygote. gradient(
121+ p -> solve(ODEProblem(oscilatior!, u0, tspan, p), Tsit5(), reltol = 1e-6 , abstol = 1e-6 ). u[end ][1 ],
122+ p)[1 ][1 ]
112123error_AD_low = abs((derivative_true - derivative_AD_low) / derivative_true)
113124
114- derivative_AD_high = Zygote. gradient(p-> solve(ODEProblem(oscilatior!, u0, tspan, p), Tsit5(), reltol= 1e-12 , abstol= 1e-12 ). u[end ][1 ], p)[1 ][1 ]
125+ derivative_AD_high = Zygote. gradient(
126+ p -> solve(ODEProblem(oscilatior!, u0, tspan, p), Tsit5(), reltol = 1e-12 , abstol = 1e-12 ). u[end ][1 ],
127+ p)[1 ][1 ]
115128error_AD_high = abs((derivative_true - derivative_AD_high) / derivative_true)
116129
117-
118130# ######## Figure ###########
119131
120- color_finitediff = RGBf(192 / 255 , 57 / 255 , 43 / 255 )
121- color_finitediff_low = RGBf(230 / 255 , 126 / 255 , 34 / 255 )
122- color_complex = RGBf(41 / 255 , 128 / 255 , 185 / 255 )
123- color_complex_low = RGBf(52 / 255 , 152 / 255 , 219 / 255 )
124- color_AD = RGBf(142 / 255 , 68 / 255 , 173 / 255 )
125- color_AD_low = RGBf(155 / 255 , 89 / 255 , 182 / 255 )
132+ color_finitediff = RGBf(192 / 255 , 57 / 255 , 43 / 255 )
133+ color_finitediff_low = RGBf(230 / 255 , 126 / 255 , 34 / 255 )
134+ color_complex = RGBf(41 / 255 , 128 / 255 , 185 / 255 )
135+ color_complex_low = RGBf(52 / 255 , 152 / 255 , 219 / 255 )
136+ color_AD = RGBf(142 / 255 , 68 / 255 , 173 / 255 )
137+ color_AD_low = RGBf(155 / 255 , 89 / 255 , 182 / 255 )
126138
127- fig = Figure(resolution= (1000 , 400 ))
128- ax = Axis(fig[1 , 1 ], xlabel = L" Stepsize ($\v arepsilon$)" , ylabel = L" \t ext{Absolute relative error}" ,
129- xscale = log10, yscale= log10, xlabelsize= 24 , ylabelsize= 24 , xticklabelsize= 18 , yticklabelsize= 18 )
139+ fig = Figure(resolution = (1000 , 400 ))
140+ ax = Axis(fig[1 , 1 ], xlabel = L" Stepsize ($\v arepsilon$)" ,
141+ ylabel = L" \t ext{Absolute relative error}" , xscale = log10, yscale = log10,
142+ xlabelsize = 24 , ylabelsize = 24 , xticklabelsize = 18 , yticklabelsize = 18 )
130143
131144# Plot derivatived of true solution (no numerical solver)
132- lines!(ax, stepsizes, error_finitediff_exact, label= L" \t ext{Finite differences (exact solution)}" ,
133- color= color_finitediff, linewidth= 2 , linestyle = :dash)
145+ lines!(ax, stepsizes, error_finitediff_exact,
146+ label = L" \t ext{Finite differences (exact solution)}" ,
147+ color = color_finitediff, linewidth = 2 , linestyle = :dash)
134148lines!(ax, stepsizes, error_complex_exact,
135- label= L" \t ext{Complex step differentiation (exact solution)}" ,
136- color= color_complex, linewidth= 2 , linestyle = :dash)
137-
149+ label = L" \t ext{Complex step differentiation (exact solution)}" ,
150+ color = color_complex, linewidth = 2 , linestyle = :dash)
151+
138152# Plot derivatives computed on top of numerical solver with finite differences
139- scatter!(ax, stepsizes, error_finitediff_low,
140- label= L" Finite differences (tol=$10^{-6}$)" , color = color_finitediff_low ,
141- marker = ' •' , markersize= 20 )
142- scatter!(ax, stepsizes, error_finitediff_high,
143- label= L" Finite differences (tol=$10^{-12}$)" , color = color_finitediff ,
144- marker = ' •' , markersize= 30 )
153+ scatter!(
154+ ax, stepsizes, error_finitediff_low, label = L" Finite differences (tol=$10^{-6}$)" ,
155+ color = color_finitediff_low, marker = ' •' , markersize = 20 )
156+ scatter!(
157+ ax, stepsizes, error_finitediff_high, label = L" Finite differences (tol=$10^{-12}$)" ,
158+ color = color_finitediff, marker = ' •' , markersize = 30 )
145159
146160# Plot derivatives computed on top of numerical solver with complex step method
147161scatter!(ax, stepsizes, error_complex_low,
148- label= L" Complex step differentiation (tol=$10^{-6}$)" ,
149- color= color_complex_low, marker = ' ∘' , markersize= 20 )
162+ label = L" Complex step differentiation (tol=$10^{-6}$)" ,
163+ color = color_complex_low, marker = ' ∘' , markersize = 20 )
150164scatter!(ax, stepsizes, error_complex_high,
151- label= L" Complex step differentiation (tol=$10^{-12}$)" , color = color_complex ,
152- marker = ' ∘' , markersize= 30 )
165+ label = L" Complex step differentiation (tol=$10^{-12}$)" ,
166+ color = color_complex, marker = ' ∘' , markersize = 30 )
153167
154168# AD
155169# hlines!(ax, [error_AD_low, error_AD_high], color=color_AD, linewidth=1.5)
@@ -158,20 +172,19 @@ scatter!(ax, stepsizes, error_complex_high,
158172# plot!(ax, [stepsizes[begin], stepsizes[end]],[error_AD_high, error_AD_high],
159173# color=color_AD, label=L"Forward AD (tol=$10^{-12}$)", marker='•', markersize=25)
160174
161- lines!(ax, stepsizes, repeat([error_AD_low], length(stepsizes)),
162- color= color_AD_low, label= L" Forward AD (tol=$10^{-6}$)" , linewidth= 2 )
163- lines!(ax, stepsizes, repeat([error_AD_high], length(stepsizes)),
164- color= color_AD, label= L" Forward AD (tol=$10^{-12}$)" , linewidth= 3 )
175+ lines!(ax, stepsizes, repeat([error_AD_low], length(stepsizes)),
176+ color = color_AD_low, label = L" Forward AD (tol=$10^{-6}$)" , linewidth = 2 )
177+ lines!(ax, stepsizes, repeat([error_AD_high], length(stepsizes)),
178+ color = color_AD, label = L" Forward AD (tol=$10^{-12}$)" , linewidth = 3 )
165179
166180# Add legend
167181fig[1 , 2 ] = Legend(fig, ax)
168182
169183! ispath(" Figures" ) && mkpath(" Figures" )
170184save(" Figures/DirectMethods_comparison.pdf" , fig)
171185
172-
173186# ######## Benchmark ###########
174187
175188# It looks like complex step has better performance... both in speed and momory allocation.
176189# @benchmark derivative_complex_low = complexstep_differentiation.(Ref(x -> solve(ODEProblem(oscilatior!, u0_complex, tspan, [x]), Tsit5(), reltol=1e-6, abstol=1e-6).u[end][1]), Ref(p[1]), [1e-5])
177- # @benchmark derivative_AD_low = Zygote.gradient(p->solve(ODEProblem(oscilatior!, u0, tspan, p), Tsit5(), reltol=1e-6, abstol=1e-6).u[end][1], p)[1][1]
190+ # @benchmark derivative_AD_low = Zygote.gradient(p->solve(ODEProblem(oscilatior!, u0, tspan, p), Tsit5(), reltol=1e-6, abstol=1e-6).u[end][1], p)[1][1]
0 commit comments