Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

This question already has an answer here:

Sometimes when I try to create a function inside a function, Mathematica gives me a hard time. I usually just have to play around with the syntax until it gets something it "likes" but I really have idea why certain things work and others don't. Here's an example I just ran into recently:

Code version A:

ans[tf_] :=
  NDSolve[{x'[t] == v[t], v'[t] == -x[t] - v[t], x[0] == 1, 
     v[0] == 1}, {x[t], v[t]}, {t, 0, tf}] // Flatten;
ans[2]
Plot[{x[t], v[t]} /. %, {t, 0, 2}]

So this works beautifully. But for some reason if I try to nest my ans[2] inside my function by replacing it with the %, Mathematica can't evaluate it!

Code version B:

ans[tf_] :=
  NDSolve[{x'[t] == v[t], v'[t] == -x[t] - v[t], x[0] == 1, 
     v[0] == 1}, {x[t], v[t]}, {t, 0, tf}] // Flatten;

Plot[{x[t], v[t]} /. ans[2], {t, 0, 2}]

So my question boils down to: Why does Code Version A work and Code Version B doesn't?

share|improve this question

marked as duplicate by Szabolcs, Artes, belisarius, Sjoerd C. de Vries, rm -rf Oct 4 '13 at 23:02

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1  
Add the option Evaluated -> True to your second Plot –  belisarius Oct 4 '13 at 18:52
    
Welcome to Mathematica.SE Steven! Please do not use the bugs tag for new question. We use this tag to categorize confirmed bugs. It'll be re-added if this is confirmed to be a bug by the community. –  Szabolcs Oct 4 '13 at 19:07
    
1  
@belisarius But Evaluated is not documented anywhere. Either, politically correct: Plot[Evaluate[{x[t], v[t]} /. %], {t, 0, 2}], or, faster: Plot @@ {{x[t], v[t]} /. %, {t, 0, 2}} –  Rolf Mertig Oct 4 '13 at 20:56
    
Maybe the reason why this is so, is that there is infinite evaluation, and sometimes this is not as efficient as needed, and therefore there is this funny attribute HoldAll, which is hard to explain. –  Rolf Mertig Oct 4 '13 at 20:57

1 Answer 1

NDSolve doesn't localize the function variable so it doesn't work if your t has a value while it is being evaluated. For example, the following won't work.

Block[{x = 1}, NDSolve[{y'[x] == y[x], y[0] == 1}, y, {x, 0, 1}]]

Plot often automatically decides not to evaluate the function until after giving the variable numerical values. If this is the case then for each point Plot wants to plot (say t=1.23), it does something equivalent to Block[{t=1.23}, {x[t], v[t]} /. ans[2]] to get the output value.

In your first case, ans[2] had been preevaluated into InterpolatingFunctions and stored in %, so it works. But in your second case, the ans[2] and hence the NDSolve are evaluated WHILE t has a numerical value so FAAIL

You could patch it by forcing Plot to preevaluate the argument as people suggested, but it seems more appropriate to fix the heart of the issue and localize your t on ans

ans[tf_] := 
 Block[{t}, 
  NDSolve[{x'[t] == v[t], v'[t] == -x[t] - v[t], x[0] == 1, 
     v[0] == 1}, {x[t], v[t]}, {t, 0, tf}] // Flatten]

Or even better, get pure functions out of NDSolve by using {x, v} as a third argument instead of {x, v}, and then you can use ANY variable name in your Plot. This opens the door to using a formal symbol (symbols that are protected by default) in ans if you want to do away with the Block.

share|improve this answer
    
    
@belisarius if you drop your soap, Plot[t, GARCH[3,2] –  Rojo Oct 4 '13 at 21:52
    
Your comment was flagged for reasons the mod will be unable to understand –  belisarius Oct 4 '13 at 22:00

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