0
$\begingroup$

I would like to know if there is any way to improve the speed of the following program:

f := 1 - (2 M)/r; M = 1;

Va := f ((l (l + 1))/r^2 + ((1 - S^2) \!\(
\*SubscriptBox[\(\[PartialD]\), \(r\)]f\))/r);(*Axial potential*)

rmin := r /. Last[FindMaximum[{V, r > M}, r]]

V1 := f \!\(
\*SubscriptBox[\(\[PartialD]\), \(r\)]V\);
V2 := f \!\(
\*SubscriptBox[\(\[PartialD]\), \(r\)]V1\);
V3 := f \!\(
\*SubscriptBox[\(\[PartialD]\), \(r\)]V2\);
V4 := f \!\(
\*SubscriptBox[\(\[PartialD]\), \(r\)]V3\);
V5 := f \!\(
\*SubscriptBox[\(\[PartialD]\), \(r\)]V4\);
V6 := f \!\(
\*SubscriptBox[\(\[PartialD]\), \(r\)]V5\);

\[CapitalGamma] := 
  1/Sqrt[-2 V2] (1/8 (V4/V2) (1/4 + (n + 1/2)^2) - 
     1/288 (V3/V2)^2 (7 + 60 (n + 1/2)^2));
\[CapitalOmega] := 
  1/(-2 V2) (5/6912 (V3 /V2)^4 (77 + 188 (n + 1/2)^2) - 
     1/384 (((V3)^2  V4)/(V2)^3) (51 + 100 (n + 1/2)^2) + 
     1/2304 (V4/V2)^2 (67 + 68 (n + 1/2)^2) + 
     1/288 ((V3 V5)/(V2)^2) (19 + 28 (n + 1/2)^2) - 
     1/288 (V6/V2) (5 + 4 (n + 1/2)^2));

\[Omega] := Sqrt[
  V + \[CapitalGamma] Sqrt[(-2 V2)] - 
   I (n + 1/2) (1 + \[CapitalOmega]) Sqrt[(-2 V2)]];

(**********Plots**********)
V := Va;
S = 0;
Print[Style["Scalar perturbation", {Bold, Larger}], " Spin = ", S]

pp = 100;

l = 2; n = 0;
P1 = Plot[{Re[\[Omega]] /. r -> rmin, -Im[\[Omega]] /. 
      r -> rmin }, {M, 10^-3, 30}, AxesLabel -> {"M", "\[Omega]"}, 
    PlotStyle -> {{Line, Blue}, {Dashed, Blue}}, 
    PlotLegends -> Placed[{"\[ScriptL]=2"}, {0.7, 0.8}], 
    PlotRange -> {{0, 30}, {0, Automatic}}, MaxRecursion -> Infinity, 
    PlotPoints -> pp]; // AbsoluteTiming
l = 3; n = 0;
P2 = Plot[{Re[\[Omega]] /. r -> rmin, -Im[\[Omega]] /. 
      r -> rmin }, {M, 10^-3, 30}, AxesLabel -> {"M", "\[Omega]"}, 
    PlotStyle -> {{Line, Red}, {Dashed, Red}}, 
    PlotLegends -> Placed[{"\[ScriptL]=3"}, {0.7, 0.8}], 
    PlotRange -> {{0, 30}, {0, Automatic}}, MaxRecursion -> Infinity, 
    PlotPoints -> pp]; // AbsoluteTiming
l = 4; n = 0;
P3 = Plot[{Re[\[Omega]] /. r -> rmin, -Im[\[Omega]] /. 
      r -> rmin }, {M, 10^-3, 30}, AxesLabel -> {"M", "\[Omega]"}, 
    PlotStyle -> {{Line, Black}, {Dashed, Black}}, 
    PlotLegends -> Placed[{"\[ScriptL]=4"}, {0.7, 0.8}], 
    PlotRange -> {{0, 30}, {0, Automatic}}, MaxRecursion -> Infinity, 
    PlotPoints -> pp]; // AbsoluteTiming

Show[P1, P2, P3, Frame -> True, FrameLabel -> {"Mass", "Frequency"}, 
 ImageSize -> Medium]

I have to make several analysis for even more complicated Vs, and several different plots. They are taking longer and longer and I have no idea how make this faster. Right now it is taking several minutes to run it.

$\endgroup$
  • 3
    $\begingroup$ You use SetDelayed (:=) in loads of places you don't need it which is a drag on performance. Just use Set (=). Also don't use [PartialD] - just write D[V, r] for instance - as it becomes messy. After changing MaxRecursion to 15 (the max allowed) and making these other edits it takes 0.924229 seconds on my machine though the plot is just flat lines. $\endgroup$ – flinty Jul 3 at 16:56
  • $\begingroup$ Removing MaxRecurson and PlotPoints makes no difference to me visually, and of course it's much, much faster. (I don't see flat lines like flinty. I see curves.) $\endgroup$ – C. E. Jul 3 at 17:00
  • $\begingroup$ Also your rmin := r /. Last[FindMaximum[{V, r > M}, r]] comes before the definition of V, you should move V up. $\endgroup$ – flinty Jul 3 at 17:07
  • $\begingroup$ @C.E. I added both MaxRecursion and PlotPoints hoping that it would be more precise. $\endgroup$ – Edison Santos Jul 3 at 17:55
  • $\begingroup$ @flinty What is the difference between setting the definition before or after V? $\endgroup$ – Edison Santos Jul 3 at 17:55
3
$\begingroup$

It is quite tedious to modify your code so I will stick to some general hints:

  • Your functions are all of relatively simple form it is best to just use their analytical form instead of SetDelay, aka :=, everything. So write

    Va[r_] = ... (*yes, no colon here*)

    instead of:

    Va := ...

    The same for all the other definitions. Check this answer why this matters in terms of performance.

  • Then write f'[r] instead of your partial derivatives in the new function definitions because the other syntax does not work any more now (check this but I think they should all be reasonable algebraically compact)

  • Try a Simplify for your expressions (might be unnecessary or useless but sometimes gives a speed up afterwards)

  • Check if certain functions get evaluated multiple times at the same argument. In this case, try memoization

| improve this answer | |
$\endgroup$
  • $\begingroup$ Can you elaborate on why you would not use SetDelayed in your first general hint? I think it would bring more clarity to this answer! $\endgroup$ – CA Trevillian Aug 10 at 21:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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