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 45KB

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