249 lines
8.4 KiB
C++
249 lines
8.4 KiB
C++
/**********************************************************
|
|
|
|
This software is part of J.-S. Caux's ABACUS library.
|
|
|
|
Copyright (c) J.-S. Caux.
|
|
|
|
-----------------------------------------------------------
|
|
|
|
File: ln_Sz_ME_XXX.cc
|
|
|
|
Purpose: compute the S^z matrix elemment for XXX
|
|
|
|
***********************************************************/
|
|
|
|
#include "ABACUS.h"
|
|
|
|
using namespace std;
|
|
using namespace ABACUS;
|
|
|
|
namespace ABACUS {
|
|
|
|
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_Sz_ME (XXX_Bethe_State& A, XXX_Bethe_State& B)
|
|
{
|
|
// 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 Sz 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 Sz matrix element!");
|
|
|
|
//if (A.iK == B.iK && (A.label != B.label))
|
|
if (A.iK == B.iK && (A.label.compare(B.label) != 0))
|
|
return(-300.0); // matrix element identically vanishes
|
|
|
|
// Some convenient arrays
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
// Define regularized products in prefactors
|
|
|
|
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)
|
|
ln_prod3 += ln_Fn_F (A, j, alpha, a - 1);
|
|
|
|
// ln_prod3 -= A.base.Mdown * log(abs(sin(A.chain.zeta)));
|
|
|
|
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);
|
|
}
|
|
|
|
// ln_prod4 -= B.base.Mdown * log(abs(sin(B.chain.zeta)));
|
|
|
|
// Now proceed to build the Hm2P matrix
|
|
|
|
SQMat_CX Hm2P(0.0, A.base.Mdown);
|
|
|
|
int index_a = 0;
|
|
int index_b = 0;
|
|
|
|
complex<DP> sum1 = 0.0;
|
|
complex<DP> sum2 = 0.0;
|
|
complex<DP> prod_num = 0.0;
|
|
complex<DP> Fn_K_0_G_0 = 0.0;
|
|
complex<DP> Prod_powerN = 0.0;
|
|
complex<DP> Fn_K_1_G_2 = 0.0;
|
|
complex<DP> two_over_A_lambda_sq_plus_1over2sq;
|
|
|
|
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;
|
|
|
|
two_over_A_lambda_sq_plus_1over2sq = 2.0/((A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) *
|
|
(A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) + 0.25);
|
|
|
|
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) {
|
|
|
|
// use simplified code for one-string here: original form of Hm2P matrix
|
|
|
|
Fn_K_0_G_0 = Fn_K (A, j, alpha, a, B, k, beta, 0) *
|
|
exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta]);
|
|
Fn_K_1_G_2 = Fn_K (A, j, alpha, a, B, k, beta, 1) *
|
|
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] + 0.5 * II)/(B.lambda[k][beta] - 0.5 * II),
|
|
complex<DP> (B.chain.Nsites));
|
|
|
|
Hm2P[index_a][index_b] = Fn_K_0_G_0 - Prod_powerN * Fn_K_1_G_2
|
|
- two_over_A_lambda_sq_plus_1over2sq * exp(II*im_ln_Fn_F_B_0[k][beta]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (b <= B.chain.Str_L[k] - 1) Hm2P[index_a][index_b] = Fn_K(A, j, alpha, a, B, k, beta, b);
|
|
else if (b == B.chain.Str_L[k]) {
|
|
|
|
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);
|
|
|
|
sum1 = 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]);
|
|
|
|
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]);
|
|
|
|
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 = 0.0;
|
|
|
|
for (int jsum = 1; jsum <= B.chain.Str_L[k]; ++jsum)
|
|
sum2 += exp(ln_FunctionG[jsum] - ln_FunctionF[jsum]);
|
|
|
|
prod_num = exp(II * im_ln_Fn_F_B_0[k][beta] + ln_FunctionF[1] - ln_FunctionG[B.chain.Str_L[k]]);
|
|
|
|
for (int jsum = 2; jsum <= B.chain.Str_L[k]; ++jsum)
|
|
prod_num *= exp(ln_FunctionG[jsum] - real(ln_Fn_F(B, k, beta, jsum - 1)));
|
|
// include all string contributions F_B_0 in this term
|
|
|
|
Hm2P[index_a][index_b] = prod_num * (sum1 - sum2 * two_over_A_lambda_sq_plus_1over2sq);
|
|
|
|
} // else if (b == B.chain.Str_L[k])
|
|
} // else
|
|
|
|
index_b++;
|
|
}}} // sums over k, beta, b
|
|
|
|
index_a++;
|
|
}}} // sums over j, alpha, a
|
|
|
|
DP det = real(lndet_LU_CX_dstry(Hm2P));
|
|
|
|
complex<DP> ln_ME_sq = log(0.25 * A.chain.Nsites) + real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4)
|
|
+ 2.0 * det
|
|
- A.lnnorm - B.lnnorm;
|
|
|
|
return(0.5 * ln_ME_sq); // Return ME, not MEsq
|
|
|
|
}
|
|
|
|
} // namespace ABACUS
|