Matlab ode solvers: changing state and specified time

青春壹個敷衍的年華 提交于 2019-11-26 06:09:05

问题


I am solving a set of ODEs (dy/dt) at t=0, all initial conditions t=0 y_0=(0,0,0). Can I add some number to the y values at different times (e.g., at t=10, y1 should be added to that number; at t=20, y2 should be added to that number, etc.) and solve the equations?


回答1:


Inserting large discontinuities in your ODE in the way you suggest (and the way illustrated by @macduff) can lead to less precision and longer computation times (especially with ode45 - ode15s might be a better option or at least make sure that your absolute and relative tolerances are suitable). You've effectively produced a very stiff system. If you want to add some number to the ODEs starting at a specific time keep in mind that the solver only evaluates these equations at specific points in time of its own choosing. (Don't be mislead by the fact that you can obtain fixed step-size outputs by specifying tspan as more than two elements – all of Matlab's solvers are variable step-size solvers and choose their true steps based on error criteria.)

A better option is to integrate the system piecewise and append the resultant outputs from each run together:

% t = 0 to t = 10, pass parameter a = 0 to add to ODEs
a = 0;
tspan = [0 10];
[T,Y] = ode45(@(t,y)myfun(t,y,a),tspan,y_0);

% t = 10 to t = 20, pass parameter a = 10 to add to ODEs
a = 10;
[t,y] = ode45(@(t,y)myfun(t,y,a),tspan+T(end),Y(end,:));
T = [T;t(2:end)];
Y = [Y;y(2:end,:)];

% t = 20 to t = 30, pass parameter a = 20 to add to ODEs
a = 20;
[t,y] = ode45(@(t,y)myfun(t,y,a),tspan+T(end),Y(end,:));
T = [T;t(2:end)];
Y = [Y;y(2:end,:)];

The Matlab editor may complain about the array T and Y not being preallocated and/or growing, but it's fine in this case as they're growing in large chunks only a few times. Alternatively, if you want fixed output step-sizes, you can do this:

dt = 0.01;
T = 0:dt:30;
Y = zeros(length(T),length(y_0));

% t = 0 to t = 10, pass parameter a = 0 to add to ODEs
a = 0;
[~,Y(1:10/dt+1,:)] = ode45(@(t,y)myfun(t,y,a),T(1:10/dt+1),y_0);

% t = 10 to t = 20, pass parameter a = 10 to add to ODEs
a = 10;
[~,Y(10/dt+1:20/dt+1,:)] = ode45(@(t,y)myfun(t,y,a),T(10/dt+1:20/dt+1),Y(10/dt+1,:));

% t = 20 to t = 30, pass parameter a = 20 to add to ODEs
a = 20;
[~,Y(20/dt+1:end,:)] = ode45(@(t,y)myfun(t,y,a),T(20/dt+1:end),Y(20/dt+1,:));

One could easily convert both of the above blocks of code to more compact for loops if desired.

In both cases your ODE function myfun incorporates the parameter a this way:

function ydot = myfun(t,y,a)
    y(1) = ... % add a however you like
    ...



回答2:


Ok, like Simon McKenzie says we really need more info on your urgent issue, but I think I can help. From what you've given us, I'll assume you have a function myfun that you pass to something like ode45

y_0 = [0,0,0];
% here Tfinal is the time in seconds that you want to simulate to
% and specify the tspan so that you will get a solution at each whole
% number of seconds, I believe
[t,y] = ode45(@myfun,[0:0.1:Tfinal],y_0);

Somewhere you have defined your function, here I'll call it myfun

function dy = myfun(t,y)
  % here let's check to see if it's time to add your offsets
  % still, you may want to put a little fudge factor for the time, but
  % you'll have to experiment, I'll set it up though
  EPS = 1e-12;
  if( t < 10 + EPS || t > 10 - EPS )
    y(1) = y(1) + 10;
  .
  .
  .
  .
  % this only makes sense if you then use y(1) in the compuatation

Otherwise, just add the offset to the returned solution vector, i.e.

idx10 = find( t == 10 ); % should be there since it's in the tspan
y(idx10:end) = y(idx10:end) + 10; % I guess you add it from that point on?


来源:https://stackoverflow.com/questions/17356037/matlab-ode-solvers-changing-state-and-specified-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!