I do not think the problem is stiffness; nor is it, arguably, scaling. The values of the solution are on the order of 10^-14
to 10^-8
. The default setting for AccuracyGoal
is around 8
, which means that steps with an error of 10^-8
or less are acceptable. And they shouldn't be accepted with solutions that are so small.
[If you are unsure how precision and accuracy goals work in Mathematica, please see the appendix below first.]
A setting AccuracyGoal -> ag
needs to be high enough so that
$$\|{\bf X(t)}\| <\mskip-4mu< 10^{-ag}$$
I would suggest setting AccuracyGoal
to be about 8
digits above -Log10[size]
, where size
is the smallest value that should be considered significantly different from zero. (One might set it to Infinity
, even.)
The above rule of thumb suggests
AccuracyGoal -> 22
based on the initial condition y[0] == 1*10^(-14)
. In fact setting it to 16
(based on the norm of the initial conditions being approximately $\scriptstyle 10^{-8}$) or Infinity
both work, too.
s = NDSolve[{x'[t] == -k1*x[t]*y[t], y'[t] == -k3*y[t] + k1*x[t]*y[t],
x[0] == 1*10^(-8), y[0] == 1*10^(-14)}, {x, y}, {t, 0, 0.001},
AccuracyGoal -> 22
];
Why do scaling and increasing WorkingPrecision
work?
In @Goofy's answer, the rescaled x[t]
and y[t]
have values on the order of 10
to nearly 100000
. So the default AccuracyGoal
of around 8
is sufficiently high. One might say that the problem is poorly scaled with respect
to the accuracy goal.
Using WorkingPrecision -> 20
seems to be barely sufficient. It raises AccuracyGoal
to 10
. It raises PrecisionGoal
to 10
, too, but with a solution whose norm is around 10^-8
or less, such a PrecisionGoal
should be negligible compared to the effect of AccuracyGoal
. One can check that through most of integration interval, WorkingPrecision -> 20
produces a solution that has 1 to 3 digits of precision, which is in line with an error of 10^-10
in a solution of norm 10^-8
. (This was estimated by comparing it with a solution computed with WorkingPrecision -> 40
and assuming this solution was highly accurate.)
FWIW, the AccuracyGoal -> 22
solution above has 6-8 digits of precision throughout most of the integration interval. The worst precision in all methods (except the OP's) is around where the x
and y
components cross near t == 0.00014
.
Appendix: Error norms in Mathematica.
The above discussion assumes the reader is familiar with how error is compared with PrecisionGoal -> pg
and AccuracyGoal -> ag
. NDSolve
uses NDSolve`ScaledVectorNorm
, which is discussed in Norms in NDSolve. The approach is also discussed in the documentation for PrecisionGoal and AccuracyGoal. I give a brief explanation.
Let $\bf E$ be the estimated error in the solution ${\bf X}$. If the error $\bf E$ is less than $10^{-ag} + 10^{-pg}\,\|{\bf X}\|$, then the result is accepted; if not, then in NDSolve
the step size is adjusted or a warning or error is generated if the step size cannot be adjusted.
When $10^{-ag} >\mskip-4mu> 10^{-pg}\,\|{\bf X}\|$,
$$10^{-ag} + 10^{-pg}\,\|{\bf X}\| \approx 10^{-ag}$$
implies that if the error indicates that ${\bf X}$ is correct to at least $ag$ digits past the decimal point, the step is accepted.
When $10^{-pg}\,\|{\bf X}\| >\mskip-4mu> 10^{-ag}$,
$$10^{-ag} + 10^{-pg}\,\|{\bf X}\| \approx 10^{-pg}\,\|{\bf X}\|$$
implies that if the error indicates that ${\bf X}$ is correct to at least the leading $pg$ digits, the step is accepted.
Thus when
$$10^{-ag} >\mskip-4mu> 10^{-pg}\,\|{\bf X}\|$$
which usually happens when $\bf X$ is small, the errors that are nearly equal to $10^{-ag}$ are acceptable. Hence, solution values of this magnitude or less are being treated as roughly equivalent to zero. This is the issue in the OP.