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.

TBA_XXZ.cc 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: TBA_XXZ.cc
  6. Purpose: TBA for the gapless XXZ antiferromagnet.
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. using namespace ABACUS;
  11. namespace ABACUS {
  12. // First, define some useful kernels:
  13. DP XXZ_phi1_kernel (DP zeta, DP lambda)
  14. {
  15. return(2.0 * atan(tanh(lambda)/tan(0.5*zeta)));
  16. }
  17. DP XXZ_phi2_kernel (DP zeta, DP lambda)
  18. {
  19. return(2.0 * atan(tanh(lambda)/tan(zeta)));
  20. }
  21. DP XXZ_a1_kernel (DP sinzeta, DP coszeta, DP lambda)
  22. {
  23. DP expmin2abslambda = exp(-2.0 * fabs(lambda));
  24. DP answer = sinzeta * expmin2abslambda
  25. /(PI * (0.5 * (1.0 + expmin2abslambda * expmin2abslambda) - coszeta * expmin2abslambda));
  26. return(answer);
  27. }
  28. DP XXZ_da1dlambda_kernel (DP sinzeta, DP coszeta, DP lambda)
  29. {
  30. DP expmin2abslambda = exp(-2.0 * fabs(lambda));
  31. DP signlambda = lambda >= 0.0 ? 1.0 : -1.0;
  32. DP answer = -sinzeta * signlambda * expmin2abslambda * (1.0 - expmin2abslambda * expmin2abslambda)
  33. /(PI * pow((0.5 * (1.0 + expmin2abslambda * expmin2abslambda)
  34. - coszeta * expmin2abslambda), 2.0));
  35. return(answer);
  36. }
  37. DP XXZ_a2_kernel (DP sin2zeta, DP cos2zeta, DP lambda)
  38. {
  39. DP expmin2abslambda = exp(-2.0 * fabs(lambda));
  40. DP answer = sin2zeta * expmin2abslambda
  41. /(PI * (0.5 * (1.0 + expmin2abslambda * expmin2abslambda) - cos2zeta * expmin2abslambda));
  42. return(answer);
  43. }
  44. void Iterate_XXZ_rhotot_GS (DP zeta, DP B, Root_Density& rhotot_GS)
  45. {
  46. // Performs an iteration of the TBA equation for rhotot_GS:
  47. // First, copy the actual values into the previous ones:
  48. for (int i = 0; i < rhotot_GS.Npts; ++i) rhotot_GS.prev_value[i] = rhotot_GS.value[i];
  49. // Calculate the new values:
  50. DP conv = 0.0;
  51. DP sinzeta = sin(zeta);
  52. DP sin2zeta = sin(2.0*zeta);
  53. DP coszeta = cos(zeta);
  54. DP cos2zeta = cos(2.0*zeta);
  55. for (int i = 0; i < rhotot_GS.Npts; ++i) {
  56. // First, calculate the convolution
  57. conv = 0.0;
  58. for (int j = 0; j < rhotot_GS.Npts; ++j)
  59. conv += fabs(rhotot_GS.lambda[j]) > B ? 0.0 :
  60. XXZ_a2_kernel (sin2zeta, cos2zeta, rhotot_GS.lambda[i] - rhotot_GS.lambda[j])
  61. * rhotot_GS.prev_value[j] * rhotot_GS.dlambda[j];
  62. rhotot_GS.value[i] = XXZ_a1_kernel(sinzeta, coszeta, rhotot_GS.lambda[i]) - conv;
  63. }
  64. // Calculate the sum of differences:
  65. rhotot_GS.diff = 0.0;
  66. for (int i = 0; i < rhotot_GS.Npts; ++i)
  67. rhotot_GS.diff += fabs(rhotot_GS.value[i] - rhotot_GS.prev_value[i]);
  68. return;
  69. }
  70. Root_Density XXZ_rhotot_GS (DP Delta, DP B, DP lambdamax, int Npts, DP req_prec)
  71. {
  72. // This function returns a Root_Density object corresponding to the ground state
  73. // root distribution of the XXZ model.
  74. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_rhotot_GS.");
  75. DP zeta = acos(Delta);
  76. Root_Density rhotot_GS(Npts, lambdamax);
  77. // We now attempt to find a solution...
  78. int niter = 0;
  79. do {
  80. Iterate_XXZ_rhotot_GS (zeta, B, rhotot_GS);
  81. niter ++;
  82. } while (rhotot_GS.diff > req_prec);
  83. return(rhotot_GS);
  84. }
  85. DP Return_GS_Sz_tot_value (DP B, Root_Density& rhotot_GS)
  86. {
  87. DP integral = 0.0;
  88. for (int i = 0; i < rhotot_GS.Npts; ++i)
  89. integral += fabs(rhotot_GS.lambda[i]) > B ? 0.0 : rhotot_GS.value[i] * rhotot_GS.dlambda[i];
  90. return(0.5 - integral);
  91. }
  92. void Iterate_XXZ_eps_GS (DP zeta, DP Hz, Root_Density& eps_GS)
  93. {
  94. // Performs an iteration of the TBA equation for eps_GS:
  95. // First, copy the actual values into the previous ones:
  96. for (int i = 0; i < eps_GS.Npts; ++i) eps_GS.prev_value[i] = eps_GS.value[i];
  97. // Calculate the new values:
  98. DP conv = 0.0;
  99. DP sinzeta = sin(zeta);
  100. DP sin2zeta = sin(2.0*zeta);
  101. DP coszeta = cos(zeta);
  102. DP cos2zeta = cos(2.0*zeta);
  103. for (int i = 0; i < eps_GS.Npts; ++i) {
  104. // First, calculate the convolution
  105. conv = 0.0;
  106. for (int j = 0; j < eps_GS.Npts; ++j)
  107. conv += eps_GS.prev_value[j] > 0.0 ? 0.0 :
  108. XXZ_a2_kernel (sin2zeta, cos2zeta, eps_GS.lambda[i] - eps_GS.lambda[j])
  109. * eps_GS.prev_value[j] * eps_GS.dlambda[j];
  110. eps_GS.value[i] = Hz - PI * sinzeta * XXZ_a1_kernel(sinzeta, coszeta, eps_GS.lambda[i]) - conv;
  111. }
  112. // Calculate the sum of differences:
  113. eps_GS.diff = 0.0;
  114. for (int i = 0; i < eps_GS.Npts; ++i)
  115. eps_GS.diff += fabs(eps_GS.value[i] - eps_GS.prev_value[i]);
  116. return;
  117. }
  118. Root_Density XXZ_eps_GS (DP Delta, DP Hz, DP lambdamax, int Npts, DP req_prec)
  119. {
  120. // This function returns a Root_Density object corresponding to the ground state
  121. // epsilon function of the XXZ model.
  122. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_eps_GS.");
  123. DP zeta = acos(Delta);
  124. Root_Density eps_GS(Npts, lambdamax);
  125. // We now attempt to find a solution...
  126. int niter = 0;
  127. do {
  128. Iterate_XXZ_eps_GS (zeta, Hz, eps_GS);
  129. niter++;
  130. } while (eps_GS.diff > req_prec);
  131. return(eps_GS);
  132. }
  133. void Iterate_XXZ_depsdlambda_GS (DP zeta, DP B, Root_Density& depsdlambda_GS)
  134. {
  135. // Performs an iteration of the TBA equation for depsdlambda_GS:
  136. // First, copy the actual values into the previous ones:
  137. for (int i = 0; i < depsdlambda_GS.Npts; ++i) depsdlambda_GS.prev_value[i] = depsdlambda_GS.value[i];
  138. // Calculate the new values:
  139. DP conv = 0.0;
  140. DP sinzeta = sin(zeta);
  141. DP sin2zeta = sin(2.0*zeta);
  142. DP coszeta = cos(zeta);
  143. DP cos2zeta = cos(2.0*zeta);
  144. for (int i = 0; i < depsdlambda_GS.Npts; ++i) {
  145. // First, calculate the convolution
  146. conv = 0.0;
  147. for (int j = 0; j < depsdlambda_GS.Npts; ++j)
  148. conv += fabs(depsdlambda_GS.lambda[j]) > B ? 0.0 :
  149. XXZ_a2_kernel (sin2zeta, cos2zeta, depsdlambda_GS.lambda[i] - depsdlambda_GS.lambda[j])
  150. * depsdlambda_GS.prev_value[j] * depsdlambda_GS.dlambda[j];
  151. depsdlambda_GS.value[i] = -PI * sinzeta * XXZ_da1dlambda_kernel(sinzeta, coszeta, depsdlambda_GS.lambda[i]) - conv;
  152. }
  153. // Calculate the sum of differences:
  154. depsdlambda_GS.diff = 0.0;
  155. for (int i = 0; i < depsdlambda_GS.Npts; ++i)
  156. depsdlambda_GS.diff += fabs(depsdlambda_GS.value[i] - depsdlambda_GS.prev_value[i]);
  157. return;
  158. }
  159. Root_Density XXZ_depsdlambda_GS (DP Delta, DP B, DP lambdamax, int Npts, DP req_prec)
  160. {
  161. // This function returns a Root_Density object corresponding to the ground state
  162. // (d/d\lambda) epsilon function of the XXZ model.
  163. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_rho_GS.");
  164. DP zeta = acos(Delta);
  165. Root_Density depsdlambda_GS(Npts, lambdamax);
  166. // We now attempt to find a solution...
  167. int niter = 0;
  168. do {
  169. Iterate_XXZ_depsdlambda_GS (zeta, B, depsdlambda_GS);
  170. niter++;
  171. } while (depsdlambda_GS.diff > req_prec);
  172. return(depsdlambda_GS);
  173. }
  174. void Iterate_XXZ_b2BB_lambda_B (DP zeta, DP B, Root_Density& b2BB)
  175. {
  176. // Calculates the vector corresponding to b2BB (lambda,B)
  177. // First, copy the actual values into the previous ones:
  178. for (int i = 0; i < b2BB.Npts; ++i) b2BB.prev_value[i] = b2BB.value[i];
  179. // Calculate the new values:
  180. DP conv = 0.0;
  181. DP sin2zeta = sin(2.0*zeta);
  182. DP cos2zeta = cos(2.0*zeta);
  183. for (int i = 0; i < b2BB.Npts; ++i) {
  184. if (fabs(b2BB.lambda[i]) > B) b2BB.value[i] = 0.0;
  185. else {
  186. // First, calculate the convolution
  187. conv = 0.0;
  188. for (int j = 0; j < b2BB.Npts; ++j)
  189. conv += fabs(b2BB.lambda[j]) > B ? 0.0 :
  190. XXZ_a2_kernel (sin2zeta, cos2zeta, b2BB.lambda[i] - b2BB.lambda[j])
  191. * b2BB.prev_value[j] * b2BB.dlambda[j];
  192. b2BB.value[i] = -XXZ_a2_kernel(sin2zeta, cos2zeta, b2BB.lambda[i] - B)
  193. - conv;
  194. }
  195. }
  196. // Calculate the sum of differences:
  197. b2BB.diff = 0.0;
  198. for (int i = 0; i < b2BB.Npts; ++i)
  199. b2BB.diff += fabs(b2BB.value[i] - b2BB.prev_value[i]);
  200. return;
  201. }
  202. Root_Density XXZ_b2BB_lambda_B (DP Delta, DP B, DP lambdamax, int Npts, DP req_prec)
  203. {
  204. // This function returns a Root_Density object corresponding to the inverse
  205. // kernel b2BB (lambda, B) used in Kbar function.
  206. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_Kbackflow_GS.");
  207. DP zeta = acos(Delta);
  208. Root_Density b2BB_lambda_B(Npts, lambdamax);
  209. // We now attempt to find a solution...
  210. int niter = 0;
  211. do {
  212. Iterate_XXZ_b2BB_lambda_B (zeta, B, b2BB_lambda_B);
  213. niter++;
  214. } while (b2BB_lambda_B.diff > req_prec);
  215. return(b2BB_lambda_B);
  216. }
  217. void Iterate_XXZ_b2BB_lambda_lambdap (DP zeta, DP B, DP lambdap, Root_Density& b2BB)
  218. {
  219. // Calculates the vector corresponding to b2BB (lambda,lambdap)
  220. // First, copy the actual values into the previous ones:
  221. for (int i = 0; i < b2BB.Npts; ++i) b2BB.prev_value[i] = b2BB.value[i];
  222. // Calculate the new values:
  223. DP conv = 0.0;
  224. DP sin2zeta = sin(2.0*zeta);
  225. DP cos2zeta = cos(2.0*zeta);
  226. for (int i = 0; i < b2BB.Npts; ++i) {
  227. if (fabs(b2BB.lambda[i]) > B) b2BB.value[i] = 0.0;
  228. else {
  229. // First, calculate the convolution
  230. conv = 0.0;
  231. for (int j = 0; j < b2BB.Npts; ++j)
  232. conv += fabs(b2BB.lambda[j]) > B ? 0.0 :
  233. XXZ_a2_kernel (sin2zeta, cos2zeta, b2BB.lambda[i] - b2BB.lambda[j])
  234. * b2BB.prev_value[j] * b2BB.dlambda[j];
  235. b2BB.value[i] = -XXZ_a2_kernel(sin2zeta, cos2zeta, b2BB.lambda[i] - lambdap)
  236. - conv;
  237. }
  238. }
  239. // Calculate the sum of differences:
  240. b2BB.diff = 0.0;
  241. for (int i = 0; i < b2BB.Npts; ++i)
  242. b2BB.diff += fabs(b2BB.value[i] - b2BB.prev_value[i]);
  243. return;
  244. }
  245. Root_Density XXZ_b2BB_lambda_lambdap (DP Delta, DP B, DP lambdap, DP lambdamax, int Npts, DP req_prec)
  246. {
  247. // This function returns a Root_Density object corresponding to the inverse
  248. // kernel b2BB (lambda, lambdap) used in Kbar function.
  249. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_Kbackflow_GS.");
  250. DP zeta = acos(Delta);
  251. Root_Density b2BB_lambda_lambdap(Npts, lambdamax);
  252. // We now attempt to find a solution...
  253. int niter = 0;
  254. do {
  255. Iterate_XXZ_b2BB_lambda_lambdap (zeta, B, lambdap, b2BB_lambda_lambdap);
  256. niter++;
  257. } while (b2BB_lambda_lambdap.diff > req_prec);
  258. return(b2BB_lambda_lambdap);
  259. }
  260. void Iterate_XXZ_Kbackflow_GS (DP zeta, DP B, DP lambda_p, DP lambda_h, Root_Density& Kbackflow_GS)
  261. {
  262. // Performs an iteration of the TBA equation for Kbackflow_GS:
  263. // First, copy the actual values into the previous ones:
  264. for (int i = 0; i < Kbackflow_GS.Npts; ++i) Kbackflow_GS.prev_value[i] = Kbackflow_GS.value[i];
  265. // Calculate the new values:
  266. DP conv = 0.0;
  267. DP sin2zeta = sin(2.0*zeta);
  268. DP cos2zeta = cos(2.0*zeta);
  269. for (int i = 0; i < Kbackflow_GS.Npts; ++i) {
  270. if (false && fabs(Kbackflow_GS.lambda[i]) > B) Kbackflow_GS.value[i] = 0.0;
  271. else {
  272. // First, calculate the convolution
  273. conv = 0.0;
  274. for (int j = 0; j < Kbackflow_GS.Npts; ++j)
  275. conv += fabs(Kbackflow_GS.lambda[j]) > B ? 0.0 :
  276. XXZ_a2_kernel (sin2zeta, cos2zeta, Kbackflow_GS.lambda[i] - Kbackflow_GS.lambda[j])
  277. * Kbackflow_GS.prev_value[j] * Kbackflow_GS.dlambda[j];
  278. Kbackflow_GS.value[i] = -XXZ_a2_kernel(sin2zeta, cos2zeta, Kbackflow_GS.lambda[i] - lambda_p)
  279. + XXZ_a2_kernel(sin2zeta, cos2zeta, Kbackflow_GS.lambda[i] - lambda_h) - conv;
  280. }
  281. }
  282. // Calculate the sum of differences:
  283. Kbackflow_GS.diff = 0.0;
  284. for (int i = 0; i < Kbackflow_GS.Npts; ++i)
  285. Kbackflow_GS.diff += fabs(Kbackflow_GS.value[i] - Kbackflow_GS.prev_value[i]);
  286. return;
  287. }
  288. Root_Density XXZ_Kbackflow_GS (DP Delta, DP B, DP lambdamax, DP lambda_p, DP lambda_h, int Npts, DP req_prec)
  289. {
  290. // This function returns a Root_Density object corresponding to the ground state
  291. // backflow function of the XXZ model.
  292. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_Kbackflow_GS.");
  293. DP zeta = acos(Delta);
  294. Root_Density Kbackflow_GS(Npts, lambdamax);
  295. // We now attempt to find a solution...
  296. int niter = 0;
  297. do {
  298. Iterate_XXZ_Kbackflow_GS (zeta, B, lambda_p, lambda_h, Kbackflow_GS);
  299. niter++;
  300. } while (Kbackflow_GS.diff > req_prec);
  301. return(Kbackflow_GS);
  302. }
  303. void Iterate_XXZ_Fbackflow_GS (DP zeta, DP B, DP lambda_p, DP lambda_h, Root_Density& Fbackflow_GS)
  304. {
  305. // Performs an iteration of the TBA equation for Fbackflow_GS:
  306. // First, copy the actual values into the previous ones:
  307. for (int i = 0; i < Fbackflow_GS.Npts; ++i) Fbackflow_GS.prev_value[i] = Fbackflow_GS.value[i];
  308. // Calculate the new values:
  309. DP conv = 0.0;
  310. DP sin2zeta = sin(2.0*zeta);
  311. DP cos2zeta = cos(2.0*zeta);
  312. for (int i = 0; i < Fbackflow_GS.Npts; ++i) {
  313. if (fabs(Fbackflow_GS.lambda[i]) > B) Fbackflow_GS.value[i] = 0.0;
  314. else {
  315. // First, calculate the convolution
  316. conv = 0.0;
  317. for (int j = 0; j < Fbackflow_GS.Npts; ++j)
  318. conv += fabs(Fbackflow_GS.lambda[j]) > B ? 0.0 :
  319. XXZ_a2_kernel (sin2zeta, cos2zeta, Fbackflow_GS.lambda[i] - Fbackflow_GS.lambda[j])
  320. * Fbackflow_GS.prev_value[j] * Fbackflow_GS.dlambda[j];
  321. Fbackflow_GS.value[i] = (-XXZ_phi2_kernel(zeta, Fbackflow_GS.lambda[i] - lambda_p)
  322. + XXZ_phi2_kernel(zeta, Fbackflow_GS.lambda[i] - lambda_h))/twoPI - conv;
  323. }
  324. }
  325. // Calculate the sum of differences:
  326. Fbackflow_GS.diff = 0.0;
  327. for (int i = 0; i < Fbackflow_GS.Npts; ++i)
  328. Fbackflow_GS.diff += fabs(Fbackflow_GS.value[i] - Fbackflow_GS.prev_value[i]);
  329. return;
  330. }
  331. Root_Density XXZ_Fbackflow_GS (DP Delta, DP B, DP lambdamax, DP lambda_p, DP lambda_h, int Npts, DP req_prec)
  332. {
  333. // This function returns a Root_Density object corresponding to the ground state
  334. // F backflow function of the XXZ model.
  335. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_Fbackflow_GS.");
  336. DP zeta = acos(Delta);
  337. Root_Density Fbackflow_GS(Npts, lambdamax);
  338. // We now attempt to find a solution...
  339. int niter = 0;
  340. do {
  341. Iterate_XXZ_Fbackflow_GS (zeta, B, lambda_p, lambda_h, Fbackflow_GS);
  342. niter++;
  343. } while (Fbackflow_GS.diff > req_prec);
  344. return(Fbackflow_GS);
  345. }
  346. void Iterate_XXZ_Z_GS (DP zeta, DP B, Root_Density& Z_GS)
  347. {
  348. // Performs an iteration of the TBA equation for the dressed charge:
  349. // First, copy the actual values into the previous ones:
  350. for (int i = 0; i < Z_GS.Npts; ++i) Z_GS.prev_value[i] = Z_GS.value[i];
  351. // Calculate the new values:
  352. DP conv = 0.0;
  353. DP sin2zeta = sin(2.0*zeta);
  354. DP cos2zeta = cos(2.0*zeta);
  355. for (int i = 0; i < Z_GS.Npts; ++i) {
  356. // First, calculate the convolution
  357. conv = 0.0;
  358. for (int j = 0; j < Z_GS.Npts; ++j)
  359. conv += fabs(Z_GS.lambda[j]) > B ? 0.0 :
  360. XXZ_a2_kernel (sin2zeta, cos2zeta, Z_GS.lambda[i] - Z_GS.lambda[j])
  361. * Z_GS.prev_value[j] * Z_GS.dlambda[j];
  362. Z_GS.value[i] = 1.0 - conv;
  363. }
  364. // Calculate the sum of differences:
  365. Z_GS.diff = 0.0;
  366. for (int i = 0; i < Z_GS.Npts; ++i)
  367. Z_GS.diff += fabs(Z_GS.value[i] - Z_GS.prev_value[i]);
  368. return;
  369. }
  370. Root_Density XXZ_Z_GS (DP Delta, DP B, DP lambdamax, int Npts, DP req_prec)
  371. {
  372. // This function returns a Root_Density object corresponding to the ground state
  373. // dressed charge function of the XXZ model.
  374. if (Delta >= 1.0 || Delta <= 0.0) ABACUSerror("Delta out of bounds in XXZ_Z_GS.");
  375. DP zeta = acos(Delta);
  376. Root_Density Z_GS(Npts, lambdamax);
  377. // We now attempt to find a solution...
  378. do {
  379. Iterate_XXZ_Z_GS (zeta, B, Z_GS);
  380. } while (Z_GS.diff > req_prec);
  381. return(Z_GS);
  382. }
  383. } // namespace ABACUS