I try to solve a partial differential equation by NDSolve. At some point, I want to stop the integrating by a condition that compares the min value of the function with a threshold. I tried to use StopIntegration in the WhenEvent, and tried using NMinimize to find the min value of the function. But it does not seem stop the evaluation. From the warning message, I think the conditions of NMinimize[h[x, t], {x, t}] <= 0.01 I set for whenevent may be wrong. Could someone explain to me what is going on? How could I handle this problem? Is there any better or simpler way to do that? mdfun = First[h /. NDSolve[{D[h[x, t], t] + D[h[x, t]^-1*D[h[x, t], x], x] + D[h[x, t]^3*D[h[x, t], {x, 3}], x] == 0, h[0, t] == h[2 Sqrt[2] \[Pi], t], h[x, 0] == 1 + 1/10*Sin[x/Sqrt[2]], WhenEvent[NMinimize[h[x, t], {x, t}] <= 0.01, "StopIntegration"]}, h, {x, 0, 2 Sqrt[2] \[Pi]}, {t, 0, 10}, StepMonitor :> Print[t]]]

=================

=================

1 Answer

1

=================

Ok, at first you don’t solve your equation properly, the grid spacing is not enough for the entire time range. So first increase resolution, e.g.:

tmax = 10;

mdfun = NDSolveValue[

{D[h[x, t], t] + D[h[x, t]^-1*D[h[x, t], x], x] + D[h[x, t]^3*D[h[x, t], {x, 3}], x] == 0,

h[0, t] == h[2 Sqrt[2] \[Pi], t], h[x, 0] == 1 + 1/10*Sin[x/Sqrt[2]]},

h, {x, 0, 2 Sqrt[2] \[Pi]}, {t, 0, tmax},

AccuracyGoal -> 2, PrecisionGoal -> 2,

Method -> {“MethodOfLines”, “SpatialDiscretization” -> {“TensorProductGrid”,

“MinPoints” -> 3000, “MaxPoints” -> 3000}}];

Then you can get nice solution:

Plot[mdfun[x, #] & /@ Range[0, tmax, 1] // Evaluate, {x, 0, 2 Sqrt[2] \[Pi]},

PlotRange -> {0, 1.5}, PlotStyle -> Opacity /@ (Range[0, tmax, 1]/tmax)]

now you see that the event h<0.01 is never achived.
Secondly, NMinimize returns value in form {value, {x,y}}, so you should use NMinimize[..][[1]]. The other point you should properly specify the range of your variables for NMinimize like this (.6 - just some arb. limit):
NMinimize[{mdfun[a, b], 0 < a < 2 Sqrt[2] \[Pi], 0 < b < t}, {a, b}][[1]] < .6
Now the whole thing works, but very slow. I would suggest to make condition simply for point, where the min is located. find the minimum with previus solution:
xmin = x /. Minimize[{mdfun[x, t], 0 < x < 2 Sqrt[2] \[Pi], 0 < t < tmax}, {x, t}][[2]]
and rewrite whenevent:
WhenEvent[h[xmin, t] < .4, "StopIntegration"]
Then it will work much faster.
Hi,@funnypony! I adopted your suggestions except for grid spacing for faster here I set it is 300. I do think your advice is correct. Actually, I don't know the exact position where the min-value is located, the eqn. in my post just makes the issue simpler. Thus, I still use WhenEvent with NMinimize. But when I run it, MMA spits a stack of warning message. However, it still returns a result, when I plot it, I find WhenEvent doesn't work because the solution contains obviously value which is less than 0.6. Pls see the following code 🙂
– can
Oct 19 '14 at 15:18
tmax = 10; mdfun = First[ h /. NDSolve[{D[h[x, t], t] + D[h[x, t]^-1*D[h[x, t], x], x] + D[h[x, t]^3*D[h[x, t], {x, 3}], x] == 0, h[0, t] == h[2 Sqrt[2] \[Pi], t], h[x, 0] == 1 + 1/10*Sin[x/Sqrt[2]], WhenEvent[ NMinimize[{mdfun[x, t], 0 < x < 2 Sqrt[2] \[Pi], 0 < t < tmax}, {x, t}][[1]] < 0.6, "StopIntegration"]}, h, {x, 0, 2 Sqrt[2] \[Pi]}, {t, 0, tmax}, AccuracyGoal -> 2, PrecisionGoal -> 2, Method -> {“MethodOfLines”, “SpatialDiscretization” -> {“TensorProductGrid”, “MinPoints” -> 300, “MaxPoints” -> 300}}]]

– can

Oct 19 ’14 at 15:20

lxy, please look once again how i wrote whenevent – with a and b instead of x and t. x and t are ndsolve variables and better avoid inserting them in numerical functions. The other point – you search for min at each integration step, so at any time the boundary for this variable is not tmax but t. write it this way: NMinimize[{mdfun[a, b], 0 < a < 2 Sqrt[2] [Pi], 0 < b < t}, {a, b}][[1]] < .6 and it will work, but slow.. – funnypony Oct 19 '14 at 18:12 Thanks @funnypony, it does work now. Thanks for your helpful suggestions! – can Oct 20 '14 at 6:41