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.

XXZ_gpd_Bethe_State.cc 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c)
  4. -----------------------------------------------------------
  5. File: src/HEIS/XXZ_gpd_Bethe_State.cc
  6. Purpose: Defines all functions for XXZ_gpd_Bethe_State
  7. ******************************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. namespace ABACUS {
  11. // Function prototypes
  12. inline DP fbar_XXZ_gpd (DP lambda, int par, DP tanhnetaover2);
  13. DP Theta_XXZ_gpd (DP lambda, int nj, int nk, DP* tanhnetaover2);
  14. DP hbar_XXZ_gpd (DP lambda, int n, DP* si_n_anis_over_2);
  15. DP ddlambda_Theta_XXZ_gpd (DP lambda, int nj, int nk, DP* si_n_anis_over_2);
  16. //***************************************************************************************************
  17. // Function definitions: class XXZ_gpd_Bethe_State
  18. XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State ()
  19. : Heis_Bethe_State(), sinlambda(Lambda(chain, 1)), coslambda(Lambda(chain, 1)), tanlambda(Lambda(chain, 1))
  20. {};
  21. XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const XXZ_gpd_Bethe_State& RefState) // copy constructor
  22. : Heis_Bethe_State(RefState),
  23. sinlambda(Lambda(RefState.chain, RefState.base)), coslambda(Lambda(RefState.chain, RefState.base)),
  24. tanlambda(Lambda(RefState.chain, RefState.base))
  25. {
  26. // copy arrays into new ones
  27. for (int j = 0; j < RefState.chain.Nstrings; ++j) {
  28. for (int alpha = 0; alpha < RefState.base[j]; ++j) {
  29. sinlambda[j][alpha] = RefState.sinlambda[j][alpha];
  30. coslambda[j][alpha] = RefState.coslambda[j][alpha];
  31. tanlambda[j][alpha] = RefState.tanlambda[j][alpha];
  32. }
  33. }
  34. }
  35. XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const Heis_Chain& RefChain, int M)
  36. : Heis_Bethe_State(RefChain, M),
  37. sinlambda(Lambda(RefChain, M)), coslambda(Lambda(RefChain, M)), tanlambda(Lambda(RefChain, M))
  38. {
  39. if (RefChain.Delta <= 1.0) ABACUSerror("Delta too low in XXZ_gpd_Bethe_State constructor");
  40. }
  41. XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const Heis_Chain& RefChain, const Heis_Base& RefBase)
  42. : Heis_Bethe_State(RefChain, RefBase),
  43. sinlambda(Lambda(RefChain, RefBase)), coslambda(Lambda(RefChain, RefBase)),
  44. tanlambda(Lambda(RefChain, RefBase))
  45. {
  46. if (RefChain.Delta <= 1.0) ABACUSerror("Delta too low in XXZ_gpd_Bethe_State constructor");
  47. }
  48. /*
  49. XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const Heis_Chain& RefChain, long long int base_id_ref, long long int type_id_ref)
  50. : Heis_Bethe_State(RefChain, base_id_ref, type_id_ref),
  51. sinlambda(Lambda(chain, base)), coslambda(Lambda(chain, base)), tanlambda(Lambda(chain, base))
  52. {
  53. if (RefChain.Delta <= 1.0) ABACUSerror("Delta too low in XXZ_gpd_Bethe_State constructor");
  54. }
  55. */
  56. XXZ_gpd_Bethe_State& XXZ_gpd_Bethe_State::operator= (const XXZ_gpd_Bethe_State& RefState)
  57. {
  58. if (this != &RefState) {
  59. chain = RefState.chain;
  60. base = RefState.base;
  61. //offsets = RefState.offsets;
  62. Ix2 = RefState.Ix2;
  63. lambda = RefState.lambda;
  64. BE = RefState.BE;
  65. diffsq = RefState.diffsq;
  66. conv = RefState.conv;
  67. iter = RefState.iter;
  68. iter_Newton = RefState.iter_Newton;
  69. E = RefState.E;
  70. iK = RefState.iK;
  71. K = RefState.K;
  72. lnnorm = RefState.lnnorm;
  73. //base_id = RefState.base_id;
  74. //type_id = RefState.type_id;
  75. //id = RefState.id;
  76. //maxid = RefState.maxid;
  77. //nparticles = RefState.nparticles;
  78. label = RefState.label;
  79. sinlambda = RefState.sinlambda;
  80. coslambda = RefState.coslambda;
  81. tanlambda = RefState.tanlambda;
  82. }
  83. return(*this);
  84. }
  85. // Member functions
  86. void XXZ_gpd_Bethe_State::Set_Free_lambdas()
  87. {
  88. // Sets all the rapidities to the solutions of the BAEs without scattering terms
  89. for (int i = 0; i < chain.Nstrings; ++i) {
  90. for (int alpha = 0; alpha < base[i]; ++alpha) {
  91. lambda[i][alpha] = atan((tanh(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)));
  92. }
  93. }
  94. return;
  95. }
  96. void XXZ_gpd_Bethe_State::Compute_sinlambda()
  97. {
  98. for (int j = 0; j < chain.Nstrings; ++j) {
  99. for (int alpha = 0; alpha < base[j]; ++alpha) sinlambda[j][alpha] = sin(lambda[j][alpha]);
  100. }
  101. return;
  102. }
  103. void XXZ_gpd_Bethe_State::Compute_coslambda()
  104. {
  105. for (int j = 0; j < chain.Nstrings; ++j) {
  106. for (int alpha = 0; alpha < base[j]; ++alpha) coslambda[j][alpha] = cos(lambda[j][alpha]);
  107. }
  108. return;
  109. }
  110. void XXZ_gpd_Bethe_State::Compute_tanlambda()
  111. {
  112. for (int j = 0; j < chain.Nstrings; ++j) {
  113. for (int alpha = 0; alpha < base[j]; ++alpha) {
  114. tanlambda[j][alpha] = tan(lambda[j][alpha]);
  115. //if (lambda[j][alpha] > 0.5*PI) cout << "Rapidity higher than 0.5*PI: j = " << j << "\talpha = " << alpha << "\trap = " << lambda[j][alpha] << "\ttan = " << tanlambda[j][alpha] << endl;
  116. }
  117. }
  118. return;
  119. }
  120. bool XXZ_gpd_Bethe_State::Check_Admissibility(char option)
  121. {
  122. // This function checks the admissibility of the Ix2's of a state:
  123. // returns false if there are higher strings with Ix2 = 0, a totally symmetric distribution of I's at each level,
  124. // and strings of equal length modulo 2 and parity with Ix2 = 0, meaning at least two equal roots in BAE.
  125. bool answer = true;
  126. Vect<bool> Zero_at_level(false, chain.Nstrings); // whether there exists an Ix2 == 0 at a given level
  127. /*
  128. Vect<bool> min_Ix2_max_busy(false, chain.Nstrings);
  129. Vect<bool> plus_Ix2_max_busy(false, chain.Nstrings);
  130. for (int j = 0; j < chain.Nstrings; ++j)
  131. for (int alpha = 0; alpha < base[j]; ++alpha) {
  132. if (Ix2[j][alpha] == -base.Ix2_max[j]) min_Ix2_max_busy[j] = true;
  133. if (Ix2[j][alpha] == base.Ix2_max[j]) plus_Ix2_max_busy[j] = true;
  134. }
  135. */
  136. /*
  137. // State is not admissible if this is false: -N/2 + 1 \leq \sum I^j_{\alpha} \leq N
  138. int sum_all_Ix2 = 0;
  139. for (int j = 0; j < chain.Nstrings; ++j)
  140. for (int alpha = 0; alpha < base[j]; ++alpha) {
  141. sum_all_Ix2 += Ix2[j][alpha];
  142. }
  143. if (sum_all_Ix2 > chain.Nsites || sum_all_Ix2 <= -chain.Nsites) {
  144. cout << "\tSum Ix2 out of fundamental interval: sum_all_Ix2 = " << sum_all_Ix2 << "\tfor N = " << chain.Nsites << endl;
  145. return(false);
  146. }
  147. */
  148. //Deactivated 2014 06 11, put in Heis_Form_Factor_Entry.cc
  149. /*
  150. // State is not admissible if I_max > 1/2 (N - \sum_k t_{jk} M_k) or I_min < -1/2 (N - sum_k...) + 1 at any level:
  151. int sum1 = 0;
  152. for (int j = 0; j < chain.Nstrings; ++j) {
  153. sum1 = 0;
  154. for (int k = 0; k < chain.Nstrings; ++k) {
  155. sum1 += base[k] * (2 * ABACUS::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1 : 0));
  156. }
  157. // Define limits...
  158. //if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1;
  159. // This almost does it: only missing are the states with one on -PI/2 and one on PI/2
  160. if (base[j] >= 1 && (Ix2[j][0] <= -(chain.Nsites - sum1) ||
  161. (Ix2[j][base[j] - 1] - Ix2[j][0]) > 2*(chain.Nsites - sum1))) {
  162. //cout << "\tAn Ix2 is out of interval at level " << j << endl;
  163. //cout << Ix2[j][base[j] - 1] << "\t" << Ix2[j][0] << "\t" << chain.Nsites << "\t" << sum1 << endl;
  164. return(false);
  165. }
  166. }
  167. */
  168. /*
  169. // State is not admissible if both a min_ and plus_Ix2_max are busy simultaneously:
  170. bool is_a_min_Ix2_max_busy = false;
  171. for (int j = 0; j < chain.Nstrings; ++j) if (min_Ix2_max_busy[j]) is_a_min_Ix2_max_busy = true;
  172. bool is_a_plus_Ix2_max_busy = false;
  173. for (int j = 0; j < chain.Nstrings; ++j) if (plus_Ix2_max_busy[j]) is_a_plus_Ix2_max_busy = true;
  174. */
  175. /*
  176. // State is not admissible if all min_Ix2_max are busy simultaneously:
  177. bool any_min_Ix2_max_free = false;
  178. for (int j = 0; j < chain.Nstrings; ++j)
  179. if (base[j] > 0 && !min_Ix2_max_busy[j]) any_min_Ix2_max_free = true;
  180. if (!any_min_Ix2_max_free) return(false);
  181. */
  182. /*
  183. // State is not admissible if -Ix2_max, -Ix2_max + 2, ..., -Ix2_max + 2*(Str_L - 1) are busy:
  184. for (int j = 0; j < chain.Nstrings; ++j)
  185. if (base[j] > 0 && Ix2[j][0] <= -base.Ix2_max[j] + 2*(chain.Str_L[j] - 1))
  186. return(false);
  187. // Almost correct with above !
  188. // State is not admissible if Ix2_max - 2, ..., Ix2_max - 2*(Str_L - 2) are busy (NB: one slot more than on left):
  189. for (int j = 0; j < chain.Nstrings; ++j)
  190. if (base[j] > 0 && Ix2[j][base[j] - 1] >= base.Ix2_max[j] - 2*(chain.Str_L[j] - 2))
  191. return(false);
  192. */
  193. // Check that at all at least doubly occupied levels, the difference between max and min quantum numbers
  194. // is strictly smaller than 2*Ix2_max - 2, so that lambda_max - lambda_min < PI at each level:
  195. //for (int j = 0; j < chain.Nstrings; ++j)
  196. //if (base[j] >= 2 && Ix2[j][base[j] - 1] - Ix2[j][0] >= 2* base.Ix2_max[j] - 2) answer = false;
  197. //if (is_a_min_Ix2_max_busy && is_a_plus_Ix2_max_busy) return(false);
  198. bool higher_string_on_zero = false;
  199. for (int j = 0; j < chain.Nstrings; ++j) {
  200. // The following line puts answer to true if there is at least one higher string with zero Ix2
  201. for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] > 2) /*&& !(chain.Str_L[j] % 2)*/)
  202. higher_string_on_zero = true;
  203. for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
  204. // NOTE: if base[j] == 0, Zero_at_level[j] remains false.
  205. }
  206. bool symmetric_state = (*this).Check_Symmetry();
  207. bool string_coincidence = false;
  208. // Checks that we have strings of equal length modulo 2 and same parity with Ix2 == 0, so equal rapidities, and inadmissibility
  209. for (int j1 = 0; j1 < chain.Nstrings; ++j1) {
  210. for (int j2 = j1 + 1; j2 < chain.Nstrings; ++j2)
  211. if (Zero_at_level[j1] && Zero_at_level[j2] && (!((chain.Str_L[j1] + chain.Str_L[j2])%2)))
  212. string_coincidence = true;
  213. }
  214. //bool onep_onem_on_zero = false;
  215. //if (option == 'm' || option == 'p') { // for Smin, we also exclude symmetric states with 1+ and 1- strings on zero
  216. //if (Zero_at_level[0] && Zero_at_level[1]) onep_onem_on_zero = true;
  217. //}
  218. //cout << min_Ix2_max_busy << "\t" << symmetric_state << "\t" << higher_string_on_zero << "\t" << string_coincidence << "\t" << onep_onem_on_zero << endl;
  219. //answer = !((symmetric_state && (higher_string_on_zero || string_coincidence || onep_onem_on_zero)));
  220. answer = !(symmetric_state && (higher_string_on_zero || string_coincidence));
  221. // Explicitly exclude state with min_Ix2_max_busy && iK == 0
  222. //Compute_Momentum();
  223. //answer = !((min_Ix2_max_busy && iK == 0) || (symmetric_state && (higher_string_on_zero || string_coincidence || onep_onem_on_zero)));
  224. // Now check that no Ix2 is equal to +N (since we take -N into account, and I + N == I by periodicity of exp)
  225. for (int j = 0; j < chain.Nstrings; ++j)
  226. for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] < -chain.Nsites) || (Ix2[j][alpha] >= chain.Nsites)) answer = false;
  227. if (!answer) {
  228. E = 0.0;
  229. K = 0.0;
  230. conv = 0;
  231. iter = 0;
  232. iter_Newton = 0;
  233. lnnorm = -100.0;
  234. }
  235. return(answer); // answer == true: nothing wrong with this Ix2_config
  236. }
  237. void XXZ_gpd_Bethe_State::Compute_BE (int j, int alpha)
  238. {
  239. // Fills in the BE members with the value of the Bethe equations.
  240. tanlambda[j][alpha] = tan(lambda[j][alpha]);
  241. DP sumtheta = 0.0;
  242. sumtheta = 0.0;
  243. for (int k = 0; k < chain.Nstrings; ++k) {
  244. for (int beta = 0; beta < base[k]; ++beta)
  245. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1)) {
  246. sumtheta += atan ((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
  247. * chain.ta_n_anis_over_2[2]))
  248. + PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  249. }
  250. else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
  251. chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
  252. + PI * (2.0 * ABACUS::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
  253. * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  254. }
  255. sumtheta *= 2.0;
  256. BE[j][alpha] = 2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  257. + PI * floor(0.5 + lambda[j][alpha]/PI))
  258. - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
  259. }
  260. void XXZ_gpd_Bethe_State::Compute_BE ()
  261. {
  262. // Fills in the BE members with the value of the Bethe equations.
  263. (*this).Compute_tanlambda();
  264. DP sumtheta = 0.0;
  265. for (int j = 0; j < chain.Nstrings; ++j)
  266. for (int alpha = 0; alpha < base[j]; ++alpha) {
  267. sumtheta = 0.0;
  268. for (int k = 0; k < chain.Nstrings; ++k) {
  269. for (int beta = 0; beta < base[k]; ++beta)
  270. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1)) {
  271. sumtheta += atan ((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
  272. * chain.ta_n_anis_over_2[2]))
  273. + PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  274. }
  275. else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
  276. chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
  277. + PI * (2.0 * ABACUS::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
  278. * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  279. }
  280. sumtheta *= 2.0;
  281. BE[j][alpha] = 2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  282. + PI * floor(0.5 + lambda[j][alpha]/PI))
  283. - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
  284. }
  285. }
  286. DP XXZ_gpd_Bethe_State::Iterate_BAE (int j, int alpha)
  287. {
  288. // Returns a new iteration value for lambda[j][alpha] given tanlambda[][] and BE[][]
  289. // Assumes that tanlambda[][] and BE[][] have been computed.
  290. DP arg0 = 0.5 * (2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  291. + PI * floor(0.5 + lambda[j][alpha]/PI)) - BE[j][alpha]);
  292. DP arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan(
  293. arg0
  294. //0.5 *
  295. //(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
  296. //(2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  297. // + PI * floor(0.5 + lambda[j][alpha]/PI)) - BE[j][alpha])
  298. );
  299. return(atan(arg)
  300. //+ PI * floor(0.5 + arg0)
  301. //0.5 * (Ix2[j][alpha] + sumtheta/PI)/(chain.Nsites)
  302. + PI * floor(0.5 + arg0/PI)
  303. );
  304. }
  305. /*
  306. void XXZ_gpd_Bethe_State::Iterate_BAE ()
  307. {
  308. // Recalculates the rapidities by iterating Bethe equations
  309. Lambda New_lambda(chain, base);
  310. DP sumtheta = 0.0;
  311. DP arg = 0.0;
  312. // First, compute the tan of rapidities:
  313. (*this).Compute_tanlambda();
  314. for (int j = 0; j < chain.Nstrings; ++j) {
  315. for (int alpha = 0; alpha < base[j]; ++alpha) {
  316. sumtheta = 0.0;
  317. for (int k = 0; k < chain.Nstrings; ++k) {
  318. for (int beta = 0; beta < base[k]; ++beta)
  319. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  320. sumtheta += atan((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
  321. * chain.ta_n_anis_over_2[2]))
  322. + PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  323. else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
  324. chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
  325. + PI * (2.0 * ABACUS::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
  326. * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  327. }
  328. sumtheta *= 2.0;
  329. arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan((PI * 0.5 * Ix2[j][alpha] + 0.5 * sumtheta)/chain.Nsites);
  330. New_lambda[j][alpha] = atan(arg) + PI * floor(0.5 + (0.5 * Ix2[j][alpha] + 0.5 * sumtheta/PI)/(chain.Nsites));
  331. }
  332. }
  333. DP New_diffsq = 0.0;
  334. for (int j = 0; j < chain.Nstrings; ++j) {
  335. for (int alpha = 0; alpha < base[j]; ++alpha) {
  336. //New_diffsq += pow(tan(New_lambda[j][alpha]) - tanlambda[j][alpha], 2.0);
  337. New_diffsq += pow(New_lambda[j][alpha] - lambda[j][alpha], 2.0);
  338. lambda[j][alpha] = 1.0 * New_lambda[j][alpha] + 0.0 * lambda[j][alpha];
  339. }
  340. }
  341. diffsq = New_diffsq;
  342. iter++;
  343. return;
  344. }
  345. */
  346. /*
  347. void XXZ_gpd_Bethe_State::Iterate_BAE_Newton ()
  348. {
  349. // does one step of a Newton method on the rapidities...
  350. Vect_DP RHSBAE (0.0, base.Nraptot); // contains RHS of BAEs
  351. Vect_CX dlambda (0.0, base.Nraptot); // contains delta lambda computed from Newton's method
  352. SQMat_CX Gaudin (0.0, base.Nraptot);
  353. Vect_INT indx (base.Nraptot);
  354. DP sumtheta = 0.0;
  355. DP arg = 0.0;
  356. DP fn_arg = 0.0;
  357. DP olddiffsq = diffsq;
  358. // Compute the RHS of the BAEs:
  359. int index = 0;
  360. (*this).Compute_tanlambda();
  361. for (int j = 0; j < chain.Nstrings; ++j) {
  362. for (int alpha = 0; alpha < base[j]; ++alpha) {
  363. sumtheta = 0.0;
  364. for (int k = 0; k < chain.Nstrings; ++k) {
  365. for (int beta = 0; beta < base[k]; ++beta)
  366. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1)) {
  367. sumtheta += atan ((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
  368. * chain.ta_n_anis_over_2[2]))
  369. + PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  370. }
  371. else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
  372. chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
  373. + PI * (2.0 * ABACUS::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
  374. * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
  375. }
  376. sumtheta *= 2.0;
  377. RHSBAE[index] = chain.Nsites * 2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  378. + PI * floor(0.5 + lambda[j][alpha]/PI))
  379. // )
  380. - sumtheta - PI*Ix2[j][alpha];
  381. index++;
  382. }
  383. }
  384. (*this).Build_Reduced_Gaudin_Matrix (Gaudin);
  385. for (int i = 0; i < base.Nraptot; ++i) dlambda[i] = - RHSBAE[i];
  386. DP d;
  387. ludcmp_CX (Gaudin, indx, d);
  388. lubksb_CX (Gaudin, indx, dlambda);
  389. diffsq = 0.0;
  390. // for (int i = 0; i < base.Nraptot; ++i) diffsq += norm(dlambda[i]);
  391. int ctr = 0;
  392. for (int j = 0; j < chain.Nstrings; ++j) {
  393. for (int alpha = 0; alpha < base[j]; ++alpha) {
  394. diffsq += norm(tan(lambda[j][alpha] + dlambda[ctr]) - tanlambda[j][alpha]);
  395. // cout << "lambda = " << lambda[j][alpha] << "\tdlambda = " << dlambda[ctr] << endl;
  396. ctr++;
  397. }
  398. }
  399. // if we've converged, calculate the norm here, since the work has been done...
  400. if (diffsq < chain.prec) {
  401. lnnorm = 0.0;
  402. for (int j = 0; j < base.Nraptot; j++) lnnorm += log(abs(Gaudin[j][j]));
  403. }
  404. index = 0;
  405. for (int j = 0; j < chain.Nstrings; ++j) {
  406. for (int alpha = 0; alpha < base[j]; ++alpha) {
  407. lambda[j][alpha] += real(dlambda[index]);
  408. index++;
  409. }
  410. }
  411. iter_Newton++;
  412. // cout << "iter_N = " << iter_Newton << "\t" << diffsq << endl;
  413. return;
  414. }
  415. */
  416. bool XXZ_gpd_Bethe_State::Check_Rapidities()
  417. {
  418. bool nonan = true;
  419. for (int j = 0; j < chain.Nstrings; ++j)
  420. for (int alpha = 0; alpha < base[j]; ++alpha) if (nonan) nonan = ((!is_nan(lambda[j][alpha]))
  421. //&& (lambda[j][alpha] > -0.5*PI*chain.Str_L[j])
  422. //&& (lambda[j][alpha] <= 0.5*PI*chain.Str_L[j])
  423. );
  424. bool all_within_pi_interval = true;
  425. DP min_lambda = 10.0;
  426. DP max_lambda = -10.0;
  427. for (int j = 0; j < chain.Nstrings; ++j)
  428. for (int alpha = 0; alpha < base[j]; ++alpha) {
  429. if (lambda[j][alpha] < min_lambda) min_lambda = lambda[j][alpha];
  430. if (lambda[j][alpha] > max_lambda) max_lambda = lambda[j][alpha];
  431. }
  432. //all_within_pi_interval = (fabs(max_lambda - min_lambda) < PI - 0.0 * 1.0e-12);
  433. // Use pi interval, but centered on 0:
  434. all_within_pi_interval = max_lambda < 0.5* PI + 1.0e-8 && min_lambda > -0.5* PI - 1.0e-8;
  435. //nonan *= all_within_pi_interval;
  436. return nonan;
  437. }
  438. DP XXZ_gpd_Bethe_State::String_delta ()
  439. {
  440. // Computes the sum of absolute value of \delta^{a, a+1} in string hypothesis, for a given bethe eigenstate
  441. DP delta = 0.0;
  442. int occupied_strings = 0;
  443. for (int i = 0; i < (*this).chain.Nstrings; ++i) if ((*this).chain.Str_L[i] > 1) occupied_strings += (*this).base.Nrap[i];
  444. //if ((*this).conv == 0) delta = 1.0;
  445. if (occupied_strings == 0) delta = 0.0;
  446. else {
  447. Vect_DP ln_deltadiff(0.0, 1000); // contains ln |delta^{a, a+1}|
  448. Vect_DP deltadiff(0.0, 1000); // contains |delta^{a, a+1}|
  449. complex<DP> log_BAE_reg = 0.0;
  450. for (int j = 0; j < (*this).chain.Nstrings; ++j) {
  451. for (int alpha = 0; alpha < (*this).base[j]; ++alpha) {
  452. ln_deltadiff = 0.0;
  453. for (int a = 1; a <= (*this).chain.Str_L[j]; ++a) {
  454. if ((*this).chain.Str_L[j] > 1) { // else the BAE are already 1
  455. log_BAE_reg = DP((*this).chain.Nsites) * log(sin((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis
  456. * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a + 1.0))
  457. /sin((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a - 1.0)));
  458. for (int k = 0; k < (*this).chain.Nstrings; ++k)
  459. for (int beta = 0; beta < (*this).base[k]; ++beta)
  460. for (int b = 1; b <= (*this).chain.Str_L[k]; ++b) {
  461. if ((j != k) || (alpha != beta) || (a != b - 1))
  462. log_BAE_reg += log(sin(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a ))
  463. - ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b ))
  464. - II * (*this).chain.anis));
  465. if ((j != k) || (alpha != beta) || (a != b + 1))
  466. log_BAE_reg -= log(sin(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a ))
  467. - ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b ))
  468. + II * (*this).chain.anis));
  469. }
  470. // The regular LHS of BAE is now defined. Now sum up the deltas...
  471. if (a == 1) ln_deltadiff[0] = -real(log_BAE_reg);
  472. else if (a < (*this).chain.Str_L[j]) ln_deltadiff[a - 1] = ln_deltadiff[a-2] - real(log_BAE_reg);
  473. else if (a == (*this).chain.Str_L[j]) ln_deltadiff[a-1] = real(log_BAE_reg);
  474. } // if ((*this).chain.Str_L[j] > 1)
  475. } // for (int a = 1; ...
  476. for (int a = 0; a < (*this).chain.Str_L[j]; ++a) {
  477. deltadiff[a] = ln_deltadiff[a] != 0.0 ? exp(ln_deltadiff[a]) : 0.0;
  478. delta += fabs(deltadiff[a]);
  479. }
  480. } // alpha sum
  481. } // j sum
  482. if (is_nan(delta)) delta = 1.0; // sentinel
  483. } // else
  484. return delta;
  485. }
  486. void XXZ_gpd_Bethe_State::Compute_Energy ()
  487. {
  488. DP sum = 0.0;
  489. for (int j = 0; j < chain.Nstrings; ++j) {
  490. for (int alpha = 0; alpha < base[j]; ++alpha) {
  491. sum += sinh(chain.Str_L[j] * chain.anis) / (cos(2.0 * lambda[j][alpha]) - cosh(chain.Str_L[j] * chain.anis));
  492. }
  493. }
  494. sum *= chain.J * sinh(chain.anis);
  495. E = sum;
  496. return;
  497. }
  498. /*
  499. void XXZ_gpd_Bethe_State::Compute_Momentum ()
  500. {
  501. int sum_Ix2 = 0;
  502. DP sum_M = 0.0;
  503. for (int j = 0; j < chain.Nstrings; ++j) {
  504. sum_M += base[j];
  505. for (int alpha = 0; alpha < base[j]; ++alpha) {
  506. sum_Ix2 += Ix2[j][alpha];
  507. }
  508. }
  509. iK = (chain.Nsites/2) * int(sum_M) - (sum_Ix2/2);
  510. while (iK >= chain.Nsites) iK -= chain.Nsites;
  511. while (iK < 0) iK += chain.Nsites;
  512. K = PI * sum_M - PI * sum_Ix2/chain.Nsites;
  513. while (K >= 2.0*PI) K -= 2.0*PI;
  514. while (K < 0.0) K += 2.0*PI;
  515. return;
  516. }
  517. */
  518. void XXZ_gpd_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
  519. {
  520. if (Gaudin_Red.size() != base.Nraptot) ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
  521. int index_jalpha;
  522. int index_kbeta;
  523. DP sum_hbar_XXZ = 0.0;
  524. DP sinhetasq = pow(sinh(chain.anis), 2.0);
  525. (*this).Compute_sinlambda();
  526. (*this).Compute_coslambda();
  527. index_jalpha = 0;
  528. for (int j = 0; j < chain.Nstrings; ++j) {
  529. for (int alpha = 0; alpha < base[j]; ++alpha) {
  530. index_kbeta = 0;
  531. for (int k = 0; k < chain.Nstrings; ++k) {
  532. for (int beta = 0; beta < base[k]; ++beta) {
  533. if ((j == k) && (alpha == beta)) {
  534. sum_hbar_XXZ = 0.0;
  535. for (int kp = 0; kp < chain.Nstrings; ++kp) {
  536. for (int betap = 0; betap < base[kp]; ++betap) {
  537. if (!((j == kp) && (alpha == betap)))
  538. sum_hbar_XXZ
  539. += ddlambda_Theta_XXZ_gpd (lambda[j][alpha] - lambda[kp][betap], chain.Str_L[j], chain.Str_L[kp],
  540. chain.si_n_anis_over_2);
  541. }
  542. }
  543. Gaudin_Red[index_jalpha][index_kbeta]
  544. = complex<DP> ( chain.Nsites * hbar_XXZ_gpd (lambda[j][alpha], chain.Str_L[j], chain.si_n_anis_over_2) - sum_hbar_XXZ);
  545. }
  546. else {
  547. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  548. Gaudin_Red[index_jalpha][index_kbeta] =
  549. complex<DP> (chain.si_n_anis_over_2[4]/(pow(sinlambda[j][alpha] * coslambda[k][beta]
  550. - coslambda[j][alpha] * sinlambda[k][beta], 2.0) + sinhetasq));
  551. else
  552. Gaudin_Red[index_jalpha][index_kbeta] = complex<DP> (ddlambda_Theta_XXZ_gpd (lambda[j][alpha] - lambda[k][beta], chain.Str_L[j],
  553. chain.Str_L[k], chain.si_n_anis_over_2));
  554. }
  555. index_kbeta++;
  556. }
  557. }
  558. index_jalpha++;
  559. }
  560. }
  561. return;
  562. }
  563. // ****************************************************************************************************
  564. // non-member functions
  565. inline DP fbar_XXZ_gpd (DP tanlambda, DP tanhnetaover2)
  566. {
  567. return (2.0 * atan(tanlambda/tanhnetaover2));
  568. }
  569. DP Theta_XXZ_gpd (DP tanlambda, int nj, int nk, DP* tanhnetaover2)
  570. {
  571. DP result;
  572. if ((nj == 1) && (nk == 1)) result = fbar_XXZ_gpd(tanlambda, tanhnetaover2[2]);
  573. else {
  574. result = (nj == nk) ? 0.0 : fbar_XXZ_gpd(tanlambda, tanhnetaover2[fabs(nj - nk)]);
  575. for (int a = 1; a < ABACUS::min(nj, nk); ++a) result += 2.0 * fbar_XXZ_gpd(tanlambda, tanhnetaover2[fabs(nj - nk) + 2*a]);
  576. result += fbar_XXZ_gpd(tanlambda, tanhnetaover2[nj + nk]);
  577. }
  578. return (result);
  579. }
  580. DP hbar_XXZ_gpd (DP lambda, int n, DP* si_n_anis_over_2)
  581. {
  582. return (si_n_anis_over_2[2*n]/(pow(sin(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0)));
  583. }
  584. DP ddlambda_Theta_XXZ_gpd (DP lambda, int nj, int nk, DP* si_n_anis_over_2)
  585. {
  586. DP result = (nj == nk) ? 0.0 : hbar_XXZ_gpd(lambda, fabs(nj - nk), si_n_anis_over_2);
  587. for (int a = 1; a < ABACUS::min(nj, nk); ++a) result += 2.0 * hbar_XXZ_gpd(lambda, fabs(nj - nk) + 2*a, si_n_anis_over_2);
  588. result += hbar_XXZ_gpd(lambda, nj + nk, si_n_anis_over_2);
  589. return (result);
  590. }
  591. XXZ_gpd_Bethe_State Add_Particle_at_Center (const XXZ_gpd_Bethe_State& RefState)
  592. {
  593. if (2*RefState.base.Mdown == RefState.chain.Nsites)
  594. ABACUSerror("Trying to add a down spin to a zero-magnetized chain in Add_Particle_at_Center.");
  595. Vect<int> newM = RefState.base.Nrap;
  596. newM[0] = newM[0] + 1;
  597. Heis_Base newBase (RefState.chain, newM);
  598. XXZ_gpd_Bethe_State ReturnState (RefState.chain, newBase);
  599. for (int il = 1; il < RefState.chain.Nstrings; ++il)
  600. for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
  601. ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
  602. // Add a quantum number in middle (explicitly: to right of index M[0]/2)
  603. // and shift quantum numbers by half-integer away from added one:
  604. ReturnState.Ix2[0][RefState.base.Nrap[0]/2] = RefState.Ix2[0][RefState.base.Nrap[0]/2] - 1;
  605. for (int i = 0; i < RefState.base.Nrap[0] + 1; ++i)
  606. ReturnState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] = RefState.Ix2[0][i] - 1 + 2*(i >= RefState.base.Nrap[0]/2);
  607. return(ReturnState);
  608. }
  609. XXZ_gpd_Bethe_State Remove_Particle_at_Center (const XXZ_gpd_Bethe_State& RefState)
  610. {
  611. if (RefState.base.Nrap[0] == 0)
  612. ABACUSerror("Trying to remove a down spin in an empty Nrap[0] state.");
  613. Vect<int> newM = RefState.base.Nrap;
  614. newM[0] = newM[0] - 1;
  615. Heis_Base newBase (RefState.chain, newM);
  616. XXZ_gpd_Bethe_State ReturnState (RefState.chain, newBase);
  617. for (int il = 1; il < RefState.chain.Nstrings; ++il)
  618. for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
  619. ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
  620. // Remove midmost and shift quantum numbers by half-integer towards removed one:
  621. for (int i = 0; i < RefState.base.Nrap[0]-1; ++i)
  622. ReturnState.Ix2[0][i] = RefState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] + 1 - 2*(i >= RefState.base.Nrap[0]/2);
  623. return(ReturnState);
  624. }
  625. } // namespace ABACUS