3
$\begingroup$

I am trying to impose multiple action based on two conditions I have an If statement inside a WhenEevent.

The problem I am facing is that I can only impose one action a(t) or b(t) if I impose the two action the code doesn't recognize it.

a(t) and b(t) are discrete variables that I want them to change every single time x(t)==0 and x'(t)<0 as they accumulate everytime they change as shown in the WhenEvent function. Should I use the Block function?

Is there an alternative way of imposing multiple conditions inside the If function because it only seem capable of doing 1 action at a time. Thank you

IC = {x[0] == 1, x'[0] == 0, a[0] == 10, b[0] == 0.1};

sol=NDSolve[
   {x''[t] + b[t] x'[t] + a[t] x[t] == 0,
    WhenEvent[x[t] == 0, If[x'[t] < 0, a[t] -> 3 - x[t] && b[t] -> 0.1 - x'[t]]],
    IC}, 
   {x[t], a[t], x'[t], b[t]}, {t, 0, 5}, DiscreteVariables -> {a[t], b[t]}]
Plot[{x[t], a[t]} /. sol, {t, 0, 5}]
Plot[{x'[t], b[t]} /. sol, {t, 0, 5}]
$\endgroup$
1
  • 1
    $\begingroup$ Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$
    – Michael E2
    Mar 7, 2017 at 23:54

2 Answers 2

4
$\begingroup$

An action in WhenEvent should be a Rule or a keyword string (see docs), or a list of these. Instead of If to impose a condition on an event, use And: WhenEvent[event && condition, action].

IC = {x[0] == 1, x'[0] == 0, a[0] == 10, b[0] == 0.1};

sol = NDSolve[{x''[t] + b[t] x'[t] + a[t] x[t] == 0,
   WhenEvent[x[t] == 0 && x'[t] < 0, {a[t] -> 3 - x[t], b[t] -> 0.1 - x'[t]}],
   IC},
  {x[t], a[t], x'[t], b[t]}, {t, 0, 5}, 
  DiscreteVariables -> {a[t], b[t]}]
Plot[{x[t], a[t]} /. sol, {t, 0, 5}]
Plot[{x'[t], b[t]} /. sol, {t, 0, 5}]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ Thank you I understand that but I am wanting to do it with If instead of only WhenEvent $\endgroup$
    – Zack
    Mar 8, 2017 at 19:42
1
$\begingroup$

Inside If, separate statements with a semicolon, not &&, the code does something. But, it is wrong, and I don't yet know why it is giving wrong output.

 IC = {x[0] == 1, x'[0] == 0, a[0] == 10, b[0] == 1/10};
sol = NDSolve[{x''[t] + b[t] x'[t] + a[t] x[t] == 0, 
    WhenEvent[x[t] == 0, 
     If[x'[t] < 0, a[t] -> 3 - x[t]; b[t] -> 0.1 - x'[t]]], IC}, {x, 
    a, b}, {t, 0, 5}, DiscreteVariables -> {a, b}];
Plot[{x[t], a[t]} /. sol, {t, 0, 5}]
Plot[{x'[t], b[t]} /. sol, {t, 0, 5}]

It looks like a sequence of actions written within If command doesn't work well, thus using two WhenEvent makes it work.

IC = {x[0] == 1, x'[0] == 0, a[0] == 10, b[0] == 1/10};
sol = NDSolve[{x''[t] + b[t] x'[t] + a[t] x[t] == 0, 
    WhenEvent[x[t] == 0, If[x'[t] < 0, b[t] -> 0.1 - x'[t]]], 
    WhenEvent[x[t] == 0, If[x'[t] < 0, a[t] -> 3 - x[t]]], IC}, {x, a,
     b}, {t, 0, 5}, DiscreteVariables -> {a, b}];
Plot[{x[t], a[t]} /. sol, {t, 0, 5}]
Plot[{x'[t], b[t]} /. sol, {t, 0, 5}]
$\endgroup$
4
  • $\begingroup$ What makes you think it works? The discrete variables a[t] and b[t] should change at the same time, but they do not. $\endgroup$
    – Michael E2
    Jul 11, 2019 at 19:22
  • $\begingroup$ @MichaelE2 I made a mistake, I did not check the result. Sorry about this. I don't know why it doesn't work though, trying to figure it out. $\endgroup$ Jul 17, 2019 at 13:36
  • $\begingroup$ I think the reason the first answer does not work is that in the value of the CompoundExpression in the If statement, a[t] -> 3 - x[t]; b[t] -> 0.1 - x'[t], is the last expression b[t] -> 0.1 - x'[t]; any expressions before a semicolon are ignored except for any side effects they have through setting a variable's value, but a Rule such as a[t] -> 3 - x[t] has no such side effect. That said, WhenEvent does rewrite the code, so you can't always count on things being as they seem. You might try a List instead of CompoundExpression: { a[t] -> 3 - x[t], b[t] -> 0.1 - x'[t]} $\endgroup$
    – Michael E2
    Jul 18, 2019 at 0:21
  • $\begingroup$ @MichaelE2 Thank you very much for this CompoundExpression. It works well, and resolved few issues for me. $\endgroup$ Jul 20, 2019 at 12:09

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.