14
$\begingroup$

I have no idea how to dynamically update a parameter inside NDSolve. For example consider following first-order DE:

Eq = x'[t] + (x[t] - λ) == 0;

where λ is a parameter. I want to solve this ODE but this parameter might change when x'[t] turns to zero:

WhenEvent[x'[t] == 0, λ -> x[t]].

I tried following code, but that doesn't work. Any idea?

λ = 1;
Eq = x'[t] + (x[t] - λ) == 0;
sol = NDSolve[{Eq, x[0] == 0,
               WhenEvent[x'[t] == 0., λ -> x[t]]
              }, x, {t, 0, 5}][[1]]
$\endgroup$
3
  • $\begingroup$ Does this get what you need: NDSolve[{x'[ t] + (x[t] - Boole[x'[t] == 0.] x[t] - \[Lambda] (1 - Boole[x'[t] == 0.])) == 0, x[0] == 0}, x, {t, 0, 5}]? $\endgroup$
    – kglr
    May 1, 2014 at 20:17
  • $\begingroup$ .. modify your when-event to WhenEvent[x'[t] == 0., x[t] -> x'[t]? $\endgroup$
    – kglr
    May 1, 2014 at 20:25
  • 1
    $\begingroup$ Are you sure the condition x'[t]==0 actually occurs? Look at DSolve[{x'[t]+(x[t]-\[Lambda])==0,x[0]==0},x,t] $\endgroup$
    – chuy
    May 1, 2014 at 20:29

2 Answers 2

20
$\begingroup$

There are other approaches to achieve what you have described. As I guess this is only a simplification of what you really need, here is how you would do it with WhenEvent:

equation = x'[t] + (x[t] - λ[t]) == 0;
sol = NDSolveValue[{equation, x[0] == 0, λ[0] == 1, 
   WhenEvent[x'[t] == 0.25, λ[t] -> x[t]]}, x, {t, 0, 5}, 
  DiscreteVariables -> {λ}]

the trick is to make λ a discrete dependent variable for the equation. I think this is not straightforward to find in the documentation as I remember I was also struggling with it when I first needed it. A discrete dependent variable will need an initial value but no differential equation and can be changed at any event just as other dependent variables (and only there). It will also become a function of time and can be in the list of variables to solve for at position 2 of the call to NDSolve. Once one knows how it works all that seems to be very consistent. The documentation for DiscreteVariables has some examples which are very close to your problem...

EDIT 2023-03-01

as @xzczd mentioned, this stopped working with newer versions. It can be made working by either adding the option SolveDelayed->True or, as that seems to be deprecated the newer version of that: Method -> {"EquationSimplification" -> "Residual"}

$\endgroup$
3
  • $\begingroup$ Can you tell me how to solve this eigenvalue problem which arises in the study of stability of flows through porous media Equaitons: (D^2-A^2)f + (AR)h=0 and (D^2-A^2)h + i*(Lambda - F(z))h + 2*i*(C/R)*Df Af=0. Now the conditions are f=h=0 at Z=0,1. In the above R is the Rayleigh number, Lambda is the exponential growth rate parameter, A is the overall wave number. D=d/dz. f and h are eigne functions. We want to plot R vs A and also finding oscillatory modes if exists. Plotting eigenfuctions as well. Can any one help me to solve this using Mathematica NDsolve.. $\endgroup$
    – PAL
    Oct 27, 2016 at 6:51
  • 1
    $\begingroup$ If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From Review $\endgroup$
    – corey979
    Oct 27, 2016 at 8:03
  • 2
    $\begingroup$ A bug seems to be introduced after v9. For now (v13.2, also tested in v12.3), we need to add SolveDelayed -> True to make the code work. For more info: mathematica.stackexchange.com/a/280665/1871 $\endgroup$
    – xzczd
    Feb 28, 2023 at 8:45
2
$\begingroup$

Excursion: Using Modelica within WL

I would like to mention this possibility here as importing and running Modelica has since been implemented within the System Modeling Functionality in the Wolfram Language. The above system of ODEs can be entered as a Modelica model using the following code:

codeString = "
model MSE47141
  Real x(start = 0.);
  discrete Real lambda(start = 1.);
algorithm
  when der(x) < 0.25 then
    lambda := x;
  end when;
equation
  0 = der(x) + (x - lambda);
end MSE47141;
";

model = ImportString[ codeString, "MO" ];
model["ModelicaDisplay"]

Modelica code

The code display is indicative for a correct interpretation of the Modelica code, which should be rather self-explanatory, if one accepts that when statements run in algorithm sections.

A couple of things to note:

  • Modelica will not allow using der(x) == 0.25 as opposed to NDSolve; we have to think in terms of crossing-functions.
  • The prefix discrete is given for clarity; the discreteness of lambda will automatically be deduced from it appearing in a when-statement should it be missing.

The thing to like about the System Modeling Functionality is added convenience imo: Fast access to nice plots and great flexibility for querying system's properties.

sim = SystemModelSimulate[ model, All, {0, 5},
  Method -> { "RungeKutta" }
];
SystemModelPlot[ sim, All ]

Simulation Plot

For some reason, the adaptive step methods (DASSL, CVODES) currently have difficulties detecting the event.

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