Common interface bindings for the MATLAB ODE solvers via MATLAB.jl
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
assets
src
test
.codecov.yml
.gitignore
.travis.yml
LICENSE.md
README.md
REQUIRE
appveyor.yml

README.md

MATLABDiffEq.jl

Join the chat at https://gitter.im/JuliaDiffEq/Lobby

MATLABDiffEq.jl is a common interface binding for the MATLAB ordinary differential equation solvers. It uses the MATLAB.jl interop in order to send the differential equation over to MATLAB and solve it. Note that this package requires the differential equation function to be defined using ParameterizedFunctions.jl.

Note that this package isn't for production use and is mostly just for benchmarking. For well-developed differential equation package, see DifferentialEquations.jl.

Installation

To install MATLABDiffEq.jl, use the following:

Pkg.clone("https://github.com/JuliaDiffEq/MATLABDiffEq.jl")

Using MATLABDiffEq.jl

MATLABDiffEq.jl is simply a solver on the DiffEq common interface, so for details see the DifferentialEquations.jl documentation. However, there are three things to know:

  1. The only options implemented are those for error calculations (timeseries_error), saveat and tolerances.
  2. The input function must be defined by a ParameterizedFunction
  3. The input function must not use parameters

Note that the algorithms are defined to have the same name as the MATLAB algorithms, but are not exported. Thus to use ode45, you would specify the algorithm as MATLABDiffEq.ode45().

Example

using DiffEqBase, MATLABDiffEq, ParameterizedFunctions


f = @ode_def LotkaVolterra begin
  dx = 1.5x - x*y
  dy = -3y + x*y
end

tspan = (0.0,10.0)
u0 = [1.0,1.0]
prob = ODEProblem(f,u0,tspan)
sol = solve(prob,MATLABDiffEq.ode45())

Measuring Overhead

To measure the overhead of over the wrapper, note that the variables from the session will be still stored in MATLAB after the computation is done. Thus you can simply call the same ODE function and time it directly. This is done by:

@time MATLABDiffEq.eval_string("[t,u] = $(algstr)(f,tspan,u0,options);")

To be even more pedantic, you can play around in the actual MATLAB session by using

MATLABDiffEq.show_msession()

Overhead Amount

Generally, for long enough problems the overhead is minimal. Example:

using DiffEqBase, ParameterizedFunctions, MATLABDiffEq
f = @ode_def_bare RigidBodyBench begin
  dy1  = -2*y2*y3
  dy2  = 1.25*y1*y3
  dy3  = -0.5*y1*y2 + 0.25*sin(t)^2
end
prob = ODEProblem(f,[1.0;0.0;0.9],(0.0,100.0))
alg = MATLABDiffEq.ode45()
algstr = string(typeof(alg).name.name)

For this, we get the following:

julia> @time sol = solve(prob,alg);
  0.063918 seconds (38.84 k allocations: 1.556 MB)

julia> @time sol = solve(prob,alg);
  0.062600 seconds (38.84 k allocations: 1.556 MB)

julia> @time sol = solve(prob,alg);
  0.061438 seconds (38.84 k allocations: 1.556 MB)

julia> @time sol = solve(prob,alg);
  0.065460 seconds (38.84 k allocations: 1.556 MB)

julia> @time MATLABDiffEq.eval_string("[t,u] = $(algstr)(f,tspan,u0,options);")
  0.058249 seconds (11 allocations: 528 bytes)

julia> @time MATLABDiffEq.eval_string("[t,u] = $(algstr)(f,tspan,u0,options);")
  0.060367 seconds (11 allocations: 528 bytes)

julia> @time MATLABDiffEq.eval_string("[t,u] = $(algstr)(f,tspan,u0,options);")
  0.060171 seconds (11 allocations: 528 bytes)

julia> @time MATLABDiffEq.eval_string("[t,u] = $(algstr)(f,tspan,u0,options);")
  0.058928 seconds (11 allocations: 528 bytes)

Benchmark

MATLABDiffEq.jl will be included into DiffEqBenchmarks.jl. However, the benchmarks are not encouraging to MATLAB at all. Instead, they show that the cost of evaluating functions in MATLAB are too large (note that the functions are re-defined in MATLAB, meaning that they are true MATLAB functions and not interop functions).

Running benchmarks at various tolerance using the same Lotka-Volterra problem from before, we get the following:

using OrdinaryDiffEq, ODEInterfaceDiffEq, Plots, ODE
using DiffEqDevTools
abstols = 1./10.^(6:13)
reltols = 1./10.^(3:10)
sol = solve(prob,Vern7(),abstol=1/10^14,reltol=1/10^14)
test_sol = TestSolution(sol)
plotly()
setups = [Dict(:alg=>DP5())
          Dict(:alg=>dopri5())
          Dict(:alg=>BS5())
          Dict(:alg=>Tsit5())
          Dict(:alg=>Vern6())
          Dict(:alg=>Vern7())
          Dict(:alg=>MATLABDiffEq.ode45())
  ]
wp = WorkPrecisionSet(prob,abstols,reltols,setups;appxsol=test_sol,dense=false,save_everystep=false,numruns=1000,maxiters=10000000,ttimeseries_errors=false,verbose=false)
plot(wp)

Benchmark

This shows that being able to run MATLAB ODE algorithms with MATLAB functions is cute, but does not really have a practical use due to MATLAB's lack of performance (and its pass by copy for functions).