375 lines
14 KiB
C++
375 lines
14 KiB
C++
/**********************************************************
|
|
|
|
This software is part of J.-S. Caux's ABACUS library.
|
|
|
|
Copyright (c) J.-S. Caux.
|
|
|
|
-----------------------------------------------------------
|
|
|
|
File: ln_Szm_p_Smz_ME_XXX.cc
|
|
|
|
Purpose: compute the S^z_j S^-_{j+1} + S^m_j S^z_{j+1}
|
|
matrix elemment for XXX
|
|
|
|
***********************************************************/
|
|
|
|
#include "ABACUS.h"
|
|
|
|
using namespace std;
|
|
using namespace ABACUS;
|
|
|
|
|
|
namespace ABACUS {
|
|
inline complex<DP> phi(complex<DP> x){return x;}
|
|
inline complex<DP> a(complex<DP> x){return 1;}
|
|
inline complex<DP> b(complex<DP> x,complex<DP> y, complex<DP> eta){ return phi(x-y)/phi(x-y+complex<DP>(0.0,1.0)*eta);}
|
|
inline complex<DP> d(complex<DP> x, complex<DP> xi, complex<DP> eta, int N){return pow(b(x,xi,eta),N);}
|
|
|
|
|
|
inline complex<DP> ln_Fn_F (XXX_Bethe_State& B, int k, int beta, int b)
|
|
{
|
|
complex<DP> ans = 0.0;
|
|
|
|
for (int j = 0; j < B.chain.Nstrings; ++j) {
|
|
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
|
|
for (int a = 1; a <= B.chain.Str_L[j]; ++a) {
|
|
|
|
if (!((j == k) && (alpha == beta) && (a == b)))
|
|
ans += log(B.lambda[j][alpha] - B.lambda[k][beta]
|
|
+ 0.5 * II * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
|
|
}
|
|
}
|
|
}
|
|
|
|
return(ans);
|
|
}
|
|
|
|
inline complex<DP> ln_Fn_G (XXX_Bethe_State& A, XXX_Bethe_State& B, int k, int beta, int b)
|
|
{
|
|
complex<DP> ans = 0.0;
|
|
|
|
for (int j = 0; j < A.chain.Nstrings; ++j) {
|
|
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
|
|
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
|
|
|
|
ans += log(A.lambda[j][alpha] - B.lambda[k][beta]
|
|
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
|
|
}
|
|
}
|
|
}
|
|
|
|
return(ans);
|
|
}
|
|
|
|
inline complex<DP> Fn_K (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
|
|
{
|
|
return(1.0/((A.lambda[j][alpha] - B.lambda[k][beta]
|
|
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
|
|
* (A.lambda[j][alpha] - B.lambda[k][beta]
|
|
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)) )));
|
|
}
|
|
|
|
inline complex<DP> Fn_L (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
|
|
{
|
|
return ((2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
|
|
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
|
|
))
|
|
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
|
|
}
|
|
|
|
|
|
complex<DP> ln_Szm_p_Smz_ME (XXX_Bethe_State& A, XXX_Bethe_State& B)
|
|
{
|
|
//clock_t start_time_local = clock();
|
|
//A has to be the ground state!
|
|
|
|
// This function returns the natural log of the S^z operator matrix element.
|
|
// The A and B states can contain strings.
|
|
|
|
// Check that the two states refer to the same XXX_Chain
|
|
|
|
if (A.chain != B.chain) ABACUSerror("Incompatible XXX_Chains in Szm_p_Smz matrix element.");
|
|
|
|
// Check that A and B are compatible: same Mdown
|
|
|
|
if (A.base.Mdown != B.base.Mdown + 1)
|
|
ABACUSerror("Incompatible Mdown between the two states in SzSm_p_SmSz matrix element!");
|
|
|
|
//if (B.type_id > 999999LL) return(complex<DP>(-300.0));
|
|
|
|
//add a delta to the origin of the centered strings
|
|
for (int i = 0; i < A.chain.Nstrings; ++i)
|
|
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
|
|
if(abs(A.lambda[i][alpha])<5.55112e-12)A.lambda[i][alpha]=5.55112e-12;
|
|
for (int i = 0; i < B.chain.Nstrings; ++i)
|
|
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
|
|
if(abs(B.lambda[i][alpha])<5.55112e-5)B.lambda[i][alpha]=5.55112e-5;
|
|
|
|
// Some convenient arrays
|
|
|
|
complex<DP> i=complex<DP>(0.0,1.0);
|
|
complex<DP> eta=-i;
|
|
complex<DP> ln_prod = complex<DP>(0.0,0.0);
|
|
complex<DP> result;
|
|
result=log(B.chain.Nsites*1.0/4.0);
|
|
|
|
int sizeA=0;
|
|
int sizeB=0;
|
|
|
|
for (int i = 0; i < A.chain.Nstrings; ++i)
|
|
sizeA+=A.base.Nrap[i]*A.chain.Str_L[i];
|
|
for (int i = 0; i < B.chain.Nstrings; ++i)
|
|
sizeB+=B.base.Nrap[i]*B.chain.Str_L[i];
|
|
|
|
complex<DP>* mu = new complex<DP>[sizeA];
|
|
complex<DP>* lam = new complex<DP>[sizeB];
|
|
int index=0;
|
|
for (int i = 0; i < A.chain.Nstrings; ++i)
|
|
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
|
|
for (int a = 1; a <= A.chain.Str_L[i]; ++a)
|
|
{
|
|
mu[index]=(A.lambda[i][alpha] + 0.5 * -eta * (A.chain.Str_L[i] + 1.0 - 2.0 * a));
|
|
index++;
|
|
}
|
|
|
|
index=0;
|
|
for (int i = 0; i < B.chain.Nstrings; ++i)
|
|
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
|
|
for (int a = 1; a <= B.chain.Str_L[i]; ++a)
|
|
{
|
|
lam[index]=(B.lambda[i][alpha] + 0.5 * -eta * (B.chain.Str_L[i] + 1.0 - 2.0 * a));
|
|
index++;
|
|
}
|
|
|
|
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
|
|
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
|
|
Lambda re_ln_Fn_G_0(B.chain, B.base);
|
|
Lambda im_ln_Fn_G_0(B.chain, B.base);
|
|
Lambda re_ln_Fn_G_2(B.chain, B.base);
|
|
Lambda im_ln_Fn_G_2(B.chain, B.base);
|
|
|
|
complex<DP> ln_prod1 = 0.0;
|
|
complex<DP> ln_prod2 = 0.0;
|
|
complex<DP> ln_prod3 = 0.0;
|
|
complex<DP> ln_prod4 = 0.0;
|
|
|
|
for (int i = 0; i < A.chain.Nstrings; ++i)
|
|
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
|
|
for (int a = 1; a <= A.chain.Str_L[i]; ++a)
|
|
ln_prod1 += log(norm(A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
|
|
|
|
for (int i = 0; i < B.chain.Nstrings; ++i)
|
|
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
|
|
for (int a = 1; a <= B.chain.Str_L[i]; ++a)
|
|
if (norm(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)) > 100.0 * MACHINE_EPS_SQ)
|
|
ln_prod2 += log(norm(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
|
|
|
|
// Define the F ones earlier...
|
|
|
|
for (int j = 0; j < B.chain.Nstrings; ++j) {
|
|
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
|
|
re_ln_Fn_F_B_0[j][alpha] = real(ln_Fn_F(B, j, alpha, 0));
|
|
im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F(B, j, alpha, 0));
|
|
re_ln_Fn_G_0[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 0));
|
|
im_ln_Fn_G_0[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 0));
|
|
re_ln_Fn_G_2[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 2));
|
|
im_ln_Fn_G_2[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 2));
|
|
}
|
|
}
|
|
|
|
//mu is the ground state!
|
|
//A -> mu, B -> lam
|
|
complex<DP> prod=complex<DP>(1.0,0.0);
|
|
complex<DP> prod2=complex<DP>(1.0,0.0);
|
|
complex<DP> prod3=complex<DP>(1.0,0.0);
|
|
for(int l=0; l<sizeA;l++) prod*=phi(mu[l]+eta*0.5);
|
|
for(int l=0; l<sizeB;l++) prod/=phi(lam[l]+eta*0.5);
|
|
|
|
for(int l=0; l<sizeA;l++)
|
|
for(int m=0; m<sizeA;m++)
|
|
if(l!=m)prod2*=1.0/sqrt(abs(phi(mu[m]-mu[l]-eta)));
|
|
for(int l=0; l<sizeB;l++)
|
|
for(int m=0; m<sizeB;m++)
|
|
if(abs(lam[m]-lam[l]-eta)!=0 && l!=m)prod3*=1.0/sqrt(abs(phi(lam[m]-lam[l]-eta)));
|
|
|
|
result+=2.0*log(abs(prod))-2.0*log(prod3)+2.0*log(prod2) - A.lnnorm - B.lnnorm;// a factor prod3^2 is inserted in the determinant!
|
|
SQMat_CX Hm(0.0, A.base.Mdown);
|
|
|
|
int index_a = 0;
|
|
int index_b = 0;
|
|
complex<DP> Prod_powerN;
|
|
|
|
for (int j = 0; j < A.chain.Nstrings; ++j) {
|
|
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
|
|
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
|
|
|
|
index_b = 0;
|
|
|
|
for (int k = 0; k < B.chain.Nstrings; ++k) {
|
|
for (int beta = 0; beta < B.base.Nrap[k]; ++beta) {
|
|
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
|
|
|
|
if (B.chain.Str_L[k] == 1) {
|
|
|
|
complex<DP> prodplus= complex<DP>(1.0,0.0);
|
|
complex<DP> prodminus= complex<DP>(1.0,0.0);
|
|
|
|
// use simplified code for one-string here: original form of Hm2P matrix
|
|
|
|
prodplus = Fn_K (A, j, alpha, a, B, k, beta, 0);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]+eta) )
|
|
prodplus*= exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta]
|
|
- re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]+eta) / prod_l!=k |phi(lam[l]-lam[k]) |;
|
|
prodminus = Fn_K (A, j, alpha, a, B, k, beta, 1);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]-eta) )
|
|
prodminus*= exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta]
|
|
- re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]-eta)/ prod_l!=k | phi(lam[l]-lam[k]) |;
|
|
|
|
Prod_powerN = pow((B.lambda[k][beta] -eta*0.5) /(B.lambda[k][beta] +eta*0.5), complex<DP> (B.chain.Nsites));
|
|
|
|
Hm[index_a][index_b] =eta*(prodplus-prodminus*Prod_powerN);
|
|
|
|
} // if (B.chain.Str_L == 1)
|
|
|
|
else {
|
|
|
|
if (b > 1) Hm[index_a][index_b] = eta* Fn_K(A, j, alpha, a, B, k, beta, b-1)
|
|
*exp(ln_Fn_G(A,B,k,beta,b-1))*exp(-real(ln_Fn_F(B, k, beta, b - 1)));//.../ prod_l!=k | phi(lam[l]-lam[k]) |
|
|
else if (b == 1) {
|
|
|
|
Vect_CX ln_FunctionF(B.chain.Str_L[k] + 2);
|
|
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionF[i] = ln_Fn_F (B, k, beta, i);
|
|
|
|
Vect_CX ln_FunctionG(B.chain.Str_L[k] + 2);
|
|
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionG[i] = ln_Fn_G (A, B, k, beta, i);
|
|
|
|
complex<DP> sum1 = complex<DP>(0.0,0.0);
|
|
|
|
sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0) *exp(ln_FunctionG[0]+ ln_FunctionG[1] //sum term when i=0
|
|
- ln_FunctionF[0] - ln_FunctionF[1]);
|
|
|
|
sum1 += Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k]) //sum term when i=n
|
|
* exp( ln_FunctionG[B.chain.Str_L[k]] + ln_FunctionG[B.chain.Str_L[k] + 1]
|
|
- ln_FunctionF[B.chain.Str_L[k]] - ln_FunctionF[B.chain.Str_L[k] + 1]);
|
|
|
|
for (int jsum = 1; jsum < B.chain.Str_L[k]; ++jsum)
|
|
|
|
sum1 -= Fn_L (A, j, alpha, a, B, k, beta, jsum) *
|
|
exp(ln_FunctionG[jsum] + ln_FunctionG[jsum + 1] - ln_FunctionF[jsum] - ln_FunctionF[jsum + 1]);
|
|
|
|
|
|
Hm[index_a][index_b] = eta * exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1]) * sum1 * exp( - real(ln_Fn_F(B, k, beta, b - 1))); //the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
|
|
} // else if (b == B.chain.Str_L[k])
|
|
} // else
|
|
index_b++;
|
|
}}} // sums over k, beta, b
|
|
|
|
// now define the elements Hm[a][M]
|
|
|
|
Hm[index_a][B.base.Mdown] = eta/((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5));
|
|
index_a++;
|
|
}}} // sums over j, alpha, a
|
|
|
|
complex<DP> F= complex<DP>(0.0,0.0);
|
|
|
|
complex<DP> detmatrix;
|
|
detmatrix=exp(lndet_LU_CX_dstry(Hm));
|
|
|
|
//mu is the ground state!
|
|
//A -> mu, B -> lam
|
|
SQMat_CX G(0.0, A.base.Mdown);
|
|
SQMat_CX BbDa(0.0, A.base.Mdown);
|
|
index_a = 0;
|
|
|
|
for (int j = 0; j < A.chain.Nstrings; ++j) {
|
|
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
|
|
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
|
|
|
|
index_b = 0;
|
|
|
|
complex<DP> Da;
|
|
complex<DP> Ca;
|
|
Da=eta/((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5));
|
|
Ca=eta*((mu[index_a]-eta*0.5)+(mu[index_a]+eta*0.5))/pow(((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5)),2.0);
|
|
|
|
|
|
for (int k = 0; k < B.chain.Nstrings; ++k) {
|
|
for (int beta = 0; beta < B.base.Nrap[k]; ++beta) {
|
|
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
|
|
|
|
{
|
|
|
|
if (b > 1){
|
|
G[index_a][index_b] = eta* Fn_K(A, j, alpha, a, B, k, beta, b-1)
|
|
*exp(ln_Fn_G(A,B,k,beta,b-1))
|
|
*exp(-real(ln_Fn_F(B, k, beta, b - 1)));//.../ prod_l!=k | phi(lam[l]-lam[k]) |
|
|
BbDa[index_a][index_b] =0 ;
|
|
}
|
|
else if (b == 1) {
|
|
|
|
Vect_CX ln_FunctionF(B.chain.Str_L[k] + 2);
|
|
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionF[i] = ln_Fn_F (B, k, beta, i);
|
|
|
|
Vect_CX ln_FunctionG(B.chain.Str_L[k] + 2);
|
|
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionG[i] = ln_Fn_G (A, B, k, beta, i);
|
|
|
|
complex<DP> sum1 = complex<DP>(0.0,0.0);
|
|
complex<DP> sum2 = complex<DP>(0.0,0.0);
|
|
|
|
sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0) *exp(ln_FunctionG[0]+ ln_FunctionG[1]
|
|
- ln_FunctionF[0] - ln_FunctionF[1]);//sum term when i=0
|
|
//sum2 doesn't have a i=0 term
|
|
|
|
sum1 += Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k])
|
|
* exp( ln_FunctionG[B.chain.Str_L[k]] + ln_FunctionG[B.chain.Str_L[k] + 1]
|
|
- ln_FunctionF[B.chain.Str_L[k]] - ln_FunctionF[B.chain.Str_L[k] + 1]); //sum term when i=n
|
|
sum2 += exp(ln_FunctionG[B.chain.Str_L[k]]- ln_FunctionF[B.chain.Str_L[k]] )
|
|
* (phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * B.chain.Str_L[k]))-eta*0.5)
|
|
+ phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * B.chain.Str_L[k]))+eta*0.5) ); //sum term when i=n
|
|
|
|
for (int jsum = 1; jsum < B.chain.Str_L[k]; ++jsum) {
|
|
sum1 -= Fn_L (A, j, alpha, a, B, k, beta, jsum) *
|
|
exp(ln_FunctionG[jsum] + ln_FunctionG[jsum + 1] - ln_FunctionF[jsum] - ln_FunctionF[jsum + 1]);
|
|
sum2 += exp(ln_FunctionG[jsum]- ln_FunctionF[jsum] )
|
|
* (phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * jsum))-eta*0.5)
|
|
+ phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * jsum))+eta*0.5) );
|
|
}
|
|
|
|
G[index_a][index_b] = eta * exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1])
|
|
* sum1 * exp( - real(ln_Fn_F(B, k, beta, b - 1))); //the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
|
|
BbDa[index_a][index_b] = - Da* exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1])
|
|
* sum2 * exp( - real(ln_Fn_F(B, k, beta, b - 1)));//the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
|
|
} // else if (b == B.chain.Str_L[k])
|
|
} // else
|
|
index_b++;
|
|
}}} // sums over k, beta, b
|
|
|
|
// now define the elements Hm[a][M]
|
|
G[index_a][B.base.Mdown]=Ca;
|
|
BbDa[index_a][B.base.Mdown]=0;
|
|
index_a++;
|
|
}}} // sums over j, alpha, a
|
|
|
|
SQMat_CX matrix(0.0, A.base.Mdown);
|
|
for(int a=0; a<sizeA;a++)
|
|
for(int b=0; b<sizeA;b++)
|
|
matrix[a][b]=G[a][b]+BbDa[a][b];
|
|
|
|
complex<DP> sum=prod*(exp(lndet_LU_CX_dstry(matrix))-exp(lndet_LU_CX_dstry(G)));
|
|
|
|
complex<DP> F2=exp(eta*(B.K-A.K))*(-2.0*sum);
|
|
complex<DP> F3=(exp(eta*(B.K-A.K)))*(detmatrix);
|
|
F=detmatrix;
|
|
F+=exp(i*(A.K-B.K))*(2.0*sum*(-1.0)+detmatrix);
|
|
|
|
result+=2.0*log(abs(F));
|
|
result-=log(A.chain.Nsites-A.base.Mdown*2+2.0);
|
|
complex<DP> ln_ME_sq = result;
|
|
|
|
delete[] mu;
|
|
delete[] lam;
|
|
|
|
return(0.5 * ln_ME_sq); // Return ME, not MEsq
|
|
|
|
}
|
|
|
|
} // namespace ABACUS
|