NDSolve with Piecewise gives the incorrect answer randomly
Following a lead from Albert Retey, I found an NDSolve
option that fixes this problem:
sol = NDSolve[{x'[t] ==
Piecewise[{{2, 0 <= Mod[t, 1] < 0.5},
{-1, 0.5 <= Mod[t, 1] < 1}}
], x[0] == 0}, x, {t, 0, 1}, Method -> {"DiscontinuityProcessing" -> False}];
Print[x[1] /. sol[[1]]];
This is not really an answer (the answer is of course that this is a bug), but it is too long for a comment and probably gives a hint where the problem is and how one can avoid it in other cases. The workaround is to define the piecewise function as an external definition only for numeric arguments. It looks like otherwise some invalid optimization with the symbolic expression is done:
ClearAll@rhs
rhs[t_?NumericQ] := Piecewise[{
{2, 0 <= Mod[t, 1] < 0.5},
{-1, 0.5 <= Mod[t, 1] < 1}
}]
Table[
sol = NDSolve[{x'[t] == rhs[t], x[0] == 0},
x, {t, 0, 1}
];
Plot[x[t] /. sol[[1]], {t, 0, 1}, PlotLabel -> (x[1] /. sol[[1]]),
Frame -> True, PlotRange -> All],
{10}
]
I have tested this with Mathematica 9.0.1 on Windows 7 64bit. Unlike for NIntegrate
there seems to not be a Method
option with which one could switch off the symbolic optimization, at least I didn't find one. It might well be there, even if not documented and of course might be a better workaround...
Another possible fix to the bug is to use Simplify`PWToUnitStep
to expand the Piecewise
into a combination of UnitStep
:
Table[NDSolveValue[{x'[t] ==
Simplify`PWToUnitStep@
Piecewise[{{2, 0 <= Mod[t, 1] < 0.5}, {-1, 0.5 <= Mod[t, 1] < 1}}], x[0] == 0},
x, {t, 0, 1}][1], {100}] // Union