8

As has been mentioned before, Piecewise causes the Mathematica Kernel to fail to during a NDSolve calculation. How can I write the function below without using Piecewise?

s[t_] := Piecewise[{{1, t < 300.}, {0, 300. <= t < 1500.}, {1, t <= 3600}}];
Plot[s[t], {t, 0., 4000.}]
MarcoB
  • 67,153
  • 18
  • 91
  • 189
tarhawk
  • 769
  • 5
  • 15
  • 1
    More often than not Piecewise causes NDSolve to succeed in my experience. – Michael E2 Apr 23 '16 at 19:33
  • I think Piecewise is the most straightforward method to use. But it is a little frustrating that he kernel crashes so often. Is there any precedent that the cause of the failures is related to the use of reals in the function definition for the independent variable t? – tarhawk Apr 24 '16 at 20:24
  • Yes, I think the use of approximate reals can make the analysis of the discontinuities computationally harder. Rounding error from transformations might slightly perturb quantities that ought to match up, for instance; x^0.5 is very different from x^(1/2), and so on. When someone here posts a problem with NDSolve[sys,...] and it seems related to this issue, I usually try it with NDSolve[Rationalize[sys, 0],...], if nothing else seems more likely. – Michael E2 Apr 24 '16 at 20:34

2 Answers2

11

You can use the functions Simplify`PWToUnitStep and Simplify`SimplifyUnitStep to convert a Piecewise function to one using UnitStep:

s[t_] := Piecewise[{{1, t < 300.}, {0, 300. <= t < 1500.}, {1, t <= 3600}}];
s2[t_] := Simplify`SimplifyUnitStep[Simplify`PWToUnitStep[s@t]];
s2[t]

1 - UnitStep[-300. + t] + UnitStep[3600 - t, -1500. + t]

To use HeavisideTheta instead of UnitStep:

s2[t] /. UnitStep -> HeavisideTheta

1 - HeavisideTheta[-300. + t] + HeavisideTheta[3600 - t, -1500. + t]

Row[Plot[#, {t, 0., 4000.}, PlotStyle -> Thick, ImageSize -> 300] & /@ {s[t], s2[t]}]

Mathematica graphics

kglr
  • 394,356
  • 18
  • 477
  • 896
  • +1 @kglr, This is great. Is there a quick way to see other simplify subroutines in the Front-End? – Rashid Apr 23 '16 at 18:56
  • @RashidZia, thanks for the vote. Perhaps ?? Simplify`*? – kglr Apr 23 '16 at 19:03
  • @ kglr, thanks again. I got it to work with ?"Simplify`*" BTW there is also a Simplify`PWToHeavisideTheta function. – Rashid Apr 23 '16 at 19:11
  • @RashidZia, I don't see a PWToHeavisideTheta function in Version 9. – kglr Apr 23 '16 at 19:18
  • I am using Version 10.4 and this is what I see – Rashid Apr 23 '16 at 19:22
  • @RashidZia, that's great! Yet another reason to upgrade to v10:) Maybe you can update your answer with that alternative. – kglr Apr 23 '16 at 19:27
  • @ kglr, unfortunately, Simplify`PWToHeavisideTheta doesn't seem to evaluate for this case, even if I play with the piecewise boundary inequalities. Perhaps some else knows how to use it.... – Rashid Apr 23 '16 at 19:34
  • 1
    I encountered an annoying issue with Simplify`PWToUnitStep: if the original Piecewise expression has an Indeterminate branch (even at a single point), the whole result becomes Indeterminate. The workaround I use is to replace Indeterminate with HeavisideTheta[0] before calling Simplify`PWToUnitStep. – Vladimir Reshetnikov Jun 25 '21 at 17:23
6

Two alternatives (depending on application) would be UnitStep and HeavisideTheta. For example,

sU[t_] := UnitStep[300 - t] + UnitStep[t - 1500, 3600 - t]
sH[t_] := HeavisideTheta[300 - t] + HeavisideTheta[t - 1500, 3600 - t]

For differential equations, I would use HeavisideTheta.

Rashid
  • 1,523
  • 10
  • 18