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

Mathematica graphics