5
$\begingroup$

I am trying to add a time dependent fraction to a parameter in NDSolve, i.e. when 10 < t< 20, add s to k1...

Manipulate[ sol = NDSolve[{A'[t] == k1*A[t], A[0] == 10, 
                           WhenEvent[ 10 < t < 20, k1 -> (k1 + s)]},
                           A, {t, 0, 100}],
            {k1, 0.0, 1.0}, {s, 0.0, 1.0}]

But I cannot get the code to work, and get the following error message. Does anyone have any suggestions, or can find the error in the code?

NDSolve::wenset: Warning: the rule FE`k1$$16->FE`k1$$16+FE`s$$16 will not
directly set the state because the left-hand side is not a list of state variables. >>
$\endgroup$

4 Answers 4

3
$\begingroup$

I don't think you can use WhenEvent to do what you want. The value of k1 is passed in the DE in NDSolve, not the symbol. WhenEvent has the attribute HoldAll, so that it deals with k1 and s as Symbols. Perhaps you could use ParametricNDSolve (see below).

Perhaps you want something like this?

kparam[t_?NumericQ, k1_, s_] := If[10 < t < 20, k1 + s, k1];
Manipulate[
 sol = NDSolve[{A'[t] == kparam[t, k1, s]*A[t], A[0] == 10}, A, {t, 0, 100}],
 {k1, 0.0, 1.0}, {s, 0.0, 1.0}]

The solution (for k1 == 0.1, s == 0.2) looks like this:

Plot[Evaluate[A[t] /. sol], {t, 0, 30}]

Plot of a solution

This accomplishes the same thing with ParametricNDSolve (if you have v9.0.1):

psol = ParametricNDSolve[{A'[t] == k1*A[t], A[0] == 10, 
   WhenEvent[t < 10, k1 -> (k1 + s)], 
   WhenEvent[t < 20, k1 -> (k1 - s)]}, 
  A, {t, 0, 100}, {k1 \[Element] Reals, s \[Element] Reals}];

Plot[Evaluate[A[0.1, 0.2][t] /. psol], {t, 0, 30}]
  (* output same as above *)
$\endgroup$
1
  • $\begingroup$ Thanks, all solutions are great! $\endgroup$
    – tarhawk
    Apr 29, 2013 at 2:04
3
$\begingroup$

I'd like to extend the solution offered by Michael E2:

psol = ParametricNDSolve[{A'[t] == k1*A[t], A[0] == 10, 
    WhenEvent[t < 10, k1 -> (k1 + s)], 
    WhenEvent[t < 20, k1 -> (k1 - s)]}, 
   A, {t, 0, 100}, {k1 \[Element] Reals, s \[Element] Reals}];
(*Plot[Evaluate[A[0.1, 0.2][t] /. psol], {t, 0, 30}]*)

Note that even in the case the DE has two WhenEvents one can find the sensitivity of k1:

Plot[Evaluate[(A[0.1, 0.2][t] + {0, .1, -.1} D[A[k1, 0.2], k1][t] /. 
     k1 -> 0.1) /. psol], {t, 0, 30}, Filling -> {2 -> {3}}]

That's pretty cool!

enter image description here

$\endgroup$
2
$\begingroup$

You don't need WhenEvent[] for this:

Manipulate[Plot[(A/. NDSolve[{A'[t] == (k1 + s HeavisidePi[1/10 (t - 15)]) A[t], A[0] == 10},
                              A, {t, 0, 100}] [[1]] )[x], {x, 0, 30}], 
{k1, 0.0, 1.0}, {s, 0.0, 1.0}]

enter image description here

$\endgroup$
2
$\begingroup$

You do not need WhenEvent here as stated. You can use it though but you have to treat k as a function of t, that is a discrete state variable k[t].

Manipulate[
 DynamicModule[{
   sol = NDSolveValue[{
      y'[t] == k[t] y[t],
      y[0] == 10, k[0] == k0,
      WhenEvent[t > 10, k[t] -> k[t] + s],
      WhenEvent[t < 20, k[t] -> k[t] - s]
      }, y, {t, 0, 100},
     DiscreteVariables -> k]},
  Plot[sol[t], {t, 0, 30}]],
 {{k0, .1}, 0, 1}, {{s, .2}, 0, 1}]

(* similar output *)
$\endgroup$

Your Answer

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

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