user188764
user188764

Reputation: 23

Errors when using functions with multiple inputs

I am trying to evaluate a duffing oscillator in MATLAB with multiple inputs, and I am getting an odd error I was hoping someone might be able to help me with.

Here is the code:

% file duffing.m

function dy=duffing(t,y,a,b,d,g,w) 
    dy=[y(2); -a*y(1)^3-b*y(1)-d*y(2)+g*cos(w*t)];
end

And the file that calls the duffing function:

t=0:0.01:100;

%duffing oscillator 

y0=[2,0];
a=1;
b=-1;
d=0.2;
w=1;
g=0.1;

% duffing oscillator
[t,y]=ode45('duffing',t,y0,a,b,d,g,w); 

When I run it, I get the following error:

Error using odearguments (line 92) DUFFING returns a vector of length 1, but the length of initial conditions vector is 2. The vector returned by DUFFING and the initial conditions vector must have the same number of elements.

But when I define the function duffing as

function dy=duffing(t,y) 

    a=1;
    b=-1;
    d=0.2;
    w=1;
    dy=[y(2); -a*y(1)^3-b*y(1)-d*y(2)+g*cos(w*t)];

end

and pass in

[t y]=ode45('duffing',t,y0);

with the same y0 as above, it runs fine and I can plot it.

What am I doing wrong?

Upvotes: 2

Views: 895

Answers (2)

chappjc
chappjc

Reputation: 30579

The syntax for ode45 is:

function varargout = ode45(ode,tspan,y0,options,varargin)

The fourth argument, options, is an options struct created with odeset. The additional inputs need to be the fifth and later, and the function needs to be modified. The official way is to use a function handle or global variables, but here's how to do it with arguments to ode45.

options = odeset('RelTol',1e-4);
[t,y]=ode45('duffing',t,y0,options,a,b,d,g,w);

Then you have to modify duffing with a dummy argument to be compatible with the calling convention of odearguments.m (f(t,y,'',p1,p2...)):

function dy=duffing(t,y,~,a,b,d,g,w) 
    dy=[y(2); -a*y(1)^3-b*y(1)-d*y(2)+g*cos(w*t)];
end

The official function handle solution looks something like this:

myDuffing = @(t,y) duffing(t,y,a,b,d,g,w);

Then call ode45 the same way as your second approach, but with myDuffing (see David's solution for this method).

Upvotes: 1

David
David

Reputation: 8459

ode45 takes as input a function of two variables only. If you want to pass more inputs, you have to create a little anonymous function, like this:

a=1;
b=-1;
d=0.2;
w=1;
g=0.1;

% duffing oscillator
[t,y]=ode45(@(t,y) duffing(t,y,a,b,d,g,w),t,y0); 

Upvotes: 1

Related Questions