You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ln_Smin_ME_XXZ.cc 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: ln_Smin_ME_XXZ.cc
  6. Purpose: compute the S^- matrix elemment for XXZ
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. using namespace ABACUS;
  11. namespace ABACUS {
  12. inline complex<DP> ln_Fn_F (XXZ_Bethe_State& B, int k, int beta, int b)
  13. {
  14. complex<DP> ans = 0.0;
  15. complex<DP> prod_temp = 1.0;
  16. int counter = 0;
  17. int arg = 0;
  18. int absarg = 0;
  19. int par_comb_1, par_comb_2;
  20. for (int j = 0; j < B.chain.Nstrings; ++j) {
  21. par_comb_1 = B.chain.par[j] == B.chain.par[k] ? 1 : 0;
  22. par_comb_2 = B.chain.par[k] == B.chain.par[j] ? 0 : B.chain.par[k];
  23. for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
  24. for (int a = 1; a <= B.chain.Str_L[j]; ++a) {
  25. if (!((j == k) && (alpha == beta) && (a == b))) {
  26. arg = B.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
  27. absarg = abs(arg);
  28. /*
  29. prod_temp *= 0.5 * //done later...
  30. ((B.sinhlambda[j][alpha] * B.coshlambda[k][beta] - B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
  31. * (B.chain.co_n_anis_over_2[absarg] * (1.0 + B.chain.par[j] * B.chain.par[k])
  32. - sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * (B.chain.par[k] - B.chain.par[j]))
  33. + II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta] - B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
  34. * (sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * (1.0 + B.chain.par[j] * B.chain.par[k])
  35. + B.chain.co_n_anis_over_2[absarg] * (B.chain.par[k] - B.chain.par[j])) );
  36. */
  37. prod_temp *= ((B.sinhlambda[j][alpha] * B.coshlambda[k][beta] - B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
  38. * (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)
  39. + II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta] - B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
  40. * (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));
  41. }
  42. if (counter++ > 100) { // we do at most 100 products before taking a log
  43. ans += log(prod_temp);
  44. prod_temp = 1.0;
  45. counter = 0;
  46. }
  47. }}}
  48. return(ans + log(prod_temp));
  49. }
  50. inline complex<DP> ln_Fn_G (XXZ_Bethe_State& A, XXZ_Bethe_State& B, int k, int beta, int b)
  51. {
  52. complex<DP> ans = 0.0;
  53. complex<DP> prod_temp = 1.0;
  54. int counter = 0;
  55. int arg = 0;
  56. int absarg = 0;
  57. int par_comb_1, par_comb_2;
  58. for (int j = 0; j < A.chain.Nstrings; ++j) {
  59. par_comb_1 = A.chain.par[j] == B.chain.par[k] ? 1 : 0;
  60. par_comb_2 = B.chain.par[k] == A.chain.par[j] ? 0 : B.chain.par[k];
  61. for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
  62. for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
  63. arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
  64. absarg = abs(arg);
  65. /*
  66. prod_temp *= 0.5 * //done later...
  67. ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
  68. * (A.chain.co_n_anis_over_2[absarg] * (1.0 + A.chain.par[j] * B.chain.par[k])
  69. - sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * (B.chain.par[k] - A.chain.par[j]))
  70. + II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
  71. * (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * (1.0 + A.chain.par[j] * B.chain.par[k])
  72. + A.chain.co_n_anis_over_2[absarg] * (B.chain.par[k] - A.chain.par[j])) );
  73. */
  74. prod_temp *= ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
  75. * (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)
  76. + II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
  77. * (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));
  78. if (counter++ > 100) { // we do at most 100 products before taking a log
  79. ans += log(prod_temp);
  80. prod_temp = 1.0;
  81. counter = 0;
  82. }
  83. }}}
  84. return(ans + log(prod_temp));
  85. }
  86. inline complex<DP> Fn_K (XXZ_Bethe_State& A, int j, int alpha, int a, XXZ_Bethe_State& B, int k, int beta, int b)
  87. {
  88. int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
  89. int absarg1 = abs(arg1);
  90. int arg2 = arg1 + 2;
  91. int absarg2 = abs(arg2);
  92. return(4.0/(
  93. ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
  94. * (A.chain.co_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
  95. - sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j]))
  96. + II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
  97. * (sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
  98. + A.chain.co_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j])) )
  99. *
  100. ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
  101. * (A.chain.co_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
  102. - sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j]))
  103. + II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
  104. * (sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
  105. + A.chain.co_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j])) )
  106. ));
  107. }
  108. inline complex<DP> Fn_L (XXZ_Bethe_State& A, int j, int alpha, int a, XXZ_Bethe_State& B, int k, int beta, int b)
  109. {
  110. return (sinh(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
  111. + 0.5 * II * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
  112. + 0.25 * II * PI * complex<DP>(-A.chain.par[j] + B.chain.par[k])))
  113. * pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
  114. }
  115. complex<DP> ln_Smin_ME (XXZ_Bethe_State& A, XXZ_Bethe_State& B)
  116. {
  117. // This function returns the natural log of the S^- operator matrix element.
  118. // The A and B states can contain strings.
  119. // Check that the two states are compatible
  120. if (A.chain != B.chain) ABACUSerror("Incompatible XXZ_Chains in Smin matrix element.");
  121. // Check that A and B are Mdown-compatible:
  122. if (A.base.Mdown != B.base.Mdown + 1) {
  123. cout << "A.base.Mdown = " << A.base.Mdown << "\tB.base.Mdown = " << B.base.Mdown << endl;
  124. cout << "A: " << A << endl << "B: " << B << endl;
  125. ABACUSerror("Incompatible Mdown between the two states in Smin matrix element!");
  126. }
  127. // Compute the sinh and cosh of rapidities
  128. A.Compute_sinhlambda();
  129. A.Compute_coshlambda();
  130. B.Compute_sinhlambda();
  131. B.Compute_coshlambda();
  132. // Some convenient arrays
  133. Lambda re_ln_Fn_F_B_0(B.chain, B.base);
  134. Lambda im_ln_Fn_F_B_0(B.chain, B.base);
  135. Lambda re_ln_Fn_G_0(B.chain, B.base);
  136. Lambda im_ln_Fn_G_0(B.chain, B.base);
  137. Lambda re_ln_Fn_G_2(B.chain, B.base);
  138. Lambda im_ln_Fn_G_2(B.chain, B.base);
  139. complex<DP> ln_prod1 = 0.0;
  140. complex<DP> ln_prod2 = 0.0;
  141. complex<DP> ln_prod3 = 0.0;
  142. complex<DP> ln_prod4 = 0.0;
  143. for (int i = 0; i < A.chain.Nstrings; ++i)
  144. for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
  145. for (int a = 1; a <= A.chain.Str_L[i]; ++a)
  146. 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)
  147. + 0.25 * II * PI * (1.0 - A.chain.par[i]))));
  148. for (int i = 0; i < B.chain.Nstrings; ++i)
  149. for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
  150. for (int a = 1; a <= B.chain.Str_L[i]; ++a)
  151. 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)
  152. + 0.25 * II * PI * (1.0 - B.chain.par[i]))) > 100.0 * MACHINE_EPS_SQ)
  153. 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)
  154. + 0.25 * II * PI * (1.0 - B.chain.par[i]))));
  155. // Define the F ones earlier...
  156. for (int j = 0; j < B.chain.Nstrings; ++j) {
  157. for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
  158. re_ln_Fn_F_B_0[j][alpha] = real(ln_Fn_F(B, j, alpha, 0));
  159. im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F(B, j, alpha, 0));
  160. re_ln_Fn_G_0[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 0));
  161. im_ln_Fn_G_0[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 0));
  162. re_ln_Fn_G_2[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 2));
  163. im_ln_Fn_G_2[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 2));
  164. }
  165. }
  166. DP logabssinzeta = log(abs(sin(A.chain.anis)));
  167. // Define regularized products in prefactors
  168. for (int j = 0; j < A.chain.Nstrings; ++j)
  169. for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha)
  170. for (int a = 1; a <= A.chain.Str_L[j]; ++a)
  171. ln_prod3 += ln_Fn_F(A, j, alpha, a - 1); // assume only one-strings here
  172. ln_prod3 -= A.base.Mdown * log(abs(sin(A.chain.anis)));
  173. for (int k = 0; k < B.chain.Nstrings; ++k)
  174. for (int beta = 0; beta < B.base.Nrap[k]; ++beta)
  175. for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
  176. if (b == 1) ln_prod4 += re_ln_Fn_F_B_0[k][beta];
  177. else if (b > 1) ln_prod4 += ln_Fn_F(B, k, beta, b - 1);
  178. }
  179. ln_prod4 -= B.base.Mdown * log(abs(sin(B.chain.anis)));
  180. // Now proceed to build the Hm matrix
  181. SQMat_CX Hm(0.0, A.base.Mdown);
  182. int index_a = 0;
  183. int index_b = 0;
  184. complex<DP> sum1 = 0.0;
  185. complex<DP> sum2 = 0.0;
  186. complex<DP> prod_num = 0.0;
  187. complex<DP> Fn_K_0_G_0 = 0.0;
  188. complex<DP> Prod_powerN = 0.0;
  189. complex<DP> Fn_K_1_G_2 = 0.0;
  190. complex<DP> one_over_A_sinhlambda_sq_plus_sinzetaover2sq;
  191. for (int j = 0; j < A.chain.Nstrings; ++j) {
  192. for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
  193. for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
  194. index_b = 0;
  195. 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)
  196. + 0.25 * II * PI * (1.0 - A.chain.par[j])))
  197. * (sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
  198. + 0.25 * II * PI * (1.0 - A.chain.par[j])))
  199. + pow(sin(0.5*A.chain.anis), 2.0));
  200. for (int k = 0; k < B.chain.Nstrings; ++k) {
  201. for (int beta = 0; beta < B.base.Nrap[k]; ++beta) {
  202. for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
  203. if (B.chain.Str_L[k] == 1) {
  204. // use simplified code for one-string here: original form of Hm matrix
  205. Fn_K_0_G_0 = Fn_K (A, j, alpha, a, B, k, beta, 0) *
  206. 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);
  207. Fn_K_1_G_2 = Fn_K (A, j, alpha, a, B, k, beta, 1) *
  208. 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);
  209. Prod_powerN = pow( B.chain.par[k] == 1 ?
  210. (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])
  211. /(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])
  212. :
  213. (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])
  214. /(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])
  215. , complex<DP> (B.chain.Nsites));
  216. Hm[index_a][index_b] = Fn_K_0_G_0 - Prod_powerN * Fn_K_1_G_2;
  217. } // if (B.chain.Str_L == 1)
  218. else {
  219. if (b <= B.chain.Str_L[k] - 1) Hm[index_a][index_b] = Fn_K(A, j, alpha, a, B, k, beta, b);
  220. else if (b == B.chain.Str_L[k]) {
  221. Vect_CX ln_FunctionF(B.chain.Str_L[k] + 2);
  222. for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionF[i] = ln_Fn_F (B, k, beta, i);
  223. Vect_CX ln_FunctionG(B.chain.Str_L[k] + 2);
  224. for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionG[i] = ln_Fn_G (A, B, k, beta, i);
  225. sum1 = 0.0;
  226. sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0) * exp(ln_FunctionG[0] + ln_FunctionG[1] - ln_FunctionF[0] - ln_FunctionF[1]);
  227. sum1 += Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k])
  228. * exp(ln_FunctionG[B.chain.Str_L[k]] + ln_FunctionG[B.chain.Str_L[k] + 1]
  229. - ln_FunctionF[B.chain.Str_L[k]] - ln_FunctionF[B.chain.Str_L[k] + 1]);
  230. for (int jsum = 1; jsum < B.chain.Str_L[k]; ++jsum)
  231. sum1 -= Fn_L (A, j, alpha, a, B, k, beta, jsum) *
  232. exp(ln_FunctionG[jsum] + ln_FunctionG[jsum + 1] - ln_FunctionF[jsum] - ln_FunctionF[jsum + 1]);
  233. /*
  234. sum2 = 0.0;
  235. for (int jsum = 1; jsum <= B.chain.Str_L[k]; ++jsum) sum2 += exp(ln_FunctionG[jsum] - ln_FunctionF[jsum]);
  236. */
  237. prod_num = exp(II * im_ln_Fn_F_B_0[k][beta] + ln_FunctionF[1] - ln_FunctionG[B.chain.Str_L[k]] + logabssinzeta);
  238. for (int jsum = 2; jsum <= B.chain.Str_L[k]; ++jsum)
  239. prod_num *= exp(ln_FunctionG[jsum] - real(ln_Fn_F(B, k, beta, jsum - 1)) + logabssinzeta);
  240. // include all string contributions F_B_0 in this term
  241. Hm[index_a][index_b] = prod_num * sum1;
  242. } // else if (b == B.chain.Str_L[k])
  243. } // else
  244. index_b++;
  245. }}} // sums over k, beta, b
  246. // now define the elements Hm[a][M]
  247. Hm[index_a][B.base.Mdown] = one_over_A_sinhlambda_sq_plus_sinzetaover2sq;
  248. index_a++;
  249. }}} // sums over j, alpha, a
  250. complex<DP> ln_ME_sq = log(1.0 * A.chain.Nsites) + real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4)
  251. + 2.0 * real(lndet_LU_CX_dstry(Hm)) + logabssinzeta - A.lnnorm - B.lnnorm;
  252. //return(ln_ME_sq);
  253. return(0.5 * ln_ME_sq); // Return ME, not MEsq
  254. }
  255. } // namespace ABACUS