In order to construct the matrix h1+h2, I have used three Table commands. I am using fxn[n1a_, n1b_, n2a_, n2b_] as a function in a loop. I need my program to be a lot faster than what it is now, since this is only a part of my main program. Could any one tell me how I can make it work faster? In other words, what are the points I should pay attention to in Mathematica, in case of timing?
Description:
In the original program I am using an iteration method in which I need to construct the matrix h1+h2, calculate the new eigenvectors in each step, reconstruct the matrix h1+h2, until I observe convergence in eigenenergies.
avec, is a guessed vector, and I am using it as an initial vector to construct the matrix h1+h2.
Later on, I need to calculate the eigenvectors of this matrix, choose the vectors related to the minimum eigenvalues and put them instead of the previous avec.
h1 is the kinetic term of my matrix and h2 is the exchange potential (the formula which I have used came from the math I did for Hartree-Fock approximation).
fxn is a function I constructed based on the pre-calculated integrals in my code (so that I do not need to calculate the integrals in each iteration).
The problem now is the calculation for h2, which consumes most of the time. I assume the problem is the way I am using the Table commands. But I couldn't think of a more efficient way.
avec = {{1, 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, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
nvec = {1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6};
svec = {-1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1};
kdfxn[i_, j_] := If[i == j, 1, 0]
ne = 3;
n\[Mu] = 12;
\[Delta] = -50;
\[Beta] = 1;
fxn[n1a_, n1b_, n2a_, n2b_] := N[ Which[
n1a == n1b && n2a == n2b,
1/6 (1 - 3/(n1a^2 \[Pi]^2) - 3/(n2a^2 \[Pi]^2)),
n1a == n1b && n2a != n2b,
(4 (1 + (-1)^(n2a + n2b)) n2a n2b)/((n2a^2 - n2b^2)^2 \[Pi]^2),
n1a != n1b && n2a == n2b,
(4 (1 + (-1)^(n1a + n1b)) n1a n1b)/((n1a^2 - n1b^2)^2 \[Pi]^2),
True, -((
32 (-1 + (-1)^(n1a + n1b)) (-1 + (-1)^(
n2a + n2b)) n1a n1b n2a n2b)/((n1a^2 - n1b^2)^2 (n2a^2 -
n2b^2)^2 \[Pi]^4))]]
hmat = Table[
n0 = nvec[[n\[Mu]0]];
n1 = nvec[[n\[Mu]1]];
h1 = (n0^2 \[Pi]^2 + \[Beta] svec[[n\[Mu]0]]) kdfxn[n\[Mu]0,
n\[Mu]1] ;
h2 = Total[Table[
n2 = nvec[[n\[Mu]2]];
n3 = nvec[[n\[Mu]3]];
Table[
temp1 =
fxn[n1, n0, n3, n2] avec[[j, n\[Mu]3]] avec[[j, n\[Mu]2]] ;
temp2 =
fxn[n1, n3, n0, n2] avec[[j, n\[Mu]3]] avec[[j, n\[Mu]2]];
temp = \[Delta] (temp1 - temp2), {j, 1, ne}],
{n\[Mu]2, 1, n\[Mu]},
{n\[Mu]3, 1, n\[Mu]}], Infinity];
h1 + h2
, {n\[Mu]0, 1, n\[Mu]}, {n\[Mu]1, 1, n\[Mu]}] // Timing
I want to use the code @Henrik Schumacher gave me to find my new avecs (which are coming from the eigenvectors of hcmat) to recalculate hcmat and iterate. The problem is I can do it manually by substituting new avec instead of the previous one, but as I start using table it doesn't work. I don't know why it's acting like that.
Table[chmat =
With[{ccfxn = cfxn},
Compile[{{nm, _Integer}, {ne, _Integer}, {d, _Real}, {b, \
_Real}, {avec, _Real, 2}, {nvec, _Real, 1}, {svec, _Real, 1}},
Block[{n0, n1, n2, n3, h1, h2, tmp, tmp2},
Table[n0 = Compile`GetElement[nvec, nm0];
n1 = Compile`GetElement[nvec, nm1];
tmp = 0.;
Do[n2 = Compile`GetElement[nvec, nm2];
n3 = Compile`GetElement[nvec, nm3];
tmp2 = (ccfxn[n1, n0, n3, n2] - ccfxn[n1, n3, n0, n2]);
Do[tmp +=
tmp2 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"]];
hmat2 = chmat[n\[Mu], ne, \[Delta], \[Beta], avec, nvec, svec]; //
AbsoluteTiming // First
hmat = hmat2
eout = Eigensystem[hmat];
evals = eout[[1]];
evecs = eout[[2]];
sortedevals = Sort[evals];
bvec = Chop[Table[bpos = Position[evals, sortedevals[[i]]][[1, 1]];
evecs[[bpos]], {i, 1, ne}]];
Table[If[Sign[bvec[[i, 1]]] == Sign[avec[[i, 1]]], avec = ( bvec) ,
avec = (Sign[avec[[i, 1]]] bvec) ], {i, 1, ne}];
normalizedavec = Table[avec[[i]]/norm[avec, i], {i, 1, ne}];
avec = normalizedavec;
en = Total[Take[sortedevals, ne]], {j, 1, 5}]
In the rest of the code, I am finding the first ne(3) minimum eigenenergies and finding the the related eigenvectors, to construct bvec. by doing some modification on bvec and normalizing it ,I could get the new avec I want to use instead of the previous one. Now my problem is doing the iteration. I would appreciate it if you could help me with this.
I want to calculate this integrals
sol = Assuming[
A \[Element] Reals && 0 <= s1 <= 1 && 1 <= n1a <= 10 &&
1 <= n2a <= 10 && 1 <= n1b <= 10 && 1 <= n2b <= 10,
Expand@FullSimplify[
Integrate[
4 A Exp[-B (s2 - s1)] Sin[n1a \[Pi] s1] Sin[n1b \[Pi] s1] Sin[
n2a \[Pi] s2] Sin[n2b \[Pi] s2], {s2, s1, 1}]]];
sol1 = Assuming[
A \[Element] Reals && 0 <= s2 <= 1 && 1 <= n1a <= 10 &&
1 <= n2a <= 10 && 1 <= n1b <= 10 && 1 <= n2b <= 10,
Expand@FullSimplify[
Integrate[
4 A Exp[-B (s1 - s2)] Sin[n1a \[Pi] s1] Sin[n1b \[Pi] s1] Sin[
n2a \[Pi] s2] Sin[n2b \[Pi] s2], {s1, s2, 1}]]];
(int[n1a_, n2a_, n1b_, n2b_] =
Integrate[sol, {s1, 0, 1},
Assumptions ->
B \[Element] Reals && A \[Element] Reals && 1 <= n1a <= 10 &&
1 <= n2a <= 10 && 1 <= n1b <= 10 && 1 <= n2b <= 10] +
Integrate[sol1, {s2, 0, 1},
Assumptions ->
B \[Element] Reals && A \[Element] Reals && 1 <= n1a <= 10 &&
1 <= n2a <= 10 && 1 <= n1b <= 10 && 1 <= n2b <= 10])
and replace n1a in the int function with n1a+0.0001 . Then I need to use the result of int after the replacement, as the material for code :code=result in:
"cfxn = Block[{n1a, n1b, n2a, n2b},
With[{code = "result"},
Compile[{{n1a, _Integer}, {n1b, _Integer}, {n2a, _Integer}, {n2b, \
_Integer}}, code, CompilationTarget -> "C"]]];"
but I am getting these errors:
CompiledFunction::cfse: Compiled expression CompiledFunction[{10,11.,5464},<<7>>,LibraryFunction[/Users/delaramnematollahi/Library/Mathematica/ApplicationData/CCompilerDriver/BuildFolder/Delarams-MacBook-Pro-3755/compiledFunction3.dylib,compiledFunction3,{<<1>>},{Real,2}]] should be a machine-size real number.
which I do not understand why.
Could you please help me with this?
fxnsupposed to do? – ercegovac Sep 30 '17 at 21:38avecandnvec. Verify that you have included all data by executing the code in the clean context by executing commandClearAll["Global\*"]` – ercegovac Sep 30 '17 at 22:25Bandstructure. Maybe fxn should be the sum of aSymmetricarray and anAntisymmetricarray. – LouisB Oct 01 '17 at 00:10