3
$\begingroup$

I have the the function

kill[x_]:=Map[#->0&,x]

which is supposed to set a list of functions to zero. That seems to be working, because

kill[{a,b}]

yields

{a->0,b->0}

but when I want to use this in a WhenEvent[] Environment it remains unevaluated. The function that I use is

wepr[f1_,x_]:=WhenEvent[f1==0,kill[x]]

Do you have any ideas?

Thank you!


EDIT:

Please consider: for easier reading, i wrote rel1 instead of Subscript[rel,i], so the index does work.

I have a table which creates the equations for my set of ODEs

eqns = DeleteDuplicates@Flatten@Table[{
reli'[t]==...,

relj'[r]==...,

wepr[reki[t], {cri[t], reli[t]}]

,{i,1,Nre},{j,1,Npr}]

Which I then solve in

NDSolve[eqns,...]

This all works fine.

I want to set the functions cr1[t] and rel1[t] to zero as soon as rek1[t] reaches zero. This works totally fine, when I write

wepr[f1_,f2_,f3_]:=WhenEvent[f1==0,{f2->0,f3->0}]

however this code needs to be adaptable.

$\endgroup$
8
  • $\begingroup$ Can you provide the syntax you use to run the function? & expected output? Thanks! $\endgroup$ Jan 20, 2020 at 15:15
  • $\begingroup$ From WhenEvent doc: WhenEvent expressions can be used in NDSolve, NDSolveValue, ParametricNDSolve, ParametricNDSolveValue, DSolve, and DSolveValue. $\endgroup$
    – Fortsaint
    Jan 20, 2020 at 15:18
  • $\begingroup$ @Fortsaint It is part of a NDSolve[ ] Environment. I have added some additional explanation $\endgroup$ Jan 20, 2020 at 15:27
  • $\begingroup$ @CATrevillian sure thing! Thank you for taking the time. $\endgroup$ Jan 20, 2020 at 15:34
  • 2
    $\begingroup$ WhenEvent (in *NDSolve*[] functions) can be finicky. Like Manipulate. They both rewrite your code before executing it. The rules literally present in action in WhenEvent[event, action] are replaced by NDSolve`SetState[] expressions for use in a function that handles the event. Since the literal, unevaluated expression kill[x] has no rules in it, no SetState[] actions will be included in the internal event function and nothing happens. It is unfortunate that it does not write the event function on the fly during integration, but the action is set before integration starts. $\endgroup$
    – Michael E2
    Jan 20, 2020 at 20:48

2 Answers 2

3
$\begingroup$

Use a rule for the WhenEvent action. Here's a silly example that kills whichever of the variables is greatest. Note that NDSolve passes the values of the variables to annihilateMax[v], not the variable names. So it returns a vector of numbers, with the greatest number replace by 0..

annihilateMax[v_] := v /. Max[v] -> 0.;

vars = Array[v, 4]; (* change 4 to get a different number of variables *)
varst = Through[vars[t]];
{sol} = NDSolve[{x'[t] == -y[t], y'[t] == x[t], x[0] == 1, y[0] == 0,
    D[varst, t] == RotateLeft[varst]/12, 
    Through[vars[0]] == RandomReal[1, Length@vars],
    WhenEvent[y[t] == 0 && x[t] > 0, # -> annihilateMax[#]] &@varst},
   vars~Join~{x, y}, {t, 0, 40}];

Plot[varst /. sol // Evaluate, {t, 0, 40}]

enter image description here

Not really sure what you want. To kill some variables you could use this:

WhenEvent[y[t] == 0, # -> 0*#]] &@ {x[1][t], x[4][t]}

That may be closer to how you intend to use kill.

$\endgroup$
0
$\begingroup$

Your fn will need to be in a list if they are singular. This is why I use Flatten@List@fn.

Maybe this will work for you?

wepr[f1_, fn___] := WhenEvent[f1 == 0, Evaluate[Rule[#, 0] & /@ Flatten@List@fn]];

Which works like this:

wepr[0, 1]

WhenEvent[0 == 0, {1 -> 0}]

wepr[0, {1, 2, 3}]

WhenEvent[0 == 0, {1 -> 0, 2 -> 0, 3 -> 0}]

wepr[0, 1, 2, 3]

WhenEvent[0 == 0, {1 -> 0, 2 -> 0, 3 -> 0}]

Hope this helps!

$\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.