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? –  Ｊ. Ｍ. Jun 9 '13 at 4:29
Im trying to solve a reaction diffusion equation with NDSolve, and reset the density function mid integration –  fernando Jun 9 '13 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}, –  fernando Jun 9 '13 at 4:39
that's the code im trying –  fernando Jun 9 '13 at 4:39
Well, please edit that code into your post, instead of posting that in comments... –  Ｊ. Ｍ. Jun 9 '13 at 4:43

1 Answer

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[
MapThread[Plot3D[
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]
xGridExtractor[f_] := InterpolatingFunctionCoordinates[Head[f]][[1]]

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. –  Michael E2 Jun 9 '13 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. –  Silvia Jun 9 '13 at 5:53
I like the use of Sign[], but maybe the PDE will look nicer if you use Piecewise[]. –  Ｊ. Ｍ. Jun 9 '13 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. –  Silvia Jun 9 '13 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.) –  Ｊ. Ｍ. Jun 9 '13 at 20:41