3
$\begingroup$

If I write this:

sol = NDSolveValue[{f'[t] == (0.4 - 0.01 s[t]) f[t], 
    s'[t] == (-0.3 + 0.005 f[t]) s[t], f[0] == 40, s[0] == 20}, {f[t],
     s[t]}, {t, 0, 80}];
r[t_] = sol;

Then do this:

Manipulate[
 Show[ParametricPlot[sol, {t, 0, 80},
   PlotRange -> {{0, 140}, {0, 100}}],
  Graphics[{Red, Arrow[{{0, 0}, r[tau]}], 
    Arrow[{r[tau], r[tau] + r'[tau]}]}]
  ],
 {{tau, 0}, 0, 80}]

I get a nice Manipulate I can use for a classroom demonstration.

enter image description here

However, if I later use the sol variable to draw another image (a Plot, a ParametricPlot), the new sol value interferes with the Manipulate demonstration. For example, if the next cell in the notebook has:

sol = NDSolveValue[{x'[t] == y[t], y[t] == -x[t], x[0] == 1, 
   y[0] == -1}, {x[t], y[t]}, {t, 0, 5}]

Then this version of sol is now used in the Manipulate demonstration above. So, I tried the following:

Manipulate[Module[{sol, r},
  sol = NDSolveValue[{f'[t] == (0.4 - 0.01 s[t]) f[t], 
     s'[t] == (-0.3 + 0.005 f[t]) s[t], f[0] == 40, 
     s[0] == 20}, {f[t], s[t]}, {t, 0, 80}];
  r[t_] = sol;
  Show[ParametricPlot[sol, {t, 0, 80},
    PlotRange -> {{0, 140}, {0, 100}}],
   Graphics[{Red, Arrow[{{0, 0}, r[tau]}], 
     Arrow[{r[tau], r[tau] + r'[tau]}]}]
   ]],
 {{tau, 0}, 0, 80}]

But it doesn't work. I get an error that I just cannot understand.

Coordinate {InterpolatingFunction[{{0., 80.}}, {5, 7, 1, {353}, {4}, 0, 0, 0, 0, Automatic, {}, {}, False}, {{0., 0.0005236906903058783, 0.0010473813806117565, 0.002094762761223513, 0.0031421441418352696, 0.004189525522447026, 0.014663339328564591`, 0.02513715313 should be a pair of numbers, or a Scaled or Offset form.

Any thoughts?

Sjoerd C. de Vries suggestion in comments:

Module[{sol, r}, 
 Manipulate[
  sol = NDSolveValue[{f'[t] == (0.4 - 0.01 s[t]) f[t], 
     s'[t] == (-0.3 + 0.005 f[t]) s[t], f[0] == 40, 
     s[0] == 20}, {f[t], s[t]}, {t, 0, 80}];
  r[t_] = sol;
  Show[ParametricPlot[sol, {t, 0, 80}, 
    PlotRange -> {{0, 140}, {0, 100}}], 
   Graphics[{Red, Arrow[{{0, 0}, r[tau]}], 
     Arrow[{r[tau], r[tau] + r'[tau]}]}]], {{tau, 0}, 0, 80}]]

Still gives the error:

Coordinate {InterpolatingFunction[{{0., 80.}}, {5, 7, 1, {353}, {4}, 0, 0, 0, 0, Automatic, {}, {}, False}, {{0., 0.0005236906903058783, 0.0010473813806117565, 0.002094762761223513, 0.0031421441418352696, 0.004189525522447026, 0.014663339328564591`, 0.02513715313 should be a pair of numbers, or a Scaled or Offset form.

Michael E2: If I run Michael E2 suggestion it works.

Clear[r];
sol = First@
   NDSolve[{r'[
       t] == ({0.4, -0.3} + {{0, -0.01}, {0.005, 0}}.r[t]) r[t], 
     r[0] == {40, 20}}, r, {t, 0, 80}];
With[{sol = sol}, 
 Manipulate[
  Show[ParametricPlot[r[t] /. sol, {t, 0, 80}, 
    PlotRange -> {{0, 140}, {0, 100}}], 
   Graphics[{Red, Arrow[{{0, 0}, r[tau]}], 
      Arrow[{r[tau], r[tau] + r'[tau]}]} /. sol]], {{tau, 0}, 0, 80}]]

enter image description here

Then if sol gets changed in the global workspace, it doesn't affect Michaels first graph. Note there are very minor changes.

sol = First@
   NDSolve[{r'[
       t] == ({0.4, -0.3} + {{0, -0.01}, {0.002, 0}}.r[t]) r[t], 
     r[0] == {40, 20}}, r, {t, 0, 80}];
With[{sol = sol}, 
 Manipulate[
  Show[ParametricPlot[r[t] /. sol, {t, 0, 80}, 
    PlotRange -> {{0, 140}, {0, 100}}], 
   Graphics[{Red, Arrow[{{0, 0}, r[tau]}], 
      Arrow[{r[tau], r[tau] + r'[tau]}]} /. sol]], {{tau, 0}, 0, 80}]]

Which gives this graph, but doesn't change the first graph.

enter image description here

However, if I now run m_goldberg's script, with slight numerical changes.

Manipulate[
 Show[ParametricPlot[r[t], {t, 0, 80}, 
   PlotRange -> {{0, 140}, {0, 100}}], 
  Graphics[{Red, Arrow[{{0, 0}, r[tau]}], 
    Arrow[{r[tau], r[tau] + r'[tau]}]}]], {{tau, 0}, 0, 80}, 
 Initialization :> (r =.; 
   r[t_] = NDSolveValue[{f'[t] == (0.4 - 0.001 s[t]) f[t], 
      s'[t] == (-0.3 + 0.05 f[t]) s[t], f[0] == 40, 
      s[0] == 20}, {f[t], s[t]}, {t, 0, 80}])]

Then all three images look like this:

enter image description here

Moreover, if I go back to the first image and try to run the code again, I get this error:

ReplaceAll::reps: {False,True} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>

ReplaceAll::reps: {False,True} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>

ReplaceAll::reps: {False,True} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>

General::stop: Further output of ReplaceAll::reps will be suppressed during this calculation. >>

Which can be fixed if I Clear[r].

So, still having problems with more than one Manipulate in one notebook.

$\endgroup$
3
  • $\begingroup$ Put the Module outside of the manipulate (let it surround it). Better yet, use DynamicModule instead. $\endgroup$ Commented Mar 29, 2015 at 20:51
  • $\begingroup$ I think I did try that (see my edit above), but I still could not get it to work. Replacing Module with Dynamic Module doesn't work either. Some strange other thing is going on? $\endgroup$
    – David
    Commented Mar 29, 2015 at 22:44
  • $\begingroup$ Hint: for the understanding of the error message, the list of reals in the error message should be a pair of numbers refers to the result of r[tau] that used within the Graphics function. It looks like if r[tau] does not return a pair of numbers, when sol is defined as a local variable using the Module construct. Sorry I don't have solution but this for clarifying the meaning of the error. $\endgroup$
    – penguin77
    Commented Mar 30, 2015 at 1:01

2 Answers 2

4
$\begingroup$

You should not wrap a Manipulate expression with Module. Read the comments to this question to learn why. You can fix your problem by clearing r and making a definition of r[t] in the initialization section of your Manipulate expression. Like so:

r = 42;
Manipulate[
  Show[
    ParametricPlot[r[t], {t, 0, 80}, PlotRange -> {{0, 140}, {0, 100}}], 
    Graphics[{Red, Arrow[{{0, 0}, r[tau]}], 
                Arrow[{r[tau], r[tau] + r'[tau]}]}]],
  {{tau, 0}, 0, 80},
  {r, None},
  Initialization :> (
    r =.;
    r[t_] = 
      NDSolveValue[{
        f'[t] == (0.4 - 0.01 s[t]) f[t], s'[t] == (-0.3 + 0.005 f[t]) s[t], 
        f[0] == 40, s[0] == 20}, 
        {f[t], s[t]}, {t, 0, 80}])]

demo

$\endgroup$
5
  • $\begingroup$ OK, this one does NOT work. To see what I am talking about, create a notebook file and enter your code and run it. Then add the following code after your first Manipulate demo, run it, and you will see it changes the plot in both demos. My comment is too long, so I will put the code in a second comment. $\endgroup$
    – David
    Commented Mar 30, 2015 at 3:05
  • $\begingroup$ Manipulate[ Show[ParametricPlot[r[t], {t, 0, 80}, PlotRange -> {{0, 140}, {0, 100}}], Graphics[{Red, Arrow[{{0, 0}, r[tau]}], Arrow[{r[tau], r[tau] + r'[tau]}]}]], {{tau, 0}, 0, 80}, Initialization :> (r =.; r[t_] = NDSolveValue[{f'[t] == (0.4 - 0.001 s[t]) f[t], s'[t] == (-0.3 + 0.05 f[t]) s[t], f[0] == 40, s[0] == 20}, {f[t], s[t]}, {t, 0, 80}])] $\endgroup$
    – David
    Commented Mar 30, 2015 at 3:05
  • $\begingroup$ @David. Sorry, I forgot to localize the variable r. I have edited my answer to fix the omission by adding the control definition {r, None} $\endgroup$
    – m_goldberg
    Commented Mar 30, 2015 at 6:41
  • $\begingroup$ Thanks for that link and comments of John Fultz. $\endgroup$
    – Kuba
    Commented Mar 30, 2015 at 6:59
  • $\begingroup$ @m_goldberg: Now it is working. I've still got a lot to learn. Thanks. $\endgroup$
    – David
    Commented Mar 31, 2015 at 0:42
2
$\begingroup$

I might approach it like this. First I like to use the replacement Rule form of NDSolve. Since the solution is used as a vector, it makes sense to have NDSolve return the vector solution r. Using With to inject the solution removes the dependence of the Manipulate on an external symbol. Then sol can be reused without affecting this Manipulate. For increased security, replace all the r by \[FormalR].

sol = First@NDSolve[{
  r'[t] == ({0.4, -0.3} + {{0, -0.01}, {0.005, 0}}.r[t]) r[t], r[0] == {40, 20}},
  r, {t, 0, 80}];
With[{sol = sol}, 
 Manipulate[
  Show[
   ParametricPlot[r[t] /. sol, {t, 0, 80}, PlotRange -> {{0, 140}, {0, 100}}], 
   Graphics[{Red, Arrow[{{0, 0}, r[tau]}], Arrow[{r[tau], r[tau] + r'[tau]}]} /. sol]
  ],
  {{tau, 0}, 0, 80}]
 ]
$\endgroup$
4
  • $\begingroup$ @Micheal E2: Ok, that worked. And so did this: sol = NDSolveValue[{r'[ t] == ({0.4, -0.3} + {{0, -0.01}, {0.005, 0}}.r[t]) r[t], r[0] == {40, 20}}, r, {t, 0, 80}]; With[{sol = sol}, Manipulate[ Show[ParametricPlot[sol[t], {t, 0, 80}, PlotRange -> {{0, 140}, {0, 100}}], Graphics[{Red, Arrow[{{0, 0}, sol[t]}], Arrow[{sol[t], sol[t] + sol'[t]}]}]], {{t, 0}, 0, 80}]] $\endgroup$
    – David
    Commented Mar 30, 2015 at 2:57
  • $\begingroup$ @Micheal E2: I understood everything you did except the With[{sol=sol}, part. Why does that work? I am not understanding why that protect an outer sol from coming in and ruining the Manipulate demo. $\endgroup$
    – David
    Commented Mar 30, 2015 at 2:58
  • $\begingroup$ Still having some problems. See my edits in the original post question. $\endgroup$
    – David
    Commented Mar 30, 2015 at 5:34
  • $\begingroup$ @David With replaces the symbols defined with their values before the body is evaluated. It is as if the symbols are not really created inside the kernel; more precisely, the code that Manipulate sees does not have the symbol sol in it. For whatever reason, you can reuse symbol names (With[{x = x},...]). See 559 for more. -- I'm not sure what problem you're having. Is it the PlotRange when the parameters of the ODE are changed? If you don't need to save sol for use outside Manipulate, try With[{sol = First@NDSolve[... $\endgroup$
    – Michael E2
    Commented Mar 30, 2015 at 10:26

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.