ODE integration example

This tutorial shows how to perform the numerical integration of an ordinary differential equation (ODE) using DA objects as the state components' type. It also demonstrates how to extract the state transition matrix (STM) from the polynomial expansion of the dynamics flow.

In this case, the state vector represents an object in orbit around a central body and subject only to the gravitational pull of the latter. Its motion is described by the differential equations for the Kepler problem expressed in Cartesian coordinates.

Install dependencies

Make sure the required packages are installed

using Pkg
Pkg.add("DACE")

Using DACE

Load the required modules

using OrdinaryDiffEq
using DACE

Define the parameters and intial conditions for a circular orbit with a normalized radius equal to one

μ = 1.0
x0 = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0]
6-element Vector{Float64}:
 1.0
 0.0
 0.0
 0.0
 1.0
 0.0

Set the integration time span equal to one revolution

t0 = 0.0
tf = 2π
6.283185307179586

Define the equations of motion for the resticted two-body problem

function kepler_ode!(du, u, μ, _)
    du[1:3] .= u[4:6]
    du[4:6] .= -u[1:3] * μ ./ sum(u[1:3].^2)^(3/2)
end
kepler_ode! (generic function with 1 method)

Compute the nominal solution

prob = ODEProblem(kepler_ode!, x0, [t0, tf], μ)
sol = solve(prob, Vern9(), abstol=1e-12, reltol=1e-12)

xf = sol.u[end]
6-element Vector{Float64}:
  0.9999999999999963
 -4.963822535880929e-14
  0.0
  4.3859021831616145e-14
  0.9999999999999949
  0.0

Initialize DACE to compute second-order expansions

DACE.init(2,6)

Define the initial conditions as a DA vector

dx_dace = [DA(i,1.0) for i in 1:6]
x0_dace = x0 .+ dx_dace

println(x0_dace)
DACE.DAAllocated[     I  COEFFICIENT              ORDER EXPONENTS
     1    1.0000000000000000e+00   0   0  0  0  0  0  0
     2    1.0000000000000000e+00   1   1  0  0  0  0  0
------------------------------------------------
,      I  COEFFICIENT              ORDER EXPONENTS
     1    1.0000000000000000e+00   1   0  1  0  0  0  0
------------------------------------------------
,      I  COEFFICIENT              ORDER EXPONENTS
     1    1.0000000000000000e+00   1   0  0  1  0  0  0
------------------------------------------------
,      I  COEFFICIENT              ORDER EXPONENTS
     1    1.0000000000000000e+00   1   0  0  0  1  0  0
------------------------------------------------
,      I  COEFFICIENT              ORDER EXPONENTS
     1    1.0000000000000000e+00   0   0  0  0  0  0  0
     2    1.0000000000000000e+00   1   0  0  0  0  1  0
------------------------------------------------
,      I  COEFFICIENT              ORDER EXPONENTS
     1    1.0000000000000000e+00   1   0  0  0  0  0  1
------------------------------------------------
]

Compute the polynomial expansion of the dynamics flow

sol_dace = solve(remake(prob, u0=x0_dace), Vern9(), abstol=1e-12, reltol=1e-12)

xf_dace = sol_dace.u[end]
xf_cons = DACE.cons.(xf_dace)
6-element Vector{Float64}:
  0.9999999999999967
 -6.053491041768666e-14
  0.0
  5.355438315035599e-14
  0.9999999999999952
  0.0

Verify the (nominal) final state

println("Max abs error on final state: " * string(maximum(abs.(xf_cons - xf))))
Max abs error on final state: 1.0896685058877372e-14

Extract the state transition matrix (STM)

stm_dace = DACE.jacobian(xf_dace)
stm_cons = DACE.cons.(stm_dace)
6×6 Matrix{Float64}:
   1.0          -1.83384e-13  0.0          -2.40419e-13   -7.38964e-13   0.0
 -18.8496        1.0          0.0           7.24656e-13  -18.8496        0.0
   0.0           0.0          1.0           0.0            0.0          -6.05349e-14
  18.8496       -5.46722e-13  0.0           1.0           18.8496        0.0
  -1.10489e-12   1.54696e-13  0.0           9.8001e-14     1.0           0.0
   0.0           0.0          5.35544e-14   0.0            0.0           1.0

This page was generated using Literate.jl.