I posted the solution I found in another thread (Constraining function found by NDSolve to stay positive) and I am reposting it here for convenience. However, in your particular case the model is not complete and you need to ensure that x'[t] is identically zero when x[t]<0. Here is your model with the necessary completion. The description is below.
ClearAll["Global`*"];
NnnX[x_?NumericQ] := ((x + Sqrt[x^2])/2);
UsbEEpsilonValue = 10^-3;
UnitStepBase[x_?NumericQ] :=
Piecewise[{{0, x < 0}, {(2*x^2 - x^4), 0 <= x < 1}, {1, x >= 1}}];
UsbE[x_?NumericQ, norm_?NumericQ] := UsbE[x, norm, UsbEEpsilonValue];
UsbE[x_?NumericQ, norm_?NumericQ, eps_?NumericQ] :=
UnitStepBase[x/(norm*eps)];
SomeNorm = 10;
f[t_] := a*r*1/(1 + E^(-p*(t - q)))
g[t_] := -b*r*1/(1 + E^(-p*(t - q)))
a = 1;
b = 1;
p = 8;
q = 5;
r = 1;
x0 = 2;
y0 = 2;
Plot[f[t], {t, -10, 20}]
system = {
Derivative[1][x][t] == UsbE[x[t], SomeNorm]*(-b NnnX[x[t]] + g[t] NnnX[y[t]])/NnnX[y[t]],
Derivative[1][y][t] == UsbE[y[t], SomeNorm]*(a NnnX[x[t]] + f[t] NnnX[y[t]])/NnnX[y[t]],
x[0] == x0,
y[0] == y0
};
s = NDSolve[system, {x, y}, {t, 0, 10}];
Plot[Evaluate[y[t] /. s], {t, 0, 10}, PlotRange -> All, Frame -> True, GridLines -> Automatic]
Plot[Evaluate[x[t] /. s], {t, 0, 10}, PlotRange -> All, Frame -> True, GridLines -> Automatic]
I had a very similar problem for a system of very large number of ODEs and none of the methods proposed above worked. The main reason is that the coefficient
If[x[t] >= 0, -10, 0]
is a stiff function. Several bad things happen because of that.
For stiff system the step size decreases substantially and it may
take forever to integrate. The simplest model I run has 11 variables
and that's exactly what I observed: the integration never finished!
NDSolve cannot know that the coefficient will be exactly zero for x[t]<0. What
happens is that as the complexity of the system increases there is a
high chance that NDSolve will overshoot zero and make some variables
negative. What happens next depends on your model. In my case the
model usually "exploded" and the variables started to run to plus and
minus infinities.
- In many cases it is necessary to just impose positivity constraint
and do not stop integration. In such case using WhenEvent and then
stopping integration does not help as we need to continue
integrating (while keeping a function at zero). At some point in
time the conditions may change and the function may become positive
again.
The solution I found involved several steps:
Any and all stiff functions should be replaced by "numerical" smoothed out functions. To do so I use a smoothed out UnitStep with some scale (norm) and stiffness (eps - default value =10^-3):
UsbEEpsilonValue=10^-3;
UnitStepBase[x_?NumericQ] :=
Piecewise[{{0, x < 0}, {(2*x^2 - x^4), 0 <= x < 1}, {1, x >= 1}}];
UsbE[x_?NumericQ, norm_?NumericQ] := UsbE[x, norm, UsbEEpsilonValue];
UsbE[x_?NumericQ, norm_?NumericQ, eps_?NumericQ] := UnitStepBase[x/(norm*eps)];
So instead of
If[x[t] >= 0, -10, 0]
I would write:
-10*UsbE[x[t],SomeNorm]
with, let's say
SomeNorm = 10;
The second step involves making sure that negative values of x[t] do not affect any other calculations. To do so I wrap all x[t] inside the derivative function
x'[t]==f[x[t]]
into another "numerical" function, which ensures that for negative x[t] we get exactly zero:
NnnX[x_?NumericQ] := ((x + Sqrt[x^2])/2);
and then eventually use:
x'[t]==UsbE[x[t],SomeNorm]*f[NnnX[x[t]]]
or
x'[t]==f[NnnX[x[t]]]
depending on the behavior of the term f. A small remaining problem is that if NDSolve does overshoot and makes x[t]<0 then there is no way for it to come back (in the first case): it will effectively stay at zero. This is not good if you have some terms, which may at some point increase x[t]. To deal with that it is important to identify the stiff terms, which may result in negative x[t] and deal with them in the described above way. You then just need to leave the positive terms with only NnnX[x[t]] wrappers.
You might wonder why using numerical functions? Well, I don't know. What I noticed is that NDSolve tries to evaluate all symbolic functions (except the ones, which can only be evaluated with numerical values). And when NDSolve encounters a lot of conditional functions (like If or Piecewise) then it starts to behave unpredictably.
x[t]
andy[t]
stay positive,x'[t]
approaches-1
or less ast -> Infinity
. (I getx'[t] == -(1/(1 + E^(-8 (-5 + t)))) - x[t]/y[t]
.) Hencex
would decrease to negative infinity over time. (Of course when the sign ofx
changes, it alters things.) Ifx
should be positive, perhaps you need to check your diff. eq. $\endgroup$(1)
and(0)
in front of the derivatives? They make things seemingly unnecessarily complicated. Are they just particular values for general parameters in your problem? I would have left them out of my answer, but I wanted to show how to deal with(0)*y'[t]
in the case the coefficient is nonzero. $\endgroup$