Plotting 2 functions & economizing on calc of intermediate result

  • Context: Mathematica 
  • Thread starter Thread starter Swamp Thing
  • Start date Start date
  • Tags Tags
    Functions Plotting
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
2 replies · 2K views
Swamp Thing
Insights Author
Messages
1,062
Reaction score
819
TL;DR
It's complicated :)
I am trying to plot two functions a(t) and b(t) that both use a common intermediate result K. In my actual code K would be a slow-ish calculation. To reuse the K across a and b, I am putting them into a single module that provides an array {a, b} to the Plot[] function. (BTW, the Evaluate[] is needed because without it, both plots come out the same color).

So far so good. But a(t) involves discretizing t to get N, and then summing over N terms, as in Total[Range[IntegerPart[t/20]]].

Now, although the plot comes out OK in this example, it displays a little error message : "Range specification in Range[IntegerPart[t/20]] does not have appropriate bounds". I am worried that this error will break my actual plot, which would be more complicated than this minimal demo, so it would be nice to get rid of the error.

And BTW, if I plot a and b separately and do a Show[Pa, Pb] then it works fine with no error -- at the cost of computing K twice as many times. Same if I Plot[{fn_a[t] , fn_ b[t],{t,0,10 }] in the usual way.

Thanks!

Code:
Plot[ Evaluate[
                       Module[{K,a,b},

                            (* "K" is an intermediate result needed for "a" and "b" *)
                            K=t; (* we don't want to calc this more than once per t *)

                            (* "a" is a sum over N terms; N depends on "t" *)
                            a= K * Total[Range[IntegerPart[t/20]]];

                             (* "b" is just a simple function of "t" *)
                                   b= K * t/10+5;

                              (* We want to plot a and b as a fn of t *)
                              {a,b}

                                   ]
                            ] ,

       {t,100,200},Exclusions->None
     ]
 
Last edited:
on Phys.org
If K is a function of x then you can make K into a function that remembers its values as follows:

K[x_]:=K[x]= (* some expression involving x *)

Every time you evaluate K it will remember the result and it will simply use that result instead of recalculating it.
 
  • Informative
Likes   Reactions: Swamp Thing
Brilliant!
Now the code is as simple as this:

Code:
fnA[x_]:=Total[Range[IntegerPart[x/20]]]
fnB[x_]:=.1*x

n=0 (*Evaluation counter for K *)
K[x_]:=K[x]= (n=n+1;0.2*x) (* value common to A, B *)

Plot[{ K[x]+fnA[x] , K[x]+fnB[x] } , {x,100,200}]

Style[Row[{"Evalutated 'K' ",n," times"}],20]

1609390845442.png

1609390952277.png


Thanks again!
 
  • Like
Likes   Reactions: Dale