123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /**********************************************************
-
- This software is part of J.-S. Caux's ABACUS library.
-
- Copyright (c) J.-S. Caux.
-
- -----------------------------------------------------------
-
- File: ln_Smin_ME_XXX.cc
-
- Purpose: compute the S^- 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_Smin_ME (XXX_Bethe_State& A, XXX_Bethe_State& B)
- {
- // This function returns the natural log of the S^- operator matrix element.
- // The A and B states can contain strings.
-
- // Check that the two states are compatible
-
- if (A.chain != B.chain) ABACUSerror("Incompatible XXX_Chains in Smin matrix element.");
-
- // Check that A and B are Mdown-compatible:
-
- if (A.base.Mdown != B.base.Mdown + 1) ABACUSerror("Incompatible Mdown between the two states in Smin matrix element!");
-
- // 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...
-
- complex<DP> ln_FB0, ln_FG0, ln_FG2;
- 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));
- ln_FB0 = ln_Fn_F(B, j, alpha, 0);
- re_ln_Fn_F_B_0[j][alpha] = real(ln_FB0);
- im_ln_Fn_F_B_0[j][alpha] = imag(ln_FB0);
- //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));
- ln_FG0 = ln_Fn_G(A, B, j, alpha, 0);
- re_ln_Fn_G_0[j][alpha] = real(ln_FG0);
- im_ln_Fn_G_0[j][alpha] = imag(ln_FG0);
- //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));
- ln_FG2 = ln_Fn_G(A, B, j, alpha, 2);
- re_ln_Fn_G_2[j][alpha] = real(ln_FG2);
- im_ln_Fn_G_2[j][alpha] = imag(ln_FG2);
- }
- }
-
- // 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 Hm matrix
-
- SQMat_CX Hm(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> one_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;
-
- one_over_A_lambda_sq_plus_1over2sq = 1.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] + II * 0.5) /(B.lambda[k][beta] - II * 0.5), complex<DP> (B.chain.Nsites));
-
- Hm[index_a][index_b] = Fn_K_0_G_0 - Prod_powerN * Fn_K_1_G_2;
-
- } // if (B.chain.Str_L == 1)
-
- else {
-
- if (b <= B.chain.Str_L[k] - 1) Hm[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
-
- Hm[index_a][index_b] = prod_num * sum1;
-
- } // 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] = one_over_A_lambda_sq_plus_1over2sq;
-
- index_a++;
- }}} // sums over j, alpha, a
-
- complex<DP> ln_ME_sq = log(1.0 * A.chain.Nsites) + real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4)
- + 2.0 * real(lndet_LU_CX_dstry(Hm)) - A.lnnorm - B.lnnorm;
-
- //return(ln_ME_sq);
- return(0.5 * ln_ME_sq); // Return ME, not MEsq
-
- }
-
- } // namespace ABACUS
|