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.

XXX_Bethe_State.cc 18KB

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