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_Bethe_State.cc 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c)
  4. -----------------------------------------------------------
  5. File: src/HEIS/XXZ_Bethe_State.cc
  6. Purpose: Defines all functions for XXZ_Bethe_State
  7. ******************************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. namespace ABACUS {
  11. // Function prototypes
  12. inline DP fbar_XXZ (DP lambda, int par, DP tannzetaover2);
  13. DP Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* tannzetaover2);
  14. DP hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2);
  15. DP ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2);
  16. //***************************************************************************************************
  17. // Function definitions: class XXZ_Bethe_State
  18. XXZ_Bethe_State::XXZ_Bethe_State ()
  19. : Heis_Bethe_State(), sinhlambda(Lambda(chain, 1)), coshlambda(Lambda(chain, 1)), tanhlambda(Lambda(chain, 1))
  20. {};
  21. XXZ_Bethe_State::XXZ_Bethe_State (const XXZ_Bethe_State& RefState) // copy constructor
  22. : Heis_Bethe_State(RefState), sinhlambda(Lambda(RefState.chain, RefState.base)), coshlambda(Lambda(RefState.chain, RefState.base)),
  23. tanhlambda(Lambda(RefState.chain, RefState.base))
  24. {
  25. // copy arrays into new ones
  26. //cout << "Calling XXZ state copy constructor." << endl;
  27. for (int j = 0; j < RefState.chain.Nstrings; ++j) {
  28. for (int alpha = 0; alpha < RefState.base[j]; ++j) {
  29. sinhlambda[j][alpha] = RefState.sinhlambda[j][alpha];
  30. coshlambda[j][alpha] = RefState.coshlambda[j][alpha];
  31. tanhlambda[j][alpha] = RefState.tanhlambda[j][alpha];
  32. }
  33. }
  34. //cout << "Done calling XXZ state copy constructor." << endl;
  35. }
  36. XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, int M)
  37. : Heis_Bethe_State(RefChain, M),
  38. sinhlambda(Lambda(RefChain, M)), coshlambda(Lambda(RefChain, M)), tanhlambda(Lambda(RefChain, M))
  39. {
  40. //cout << "Here in XXZ BS constructor." << endl;
  41. //cout << (*this).lambda[0][0] << endl;
  42. //cout << "OK" << endl;
  43. if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in XXZ_Bethe_State constructor");
  44. }
  45. XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, const Heis_Base& RefBase)
  46. : Heis_Bethe_State(RefChain, RefBase),
  47. sinhlambda(Lambda(RefChain, RefBase)), coshlambda(Lambda(RefChain, RefBase)), tanhlambda(Lambda(RefChain, RefBase))
  48. {
  49. if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in XXZ_Bethe_State constructor");
  50. }
  51. /*
  52. XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, long long int base_id_ref, long long int type_id_ref)
  53. : Heis_Bethe_State(RefChain, base_id_ref, type_id_ref),
  54. sinhlambda(Lambda(chain, base)), coshlambda(Lambda(chain, base)), tanhlambda(Lambda(chain, base))
  55. {
  56. if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in XXZ_Bethe_State constructor");
  57. }
  58. */
  59. XXZ_Bethe_State& XXZ_Bethe_State::operator= (const XXZ_Bethe_State& RefState)
  60. {
  61. if (this != &RefState) {
  62. chain = RefState.chain;
  63. base = RefState.base;
  64. //offsets = RefState.offsets;
  65. Ix2 = RefState.Ix2;
  66. lambda = RefState.lambda;
  67. BE = RefState.BE;
  68. diffsq = RefState.diffsq;
  69. conv = RefState.conv;
  70. iter = RefState.iter;
  71. iter_Newton = RefState.iter_Newton;
  72. E = RefState.E;
  73. iK = RefState.iK;
  74. K = RefState.K;
  75. lnnorm = RefState.lnnorm;
  76. //base_id = RefState.base_id;
  77. //type_id = RefState.type_id;
  78. //id = RefState.id;
  79. //maxid = RefState.maxid;
  80. //nparticles = RefState.nparticles;
  81. label = RefState.label;
  82. sinhlambda = RefState.sinhlambda;
  83. coshlambda = RefState.coshlambda;
  84. tanhlambda = RefState.tanhlambda;
  85. }
  86. return(*this);
  87. }
  88. // Member functions
  89. void XXZ_Bethe_State::Set_Free_lambdas()
  90. {
  91. // Sets all the rapidities to the solutions of the BAEs without scattering terms
  92. DP x = 0.0;
  93. for (int i = 0; i < chain.Nstrings; ++i) {
  94. for (int alpha = 0; alpha < base[i]; ++alpha) {
  95. if (chain.par[i] == 1) {
  96. //lambda[i][alpha] = atanh(tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites));
  97. x = tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites);
  98. lambda[i][alpha] = atanh(x/sqrt(1.0 + x*x)); // lambda then always initiated real
  99. }
  100. else if (chain.par[i] == -1) {
  101. //lambda[i][alpha] = atanh(-tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis));
  102. x = -tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis);
  103. lambda[i][alpha] = atanh(x/sqrt(1.0 + x*x)); // lambda then always initiated real
  104. }
  105. else ABACUSerror("Invalid parities in Set_Free_lambdas.");
  106. //cout << tan(chain.Str_L[i] * 0.5 * chain.anis) << endl;
  107. //cout << "Set_Free_lambdas: " << i << "\t" << alpha << "\t" << lambda[i][alpha] << "\t" << tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites) << endl;
  108. }
  109. }
  110. return;
  111. }
  112. void XXZ_Bethe_State::Compute_sinhlambda()
  113. {
  114. for (int j = 0; j < chain.Nstrings; ++j) {
  115. for (int alpha = 0; alpha < base[j]; ++alpha) sinhlambda[j][alpha] = sinh(lambda[j][alpha]);
  116. }
  117. return;
  118. }
  119. void XXZ_Bethe_State::Compute_coshlambda()
  120. {
  121. for (int j = 0; j < chain.Nstrings; ++j) {
  122. for (int alpha = 0; alpha < base[j]; ++alpha) coshlambda[j][alpha] = cosh(lambda[j][alpha]);
  123. }
  124. return;
  125. }
  126. void XXZ_Bethe_State::Compute_tanhlambda()
  127. {
  128. for (int j = 0; j < chain.Nstrings; ++j) {
  129. for (int alpha = 0; alpha < base[j]; ++alpha) tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
  130. }
  131. return;
  132. }
  133. bool XXZ_Bethe_State::Check_Admissibility(char option)
  134. {
  135. // This function checks the admissibility of the Ix2's of a state:
  136. // returns false if there are higher strings with Ix2 = 0, a totally symmetric distribution of I's at each level,
  137. // and strings of equal length modulo 2 and parity with Ix2 = 0, meaning at least two equal roots in BAE.
  138. bool answer = true;
  139. Vect<bool> Zero_at_level(false, chain.Nstrings); // whether there exists an Ix2 == 0 at a given level
  140. bool higher_string_on_zero = false;
  141. for (int j = 0; j < chain.Nstrings; ++j) {
  142. // The following line puts answer to true if there is at least one higher string with zero Ix2
  143. for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] >= 2) /*&& !(chain.Str_L[j] % 2)*/)
  144. higher_string_on_zero = true;
  145. for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
  146. // NOTE: if base[j] == 0, Zero_at_level[j] remains false.
  147. }
  148. // check symmetry of Ix2 at each level, if there exists a potentially risky Ix2...
  149. bool symmetric_state = (*this).Check_Symmetry();
  150. bool string_coincidence = false;
  151. for (int j1 = 0; j1 < chain.Nstrings; ++j1) {
  152. for (int j2 = j1 + 1; j2 < chain.Nstrings; ++j2)
  153. if (Zero_at_level[j1] && Zero_at_level[j2] && (chain.par[j1] == chain.par[j2]) && (!((chain.Str_L[j1] + chain.Str_L[j2])%2)))
  154. string_coincidence = true;
  155. }
  156. bool M_odd_and_onep_on_zero = false;
  157. if (option == 'z') { // for Sz, if M is odd, exclude symmetric states with a 1+ on zero
  158. // (zero rapidities in left and right states, so FF det not defined).
  159. bool is_ground_state = base.Nrap[0] == base.Mdown && Ix2[0][0] == -(base.Mdown - 1) && Ix2[0][base.Mdown-1] == base.Mdown - 1;
  160. if (Zero_at_level[0] && (base.Mdown % 2) && !is_ground_state) M_odd_and_onep_on_zero = true;
  161. }
  162. bool onep_onem_on_zero = false;
  163. if (option == 'm' || option == 'p') { // for Smin, we also exclude symmetric states with 1+ and 1- strings on zero
  164. if (Zero_at_level[0] && Zero_at_level[1]) onep_onem_on_zero = true;
  165. }
  166. answer = !(symmetric_state && (higher_string_on_zero || string_coincidence || onep_onem_on_zero || M_odd_and_onep_on_zero));
  167. // Now check that no Ix2 is equal to +N (since we take -N into account, and I + N == I by periodicity of exp)
  168. for (int j = 0; j < chain.Nstrings; ++j)
  169. for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] < -chain.Nsites) || (Ix2[j][alpha] >= chain.Nsites)) answer = false;
  170. if (!answer) {
  171. E = 0.0;
  172. K = 0.0;
  173. conv = 0;
  174. iter = 0;
  175. iter_Newton = 0;
  176. lnnorm = -100.0;
  177. }
  178. return(answer); // answer == true: nothing wrong with this Ix2_config
  179. }
  180. void XXZ_Bethe_State::Compute_BE (int j, int alpha)
  181. {
  182. tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
  183. DP sumtheta = 0.0;
  184. for (int k = 0; k < chain.Nstrings; ++k)
  185. for (int beta = 0; beta < base[k]; ++beta) {
  186. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  187. sumtheta += (chain.par[j] == chain.par[k])
  188. ? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
  189. : - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
  190. else sumtheta += 0.5 * Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
  191. chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
  192. }
  193. sumtheta *= 2.0;
  194. BE[j][alpha] = ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  195. : -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]])) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
  196. }
  197. void XXZ_Bethe_State::Compute_BE ()
  198. {
  199. // Fills in the BE members with the value of the Bethe equations.
  200. (*this).Compute_tanhlambda();
  201. DP sumtheta = 0.0;
  202. for (int j = 0; j < chain.Nstrings; ++j)
  203. for (int alpha = 0; alpha < base[j]; ++alpha) {
  204. sumtheta = 0.0;
  205. for (int k = 0; k < chain.Nstrings; ++k)
  206. for (int beta = 0; beta < base[k]; ++beta) {
  207. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  208. sumtheta += (chain.par[j] == chain.par[k])
  209. ? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
  210. : - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
  211. else sumtheta += 0.5 * Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
  212. chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
  213. }
  214. sumtheta *= 2.0;
  215. BE[j][alpha] = ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  216. : -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]])) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
  217. //if (is_nan(BE[j][alpha])) cout << "BE nan: " << j << "\t" << alpha << "\t" << lambda[j][alpha] << "\t" << tanhlambda[j][alpha] << endl;
  218. }
  219. }
  220. DP XXZ_Bethe_State::Iterate_BAE (int j, int alpha)
  221. {
  222. // Returns a new iteration value for lambda[j][alpha] given tanhlambda and BE Lambdas
  223. // Assumes that tanhlambda[][] and BE[][] have been computed.
  224. DP new_lambda = 0.0;
  225. DP arg = 0.0;
  226. if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]]
  227. * tan(0.5 *
  228. //(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
  229. (2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha])
  230. );
  231. else if (chain.par[j] == -1) arg = -tan(0.5 *
  232. //(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites)
  233. (-2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha]))
  234. /chain.ta_n_anis_over_2[chain.Str_L[j]];
  235. if (fabs(arg) < 1.0) {
  236. new_lambda = atanh(arg);
  237. }
  238. else {
  239. new_lambda = lambda[j][alpha]; // back to drawing board...
  240. int block = 0; // counter to prevent runaway while loop
  241. DP new_tanhlambda = 0.0;
  242. DP sumtheta = 0.0;
  243. arg = 10.0; // reset value to start while loop
  244. while ((fabs(arg) > 1.0) && (block++ < 100)) { // recompute the diverging root on its own...
  245. new_lambda *= 1.01; // try to go slowly towards infinity...
  246. new_tanhlambda = tanh(new_lambda);
  247. sumtheta = 0.0;
  248. for (int k = 0; k < chain.Nstrings; ++k) {
  249. for (int beta = 0; beta < base[k]; ++beta)
  250. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  251. sumtheta += (chain.par[j] == chain.par[k])
  252. ? atan((new_tanhlambda - tanhlambda[k][beta])/((1.0 - new_tanhlambda * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
  253. : - atan(((new_tanhlambda - tanhlambda[k][beta])/(1.0 - new_tanhlambda * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
  254. else sumtheta += 0.5 * Theta_XXZ((new_tanhlambda - tanhlambda[k][beta])/(1.0 - new_tanhlambda * tanhlambda[k][beta]),
  255. chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
  256. }
  257. sumtheta *= 2.0;
  258. if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites);
  259. else if (chain.par[j] == -1) arg = -tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites)/chain.ta_n_anis_over_2[chain.Str_L[j]];
  260. else ABACUSerror("Invalid parities in Iterate_BAE.");
  261. }
  262. if (fabs(arg) < 1.0) {
  263. new_lambda = atanh(arg);
  264. }
  265. //else cout << "Rapidity blows up !\t" << lambda[j][alpha] << "\t" << new_lambda << endl;
  266. } // else
  267. return(new_lambda);
  268. }
  269. bool XXZ_Bethe_State::Check_Rapidities()
  270. {
  271. bool nonan = true;
  272. for (int j = 0; j < chain.Nstrings; ++j)
  273. for (int alpha = 0; alpha < base[j]; ++alpha) nonan *= !is_nan(lambda[j][alpha]);
  274. return nonan;
  275. }
  276. DP XXZ_Bethe_State::String_delta ()
  277. {
  278. // Computes the sum of absolute value of \delta^{a, a+1} in string hypothesis, for a given bethe eigenstate
  279. DP delta = 0.0;
  280. int occupied_strings = 0;
  281. for (int i = 0; i < (*this).chain.Nstrings; ++i) if ((*this).chain.Str_L[i] > 1) occupied_strings += (*this).base.Nrap[i];
  282. //if ((*this).conv == 0) delta = 1.0;
  283. if (occupied_strings == 0) delta = 0.0;
  284. else {
  285. Vect_DP ln_deltadiff(0.0, 1000); // contains ln |delta^{a, a+1}|
  286. Vect_DP deltadiff(0.0, 1000); // contains |delta^{a, a+1}|
  287. complex<DP> log_BAE_reg = 0.0;
  288. for (int j = 0; j < (*this).chain.Nstrings; ++j) {
  289. for (int alpha = 0; alpha < (*this).base[j]; ++alpha) {
  290. ln_deltadiff = 0.0;
  291. for (int a = 1; a <= (*this).chain.Str_L[j]; ++a) {
  292. if ((*this).chain.Str_L[j] > 1) { // else the BAE are already 1
  293. log_BAE_reg = DP((*this).chain.Nsites) * log(sinh((*this).lambda[j][alpha]
  294. + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a + 1.0)
  295. + 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
  296. /sinh((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a - 1.0)
  297. + 0.25 * II * PI * (1.0 - (*this).chain.par[j])));
  298. for (int k = 0; k < (*this).chain.Nstrings; ++k)
  299. for (int beta = 0; beta < (*this).base[k]; ++beta)
  300. for (int b = 1; b <= (*this).chain.Str_L[k]; ++b) {
  301. if ((j != k) || (alpha != beta) || (a != b - 1))
  302. log_BAE_reg += log(sinh(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
  303. + 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
  304. - ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
  305. + 0.25 * II * PI * (1.0 - (*this).chain.par[k])) - II * (*this).chain.anis));
  306. if ((j != k) || (alpha != beta) || (a != b + 1))
  307. log_BAE_reg -= log(sinh(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
  308. + 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
  309. - ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
  310. + 0.25 * II * PI * (1.0 - (*this).chain.par[k])) + II * (*this).chain.anis));
  311. }
  312. // The regular LHS of BAE is now defined. Now sum up the deltas...
  313. if (a == 1) ln_deltadiff[0] = - real(log_BAE_reg);
  314. else if (a < (*this).chain.Str_L[j]) ln_deltadiff[a - 1] = ln_deltadiff[a-2] - real(log_BAE_reg);
  315. else if (a == (*this).chain.Str_L[j]) ln_deltadiff[a-1] = real(log_BAE_reg);
  316. } // if ((*this).chain.Str_L[j] > 1)
  317. } // for (int a = 1; ...
  318. for (int a = 0; a < (*this).chain.Str_L[j]; ++a) {
  319. deltadiff[a] = ln_deltadiff[a] != 0.0 ? exp(ln_deltadiff[a]) : 0.0;
  320. delta += fabs(deltadiff[a]);
  321. }
  322. } // alpha sum
  323. } // j sum
  324. if (is_nan(delta)) delta = 1.0; // sentinel
  325. } // else
  326. return delta;
  327. }
  328. void XXZ_Bethe_State::Compute_Energy ()
  329. {
  330. DP sum = 0.0;
  331. for (int j = 0; j < chain.Nstrings; ++j) {
  332. for (int alpha = 0; alpha < base[j]; ++alpha) {
  333. sum += sin(chain.Str_L[j] * chain.anis) / (chain.par[j] * cosh(2.0 * lambda[j][alpha]) - cos(chain.Str_L[j] * chain.anis));
  334. }
  335. }
  336. sum *= - chain.J * sin(chain.anis);
  337. E = sum;
  338. return;
  339. }
  340. /*
  341. void XXZ_Bethe_State::Compute_Momentum ()
  342. {
  343. int sum_Ix2 = 0;
  344. DP sum_M = 0.0;
  345. for (int j = 0; j < chain.Nstrings; ++j) {
  346. sum_M += 0.5 * (1.0 + chain.par[j]) * base[j];
  347. for (int alpha = 0; alpha < base[j]; ++alpha) {
  348. sum_Ix2 += Ix2[j][alpha];
  349. }
  350. }
  351. iK = (chain.Nsites/2) * int(sum_M + 0.1) - (sum_Ix2/2); // + 0.1: for safety...
  352. while (iK >= chain.Nsites) iK -= chain.Nsites;
  353. while (iK < 0) iK += chain.Nsites;
  354. K = PI * sum_M - PI * sum_Ix2/chain.Nsites;
  355. while (K >= 2.0*PI) K -= 2.0*PI;
  356. while (K < 0.0) K += 2.0*PI;
  357. return;
  358. }
  359. */
  360. void XXZ_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
  361. {
  362. if (Gaudin_Red.size() != base.Nraptot) ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
  363. int index_jalpha;
  364. int index_kbeta;
  365. DP sum_hbar_XXZ = 0.0;
  366. DP sinzetasq = pow(sin(chain.anis), 2.0);
  367. (*this).Compute_sinhlambda();
  368. (*this).Compute_coshlambda();
  369. index_jalpha = 0;
  370. for (int j = 0; j < chain.Nstrings; ++j) {
  371. for (int alpha = 0; alpha < base[j]; ++alpha) {
  372. index_kbeta = 0;
  373. for (int k = 0; k < chain.Nstrings; ++k) {
  374. for (int beta = 0; beta < base[k]; ++beta) {
  375. if ((j == k) && (alpha == beta)) {
  376. sum_hbar_XXZ = 0.0;
  377. for (int kp = 0; kp < chain.Nstrings; ++kp) {
  378. for (int betap = 0; betap < base[kp]; ++betap) {
  379. if (!((j == kp) && (alpha == betap)))
  380. sum_hbar_XXZ
  381. += ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[kp][betap], chain.Str_L[j], chain.Str_L[kp], chain.par[j], chain.par[kp],
  382. chain.si_n_anis_over_2);
  383. }
  384. }
  385. Gaudin_Red[index_jalpha][index_kbeta]
  386. = complex<DP> ( chain.Nsites * hbar_XXZ (lambda[j][alpha], chain.Str_L[j], chain.par[j], chain.si_n_anis_over_2) - sum_hbar_XXZ);
  387. }
  388. else {
  389. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  390. Gaudin_Red[index_jalpha][index_kbeta] =
  391. complex<DP> ((chain.par[j] * chain.par[k] == 1)
  392. ? chain.si_n_anis_over_2[4]/(pow(sinhlambda[j][alpha] * coshlambda[k][beta]
  393. - coshlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq)
  394. : chain.si_n_anis_over_2[4]/(-pow(coshlambda[j][alpha] * coshlambda[k][beta]
  395. - sinhlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq) );
  396. else
  397. Gaudin_Red[index_jalpha][index_kbeta] = complex<DP> (ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[k][beta], chain.Str_L[j], chain.Str_L[k],
  398. chain.par[j], chain.par[k], chain.si_n_anis_over_2));
  399. }
  400. index_kbeta++;
  401. }
  402. }
  403. index_jalpha++;
  404. }
  405. }
  406. return;
  407. }
  408. // ****************************************************************************************************
  409. // non-member functions
  410. inline DP fbar_XXZ (DP tanhlambda, int par, DP tannzetaover2)
  411. {
  412. DP result = 0.0;
  413. if (par == 1) result = 2.0 * atan(tanhlambda/tannzetaover2);
  414. else if (par == -1) result = -2.0 * atan(tanhlambda * tannzetaover2);
  415. else ABACUSerror("Faulty parity in fbar_XXZ.");
  416. return (result);
  417. }
  418. DP Theta_XXZ (DP tanhlambda, int nj, int nk, int parj, int park, DP* tannzetaover2)
  419. {
  420. DP result = 0.0;
  421. if ((nj == 1) && (nk == 1)) result = fbar_XXZ(tanhlambda, parj*park, tannzetaover2[2]);
  422. else {
  423. result = (nj == nk) ? 0.0 : fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk)]);
  424. for (int a = 1; a < ABACUS::min(nj, nk); ++a) result += 2.0 * fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk) + 2*a]);
  425. result += fbar_XXZ(tanhlambda, parj*park, tannzetaover2[nj + nk]);
  426. }
  427. return (result);
  428. }
  429. DP hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2)
  430. {
  431. DP result = 0.0;
  432. if (par == 1) result = si_n_anis_over_2[2*n]/(pow(sinh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
  433. else if (par == -1) result = si_n_anis_over_2[2*n]/(-pow(cosh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
  434. else ABACUSerror("Faulty parity in hbar_XXZ.");
  435. return (result);
  436. }
  437. DP ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2)
  438. {
  439. DP result = (nj == nk) ? 0.0 : hbar_XXZ(lambda, fabs(nj - nk), parj*park, si_n_anis_over_2);
  440. for (int a = 1; a < ABACUS::min(nj, nk); ++a) result += 2.0 * hbar_XXZ(lambda, fabs(nj - nk) + 2*a, parj*park, si_n_anis_over_2);
  441. result += hbar_XXZ(lambda, nj + nk, parj*park, si_n_anis_over_2);
  442. return (result);
  443. }
  444. XXZ_Bethe_State Add_Particle_at_Center (const XXZ_Bethe_State& RefState)
  445. {
  446. if (2*RefState.base.Mdown == RefState.chain.Nsites)
  447. ABACUSerror("Trying to add a down spin to a zero-magnetized chain in Add_Particle_at_Center.");
  448. Vect<int> newM = RefState.base.Nrap;
  449. newM[0] = newM[0] + 1;
  450. Heis_Base newBase (RefState.chain, newM);
  451. XXZ_Bethe_State ReturnState (RefState.chain, newBase);
  452. for (int il = 1; il < RefState.chain.Nstrings; ++il)
  453. for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
  454. ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
  455. // Add a quantum number in middle (explicitly: to right of index M[0]/2)
  456. // and shift quantum numbers by half-integer away from added one:
  457. ReturnState.Ix2[0][RefState.base.Nrap[0]/2] = RefState.Ix2[0][RefState.base.Nrap[0]/2] - 1;
  458. for (int i = 0; i < RefState.base.Nrap[0] + 1; ++i)
  459. ReturnState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] = RefState.Ix2[0][i] - 1 + 2*(i >= RefState.base.Nrap[0]/2);
  460. return(ReturnState);
  461. }
  462. XXZ_Bethe_State Remove_Particle_at_Center (const XXZ_Bethe_State& RefState)
  463. {
  464. if (RefState.base.Nrap[0] == 0)
  465. ABACUSerror("Trying to remove a down spin in an empty Nrap[0] state.");
  466. Vect<int> newM = RefState.base.Nrap;
  467. newM[0] = newM[0] - 1;
  468. Heis_Base newBase (RefState.chain, newM);
  469. XXZ_Bethe_State ReturnState (RefState.chain, newBase);
  470. for (int il = 1; il < RefState.chain.Nstrings; ++il)
  471. for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
  472. ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
  473. // Remove midmost and shift quantum numbers by half-integer towards removed one:
  474. for (int i = 0; i < RefState.base.Nrap[0]-1; ++i)
  475. ReturnState.Ix2[0][i] = RefState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] + 1 - 2*(i >= RefState.base.Nrap[0]/2);
  476. return(ReturnState);
  477. }
  478. } // namespace ABACUS