0

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.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Edison Santos
  • 245
  • 1
  • 6
  • 3
    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. – flinty Jul 03 '20 at 16:56
  • 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.) – C. E. Jul 03 '20 at 17:00
  • Also your rmin := r /. Last[FindMaximum[{V, r > M}, r]] comes before the definition of V, you should move V up. – flinty Jul 03 '20 at 17:07
  • @C.E. I added both MaxRecursion and PlotPoints hoping that it would be more precise. – Edison Santos Jul 03 '20 at 17:55
  • @flinty What is the difference between setting the definition before or after V? – Edison Santos Jul 03 '20 at 17:55
  • @EdisonSantos Because when I copy and paste your code and evaluate the notebook top down from a single cell , V is undefined (fresh kernel) and FindMaximum fails. It's best to stick to defining things in order so we don't have to guess evaluation order. – flinty Jul 03 '20 at 17:58

1 Answers1

3

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

Mr Puh
  • 1,017
  • 6
  • 12
  • 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! – CA Trevillian Aug 10 '20 at 21:10