# WhenEvent in NDSolve

How come this doesn't work as I intended?

s[{x0_, y0_}, a_, v_] := NDSolveValue[{
x'[t] == vx[t], WhenEvent[x[t] > 0, vx[t] -> -vx[t]],
y'[t] == vy[t] - t, WhenEvent[y[t] < 0, vy[t] -> -vy[t]],
x[0] == x0, vx[0] == v Cos@a,
y[0] == y0, vy[0] == v Sin@a},
{x[t], y[t]}, {t, 0, 10},
DiscreteVariables -> {vx, vy}]


Simulating falling and bouncing of a 2D mass point.

With[{r0 = {-5, 7}},
ParametricPlot[Evaluate@s[r0, -.9, 2],
{t, 0, 10},
PlotRange -> {{-10, 10}, {-10, 10}},
Epilog -> {Point@r0}]]


I can't understand why it doesn't bounce on the x-axis first, and what does happen there anyway? Event x[t]>0 works fine.

-
Have you tried removing the WhenEvent for x[t]>0? Is it the other When Event still ignored? –  Spawn1701D Apr 10 '13 at 21:13
Try this WhenEvent[{x[t] > 0, y[t] <0}, If[x[t]>0,vx[t] -> -vx[t],vy[t] -> -vy[t] ]] I think you can have only one WhenEvent included. –  Spawn1701D Apr 10 '13 at 21:16
@Spawn1701D Gee, now the same "refraction" occurs at y-axis as well. –  BoLe Apr 10 '13 at 21:20
I read the manual and I thing that if you have more than one WhenEvents you have to put them in a list, e.g { WhenEvent[x[t] > 0, vx[t] -> -vx[t]], WhenEvent[y[t] < 0, vy[t] -> -vy[t]]} –  Spawn1701D Apr 10 '13 at 21:22

Here you have a bouncing ball simulation using WithEvents[]:

s[{x0_, y0_}, a_, v_] := NDSolveValue[
{
y''[t] == -1,
x'[t] == vx[t],
y[0] == y0,
x[0] == x0,
y'[0] == v Sin@a,
vx[0] == v Cos@a,
vy[0] == v Sin@a,
WhenEvent[y[t] < 0, y'[t] -> - y'[t]],
WhenEvent[x[t] > 0, vx[t] -> -vx[t]]},
{x, y}, {t, 0, 8},
DiscreteVariables -> {vx, vy}] ;

With[{r0 = {-1, 1}},
ParametricPlot[Through[s[r0, 1, 1][u]], {u, 0, 5}, PlotRange -> All,
Epilog -> {Point@r0}]]


-
That is weird. If anything, vy picks up, and what does vx[t] -> - 3 vx[t] mean? I'm running a physical system here! :) –  BoLe Apr 10 '13 at 22:11
Thanks. I made a conceptual mistake, I can now understand what was going on above. –  BoLe Apr 11 '13 at 19:09

Following help I started with lowering the order of equations (and so doubling the number of variables). Here I wrote the equations in a more familiar 2nd order; everything works as expected. I put the function below in a tiny loop which bisected the right initial velocity v0 that returns the ball in its starting position.

Could this be done within NDSolve? I looked Wolfram tutorial for Boundary Value Problems but haven't been able to figure it out.

sstop[{x0_, y0_}, a_, v0_] := NDSolveValue[{
x''[t] == 0, WhenEvent[x[t] > 0, x'[t] -> -x'[t]],
y''[t] == -1, WhenEvent[y[t] < 0, y'[t] -> -y'[t]],
WhenEvent[x[t] < x0, Sow[{t, y[t]}]; "StopIntegration"],
x[0] == x0, x'[0] == v0 Cos[a],
y[0] == y0, y'[0] == v0 Sin[a]},
{x[t], y[t]}, {t, 0, 20}] // Reap

-
If you have a new question, you should post it as a new question instead of an "answer" –  rm -rf Apr 12 '13 at 18:13
@rm-rf Even though it is sort of continuation of this question? I think I'll think about it for a bit before, don't want to pose a stupid question. –  BoLe Apr 12 '13 at 20:59
Well, in that case you can update your question. Note that where the line is drawn between a "continuation" and a "totally new question" differs from person to person, but updating the post is the way to go –  rm -rf Apr 12 '13 at 21:26