1
$\begingroup$

I need to use WhenEvent inside NDSolve in which events happen simultaneously.
I show simple code to better explain my question:

eqTime = {time'[t] == 1, time[0] == 0};
update1 = WhenEvent[Mod[t , 0.2], {a[t] -> a[t] + 0.1, Sow@a[t]}];
update2 = WhenEvent[Mod[t , 0.3], {a[t] -> a[t] + 1, Sow@a[t]}];
update3 = WhenEvent[Mod[t , 0.6], {a[t] -> a[t] + 2, Sow@a[t]}];
update = {update1, update2, update3};
ic = a[0] == 0;
{sol, data} = 
  NDSolveValue[{eqTime, update, ic}, a[t], {t, 0, 0.7}, 
    DiscreteVariables -> a[t]] // Reap;
data
(*{{0.1, 1.1, 1.2, 2.2, 4.2, 4.3}}*)

What I'd like to obtain is {{0.1, 1.1, 1.2, 3.2}} in such a way that when the events happen at the same time only one wins, update3 in this case.
Another question, why data is not {{.1, 1.1, 1.2, 1.3, 2.3, 4.3}} ? Which is the order of detection ?


An approach could be to make the event in this form Mod[t,ST1] && !Mod[t, ST2]. I've already read the documentation and previous questions about how WhenEvent manages the event trigger thereby I know it has no Mathematica meaning but is just to show one road to approach the problem.

Here is a simple code to represent the issue:

eqTime = {time'[t] == 1, time[0] == 0};
update = WhenEvent[Mod[t, 0.1] && !Mod[t,0.2], { a[t] -> a[t] + 0.1, Sow@a[t]}]; (*Not Working*)
ic = a[0] == 0;
{sol, data} = 
  NDSolveValue[{eqTime, update, ic}, a[t], {t, 0, 1}, 
    DiscreteVariables -> a[t]] // Reap;

Plot[sol, {t, 0, 1}]

The output should be a step function that increases at {0.1, 0.3, 0.5, 0.7, 0.9}.

$\endgroup$
5
  • $\begingroup$ @Bill Thanks for the answer. I know Mod[t, ST] is like a special function for WhenEvent and it doesn't return either True or False. It was just to show the behave I'd like to obtain. $\endgroup$ Commented May 3, 2021 at 9:47
  • $\begingroup$ @Bill Thanks, I've modified the answer because I wasn't explaining myself as I wanted. Your solution work for the last part of the question but it just translates in the time Mod[t, 0.2]. $\endgroup$ Commented May 3, 2021 at 13:36
  • $\begingroup$ @Bill Thanks for the answer, I understand your work around. The fact is that in my original problem I need to do other more complex actions and this solution doesn't fit $\endgroup$ Commented May 4, 2021 at 6:11
  • $\begingroup$ @Bill There is no need to be sorry, you have been very useful, my question was ill posed and thanks to you I caught it. $\endgroup$ Commented May 4, 2021 at 8:21
  • $\begingroup$ @Bill I made it ! I'm gonna post it as an answer hoping it will help someone else in the future $\endgroup$ Commented May 5, 2021 at 12:40

1 Answer 1

1
$\begingroup$

The best solution I've found is quite simple despite of the struggle in making everything works.

t0 = 0;
tfin = 300;
TS1 = 0.2 // Rationalize;
TS2 = 0.3 // Rationalize;
TS3 = 0.6 // Rationalize;
eqTime = {time'[t] == 1, time[0] == t0};
ac1 = {a[t] -> a[t] + 0.1, Hold@Sow@"a"};
ac2 = {a[t] -> a[t] + 1, Hold@Sow@"b"};
ac3 = {a[t] -> a[t] + 2, Hold@Sow@"c"};
update1 = 
  WhenEvent[Mod[t, TS1] && Mod[Rationalize@t, TS3] != 0, Evaluate@ac1];
update2 = 
  WhenEvent[Mod[t, TS2] && Mod[Rationalize@t, TS3] != 0, 
   Evaluate@ac2];
update3 = WhenEvent[Mod[t, TS3], Evaluate@ac3];
update = {update1, update2, update3};
ic = a[0] == 0;
{tempo, {sol, data}} = 
  NDSolveValue[{eqTime, update, ic}, {a[t], n[t]}, {t, t0, 0.65}, 
     DiscreteVariables -> a[t]] // Reap // AbsoluteTiming;
Plot[sol[[1]], {t, t0, 0.65}, PlotRange -> All]

enter image description here

data
{{"a", "b", "a", "c"}}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.