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.

Root_Density.cc 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /**********************************************************
  2. This software is part of J.-S. Caux's C++ library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: Root_Density.cc
  6. Purpose: defines Root_Density & Root_Density_Set, and their member functions
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. using namespace ABACUS;
  11. namespace ABACUS {
  12. Root_Density::Root_Density ()
  13. : Npts(1), lambdamax(0.0), lambda(Vect_DP(0.0, Npts)), dlambda(Vect_DP(0.0, Npts)), value(Vect_DP(0.0, Npts)),
  14. prev_value(Vect_DP(0.0, Npts)), diff(1.0e+6), value_infty_set(false), value_infty(0.0)
  15. {
  16. }
  17. Root_Density::Root_Density (int Npts_ref, DP lambdamax_ref)
  18. : Npts(Npts_ref), lambdamax(lambdamax_ref), lambda(Vect_DP(Npts)), dlambda(Vect_DP(0.0, Npts)), value(Vect_DP(0.0, Npts)),
  19. prev_value(Vect_DP(0.0, Npts)), diff(1.0e+6), value_infty_set(false), value_infty(0.0)
  20. {
  21. for (int i = 0; i < value.size(); ++i) {
  22. lambda[i] = lambdamax * (-(Npts - 1.0) + 2*i)/Npts;
  23. dlambda[i] = 2.0 * lambdamax/Npts;
  24. }
  25. }
  26. Root_Density& Root_Density::operator= (const Root_Density& RefDensity)
  27. {
  28. if (this != &RefDensity) {
  29. Npts = RefDensity.Npts;
  30. lambdamax = RefDensity.lambdamax;
  31. lambda = RefDensity.lambda;
  32. dlambda = RefDensity.dlambda;
  33. value = RefDensity.value;
  34. prev_value = RefDensity.prev_value;
  35. diff = RefDensity.diff;
  36. value_infty_set = RefDensity.value_infty_set;
  37. value_infty = RefDensity.value_infty;
  38. }
  39. return(*this);
  40. }
  41. DP Root_Density::Return_Value (DP lambda_ref)
  42. {
  43. // This function returns a value for epsilon at any real lambda
  44. // using simple linear interpolation.
  45. // Degree 3 polynomical also programmed in, but commented out: no improvement.
  46. DP answer = 0.0;
  47. if (fabs(lambda_ref) >= fabs(lambda[0])) {
  48. if (value_infty_set) answer = value_infty;
  49. else ABACUSerror("Need to set asymptotics of Root_Density !");
  50. }
  51. else { // try to find the i such that lambda[i] <= lambda_ref < lambda[i+1]
  52. int index = (Npts - 1)/2;
  53. int indexstep = (Npts - 1)/4 + 1;
  54. while (indexstep >= 1) {
  55. if ( // if is "lower": we go up
  56. lambda_ref >= lambda[index + 1]) {
  57. index += indexstep;
  58. }
  59. else if ( // if is "higher" or equal: we go down
  60. lambda[index] > lambda_ref) {
  61. index -= indexstep;
  62. }
  63. index = ABACUS::max(0, index);
  64. index = ABACUS::min(Npts - 2, index);
  65. if (indexstep == 1) indexstep--;
  66. else indexstep = (indexstep + 1)/2;
  67. } // while ...
  68. if (index < 0 || index >= Npts || lambda[index] > lambda_ref || lambda[index + 1] < lambda_ref) {
  69. cout << "Seeking index: " << index << "\t" << lambda[index] << "\t <=? " << lambda_ref
  70. << "\t<? " << lambda[index + 1] << endl;
  71. ABACUSerror("Calculating index wrong in Root_Density::Evaluate.");
  72. }
  73. answer = ((value[index] * (lambda[index+1] - lambda_ref)
  74. + value[index + 1] * (lambda_ref - lambda[index]))/(lambda[index+1] - lambda[index]));
  75. }
  76. return(answer);
  77. }
  78. void Root_Density::Set_Asymptotics (DP value_infty_ref)
  79. {
  80. value_infty = value_infty_ref;
  81. value_infty_set = true;
  82. }
  83. Root_Density Root_Density::Compress_and_Match_Densities (DP comp_factor)
  84. {
  85. // Returns a 'compressed' version of the density, using 1/comp_factor as many points.
  86. int Npts_used = int(2.0 * lambdamax/(dlambda[0] * comp_factor));
  87. Root_Density compressed_density(Npts_used, lambdamax);
  88. compressed_density.Set_Asymptotics (value_infty);
  89. for (int i = 0; i < compressed_density.Npts; ++i)
  90. compressed_density.value[i] = (*this).Return_Value (compressed_density.lambda[i]);
  91. return(compressed_density);
  92. }
  93. void Root_Density::Save (const char* outfile_Cstr)
  94. {
  95. ofstream outfile;
  96. outfile.open(outfile_Cstr);
  97. outfile.precision(16);
  98. for (int i = 0; i < Npts; ++i) {
  99. if (i > 0) outfile << endl;
  100. outfile << setw(20) << lambda[i] << "\t" << setw(20) << value[i];
  101. }
  102. outfile.close();
  103. }
  104. Root_Density_Set::Root_Density_Set () : ntypes(1), epsilon(Vect<Root_Density> (ntypes)), Npts_total(0), diff(1.0e+6)
  105. {
  106. }
  107. Root_Density_Set::Root_Density_Set (int ntypes_ref, int Npts_ref, DP lambdamax_ref)
  108. : ntypes(ntypes_ref), epsilon(Vect<Root_Density> (ntypes_ref)), Npts_total(ntypes_ref * Npts_ref), diff(1.0e+6)
  109. {
  110. for (int n = 0; n < ntypes; ++n) epsilon[n] = Root_Density(Npts_ref, lambdamax_ref);
  111. }
  112. Root_Density_Set::Root_Density_Set (int ntypes_ref, Vect_INT Npts_ref, Vect_DP lambdamax_ref)
  113. : ntypes(ntypes_ref), epsilon(Vect<Root_Density> (ntypes_ref)), Npts_total(Npts_ref.sum()), diff(1.0e+6)
  114. {
  115. if (Npts_ref.size() != ntypes_ref || lambdamax_ref.size() != ntypes_ref)
  116. ABACUSerror("Wrong vector sizes in Root_Density_Set.");
  117. for (int n = 0; n < ntypes; ++n) epsilon[n] = Root_Density(Npts_ref[n], lambdamax_ref[n]);
  118. }
  119. Root_Density_Set& Root_Density_Set::operator= (const Root_Density_Set& RefSet)
  120. {
  121. if (this != &RefSet) {
  122. ntypes = RefSet.ntypes;
  123. epsilon = RefSet.epsilon;
  124. Npts_total = RefSet.Npts_total;
  125. diff = RefSet.diff;
  126. }
  127. return(*this);
  128. }
  129. void Root_Density_Set::Insert_new_function (DP asymptotic_value)
  130. {
  131. // This function extends a set by adding one epsilon_n function on top
  132. Root_Density_Set Updated_Set (ntypes + 1, 10, 10.0); // last two parameters are meaningless
  133. for (int n = 0; n < ntypes; ++n) Updated_Set.epsilon[n] = epsilon[n];
  134. Updated_Set.epsilon[ntypes] = Root_Density (50, epsilon[ntypes - 1].lambdamax);
  135. Updated_Set.epsilon[ntypes].Set_Asymptotics (asymptotic_value);
  136. for (int i = 0; i < Updated_Set.epsilon[ntypes].Npts; ++i)
  137. Updated_Set.epsilon[ntypes].value[i] = Updated_Set.epsilon[ntypes].value_infty;
  138. ntypes = Updated_Set.ntypes;
  139. epsilon = Updated_Set.epsilon;
  140. Npts_total+= Updated_Set.epsilon[ntypes - 1].Npts;
  141. }
  142. void Root_Density_Set::Extend_limits (Vect<bool> need_to_extend_limit)
  143. {
  144. // Extend the limits of integration at each level, according to boolean
  145. // The function extends the limits by 10% on both sides, putting the
  146. // extra values to value_infty.
  147. if (need_to_extend_limit.size() != epsilon.size())
  148. ABACUSerror("Wrong size need_to_extend_limit boolean in Extend_limits.");
  149. Vect_INT nr_new_points_needed(0, ntypes);
  150. int total_nr_new_points_added = 0;
  151. DP dlambda_used = 0.0;
  152. for (int n = 0; n < ntypes; ++n) {
  153. if (need_to_extend_limit[n]) {
  154. Root_Density epsilon_n_before_update = epsilon[n];
  155. // Determine the dlambda to be used:
  156. dlambda_used = epsilon[n].dlambda[0];
  157. // How many new points do we add ? Say 5\% on each side:
  158. nr_new_points_needed[n] = ABACUS::max(1, epsilon[n].Npts/20);
  159. epsilon[n] = Root_Density(epsilon_n_before_update.Npts + 2* nr_new_points_needed[n],
  160. epsilon_n_before_update.lambdamax + nr_new_points_needed[n] * dlambda_used);
  161. epsilon[n].Set_Asymptotics(epsilon_n_before_update.value_infty);
  162. for (int i = 0; i < nr_new_points_needed[n]; ++i) {
  163. epsilon[n].lambda[i] = epsilon_n_before_update.lambda[0] - (nr_new_points_needed[n] - i) * dlambda_used;
  164. epsilon[n].dlambda[i] = dlambda_used;
  165. epsilon[n].value[i] = epsilon_n_before_update.value_infty;
  166. }
  167. for (int i = 0; i < epsilon_n_before_update.Npts; ++i) {
  168. epsilon[n].lambda[i + nr_new_points_needed[n] ] = epsilon_n_before_update.lambda[i];
  169. epsilon[n].dlambda[i + nr_new_points_needed[n] ] = epsilon_n_before_update.dlambda[i];
  170. epsilon[n].value[i + nr_new_points_needed[n] ] = epsilon_n_before_update.value[i];
  171. }
  172. for (int i = 0; i < nr_new_points_needed[n]; ++i) {
  173. epsilon[n].lambda[i + epsilon_n_before_update.Npts + nr_new_points_needed[n] ]
  174. = epsilon_n_before_update.lambda[epsilon_n_before_update.Npts - 1] + (i+1.0) * dlambda_used;
  175. epsilon[n].dlambda[i + epsilon_n_before_update.Npts + nr_new_points_needed[n] ] = dlambda_used;
  176. epsilon[n].value[i + epsilon_n_before_update.Npts + nr_new_points_needed[n] ] = epsilon_n_before_update.value_infty;
  177. }
  178. total_nr_new_points_added += 2 * nr_new_points_needed[n];
  179. } // if (need
  180. } // for n
  181. Npts_total += total_nr_new_points_added;
  182. // Done !
  183. return;
  184. }
  185. void Root_Density_Set::Insert_new_points (Vect<Vect<bool> > need_new_point_around)
  186. {
  187. // need_new_point_around specifies whether a new point needs to be inserted around existing points.
  188. // Count the number of new points needed per type:
  189. Vect_INT nr_new_points_needed(0, ntypes);
  190. int total_nr_new_points_needed = 0;
  191. for (int n = 0; n < ntypes; ++n) {
  192. if (need_new_point_around[n].size() != epsilon[n].Npts)
  193. ABACUSerror("Wrong size need_new_point_around boolean in Insert_new_points.");
  194. for (int i = 0; i < epsilon[n].Npts; ++i)
  195. if (need_new_point_around[n][i]) nr_new_points_needed[n]++;
  196. total_nr_new_points_needed += nr_new_points_needed[n];
  197. }
  198. // Working version using non-equispaced points
  199. // Now update all data via interpolation:
  200. for (int n = 0; n < ntypes; ++n) {
  201. Root_Density epsilon_n_before_update = epsilon[n];
  202. epsilon[n] = Root_Density(epsilon_n_before_update.Npts + nr_new_points_needed[n], epsilon_n_before_update.lambdamax);
  203. epsilon[n].Set_Asymptotics(epsilon_n_before_update.value_infty);
  204. int nr_pts_added_n = 0;
  205. for (int i = 0; i < epsilon_n_before_update.Npts; ++i) {
  206. if (!need_new_point_around[n][i]) {
  207. epsilon[n].lambda[i + nr_pts_added_n] = epsilon_n_before_update.lambda[i];
  208. epsilon[n].dlambda[i + nr_pts_added_n] = epsilon_n_before_update.dlambda[i];
  209. epsilon[n].value[i + nr_pts_added_n] = epsilon_n_before_update.value[i];
  210. }
  211. else if (need_new_point_around[n][i]) {
  212. epsilon[n].lambda[i + nr_pts_added_n] = epsilon_n_before_update.lambda[i] - 0.25 * epsilon_n_before_update.dlambda[i];
  213. epsilon[n].dlambda[i + nr_pts_added_n] = 0.5 * epsilon_n_before_update.dlambda[i];
  214. epsilon[n].value[i + nr_pts_added_n] = epsilon_n_before_update.Return_Value(epsilon[n].lambda[i + nr_pts_added_n]);
  215. nr_pts_added_n++;
  216. epsilon[n].lambda[i + nr_pts_added_n] = epsilon_n_before_update.lambda[i] + 0.25 * epsilon_n_before_update.dlambda[i];
  217. epsilon[n].dlambda[i + nr_pts_added_n] = 0.5 * epsilon_n_before_update.dlambda[i];
  218. epsilon[n].value[i + nr_pts_added_n] = epsilon_n_before_update.Return_Value(epsilon[n].lambda[i + nr_pts_added_n]);
  219. }
  220. }
  221. if (nr_pts_added_n != nr_new_points_needed[n]) {
  222. cout << nr_pts_added_n << "\t" << nr_new_points_needed[n] << endl;
  223. ABACUSerror("Wrong counting of new points in Insert_new_points.");
  224. }
  225. } // for n
  226. Npts_total += total_nr_new_points_needed;
  227. // Done !
  228. return;
  229. }
  230. DP Root_Density_Set::Return_Value (int n_ref, DP lambda_ref)
  231. {
  232. // Returns a value, no matter what !
  233. if (n_ref < ntypes) return(epsilon[n_ref].Return_Value(lambda_ref));
  234. else // assume asymptotic form of epsilon, proportional to n
  235. return(epsilon[ntypes - 1].Return_Value(lambda_ref) * n_ref/(ntypes - 1.0));
  236. }
  237. Root_Density_Set Root_Density_Set::Return_Compressed_and_Matched_Set (DP comp_factor)
  238. {
  239. // Returns a set with 1/comp_factor as many points at each level
  240. if (comp_factor >= 2.0)
  241. ABACUSerror("Compression factor too large in Return_Compressed_and_Matched_Set, numerical instability will occur.");
  242. Vect_INT nrpts_comp (ntypes);
  243. Vect_DP lambdamax_comp (ntypes);
  244. for (int n = 0; n < ntypes; ++n) {
  245. nrpts_comp[n] = int(2.0 * epsilon[n].lambdamax/(epsilon[n].dlambda[0] * comp_factor));
  246. lambdamax_comp[n] = epsilon[n].lambdamax;
  247. }
  248. Root_Density_Set Compressed_and_Matched_Set (ntypes, nrpts_comp, lambdamax_comp);
  249. for (int n = 0; n < ntypes; ++n)
  250. Compressed_and_Matched_Set.epsilon[n] = (*this).epsilon[n].Compress_and_Match_Densities (comp_factor);
  251. return(Compressed_and_Matched_Set);
  252. }
  253. void Root_Density_Set::Match_Densities (Root_Density_Set& RefSet)
  254. {
  255. // matched densities to those in RefSet
  256. for (int n = 0; n < ntypes; ++n)
  257. for (int i = 0; i < epsilon[n].Npts; ++i)
  258. epsilon[n].value[i] = RefSet.epsilon[n].Return_Value(epsilon[n].lambda[i]);
  259. }
  260. void Root_Density_Set::Save (const char* outfile_Cstr)
  261. {
  262. ofstream outfile;
  263. outfile.open(outfile_Cstr);
  264. outfile.precision(16);
  265. // Determine what the maximal nr of pts is:
  266. int Npts_n_max = 0;
  267. for (int n = 0; n < ntypes; ++n) Npts_n_max = ABACUS::max(Npts_n_max, epsilon[n].Npts);
  268. for (int i = 0; i < Npts_n_max; ++i) {
  269. if (i > 0) outfile << endl;
  270. for (int n = 0; n < ntypes; ++n) (i < epsilon[n].Npts) ?
  271. (outfile << epsilon[n].lambda[i] << "\t" << epsilon[n].value[i] << "\t")
  272. : (outfile << 0 << "\t" << 0 << "\t");
  273. }
  274. outfile.close();
  275. }
  276. } // namespace ABACUS