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_2CBG.cc 44KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: TBA_2CBG.cc
  6. Purpose: solves the TBA equations for the 2-component Bose gas
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. using namespace ABACUS;
  11. namespace ABACUS {
  12. /********************* 2CBG specific *******************/
  13. DP Asymptotic_2CBG_epsilon (int n, DP Omega, DP kBT)
  14. {
  15. return(2.0 * Omega * n + kBT * log(pow((1.0 - exp(-2.0 * (n + 1.0) * Omega/kBT))
  16. /(1.0 - exp(-2.0 * Omega/kBT)), 2.0) - exp(-2.0 * n * Omega/kBT)));
  17. }
  18. void Set_2CBG_Asymptotics (Root_Density_Set& TBA_Set, DP mu, DP Omega, DP kBT)
  19. {
  20. TBA_Set.epsilon[0].Set_Asymptotics (pow(TBA_Set.epsilon[0].lambdamax, 2.0) - mu - Omega);
  21. for (int n = 1; n < TBA_Set.ntypes; ++n) {
  22. TBA_Set.epsilon[n].Set_Asymptotics (Asymptotic_2CBG_epsilon(n, Omega, kBT));
  23. }
  24. }
  25. void Set_2CBG_deps_dchempot_Asymptotics (int option, const Root_Density_Set& Set, Root_Density_Set& DSet,
  26. DP mu, DP Omega, DP kBT)
  27. {
  28. // option == 0: deps/dmu
  29. // option == 1: deps/dOmega
  30. DP zeroasymptote = -1.0;
  31. DP em2OoT = exp(-2.0 * Omega/kBT);
  32. for (int n = 1; n < DSet.ntypes; ++n) {
  33. if (option == 0) DSet.epsilon[n].Set_Asymptotics (0.0);
  34. else if (option == 1)
  35. DSet.epsilon[n].Set_Asymptotics (2.0 * (1.0 - pow(em2OoT, n+1.0))
  36. * (n * (1.0 - pow(em2OoT, n+2.0)) - (n + 2.0) * em2OoT * (1.0 - pow(em2OoT, DP(n))))
  37. /((1.0 - em2OoT) * (1.0 - pow(em2OoT, DP(n))) * (1.0 - pow(em2OoT, n + 2.0))));
  38. zeroasymptote += DSet.epsilon[n].value_infty
  39. * exp(-Set.epsilon[n].value_infty/kBT)/(1.0 + exp(-Set.epsilon[n].value_infty/kBT));
  40. }
  41. // For n > nmax sum in RHS of BE for epsilon, assuming epsilon_n = epsilon_n^\infty in those cases:
  42. // Remember: nmax in notes is Set.ntypes - 1.
  43. zeroasymptote -= option == 0 ? 0.0
  44. : 2.0 * ((Set.ntypes + 1.0) * exp(-2.0 * (Set.ntypes + 1.0) * Omega/kBT)
  45. /(1.0 - exp(-2.0 * (Set.ntypes + 1.0) * Omega/kBT))
  46. - Set.ntypes * exp(-2.0 * Set.ntypes * Omega/kBT)/(1.0 - exp(-2.0 * Set.ntypes * Omega/kBT)));
  47. DSet.epsilon[0].Set_Asymptotics (zeroasymptote);
  48. return;
  49. }
  50. void Initiate_2CBG_TBA_Functions (Root_Density_Set& TBA_Set, DP mu, DP Omega)
  51. {
  52. for (int i = 0; i < TBA_Set.epsilon[0].Npts; ++i) {
  53. TBA_Set.epsilon[0].value[i] = TBA_Set.epsilon[0].lambda[i] * TBA_Set.epsilon[0].lambda[i] - mu - Omega;
  54. TBA_Set.epsilon[0].prev_value[i] = TBA_Set.epsilon[0].value[i];
  55. }
  56. for (int n = 1; n < TBA_Set.ntypes; ++n) {
  57. for (int i = 0; i < TBA_Set.epsilon[n].Npts; ++i)
  58. TBA_Set.epsilon[n].value[i] = TBA_Set.epsilon[n].value_infty;
  59. }
  60. }
  61. void Initiate_2CBG_deps_dchempot_Functions (Root_Density_Set& DSet)
  62. {
  63. for (int n = 0; n < DSet.ntypes; ++n) {
  64. for (int i = 0; i < DSet.epsilon[n].Npts; ++i)
  65. DSet.epsilon[n].value[i] = DSet.epsilon[n].value_infty;
  66. }
  67. }
  68. void Iterate_2CBG_TBAE (Root_Density_Set& Set, Vect<Vect<Vect_DP> >& a_n_dlambda, Vect<Vect<Vect_DP> >& fmin_dlambda,
  69. Vect<Vect<Vect_DP> >& fplus_dlambda, DP c_int, DP mu, DP Omega, DP kBT)
  70. {
  71. // Produces a new Root_Density_Set from a previous iteration.
  72. // Does NOT add types or change Npts, lambdamax values.
  73. // First define some useful functions:
  74. Vect<Vect_DP> Tln1plusemineps(Set.ntypes);
  75. Vect_DP Tln1pluseminepsinfty(Set.ntypes);
  76. for (int n = 0; n < Set.ntypes; ++n) {
  77. Tln1plusemineps[n] = Vect_DP (0.0, Set.epsilon[n].Npts);
  78. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  79. Tln1plusemineps[n][i] = Set.epsilon[n].value[i] > 0.0 ?
  80. kBT * (Set.epsilon[n].value[i] < 24.0 * kBT ? log(1.0 + exp(-Set.epsilon[n].value[i]/kBT))
  81. : exp(-Set.epsilon[n].value[i]/kBT))
  82. :
  83. -Set.epsilon[n].value[i] + kBT * (-Set.epsilon[n].value[i] < 24.0 * kBT
  84. ? log (1.0 + exp(Set.epsilon[n].value[i]/kBT)) : exp(Set.epsilon[n].value[i]/kBT));
  85. // Keep previous rapidities:
  86. Set.epsilon[n].prev_value[i] = Set.epsilon[n].value[i];
  87. }
  88. Tln1pluseminepsinfty[n] = kBT * (Set.epsilon[n].value_infty < 24.0 * kBT
  89. ? log(1.0 + exp(-Set.epsilon[n].value_infty/kBT)) : exp(-Set.epsilon[n].value_infty/kBT));
  90. }
  91. // Now do the necessary convolutions for epsilon == epsilon[0].
  92. // For each value of lambda, do the convolutions:
  93. // Careful: the lambda's used for lambda (index i) are those of epsilon[0], the lambda' (index j) are for epsilon[n] !!
  94. Vect<Vect_DP> a_n_Tln_conv(Set.ntypes);
  95. for (int n = 0; n < Set.ntypes; ++n) {
  96. a_n_Tln_conv[n] = Vect_DP (0.0, Set.epsilon[0].Npts);
  97. Vect_DP f(0.0, Set.epsilon[n].Npts);
  98. for (int i = 0; i < Set.epsilon[0].Npts; ++i) {
  99. a_n_Tln_conv[n][i] = 0.0;
  100. for (int j = 0; j < Set.epsilon[n].Npts; ++j) a_n_Tln_conv[n][i] += Tln1plusemineps[n][j] * a_n_dlambda[i][n][j];
  101. // Add alpha curvature terms: VERY COSTLY, remove for now
  102. /*
  103. for (int j = 1; j < Set.epsilon[n].Npts - 1; ++j)
  104. a_n_Tln_conv[n][i] += (1.0/12.0) * pow(Set.epsilon[n].dlambda[j], 3.0)
  105. * ((Tln1plusemineps[n][j+1] * a_n_dlambda[i][n][j+1]
  106. - Tln1plusemineps[n][j] * a_n_dlambda[i][n][j])/(Set.epsilon[n].lambda[j+1] - Set.epsilon[n].lambda[j])
  107. - (Tln1plusemineps[n][j] * a_n_dlambda[i][n][j]
  108. - Tln1plusemineps[n][j-1] * a_n_dlambda[i][n][j-1])/(Set.epsilon[n].lambda[j] - Set.epsilon[n].lambda[j-1]))
  109. /(Set.epsilon[n].lambda[j+1] - Set.epsilon[n].lambda[j-1]);
  110. */
  111. } // for (int i ...
  112. } // for (int n... We now have all the a_n * Tln... at our disposal.
  113. // For n > nmax sum in RHS of BE for epsilon, assuming epsilon_n = epsilon_n^\infty in those cases:
  114. // Remember: nmax = Set.ntypes - 1
  115. DP Smaxsum = kBT * log((1.0 - exp(-2.0 * (Set.ntypes + 1.0) * Omega/kBT))/(1.0 - exp(-2.0 * Set.ntypes * Omega/kBT)));
  116. // Reconstruct the epsilon[0] function:
  117. for (int i = 0; i < Set.epsilon[0].Npts; ++i) {
  118. Set.epsilon[0].value[i] = pow(Set.epsilon[0].lambda[i], 2.0) - mu - Omega;
  119. // Add the convolutions:
  120. for (int n = 0; n < Set.ntypes; ++n)
  121. Set.epsilon[0].value[i] -= a_n_Tln_conv[n][i];
  122. // Add the asymptotic parts of convolutions:
  123. for (int n = 1; n < Set.ntypes; ++n)
  124. Set.epsilon[0].value[i] -= Tln1pluseminepsinfty[n]
  125. * (1.0 - (atan((Set.epsilon[n].lambdamax - Set.epsilon[0].lambda[i])/(0.5 * n * c_int))
  126. + atan((Set.epsilon[n].lambdamax + Set.epsilon[0].lambda[i])/(0.5 * n * c_int)))/PI);
  127. // Add the leftover summation for species n > nmax, assuming epsilon_n = epsilon_n^\infty in those cases:
  128. Set.epsilon[0].value[i] -= Smaxsum;
  129. // Include some damping:
  130. Set.epsilon[0].value[i] = 0.1 * Set.epsilon[0].prev_value[i] + 0.9 * Set.epsilon[0].value[i];
  131. // No need to force boundaries here, epsilon[0] is inherently stable.
  132. }
  133. // epsilon[0] is now fully iterated.
  134. // Now do the remaining epsilons:
  135. for (int n = 1; n < Set.ntypes; ++n) {
  136. Vect_DP f_Tln_conv_min (0.0, Set.epsilon[n].Npts); // 'down' convolution
  137. Vect_DP f_Tln_conv_plus (0.0, Set.epsilon[n].Npts); // 'up' convolution
  138. Vect_DP fmin(0.0, Set.epsilon[n-1].Npts);
  139. Vect_DP fplus(0.0, Set.epsilon[ABACUS::min(n+1, Set.ntypes - 1)].Npts);
  140. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  141. f_Tln_conv_min[i] = 0.0;
  142. f_Tln_conv_plus[i] = 0.0;
  143. // 'down' convolutions
  144. if (n == 1)
  145. for (int j = 0; j < Set.epsilon[0].Npts; ++j)
  146. f_Tln_conv_min[i] += Tln1plusemineps[0][j] * fmin_dlambda[n][i][j];
  147. else for (int j = 0; j < Set.epsilon[n - 1].Npts; ++j)
  148. f_Tln_conv_min[i] += (Set.epsilon[n-1].prev_value[j] - Set.epsilon[n-1].value_infty
  149. + Tln1plusemineps[n-1][j] - Tln1pluseminepsinfty[n-1])
  150. * fmin_dlambda[n][i][j];
  151. // 'up' convolutions
  152. if (n < Set.ntypes - 1)
  153. for (int j = 0; j < Set.epsilon[n+1].Npts; ++j)
  154. f_Tln_conv_plus[i] += (Set.epsilon[n+1].prev_value[j] - Set.epsilon[n+1].value_infty
  155. + Tln1plusemineps[n+1][j] - Tln1pluseminepsinfty[n+1])
  156. * fplus_dlambda[n][i][j];
  157. else f_Tln_conv_plus[i] = 0.0;
  158. // Do some damping:
  159. Set.epsilon[n].value[i] = 0.1 * Set.epsilon[n].prev_value[i]
  160. + 0.9 * (Set.epsilon[n].value_infty + f_Tln_conv_min[i] + f_Tln_conv_plus[i]);
  161. // Force boundary values to asymptotes: force boundary 10 points on each side
  162. if (i < 10)
  163. Set.epsilon[n].value[i] = (1.0 - 0.1 * i) * Set.epsilon[n].value_infty + 0.1 * i * Set.epsilon[n].value[i];
  164. if (i > Set.epsilon[n].Npts - 11)
  165. Set.epsilon[n].value[i] = (1.0 - 0.1 * (Set.epsilon[n].Npts-1 - i)) * Set.epsilon[n].value_infty
  166. + 0.1 * (Set.epsilon[n].Npts-1 - i) * Set.epsilon[n].value[i];
  167. } // for (int i = 0...
  168. } // for (int n = 1...
  169. // All functions have now been iterated.
  170. // Now calculate diff:
  171. DP eps0i = 0.0;
  172. DP eps1i = 0.0;
  173. Set.diff = 0.0;
  174. for (int n = 0; n < Set.ntypes; ++n) {
  175. Set.epsilon[n].diff = 0.0;
  176. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  177. // Measure based on delta f/delta epsilon:
  178. if (n == 0)
  179. Set.epsilon[n].diff += Set.epsilon[n].dlambda[i] *
  180. (Set.epsilon[0].value[i] > 0.0 ?
  181. exp(-Set.epsilon[0].value[i]/kBT)/(1.0 + exp(-Set.epsilon[0].value[i]/kBT)) : 1.0/(1.0 + exp(Set.epsilon[0].value[i]/kBT)))
  182. * fabs(Set.epsilon[n].value[i] - Set.epsilon[n].prev_value[i]);
  183. else {
  184. eps0i = Set.epsilon[0].Return_Value(Set.epsilon[n].lambda[i]);
  185. eps1i = Set.epsilon[1].Return_Value(Set.epsilon[n].lambda[i]);
  186. Set.epsilon[n].diff += Set.epsilon[n].dlambda[i] *
  187. // Logic: simple 1/2 cascade
  188. (eps0i > 0.0 ? exp(-eps0i/kBT)/(1.0 + exp(-eps0i/kBT)) : 1.0/(1.0 + exp(eps0i/kBT)))
  189. * pow(0.5, n) //* (exp(-eps1i/kBT)/(1.0 + exp(-eps1i/kBT)))
  190. * fabs(Set.epsilon[n].value[i] - Set.epsilon[n].prev_value[i]);
  191. }
  192. }
  193. Set.diff += Set.epsilon[n].diff;
  194. }
  195. return;
  196. }
  197. void Iterate_and_Extrapolate_2CBG_TBAE (Root_Density_Set& Set, Vect<Root_Density_Set>& IterSet,
  198. Vect<Vect<Vect_DP> >& a_n_dlambda, Vect<Vect<Vect_DP> >& fmin_dlambda,
  199. Vect<Vect<Vect_DP> >& fplus_dlambda, DP c_int, DP mu, DP Omega, DP kBT)
  200. {
  201. int nfit = IterSet.size();
  202. for (int ifit = 0; ifit < nfit; ++ifit) {
  203. Iterate_2CBG_TBAE (Set, a_n_dlambda, fmin_dlambda, fplus_dlambda, c_int, mu, Omega, kBT);
  204. IterSet[ifit] = Set;
  205. }
  206. // Now extrapolate each value to infinite nr of iterations:
  207. Vect_DP density(nfit);
  208. Vect_DP oneoverP(nfit);
  209. DP deltalambda = 0.0;
  210. for (int ifit = 0; ifit < nfit; ++ifit) oneoverP[ifit] = 1.0/(1.0 + ifit*ifit);
  211. for (int n = 0; n < Set.ntypes; ++n)
  212. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  213. for (int ifit = 0; ifit < nfit; ++ifit) density[ifit] = IterSet[ifit].epsilon[n].value[i];
  214. polint (oneoverP, density, 0.0, Set.epsilon[n].value[i], deltalambda);
  215. }
  216. // Now iterate a few times to stabilize:
  217. for (int iint = 0; iint < 2; ++iint)
  218. Iterate_2CBG_TBAE(Set, a_n_dlambda, fmin_dlambda, fplus_dlambda, c_int, mu, Omega, kBT);
  219. return;
  220. }
  221. DP Refine_2CBG_Set (Root_Density_Set& Set, DP c_int, DP mu, DP Omega, DP kBT, DP refine_fraction)
  222. {
  223. // This function replaces Set by a new set with more points, where
  224. // Tln(...) needs to be evaluated more precisely.
  225. // The return value is the max of delta_tni found.
  226. // First, calculate the needed Tln...
  227. Vect<Vect_DP> Tln1plusemineps(Set.ntypes);
  228. Vect_DP Tln1pluseminepsinfty(Set.ntypes);
  229. for (int n = 0; n < Set.ntypes; ++n) {
  230. Tln1plusemineps[n] = Vect_DP (0.0, Set.epsilon[n].Npts);
  231. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  232. Tln1plusemineps[n][i] = Set.epsilon[n].value[i] > 0.0 ?
  233. kBT * (Set.epsilon[n].value[i] < 24.0 * kBT
  234. ? log(1.0 + exp(-Set.epsilon[n].value[i]/kBT)) : exp(-Set.epsilon[n].value[i]/kBT))
  235. : -Set.epsilon[n].value[i] + kBT * log (1.0 + exp(Set.epsilon[n].value[i]/kBT));
  236. }
  237. Tln1pluseminepsinfty[n] = kBT * (Set.epsilon[n].value_infty < 24.0 * kBT ?
  238. log(1.0 + exp(-Set.epsilon[n].value_infty/kBT)) : exp(-Set.epsilon[n].value_infty/kBT));
  239. }
  240. // Now find the achieved delta_tni
  241. DP max_delta_tni_dlambda = 0.0;
  242. DP max_delta_tni_dlambda_toplevel = 0.0;
  243. DP sum_delta_tni_dlambda = 0.0;
  244. Vect<Vect_DP> tni(Set.ntypes);
  245. Vect<Vect_DP> tni_ex(Set.ntypes);
  246. DP measure_factor = 0.0;
  247. DP eps0i = 0.0;
  248. DP eps1i = 0.0;
  249. for (int n = 0; n < Set.ntypes; ++n) {
  250. tni[n] = Vect_DP (0.0, Set.epsilon[n].Npts);
  251. tni_ex[n] = Vect_DP (0.0, Set.epsilon[n].Npts); // extrapolation from adjacent points, to compare to obtained value
  252. for (int i = 1; i < Set.epsilon[n].Npts - 1; ++i) {
  253. if (n == 0) {
  254. // Measure based on delta f/delta epsilon:
  255. measure_factor = (Set.epsilon[0].value[i] > 0.0
  256. ? exp(-Set.epsilon[0].value[i]/kBT)/(1.0 + exp(-Set.epsilon[0].value[i]/kBT))
  257. : 1.0/(1.0 + exp(Set.epsilon[0].value[i]/kBT)));
  258. }
  259. else {
  260. // Measure based on delta f/delta epsilon:
  261. eps0i = Set.epsilon[0].Return_Value(Set.epsilon[n].lambda[i]);
  262. eps1i = Set.epsilon[1].Return_Value(Set.epsilon[n].lambda[i]);
  263. measure_factor = (eps0i > 0.0 ? exp(-eps0i/kBT)/(1.0 + exp(-eps0i/kBT)) : 1.0/(1.0 + exp(eps0i/kBT)))
  264. // Logic: simple 1/2 per level cascade down
  265. * pow(0.5, n);
  266. }
  267. tni[n][i] = measure_factor * Set.epsilon[n].value[i];
  268. tni_ex[n][i] = measure_factor * (Set.epsilon[n].value[i-1] * (Set.epsilon[n].lambda[i+1] - Set.epsilon[n].lambda[i])
  269. + Set.epsilon[n].value[i+1] * (Set.epsilon[n].lambda[i] - Set.epsilon[n].lambda[i-1]))
  270. /(Set.epsilon[n].lambda[i+1] - Set.epsilon[n].lambda[i-1]);
  271. max_delta_tni_dlambda = ABACUS::max(max_delta_tni_dlambda, fabs(tni[n][i] - tni_ex[n][i]) * Set.epsilon[n].dlambda[i]);
  272. if (n == Set.ntypes - 1)
  273. max_delta_tni_dlambda_toplevel = ABACUS::max(max_delta_tni_dlambda_toplevel, fabs(tni[n][i] - tni_ex[n][i]) * Set.epsilon[n].dlambda[i]);
  274. sum_delta_tni_dlambda += fabs(tni[n][i] - tni_ex[n][i]) * Set.epsilon[n].dlambda[i];
  275. }
  276. }
  277. // We now determine the locations where we need to add points
  278. Vect<Vect<bool> > need_new_point_around(Set.ntypes);
  279. Vect<bool> need_to_extend_limit(false, Set.ntypes);
  280. for (int n = 0; n < Set.ntypes; ++n) {
  281. need_new_point_around[n] = Vect<bool> (false, Set.epsilon[n].Npts);
  282. for (int i = 1; i < Set.epsilon[n].Npts - 1; ++i) {
  283. if (fabs(tni[n][i] - tni_ex[n][i]) * Set.epsilon[n].dlambda[i] > (1.0 - refine_fraction) * max_delta_tni_dlambda) {
  284. need_new_point_around[n][i] = true;
  285. // Do also the symmetric ones... Require need...[n][i] = need...[n][Npts - 1 - i]
  286. need_new_point_around[n][Set.epsilon[n].Npts - 1 - i] = true;
  287. }
  288. }
  289. // Check boundary values; if too different from value_infty, extend limits
  290. if (n == 0) {
  291. // Measure based on delta f/delta epsilon:
  292. if (exp(-Set.epsilon[0].value[0]/kBT) > 0.001 * max_delta_tni_dlambda)
  293. need_to_extend_limit[0] = true;
  294. }
  295. else
  296. // Measure deviation from asymptote for 10th element, since we smoothly put the i<10 ones to the asymptote when damping:
  297. if (fabs(Set.epsilon[n].value[10] - Set.epsilon[n].value_infty) * Set.epsilon[0].dlambda[10] > max_delta_tni_dlambda)
  298. need_to_extend_limit[n] = true;
  299. }
  300. // Check if we need to add a level
  301. bool need_new_epsilon_n_function = false;
  302. // We add new levels if the integral a_n * Tln1plusemineps at the highest level differs too much from
  303. // the asymptotic value. Since such integrals appear for each point of the epsilon[0] function, these
  304. // errors should be compared to the individual delta_tni factors.
  305. DP a_2_Tln_conv_0_integ = 0.0;
  306. DP oneoverpi = 1.0/PI;
  307. DP twoovernc = 2.0/((Set.ntypes - 1) * c_int);
  308. int i0 = Set.epsilon[0].Npts/2;
  309. for (int j = 0; j < Set.epsilon[Set.ntypes - 1].Npts; ++j)
  310. a_2_Tln_conv_0_integ += (Tln1plusemineps[Set.ntypes - 1][j] - Tln1pluseminepsinfty[Set.ntypes - 1])
  311. * oneoverpi * (atan(twoovernc * (Set.epsilon[0].lambda[i0] - Set.epsilon[Set.ntypes - 1].lambda[j]
  312. + 0.5 * Set.epsilon[Set.ntypes - 1].dlambda[j]))
  313. - atan(twoovernc * (Set.epsilon[0].lambda[i0] - Set.epsilon[Set.ntypes - 1].lambda[j]
  314. - 0.5 * Set.epsilon[Set.ntypes - 1].dlambda[j])));
  315. // Compare to prediction for this integral based on value_infty, which is simply 0.
  316. // Count this difference Set.ntypes times over, since it cascades down all levels
  317. if (fabs(a_2_Tln_conv_0_integ) * Set.ntypes > max_delta_tni_dlambda) need_new_epsilon_n_function = true;
  318. // Additionally, if the highest level needs updating, we automatically add new functions:
  319. for (int i = 0; i < Set.epsilon[Set.ntypes - 1].Npts; ++i)
  320. if (need_new_point_around[Set.ntypes - 1][i] || need_to_extend_limit[Set.ntypes - 1]) need_new_epsilon_n_function = true;
  321. // Now insert the new points between existing points:
  322. Set.Insert_new_points (need_new_point_around);
  323. // Now extend the integration limits if needed:
  324. Set.Extend_limits (need_to_extend_limit);
  325. // If we add a level, we do it here:
  326. if (need_new_epsilon_n_function) {
  327. // Insert more than one function per cycle...
  328. Set.Insert_new_function(Asymptotic_2CBG_epsilon(Set.ntypes, Omega, kBT));
  329. Set.Insert_new_function(Asymptotic_2CBG_epsilon(Set.ntypes, Omega, kBT)); // CAREFUL !! ntypes is already updated
  330. Set.Insert_new_function(Asymptotic_2CBG_epsilon(Set.ntypes, Omega, kBT)); // CAREFUL !! ntypes is already updated
  331. Set.Insert_new_function(Asymptotic_2CBG_epsilon(Set.ntypes, Omega, kBT)); // CAREFUL !! ntypes is already updated;
  332. Set.Insert_new_function(Asymptotic_2CBG_epsilon(Set.ntypes, Omega, kBT)); // CAREFUL !! ntypes is already updated
  333. }
  334. //return(max_delta_tni_dlambda);
  335. return(sum_delta_tni_dlambda);
  336. }
  337. DP Calculate_Gibbs_Free_Energy (const Root_Density_Set& Set, DP c_int, DP mu, DP Omega, DP kBT)
  338. {
  339. // Computes the Gibbs free energy, assuming that epsilon[0] is symmetric.
  340. // WORKING VERSION
  341. DP sum_f = 0.0;
  342. Vect_DP f(0.0, Set.epsilon[0].Npts);
  343. DP sum_f_check = 0.0;
  344. Vect_DP fcheck(0.0, Set.epsilon[0].Npts);
  345. DP sum_g_check = 0.0;
  346. Vect_DP gcheck(0.0, Set.epsilon[0].Npts);
  347. for (int i = 0; i < Set.epsilon[0].Npts; ++i) {
  348. f[i] = (Set.epsilon[0].value[i] > 0.0 ? kBT* log(1.0 + exp(-Set.epsilon[0].value[i]/kBT))
  349. : -Set.epsilon[0].value[i] + kBT * log(1.0 + exp(Set.epsilon[0].value[i]/kBT)));
  350. sum_f += Set.epsilon[0].dlambda[i] * f[i];
  351. fcheck[i] = kBT * log(1.0 + exp(-(Set.epsilon[0].lambda[i] * Set.epsilon[0].lambda[i] - mu - Omega)/kBT));
  352. sum_f_check += Set.epsilon[0].dlambda[i] * fcheck[i];
  353. gcheck[i] = exp(-(Set.epsilon[0].lambda[i] * Set.epsilon[0].lambda[i])/kBT);
  354. sum_g_check += Set.epsilon[0].dlambda[i] * gcheck[i];
  355. }
  356. // Now add alpha curvature terms:
  357. for (int i = 1; i < Set.epsilon[0].Npts - 1; ++i)
  358. sum_f += pow(Set.epsilon[0].dlambda[i], 3.0) * ((f[i+1] - f[i])/(Set.epsilon[0].lambda[i+1] - Set.epsilon[0].lambda[i])
  359. - (f[i] - f[i-1])/(Set.epsilon[0].lambda[i] - Set.epsilon[0].lambda[i-1]))
  360. /(12.0 * (Set.epsilon[0].lambda[i+1] - Set.epsilon[0].lambda[i-1]));
  361. // Now add alpha curvature terms:
  362. DP sum_gcorralphacheck = 0.0;
  363. Vect_DP gcorr_alpha_check(0.0, Set.epsilon[0].Npts);
  364. for (int i = 1; i < Set.epsilon[0].Npts - 1; ++i) {
  365. gcorr_alpha_check[i] = (1.0/12.0) * pow(Set.epsilon[0].dlambda[i], 3.0)
  366. * ((gcheck[i+1] - gcheck[i]) * (Set.epsilon[0].lambda[i] - Set.epsilon[0].lambda[i-1])
  367. - (gcheck[i] - gcheck[i-1]) * (Set.epsilon[0].lambda[i+1] - Set.epsilon[0].lambda[i]))
  368. /((Set.epsilon[0].lambda[i+1] - Set.epsilon[0].lambda[i-1]) * (Set.epsilon[0].lambda[i+1] - Set.epsilon[0].lambda[i])
  369. * (Set.epsilon[0].lambda[i] - Set.epsilon[0].lambda[i-1]));
  370. sum_gcorralphacheck += gcorr_alpha_check[i];
  371. }
  372. // Testing:
  373. int Npts_test = Set.epsilon[0].Npts;
  374. DP lambdamax_test = Set.epsilon[0].lambdamax;
  375. DP testsum = 0.0;
  376. DP testgauss = 0.0;
  377. DP lambda;
  378. DP dlambda;
  379. for (int i = 0; i < Npts_test; ++i) {
  380. lambda = lambdamax_test * (-Npts_test + 1.0 + 2*i)/Npts_test;
  381. dlambda = lambdamax_test * 2.0/Npts_test;
  382. testsum += kBT * log(1.0 + exp(-(lambda*lambda - mu - Omega)/kBT)) * dlambda;
  383. testgauss += exp(-lambda*lambda/kBT) * dlambda;
  384. }
  385. return(-sum_f/twoPI);
  386. }
  387. DP Calculate_dGibbs_dchempot (const Root_Density_Set& DSet, const Root_Density_Set& Set, DP c_int, DP mu, DP Omega, DP kBT)
  388. {
  389. // This calculates the derivative of the Gibbs free energy with respect to either of the two chemical potential,
  390. // given the fundametal set Set for eps and DSet for either deps_du or deps_dOmega.
  391. DP sum_f = 0.0;
  392. Vect_DP f(0.0, Set.epsilon[0].Npts);
  393. for (int i = 0; i < Set.epsilon[0].Npts; ++i) {
  394. f[i] = DSet.epsilon[0].value[i] * (Set.epsilon[0].value[i] > 0.0
  395. ? exp(-Set.epsilon[0].value[i]/kBT)/(1.0 + exp(-Set.epsilon[0].value[i]/kBT))
  396. : 1.0/(1.0 + exp(Set.epsilon[0].value[i]/kBT)));
  397. sum_f += DSet.epsilon[0].dlambda[i] * f[i];
  398. }
  399. // Now add alpha curvature terms:
  400. for (int i = 1; i < DSet.epsilon[0].Npts - 1; ++i)
  401. sum_f += pow(DSet.epsilon[0].dlambda[i], 3.0)
  402. * ((f[i+1] - f[i])/(DSet.epsilon[0].lambda[i+1] - DSet.epsilon[0].lambda[i])
  403. - (f[i] - f[i-1])/(DSet.epsilon[0].lambda[i] - DSet.epsilon[0].lambda[i-1]))
  404. /(12.0 * (DSet.epsilon[0].lambda[i+1] - DSet.epsilon[0].lambda[i-1]));
  405. return(sum_f/twoPI);
  406. }
  407. Vect<Vect<Vect_DP> > Build_a_n_dlambda (const Root_Density_Set& Set, DP c_int, DP mu, DP Omega, DP kBT)
  408. {
  409. DP oneoverpi = 1.0/PI;
  410. DP oneoverc = 1.0/c_int;
  411. DP twoovernc = 2.0/c_int;
  412. Vect<Vect<Vect_DP> > a_n_dlambda(Set.epsilon[0].Npts);
  413. for (int i = 0; i < Set.epsilon[0].Npts; ++i) {
  414. a_n_dlambda[i] = Vect<Vect_DP>(Set.ntypes);
  415. for (int n = 0; n < Set.ntypes; ++n) {
  416. a_n_dlambda[i][n] = Vect_DP(0.0, Set.epsilon[n].Npts);
  417. }
  418. }
  419. for (int i = 0; i < Set.epsilon[0].Npts; ++i) {
  420. // Do n == 0 separately:
  421. for (int j = 0; j < Set.epsilon[0].Npts; ++j)
  422. a_n_dlambda[i][0][j] = oneoverpi
  423. * (atan(oneoverc * (Set.epsilon[0].lambda[i] - Set.epsilon[0].lambda[j] + 0.5 * Set.epsilon[0].dlambda[j]))
  424. - atan(oneoverc * (Set.epsilon[0].lambda[i] - Set.epsilon[0].lambda[j] - 0.5 * Set.epsilon[0].dlambda[j])));
  425. // Now do n > 0:
  426. for (int n = 1; n < Set.ntypes; ++n) {
  427. twoovernc = 2.0/(n * c_int);
  428. for (int j = 0; j < Set.epsilon[n].Npts; ++j) {
  429. a_n_dlambda[i][n][j] = oneoverpi
  430. * (atan(twoovernc * (Set.epsilon[0].lambda[i] - Set.epsilon[n].lambda[j] + 0.5 * Set.epsilon[n].dlambda[j]))
  431. - atan(twoovernc * (Set.epsilon[0].lambda[i] - Set.epsilon[n].lambda[j] - 0.5 * Set.epsilon[n].dlambda[j])));
  432. }
  433. } // for (int n
  434. } // for (int i
  435. return(a_n_dlambda);
  436. }
  437. Vect<Vect<Vect_DP> > Build_fmin_dlambda (const Root_Density_Set& Set, DP c_int, DP mu, DP Omega, DP kBT)
  438. {
  439. DP oneoverpi = 1.0/PI;
  440. DP pioverc = PI/c_int;
  441. DP twopioverc = 2.0*PI/c_int;
  442. DP piovertwoc = 0.5 * pioverc;
  443. Vect<Vect<Vect_DP> > fmin_dlambda(Set.ntypes);
  444. for (int n = 0; n < Set.ntypes; ++n) {
  445. fmin_dlambda[n] = Vect<Vect_DP> (Set.epsilon[n].Npts);
  446. for (int i = 0; i < Set.epsilon[n].Npts; ++i)
  447. fmin_dlambda[n][i] = Vect_DP (0.0, Set.epsilon[ABACUS::max(n-1, 0)].Npts);
  448. }
  449. for (int n = 1; n < Set.ntypes; ++n) {
  450. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  451. for (int j = 0; j < Set.epsilon[n-1].Npts; ++j)
  452. fmin_dlambda[n][i][j] = oneoverpi
  453. * atan(exp(-pioverc * fabs(Set.epsilon[n].lambda[i] - Set.epsilon[n-1].lambda[j]))
  454. * 2.0 * sinh(piovertwoc * Set.epsilon[n-1].dlambda[j])
  455. /(1.0 + exp(-twopioverc * fabs(Set.epsilon[n].lambda[i] - Set.epsilon[n-1].lambda[j]))));
  456. } // for i
  457. } // for n
  458. return(fmin_dlambda);
  459. }
  460. Vect<Vect<Vect_DP> > Build_fplus_dlambda (const Root_Density_Set& Set, DP c_int, DP mu, DP Omega, DP kBT)
  461. {
  462. DP oneoverpi = 1.0/PI;
  463. DP pioverc = PI/c_int;
  464. DP twopioverc = 2.0*PI/c_int;
  465. DP piovertwoc = 0.5 * pioverc;
  466. Vect<Vect<Vect_DP> > fplus_dlambda(Set.ntypes);
  467. for (int n = 0; n < Set.ntypes; ++n) {
  468. fplus_dlambda[n] = Vect<Vect_DP> (Set.epsilon[n].Npts);
  469. for (int i = 0; i < Set.epsilon[n].Npts; ++i)
  470. fplus_dlambda[n][i] = Vect_DP (0.0, Set.epsilon[ABACUS::min(n+1, Set.ntypes - 1)].Npts);
  471. }
  472. for (int n = 0; n < Set.ntypes - 1; ++n) {
  473. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  474. for (int j = 0; j < Set.epsilon[n+1].Npts; ++j)
  475. fplus_dlambda[n][i][j] = oneoverpi
  476. * atan(exp(-pioverc * fabs(Set.epsilon[n].lambda[i] - Set.epsilon[n+1].lambda[j]))
  477. * 2.0 * sinh(piovertwoc * Set.epsilon[n+1].dlambda[j])
  478. /(1.0 + exp(-twopioverc * fabs(Set.epsilon[n].lambda[i] - Set.epsilon[n+1].lambda[j]))));
  479. }
  480. }
  481. return(fplus_dlambda);
  482. }
  483. Root_Density_Set Solve_2CBG_TBAE_via_refinements (DP c_int, DP mu, DP Omega, DP kBT, int Max_Secs,
  484. ofstream& LOG_outfile, bool Save_data)
  485. {
  486. // This solves the 2CBG TBAE as best as possible given the time constraint.
  487. clock_t StartTime = clock();
  488. int Max_CPU_ticks = 98 * (Max_Secs - 0) * CLOCKS_PER_SEC/100; // give 30 seconds to wrap up, assume we time to 2% accuracy.
  489. // Set basic precision needed:
  490. DP running_prec = 1.0;
  491. DP refine_fraction = 0.5; // value fraction of points to be refined
  492. // Set basic number of types needed:
  493. int ntypes_needed = int(kBT * log(kBT/1.0e-14)/Omega);
  494. int ntypes = ABACUS::max(ntypes_needed, 1);
  495. ntypes = ABACUS::min(ntypes, 10);
  496. if (Save_data)
  497. if (ntypes >= 10) LOG_outfile << "WARNING: ntypes needs to be quite high for c_int = " << c_int
  498. << " mu = " << mu << " Omega = " << Omega
  499. << " kBT = " << kBT << ". Set to " << ntypes << ", ideally needed: "
  500. << ntypes_needed << ". Accuracy might be incorrectly evaluated." << endl;
  501. DP lambdamax = 10.0 + sqrt(ABACUS::max(1.0, kBT * 36.0 + mu + Omega));
  502. // such that exp(-(lambdamax^2 - mu - Omega)/T) <~ machine_eps
  503. int Npts = 50;
  504. Vect_INT Npts_init(Npts, ntypes);
  505. if (Save_data) LOG_outfile << "Npts (basic) set to " << Npts_init << endl;
  506. Vect_DP lambdamax_init(lambdamax, ntypes); // such that exp(-pi *lambdamax/c) <~ machine_eps
  507. Npts_init[0] = 1 * Npts; // give more precision to lowest level
  508. lambdamax_init[0] = 10.0 + sqrt(ABACUS::max(1.0, kBT * 36.0 + mu + Omega));
  509. // such that exp(-(lambdamax^2 - mu - Omega)/T) <~ machine_eps
  510. Root_Density_Set TBA_Set (ntypes, Npts_init, lambdamax_init);
  511. // Set the asymptotics of the TBA_fns:
  512. Set_2CBG_Asymptotics (TBA_Set, mu, Omega, kBT);
  513. // Initiate the functions:
  514. Initiate_2CBG_TBA_Functions (TBA_Set, mu, Omega);
  515. clock_t StopTime = clock();
  516. clock_t Cycle_StartTime, Cycle_StopTime;
  517. int CPU_ticks = StopTime - StartTime;
  518. int ncycles = 0;
  519. int niter_tot = 0;
  520. do {
  521. StartTime = clock();
  522. Cycle_StartTime = clock();
  523. // The running precision is an estimate of the accuracy of the free energy integral.
  524. // Refine... returns sum_delta_tni_dlambda, so running prec is estimated as...
  525. running_prec = Refine_2CBG_Set (TBA_Set, c_int, mu, Omega, kBT, refine_fraction);
  526. Vect<Vect<Vect_DP> > a_n_dlambda = Build_a_n_dlambda (TBA_Set, c_int, mu, Omega, kBT);
  527. Vect<Vect<Vect_DP> > fmin_dlambda = Build_fmin_dlambda (TBA_Set, c_int, mu, Omega, kBT);
  528. Vect<Vect<Vect_DP> > fplus_dlambda = Build_fplus_dlambda (TBA_Set, c_int, mu, Omega, kBT);
  529. StopTime = clock();
  530. CPU_ticks += StopTime - StartTime;
  531. int niter = 0;
  532. int niter_max = ncycles == 0 ? 300 : 300;
  533. // For extrapolations:
  534. Vect<Root_Density_Set> IterSet(4);
  535. do {
  536. StartTime = clock();
  537. if (niter <= 10 || niter > 100) {
  538. Iterate_2CBG_TBAE (TBA_Set, a_n_dlambda, fmin_dlambda, fplus_dlambda, c_int, mu, Omega, kBT);
  539. niter++;
  540. }
  541. else {
  542. Iterate_and_Extrapolate_2CBG_TBAE (TBA_Set, IterSet, a_n_dlambda, fmin_dlambda, fplus_dlambda, c_int, mu, Omega, kBT);
  543. niter += 6;
  544. }
  545. StopTime = clock();
  546. CPU_ticks += StopTime - StartTime;
  547. } while (niter < 5 || niter < niter_max && TBA_Set.diff > 0.1 * running_prec && CPU_ticks < Max_CPU_ticks);
  548. if (Save_data) {
  549. LOG_outfile << "ncycles = " << ncycles << "\trunning_prec = " << running_prec << "\t niter = " << niter
  550. << "\tntypes = " << TBA_Set.ntypes << "\tNpts ";
  551. for (int n = 0; n < TBA_Set.ntypes; ++n) LOG_outfile << TBA_Set.epsilon[n].Npts << " ";
  552. LOG_outfile << "\tNpts_total = " << TBA_Set.Npts_total << endl
  553. << "\tdiff = " << TBA_Set.diff
  554. << "\tGSE = " << Calculate_Gibbs_Free_Energy (TBA_Set, c_int, mu, Omega, kBT) << endl;
  555. }
  556. ncycles++;
  557. niter_tot += niter;
  558. if (niter == niter_max) {
  559. if (Save_data) LOG_outfile << "Not able to improve functions enough after " << niter_max << " iterations." << endl;
  560. }
  561. Cycle_StopTime = clock();
  562. } while (CPU_ticks < Max_CPU_ticks - 2.0*(Cycle_StopTime - Cycle_StartTime));
  563. // Allow a new cycle only if there is time, assuming new cycle time < 2* last one
  564. if (Save_data) {
  565. LOG_outfile << "c_int " << c_int << "\tmu " << mu << "\tOmega " << Omega << "\tkBT " << kBT
  566. << "\tncycles = " << ncycles << "\trunning_prec = " << running_prec << "\t niter_tot = " << niter_tot
  567. << "\tntypes = " << TBA_Set.ntypes << "\tdiff = " << TBA_Set.diff << endl << "\tNpts ";
  568. for (int n = 0; n < TBA_Set.ntypes; ++n) LOG_outfile << TBA_Set.epsilon[n].Npts << " ";
  569. LOG_outfile << "\tNpts_total = " << TBA_Set.Npts_total << endl;
  570. }
  571. return(TBA_Set);
  572. //return;
  573. }
  574. // Iterative procedures for deps/dmu or /dOmega:
  575. void Iterate_2CBG_deps_dchempot (int option, Root_Density_Set& DSet, const Root_Density_Set& Set,
  576. Vect<Vect<Vect_DP> >& a_n_dlambda, Vect<Vect<Vect_DP> >& fmin_dlambda,
  577. Vect<Vect<Vect_DP> >& fplus_dlambda, DP c_int, DP mu, DP Omega, DP kBT)
  578. {
  579. // Produces a new Root_Density_Set for depsilon/dmu (option == 0) or depsilon/dOmega (option == 1) from a previous iteration.
  580. // Does NOT add types or change Npts, lambdamax values.
  581. // First define some useful functions:
  582. Vect<Vect_DP> depsover1plusemineps(Set.ntypes);
  583. Vect<Vect_DP> depsover1plusepluseps(Set.ntypes);
  584. Vect_DP depsover1pluseminepsinfty(Set.ntypes);
  585. Vect_DP depsover1pluseplusepsinfty(Set.ntypes);
  586. for (int n = 0; n < Set.ntypes; ++n) {
  587. depsover1plusemineps[n] = Vect_DP (0.0, Set.epsilon[n].Npts);
  588. depsover1plusepluseps[n] = Vect_DP (0.0, Set.epsilon[n].Npts);
  589. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  590. depsover1plusemineps[n][i] = Set.epsilon[n].value[i] > 0.0 ?
  591. DSet.epsilon[n].value[i]/(1.0 + exp(-Set.epsilon[n].value[i]/kBT)) :
  592. DSet.epsilon[n].value[i] * exp(Set.epsilon[n].value[i]/kBT)/(1.0 + exp(Set.epsilon[n].value[i]/kBT));
  593. depsover1plusepluseps[n][i] = Set.epsilon[n].value[i] > 0.0 ?
  594. DSet.epsilon[n].value[i] * exp(-Set.epsilon[n].value[i]/kBT)/(1.0 + exp(-Set.epsilon[n].value[i]/kBT)) :
  595. DSet.epsilon[n].value[i]/(1.0 + exp(Set.epsilon[n].value[i]/kBT));
  596. // Keep previous rapidities:
  597. DSet.epsilon[n].prev_value[i] = DSet.epsilon[n].value[i];
  598. }
  599. depsover1pluseminepsinfty[n] = DSet.epsilon[n].value_infty/(1.0 + exp(-Set.epsilon[n].value_infty/kBT));
  600. depsover1pluseplusepsinfty[n] = DSet.epsilon[n].value_infty * exp(-Set.epsilon[n].value_infty/kBT)
  601. /(1.0 + exp(-Set.epsilon[n].value_infty/kBT));
  602. }
  603. // Now do the necessary convolutions for epsilon == epsilon[0].
  604. // For each value of lambda, do the convolutions:
  605. // Careful: the lambda's used for lambda (index i) are those of epsilon[0], the lambda' (index j) are for epsilon[n] !!
  606. Vect<Vect_DP> a_n_depsover_conv(Set.ntypes);
  607. for (int n = 0; n < Set.ntypes; ++n) {
  608. a_n_depsover_conv[n] = Vect_DP (0.0, Set.epsilon[0].Npts);
  609. Vect_DP f(0.0, Set.epsilon[n].Npts);
  610. for (int i = 0; i < Set.epsilon[0].Npts; ++i) {
  611. a_n_depsover_conv[n][i] = 0.0;
  612. for (int j = 0; j < Set.epsilon[n].Npts; ++j) {
  613. f[j] = depsover1plusepluseps[n][j] * a_n_dlambda[i][n][j];
  614. a_n_depsover_conv[n][i] += f[j];
  615. }
  616. }
  617. } // for (int n... We now have all the a_n * deps... at our disposal.
  618. // For n > nmax sum in RHS of BE for epsilon, assuming epsilon_n = epsilon_n^\infty in those cases:
  619. // Remember: nmax = Set.ntypes - 1
  620. DP Smaxsum = option == 0 ? 0.0 : 2.0 * ((Set.ntypes + 1.0) * exp(-2.0 * (Set.ntypes + 1.0) * Omega/kBT)
  621. /(1.0 - exp(-2.0 * (Set.ntypes + 1.0) * Omega/kBT))
  622. - Set.ntypes * exp(-2.0 * Set.ntypes * Omega/kBT)
  623. /(1.0 - exp(-2.0 * Set.ntypes * Omega/kBT)));
  624. // Reconstruct the epsilon[0] function:
  625. for (int i = 0; i < DSet.epsilon[0].Npts; ++i) {
  626. DSet.epsilon[0].value[i] = -1.0;
  627. // Add the convolutions:
  628. for (int n = 0; n < Set.ntypes; ++n)
  629. DSet.epsilon[0].value[i] += a_n_depsover_conv[n][i];
  630. // Add the asymptotic parts of convolutions: n == 0 part is zero because of 1 + exp[epsilon[0] ] in denominator
  631. for (int n = 1; n < Set.ntypes; ++n)
  632. DSet.epsilon[0].value[i] += depsover1pluseplusepsinfty[n]
  633. * (1.0 - (atan((DSet.epsilon[n].lambdamax - DSet.epsilon[0].lambda[i])/(0.5 * n * c_int))
  634. + atan((DSet.epsilon[n].lambdamax + DSet.epsilon[0].lambda[i])/(0.5 * n * c_int)))/PI);
  635. // Add the leftover summation for species n > nmax, assuming epsilon_n = epsilon_n^\infty in those cases:
  636. DSet.epsilon[0].value[i] -= Smaxsum;
  637. // Include some damping:
  638. DSet.epsilon[0].value[i] = 0.1 * DSet.epsilon[0].prev_value[i] + 0.9 * DSet.epsilon[0].value[i];
  639. // Force boundary values to asymptotes: force boundary 10 points on each side
  640. if (i < 10)
  641. DSet.epsilon[0].value[i] = (1.0 - 0.1 * i) * DSet.epsilon[0].value_infty + 0.1 * i * DSet.epsilon[0].value[i];
  642. if (i > DSet.epsilon[0].Npts - 11)
  643. DSet.epsilon[0].value[i] = (1.0 - 0.1 * (DSet.epsilon[0].Npts-1 - i)) * DSet.epsilon[0].value_infty
  644. + 0.1 * (DSet.epsilon[0].Npts-1 - i) * DSet.epsilon[0].value[i];
  645. }
  646. // epsilon[0] is now fully iterated.
  647. // Now do the remaining epsilons:
  648. for (int n = 1; n < Set.ntypes; ++n) {
  649. Vect_DP f_depsover_conv_min (0.0, Set.epsilon[n].Npts); // 'down' convolution
  650. Vect_DP f_depsover_conv_plus (0.0, Set.epsilon[n].Npts); // 'up' convolution
  651. Vect_DP fmin(0.0, Set.epsilon[n-1].Npts);
  652. Vect_DP fplus(0.0, Set.epsilon[ABACUS::min(n+1, Set.ntypes - 1)].Npts);
  653. for (int i = 0; i < Set.epsilon[n].Npts; ++i) {
  654. f_depsover_conv_min[i] = 0.0;
  655. f_depsover_conv_plus[i] = 0.0;
  656. // 'down' convolutions
  657. if (n == 1) {
  658. for (int j = 0; j < Set.epsilon[0].Npts; ++j) {
  659. fmin[j] = depsover1plusepluseps[0][j]
  660. * fmin_dlambda[n][i][j];
  661. f_depsover_conv_min[i] -= fmin[j]; // Careful ! - sign here
  662. }
  663. } // if (n == 1)
  664. else { // if (n != 1)
  665. for (int j = 0; j < Set.epsilon[n - 1].Npts; ++j) {
  666. fmin[j] = (depsover1plusemineps[n-1][j] - depsover1pluseminepsinfty[n-1])
  667. * fmin_dlambda[n][i][j];
  668. f_depsover_conv_min[i] += fmin[j];
  669. }
  670. } // if (n != 1)
  671. // 'up' convolutions
  672. if (n < Set.ntypes - 1) {
  673. for (int j = 0; j < Set.epsilon[n+1].Npts; ++j) {
  674. fplus[j] = (depsover1plusemineps[n+1][j] - depsover1pluseminepsinfty[n+1])
  675. * fplus_dlambda[n][i][j];
  676. f_depsover_conv_plus[i] += fplus[j];
  677. }
  678. } // if (n < Set.ntypes - 1...
  679. // otherwise, we put the function to 1/2 times depsover... of epsilon[n+1] at infinity, minus the same:
  680. else f_depsover_conv_plus[i] = 0.0;
  681. // Do some damping:
  682. DSet.epsilon[n].value[i] = 0.1 * DSet.epsilon[n].prev_value[i]
  683. + 0.9 * (DSet.epsilon[n].value_infty + f_depsover_conv_min[i] + f_depsover_conv_plus[i]);
  684. // Force boundary values to asymptotes: force boundary 10 points on each side
  685. if (i < 10)
  686. DSet.epsilon[n].value[i] = (1.0 - 0.1 * i) * DSet.epsilon[n].value_infty + 0.1 * i * DSet.epsilon[n].value[i];
  687. if (i > DSet.epsilon[n].Npts - 11)
  688. DSet.epsilon[n].value[i] = (1.0 - 0.1 * (DSet.epsilon[n].Npts-1 - i)) * DSet.epsilon[n].value_infty
  689. + 0.1 * (DSet.epsilon[n].Npts-1 - i) * DSet.epsilon[n].value[i];
  690. } // for (int i = 0...
  691. } // for (int n = 1...
  692. // All functions have now been iterated.
  693. // Now calculate diff:
  694. DSet.diff = 0.0;
  695. for (int n = 0; n < DSet.ntypes; ++n) {
  696. DSet.epsilon[n].diff = 0.0;
  697. for (int i = 0; i < DSet.epsilon[n].Npts; ++i) {
  698. DSet.epsilon[n].diff += DSet.epsilon[n].dlambda[i] *
  699. fabs((DSet.epsilon[n].value[i] - DSet.epsilon[n].prev_value[i]) * depsover1plusepluseps[n][i]);
  700. }
  701. DSet.diff += DSet.epsilon[n].diff;
  702. }
  703. return;
  704. }
  705. Root_Density_Set Solve_2CBG_deps_dchempot (int option, Root_Density_Set& TBA_Set, DP c_int, DP mu, DP Omega, DP kBT,
  706. int Max_Secs, ofstream& LOG_outfile, bool Save_data)
  707. {
  708. // This solves the 2CBG deps/dmu (option == 0) or deps/dOmega (option == 1).
  709. clock_t StartTime, StopTime;
  710. int Max_CPU_ticks = 98 * (Max_Secs - 10) * CLOCKS_PER_SEC/100; // give 30 seconds to wrap up, assume we time to 2% accuracy.
  711. // Set basic precision needed:
  712. DP running_prec = TBA_Set.diff;
  713. // We start by converging simplified sets, with fewer points:
  714. Root_Density_Set TBA_Set_comp = TBA_Set.Return_Compressed_and_Matched_Set(1.0);
  715. Root_Density_Set DSet = TBA_Set; // this will be the final function return
  716. Root_Density_Set DSet_comp = TBA_Set_comp;
  717. // Set the asymptotics of the TBA_fns:
  718. Set_2CBG_deps_dchempot_Asymptotics (option, TBA_Set_comp, DSet_comp, mu, Omega, kBT);
  719. Set_2CBG_deps_dchempot_Asymptotics (option, TBA_Set, DSet, mu, Omega, kBT);
  720. // Now, start by 'converging' the comp set:
  721. // Initiate the functions:
  722. Initiate_2CBG_deps_dchempot_Functions (DSet_comp);
  723. Vect<Vect<Vect_DP> > a_n_dlambda_comp = Build_a_n_dlambda (TBA_Set_comp, c_int, mu, Omega, kBT);
  724. Vect<Vect<Vect_DP> > fmin_dlambda_comp = Build_fmin_dlambda (TBA_Set_comp, c_int, mu, Omega, kBT);
  725. Vect<Vect<Vect_DP> > fplus_dlambda_comp = Build_fplus_dlambda (TBA_Set_comp, c_int, mu, Omega, kBT);
  726. int CPU_ticks = 0;
  727. int niter_comp = 0;
  728. do {
  729. StartTime = clock();
  730. Iterate_2CBG_deps_dchempot (option, DSet_comp, TBA_Set_comp,
  731. a_n_dlambda_comp, fmin_dlambda_comp, fplus_dlambda_comp, c_int, mu, Omega, kBT);
  732. niter_comp++;
  733. StopTime = clock();
  734. CPU_ticks += StopTime - StartTime;
  735. } while (CPU_ticks < Max_CPU_ticks/2 && (niter_comp < 100 || DSet_comp.diff > running_prec));
  736. // use at most half the time, keep rest for later.
  737. DSet.Match_Densities(DSet_comp);
  738. Vect<Vect<Vect_DP> > a_n_dlambda = Build_a_n_dlambda (TBA_Set, c_int, mu, Omega, kBT);
  739. Vect<Vect<Vect_DP> > fmin_dlambda = Build_fmin_dlambda (TBA_Set, c_int, mu, Omega, kBT);
  740. Vect<Vect<Vect_DP> > fplus_dlambda = Build_fplus_dlambda (TBA_Set, c_int, mu, Omega, kBT);
  741. int niter = 0;
  742. do {
  743. StartTime = clock();
  744. Iterate_2CBG_deps_dchempot (option, DSet, TBA_Set, a_n_dlambda, fmin_dlambda, fplus_dlambda, c_int, mu, Omega, kBT);
  745. niter++;
  746. StopTime = clock();
  747. CPU_ticks += StopTime - StartTime;
  748. } while (CPU_ticks < Max_CPU_ticks && DSet_comp.diff > 1.0e-4 * running_prec);
  749. // We're done !!
  750. if (Save_data) {
  751. LOG_outfile << "deps_dchempot, option == " << option << endl;
  752. LOG_outfile << "c_int " << c_int << "\tmu " << mu << "\tOmega " << Omega << "\tkBT " << kBT
  753. << "\trunning_prec " << running_prec << " niter_comp " << niter_comp << " niter_full " << niter
  754. << "\tntypes " << DSet.ntypes << "\tdiff " << DSet.diff << endl;
  755. }
  756. return(DSet);
  757. }
  758. TBA_Data_2CBG Solve_2CBG_TBAE_via_refinements (DP c_int, DP mu, DP Omega, DP kBT, int Max_Secs, bool Save_data)
  759. {
  760. // This solves the 2CBG TBAE as best as possible given the time constraint.
  761. stringstream TBA_stringstream;
  762. string TBA_string;
  763. stringstream Dmu_stringstream;
  764. string Dmu_string;
  765. stringstream DOmega_stringstream;
  766. string DOmega_string;
  767. stringstream LOG_stringstream;
  768. string LOG_string;
  769. stringstream GFE_stringstream;
  770. string GFE_string;
  771. TBA_stringstream << "EPS_2CBG_c_" << c_int << "_mu_" << mu << "_Omega_" << Omega
  772. << "_kBT_" << kBT << "_Secs_" << Max_Secs << ".dat";
  773. Dmu_stringstream << "EPS_2CBG_c_" << c_int << "_mu_" << mu << "_Omega_" << Omega
  774. << "_kBT_" << kBT << "_Secs_" << Max_Secs << ".dmu";
  775. DOmega_stringstream << "EPS_2CBG_c_" << c_int << "_mu_" << mu << "_Omega_" << Omega
  776. << "_kBT_" << kBT << "_Secs_" << Max_Secs << ".dOm";
  777. LOG_stringstream << "EPS_2CBG_c_" << c_int << "_mu_" << mu << "_Omega_" << Omega
  778. << "_kBT_" << kBT << "_Secs_" << Max_Secs << ".log";
  779. GFE_stringstream << "GFE_2CBG_c_" << c_int << "_mu_" << mu << "_Omega_" << Omega
  780. << "_kBT_" << kBT << "_Secs_" << Max_Secs << ".dat";
  781. TBA_string = TBA_stringstream.str();
  782. const char* TBA_Cstr = TBA_string.c_str();
  783. Dmu_string = Dmu_stringstream.str();
  784. const char* Dmu_Cstr = Dmu_string.c_str();
  785. DOmega_string = DOmega_stringstream.str();
  786. const char* DOmega_Cstr = DOmega_string.c_str();
  787. LOG_string = LOG_stringstream.str();
  788. const char* LOG_Cstr = LOG_string.c_str();
  789. GFE_string = GFE_stringstream.str();
  790. const char* GFE_Cstr = GFE_string.c_str();
  791. ofstream LOG_outfile;
  792. ofstream GFE_outfile;
  793. if (Save_data) {
  794. LOG_outfile.open(LOG_Cstr);
  795. LOG_outfile.precision(6);
  796. GFE_outfile.open(GFE_Cstr);
  797. GFE_outfile.precision(16);
  798. }
  799. Root_Density_Set TBA_Set = Solve_2CBG_TBAE_via_refinements (c_int, mu, Omega, kBT, Max_Secs/3, LOG_outfile, Save_data);
  800. if (Save_data) {
  801. // Output the functions:
  802. TBA_Set.Save(TBA_Cstr);
  803. }
  804. Root_Density_Set DSet_dmu =
  805. Solve_2CBG_deps_dchempot (0, TBA_Set, c_int, mu, Omega, kBT, Max_Secs/3, LOG_outfile, Save_data);
  806. if (Save_data) DSet_dmu.Save(Dmu_Cstr);
  807. Root_Density_Set DSet_dOmega =
  808. Solve_2CBG_deps_dchempot (1, TBA_Set, c_int, mu, Omega, kBT, Max_Secs/3, LOG_outfile, Save_data);
  809. if (Save_data) DSet_dOmega.Save(DOmega_Cstr);
  810. DP f = Calculate_Gibbs_Free_Energy (TBA_Set, c_int, mu, Omega, kBT);
  811. DP dfdmu = Calculate_dGibbs_dchempot (DSet_dmu, TBA_Set, c_int, mu, Omega, kBT);
  812. DP dfdOm = Calculate_dGibbs_dchempot (DSet_dOmega, TBA_Set, c_int, mu, Omega, kBT);
  813. if (Save_data)
  814. GFE_outfile << f << "\t" << TBA_Set.diff
  815. << "\t" << dfdmu << "\t" << dfdOm << "\t" << 0.5 * (-dfdmu - dfdOm) << "\t" << 0.5 * (-dfdmu + dfdOm)
  816. << endl;
  817. else cout << setprecision(16) << f << "\t" << 0.5 * (-dfdmu - dfdOm) << "\t" << 0.5 * (-dfdmu + dfdOm);
  818. if (Save_data) {
  819. LOG_outfile.close();
  820. GFE_outfile.close();
  821. }
  822. TBA_Data_2CBG answer;
  823. answer.c_int = c_int;
  824. answer.mu = mu;
  825. answer.Omega = Omega;
  826. answer.kBT = kBT;
  827. answer.f = f;
  828. answer.n1 = 0.5 * (-dfdmu - dfdOm);
  829. answer.n2 = 0.5 * (-dfdmu + dfdOm);
  830. return(answer);
  831. }
  832. void GFE_muscan_2CBG (DP c_int, DP mu_min, DP mu_max, DP Omega, DP kBT, int Npts_mu, int Max_Secs, bool Save_data)
  833. {
  834. DP dmu = (mu_max - mu_min)/(Npts_mu - 1);
  835. stringstream LOG_stringstream;
  836. string LOG_string;
  837. stringstream GFE_stringstream;
  838. string GFE_string;
  839. LOG_stringstream << "GFE_2CBG_c_" << c_int << "_mu_min_" << mu_min << "_mu_max_" << mu_max
  840. << "_Npts_mu_" << Npts_mu << "_Omega_" << Omega << "_kBT_" << kBT << "_Secs_" << Max_Secs << ".log";
  841. GFE_stringstream << "GFE_2CBG_c_" << c_int << "_mu_min_" << mu_min << "_mu_max_" << mu_max
  842. << "_Npts_mu_" << Npts_mu << "_Omega_" << Omega << "_kBT_" << kBT << "_Secs_" << Max_Secs << ".dat";
  843. LOG_string = LOG_stringstream.str();
  844. const char* LOG_Cstr = LOG_string.c_str();
  845. GFE_string = GFE_stringstream.str();
  846. const char* GFE_Cstr = GFE_string.c_str();
  847. ofstream LOG_outfile;
  848. ofstream GFE_outfile;
  849. LOG_outfile.open(LOG_Cstr);
  850. LOG_outfile.precision(6);
  851. GFE_outfile.open(GFE_Cstr);
  852. GFE_outfile.precision(16);
  853. Root_Density_Set Scan_Set (10, 10, 10.0);;
  854. Root_Density_Set Scan_dSet_dmu (10, 10, 10.0);;
  855. Root_Density_Set Scan_dSet_dOmega (10, 10, 10.0);;
  856. DP mu;
  857. int Max_Secs_per_mu_pt = Max_Secs/Npts_mu;
  858. for (int imu = 0; imu < Npts_mu; ++imu) {
  859. mu = mu_min + imu * dmu;
  860. Scan_Set = Solve_2CBG_TBAE_via_refinements (c_int, mu, Omega, kBT, Max_Secs_per_mu_pt/3, LOG_outfile, Save_data);
  861. Scan_dSet_dmu = Solve_2CBG_deps_dchempot (0, Scan_Set, c_int, mu, Omega, kBT, Max_Secs_per_mu_pt/3,
  862. LOG_outfile, Save_data);
  863. Scan_dSet_dOmega = Solve_2CBG_deps_dchempot (1, Scan_Set, c_int, mu, Omega, kBT, Max_Secs_per_mu_pt/3,
  864. LOG_outfile, Save_data);
  865. DP dfdmu = Calculate_dGibbs_dchempot (Scan_dSet_dmu, Scan_Set, c_int, mu, Omega, kBT);
  866. DP dfdOm = Calculate_dGibbs_dchempot (Scan_dSet_dOmega, Scan_Set, c_int, mu, Omega, kBT);
  867. GFE_outfile << mu << "\t" << Calculate_Gibbs_Free_Energy (Scan_Set, c_int, mu, Omega, kBT) << "\t" << Scan_Set.diff
  868. << "\t" << dfdmu << "\t" << dfdOm << "\t" << 0.5 * (-dfdmu - dfdOm) << "\t" << 0.5 * (-dfdmu + dfdOm)
  869. << endl;
  870. } // for imu
  871. LOG_outfile.close();
  872. GFE_outfile.close();
  873. return;
  874. }
  875. } // namespace ABACUS