1
$\begingroup$

Previous question: Can any one help me make my program work faster?

This question is an extension to the question I asked previously and referred to in the link above. I want to add spin to my system, so I changed it to the following code. the problem is that although I am using Compile, it is still very slow. I didn't change it much, so I don't understand why it is becoming so slow?

This is the code after including the spin by using the function kdfxn which acts as a delta function. gives 1 in case I have equal spin for instance if sz1 and sz2 are equal and gives 0 otherwise. The only changed I made is in chmat, the rest is the same as previous.

 nvec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
 19, 20, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
 18, 19, 20};
 svec = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  1, 1, 1};
  ne = 5;
  nμ = 40;
  δ = -150;
 β = 1;
  kdfxn[i_, j_] := If[i == j, 1, 0]
 avec = {{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 
 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 0, 0, 0, 0, 0, 0, 0, 0}};

 cfxn = Block[{n1a, n1b, n2a, n2b},
  With[{code = Which[
   n1a == n1b && n2a == n2b,
   Evaluate[N[1/6 (1 - 3/(n1a^2 π^2) - 3/(n2a^2 π^2))]],

   n1a == n1b && n2a != n2b,
   Evaluate[N[(4 (1 + (-1)^(n2a + n2b)) n2a n2b)/((n2a^2 - n2b^2)^2 π^2)]],

   n1a != n1b && n2a == n2b,
   Evaluate[N[(4 (1 + (-1)^(n1a + n1b)) n1a n1b)/((n1a^2 - n1b^2)^2 π^2)]],       

   True, 
   Evaluate[N[-((32 (-1 + (-1)^(n1a + n1b)) (-1 + (-1)^(n2a + n2b)) n1a n1b 
   n2a n2b)/((n1a^2 - n1b^2)^2 (n2a^2 - n2b^2)^2 π^4))]]
   ]},
   Compile[{{n1a, _Integer}, {n1b, _Integer}, {n2a, _Integer}, {n2b, 
   _Integer}},
    code,
  CompilationTarget -> "C"
   ]
    ]];

This is the same function as previous question, which I did not change, and it will be use later to calculate a matrix:

   chmat = With[{ccfxn = cfxn, kkdfxn = kdfxn}, 
   Compile[{{nm, _Integer}, {ne, _Integer}, {b, _Real}, {d, _Real}, \
   {avec, _Real, 2}, {nvec, _Real, 1}, {svec, _Real, 1}}, 
   Block[{sz0, sz1, sz2, sz3, n0, n1, n2, n3, h1, h2, tmp, tmp2, 
   tmp21, kf01, kf23, kf13, kf02}, 
   Table[n0 = Compile`GetElement[nvec, nm0];
   n1 = Compile`GetElement[nvec, nm1];
   sz0 = Compile`GetElement[svec, nm0];
   sz1 = Compile`GetElement[svec, nm1];
   tmp = 0.;
   Do[sz2 = Compile`GetElement[svec, nm2];
   sz3 = Compile`GetElement[svec, nm3];
   n2 = Compile`GetElement[nvec, nm2];
   n3 = Compile`GetElement[nvec, nm3];
   tmp2 = ccfxn[n1, n0, n3, n2];
   tmp21 = ccfxn[n1, n3, n0, n2];

   kf01 = kkdfxn[sz0, sz1];
   kf23 = kkdfxn[sz2, sz3];
   kf13 = kkdfxn[sz1, sz3];
   kf02 = kkdfxn[sz0, sz2];

   Do[
    tmp += (tmp2 kf23 kf01 - tmp21 kf13 kf02) Compile`GetElement[
       avec, j, nm3] Compile`GetElement[avec, j, nm2], {j, 1, 
     ne}], {nm2, 1, nm}, {nm3, 1, nm}];
    d tmp + 
    If[nm0 == nm1, (n0^2 Pi^2 + b Compile`GetElement[svec, nm0]), 
    0.], {nm0, 1, nm}, {nm1, 1, nm}]], CompilationTarget -> "C", 
  CompilationOptions -> {"InlineCompiledFunctions" -> True}, 
  RuntimeOptions -> "Speed"]];

and then I use the iteration method to converge the energies, which is the same as previous question and the speed is fine,:

  Table[
  hmat = chmat[nμ, ne, δ, β, avec, nvec, svec];
  {evals, evecs} = Eigensystem[hmat];
  pos = Ordering[evals][[1 ;; ne]];
  bvec = Map[x \[Function] If[Total[x] < 0, -x, x], evecs[[pos]]];
  residual = Max[Abs[avec - bvec]];
  avec = bvec;
  {residual, Total[evals[[pos]]]},
  {j, 1, 30}]

I wish some one could tell me why does it become so slow as I have included spin, and is there any way I can make it work faster?

$\endgroup$
  • $\begingroup$ @b3m2a1 Ok, Thank you. Sorry for the Junk!!! I am beginner, maybe I couldn't find a way to make it shorter. Anyway, Thanks for your help $\endgroup$ – Delaram Nematollahi Oct 23 '17 at 21:05
  • $\begingroup$ "junk" was too harsh a word. I just meant it's a lot. Generally we advocate breaking things down into the most minimal piece you can find. In this case that might be using a chmat adapted so that it used a smaller cfxn that had fewer parameters being fed into it. That would also have helped you find the issue, which was the kdfxn. $\endgroup$ – b3m2a1 Oct 23 '17 at 21:07
  • $\begingroup$ @b3m2a1 sure, Thank you $\endgroup$ – Delaram Nematollahi Oct 23 '17 at 21:09
4
$\begingroup$

Despite telling myself I wouldn't fix this, here you are... Your problem is that you can't Compile DownValues.

Replace kdfxn with (If[# == #2, 1, 0] &) and it'll work fine.

It might help to read up on Compile a bit so this won't be an issue in the future

P.S. KroneckerDelta already exists in the language and if you were to do your own version you'd want to use === instead of ==

| improve this answer | |
$\endgroup$
  • $\begingroup$ yeah I need to get used it more, I have already read, seems didn't get it completely. $\endgroup$ – Delaram Nematollahi Oct 23 '17 at 21:07
  • 1
    $\begingroup$ @DelaramNematollahi understandable. It's a very different way to think about the code. Just keep in mind that DownValues can't be compiled and you'll be much better off. $\endgroup$ – b3m2a1 Oct 23 '17 at 21:08

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.