/********************************************************** This software is part of J.-S. Caux's ABACUS library. Copyright (c) J.-S. Caux. ----------------------------------------------------------- File: ln_Smin_ME_ODSLF_XXZ.cc Purpose: S^- matrix element ***********************************************************/ #include "ABACUS.h" using namespace ABACUS; namespace ABACUS { inline complex ln_Fn_F (ODSLF_XXZ_Bethe_State& B, int k, int beta, int b) { complex ans = 0.0; complex prod_temp = 1.0; int counter = 0; int arg = 0; int absarg = 0; int par_comb_1, par_comb_2; for (int j = 0; j < B.chain.Nstrings; ++j) { par_comb_1 = B.chain.par[j] == B.chain.par[k] ? 1 : 0; par_comb_2 = B.chain.par[k] == B.chain.par[j] ? 0 : B.chain.par[k]; 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))) { arg = B.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b); absarg = abs(arg); prod_temp *= ((B.sinhlambda[j][alpha] * B.coshlambda[k][beta] - B.coshlambda[j][alpha] * B.sinhlambda[k][beta]) * (B.chain.co_n_anis_over_2[absarg] * par_comb_1 - sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_2) + II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta] - B.sinhlambda[j][alpha] * B.sinhlambda[k][beta]) * (sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_1 + B.chain.co_n_anis_over_2[absarg] * par_comb_2)); } if (counter++ > 100) { // we do at most 100 products before taking a log ans += log(prod_temp); prod_temp = 1.0; counter = 0; } }}} return(ans + log(prod_temp)); } inline complex ln_Fn_G (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b) { complex ans = 0.0; complex prod_temp = 1.0; int counter = 0; int arg = 0; int absarg = 0; int par_comb_1, par_comb_2; for (int j = 0; j < A.chain.Nstrings; ++j) { par_comb_1 = A.chain.par[j] == B.chain.par[k] ? 1 : 0; par_comb_2 = B.chain.par[k] == A.chain.par[j] ? 0 : B.chain.par[k]; for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) { for (int a = 1; a <= A.chain.Str_L[j]; ++a) { arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b); absarg = abs(arg); prod_temp *= ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta]) * (A.chain.co_n_anis_over_2[absarg] * par_comb_1 - sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_2) + II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta]) * (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_1 + A.chain.co_n_anis_over_2[absarg] * par_comb_2)); if (counter++ > 100) { // we do at most 100 products before taking a log ans += log(prod_temp); prod_temp = 1.0; counter = 0; } }}} return(ans + log(prod_temp)); } inline complex Fn_K (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b) { int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b); int absarg1 = abs(arg1); int arg2 = arg1 + 2; int absarg2 = abs(arg2); return(4.0/( ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta]) * (A.chain.co_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k]) - sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j])) + II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta]) * (sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k]) + A.chain.co_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j])) ) * ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta]) * (A.chain.co_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k]) - sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j])) + II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta]) * (sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k]) + A.chain.co_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j])) ) )); } inline complex Fn_L (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b) { return (sinh(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta] + 0.5 * II * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5)) + 0.25 * II * PI * complex(-A.chain.par[j] + B.chain.par[k]))) * pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0)); } complex ln_Smin_ME (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_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 ODSLF_XXZ_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!"); // Compute the sinh and cosh of rapidities A.Compute_sinhlambda(); A.Compute_coshlambda(); B.Compute_sinhlambda(); B.Compute_coshlambda(); // Some convenient arrays ODSLF_Lambda re_ln_Fn_F_B_0(B.chain, B.base); ODSLF_Lambda im_ln_Fn_F_B_0(B.chain, B.base); ODSLF_Lambda re_ln_Fn_G_0(B.chain, B.base); ODSLF_Lambda im_ln_Fn_G_0(B.chain, B.base); ODSLF_Lambda re_ln_Fn_G_2(B.chain, B.base); ODSLF_Lambda im_ln_Fn_G_2(B.chain, B.base); complex ln_prod1 = 0.0; complex ln_prod2 = 0.0; complex ln_prod3 = 0.0; complex 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(sinh(A.lambda[i][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0) + 0.25 * II * PI * (1.0 - A.chain.par[i])))); 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(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0) + 0.25 * II * PI * (1.0 - B.chain.par[i]))) > 100.0 * MACHINE_EPS_SQ) ln_prod2 += log(norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0) + 0.25 * II * PI * (1.0 - B.chain.par[i])))); // 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)); } } DP logabssinzeta = log(abs(sin(A.chain.anis))); // 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); // assume only one-strings here ln_prod3 -= A.base.Mdown * log(abs(sin(A.chain.anis))); 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.anis))); // Now proceed to build the Hm matrix SQMat_CX Hm(0.0, A.base.Mdown); int index_a = 0; int index_b = 0; complex sum1 = 0.0; complex sum2 = 0.0; complex prod_num = 0.0; complex Fn_K_0_G_0 = 0.0; complex Prod_powerN = 0.0; complex Fn_K_1_G_2 = 0.0; complex one_over_A_sinhlambda_sq_plus_sinzetaover2sq; 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_sinhlambda_sq_plus_sinzetaover2sq = 1.0/((sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a) + 0.25 * II * PI * (1.0 - A.chain.par[j]))) * (sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a) + 0.25 * II * PI * (1.0 - A.chain.par[j]))) + pow(sin(0.5*A.chain.anis), 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.chain.Str_L[k] == 1) { // use simplified code for one-string here: original form of Hm 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] + logabssinzeta); 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] + logabssinzeta); Prod_powerN = pow( B.chain.par[k] == 1 ? (B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1]) /(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1]) : (B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1]) /(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1]) , complex (B.chain.Nsites)); Hm[index_a][index_b] = Fn_K_0_G_0 - (1.0 - 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ 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 += (1.0 - 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ 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]); prod_num = exp(II * im_ln_Fn_F_B_0[k][beta] + ln_FunctionF[1] - ln_FunctionG[B.chain.Str_L[k]] + logabssinzeta); 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)) + logabssinzeta); // 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_sinhlambda_sq_plus_sinzetaover2sq; index_a++; }}} // sums over j, alpha, a complex 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)) + logabssinzeta - A.lnnorm - B.lnnorm; return(0.5 * ln_ME_sq); // Return ME, not MEsq } } // namespace ABACUS