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

65 Ansichten (letzte 30 Tage)
Kitrick
Kitrick am 6 Nov. 2025 um 0:25
Bearbeitet: Kitrick am 6 Nov. 2025 um 22:42
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?

Akzeptierte Antwort

Torsten
Torsten am 6 Nov. 2025 um 2:07
Bearbeitet: Torsten am 6 Nov. 2025 um 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 Kommentare
Torsten
Torsten am 6 Nov. 2025 um 18:26
Bearbeitet: Torsten am 6 Nov. 2025 um 19:34
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 am 6 Nov. 2025 um 20:36
Bearbeitet: Kitrick am 6 Nov. 2025 um 22:42
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.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Programming finden Sie in Help Center und File Exchange

Produkte


Version

R2024b

Community Treasure Hunt

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

Start Hunting!

Translated by