Solucionadores de oda de Matlab: cambio de estado y tiempo especificado

Estoy resolviendo un conjunto de ODE (dy / dt) en t = 0, todas las condiciones iniciales t = 0 y_0 = (0,0,0). ¿Puedo agregar un número a los valores y en diferentes momentos (por ejemplo, en t = 10, y1 debe agregarse a ese número, en t = 20, y2 debe agregarse a ese número, etc.) y resolver las ecuaciones?

Ok, como Simon McKenzie dice que realmente necesitamos más información sobre su problema urgente , pero creo que puedo ayudarlo. Por lo que nos has dado, asumiré que tienes una función myfun que pasas a algo como 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); 

En algún lugar donde hayas definido tu función, aquí la llamaré 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 

De lo contrario, simplemente agregue el desplazamiento al vector de solución devuelto, es decir,

 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? 

Insertar grandes discontinuidades en su ODE de la manera que sugiere (y la forma ilustrada por @macduff) puede llevar a una menor precisión y tiempos de cálculo más largos (especialmente con ode45ode15s podría ser una mejor opción o al menos asegurarse de que su absoluta y relativa tolerancias son adecuadas). De hecho, has producido un sistema muy rígido . Si desea agregar un número a los ODE comenzando en un momento específico, tenga en cuenta que el solucionador solo evalúa estas ecuaciones en puntos específicos en el momento que elija. (No se deje engañar por el hecho de que puede obtener salidas de paso fijas especificando tspan como más de dos elementos; todos los solucionadores de Matlab son solucionadores de pasos variables y elige sus pasos verdaderos según los criterios de error).

Una mejor opción es integrar el sistema por partes y anexar las salidas resultantes de cada ejecución juntas:

 % 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,:)]; 

El editor de Matlab puede quejarse de que la matriz T e Y no están preasignadas y / o están creciendo, pero está bien en este caso ya que están creciendo en trozos grandes solo unas pocas veces. Alternativamente, si desea tamaños de paso de salida fijos, puede hacer esto:

 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,:)); 

Uno podría convertir fácilmente ambos bloques de código anteriores for bucles más compactos si lo desea.

En ambos casos, su función ODE myfun incorpora el parámetro a esta manera:

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