# WhenEvent and partial derivatives

Can WhenEvent be used to reset the conditions on a PDE at a given time? How would the syntax of that be?

This is the code Im using

r = 2;
d2 = 1;
l = 5;
sol = NDSolve[{Derivative[0, 1][n][x, t] ==
d2 Derivative[2, 0][n][x, t] + r*n[x, t]*(1 - n[x, t]),
n[x, 0] == 0.1*x*(1 - x/l), n[0, t] == 0, n[l, t] == 0,
WhenEvent[t == 50, n[x, t] -> 0]}, {n}, {x, 0, l}, {t, 0, tmax}]

• Could you maybe specify the particular PDE you're working with, so that it's easier for us to show you how? Commented Jun 9, 2013 at 4:29
• Im trying to solve a reaction diffusion equation with NDSolve, and reset the density function mid integration Commented Jun 9, 2013 at 4:36
• sol = NDSolve[{ \!( *SubscriptBox[([PartialD]), (t)](n[x, t])) == d2*\!( *SubscriptBox[([PartialD]), (x, x)](n[x, t])) + r*n[x, t]*(1 - n[x, t]), n[x, 0] == 0.1*x*(1 - x/l), n[0, t] == 0, n[l, t] == 0, WhenEvent[t == 50, n[x, t] -> 0]}, {n}, {x, 0, l}, {t, 0, tmax}, Commented Jun 9, 2013 at 4:39
• that's the code im trying Commented Jun 9, 2013 at 4:39

According to the error message:

NDSolve::nlnum1: "The function value {0} is not a list of numbers with dimensions {25} when the arguments are {50.,{<<25>>}."

I think you should feed a 25-length list of 0 to n[x,t] in the WhenEvent:

WhenEvent[t > 50, n[x, t] -> ConstantArray[0, 25]]


Plot the result:

Plot3D[Evaluate[n[x, t] /. sol], {x, 0, l}, {t, 0, 100}, PlotPoints -> 50]


Edit:

According to the documentation, NDSolve automatically does processing for discontinuous functions like Sign, so here an alternative way which do not require manual specifying the number of grid nodes (i.e. 25):

sol2 = NDSolve[{
Derivative[0, 1][n][x, t] ==
d2*Derivative[2, 0][n][x, t] +
r*Sign[50 - t]*n[x, t]*(1 - Sign[50 - t]*n[x, t]),
n[x, 0] == 0.1*x*(1 - x/l),
n[0, t] == 0,
n[l, t] == 0},
{n}, {x, 0, l}, {t, 0, 100}]


Note the difference near the discontinuity line between this solution and sol by above WhenEvent:

Show[
Evaluate[n[x, t] /. #1], {x, 0, l}, {t, 49, 53},
PlotPoints -> 50, PlotStyle -> None,
MeshFunctions -> (#1 &), MeshStyle -> #2,
BoundaryStyle -> None, PlotRange -> All
] &,
{{sol, sol2}, {Red, Blue}}
]]


Edit 2:

Using WhenEvent with automatic detecting the x-grid:

<< DifferentialEquationsInterpolatingFunctionAnatomy
Clear[xGridExtractor]

sol = NDSolve[
{
Derivative[0, 1][n][x, t] == d2*Derivative[2, 0][n][x, t] + r*n[x, t]*(1-n[x, t]),
n[x, 0] == 0.1*x*(1 - x/l),
n[0, t] == 0,
n[l, t] == 0,
WhenEvent[t > 50, n[x, t] -> 0*xGridExtractor[n[x, t]]]
},
{n}, {x, 0, l}, {t, 0, 100}]


Edit 3:

According to OP's comment, here is how to reset the initial condition along $t=50$ in a more general sense:

sol = NDSolve[
{
Derivative[0, 1][n][x, t] == d2*Derivative[2, 0][n][x, t] + r*n[x, t]*(1-n[x, t]),
n[x, 0] == 0.1*x*(1 - x/l),
n[0, t] == 0,
n[l, t] == 0,
WhenEvent[t > 50, n[x, t] -> (.5 Head[n[x, t]] /@ xGridExtractor[n[x, t]])]
},
{n}, {x, 0, l}, {t, 0, 100}]

Plot3D[Evaluate[n[x, t] /. sol], {x, 0, l}, {t, 49, 51},
PlotPoints -> 50, MeshFunctions -> {#2 &, #3 &}, Exclusions -> t == 50]


• +1. I was just writing such an answer! The array seems to reinitialize the values of n[x, 50] along the line 0 <= x <= l -- probably the interpolation grid. Commented Jun 9, 2013 at 5:40
• @MichaelE2 Thanks and agree. I think there should be an alternative way which does not require manual specifying the number of grid nodes. Commented Jun 9, 2013 at 5:53
• I like the use of Sign[], but maybe the PDE will look nicer if you use Piecewise[]. Commented Jun 9, 2013 at 20:26
• @0x4A4D I just tried Piecewise, and I think I'd prefer the WhenEvent version. Neither Sign nor Piecewise are as good as WhenEvent` near the discontinuity interface. Commented Jun 9, 2013 at 20:36
• That's too bad. I was hoping for an alternative that'd also work in earlier versions of Mathematica. (I'm still on version 8.) Commented Jun 9, 2013 at 20:41