ABACUS/src/LIEBLIN/ln_Density_ME.cc

84 lines
2.9 KiB
C++

/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c) J.-S. Caux.
-----------------------------------------------------------
File: ln_Density_ME.cc
Purpose: Computes the density operator \rho(x = 0) matrix element
***********************************************************/
#include "ABACUS.h"
using namespace std;
using namespace ABACUS;
namespace ABACUS {
complex<DP> Fn_V (int j, LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
complex<DP> result = 1.0;
for (int m = 0; m < lstate.N; ++m) {
result *= (lstate.lambdaoc[m] - rstate.lambdaoc[j] + II)/(rstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
}
return(result);
}
complex<DP> ln_Density_ME (LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
// Computes the log of the density operator \rho(x = 0) matrix element between lstate and rstate.
// If we have lstate == rstate, density matrix element = N/L:
if (lstate.Ix2 == rstate.Ix2) return(log(lstate.N/lstate.L));
// If momentum difference is zero but states are different, then matrix element is zero:
else if (lstate.iK == rstate.iK) return(-200.0); // so exp(.) is zero
SQMat_DP one_plus_U (0.0, lstate.N);
Vect_CX Vplus (0.0, lstate.N); // contains V^+_j; V^-_j is the conjugate
Vect_CX ln_Fn_Prod (0.0, lstate.N); // product_{m\neq j} (\mu_m - \lambdaoc_j)/(\lambdaoc_m - \lambdaoc_j)
Vect_DP rKern (0.0, lstate.N); // K(lambdaoc_j - lambdaoc_(p == arbitrary))
//int p = 0;
int p = rstate.N/2-1; // choice doesn't matter, see 1990_Slavnov_TMP_82 after (3.8). Choose rapidity around the middle.
DP Kout = lstate.K - rstate.K;
for (int a = 0; a < lstate.N; ++a) {
Vplus[a] = Fn_V (a, lstate, rstate);
ln_Fn_Prod[a] = 0.0;;
for (int m = 0; m < lstate.N; ++m)
if (m != a) ln_Fn_Prod[a] += log(complex<DP>(lstate.lambdaoc[m] - rstate.lambdaoc[a])
/(rstate.lambdaoc[m] - rstate.lambdaoc[a]));
rKern[a] = rstate.Kernel (a, p);
}
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
one_plus_U[a][b] = (a == b ? 1.0 : 0.0) + 0.5 * ((lstate.lambdaoc[a] - rstate.lambdaoc[a])/imag(Vplus[a]))
* real(exp(ln_Fn_Prod[a])) * (rstate.Kernel(a,b) - rKern[b]); // BUGRISK: why real here?
complex<DP> ln_ddalpha_sigma = lndet_LU_dstry(one_plus_U);
complex<DP> ln_prod_V = 0.0;
for (int a = 0; a < lstate.N; ++a) ln_prod_V += log(2.0 * II * imag(Vplus[a]));
complex<DP> ln_prod_2 = 0.0;
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
ln_prod_2 += log((rstate.lambdaoc[a] - rstate.lambdaoc[b] + II)/(lstate.lambdaoc[a] - rstate.lambdaoc[b]));
ln_ddalpha_sigma += ln_prod_V + ln_prod_2 - log(2.0 * II * imag(Vplus[p]));
return (log(-II * Kout) + ln_ddalpha_sigma - 0.5 * (lstate.lnnorm + rstate.lnnorm));
}
}