4
$\begingroup$

The function trajectory below is defined in terms of Manipulate and calls the auxiliary function soln:

soln[f_, y0_][t_] := 
     y[t] /. First@DSolve[{y'[t] == f[t], y[0] == y0}, y[t], t] 

 trajectory[f_] := Manipulate[
      {f[t], Plot[Evaluate[soln[f, y0][t]], {t, 0, 5}, PlotRange -> 5]},
      {{y0, 0}, -2, 2, 0.25}]

Consider the following two calls to trajectory in the same notebook:

 (* example 1 *)
 f[t_] := 1 - t^2
 trajectory[f]

 (* example 2 *)
 f[t_] := 2 t - 3
 trajectory[f]

After evaluating the two lines in example 1, if I then evaluate the two lines in example 2, immediately the previously displayed output in example 1 changes so as to use the output from example 2.

How can this unwanted interaction be prevented? I would strongly prefer:

  • not to use different names for the function f in the two examples (using g[t_] := 1 - t^2; trajectory[g] and h[t_] := 2 t - 3; trajectory[h] does prevent the unwanted interaction; and

  • not to use a pure function directly as the argument to trajectory (using trajectory[(1 - #^2) &] and trajectory[(2 # - 3) &] does prevent the unwanted interaction).

In short, is there some way of doing scoping to prevent what I'm seeing?

Relation to similar question Localizing variables within a Manipulate

I had seen that related question and the answer provided, namely, to use the setting Evaluation->Notebook's Default Context-> Unique to Each Cell Group. However, that is unsatisfactory here because (i) it would require putting a copy of the code for soon and trajectory into a separate group with each example invocation of trajectory; and (ii) even in that case, the code may well be copied by a user into a different notebook where it may be awkward to use the indicated evaluation option.

$\endgroup$
3
  • $\begingroup$ DynamicModule. $\endgroup$ Commented Mar 18, 2015 at 22:53
  • $\begingroup$ You are using Manipulate as a function. This is not really how Manipulate is meant to be used. Manipulate should be self contained. If you want to test 2 functions, make a Manipulate with pull-up menu and select one of the functions. In your example, first Manipulate detected f changed and updated. You do not need to even make a new manipulate call to see the interaction. Just defining f again in the global context will cause the Manipulate to change. $\endgroup$
    – Nasser
    Commented Mar 18, 2015 at 23:43
  • $\begingroup$ No, 2 or even half a dozen or more "test" functions would not suffice for building into the Manipulate: the idea is to create a function trajectory that can be used with *any" vector field function the user might wish. $\endgroup$
    – murray
    Commented Mar 19, 2015 at 0:44

1 Answer 1

5
$\begingroup$

The problem is that trajectory[f] passes the Symbol f to Manipulate, so that the Manipulate updates to the new f whenever the definition of f is changed. The trick is to somehow to evaluate f so that the symbol f is replaced by its definition before it is injected into the Manipulate code.

Method 1:

ClearAll[soln];
soln[f0_, y0_] := Function[t0, 
  y[t0] /. First@DSolve[Evaluate@{y'[t] == f0[t], y[0] == y0}, y, t] // Evaluate]

trajectory[f0_] := With[{f = Function[t, Evaluate@f0[t]]},
  Manipulate[
   {f[t], Plot[Evaluate[soln[f, y0][t]], {t, 0, 5}, PlotRange -> 5]},
   {{y0, 0}, -2, 2, 0.25}]
  ]

Method 2:

ClearAll[soln];
soln[f_, y0_] := y /. First@DSolve[Evaluate@{y'[t] == f[t], y[0] == y0}, y, t]

trajectory[f_] := With[{sol = Evaluate@soln[f, #] &, ft = f[t]},
  Manipulate[
   {ft, Plot[Evaluate[sol[y0][t]], {t, 0, 5}, PlotRange -> 5]},
   {{y0, 0}, -2, 2, 0.25}]
  ]
$\endgroup$
2
  • $\begingroup$ Thanks! Is there any way to simplify this so that a Function construct is not needed? The code is something I'd like somebody to be able both to use and to understand readily who is fairly new to using Mathematica. $\endgroup$
    – murray
    Commented Mar 19, 2015 at 0:53
  • $\begingroup$ In the first solution, replace soln by soln[f0_, y0_][t0_] := y[t0] /. First@DSolve[Evaluate@{y'[t] == f0[t], y[0] == y0}, y, t] /. t -> t0; -- Would that be readily understood? (There are real issues of scope here, which may not be familiar to somebody not acquainted with programming languages.) $\endgroup$
    – Michael E2
    Commented Mar 19, 2015 at 1:00

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.