3

I have a problem when using the MATLAB python engine.

I want to get approximated solutions to ODEs (using something like the ode45 function in MATLAB) from Python, but the problem is that ODE approximation requires an ODE function specification that I can't seem to create from the MATLAB Python engine.

It works fine calling MATLAB functions, such as isprime, from Python but there seems to be no way of specifying a MATLAB function in Python.

My question is therefore; Are there any way of generating MATLAB function code from Python or is a way to specify MATLAB functions from Python?

2
  • is using scipy a possibility? scipy.integrate.ode(f).set_integrator('dopri5') Commented Sep 18, 2016 at 16:09
  • @JamesK It has to be MATLAB since I would like to give the user a choice of solvers/libraries. Commented Sep 18, 2016 at 18:30

1 Answer 1

1

odefun passed to ode45, according to docs, has to be a function handle.

Solve the ODE

y' = 2t

Use a time interval of [0,5] and the initial condition y0 = 0.

tspan = [0 5];
y0 = 0;
[t,y] = ode45(@(t,y) 2*t, tspan, y0);

@(t,y) 2*t returns a function handle to anonymous function.

Unfortunately, function handles are listed as one of datatypes unsupported in MATLAB <-> Python conversion:

Unsupported MATLAB Types The following MATLAB data types are not supported by the MATLAB Engine API for Python:

  • Categorical array
  • char array (M-by-N)
  • Cell array (M-by-N)
  • Function handle
  • Sparse array
  • Structure array
  • Table
  • MATLAB value objects (for a discussion of handle and value classes see Comparison of Handle and Value Classes)
  • Non-MATLAB objects (such as Java® objects)

To sum up, it seems like there is no straightforward way of doing it.

Potential workaround may involve some combination of engine.workspace and engine.eval, as shown in Use MATLAB Engine Workspace in Python example.

Workaround with engine.eval (first demo):

import matlab.engine
import matplotlib.pyplot as plt

e = matlab.engine.start_matlab()
tr, yr = e.eval('ode45(@(t,y) 2*t, [0 5], 0)', nargout=2)
plt.plot(tr, yr)
plt.show()

By doing so, you avoid passing function handle via MATLAB/Python barrier. You pass string (bytes) and allow MATLAB to evaluate it there. What's returned is pure numeric arrays. After that, you may operate on result vectors, e.g. plot them.

Matplotlib result

Since passing arguments as literals would quickly became pain, engine.workspace may be used to avoid it:

import matlab.engine
import matplotlib.pyplot as plt

e = matlab.engine.start_matlab()
e.workspace['tspan'] = matlab.double([0.0, 5.0])
e.workspace['y0'] = 0.0
tr, yr = e.eval('ode45(@(t,y) 2*t, tspan, y0)', nargout=2)
plt.plot(tr, yr)
plt.show()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.