Sign up ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a discontinuous function ($u(t)$, a square wave) and I would like WhenEvent to trigger when the signal goes high/low, i.e. when the value of $u(t)$ changes. I was hoping to use the derivative of $u(t)$ to determine this.

squareWave[t_, period_, duty_] := UnitBox[Mod[t/period, 1.]/(2. duty)]

system =  {x'[t] == u[t], WhenEvent[Mod[t, 0.5 τ], 
    u[t] -> squareWave[t, 2 τ, 0.2]], x[0] == 0, u[0] == 1, 
    WhenEvent[D[u[t]] > 0, Print[t]]};
params = {τ -> 1};
sol = NDSolve[system /. params, {x, u}, {t, 0, 10}, 
   DiscreteVariables -> u];
Plot[Evaluate[{x[t], u[t], u'[t]} /. sol], {t, 0, 10}, 
   PlotLegends -> {"x(t)", "u(t)", "u'[t]"}]

Unfortunately this does not seem to work? The output is:


share|improve this question
for me with 9.0.1 this gives the error "NDSolve::disder: Cannot take the derivative of discrete variable u." which seems quite self explaining. Other than that it seems to work, although as the squareWave only depends on time you wouldn't really need a WhenEvent. Which version/OS are you using? – Albert Retey Jul 30 '13 at 9:05
I was using 9.0.0 on OS X, but updated to 9.0.1 and now I also see the proper error message. I'll update the question. – Gerrit Jul 30 '13 at 15:37
@Nasser Isn't the derivative of a square wave a series of dirac delta functions, each positioned where the amplitude changes? – Gerrit Jul 31 '13 at 11:40
@Nasser Good point! I've replaced UnitBox with HeavisidePi, but it still doesn't work. – Gerrit Jul 31 '13 at 12:04

1 Answer 1

The reason why D[u[t]]>0 doesn't work is that the derivative at the changing point doesn't exist. You can verify this by:

D[UnitBox[x], x]

$\begin{array}{cc} \{ & \begin{array}{cc} \text{Indeterminate} & x=\frac{1}{2}\lor x=-\frac{1}{2} \\ 0 & \text{True} \\ \end{array} \\ \end{array}$

So the predicate in WhenEvent never come true.

If you refer to the documentation, in the details and options of WhenEvent, you may pay great attention to this

pred the predicate pred becomes True
f==0&&pred f crosses zero and pred is True

In the first case, your action in WhenEvent is evaluated only when pred jump from false to true. While in the second case, action is evaluated when pred keeps true and f crosses zero.

So for your purpose, you may change the WhenEvent part to this

WhenEvent[{u[t] == 0, u[t] == 1}, Print[t]]
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.