An ordinary differential equation

This page shows a part of a tutorial by SciML (https://docs.sciml.ai/DiffEqDocs/stable/examples/classical_physics/).

In the tutorial, a simple harmonic oscillator is shown. It is given by

$$\ddot{x} + \omega^2 x = 0$$

with the analytical solution

$$\begin{eqnarray} x(t) &= A \cos (\omega t - \phi) \\ v(t) &= - A \omega \sin (\omega t - \phi) \end{eqnarray}$$

where

$$A = \sqrt{c_1 + c_2} \: \: \: \: \: \text{and} \: \: \: \: \: \tan \phi = \frac{c_2}{c_1}$$

with \(c_1\), \(c_2\) constants determined by the initial conditions such that \(c_1\) is the initial position and \(\omega c_2\) is the initial velocity.

Instead of transforming this to a system of ODEs to solve with ODEProblem, we can use SecondOrderODEProblem as follows.

using OrdinaryDiffEq, Plots

With parameter:

ω = 1;

and initial conditions:

x₀ = [0.0];
dx₀ = [π / 2];
tspan = (0.0, 2π);
ϕ = atan((dx₀[1] / ω) / x₀[1]);
A = √(x₀[1]^2 + dx₀[1]^2);

We define the problem as follows:

function harmonicoscillator(ddu, du, u, ω, t)
    ddu .= -ω^2 * u
end;

And pass it to the solvers:

prob = SecondOrderODEProblem(harmonicoscillator, dx₀, x₀, tspan, ω);
sol = solve(prob, DPRKN6())
retcode: Success
Interpolation: specialized 6th order interpolation
t: 21-element Vector{Float64}:
 0.0
 0.0006362147454811361
 0.010180207933076954
 0.04804241764385478
 0.12816946395559364
 0.250842712371822
 0.4093033665532287
 ⋮
 3.6758814439731107
 4.1413392906488715
 4.641874215009247
 5.199947963397019
 5.823354512663183
 6.283185307179586
u: 21-element Vector{RecursiveArrayTools.ArrayPartition{Float64, Tuple{Vector{Float64}, Vector{Float64}}}}:
 ([1.5707963267948966], [0.0])
 ([1.570796008889919], [0.0009993637178359062])
 ([1.5707149314762023], [0.015990757019241676])
 ([1.5689839184362309], [0.0754358267723675])
 ([1.5579119205978385], [0.20077735911161132])
 ([1.5216360367069885], [0.38990367025826794])
 ([1.4410458560452288], [0.625130339363116])
 ⋮
 ([-1.3518757589309065], [-0.7998953985772836])
 ([-0.8490394018385742], [-1.3215646890993369])
 ([-0.11067221593113467], [-1.5668928568020466])
 ([0.7358722626762072], [-1.3877655377446527])
 ([1.4076336577155995], [-0.6971128331231436])
 ([1.570795569343618], [9.764294399629317e-7])
let
    plot(
        sol,
        vars=[2, 1],
        linewidth=2,
        title="Simple Harmonic Oscillator",
        xaxis="Time",
        yaxis="Elongation",
        label=["x" "dx"],
    )
    plot!(t -> A * cos(ω * t - ϕ), lw=3, ls=:dash, label="Analytical Solution x")
    plot!(t -> -A * ω * sin(ω * t - ϕ), lw=3, ls=:dash, label="Analytical Solution dx")
end

Built with Julia 1.12.4 and

OrdinaryDiffEq 6.108.0
Plots 1.41.6

To run this tutorial locally, download this file and open it with Pluto.jl.