ABACUS/src/HEIS/ln_Szz_ME_XXX.cc

440 lines
15 KiB
C++

/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c) J.-S. Caux.
-----------------------------------------------------------
File: ln_Szz_ME_XXX.cc
Purpose: compute the S^z_j S^z_{j+1} matrix elemment for XXX
***********************************************************/
#include "ABACUS.h"
using namespace std;
using namespace ABACUS;
namespace ABACUS {
complex<DP> phi(complex<DP> x){return x;}
complex<DP> a(complex<DP> x){return 1;}
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);}
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_Szz_ME (XXX_Bethe_State& A, XXX_Bethe_State& B){
//clock_t start_time_local = clock();
//B has to be the ground state!
const DP Zero_Center_Thres=1.0e-5;
const DP real_dev=1.0e-14;
const DP Diff_ME_Thres=1.e-6;
// 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 Szz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) ABACUSerror("Incompatible Mdown between the two states in Szz matrix element!");
complex<DP> eta=-II;
complex<DP> ln_prod = complex<DP>(0.0,0.0);
complex<DP> result=-300;
complex<DP> prev_result=-300;
if((A.E)==(B.E) && B.chain.Nsites ==B.base.Mdown*2){
return(2*log(abs((B.E+(B.chain.Nsites)/4.0)/(3.0*sqrt(B.chain.Nsites)))));
}
XXX_Bethe_State A_origin; A_origin=A;
bool zero_string=false;
for (int j = 0; j < A_origin.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A_origin.base.Nrap[j]; ++alpha)
if(abs(A_origin.lambda[j][alpha])<Zero_Center_Thres) zero_string=true;
// Some convenient arrays
bool real_dev_conv=false;
int dev=-1;
while(!real_dev_conv){
real_dev_conv=true;
dev++;
//add a delta to the origin of the centered strings
if(zero_string){
real_dev_conv=false;
for (int j = 0; j < A.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha)
if(abs(A_origin.lambda[j][alpha])<Zero_Center_Thres)
A.lambda[j][alpha]=real_dev*pow(10.0,dev);
}
prev_result=result;
//add manualy the ground state value
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 * II * (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 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a));
index++;
}
Lambda re_ln_Fn_F_A_0(A.chain, A.base);
Lambda im_ln_Fn_F_A_0(A.chain, A.base);
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 < A.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
re_ln_Fn_F_A_0[j][alpha] = real(ln_Fn_F(A, j, alpha, 0));
im_ln_Fn_F_A_0[j][alpha] = imag(ln_Fn_F(A, j, alpha, 0));
}
}
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));
}
}
// Define regularized products in prefactors
for (int k = 0; k < A.chain.Nstrings; ++k)
for (int beta = 0; beta < A.base.Nrap[k]; ++beta)
for (int b = 1; b <= A.chain.Str_L[k]; ++b) {
if (b == 1)ln_prod3 += re_ln_Fn_F_A_0[k][beta];
else if (b > 1) ln_prod3 += ln_Fn_F(A, k, beta, b - 1);/*TEST*/
}
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) ln_prod4 += re_ln_Fn_F_B_0[k][beta];
else if (b > 1) ln_prod4 += ln_Fn_F(B, k, beta, b - 1);
}
complex<DP> prod=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);
double factor = log((B.chain.Nsites)*1/16.0);
factor +=(2.0*log(abs(prod)) - real(ln_prod3) + real(ln_prod4) - A.lnnorm - B.lnnorm);
// a factor prod4^-2 is inserted in the determinant!
int index_a = 0;
int index_b = 0;
complex<DP> Prod_powerN;
SQMat_CX H(0.0, A.base.Mdown);
SQMat_CX P(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));
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> Bb=complex<DP>(1.0,0.0);
for(int o=0; o<sizeB;o++)Bb*=phi(lam[o]-lam[index_b]+eta);
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);
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]);
prodminus = Fn_K (A, j, alpha, a, B, k, beta, 1);
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_powerN = pow((B.lambda[k][beta] - eta*0.5) /(B.lambda[k][beta] + eta*0.5),
complex<DP> (B.chain.Nsites));
H[index_a][index_b] = eta*(prodplus-prodminus*Prod_powerN);
P[index_a][index_b] = Bb*Da*exp(- re_ln_Fn_F_B_0[k][beta]);
} // if (B.chain.Str_L == 1)
else {
if (b > 1){
H[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]) |
P[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]] ); //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] );
}
H[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_...)
P[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
index_a++;
}}} // sums over j, alpha, a
complex<DP> F= complex<DP>(0.0,0.0);
SQMat_CX matrix(0.0, A.base.Mdown);
for(int j=0; j<sizeA;j++)
for(int k=0; k<sizeA;k++){
matrix[j][k]=(H[j][k]-2.0*P[j][k]);
}
complex<DP> detmatrix;
detmatrix=exp(lndet_LU_CX_dstry(matrix)+0.5*factor);
SQMat_CX Gn(0.0, A.base.Mdown);
complex<DP> sum_n=complex<DP>(0.0,0.0);
for(int n=0; n<sizeA;n++){
complex<DP> An;
An=-phi(lam[n]-eta*0.5);
for(int m=0; m<sizeA;m++)
An*=phi(lam[m]-lam[n]+eta);
SQMat_CX Gn(0.0, A.base.Mdown);
SQMat_CX BnbDa(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(index_b==n){
Gn[index_a][index_b] = Ca*exp(-real(ln_Fn_F(B, k, beta, b - 1)));
BnbDa[index_a][index_b] = 0;
} // else (index_b!=n)
else if (B.chain.Str_L[k] == 1) {
complex<DP> Bnb;
Bnb=-phi(lam[index_b]+eta*0.5)/phi(lam[n]-lam[index_b]-eta);
complex<DP> product=complex<DP>(1.0,0.0);
for(int o=0; o<sizeB;o++)product*=phi(lam[o]-lam[index_b]+eta);
Bnb*=product;
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));
Gn[index_a][index_b] =eta*(prodplus-prodminus*Prod_powerN);
BnbDa[index_a][index_b]=Bnb*Da*exp(- re_ln_Fn_F_B_0[k][beta]);
} // if (B.chain.Str_L == 1)
else{
ABACUSerror("The Szz matrix element computation is not able to handle string states "
"in the B.state (second argument). This is in development...");
} // else
index_b++;
}}} // sums over k, beta, b
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]=Gn[a][b]+BnbDa[a][b];
sum_n+=(exp(lndet_LU_CX_dstry(matrix)+0.5*factor+log(An))-exp(lndet_LU_CX_dstry(Gn)+0.5*factor+log(An)));
}// sum over n
sum_n*=prod;
F=(exp(II*(A.K-B.K))+1.0)*detmatrix;
F+=-4.0*exp(II*(A.K-B.K))*sum_n;
result=2*log(abs(F));
if (!(real_dev_conv) && abs(exp(result)-exp(prev_result))<abs( Diff_ME_Thres*exp(result))){
real_dev_conv=true;
}
if (!(real_dev_conv) && dev >20){
result=-300;
real_dev_conv=true;
}
delete[] mu;
delete[] lam;
}
//return(result);
return(0.5 * result); // Return ME, not MEsq
}
} // namespace ABACUS