# Using WhenEvent for derivative of discontinuous function

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:

-
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

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]]

-