0
$\begingroup$

I have some performance issues when calling

Table[{h, Slow1[h, n]}, {n, nlist}, {h, 0.1, 10, 0.5}];

for a given list

nlist={37,288,5300}

with

Slow1[strength_,numberOfBathSpins_] := 
 Module[{Encapsulate, a, HzScalarProduct, normMatrix, h=strength},
  Encapsulate[x_] := {x};
  a = Encapsulate /@ 
    Prepend[Table[-1/16 J[j, 0], {j, 1, numberOfBathSpins}], 
     1/16 S[0]];
  HzScalarProduct[l_, p_] := 
   If[l == p, 
    2/64 S[l]^2 + 3/64 (numberOfBathSpins - 1) Q[l] - h/8 S[l] + h^2/
     4, 1/16 J[p, l] (S[p] - S[l]) - 
     3/64 (numberOfBathSpins - 3) J[p, l]^2];
  normMatrix = 
   Table[HzScalarProduct[l, p], {l, 0, numberOfBathSpins}, {p, 0, 
     numberOfBathSpins}];
  Flatten[Transpose[a].Inverse[normMatrix].a][[1]] 
  ]

Above all the problem is that the size of the vector

a

as well as the size of the matrix

normMatrix

depend on the input parameter "numberOfBathSpins". The table creation requires evaluating the whole matrix multiplication time and again. I would like to give back a list of functions with

funList={Slow1[h,37], Slow1[h,288], Slow1[h,5300]}

that I can use in order to plot the dependence of "h" for three different "numberOfBathSpins". The problem is connected to the last line within the Slow1-function. Mathematica needs too long to calculate the

Inverse[normMatrix]

symbolically. I tried to

Inverse[normMatrix]/.h->strength

This works fast and satisfactory but I don't know how to give back the whole expression without inserting a specific "h" in order for me to evaluate the expression afterwards with the function list "funList".

$\endgroup$
  • $\begingroup$ Are your J , Q, S functions defined elsewhere, or are they to be left symbolic? $\endgroup$ – MarcoB May 11 '15 at 16:40
  • $\begingroup$ @MarcoB: You are right. I forgot to mention that: Those functions are defined elsewhere and give back rational numbers for given arguments (in principle those are constants looked up from a list). $\endgroup$ – pbx May 11 '15 at 16:45
  • $\begingroup$ Could you add those definitions to your question, if they are not too cumbersome? Alternatively, you could also give toy definitions that simulate the return values of those functions, or maybe even a single typical value. $\endgroup$ – MarcoB May 11 '15 at 16:47
  • $\begingroup$ No problem. Those are essentially functions that look at specific positions within a list, so nothing special there. The lists are as long as the Maximum of the bathSizes and the values are between 0.01 and 100. $\endgroup$ – pbx May 11 '15 at 19:57
2
$\begingroup$

One way to improve the performance of your code is to remove definitions of auxiliary functions from the bodies of function definitions. Such auxiliary functions are redefined every time the function is called. This is demonstrated by

f[] := Module[{g}, g[] := SymbolName[g]; g[]]
Table[f[], {4}]
{"g$11401", "g$11402", "g$11403", "g$11404"}

In your case, for example, I would define HzScalarProduct as a top-level helper like so:

HzScalarProduct[l_, p_, spins_] := 
  If[l == p, 
    2/64 S[l]^2 + 3/64 (spins - 1) Q[l] - h/8 S[l] + h^2/4, 
    1/16 J[p, l] (S[p] - S[l]) - 3/64 (spins - 3) J[p, l]^2]

and call it with HzScalarProduct[l, p, numberOfBathSpins].

Also, compare

AbsoluteTiming[Encapsulate[x_] := {x}; 
  Encapsulate /@ Prepend[Table[i, {i, 1000000}], 0];]
{0.716317, Null}
AbsoluteTiming[Prepend[Table[{i}, {i, 1000000}], {0}];]
{0.224965, Null}
$\endgroup$
  • $\begingroup$ +1 for providing an insight into what I did in order to completely spoil the performance. Is there a performant way of solving the main problem, i.e. giving back a list of three usable functions (one for each bath spin size) that only need to be evaluated for a given strength "h" without recalculating the matrix, vector multiplication time and again? $\endgroup$ – pbx May 11 '15 at 17:38

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.