ddesd giving NaN for all state variables beyond time step 1.

61 次查看(过去 30 天)
The following is my code for a state-dependent delay equation I am working on.
% Parameter set and intialization
%(Q=20, a=5, k=1, ell=10)
tstar = 60.2762; %tstar for b=.03
tspan = [tstar 5000];
options = ddeset(RelTol=1e-12); %Without this extreme tolerance, ddesd never runs at all
sol = ddesd(@ddefun, @dely, @history, tspan, options); %call ddesd
% Print graph
axes
hold on
plot(sol.x,sol.y);
legend('C','n1','m1','n2','m2','tau')
hold off
xlim([0 400])
xlabel('Time (s)')
ylabel('Total Fission Rate (nM/s)')
%ODE which defines behavior before critical time tstar
function dydt = odefun(t,y)
b = .03;
k = 1;
dydt = [-k*y(1)^2 - k*y(1)*y(2) + b*y(3);
k*y(1)^2 - b*y(2);
k*y(1)*(y(1) + y(2)) - b*y(3);
];
end
function dydt = ddefun(t,y,Z) % DDE being solved
b = .03;
k = 1;
a = 5;
ell = 10;
dydt = [a*y(5) - k*y(1) - k*y(1)*(y(2) + y(4)) + b*(y(3) + y(4));
-k*y(1)*(Z(1,1)*exp(-b*y(6)) - y(1)) - b*y(2);
-k*y(1)*(ell*Z(1,1)*exp(-b*y(6)) - y(1) - y(2)) - b*y(3);
k*y(1)*Z(1,1)*exp(-b*y(6)) - a*y(4);
k*y(1)*(ell*Z(1,1)*exp(-b*y(6)) + y(4)) - a*y(5);
1 - y(1)/Z(1,1)
];
end
%-------------------------------------------
function d = dely(t,y) % delay for y
d = t - y(6);
end
%-------------------------------------------
function v = history(t) % history function for t < t0
tstar = 60.2762; %tstar for b=.03
preTstarSol = ode45(@odefun, [0 tstar], [20 0 0]); %Here the ODE is called to create the history of C, n1, and m1
IC1 = @(t) interp1(preTstarSol.x, preTstarSol.y(1,:), t, 'linear');
IC2 = @(t) interp1(preTstarSol.x, preTstarSol.y(2,:), t, 'linear');
IC3 = @(t) interp1(preTstarSol.x, preTstarSol.y(3,:), t, 'linear');
v = [IC1(t);
IC2(t);
IC3(t);
0;
0;
tstar]; %The delay is initialized as "tstar" meaning in the first time step the delay looks back to time 0
end
%-------------------------------------------
As it is written, the solver finds all the state variables to be NaN after time step 1, and prints an empty graph. You may note the rather extreme RelTol=1e-12. However, without a change to the tolerance, nothing happens at all. That is, if you delete "options" from inside ddesd, the code will never finish running and even when you click "STOP" there is no "sol" initialized at all, which implies the code never even runs the first time step of ddesd.
What I can't understand is that a tiny tweak to parameter b and the corresponding tweak to tstar: tstar1 = 37.8275; %tstar for b = .05, it runs just fine and produces the damped oscillations I expect from the system.
Any ideas what could be causing the issue?

采纳的回答

Torsten
Torsten 2025-11-6,2:07
编辑:Torsten 2025-11-6,10:09
The history function has to cover values for t that are negative (because y6 becomes large and you have to supply y1(t-y6)). But you only supply history data for y1(t), y2(t) and y3(t) between 0 and tstar for t. This means that IC1(t), IC2(t) and IC3(t) will return NaN. Something like
t = 0:0.1:1;
y = t.^2;
interp1(t,y,-2,'linear')
ans = NaN
  4 个评论
Torsten
Torsten about 19 hours 前
编辑:Torsten about 18 hours 前
Resetting the "ddeset" option of "RelTol=1e-12" makes negative time values in "history" disappear. I nonetheless used an if-statement to avoid possible NaN values returned from "interp1" for the case that parameters might be changed.
Thus your original code would have worked (at least up to t = 800) if you hadn't requested such a stringent precision.
%(Q=20, a=5, k=1, ell=10)
tstar = 60.2762; %tstar for b=.03
tspan = [tstar 800];
preTstarSol = ode45(@odefun, [0 tstar], [20 0 0]);
options = [];%ddeset(RelTol=1e-12);
sol = ddesd(@ddefun, @dely, @history, tspan, options);
axes
hold on
plot(sol.x,sol.y);
legend('C','n1','m1','n2','m2','tau')
hold off
%xlim([0 400])
xlabel('Time (s)')
ylabel('Total Fission Rate (nM/s)')
plot(preTstarSol.x,preTstarSol.y);
legend('C','n1','m1');
function dydt = odefun(t,y)
b = .03;
k = 1;
dydt = [-k*y(1)^2 - k*y(1)*y(2) + b*y(3);
k*y(1)^2 - b*y(2);
k*y(1)*(y(1) + y(2)) - b*y(3);
];
end
function dydt = ddefun(t,y,Z) % equation being solved
b = .03;
k = 1;
a = 5;
ell = 10;
dydt = [a*y(5) - k*y(1) - k*y(1)*(y(2) + y(4)) + b*(y(3) + y(4));
-k*y(1)*(Z(1,1)*exp(-b*y(6)) - y(1)) - b*y(2);
-k*y(1)*(ell*Z(1,1)*exp(-b*y(6)) - y(1) - y(2)) - b*y(3);
k*y(1)*Z(1,1)*exp(-b*y(6)) - a*y(4);
k*y(1)*(ell*Z(1,1)*exp(-b*y(6)) + y(4)) - a*y(5);
1 - y(1)/Z(1,1)
];
end
%-------------------------------------------
function d = dely(t,y) % delay for y
d = t - y(6);
end
%-------------------------------------------
function v = history(t) % history function for t < t0
tstar = 60.2762; %tstar for b=.03
if t < 0
v = [20;
0;
0;
0;
0;
tstar];
return
end
preTstarSol = ode45(@odefun, [0 tstar], [20 0 0]);
% Here is the change I made, having each initial condition function be
% constant at it's time=0 value for all time between -10 and 0.
IC1 = interp1(preTstarSol.x, preTstarSol.y(1,:), t, 'linear');
IC2 = interp1(preTstarSol.x, preTstarSol.y(2,:), t, 'linear');
IC3 = interp1(preTstarSol.x, preTstarSol.y(3,:), t, 'linear');
v = [IC1;
IC2;
IC3;
0;
0;
tstar];
end
%-------------------------------------------
Kitrick
Kitrick about 17 hours 前
编辑:Kitrick about 15 hours 前
Thank you again for your help. This has fixed the issue I was having. It is with some embarassment that I must admit the real issue for why the solution was not behaving the way I was expecting is that the line:
dydt = [a*y(5) - k*y(1) - k*y(1)*(y(2) + y(4)) + b*(y(3) + y(4));
should actually be
dydt = [a*y(5) - k*y(1)^2 - k*y(1)*(y(2) + y(4)) + b*y(3);
Another great reminder to double, triple, quadruple check that you copied the system from your notes to the computer correctly.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Programming 的更多信息

产品


版本

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by