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.

Heis.cc 58KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: src/HEIS/Heis.cc
  6. Purpose: defines functions in all HEIS classes.
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. namespace ABACUS {
  11. //***************************************************************************************************
  12. // Function definitions: class Heis_Chain
  13. Heis_Chain::Heis_Chain()
  14. : J(0.0), Delta(0.0), anis(0.0), hz(0.0), Nsites(0), Nstrings(0), Str_L(0), par(0),
  15. si_n_anis_over_2(new DP[1]), co_n_anis_over_2(new DP[1]), ta_n_anis_over_2(new DP[1]), prec(ITER_REQ_PREC) {}
  16. Heis_Chain::Heis_Chain (DP JJ, DP DD, DP hh, int NN)
  17. : J(JJ), Delta(DD), anis(0.0), hz(hh), Nsites(NN), Nstrings(MAXSTRINGS), Str_L(new int[MAXSTRINGS]), par(new int[MAXSTRINGS]),
  18. si_n_anis_over_2(new DP[10*MAXSTRINGS]), co_n_anis_over_2(new DP[10*MAXSTRINGS]), ta_n_anis_over_2(new DP[10*MAXSTRINGS]), prec(ITER_REQ_PREC)
  19. {
  20. // We restrict to even chains everywhere
  21. if (NN % 2) ABACUSerror("Please use an even-length chain.");
  22. if ((Delta > 0.0) && (Delta < 1.0)) {
  23. // gapless XXZ case
  24. anis = acos(DD);
  25. // Set the Str_L and par vectors:
  26. DP gammaoverpi = acos(DD)/PI;
  27. //cout << "gammaoverpi = " << gammaoverpi << endl;
  28. Vect<int> Nu(MAXSTRINGS);
  29. DP gammaoverpi_eff = gammaoverpi;
  30. DP gammaoverpi_reached = 0.0;
  31. // First, define the series Nu[i], like in TakahashiBOOK eqn 9.35
  32. // CAREFUL: the labelling is different, Nu[0] is \nu_1, etc.
  33. int l = 0;
  34. int ml_temp = 0; // checks the sum of all Nu's
  35. while (fabs(gammaoverpi - gammaoverpi_reached) > 1.0e-8){
  36. Nu[l] = int(1.0/gammaoverpi_eff);
  37. ml_temp += Nu[l];
  38. if (Nu[l] == 0) gammaoverpi_eff = 0.0;
  39. else gammaoverpi_eff = 1.0/gammaoverpi_eff - DP(Nu[l]);
  40. // compute gammaoverpi_reached:
  41. gammaoverpi_reached = Nu[l];
  42. for (int p = 0; p < l; ++p) gammaoverpi_reached = Nu[l - p - 1] + 1.0/gammaoverpi_reached;
  43. gammaoverpi_reached = 1.0/gammaoverpi_reached;
  44. //cout << "gammaoverpi_reached = " << gammaoverpi_reached << "\tdiff = " << fabs(gammaoverpi - gammaoverpi_reached) << endl;
  45. //cout << "ml_temp = " << ml_temp << "\tMAXSTRINGS = " << MAXSTRINGS << endl;
  46. l++;
  47. if (ml_temp > MAXSTRINGS) break; // we defined Str_L and par as arrays of at most MAXSTRINGS elements, so we cut off here...
  48. }
  49. //cout << "l = " << l << endl;
  50. // Check: make sure the last Nu is greater than one: if one, add 1 to previous Nu
  51. if (l > 1) {
  52. if (Nu[l-1] == 1) {
  53. Nu[l-1] = 0;
  54. Nu[l-2] += 1;
  55. l -= 1;
  56. }
  57. }
  58. // Length of continued fraction is l-1, which is denoted l in Takahashi
  59. // Second, define the series y[i] and m[i] as in TakahashiBOOK eqn 9.36
  60. // y_{-1} is treated separately, and here y[i] = y_i, m[i] = m_i, i = 0, ..., l
  61. Vect<int> y(0, l+1);
  62. Vect<int> m(0, l+1);
  63. y[0] = 1;
  64. m[0] = 0;
  65. y[1] = Nu[0];
  66. m[1] = Nu[0];
  67. for (int i = 2; i <= l; ++i) {
  68. y[i] = y[i - 2] + Nu[i-1]*y[i-1];
  69. m[i] = 0;
  70. for (int k = 0; k < i; ++k) m[i] += Nu[k];
  71. }
  72. // Now determine the lengths and parity, following TakahashiBOOK eqn 9.37
  73. // Nstrings = ABACUS::min(m[l] + 1, MAXSTRINGS); // number of different strings that are possible for this chain
  74. // Always set to MAXSTRINGS
  75. Str_L[0] = 1;
  76. par[0] = 1;
  77. Str_L[1] = 1;
  78. par[1] = -1;
  79. int max_j = 0;
  80. for (int i = 0; i < l; ++i) {
  81. for (int j = ABACUS::max(1, m[i]) + 1; j < ABACUS::min(m[i+1] + 1, MAXSTRINGS); ++j) {
  82. if (i == 0) Str_L[j] = (j - m[0])* y[0];
  83. else if (i >= 1) Str_L[j] = y[i-1] + (j - m[i])*y[i];
  84. par[j] = (int(floor((Str_L[j] - 1)*gammaoverpi)) % 2) ? -1 : 1;
  85. max_j = j;
  86. }
  87. }
  88. // Set the rest of Str_L and par vector elements to zero
  89. for (int i = max_j + 1; i < MAXSTRINGS; ++i) {
  90. Str_L[i] = 0;
  91. par[i] = 0;
  92. }
  93. // Set the sin, cos and tan_n_zeta_over_2 vectors:
  94. for (int i = 0; i < 10*MAXSTRINGS; ++i) si_n_anis_over_2[i] = sin(i * anis/2.0);
  95. for (int i = 0; i < 10*MAXSTRINGS; ++i) co_n_anis_over_2[i] = cos(i * anis/2.0);
  96. for (int i = 0; i < 10*MAXSTRINGS; ++i) ta_n_anis_over_2[i] = tan(i * anis/2.0);
  97. } // if XXZ gapless
  98. else if (Delta == 1.0) {
  99. // Isotropic antiferromagnet
  100. anis = 0.0;
  101. // Set Str_L and par:
  102. for (int i = 0; i < MAXSTRINGS; ++i) {
  103. Str_L[i] = i + 1;
  104. par[i] = 1;
  105. }
  106. } // if XXX AFM
  107. else if (Delta > 1.0) {
  108. // Gapped antiferromagnet
  109. anis = acosh(DD);
  110. // Set the Str_L and par vectors:
  111. for (int i = 0; i < MAXSTRINGS; ++i) {
  112. Str_L[i] = i + 1;
  113. par[i] = 1;
  114. }
  115. // Set the sinh, cosh and tanh_n_eta_over_2 vectors:
  116. for (int i = 0; i < 10*MAXSTRINGS; ++i) si_n_anis_over_2[i] = sinh(i * anis/2.0);
  117. for (int i = 0; i < 10*MAXSTRINGS; ++i) co_n_anis_over_2[i] = cosh(i * anis/2.0);
  118. for (int i = 0; i < 10*MAXSTRINGS; ++i) ta_n_anis_over_2[i] = tanh(i * anis/2.0);
  119. } // if XXZ_gpd
  120. }
  121. Heis_Chain::Heis_Chain (const Heis_Chain& RefChain) // copy constructor
  122. {
  123. J = RefChain.J;
  124. Delta = RefChain.Delta;
  125. anis = RefChain.anis;
  126. hz = RefChain.hz;
  127. Nsites = RefChain.Nsites;
  128. Nstrings = RefChain.Nstrings;
  129. Str_L = new int[RefChain.Nstrings];
  130. for (int i = 0; i < RefChain.Nstrings; ++i) Str_L[i] = RefChain.Str_L[i];
  131. par = new int[RefChain.Nstrings];
  132. for (int i = 0; i < RefChain.Nstrings; ++i) par[i] = RefChain.par[i];
  133. si_n_anis_over_2 = new DP[10*MAXSTRINGS];
  134. for (int i = 0; i < 10*MAXSTRINGS; ++i) si_n_anis_over_2[i] = RefChain.si_n_anis_over_2[i];
  135. co_n_anis_over_2 = new DP[10*MAXSTRINGS];
  136. for (int i = 0; i < 10*MAXSTRINGS; ++i) co_n_anis_over_2[i] = RefChain.co_n_anis_over_2[i];
  137. ta_n_anis_over_2 = new DP[10*MAXSTRINGS];
  138. for (int i = 0; i < 10*MAXSTRINGS; ++i) ta_n_anis_over_2[i] = RefChain.ta_n_anis_over_2[i];
  139. prec = RefChain.prec;
  140. }
  141. Heis_Chain& Heis_Chain::operator= (const Heis_Chain& RefChain) // assignment operator
  142. {
  143. if (this != &RefChain) {
  144. J = RefChain.J;
  145. Delta = RefChain.Delta;
  146. anis = RefChain.anis;
  147. hz = RefChain.hz;
  148. Nsites = RefChain.Nsites;
  149. Nstrings = RefChain.Nstrings;
  150. if (Str_L != 0) delete[] Str_L;
  151. Str_L = new int[RefChain.Nstrings];
  152. for (int i = 0; i < RefChain.Nstrings; ++i) Str_L[i] = RefChain.Str_L[i];
  153. if (par != 0) delete[] par;
  154. par = new int[RefChain.Nstrings];
  155. for (int i = 0; i < RefChain.Nstrings; ++i) par[i] = RefChain.par[i];
  156. if (si_n_anis_over_2 != 0) delete[] si_n_anis_over_2;
  157. si_n_anis_over_2 = new DP[10*MAXSTRINGS];
  158. for (int i = 0; i < 10*MAXSTRINGS; ++i) si_n_anis_over_2[i] = RefChain.si_n_anis_over_2[i];
  159. if (co_n_anis_over_2 != 0) delete[] co_n_anis_over_2;
  160. co_n_anis_over_2 = new DP[10*MAXSTRINGS];
  161. for (int i = 0; i < 10*MAXSTRINGS; ++i) co_n_anis_over_2[i] = RefChain.co_n_anis_over_2[i];
  162. if (ta_n_anis_over_2 != 0) delete[] ta_n_anis_over_2;
  163. ta_n_anis_over_2 = new DP[10*MAXSTRINGS];
  164. for (int i = 0; i < 10*MAXSTRINGS; ++i) ta_n_anis_over_2[i] = RefChain.ta_n_anis_over_2[i];
  165. prec = RefChain.prec;
  166. }
  167. return *this;
  168. }
  169. bool Heis_Chain::operator== (const Heis_Chain& RefChain)
  170. {
  171. bool answer = true;
  172. if ((J != RefChain.J) || (Nsites != RefChain.Nsites) || (Delta != RefChain.Delta)) answer = false;
  173. return(answer);
  174. }
  175. bool Heis_Chain::operator!= (const Heis_Chain& RefChain)
  176. {
  177. bool answer = false;
  178. if ((J != RefChain.J) || (Nsites != RefChain.Nsites) || (Delta != RefChain.Delta)) answer = true;
  179. return(answer);
  180. }
  181. Heis_Chain::~Heis_Chain()
  182. {
  183. if (Str_L != 0) delete[] Str_L;
  184. if (par != 0) delete[] par;
  185. if (si_n_anis_over_2 != 0) delete[] si_n_anis_over_2;
  186. if (co_n_anis_over_2 != 0) delete[] co_n_anis_over_2;
  187. if (ta_n_anis_over_2 != 0) delete[] ta_n_anis_over_2;
  188. }
  189. /* Deactivated in ++G_8
  190. void Heis_Chain::Scan_for_Possible_Bases (int Mdown_remaining, Vect<string>& possible_base_label, int& nfound, int nexc_max_used,
  191. int base_level_to_scan, Vect<int>& Nrapidities)
  192. {
  193. if (Mdown_remaining < 0) { ABACUSerror("Scan_for_Possible_Bases: shouldn't be here..."); } // reached inconsistent point
  194. //cout << "Mdown_remaining " << Mdown_remaining << "\t" << possible_base_id << "\tnfound " << nfound
  195. // << "\tnexc_max_used " << nexc_max_used << "\tbase_level_to_scan " << base_level_to_scan << "\tNrap " << Nrapidities << endl;
  196. if (base_level_to_scan == 0) {
  197. Nrapidities[0] = Mdown_remaining;
  198. // Set label:
  199. stringstream M0out;
  200. M0out << Nrapidities[0];
  201. possible_base_label[nfound] = M0out.str();
  202. for (int itype = 1; itype < Nrapidities.size(); ++itype)
  203. if (Nrapidities[itype] > 0) {
  204. possible_base_label[nfound] += TYPESEP;
  205. stringstream typeout;
  206. typeout << itype;
  207. possible_base_label[nfound] += typeout.str();
  208. possible_base_label[nfound] += EXCSEP;
  209. stringstream Mout;
  210. Mout << Nrapidities[itype];
  211. possible_base_label[nfound] += Mout.str();
  212. }
  213. nfound++;
  214. }
  215. else {
  216. // Remove all higher strings:
  217. //Nrapidities[base_level_to_scan] = 0;
  218. //Scan_for_Possible_Bases (Mdown_remaining, possible_base_id, nfound, nexc_max_used, base_level_to_scan - 1, Nrapidities);
  219. for (int i = 0; i <= (Str_L[base_level_to_scan] == 0 ? 0 : nexc_max_used/Str_L[base_level_to_scan]); ++i) {
  220. Nrapidities[base_level_to_scan] = i;
  221. Scan_for_Possible_Bases (Mdown_remaining - i*Str_L[base_level_to_scan], possible_base_label, nfound,
  222. nexc_max_used - i*Str_L[base_level_to_scan], base_level_to_scan - 1, Nrapidities);
  223. }
  224. }
  225. }
  226. Vect<string> Heis_Chain::Possible_Bases (int Mdown) // returns a vector of possible bases
  227. {
  228. // We partition Mdown into up to NEXC_MAX_HEIS excitations
  229. int nexc_max_used = ABACUS::min(NEXC_MAX_HEIS, 2*(Mdown/2)); // since each inner sector can contain at most N/2 holes.
  230. Vect<string> possible_base_label (1000);
  231. int nfound = 0;
  232. Vect<int> Nrapidities (0, Nstrings);
  233. //cout << "In Possible_Bases: start scan for Mdown = " << Mdown << endl;
  234. (*this).Scan_for_Possible_Bases (Mdown, possible_base_label, nfound, nexc_max_used, Nstrings - 1, Nrapidities);
  235. // Copy results into a clean vector:
  236. Vect<string> possible_base_label_found (nfound);
  237. for (int i = 0; i < nfound; ++i) possible_base_label_found[i] = possible_base_label[i];
  238. //cout << "In Possible_Bases: possible_base_label_found = " << possible_base_label_found << endl;
  239. return(possible_base_label_found);
  240. }
  241. */
  242. //***************************************************************************************************
  243. // Function definitions: class Heis_Base
  244. Heis_Base::Heis_Base () : Mdown(0), Nrap(Vect<int>()), Nraptot(0),
  245. Ix2_infty(Vect<DP>()), Ix2_min(Vect<int>()), Ix2_max(Vect<int>()), dimH(0.0), baselabel("") {}
  246. Heis_Base::Heis_Base (const Heis_Base& RefBase) // copy constructor
  247. : Mdown(RefBase.Mdown), Nrap(Vect<int>(RefBase.Nrap.size())), Nraptot(RefBase.Nraptot),
  248. Ix2_infty(Vect<DP>(RefBase.Nrap.size())), Ix2_min(Vect<int>(RefBase.Nrap.size())), Ix2_max(Vect<int>(RefBase.Nrap.size())),
  249. baselabel(RefBase.baselabel)
  250. {
  251. for (int i = 0; i < Nrap.size(); ++i) {
  252. Nrap[i] = RefBase.Nrap[i];
  253. Ix2_infty[i] = RefBase.Ix2_infty[i];
  254. Ix2_min[i] = RefBase.Ix2_min[i];
  255. Ix2_max[i] = RefBase.Ix2_max[i];
  256. dimH = RefBase.dimH;
  257. }
  258. }
  259. Heis_Base::Heis_Base (const Heis_Chain& RefChain, int M)
  260. : Mdown(M), Nrap(Vect<int>(RefChain.Nstrings)), Nraptot(0),
  261. Ix2_infty(Vect<DP>(RefChain.Nstrings)), Ix2_min(Vect<int>(RefChain.Nstrings)), Ix2_max(Vect<int>(RefChain.Nstrings))
  262. {
  263. for (int i = 0; i < RefChain.Nstrings; ++i) Nrap[i] = 0;
  264. Nrap[0] = M;
  265. Nraptot = 0;
  266. for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
  267. stringstream M0out;
  268. M0out << M;
  269. baselabel = M0out.str();
  270. // Now compute the Ix2_infty numbers
  271. (*this).Compute_Ix2_limits(RefChain);
  272. // Compute dimensionality of this sub-Hilbert space:
  273. complex<double> ln_dimH_cx = 0.0;
  274. for (int i = 0; i < RefChain.Nstrings; ++i)
  275. if (Nrap[i] > 0) ln_dimH_cx += ln_Gamma(complex<double>((Ix2_max[i] - Ix2_min[i])/2 + 2)) - ln_Gamma(complex<double>((Ix2_max[i] - Ix2_min[i])/2 + 2 - Nrap[i])) - ln_Gamma(complex<double>(Nrap[i] + 1));
  276. dimH = exp(real(ln_dimH_cx));
  277. }
  278. Heis_Base::Heis_Base (const Heis_Chain& RefChain, const Vect<int>& Nrapidities)
  279. : Mdown(0), Nrap(Nrapidities), Nraptot(0),
  280. Ix2_infty(Vect<DP>(RefChain.Nstrings)), Ix2_min(Vect<int>(RefChain.Nstrings)), Ix2_max(Vect<int>(RefChain.Nstrings))
  281. {
  282. // Check consistency of Nrapidities vector with RefChain
  283. //if (RefChain.Nstrings != Nrapidities.size()) cout << "error: Nstrings = " << RefChain.Nstrings << "\tNrap.size = " << Nrapidities.size() << endl;
  284. if (RefChain.Nstrings != Nrapidities.size()) ABACUSerror("Incompatible Nrapidities vector used in Heis_Base constructor.");
  285. int Mcheck = 0;
  286. for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += RefChain.Str_L[i] * Nrap[i];
  287. Mdown = Mcheck;
  288. Nraptot = 0;
  289. for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
  290. /*
  291. // Compute id
  292. id += Nrapidities[0];
  293. long long int factor = 100000LL;
  294. for (int i = 1; i < RefChain.Nstrings; ++i) {
  295. id += factor * Nrapidities[i];
  296. factor *= 100LL;
  297. }
  298. */
  299. // Set label:
  300. /*
  301. stringstream baselabel_strstream;
  302. baselabel_strstream << Nrapidities[0];
  303. for (int itype = 1; itype < Nrapidities.size(); ++itype)
  304. if (Nrapidities[itype] > 0) {
  305. baselabel_strstream << TYPESEP;
  306. stringstream typeout;
  307. typeout << itype;
  308. baselabel += typeout.str();
  309. baselabel += 'EXCSEP';
  310. stringstream Mout;
  311. Mout << Nrapidities[itype];
  312. baselabel += Mout.str();
  313. }
  314. */
  315. stringstream M0out;
  316. M0out << Nrapidities[0];
  317. baselabel = M0out.str();
  318. for (int itype = 1; itype < Nrapidities.size(); ++itype)
  319. if (Nrapidities[itype] > 0) {
  320. baselabel += TYPESEP;
  321. stringstream typeout;
  322. typeout << itype;
  323. baselabel += typeout.str();
  324. baselabel += EXCSEP;
  325. stringstream Mout;
  326. Mout << Nrapidities[itype];
  327. baselabel += Mout.str();
  328. }
  329. // Now compute the Ix2_infty numbers
  330. (*this).Compute_Ix2_limits(RefChain);
  331. // Compute dimensionality of this sub-Hilbert space:
  332. complex<double> ln_dimH_cx = 0.0;
  333. for (int i = 0; i < RefChain.Nstrings; ++i)
  334. if (Nrap[i] > 0) ln_dimH_cx += ln_Gamma(complex<double>((Ix2_max[i] - Ix2_min[i])/2 + 2)) - ln_Gamma(complex<double>((Ix2_max[i] - Ix2_min[i])/2 + 2 - Nrap[i])) - ln_Gamma(complex<double>(Nrap[i] + 1));
  335. dimH = exp(real(ln_dimH_cx));
  336. }
  337. Heis_Base::Heis_Base (const Heis_Chain& RefChain, string baselabel_ref)
  338. : Mdown(0), Nrap(Vect<int>(0, RefChain.Nstrings)), Nraptot(0),
  339. Ix2_infty(Vect<DP>(RefChain.Nstrings)), Ix2_min(Vect<int>(RefChain.Nstrings)), Ix2_max(Vect<int>(RefChain.Nstrings)),
  340. baselabel (baselabel_ref)
  341. {
  342. // Build Nrapidities vector from baselabel_ref.
  343. // This is simply done by using the state label standard reading function after conveniently
  344. // making baselabel into a label (as for a state with no excitations):
  345. string label_ref = baselabel + "_0_";
  346. Vect<Vect<int> > dummyOriginIx2(1);
  347. //cout << "Trying to build base from baselabel_ref " << baselabel_ref << "\t and label_ref " << label_ref << endl;
  348. //State_Label_Data labeldata = Read_State_Label (label_ref, dummyOriginIx2);
  349. State_Label_Data labeldata = Read_Base_Label (label_ref);
  350. //cout << "Read data." << endl;
  351. // Initialize Nrap:
  352. for (int i = 0; i < labeldata.type.size(); ++i)
  353. Nrap[labeldata.type[i] ] = labeldata.M[i];
  354. int Mcheck = 0;
  355. for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += RefChain.Str_L[i] * Nrap[i];
  356. Mdown = Mcheck;
  357. Nraptot = 0;
  358. for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
  359. // Now compute the Ix2_infty numbers
  360. (*this).Compute_Ix2_limits(RefChain);
  361. // Compute dimensionality of this sub-Hilbert space:
  362. complex<double> ln_dimH_cx = 0.0;
  363. for (int i = 0; i < RefChain.Nstrings; ++i)
  364. if (Nrap[i] > 0) ln_dimH_cx += ln_Gamma(complex<double>((Ix2_max[i] - Ix2_min[i])/2 + 2)) - ln_Gamma(complex<double>((Ix2_max[i] - Ix2_min[i])/2 + 2 - Nrap[i])) - ln_Gamma(complex<double>(Nrap[i] + 1));
  365. dimH = exp(real(ln_dimH_cx));
  366. }
  367. Heis_Base& Heis_Base::operator= (const Heis_Base& RefBase)
  368. {
  369. if (this != & RefBase) {
  370. Mdown = RefBase.Mdown;
  371. Nrap = RefBase.Nrap;
  372. Nraptot = RefBase.Nraptot;
  373. Ix2_infty = RefBase.Ix2_infty;
  374. Ix2_min = RefBase.Ix2_min;
  375. Ix2_max = RefBase.Ix2_max;
  376. dimH = RefBase.dimH;
  377. baselabel = RefBase.baselabel;
  378. }
  379. return(*this);
  380. }
  381. bool Heis_Base::operator== (const Heis_Base& RefBase)
  382. {
  383. bool answer = (Nrap == RefBase.Nrap);
  384. return (answer);
  385. }
  386. bool Heis_Base::operator!= (const Heis_Base& RefBase)
  387. {
  388. bool answer = (Nrap != RefBase.Nrap);
  389. return (answer);
  390. }
  391. void Heis_Base::Compute_Ix2_limits (const Heis_Chain& RefChain)
  392. {
  393. if ((RefChain.Delta > 0.0) && (RefChain.Delta < 1.0)) {
  394. // Compute the Ix2_infty numbers
  395. DP sum1 = 0.0;
  396. DP sum2 = 0.0;
  397. for (int j = 0; j < RefChain.Nstrings; ++j) {
  398. sum1 = 0.0;
  399. for (int k = 0; k < RefChain.Nstrings; ++k) {
  400. sum2 = 0.0;
  401. sum2 += (RefChain.Str_L[j] == RefChain.Str_L[k]) ? 0.0 : 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
  402. - 0.5 * fabs(RefChain.Str_L[j] - RefChain.Str_L[k]) * RefChain.anis));
  403. sum2 += 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
  404. - 0.5 * (RefChain.Str_L[j] + RefChain.Str_L[k]) * RefChain.anis));
  405. for (int a = 1; a < ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]); ++a)
  406. sum2 += 2.0 * 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
  407. - 0.5 * (fabs(RefChain.Str_L[j] - RefChain.Str_L[k]) + 2.0*a) * RefChain.anis));
  408. sum1 += (Nrap[k] - ((j == k) ? 1 : 0)) * sum2;
  409. }
  410. Ix2_infty[j] = (1.0/PI) * fabs(RefChain.Nsites * 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j])
  411. - 0.5 * RefChain.Str_L[j] * RefChain.anis)) - sum1);
  412. } // The Ix2_infty are now set.
  413. // Now compute the Ix2_max limits
  414. for (int j = 0; j < RefChain.Nstrings; ++j) {
  415. Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
  416. // Reject formally infinite rapidities (i.e. if Delta is root of unity)
  417. //cout << "Ix2_infty - Ix2_max = " << Ix2_infty[j] - Ix2_max[j] << endl;
  418. //if (Ix2_infty[j] == Ix2_max[j]) {
  419. //Ix2_max[j] -= 2;
  420. //}
  421. // If Nrap is even, Ix2_max must be odd. If odd, then even.
  422. if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1;
  423. while (Ix2_max[j] > RefChain.Nsites) {
  424. Ix2_max[j] -= 2;
  425. }
  426. Ix2_min[j] = -Ix2_max[j];
  427. }
  428. } // if XXZ gapless
  429. else if (RefChain.Delta == 1.0) {
  430. // Compute the Ix2_infty numbers
  431. int sum1 = 0;
  432. for (int j = 0; j < RefChain.Nstrings; ++j) {
  433. sum1 = 0;
  434. for (int k = 0; k < RefChain.Nstrings; ++k) {
  435. sum1 += Nrap[k] * (2 * ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]) - ((j == k) ? 1 : 0));
  436. }
  437. //Ix2_infty[j] = (RefChain.Nsites - 1.0 + 2.0 * RefChain.Str_L[j] - sum1);
  438. Ix2_infty[j] = (RefChain.Nsites + 1.0 - sum1); // to get counting right...
  439. } // The Ix2_infty are now set.
  440. // Now compute the Ix2_max limits
  441. for (int j = 0; j < RefChain.Nstrings; ++j) {
  442. Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
  443. // Give the correct parity to Ix2_max
  444. // If Nrap is even, Ix2_max must be odd. If odd, then even.
  445. if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1;
  446. // If Ix2_max equals Ix2_infty, we reduce it by 2:
  447. if (Ix2_max[j] == int(Ix2_infty[j])) Ix2_max[j] -= 2;
  448. while (Ix2_max[j] > RefChain.Nsites) {
  449. Ix2_max[j] -= 2;
  450. }
  451. Ix2_min[j] = -Ix2_max[j];
  452. }
  453. } // if XXX AFM
  454. else if (RefChain.Delta > 1.0) {
  455. // Compute the Ix2_infty numbers
  456. int sum1 = 0;
  457. for (int j = 0; j < RefChain.Nstrings; ++j) {
  458. sum1 = 0;
  459. for (int k = 0; k < RefChain.Nstrings; ++k) {
  460. sum1 += Nrap[k] * (2 * ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]) - ((j == k) ? 1 : 0));
  461. }
  462. Ix2_infty[j] = (RefChain.Nsites - 1 + 2 * RefChain.Str_L[j] - sum1);
  463. } // The Ix2_infty are now set.
  464. // Now compute the Ix2_max limits
  465. for (int j = 0; j < RefChain.Nstrings; ++j) {
  466. Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
  467. // Give the correct parity to Ix2_max
  468. // If Nrap is even, Ix2_max must be odd. If odd, then even.
  469. if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1;
  470. // If Ix2_max equals Ix2_infty, we reduce it by 2:
  471. //if (Ix2_max[j] == Ix2_infty[j]) Ix2_max[j] -= 2;
  472. while (Ix2_max[j] > RefChain.Nsites) {
  473. Ix2_max[j] -= 2;
  474. }
  475. // Fudge, for strings:
  476. //if (RefChain.Str_L[j] >= 1) Ix2_max[j] += 2;
  477. //Ix2_max[j] += 2;
  478. Ix2_min[j] = -Ix2_max[j];
  479. }
  480. } // if XXZ_gpd
  481. }
  482. //***************************************************************************************************
  483. // Function definitions: class Lambda
  484. Lambda::Lambda () : lambda(NULL) {}
  485. Lambda::Lambda (const Heis_Chain& RefChain, int M)
  486. : Nstrings(1), Nrap(Vect<int>(M,1)), Nraptot(M), lambda(new DP*[1]) // single type of string here
  487. //: lambda(Vect<Vect<DP> > (1))
  488. {
  489. lambda[0] = new DP[M];
  490. //lambda[0] = Vect<DP> (M);
  491. for (int j = 0; j < M; ++j) lambda[0][j] = 0.0;
  492. }
  493. Lambda::Lambda (const Heis_Chain& RefChain, const Heis_Base& base)
  494. : Nstrings(RefChain.Nstrings), Nrap(base.Nrap), Nraptot(base.Nraptot), lambda(new DP*[RefChain.Nstrings])
  495. //: lambda(Vect<Vect<DP> > (RefChain.Nstrings))
  496. {
  497. //lambda[0] = new DP[base.Mdown];
  498. lambda[0] = new DP[base.Nraptot];
  499. for (int i = 1; i < RefChain.Nstrings; ++i) lambda[i] = lambda[i-1] + base[i-1];
  500. //for (int i = 0; i < RefChain.Nstrings; ++i) lambda[i] = Vect<DP> (base[i]);
  501. for (int i = 0; i < RefChain.Nstrings; ++i) {
  502. for (int j = 0; j < base[i]; ++j) lambda[i][j] = 0.0;
  503. }
  504. }
  505. Lambda& Lambda::operator= (const Lambda& RefLambda)
  506. {
  507. if (this != &RefLambda) {
  508. Nstrings = RefLambda.Nstrings;
  509. Nrap = RefLambda.Nrap;
  510. Nraptot = RefLambda.Nraptot;
  511. if (lambda != 0) {
  512. delete[] (lambda[0]);
  513. delete[] (lambda);
  514. }
  515. lambda = new DP*[Nstrings];
  516. lambda[0] = new DP[Nraptot];
  517. for (int i = 1; i < Nstrings; ++i) lambda[i] = lambda[i-1] + Nrap[i-1];
  518. for (int i = 0; i < Nstrings; ++i)
  519. for (int j = 0; j < Nrap[i]; ++j) lambda[i][j] = RefLambda.lambda[i][j];
  520. }
  521. return(*this);
  522. }
  523. Lambda::~Lambda()
  524. {
  525. if (lambda != 0) {
  526. delete[] (lambda[0]);
  527. delete[] lambda;
  528. }
  529. }
  530. //***************************************************************************************************
  531. // Function definitions: class Heis_Bethe_State
  532. Heis_Bethe_State::Heis_Bethe_State ()
  533. : chain(Heis_Chain()), base(Heis_Base()), //offsets(Ix2_Offsets()),
  534. //Ix2(Ix2_Config(chain, 1)),
  535. Ix2(Vect<Vect<int> > (1)),
  536. lambda(Lambda(chain, 1)), BE(Lambda(chain, 1)), diffsq(0.0), conv(0), dev(1.0), iter(0), iter_Newton(0),
  537. E(0.0), iK(0), K(0.0), lnnorm(-100.0), //base_id(0LL), type_id(0LL), id(0LL), maxid(0LL), nparticles(0)
  538. label("")
  539. {
  540. };
  541. Heis_Bethe_State::Heis_Bethe_State (const Heis_Bethe_State& RefState) // copy constructor
  542. //: chain(RefState.chain), base(RefState.base), offsets(RefState.offsets), Ix2(Ix2_Config(RefState.chain, RefState.base.Mdown)),
  543. // lambda(Lambda(RefState.chain, RefState.base.Mdown)), BE(Lambda(RefState.chain, RefState.base.Mdown)),
  544. : chain(RefState.chain), base(RefState.base), //offsets(RefState.offsets),
  545. //Ix2(Ix2_Config(RefState.chain, RefState.base)),
  546. Ix2 (RefState.Ix2),
  547. lambda(Lambda(RefState.chain, RefState.base)), BE(Lambda(RefState.chain, RefState.base)),
  548. diffsq(RefState.diffsq), conv(RefState.conv), dev(RefState.dev), iter(RefState.iter), iter_Newton(RefState.iter_Newton),
  549. E(RefState.E), iK(RefState.iK), K(RefState.K), lnnorm(RefState.lnnorm),
  550. //id(RefState.id), maxid(RefState.maxid)
  551. //base_id(RefState.base_id), type_id(RefState.type_id), id(RefState.id), maxid(RefState.maxid), nparticles(RefState.nparticles)
  552. label(RefState.label)
  553. {
  554. // copy arrays into new ones
  555. /*
  556. cout << "Here in Heis constructor state" << endl;
  557. cout << "lambda " << lambda[0][0] << endl;
  558. cout << "lambda OK" << endl;
  559. cout << "RefConfig: " << endl << RefState.Ix2 << endl;
  560. cout << "(*this).Ix2: " << endl << Ix2 << endl;
  561. */
  562. for (int j = 0; j < RefState.chain.Nstrings; ++j) {
  563. for (int alpha = 0; alpha < RefState.base[j]; ++j) {
  564. //Ix2[j][alpha] = RefState.Ix2[j][alpha]; // not needed anymore since Ix2 is Vect<Vect<int> >
  565. lambda[j][alpha] = RefState.lambda[j][alpha];
  566. }
  567. }
  568. //cout << "Heis constructor state OK" << endl;
  569. }
  570. Heis_Bethe_State::Heis_Bethe_State (const Heis_Chain& RefChain, int M)
  571. : chain(RefChain), base(RefChain, M), //offsets(base, 0LL),
  572. //Ix2(Ix2_Config(RefChain, M)),
  573. Ix2 (Vect<Vect<int> > (1)),
  574. lambda(Lambda(RefChain, M)),
  575. BE(Lambda(RefChain, M)), diffsq(1.0), conv(0), dev(1.0), iter(0), iter_Newton(0),
  576. E(0.0), iK(0), K(0.0), lnnorm(-100.0)
  577. //id(0LL), maxid(0LL)
  578. //base_id(0LL), type_id(0LL), id(0LL), maxid(offsets.maxid), nparticles(0)
  579. {
  580. Ix2[0] = Vect<int> (M);
  581. for (int j = 0; j < M; ++j) Ix2[0][j] = -(M - 1) + 2*j;
  582. stringstream M0out;
  583. M0out << M;
  584. label = M0out.str() + "_0_";
  585. }
  586. Heis_Bethe_State::Heis_Bethe_State (const Heis_Chain& RefChain, const Heis_Base& RefBase)
  587. : chain(RefChain), base(RefBase), //offsets(RefBase, 0LL),
  588. //Ix2(Ix2_Config(RefChain, RefBase)),
  589. Ix2 (Vect<Vect<int> > (RefChain.Nstrings)),
  590. lambda(Lambda(RefChain, RefBase)),
  591. BE(Lambda(RefChain, RefBase)), diffsq(1.0), conv(0), dev(1.0), iter(0), iter_Newton(0), E(0.0), iK(0), K(0.0), lnnorm(-100.0)
  592. //id(0LL), maxid(0LL)
  593. //base_id(RefBase.id), type_id(0LL), id(0LL), maxid(offsets.maxid), nparticles(0)
  594. {
  595. // Check that the number of rapidities is consistent with Mdown
  596. //cout << "Here in Heis constructor chain base" << endl;
  597. //cout << "lambda " << lambda[0][0] << endl;
  598. //cout << "lambda OK" << endl;
  599. int Mcheck = 0;
  600. for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += base[i] * RefChain.Str_L[i];
  601. if (RefBase.Mdown != Mcheck) ABACUSerror("Wrong M from Nrapidities input vector, in Heis_Bethe_State constructor.");
  602. for (int i = 0; i < RefChain.Nstrings; ++i) Ix2[i] = Vect<int> (base[i]);
  603. // And now for the other string types...
  604. for (int i = 0; i < RefChain.Nstrings; ++i) {
  605. for (int j = 0; j < base[i]; ++j) Ix2[i][j] = -(base[i] - 1) + 2*j;
  606. }
  607. label = Return_State_Label (Ix2, Ix2);
  608. }
  609. void Heis_Bethe_State::Set_to_Label (string label_ref, const Vect<Vect<int> >& OriginIx2)
  610. {
  611. //cout << "Called Set_to_Label with label_ref " << label_ref << " on state " << (*this) << endl;
  612. //cout << "Check labeldata of label " << label_ref << endl;
  613. State_Label_Data labeldata = Read_State_Label (label_ref, OriginIx2);
  614. //cout << "type: " << labeldata.type << endl << "M: " << labeldata.M << endl << "nexc: " << labeldata.nexc << endl;
  615. //for (int i = 0; i < labeldata.Ix2old.size(); ++i) cout << "Ix2old[" << i << "] = " << labeldata.Ix2old[i] << endl << "Ix2exc[" << i << "] = " << labeldata.Ix2exc[i] << endl;
  616. label = label_ref;
  617. Vect<Vect<int> > OriginIx2ordered = OriginIx2;
  618. for (int i = 0; i < OriginIx2.size(); ++i) OriginIx2ordered[i].QuickSort();
  619. // Set all Ix2 to OriginIx2:
  620. for (int il = 0; il < OriginIx2.size(); ++il)
  621. for (int i = 0; i < OriginIx2[il].size(); ++i) Ix2[il][i] = OriginIx2ordered[il][i];
  622. // Now set the excitations:
  623. for (int it = 0; it < labeldata.type.size(); ++it)
  624. for (int iexc = 0; iexc < labeldata.nexc[it]; ++iexc)
  625. for (int i = 0; i < labeldata.M[it]; ++i)
  626. if (Ix2[labeldata.type[it] ][i] == labeldata.Ix2old[it][iexc]) {
  627. //cout << it << "\t" << iexc << "\t" << i << endl;
  628. //cout << "\tSetting Ix2[" << labeldata.type[it] << "][" << i << "] to " << labeldata.Ix2exc[it][iexc] << endl;
  629. //cout << Ix2[labeldata.type[it] ][i] << "\t" << labeldata.Ix2old[it][iexc] << "\t" << labeldata.Ix2exc[it][iexc] << endl;
  630. Ix2[labeldata.type[it] ][i] = labeldata.Ix2exc[it][iexc];
  631. //cout << Ix2[labeldata.type[it] ][i] << "\t" << labeldata.Ix2old[it][iexc] << "\t" << labeldata.Ix2exc[it][iexc] << endl;
  632. }
  633. //cout << "State obtained(1): " << (*this) << endl;
  634. // Now reorder the Ix2 to follow convention:
  635. for (int il = 0; il < Ix2.size(); ++il) Ix2[il].QuickSort();
  636. //cout << "Setting label:" << label_ref << endl << "Ix2old = " << labeldata.Ix2old[0] << endl << "Ix2exc = " << labeldata.Ix2exc[0] << endl;
  637. //cout << "on " << OriginStateIx2ordered << endl << "giving " << Ix2 << endl;
  638. //cout << "State obtained(2): " << (*this) << endl;
  639. //char a; cin >> a;
  640. //(*this).Set_Label_from_Ix2 (OriginStateIx2ordered);
  641. //(*this).Set_Label_Internals_from_Ix2 (OriginStateIx2ordered);
  642. }
  643. void Heis_Bethe_State::Set_Label_from_Ix2 (const Vect<Vect<int> >& OriginIx2)
  644. {
  645. // This function does not assume any ordering of the Ix2.
  646. // ASSUMPTIONS:
  647. // (*this) has a base already identical to base of OriginIx2
  648. // First check that bases are consistent
  649. if ((*this).chain.Nstrings != OriginIx2.size()) ABACUSerror("Inconsistent base sizes in Heis_Bethe_State::Set_Label_from_Ix2.");
  650. // Then check that the filling at each level is equal
  651. for (int il = 0; il < (*this).chain.Nstrings; ++il)
  652. if ((*this).base.Nrap[il] != OriginIx2[il].size()) ABACUSerror("Inconsistent base filling in Heis_Bethe_State::Set_Label_from_Ix2.");
  653. // Determine how many types of particles are present
  654. int ntypes = 1; // level 0 always assumed present
  655. for (int il = 1; il < chain.Nstrings; ++il) if (base.Nrap[il] > 0) ntypes++;
  656. // Set the state label
  657. Vect<int> type_ref(0, ntypes);
  658. Vect<int> M_ref(ntypes);
  659. M_ref[0] = OriginIx2[0].size();
  660. type_ref[0] = 0;
  661. int itype = 1;
  662. for (int il = 1; il < chain.Nstrings; ++il)
  663. if (base.Nrap[il] > 0) {
  664. type_ref[itype] = il;
  665. M_ref[itype++] = OriginIx2[il].size();
  666. }
  667. Vect<int> nexc_ref(0, ntypes);
  668. Vect<Vect<int> > Ix2old_ref(ntypes);
  669. Vect<Vect<int> > Ix2exc_ref(ntypes);
  670. // Count nr of particle-holes at each level:
  671. //itype = 0;
  672. itype = -1;
  673. for (int il = 0; il < chain.Nstrings; ++il) {
  674. if (il == 0 || base.Nrap[il] > 0) {
  675. itype++;
  676. for (int alpha = 0; alpha < base.Nrap[il]; ++alpha)
  677. if (!OriginIx2[il].includes(Ix2[il][alpha])) nexc_ref[itype] += 1;
  678. Ix2old_ref[itype] = Vect<int>(ABACUS::max(nexc_ref[itype], 1));
  679. Ix2exc_ref[itype] = Vect<int>(ABACUS::max(nexc_ref[itype], 1));
  680. int nexccheck = 0;
  681. for (int alpha = 0; alpha < base.Nrap[il]; ++alpha)
  682. if (!OriginIx2[il].includes(Ix2[il][alpha])) Ix2exc_ref[itype][nexccheck++] = Ix2[il][alpha];
  683. if (nexccheck != nexc_ref[itype]) {
  684. cout << "il = " << il << "\titype = " << itype << "\tnexccheck = " << nexccheck << "\tnexc_ref[itype] = " << nexc_ref[itype] << endl;
  685. cout << OriginIx2[il] << endl << Ix2[il] << endl;
  686. ABACUSerror("Counting excitations wrong (1) in Heis_Bethe_State::Set_Label_from_Ix2.");
  687. }
  688. nexccheck = 0;
  689. for (int alpha = 0; alpha < base.Nrap[il]; ++alpha)
  690. if (!Ix2[il].includes (OriginIx2[il][alpha])) Ix2old_ref[itype][nexccheck++] = OriginIx2[il][alpha];
  691. if (nexccheck != nexc_ref[itype]) {
  692. ABACUSerror("Counting excitations wrong (2) in Heis_Bethe_State::Set_Label_from_Ix2.");
  693. }
  694. // Now order the Ix2old_ref and Ix2exc_ref:
  695. Ix2old_ref[itype].QuickSort();
  696. Ix2exc_ref[itype].QuickSort();
  697. } // if (il == 0 || ...
  698. } // for il
  699. State_Label_Data labeldata(type_ref, M_ref, nexc_ref, Ix2old_ref, Ix2exc_ref);
  700. label = Return_State_Label (labeldata, OriginIx2);
  701. }
  702. bool Heis_Bethe_State::Check_Symmetry ()
  703. {
  704. // Checks whether the I's are symmetrically distributed.
  705. bool symmetric_state = true;
  706. int arg, test1, test3;
  707. //if (chain.Delta <= 1.0) {
  708. for (int j = 0; j < chain.Nstrings; ++j) {
  709. test1 = 0;
  710. test3 = 0;
  711. for (int alpha = 0; alpha < base[j]; ++alpha) {
  712. arg = (Ix2[j][alpha] != chain.Nsites) ? Ix2[j][alpha] : 0; // since Ix2 = N is same as Ix2 = -N by periodicity, this is symmetric.
  713. test1 += arg;
  714. test3 += arg * arg * arg; // to make sure that all I's are symmetrical...
  715. }
  716. if (!(symmetric_state && (test1 == 0) && (test3 == 0))) symmetric_state = false;
  717. }
  718. //}
  719. /*
  720. else if (chain.Delta > 1.0) {
  721. // For the gapped antiferromagnet, we check symmetry *excluding* the Ix2_max values
  722. // The state is then inadmissible is symmetric && -Ix2_max occupied
  723. for (int j = 0; j < chain.Nstrings; ++j) {
  724. test1 = 0;
  725. test3 = 0;
  726. for (int alpha = 0; alpha < base[j]; ++alpha) {
  727. arg = (Ix2[j][alpha] != chain.Nsites
  728. && abs(Ix2[j][alpha]) != base.Ix2_max[j]) ? Ix2[j][alpha] : 0; // since Ix2 = N is same as Ix2 = -N by periodicity, this is symmetric.
  729. test1 += arg;
  730. test3 += arg * arg * arg; // to make sure that all I's are symmetrical...
  731. }
  732. if (!(symmetric_state && (test1 == 0) && (test3 == 0))) symmetric_state = false;
  733. }
  734. }
  735. */
  736. return symmetric_state;
  737. }
  738. // SOLVING BETHE EQUATIONS:
  739. void Heis_Bethe_State::Compute_diffsq ()
  740. {
  741. DP maxterm = 0.0;
  742. int jmax, alphamax;
  743. diffsq = 0.0;
  744. for (int j = 0; j < chain.Nstrings; ++j)
  745. for (int alpha = 0; alpha < base[j]; ++alpha) {
  746. diffsq += pow(BE[j][alpha], 2.0);
  747. if (pow(BE[j][alpha], 2.0)/chain.Nsites > maxterm) {
  748. jmax = j;
  749. alphamax = alpha;
  750. maxterm = pow(BE[j][alpha], 2.0)/chain.Nsites;
  751. }
  752. }
  753. diffsq /= DP(chain.Nsites);
  754. }
  755. void Heis_Bethe_State::Find_Rapidities (bool reset_rapidities)
  756. {
  757. // This function finds the rapidities of the eigenstate
  758. //cout << endl << "Find_Rapidities called: " << (*this) << endl;
  759. lnnorm = -100.0; // sentinel value, recalculated if Newton method used in the last step of iteration.
  760. Lambda lambda_ref(chain, base);
  761. diffsq = 1.0;
  762. if (reset_rapidities)
  763. (*this).Set_Free_lambdas();
  764. //cout << endl << "After Set_Free_lambdas: " << (*this) << endl;
  765. (*this).Compute_BE();
  766. //cout << endl << "After Compute_BE: " << (*this) << endl;
  767. iter = 0;
  768. iter_Newton = 0;
  769. // Start with conventional iterations
  770. DP iter_prec = 1.0e-2/DP(chain.Nsites);
  771. DP iter_factor = 0.99;
  772. DP iter_factor_extrap = 0.99;
  773. clock_t extrap_start;
  774. clock_t extrap_stop;
  775. clock_t Newton_start;
  776. clock_t Newton_stop;
  777. int iter_extrap_start, iter_extrap_stop, iter_Newton_start, iter_Newton_stop;
  778. DP diffsq_start;
  779. DP diffsq_extrap_start, diffsq_extrap_stop, diffsq_Newton_start, diffsq_Newton_stop;
  780. bool straight_improving = true;
  781. bool extrap_improving = true;
  782. bool Newton_improving = true;
  783. DP diffsq_iter_aim = 1.0e-5;
  784. bool info_findrap = false;
  785. if (info_findrap) cout << "Find_Rapidities called for state with label " << (*this).label << endl;
  786. while (diffsq > chain.prec && (iter < 500 && iter_Newton < 100
  787. || straight_improving || extrap_improving || Newton_improving)) {
  788. // If we haven't reset, first try a few Newton steps...
  789. //if (!reset_rapidities && iter_Newton == 0) (*this).Solve_BAE_Newton (chain.prec, 10);
  790. if (!Newton_improving) diffsq_iter_aim *= 1.0e-5;
  791. // Start with a few straight iterations:
  792. if (!straight_improving) iter_factor *= 2.0/3.0;
  793. else iter_factor = 0.99;
  794. diffsq_start = diffsq;
  795. do {
  796. extrap_start = clock();
  797. iter_extrap_start = iter;
  798. diffsq_extrap_start = diffsq;
  799. if (diffsq > iter_prec) (*this).Solve_BAE_straight_iter (iter_prec, 10, iter_factor);
  800. extrap_stop = clock();
  801. iter_extrap_stop = iter;
  802. diffsq_extrap_stop = diffsq;
  803. iter_prec = diffsq * 0.1;
  804. if (info_findrap) cout << "Straight iter: iter " << iter << "\titer_factor " << iter_factor << "\tdiffsq " << diffsq << endl;
  805. //} while (diffsq > chain.prec && !is_nan(diffsq) && diffsq_extrap_stop/diffsq_extrap_start < 0.01);
  806. } while (diffsq > diffsq_iter_aim && !is_nan(diffsq) && diffsq_extrap_stop/diffsq_extrap_start < 0.01);
  807. straight_improving = (diffsq < diffsq_start);
  808. // Now try to extrapolate to infinite nr of iterations:
  809. if (!extrap_improving) iter_factor_extrap *= 2.0/3.0;
  810. else iter_factor_extrap = 0.99;
  811. diffsq_start = diffsq;
  812. if (diffsq > chain.prec)
  813. do {
  814. extrap_start = clock();
  815. iter_extrap_start = iter;
  816. diffsq_extrap_start = diffsq;
  817. if (diffsq > iter_prec) (*this).Solve_BAE_extrap (iter_prec, 10, iter_factor_extrap);
  818. extrap_stop = clock();
  819. iter_extrap_stop = iter;
  820. diffsq_extrap_stop = diffsq;
  821. iter_prec = diffsq * 0.1;
  822. if (info_findrap) cout << "Extrap: iter " << iter << "\tdiffsq " << diffsq << endl;
  823. } while (diffsq > chain.prec && !is_nan(diffsq) && diffsq_extrap_stop/diffsq_extrap_start < 0.01);
  824. extrap_improving = (diffsq < diffsq_extrap_start);
  825. // Now try Newton
  826. diffsq_Newton_start = diffsq;
  827. if (diffsq > chain.prec)
  828. do {
  829. Newton_start = clock();
  830. iter_Newton_start = iter_Newton;
  831. diffsq_Newton_start = diffsq;
  832. if (diffsq > iter_prec) (*this).Solve_BAE_Newton (chain.prec, 5);
  833. Newton_stop = clock();
  834. iter_Newton_stop = iter_Newton;
  835. diffsq_Newton_stop = diffsq;
  836. if (info_findrap) cout << "Newton: iter_Newton " << iter_Newton << "\tdiffsq " << diffsq << endl;
  837. } while (diffsq > chain.prec && !is_nan(diffsq) && diffsq_Newton_stop/diffsq_Newton_start < 0.01);
  838. Newton_improving = (diffsq < diffsq_Newton_start);
  839. //if (diffsq > iter_prec) (*this).Solve_BAE_smackdown (0.1 * diffsq, 1);
  840. //cout << "Before silk: diffsq = " << diffsq << endl;
  841. // If none of the methods are improving the result, try the silk gloves...
  842. if (!(straight_improving || extrap_improving || Newton_improving)) {
  843. if (info_findrap) cout << "Before silk gloves: diffsq " << diffsq << endl;
  844. (*this).Solve_BAE_with_silk_gloves (chain.prec, chain.Nsites, 0.9);
  845. if (info_findrap) cout << "After silk gloves: diffsq " << diffsq << endl;
  846. }
  847. if (is_nan(diffsq)) {
  848. (*this).Set_Free_lambdas(); // good start if we've messed up with Newton
  849. diffsq = 1.0;
  850. }
  851. iter_prec *= 1.0e-4;
  852. iter_prec = ABACUS::max(iter_prec, chain.prec);
  853. } // while (diffsq > chain.prec && (iter < 300 && iter_Newton < 50...
  854. // Check convergence:
  855. //cout << "Check_Rapidities: " << (*this).Check_Rapidities() << endl;
  856. //conv = (diffsq < chain.prec && (*this).Check_Rapidities() && ((*this).String_delta() < HEIS_deltaprec)) ? 1 : 0;
  857. conv = (diffsq < chain.prec && (*this).Check_Rapidities()) ? 1 : 0;
  858. dev = (*this).String_delta();
  859. //cout << "String delta: " << (*this).String_delta() << "\tBoolean: " << ((*this).String_delta() < HEIS_deltaprec) << endl;
  860. return;
  861. }
  862. void Heis_Bethe_State::Solve_BAE_bisect (int j, int alpha, DP req_prec, int itermax)
  863. {
  864. // Finds the root lambda[j][alpha] to precision req_prec using bisection
  865. DP prec_obtained = 1.0;
  866. int niter_here = 0;
  867. DP lambdajalphastart = lambda[j][alpha];
  868. DP lambdamax = (fabs(chain.Delta) <= 1.0 ? pow(log(chain.Nsites), 1.1) : PI - 1.0e-4);
  869. // Find values of lambda such that BE changes sign:
  870. DP lambdaleft = -lambdamax;
  871. DP lambdamid = 0.0;
  872. DP lambdaright = lambdamax;
  873. DP BEleft, BEmid, BEright;
  874. lambda[j][alpha] = lambdaleft;
  875. (*this).Compute_BE (j, alpha);
  876. //cout << "lambda: " << lambda[j][alpha] << "\ttanhlambda: " << tanh(lambda[j][alpha]) << endl;
  877. BEleft= BE[j][alpha];
  878. lambda[j][alpha] = lambdaright;
  879. (*this).Compute_BE (j, alpha);
  880. BEright= BE[j][alpha];
  881. if (BEleft * BEright > 0.0) {
  882. lambda[j][alpha] = lambdajalphastart;
  883. //cout << lambdaleft << "\t" << lambdaright << "\t" << BEleft << "\t" << BEright << endl;
  884. //cout << "Could not bisect BE[" << j << "][" << alpha << "]" << endl;
  885. return;
  886. }
  887. while (prec_obtained > req_prec && niter_here < itermax) {
  888. lambdamid = 0.5 * (lambdaleft + lambdaright);
  889. lambda[j][alpha] = lambdamid;
  890. (*this).Compute_BE (j, alpha);
  891. BEmid = BE[j][alpha];
  892. //cout << "niter_here = " << niter_here << "\t" << lambdaleft << "\t" << lambdamid << "\t" << lambdaright << endl;
  893. //cout << BEleft << "\t" << BEmid << "\t" << BEright << endl;
  894. if (BEmid * BEleft < 0.0) { // root is to the left of mid
  895. lambdaright = lambdamid;
  896. BEright = BEmid;
  897. }
  898. else if (BEmid * BEright < 0.0) { // root is to the right of mid
  899. lambdaleft = lambdamid;
  900. BEleft = BEmid;
  901. }
  902. else if (BEmid * BEmid < req_prec) return;
  903. else {
  904. //cout << lambdaleft << "\t" << lambdamid << "\t" << lambdaright << endl;
  905. //cout << BEleft << "\t" << BEmid << "\t" << BEright << endl;
  906. //ABACUSerror("Problem in Solve_BAE_bisect.");
  907. return; // this procedure has failed
  908. }
  909. prec_obtained = BEmid * BEmid;
  910. niter_here++;
  911. //cout << "bisect: " << lambdaleft << "\t" << lambdaright << "\t" << BEleft << "\t" << BEright << "\t" << prec_obtained << "\t" << req_prec << endl;
  912. }
  913. return;
  914. }
  915. void Heis_Bethe_State::Iterate_BAE (DP iter_factor)
  916. {
  917. //DP lambda_old;
  918. for (int j = 0; j < chain.Nstrings; ++j) {
  919. for (int alpha = 0; alpha < base[j]; ++alpha)
  920. {
  921. //lambda_old = lambda[j][alpha];
  922. //lambda[j][alpha] = Iterate_BAE (j, alpha);
  923. lambda[j][alpha] += iter_factor * (Iterate_BAE (j, alpha) - lambda[j][alpha]);
  924. //cout << j << "\t" << alpha << "\t" << Ix2[j][alpha] << "\t" << lambda_old << "\t" << lambda[j][alpha] << "\t";
  925. //if (j > 0) cout << j << "\t" << alpha << "\t" << Ix2[j][alpha] << "\t" << lambda_old << "\t" << lambda[j][alpha] << endl;
  926. }
  927. }
  928. iter++;
  929. (*this).Compute_BE();
  930. (*this).Compute_diffsq();
  931. }
  932. void Heis_Bethe_State::Solve_BAE_straight_iter (DP straight_prec, int max_iter, DP iter_factor)
  933. {
  934. // This function attempts to get convergence diffsq <= straight_prec in at most max_iter steps.
  935. // If this fails, the lambda's are reset to original values, defined as...
  936. Lambda lambda_ref(chain, base);
  937. DP diffsq_ref = 1.0;
  938. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
  939. diffsq_ref = diffsq;
  940. // Now begin solving...
  941. diffsq = 1.0;
  942. int iter_done_here = 0;
  943. while ((diffsq > straight_prec) && (max_iter > iter_done_here)) {
  944. //cout << "BEFORE ITERATION" << endl << (*this) << endl << endl;
  945. (*this).Iterate_BAE(iter_factor);
  946. //cout << "ITERATION " << iter_done_here << endl << (*this) << endl << endl;
  947. iter_done_here++;
  948. }
  949. if ((diffsq > diffsq_ref) || (is_nan(diffsq))) {
  950. // This procedure has failed. We reset everything to begin values.
  951. //cout << "Straight iter failed: resetting." << endl;
  952. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda[j][alpha] = lambda_ref[j][alpha];
  953. (*this).Compute_BE();
  954. diffsq = diffsq_ref;
  955. }
  956. }
  957. void Heis_Bethe_State::Solve_BAE_extrap (DP extrap_prec, int max_iter_extrap, DP iter_factor)
  958. {
  959. // This function attempts to get convergence diffsq <= extrap_prec in at most max_iter_extrap steps.
  960. // If this fails, the lambda's are reset to original values, defined as...
  961. Lambda lambda_ref(chain, base);
  962. DP diffsq_ref = 1.0;
  963. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
  964. diffsq_ref = diffsq;
  965. // Now begin solving...
  966. diffsq = 1.0;
  967. DP diffsq1, diffsq2, diffsq3, diffsq4;
  968. int iter_done_here = 0;
  969. Lambda lambda1(chain, base);
  970. Lambda lambda2(chain, base);
  971. Lambda lambda3(chain, base);
  972. Lambda lambda4(chain, base);
  973. Lambda lambda5(chain, base);
  974. while ((diffsq > extrap_prec) && (max_iter_extrap > iter_done_here)) {
  975. (*this).Iterate_BAE(iter_factor);
  976. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda1[j][alpha] = lambda[j][alpha];
  977. diffsq1 = diffsq;
  978. (*this).Iterate_BAE(iter_factor);
  979. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda2[j][alpha] = lambda[j][alpha];
  980. diffsq2 = diffsq;
  981. (*this).Iterate_BAE(iter_factor);
  982. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda3[j][alpha] = lambda[j][alpha];
  983. diffsq3 = diffsq;
  984. (*this).Iterate_BAE(iter_factor);
  985. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda4[j][alpha] = lambda[j][alpha];
  986. diffsq4 = diffsq;
  987. //(*this).Iterate_BAE(iter_factor);
  988. //for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda5[j][alpha] = lambda[j][alpha];
  989. //diffsq5 = diffsq;
  990. iter_done_here += 4;
  991. // now extrapolate the result to infinite number of iterations...
  992. if (diffsq4 < diffsq3 && diffsq3 < diffsq2 && diffsq2 < diffsq1 && diffsq1 < diffsq_ref) {
  993. Vect_DP rap(0.0, 4);
  994. Vect_DP oneoverP(0.0, 4);
  995. DP deltalambda = 0.0;
  996. for (int i = 0; i < 4; ++i) oneoverP[i] = 1.0/(1.0 + i*i);
  997. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) {
  998. rap[0] = lambda1[j][alpha];
  999. rap[1] = lambda2[j][alpha];
  1000. rap[2] = lambda3[j][alpha];
  1001. rap[3] = lambda4[j][alpha];
  1002. //rap[4] = lambda5[j][alpha];
  1003. polint (oneoverP, rap, 0.0, lambda[j][alpha], deltalambda);
  1004. //cout << j << "\t" << alpha << "\t" << rap << "\t" << lambda[j][alpha] << "\t" << deltalambda << endl;
  1005. }
  1006. // Iterate once to stabilize result
  1007. (*this).Iterate_BAE(iter_factor);
  1008. }
  1009. } // ((diffsq > extrap_prec) && (max_iter_extrap > iter_done_here))
  1010. if ((diffsq >= diffsq_ref) || (is_nan(diffsq))) {
  1011. // This procedure has failed. We reset everything to begin values.
  1012. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda[j][alpha] = lambda_ref[j][alpha];
  1013. (*this).Compute_BE();
  1014. diffsq = diffsq_ref;
  1015. }
  1016. return;
  1017. }
  1018. void Heis_Bethe_State::Solve_BAE_with_silk_gloves (DP silk_prec, int max_iter_silk, DP iter_factor)
  1019. {
  1020. // Logic: do iterations, but change only one rapidity at a time.
  1021. // This is slow, and called only if straight_iter, extrap and Newton methods don't work.
  1022. // If this fails, the lambda's are reset to original values, defined as...
  1023. Lambda lambda_ref(chain, base);
  1024. DP diffsq_ref = 1.0;
  1025. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
  1026. diffsq_ref = diffsq;
  1027. // Now begin solving...
  1028. diffsq = 1.0;
  1029. int iter_done_here = 0;
  1030. while ((diffsq > silk_prec) && (max_iter_silk > iter_done_here)) {
  1031. // Find the highest `deviant' rapidity
  1032. int jmax = 0;
  1033. int alphamax = 0;
  1034. DP absBEmax = 0.0;
  1035. for (int j = 0; j < chain.Nstrings; ++j)
  1036. for (int alpha = 0; alpha < base[j]; ++alpha) {
  1037. //cout << j << "\t" << alpha << "\t" << BE[j][alpha] << endl;
  1038. if (fabs(BE[j][alpha]) > absBEmax) {
  1039. jmax = j;
  1040. alphamax = alpha;
  1041. absBEmax = fabs(BE[j][alpha]);
  1042. }
  1043. }
  1044. //cout << "jmax = " << jmax << "\talphamax = " << alphamax << "\t" << lambda[jmax][alphamax] << "\tBE before " << BE[jmax][alphamax] << endl;
  1045. // Now recalculate this max deviant rapidity,
  1046. //cout << lambda[jmax][alphamax] << "\t" << Iterate_BAE (jmax, alphamax) << endl;
  1047. /*
  1048. DP dlambda = 0.0;
  1049. DP prevBEmax = 0.0;
  1050. do {
  1051. dlambda = Iterate_BAE (jmax, alphamax) - lambda[jmax][alphamax];
  1052. lambda[jmax][alphamax] += iter_factor * dlambda;
  1053. prevBEmax = BE[jmax][alphamax];
  1054. (*this).Compute_BE();
  1055. iter_done_here++;
  1056. cout << "jmax = " << jmax << "\talphamax = " << alphamax << "\t" << lambda[jmax][alphamax] << "\t" << dlambda << "\tBE during " << BE[jmax][alphamax] << endl;
  1057. } while (dlambda * dlambda > silk_prec && fabs(BE[jmax][alphamax]) < fabs(prevBEmax) && max_iter_silk > iter_done_here);
  1058. */
  1059. Solve_BAE_bisect (jmax, alphamax, silk_prec, max_iter_silk);
  1060. iter_done_here++;
  1061. //cout << "jmax = " << jmax << "\talphamax = " << alphamax << "\t" << lambda[jmax][alphamax] << "\tBE after " << BE[jmax][alphamax] << endl;
  1062. // and reset all important arrays.
  1063. (*this).Compute_diffsq();
  1064. }
  1065. //cout << "Silk gloves: diffsq from " << diffsq_ref << "\tto " << diffsq << endl;
  1066. if ((diffsq > diffsq_ref) || (is_nan(diffsq))) {
  1067. // This procedure has failed. We reset everything to begin values.
  1068. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda[j][alpha] = lambda_ref[j][alpha];
  1069. (*this).Compute_BE();
  1070. diffsq = diffsq_ref;
  1071. }
  1072. return;
  1073. }
  1074. /*
  1075. void Heis_Bethe_State::BAE_smackdown (DP max_allowed)
  1076. {
  1077. // Re-solves for all rapidities lambda[j][alpha] such that BE[j][alpha]^2/N > max_allowed.
  1078. // Assumes that BE[][] is up-to-date.
  1079. for (int j = 0; j < chain.Nstrings; ++j)
  1080. for (int alpha = 0; alpha < base[j]; ++alpha)
  1081. if (pow(BE[j][alpha], 2.0)/chain.Nsites > max_allowed) (*this).Solve_BAE (j, alpha, max_allowed, 100);
  1082. }
  1083. void Heis_Bethe_State::Solve_BAE_smackdown (DP max_allowed, int maxruns)
  1084. {
  1085. int runs_done = 0;
  1086. (*this).Compute_BE();
  1087. (*this).Compute_diffsq();
  1088. while (diffsq > chain.prec && diffsq > max_allowed && runs_done < maxruns) {
  1089. (*this).BAE_smackdown (max_allowed);
  1090. (*this).Compute_BE();
  1091. (*this).Compute_diffsq();
  1092. runs_done++;
  1093. }
  1094. }
  1095. */
  1096. void Heis_Bethe_State::Iterate_BAE_Newton ()
  1097. {
  1098. // does one step of a Newton method on the rapidities...
  1099. // Assumes that BE[j][alpha] have been computed
  1100. Vect_CX dlambda (0.0, base.Nraptot); // contains delta lambda computed from Newton's method
  1101. SQMat_CX Gaudin (0.0, base.Nraptot);
  1102. Vect_INT indx (base.Nraptot);
  1103. Lambda lambda_ref(chain, base);
  1104. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
  1105. (*this).Build_Reduced_Gaudin_Matrix (Gaudin);
  1106. int index = 0;
  1107. for (int j = 0; j < chain.Nstrings; ++j)
  1108. for (int alpha = 0; alpha < base[j]; ++alpha) {
  1109. dlambda[index] = - BE[j][alpha] * chain.Nsites;
  1110. index++;
  1111. }
  1112. DP d;
  1113. try {
  1114. ludcmp_CX (Gaudin, indx, d);
  1115. lubksb_CX (Gaudin, indx, dlambda);
  1116. }
  1117. catch (Divide_by_zero) {
  1118. diffsq = log(-1.0); // reset to nan to stop Newton method
  1119. return;
  1120. }
  1121. //cout << iter_Newton << "\t" << dlambda << endl;
  1122. // Regularize dlambda: max step is +-1.0 to prevent rapidity flying off into outer space.
  1123. for (int i = 0; i < base.Nraptot; ++i) if (fabs(real(dlambda[i])) > 1.0) dlambda[i] = 0.0;//(real(dlambda[i]) > 0) ? 1.0 : -1.0;
  1124. index = 0;
  1125. for (int j = 0; j < chain.Nstrings; ++j)
  1126. for (int alpha = 0; alpha < base[j]; ++alpha) {
  1127. lambda[j][alpha] = lambda_ref[j][alpha] + real(dlambda[index]);
  1128. //cout << j << "\t" << alpha << "\t" << dlambda[index] << "\t" << lambda_ref[j][alpha] << "\t" << lambda[j][alpha] << endl;
  1129. index++;
  1130. }
  1131. (*this).Compute_BE();
  1132. (*this).Iterate_BAE(1.0);
  1133. (*this).Compute_diffsq();
  1134. // if we've converged, calculate the norm here, since the work has been done...
  1135. if (diffsq < chain.prec) {
  1136. lnnorm = 0.0;
  1137. for (int j = 0; j < base.Nraptot; j++) lnnorm += log(abs(Gaudin[j][j]));
  1138. }
  1139. iter_Newton++;
  1140. return;
  1141. }
  1142. void Heis_Bethe_State::Solve_BAE_Newton (DP Newton_prec, int max_iter_Newton)
  1143. {
  1144. // This function attempts to get convergence diffsq <= Newton_prec in at most max_iter_Newton steps.
  1145. // The results are accepted if diffsq has decreased, otherwise the lambda's are reset to original values, defined as...
  1146. Lambda lambda_ref(chain, base);
  1147. DP diffsq_ref = 1.0;
  1148. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
  1149. diffsq_ref = diffsq;
  1150. // Now begin solving...
  1151. int iter_done_here = 0;
  1152. while ((diffsq > Newton_prec) && (diffsq < 10.0) && (!is_nan(diffsq)) && (iter_done_here < max_iter_Newton)) {
  1153. (*this).Iterate_BAE_Newton();
  1154. iter_done_here++;
  1155. (*this).Iterate_BAE(1.0);
  1156. }
  1157. if ((diffsq > diffsq_ref) || (is_nan(diffsq))) {
  1158. // This procedure has failed. We reset everything to begin values.
  1159. //cout << "Newton: failed, resetting." << "\t" << diffsq << endl;
  1160. for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda[j][alpha] = lambda_ref[j][alpha];
  1161. (*this).Compute_BE();
  1162. diffsq = diffsq_ref;
  1163. }
  1164. return;
  1165. }
  1166. void Heis_Bethe_State::Compute_lnnorm ()
  1167. {
  1168. if (true || lnnorm == -100.0) { // else norm already calculated by Newton method
  1169. // Actually, compute anyway to increase accuracy !
  1170. SQMat_CX Gaudin_Red(base.Nraptot);
  1171. (*this).Build_Reduced_Gaudin_Matrix(Gaudin_Red);
  1172. /*
  1173. cout << endl << "Gaudin matrix: " << endl;
  1174. for (int j = 0; j < Gaudin_Red.size(); ++j) {
  1175. for (int k = 0; k < Gaudin_Red.size(); ++k) cout << Gaudin_Red[j][k] << " ";
  1176. cout << endl;
  1177. }
  1178. cout << endl << endl;
  1179. */
  1180. complex<DP> lnnorm_check = lndet_LU_CX_dstry(Gaudin_Red);
  1181. //cout << "Calculated lnnorm = " << lnnorm_check;
  1182. //lnnorm = real(lndet_LU_CX_dstry(Gaudin_Red));
  1183. lnnorm = real(lnnorm_check);
  1184. }
  1185. return;
  1186. }
  1187. void Heis_Bethe_State::Compute_Momentum ()
  1188. {
  1189. int sum_Ix2 = 0;
  1190. DP sum_M = 0.0;
  1191. for (int j = 0; j < chain.Nstrings; ++j) {
  1192. sum_M += 0.5 * (1.0 + chain.par[j]) * base[j];
  1193. for (int alpha = 0; alpha < base[j]; ++alpha) {
  1194. sum_Ix2 += Ix2[j][alpha];
  1195. }
  1196. }
  1197. iK = (chain.Nsites/2) * int(sum_M + 0.1) - (sum_Ix2/2); // + 0.1: for safety...
  1198. while (iK >= chain.Nsites) iK -= chain.Nsites;
  1199. while (iK < 0) iK += chain.Nsites;
  1200. K = PI * sum_M - PI * sum_Ix2/chain.Nsites;
  1201. while (K >= 2.0*PI) K -= 2.0*PI;
  1202. while (K < 0.0) K += 2.0*PI;
  1203. return;
  1204. }
  1205. void Heis_Bethe_State::Compute_All (bool reset_rapidities) // solves BAE, computes E, K and lnnorm
  1206. {
  1207. (*this).Find_Rapidities (reset_rapidities);
  1208. if (conv == 1) {
  1209. (*this).Compute_Energy ();
  1210. (*this).Compute_Momentum ();
  1211. (*this).Compute_lnnorm ();
  1212. }
  1213. return;
  1214. }
  1215. /*
  1216. bool Heis_Bethe_State::Boost_Momentum (int iKboost)
  1217. {
  1218. if (iKboost == 0) return(true); // done
  1219. Ix2_Offsets offsets_here = offsets;
  1220. bool success = false;
  1221. if (iKboost < 0)
  1222. success = offsets_here.Add_Boxes_From_Lowest(-iKboost, 0); // add boxes in even sectors to decrease iK
  1223. else if (iKboost > 0)
  1224. success = offsets_here.Add_Boxes_From_Lowest(iKboost, 1); // add boxes in odd sectors to increase iK
  1225. if (success) (*this).Set_Ix2_Offsets(offsets_here);
  1226. return(success);
  1227. }
  1228. */
  1229. void Heis_Bethe_State::Set_to_Closest_Matching_Ix2_fixed_Base (const Heis_Bethe_State& StateToMatch)
  1230. {
  1231. // Given a state with given Ix2 distribution, set the Ix2 to closest match.
  1232. // The base of (*this) is fixed, and does not necessarily match that of StateToMatch.
  1233. //cout << "Matching Ix2 for base " << (*this).base.baselabel << " from base " << StateToMatch.base.baselabel << endl;
  1234. if ((*this).chain != StateToMatch.chain)
  1235. ABACUSerror("Heis_Bethe_State::Find_Closest_Matching_Ix2_fixed_Base: trying to match Ix2 for two states with different chains.");
  1236. // Check level by level, match quantum numbers from center up.
  1237. for (int il = 0; il < chain.Nstrings; ++il) {
  1238. // Careful: if parity of Nraps is different, the Ix2 live on different lattices!
  1239. int Ix2shift = ((StateToMatch.base.Nrap[il] - (*this).base.Nrap[il]) % 2);
  1240. if (StateToMatch.base.Nrap[il] >= (*this).base.Nrap[il]) {
  1241. // We match the rapidities from the center towards the sides.
  1242. int ashift = (StateToMatch.base.Nrap[il] - (*this).base.Nrap[il])/2;
  1243. for (int a = 0; a < (*this).base.Nrap[il]; ++a)
  1244. (*this).Ix2[il][a] = StateToMatch.Ix2[il][a + ashift] + Ix2shift;
  1245. }
  1246. else { // There are less Ix2 in StateToMatch than in (*this)
  1247. // We start by filling all the (*this) Ix2 symmetrically from the middle.
  1248. // We thereafter start from the left and identify half of the StateToMatch Ix2 with the leftmost (*this)Ix2
  1249. // and then do the same thing from the right.
  1250. for (int a = 0; a < (*this).base.Nrap[il]; ++a)
  1251. (*this).Ix2[il][a] = -(*this).base.Nrap[il] + 1 + 2*a;
  1252. int nleft = StateToMatch.base.Nrap[il]/2;
  1253. for (int a = 0; a < nleft; ++a)
  1254. if (StateToMatch.Ix2[il][a] - Ix2shift < (*this).Ix2[il][a]) (*this).Ix2[il][a] = StateToMatch.Ix2[il][a] - Ix2shift;
  1255. for (int a = 0; a < StateToMatch.base.Nrap[il] - 1 - nleft; ++a)
  1256. if (StateToMatch.Ix2[il][StateToMatch.base.Nrap[il] - 1 - a] - Ix2shift > (*this).Ix2[il][(*this).base.Nrap[il] - 1 - a])
  1257. (*this).Ix2[il][(*this).base.Nrap[il] - 1 - a] = StateToMatch.Ix2[il][StateToMatch.base.Nrap[il] - 1 - a] - Ix2shift;
  1258. }
  1259. } // for il
  1260. //cout << "StateToMatch:" << endl << StateToMatch << endl << "MatchingState:" << endl << (*this) << endl;
  1261. }
  1262. std::ostream& operator<< (std::ostream& s, const Heis_Bethe_State& state)
  1263. {
  1264. // sends all the state data to output stream
  1265. s << endl << "******** Chain with Delta = " << state.chain.Delta << " Nsites = " << state.chain.Nsites << " Mdown = " << state.base.Mdown
  1266. //<< ": eigenstate with base_id " << state.base_id << ", type_id " << state.type_id << " id " << state.id << " maxid " << state.maxid << endl
  1267. << ": eigenstate with label " << state.label << endl
  1268. << "E = " << state.E << " K = " << state.K << " iK = " << state.iK << " lnnorm = " << state.lnnorm << endl
  1269. << "conv = " << state.conv << " dev = " << state.dev << " iter = " << state.iter << " iter_Newton = " << state.iter_Newton << "\tdiffsq " << state.diffsq << endl;
  1270. for (int j = 0; j < state.chain.Nstrings; ++j) {
  1271. if (state.base.Nrap[j] > 0) {
  1272. s << "Type " << j << " Str_L = " << state.chain.Str_L[j] << " par = " << state.chain.par[j] << " M_j = " << state.base.Nrap[j]
  1273. << " Ix2_infty = " << state.base.Ix2_infty[j] << " Ix2_min = " << state.base.Ix2_min[j] << " Ix2_max = " << state.base.Ix2_max[j] << endl;
  1274. Vect_INT qnumbers(state.base.Nrap[j]);
  1275. Vect_DP rapidities(state.base.Nrap[j]);
  1276. for (int alpha = 0; alpha < state.base.Nrap[j]; ++alpha) {
  1277. qnumbers[alpha] = state.Ix2[j][alpha];
  1278. rapidities[alpha] = state.lambda[j][alpha];
  1279. }
  1280. qnumbers.QuickSort();
  1281. rapidities.QuickSort();
  1282. s << "Ix2 quantum numbers: " << endl;
  1283. for (int alpha = 0; alpha < state.base.Nrap[j]; ++alpha) s << qnumbers[alpha] << " ";
  1284. s << endl;
  1285. s << "Rapidities: " << endl;
  1286. for (int alpha = 0; alpha < state.base.Nrap[j]; ++alpha) s << rapidities[alpha] << " ";
  1287. s << endl;
  1288. }
  1289. }
  1290. s << endl;
  1291. return s;
  1292. }
  1293. } // namespace ABACUS