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_LiebLin.cc 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: TBA_LiebLin.cc
  6. Purpose: TBA for Lieb-Liniger
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. using namespace ABACUS;
  11. namespace ABACUS {
  12. // T = 0 functions
  13. DP LiebLin_a2_kernel (DP c_int, DP lambdadiff)
  14. {
  15. return(c_int/(PI * (lambdadiff * lambdadiff + c_int * c_int)));
  16. }
  17. void Iterate_LiebLin_rho_GS (DP c_int, DP k_F, Root_Density& rho_GS)
  18. {
  19. // Performs an iteration of the TBA equation for the dressed charge:
  20. // First, copy the actual values into the previous ones:
  21. for (int i = 0; i < rho_GS.Npts; ++i) rho_GS.prev_value[i] = rho_GS.value[i];
  22. // Calculate the new values:
  23. DP conv = 0.0;
  24. for (int i = 0; i < rho_GS.Npts; ++i) {
  25. // First, calculate the convolution
  26. conv = 0.0;
  27. for (int j = 0; j < rho_GS.Npts; ++j)
  28. conv += fabs(rho_GS.lambda[j]) > k_F ? 0.0 :
  29. LiebLin_a2_kernel (c_int, rho_GS.lambda[i] - rho_GS.lambda[j])
  30. * rho_GS.prev_value[j] * rho_GS.dlambda[j];
  31. rho_GS.value[i] = fabs(rho_GS.lambda[i]) < k_F ? 1.0/twoPI + conv : 0.0;
  32. }
  33. // Calculate the sum of differences:
  34. rho_GS.diff = 0.0;
  35. for (int i = 0; i < rho_GS.Npts; ++i)
  36. rho_GS.diff += fabs(rho_GS.value[i] - rho_GS.prev_value[i]);
  37. return;
  38. }
  39. Root_Density LiebLin_rho_GS (DP c_int, DP k_F, DP lambdamax, int Npts, DP req_prec)
  40. {
  41. // This function returns a Root_Density object corresponding to the ground state
  42. // density function of the Lieb-Liniger model.
  43. Root_Density rho_GS(Npts, lambdamax);
  44. // We now attempt to find a solution...
  45. do {
  46. Iterate_LiebLin_rho_GS (c_int, k_F, rho_GS);
  47. } while (rho_GS.diff > req_prec);
  48. return(rho_GS);
  49. }
  50. DP Density_GS (Root_Density& rho_GS)
  51. {
  52. DP n = 0.0;
  53. for (int i = 0; i < rho_GS.Npts; ++i) n += rho_GS.value[i] * rho_GS.dlambda[i];
  54. return(n);
  55. }
  56. DP k_F_given_n (DP c_int, DP n, DP lambdamax, int Npts, DP req_prec)
  57. {
  58. DP k_F = 1.0;
  59. DP dk_F = k_F;
  60. Root_Density rho_GS = LiebLin_rho_GS (c_int, k_F, lambdamax, Npts, req_prec);
  61. DP n_found = Density_GS (rho_GS);
  62. do {
  63. dk_F *= 0.7;
  64. k_F += (n_found < n) ? dk_F : -dk_F;
  65. rho_GS = LiebLin_rho_GS (c_int, k_F, lambdamax, Npts, req_prec);
  66. n_found = Density_GS (rho_GS);
  67. } while (fabs(dk_F) > req_prec && dk_F > 1.0/Npts
  68. && fabs(n - n_found) > req_prec && fabs(n - n_found) > 1.0/Npts);
  69. return(k_F);
  70. }
  71. void Iterate_LiebLin_Z_GS (DP c_int, DP k_F, Root_Density& Z_GS)
  72. {
  73. // Performs an iteration of the TBA equation for the dressed charge:
  74. // First, copy the actual values into the previous ones:
  75. for (int i = 0; i < Z_GS.Npts; ++i) Z_GS.prev_value[i] = Z_GS.value[i];
  76. // Calculate the new values:
  77. DP conv = 0.0;
  78. for (int i = 0; i < Z_GS.Npts; ++i) {
  79. // First, calculate the convolution
  80. conv = 0.0;
  81. for (int j = 0; j < Z_GS.Npts; ++j)
  82. conv += fabs(Z_GS.lambda[j]) > k_F ? 0.0 :
  83. LiebLin_a2_kernel (c_int, Z_GS.lambda[i] - Z_GS.lambda[j])
  84. * Z_GS.prev_value[j] * Z_GS.dlambda[j];
  85. Z_GS.value[i] = 1.0 + conv;
  86. }
  87. // Calculate the sum of differences:
  88. Z_GS.diff = 0.0;
  89. for (int i = 0; i < Z_GS.Npts; ++i)
  90. Z_GS.diff += fabs(Z_GS.value[i] - Z_GS.prev_value[i]);
  91. return;
  92. }
  93. Root_Density LiebLin_Z_GS (DP c_int, DP k_F, DP lambdamax, int Npts, DP req_prec)
  94. {
  95. // This function returns a Root_Density object corresponding to the ground state
  96. // dressed charge function of the Lieb-Liniger model.
  97. Root_Density Z_GS(Npts, lambdamax);
  98. // We now attempt to find a solution...
  99. do {
  100. Iterate_LiebLin_Z_GS (c_int, k_F, Z_GS);
  101. } while (Z_GS.diff > req_prec);
  102. return(Z_GS);
  103. }
  104. void Iterate_LiebLin_Fbackflow_GS (DP c_int, DP k_F, DP lambda, Root_Density& F_GS)
  105. {
  106. // Performs an iteration of the TBA equation for the backflow:
  107. // First, copy the actual values into the previous ones:
  108. for (int i = 0; i < F_GS.Npts; ++i) F_GS.prev_value[i] = F_GS.value[i];
  109. // Calculate the new values:
  110. DP conv = 0.0;
  111. for (int i = 0; i < F_GS.Npts; ++i) {
  112. // First, calculate the convolution
  113. conv = 0.0;
  114. for (int j = 0; j < F_GS.Npts; ++j)
  115. conv += fabs(F_GS.lambda[j]) > k_F ? 0.0 :
  116. LiebLin_a2_kernel (c_int, F_GS.lambda[i] - F_GS.lambda[j])
  117. * F_GS.prev_value[j] * F_GS.dlambda[j];
  118. F_GS.value[i] = 0.5 + atan((F_GS.lambda[i] - lambda)/c_int)/PI + conv;
  119. }
  120. // Calculate the sum of differences:
  121. F_GS.diff = 0.0;
  122. for (int i = 0; i < F_GS.Npts; ++i)
  123. F_GS.diff += fabs(F_GS.value[i] - F_GS.prev_value[i]);
  124. return;
  125. }
  126. Root_Density LiebLin_Fbackflow_GS (DP c_int, DP k_F, DP lambdamax, DP lambda, int Npts, DP req_prec)
  127. {
  128. // This function returns a Root_Density object corresponding to the ground state
  129. // F backflow for parameter \lambda.
  130. Root_Density F_GS(Npts, lambdamax);
  131. // We now attempt to find a solution...
  132. do {
  133. Iterate_LiebLin_Fbackflow_GS (c_int, k_F, lambda, F_GS);
  134. } while (F_GS.diff > req_prec);
  135. return(F_GS);
  136. }
  137. // Finite T functions:
  138. LiebLin_TBA_Solution::LiebLin_TBA_Solution (DP c_int_ref, DP mu_ref, DP kBT_ref, DP req_diff, int Max_Secs)
  139. : c_int(c_int_ref), mu(mu_ref), kBT(kBT_ref)
  140. {
  141. epsilon = LiebLin_epsilon_TBA (c_int, mu, kBT, req_diff, Max_Secs);
  142. depsilon_dmu = LiebLin_depsilon_dmu_TBA (c_int, mu, kBT, req_diff, Max_Secs, epsilon);
  143. rho = LiebLin_rho_TBA (kBT, epsilon, depsilon_dmu);
  144. rhoh = LiebLin_rhoh_TBA (kBT, epsilon, depsilon_dmu);
  145. nbar = LiebLin_nbar_TBA (rho);
  146. ebar = LiebLin_ebar_TBA (rho);
  147. sbar = LiebLin_sbar_TBA (rho, rhoh);
  148. }
  149. LiebLin_TBA_Solution LiebLin_TBA_Solution_fixed_nbar_ebar (DP c_int, DP nbar_required, DP ebar_required,
  150. DP req_diff, int Max_Secs)
  151. {
  152. // This function finds the TBA solution for a required nbar and ebar (mean energy).
  153. // We here try to triangulate the temperature; the chemical potential is triangulated
  154. // using the function LiebLin_TBA_Solution_fixed_nbar.
  155. // FIRST VERSION
  156. DP lnkBT = 1.0;
  157. DP dlnkBT = 1.0;
  158. LiebLin_TBA_Solution tbasol = LiebLin_TBA_Solution_fixed_nbar (c_int, nbar_required, exp(lnkBT), req_diff, Max_Secs);
  159. DP lnkBT_prev = lnkBT;
  160. DP ebar_prev = LiebLin_ebar_TBA (tbasol.rho);
  161. DP dlnkBT_prev, debardlnkBT;
  162. lnkBT += dlnkBT;
  163. tbasol = LiebLin_TBA_Solution_fixed_nbar (c_int, nbar_required, exp(lnkBT), req_diff, Max_Secs);
  164. int niter = 1;
  165. while (fabs(tbasol.ebar - ebar_required) > req_diff) {
  166. dlnkBT_prev = dlnkBT;
  167. lnkBT_prev = lnkBT;
  168. // Calculate a new kBT based on earlier data:
  169. debardlnkBT = (tbasol.ebar - ebar_prev)/dlnkBT;
  170. ebar_prev = tbasol.ebar;
  171. dlnkBT = (ebar_required - tbasol.ebar)/debardlnkBT;
  172. if (fabs(dlnkBT) > fabs(dlnkBT_prev)) dlnkBT *= fabs(dlnkBT_prev/dlnkBT); // make sure we don't blow up.
  173. lnkBT += dlnkBT;
  174. tbasol = LiebLin_TBA_Solution_fixed_nbar(c_int, nbar_required, exp(lnkBT), req_diff, Max_Secs);
  175. niter++;
  176. }
  177. return(tbasol);
  178. }
  179. LiebLin_TBA_Solution LiebLin_TBA_Solution_fixed_nbar (DP c_int, DP nbar_required, DP kBT, DP req_diff, int Max_Secs)
  180. {
  181. // Find the required mu. Provide some initial guess.
  182. DP mu = 2.0;
  183. DP dmu = 1.0;
  184. LiebLin_TBA_Solution tbasol = LiebLin_TBA_Solution(c_int, mu, kBT, req_diff, Max_Secs);
  185. DP mu_prev = mu;
  186. DP nbar_prev = tbasol.nbar;
  187. DP dmu_prev, dnbardmu;
  188. mu += dmu;
  189. tbasol = LiebLin_TBA_Solution(c_int, mu, kBT, req_diff, Max_Secs);
  190. int niter = 1;
  191. while (fabs(tbasol.nbar - nbar_required) > req_diff) {
  192. dmu_prev = dmu;
  193. mu_prev = mu;
  194. // Calculate a new mu based on earlier data:
  195. dnbardmu = (tbasol.nbar - nbar_prev)/dmu;
  196. nbar_prev = tbasol.nbar;
  197. dmu = (nbar_required - tbasol.nbar)/dnbardmu;
  198. if (fabs(dmu) > 2.0 * fabs(dmu_prev)) dmu = 2.0*dmu * fabs(dmu_prev/dmu); // make sure we don't blow up.
  199. mu += dmu;
  200. tbasol = LiebLin_TBA_Solution(c_int, mu, kBT, req_diff, Max_Secs);
  201. niter++;
  202. }
  203. return(tbasol);
  204. }
  205. DP Refine_LiebLin_epsilon_TBA (Root_Density& epsilon, DP c_int, DP mu, DP kBT, DP refine_fraction)
  206. {
  207. // This function replaces Set by a new set with more points, where
  208. // Tln(...) needs to be evaluated more precisely.
  209. // The return value is the max of delta_tni found.
  210. // First, calculate the needed Tln...
  211. Vect<DP> Tln1plusemineps(epsilon.Npts);
  212. for (int i = 0; i < epsilon.Npts; ++i) {
  213. Tln1plusemineps[i] = epsilon.value[i] > 0.0 ?
  214. kBT * (epsilon.value[i] < 24.0 * kBT ? log(1.0 + exp(-epsilon.value[i]/kBT)) : exp(-epsilon.value[i]/kBT))
  215. : -epsilon.value[i] + kBT * log (1.0 + exp(epsilon.value[i]/kBT));
  216. }
  217. // Now find the achieved delta_tni
  218. DP max_delta_tni_dlambda = 0.0;
  219. DP sum_delta_tni_dlambda = 0.0;
  220. Vect<DP> tni(0.0, epsilon.Npts);
  221. Vect<DP> tni_ex(0.0, epsilon.Npts);
  222. DP measure_factor = 0.0;
  223. for (int i = 1; i < epsilon.Npts - 1; ++i) {
  224. measure_factor = (epsilon.value[i] > 0.0 ? exp(-epsilon.value[i]/kBT)/(1.0 + exp(-epsilon.value[i]/kBT))
  225. : 1.0/(1.0 + exp(epsilon.value[i]/kBT)));
  226. tni[i] = measure_factor * epsilon.value[i];
  227. tni_ex[i] = measure_factor * (epsilon.value[i-1] * (epsilon.lambda[i+1] - epsilon.lambda[i])
  228. + epsilon.value[i+1] * (epsilon.lambda[i] - epsilon.lambda[i-1]))
  229. /(epsilon.lambda[i+1] - epsilon.lambda[i-1]);
  230. max_delta_tni_dlambda = ABACUS::max(max_delta_tni_dlambda, fabs(tni[i] - tni_ex[i]) * epsilon.dlambda[i]);
  231. sum_delta_tni_dlambda += fabs(tni[i] - tni_ex[i]) * epsilon.dlambda[i];
  232. }
  233. // We now determine the locations where we need to add points
  234. Vect<bool> need_new_point_around(false, epsilon.Npts);
  235. int nr_new_points_needed = 0;
  236. for (int i = 1; i < epsilon.Npts - 1; ++i) {
  237. if (fabs(tni[i] - tni_ex[i]) * epsilon.dlambda[i] > (1.0 - refine_fraction) * max_delta_tni_dlambda) {
  238. need_new_point_around[i] = true;
  239. // Do also the symmetric ones... Require need...[n][i] = need...[n][Npts - 1 - i]
  240. need_new_point_around[epsilon.Npts - 1 - i] = true;
  241. }
  242. }
  243. for (int i = 0; i < epsilon.Npts; ++i)
  244. if (need_new_point_around[i]) nr_new_points_needed++;
  245. // Now insert the new points between existing points:
  246. // Update all data via interpolation:
  247. Root_Density epsilon_before_update = epsilon;
  248. epsilon = Root_Density(epsilon_before_update.Npts + nr_new_points_needed, epsilon_before_update.lambdamax);
  249. int nr_pts_added = 0;
  250. for (int i = 0; i < epsilon_before_update.Npts; ++i) {
  251. if (!need_new_point_around[i]) {
  252. epsilon.lambda[i + nr_pts_added] = epsilon_before_update.lambda[i];
  253. epsilon.dlambda[i + nr_pts_added] = epsilon_before_update.dlambda[i];
  254. epsilon.value[i + nr_pts_added] = epsilon_before_update.value[i];
  255. }
  256. else if (need_new_point_around[i]) {
  257. epsilon.lambda[i + nr_pts_added] = epsilon_before_update.lambda[i] - 0.25 * epsilon_before_update.dlambda[i];
  258. epsilon.dlambda[i + nr_pts_added] = 0.5 * epsilon_before_update.dlambda[i];
  259. epsilon.value[i + nr_pts_added] = epsilon_before_update.Return_Value(epsilon.lambda[i + nr_pts_added]);
  260. nr_pts_added++;
  261. epsilon.lambda[i + nr_pts_added] = epsilon_before_update.lambda[i] + 0.25 * epsilon_before_update.dlambda[i];
  262. epsilon.dlambda[i + nr_pts_added] = 0.5 * epsilon_before_update.dlambda[i];
  263. epsilon.value[i + nr_pts_added] = epsilon_before_update.Return_Value(epsilon.lambda[i + nr_pts_added]);
  264. }
  265. }
  266. if (nr_pts_added != nr_new_points_needed) {
  267. cout << nr_pts_added << "\t" << nr_new_points_needed << endl;
  268. ABACUSerror("Wrong counting of new points in Insert_new_points.");
  269. }
  270. // Check boundary values; if too different from value_infty, extend limits
  271. if (exp(-epsilon.value[0]/kBT) > 0.001 * max_delta_tni_dlambda) {
  272. int nr_pts_to_add_left = epsilon.Npts/10;
  273. int nr_pts_to_add_right = epsilon.Npts/10;
  274. Root_Density epsilon_before_update = epsilon;
  275. epsilon = Root_Density(epsilon_before_update.Npts + nr_pts_to_add_left + nr_pts_to_add_right,
  276. epsilon_before_update.lambdamax + nr_pts_to_add_left * epsilon_before_update.dlambda[0]
  277. + nr_pts_to_add_right * epsilon_before_update.dlambda[epsilon_before_update.Npts - 1]);
  278. // Initialize points added on left
  279. for (int i = 0; i < nr_pts_to_add_left; ++i) {
  280. epsilon.lambda[i] = epsilon_before_update.lambda[i] + (i - nr_pts_to_add_left) * epsilon_before_update.dlambda[0];
  281. epsilon.dlambda[i] = epsilon_before_update.dlambda[0];
  282. epsilon.value[i] = epsilon_before_update.value[0];
  283. }
  284. // Initialize middle (unchanged) points
  285. for (int i = 0; i < epsilon_before_update.Npts; ++i) {
  286. epsilon.lambda[nr_pts_to_add_left + i] = epsilon_before_update.lambda[i];
  287. epsilon.dlambda[nr_pts_to_add_left + i] = epsilon_before_update.dlambda[i];
  288. epsilon.value[nr_pts_to_add_left + i] = epsilon_before_update.value[i];
  289. }
  290. // Initialize points added on right
  291. for (int i = 0; i < nr_pts_to_add_right; ++i) {
  292. epsilon.lambda[nr_pts_to_add_left + epsilon_before_update.Npts + i] =
  293. epsilon_before_update.lambda[epsilon_before_update.Npts - 1]
  294. + (i+1) * epsilon_before_update.dlambda[epsilon_before_update.Npts - 1];
  295. epsilon.dlambda[nr_pts_to_add_left + epsilon_before_update.Npts + i] =
  296. epsilon_before_update.dlambda[epsilon_before_update.Npts - 1];
  297. epsilon.value[nr_pts_to_add_left + epsilon_before_update.Npts + i] =
  298. epsilon_before_update.value[epsilon_before_update.Npts - 1];
  299. }
  300. }
  301. return(sum_delta_tni_dlambda);
  302. }
  303. // epsilon for a given mu:
  304. Root_Density LiebLin_epsilon_TBA (DP c_int, DP mu, DP kBT, DP req_diff, int Max_Secs)
  305. {
  306. clock_t StartTime = clock();
  307. int Max_CPU_ticks = 98 * (Max_Secs - 0) * CLOCKS_PER_SEC/100;
  308. // give 30 seconds to wrap up, assume we time to 2% accuracy.
  309. // Set basic precision needed:
  310. DP running_prec = 1.0;
  311. DP refine_fraction = 0.5; // value fraction of points to be refined
  312. DP lambdamax_init = 10.0 * sqrt(ABACUS::max(1.0, kBT + mu));
  313. // such that exp(-(lambdamax^2 - mu - Omega)/T) <~ machine_eps
  314. int Npts = 50;
  315. Root_Density epsilon(Npts, lambdamax_init);
  316. // Initiate the function:
  317. for (int i = 0; i < epsilon.Npts; ++i) {
  318. epsilon.value[i] = epsilon.lambda[i] * epsilon.lambda[i] - mu;
  319. epsilon.prev_value[i] = epsilon.value[i];
  320. }
  321. clock_t StopTime = clock();
  322. int CPU_ticks = StopTime - StartTime;
  323. int ncycles = 0;
  324. int niter_tot = 0;
  325. DP previous_running_prec;
  326. DP oneoverpi = 1.0/PI;
  327. DP oneoverc = 1.0/c_int;
  328. do {
  329. StartTime = clock();
  330. // The running precision is an estimate of the accuracy of the free energy integral.
  331. // Refine... returns sum_delta_tni_dlambda, so running prec is estimated as...
  332. previous_running_prec = running_prec;
  333. running_prec = Refine_LiebLin_epsilon_TBA (epsilon, c_int, mu, kBT, refine_fraction);
  334. running_prec = ABACUS::min(running_prec, previous_running_prec);
  335. // Now iterate to convergence for given discretization
  336. int niter = 0;
  337. int niter_max = ncycles == 0 ? 300 : 300;
  338. do {
  339. StartTime = clock();
  340. // Iterate the TBA equation for epsilon:
  341. Vect<DP> Tln1plusemineps(epsilon.Npts);
  342. for (int i = 0; i < epsilon.Npts; ++i) {
  343. Tln1plusemineps[i] = epsilon.value[i] > 0.0 ?
  344. kBT * (epsilon.value[i] < 24.0 * kBT
  345. ? log(1.0 + exp(-epsilon.value[i]/kBT))
  346. : exp(-epsilon.value[i]/kBT) * (1.0 - 0.5 * exp(-epsilon.value[i]/kBT)))
  347. :
  348. -epsilon.value[i] + kBT * (-epsilon.value[i] < 24.0 * kBT
  349. ? log (1.0 + exp(epsilon.value[i]/kBT))
  350. : exp(epsilon.value[i]/kBT) * (1.0 - 0.5 * exp(epsilon.value[i]/kBT)));
  351. // Keep previous rapidities:
  352. epsilon.prev_value[i] = epsilon.value[i];
  353. }
  354. Vect<DP> a_2_Tln_conv(epsilon.Npts);
  355. for (int i = 0; i < epsilon.Npts; ++i) {
  356. a_2_Tln_conv[i] = 0.0;
  357. for (int j = 0; j < epsilon.Npts; ++j)
  358. a_2_Tln_conv[i] +=
  359. oneoverpi * (atan(oneoverc * (epsilon.lambda[i] - epsilon.lambda[j] + 0.5 * epsilon.dlambda[j]))
  360. - atan(oneoverc * (epsilon.lambda[i] - epsilon.lambda[j]
  361. - 0.5 * epsilon.dlambda[j]))) * Tln1plusemineps[j];
  362. } // a_2_Tln_conv is now calculated
  363. // Reconstruct the epsilon function:
  364. for (int i = 0; i < epsilon.Npts; ++i) {
  365. epsilon.value[i] = pow(epsilon.lambda[i], 2.0) - mu;
  366. // Add the convolution:
  367. epsilon.value[i] -= a_2_Tln_conv[i];
  368. // Include some damping:
  369. epsilon.value[i] = 0.1 * epsilon.prev_value[i] + 0.9 * epsilon.value[i];
  370. }
  371. niter++;
  372. // epsilon is now fully iterated.
  373. // Calculate the diff:
  374. epsilon.diff = 0.0;
  375. for (int i = 0; i < epsilon.Npts; ++i)
  376. epsilon.diff += epsilon.dlambda[i] *
  377. (epsilon.value[i] > 0.0 ?
  378. exp(-epsilon.value[i]/kBT)/(1.0 + exp(-epsilon.value[i]/kBT)) : 1.0/(1.0 + exp(epsilon.value[i]/kBT)))
  379. * fabs(epsilon.value[i] - epsilon.prev_value[i]);
  380. StopTime = clock();
  381. CPU_ticks += StopTime - StartTime;
  382. } while (niter < 5 || niter < niter_max && CPU_ticks < Max_CPU_ticks && epsilon.diff > 0.1*running_prec);
  383. ncycles++;
  384. niter_tot += niter;
  385. } // do cycles
  386. while (ncycles < 5 || running_prec > req_diff && CPU_ticks < Max_CPU_ticks);
  387. return(epsilon);
  388. }
  389. // depsilon/dmu for a given mu
  390. Root_Density LiebLin_depsilon_dmu_TBA (DP c_int, DP mu, DP kBT, DP req_diff, int Max_Secs, const Root_Density& epsilon)
  391. {
  392. clock_t StartTime = clock();
  393. int Max_CPU_ticks = 98 * (Max_Secs - 0) * CLOCKS_PER_SEC/100;
  394. // give 30 seconds to wrap up, assume we time to 2% accuracy.
  395. Root_Density depsilon_dmu = epsilon;
  396. // Initiate the functions:
  397. for (int i = 0; i < depsilon_dmu.Npts; ++i) {
  398. depsilon_dmu.value[i] = -1.0;
  399. depsilon_dmu.prev_value[i] = depsilon_dmu.value[i];
  400. }
  401. clock_t StopTime = clock();
  402. int CPU_ticks = StopTime - StartTime;
  403. int niter = 0;
  404. int niter_max = 1000;
  405. DP oneoverpi = 1.0/PI;
  406. DP oneoverc = 1.0/c_int;
  407. do {
  408. StartTime = clock();
  409. // Iterate the TBA equation for depsilon_dmu:
  410. Vect<DP> depsover1plusepluseps(depsilon_dmu.Npts);
  411. for (int i = 0; i < depsilon_dmu.Npts; ++i) {
  412. depsover1plusepluseps[i] = epsilon.value[i] > 0.0 ?
  413. depsilon_dmu.value[i] * exp(-epsilon.value[i]/kBT)/(1.0 + exp(-epsilon.value[i]/kBT)) :
  414. depsilon_dmu.value[i]/(1.0 + exp(epsilon.value[i]/kBT));
  415. // Keep previous rapidities:
  416. depsilon_dmu.prev_value[i] = depsilon_dmu.value[i];
  417. }
  418. Vect<DP> a_2_depsover1plusepluseps_conv(depsilon_dmu.Npts);
  419. for (int i = 0; i < depsilon_dmu.Npts; ++i) {
  420. a_2_depsover1plusepluseps_conv[i] = 0.0;
  421. for (int j = 0; j < depsilon_dmu.Npts; ++j)
  422. a_2_depsover1plusepluseps_conv[i] +=
  423. oneoverpi * (atan(oneoverc * (epsilon.lambda[i] - epsilon.lambda[j] + 0.5 * epsilon.dlambda[j]))
  424. - atan(oneoverc * (epsilon.lambda[i] - epsilon.lambda[j] - 0.5 * epsilon.dlambda[j])))
  425. * depsover1plusepluseps[j];
  426. }
  427. // Reconstruct the depsilon_dmu function:
  428. for (int i = 0; i < epsilon.Npts; ++i) {
  429. depsilon_dmu.value[i] = -1.0;
  430. // Add the convolution:
  431. depsilon_dmu.value[i] += a_2_depsover1plusepluseps_conv[i];
  432. // Include some damping:
  433. depsilon_dmu.value[i] = 0.1 * depsilon_dmu.prev_value[i] + 0.9 * depsilon_dmu.value[i];
  434. }
  435. niter++;
  436. // depsilon_dmu is now fully iterated.
  437. // Calculate the diff:
  438. depsilon_dmu.diff = 0.0;
  439. for (int i = 0; i < depsilon_dmu.Npts; ++i)
  440. depsilon_dmu.diff += fabs(depsilon_dmu.value[i] - depsilon_dmu.prev_value[i]);
  441. StopTime = clock();
  442. CPU_ticks += StopTime - StartTime;
  443. } while (niter < 5 || niter < niter_max && CPU_ticks < Max_CPU_ticks && depsilon_dmu.diff > req_diff);
  444. return(depsilon_dmu);
  445. }
  446. Root_Density LiebLin_rho_TBA (DP kBT, const Root_Density& epsilon, const Root_Density& depsilon_dmu)
  447. {
  448. Root_Density rho = epsilon;
  449. for (int i = 0; i < epsilon.Npts; ++i)
  450. rho.value[i] = -(1.0/twoPI) * depsilon_dmu.value[i]
  451. * (epsilon.value[i] > 0.0 ?
  452. exp(-epsilon.value[i]/kBT)/(1.0 + exp(-epsilon.value[i]/kBT)) :
  453. 1.0/(1.0 + exp(epsilon.value[i]/kBT)));
  454. return(rho);
  455. }
  456. Root_Density LiebLin_rhoh_TBA (DP kBT, const Root_Density& epsilon, const Root_Density& depsilon_dmu)
  457. {
  458. Root_Density rhoh = epsilon;
  459. for (int i = 0; i < epsilon.Npts; ++i)
  460. rhoh.value[i] = -(1.0/twoPI) * depsilon_dmu.value[i]
  461. * (epsilon.value[i] > 0.0 ?
  462. 1.0/(1.0 + exp(-epsilon.value[i]/kBT)) :
  463. exp(epsilon.value[i]/kBT)/(1.0 + exp(epsilon.value[i]/kBT)));
  464. return(rhoh);
  465. }
  466. DP LiebLin_nbar_TBA (const Root_Density& rho)
  467. {
  468. DP nbar = 0.0;
  469. for (int i = 0; i < rho.Npts; ++i) nbar += rho.value[i] * rho.dlambda[i];
  470. return(nbar);
  471. }
  472. DP LiebLin_ebar_TBA (const Root_Density& rho)
  473. {
  474. DP ebar = 0.0;
  475. for (int i = 0; i < rho.Npts; ++i) ebar += rho.lambda[i] * rho.lambda[i] * rho.value[i] * rho.dlambda[i];
  476. return(ebar);
  477. }
  478. DP LiebLin_sbar_TBA (const Root_Density& rho, const Root_Density& rhoh)
  479. {
  480. DP sbar = 0.0;
  481. for (int i = 0; i < rho.Npts; ++i)
  482. sbar += ((rho.value[i] + rhoh.value[i]) * log(rho.value[i] + rhoh.value[i])
  483. - rho.value[i] * log(rho.value[i]+1.0e-30) - rhoh.value[i] * log(rhoh.value[i]+1.0e-30)) * rho.dlambda[i];
  484. return(sbar);
  485. }
  486. LiebLin_Bethe_State Discretized_LiebLin_Bethe_State (DP c_int, DP L, int N, const Root_Density& rho)
  487. {
  488. // This function returns the Bethe state at finite size which is
  489. // the closest approximation to the continuum density rho(lambda)
  490. // Check that the provided rho has the expected filling
  491. DP rho_check = 0.0;
  492. for (int i = 0; i < rho.Npts; ++i) rho_check += L * rho.value[i] * rho.dlambda[i];
  493. // The integral of rho should be between N - 0.5 and N + 0.5 for the algorithm to work
  494. if (fabs(rho_check - N) > 0.5)
  495. cout << "WARNING: integral of rho != N in Discretized_LiebLin_Bethe_State, "
  496. << "consistent discretization is impossible. \int rho dlambda = "
  497. << rho_check << ", N = " << N << ", L = " << L << ", N/L = " << N/L << endl;
  498. // Using the counting function
  499. // c(\lambda) \equiv L \int_{-\infty}^\lambda d\lambda' \rho(\lambda'),
  500. // we seek to find lambda[i] such that c(lambda[i]) = i + 0.5, i = 0...N-1
  501. DP integral = 0.0;
  502. DP integral_prev = 0.0;
  503. int Nfound = 0;
  504. Vect<DP> lambda_found(0.0, N);
  505. int nr_to_set = 0;
  506. for (int i = 0; i < rho.Npts; ++i) {
  507. // Note: integral_prev is the counting function
  508. // at rapidity rho.lambda[i-1] + 0.5* rho.dlambda[i-1]
  509. // which equals rho.lambda[i] - 0.5* rho.dlambda[i]
  510. integral_prev = integral;
  511. // Note: integral gives the value of the counting function
  512. // at rapidity rho.lambda[i] + 0.5* rho.dlambda[i]
  513. integral += L * rho.value[i] * rho.dlambda[i];
  514. // We already have filled the RHS of the counting equation up to Nfound - 0.5.
  515. // Therefore, the additional number found is
  516. nr_to_set = floor(integral + 0.5 - Nfound);
  517. // if (nr_to_set > 1)
  518. // cout << "WARNING: setting " << nr_to_set << " rapidities in one step in Discretized_LiebLin_Bethe_State" << endl;
  519. for (int n = 1; n <= nr_to_set; ++n) {
  520. // Solve c(lambda[Nfound]) = Nfound + 0.5 for lambda[Nfound],
  521. // namely (using linear interpolation)
  522. // integral_prev + (lambda - rho.lambda[i-1] - 0.5*rho.dlambda[i-1]) * (integral - integra_prev)/rho.dlambda[i] = Nfound + 0.5
  523. lambda_found[Nfound] = rho.lambda[i-1] + 0.5*rho.dlambda[i-1] + (Nfound + 0.5 - integral_prev) * rho.dlambda[i]/(integral - integral_prev);
  524. Nfound++;
  525. }
  526. }
  527. Vect<DP> lambda(N);
  528. // Fill up the found rapidities:
  529. for (int il = 0; il < abacus::min(N, Nfound); ++il) lambda[il] = lambda_found[il];
  530. // If there are missing ones, put them at the end; ideally, this should never be called
  531. for (int il = Nfound; il < N; ++il) lambda[il] = lambda_found[Nfound-1] + (il - Nfound + 1) * (lambda_found[Nfound-1] - lambda_found[Nfound-2]);
  532. // Calculate quantum numbers: 2\pi * (L lambda + \sum_j 2 atan((lambda - lambda_j)/c)) = I_j
  533. // Use rounding.
  534. Vect<int> Ix2(N);
  535. for (int i = 0; i < N; ++i) {
  536. DP sum = 0.0;
  537. for (int j = 0; j < N; ++j) sum += 2.0 * atan((lambda[i] - lambda[j])/c_int);
  538. // For N is even/odd, we want to round off to the nearest odd/even integer.
  539. Ix2[i] = 2.0 * floor((L* lambda[i] + sum)/twoPI + 0.5 * (N%2 ? 1 : 2)) + (N%2) - 1;
  540. }
  541. // Check that the Ix2 are all ordered
  542. for (int i = 0; i < N-1; ++i) if (Ix2[i] >= Ix2[i+1]) cout << "Alert: Ix2 not ordered around index i = " << i << ": Ix2[i] = " << Ix2[i] << "\tIx2[i+1] = " << Ix2[i+1] << endl;
  543. // Check that the quantum numbers are all distinct:
  544. bool allOK = false;
  545. while (!allOK) {
  546. for (int i = 0; i < N-1; ++i) if (Ix2[i] == Ix2[i+1] && Ix2[i] < 0) Ix2[i] -= 2;
  547. for (int i = 1; i < N; ++i) if (Ix2[i] == Ix2[i-1] && Ix2[i] > 0) Ix2[i] += 2;
  548. allOK = true;
  549. for (int i = 0; i < N-1; ++i) if (Ix2[i] == Ix2[i+1]) allOK = false;
  550. }
  551. LiebLin_Bethe_State rhostate(c_int, L, N);
  552. rhostate.Ix2 = Ix2;
  553. rhostate.Compute_All(true);
  554. return(rhostate);
  555. }
  556. } // namespace ABACUS