Skip to content

A numerical integrator written in Elixir for the solution of sets of non-stiff ordinary differential equations (ODEs).

License

Notifications You must be signed in to change notification settings

woodward/integrator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Integrator

A numerical integrator written in Elixir for the solution of sets of non-stiff ordinary differential equations (ODEs).

Installation

The package can be installed by adding integrator to your list of dependencies in mix.exs:

def deps do
  [
    {:integrator, "~> 0.1"},
  ]
end

The docs can be found at https://hexdocs.pm/integrator.

Description

Two integrator options are available; ode45 which is an adaptation of the Octave ode45 and Matlab ode45. The ode45 integrator utilizes the Dormand-Prince 4th/5th order Runge Kutta algorithm.

ode23 is an adaptation of the Octave ode23 and Matlab ode23 The ode23 integrator uses the Bogacki-Shampine 3rd order Runge Kutta algorithm.

Both ode45 (which is the default integrator option) and ode23 utilize an adaptive stepsize algorithm for computing the integration time step. The time step is computed based on the satisfaction of a required error tolerance.

This library heavily leverages Elixir Nx; many thanks to the creators of Nx, as without it this library would not have been possible. The GNU Octave code was also used heavily for inspiration and was used to generate numerical test cases for the Elixir versions of the algorithms. Many thanks to John W. Eaton for his tremendous work on Octave. Integrator has been tested extensively during its development, and has a large and growing test suite.

Usage

See the Livebook guides for detailed examples of usage. As a simple example, you can integrate the Van der Pol equation as defined in Integrator.SampleEqns.van_der_pol_fn/2 from time 0 to 20 with an intial x value of [0, 1] via:

t_initial = 0.0
t_final = 20.0
x_initial = Nx.tensor([0.0, 1.0])
solution = Integrator.integrate(&SampleEqns.van_der_pol_fn/2, [t_initial, t_final], x_initial)

Then, solution.output_t contains a list of output times, and solution.output_x contains a list of values of x at these corresponding times.

images/van_der_pol

Options exist for:

  • outputting simulation results dynamically via an output function (for applications such as plotting dynamically, or for animating while the simulation is underway)
  • generating simulation output at fixed times (such as at t = 0.1, 0.2, 0.3, etc.)
  • interpolating intermediate points via quartic Hermite interpolation (for ode45) or via cubic Hermite interpolation (for ode23)
  • detecting termination events (such as collisions); see the Livebooks for details.
  • increasing the simulation fidelity (at the expense of simulation time) via absolute tolerance and relative tolerance settings

So why should I care??? A tool to solve ODEs? WTF???

The basic gist of the project is that it is a tool in Elixir (that leverages Nx) to numerically solve sets of ordinary differential equations (ODEs). Science and engineering problems typically generate either sets of ODEs or partial differential equations (PDEs). So basically integrator lets you solve any scientific or engineering problem which generates ODEs, which is a HUGE class of problems (FYI, finite element methods are used to solve sets of PDEs).

Fun fact: hundreds (or even thousands) of scientific problems had been formulated in the form of ODEs since the time that Isaac Newton first invented calculus in the 1600's, but these problems remained intractable & unsolvable for over three centuries other than a very small handful that were amenable to a "closed form solution"; i.e., the ODEs could be solved analytically (i.e., via mathematical manipulations). So there was this tragic dilemma; we could formulate these problems mathematically since the 1600's - 1800's, but couldn't actually solve them. SAD! 😞

So one of the primary drivers to create the first digital computers in the 1940's - 1960's was to solve ODEs. The space program, for example, would have been impossible without the numerical solution of ODEs which represented the space flight trajectories, attitude, & control. And before the first digital computers, analog computers were used to solve ODEs back in the 1920's - 1940's.

So believe it or not, the first computers were developed and used to solve ODEs, not play League of Legends. 😉

These algorithms are battle-tested and in some cases have been around for decades; Matlab and Octave are just relatively clean implementations of some of these algorithms, so I used them as the basis for my Elixir versions.