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.

Richardson.cc 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: src/RICHARDSON/Rischardson.cc
  6. Purpose: Richardson model
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. using namespace ABACUS;
  11. namespace ABACUS {
  12. bool Solve_Richardson_Quad_S (DP g_int, const Vect_DP epsilon, const Vect_DP sumoneovereps,
  13. const Vect_CX S, const Vect_CX sumSovereps, int j, complex<DP>& Sjleft, complex<DP>& Sjright)
  14. {
  15. // This solves the equation
  16. // S^2_j - \sum_{i \neq j}^N \frac{S_j - S_i}{\epsilon_j - \epsilon_i} - (1/g) S_j = 0.
  17. // for S_j, and puts the result in Sj.
  18. // If the result is real, true is returned, otherwise false.
  19. //DP bquad = -1.0/g_int - sumoneovereps[j];
  20. //DP cquad = sumSovereps[j];
  21. /*
  22. DP discr = 0.0;
  23. bool retval = false;
  24. //if ((discr = bquad * bquad - 4.0 * cquad) >= 0.0) {
  25. if ((discr = (1.0/g_int + sumoneovereps[j]) * (1.0/g_int + sumoneovereps[j]) - 4.0 * sumSovereps[j]) >= 0.0) {
  26. discr = sqrt(discr);
  27. Sjleft = 0.5 * (-(1.0/g_int + sumoneovereps[j]) - discr);
  28. Sjright = 0.5 * (-(1.0/g_int + sumoneovereps[j]) + discr);
  29. retval = true;
  30. }
  31. return(retval);
  32. */
  33. complex<DP> discr = sqrt((1.0/g_int + sumoneovereps[j]) * (1.0/g_int + sumoneovereps[j]) - 4.0 * sumSovereps[j]);
  34. Sjleft = 0.5 * (1.0/g_int + sumoneovereps[j] - discr);
  35. Sjright = 0.5 * (1.0/g_int + sumoneovereps[j] + discr);
  36. return(true);
  37. }
  38. bool Solve_Richardson_Quad_S (DP g_int, const Vect_DP epsilon, Vect_CX& S, Vect<bool> leftroot, DP req_prec)
  39. {
  40. // This solves the set of equations
  41. // S^2_j - \sum_{i \neq j}^N \frac{S_j - S_i}{\epsilon_j - \epsilon_i} - (1/g) S_j = 0.
  42. int Nlevels = epsilon.size();
  43. Vect_DP absLHSRE (Nlevels); // absolute value of left-hand side of Richardson eqns for S_j written as LHSRE == 0.
  44. Vect_DP sumoneovereps (0.0, Nlevels);
  45. Vect_CX sumSovereps (Nlevels);
  46. for (int j = 0; j < Nlevels; ++j) {
  47. sumoneovereps[j] = 0.0;
  48. for (int i = 0; i < Nlevels; ++i) if (i != j) sumoneovereps[j] += 1.0/(epsilon[j] - epsilon[i]);
  49. sumSovereps[j] = 0.0;
  50. for (int i = 0; i < Nlevels; ++i) if (i != j) sumSovereps[j] += S[i]/(epsilon[j] - epsilon[i]);
  51. }
  52. DP maxabsLHSRE = 0.0;
  53. int jmax = 0;
  54. complex<DP> Sleft, Sright;
  55. DP damping = 1.0;
  56. do {
  57. // Calculate the deviations, identify the largest:
  58. maxabsLHSRE = 0.0;
  59. for (int j = 0; j < Nlevels; ++j) {
  60. absLHSRE[j] = abs(S[j] * S[j] - S[j] * sumoneovereps[j] + sumSovereps[j] - S[j]/g_int);
  61. if (absLHSRE[j] > maxabsLHSRE) {
  62. maxabsLHSRE = absLHSRE[j];
  63. jmax = j;
  64. }
  65. }
  66. cout << "identified jmax = " << jmax << " with maxabsLHSRE = " << maxabsLHSRE << endl;
  67. cout << "S[jmax]: from " << S[jmax];
  68. // Re-solve for jmax:
  69. if (Solve_Richardson_Quad_S (g_int, epsilon, sumoneovereps, S, sumSovereps, jmax, Sleft, Sright)) {
  70. if (abs(S[jmax] - Sleft) < abs(S[jmax] - Sright)) S[jmax] = damping * Sleft + (1.0 - damping) * S[jmax];
  71. else S[jmax] = damping * Sright + (1.0 - damping) * S[jmax];
  72. }
  73. else {
  74. ABACUSerror("Complex jmax root.");
  75. }
  76. cout << " to " << S[jmax] << endl;
  77. // Re-solve also for a random j, given by
  78. int jrand = rand() % Nlevels;
  79. cout << "identified jrand = " << jrand << endl;
  80. cout << "S[jrand]: from " << S[jrand];
  81. if (Solve_Richardson_Quad_S (g_int, epsilon, sumoneovereps, S, sumSovereps, jrand, Sleft, Sright)) {
  82. if (abs(S[jrand] - Sleft) < abs(S[jrand] - Sright)) S[jrand] = damping * Sleft + (1.0 - damping) * S[jrand];
  83. else S[jrand] = damping * Sright + (1.0 - damping) * S[jrand];
  84. }
  85. else {
  86. ABACUSerror("Complex jrand root.");
  87. }
  88. cout << " to " << S[jrand] << endl;
  89. // Recalculate all sums:
  90. for (int j = 0; j < Nlevels; ++j) {
  91. sumSovereps[j] = 0.0;
  92. for (int i = 0; i < Nlevels; ++i) if (i != j) sumSovereps[j] += S[i]/(epsilon[j] - epsilon[i]);
  93. }
  94. } while (maxabsLHSRE > req_prec);
  95. return(true);
  96. }
  97. } // namespace ABACUS
  98. int main ()
  99. {
  100. DP g_int = 0.1;
  101. int Nlevels = 10;
  102. Vect_DP epsilon (Nlevels);
  103. for (int i = 0; i < Nlevels; ++i) epsilon[i] = -0.5 * (Nlevels - 1.0) + i;
  104. DP req_prec = 1.0e-10;
  105. Vect_CX S (2.0, Nlevels);
  106. // Initial conditions:
  107. /*
  108. // Sa252 g = 0.78
  109. S[0] = -0.6142;
  110. S[1] = -0.7344;
  111. S[2] = -0.9177;
  112. S[3] = -1.2414;
  113. S[4] = -2.06103;
  114. S[5] = 3.06103;
  115. S[6] = 2.2414;
  116. S[7] = 1.9178;
  117. S[8] = 1.7344;
  118. S[9] = 1.6142;
  119. //for (int j = 0; j < Nlevels; ++j) S[j] /= g_int;
  120. */
  121. Vect<bool> leftroot (true, Nlevels);
  122. //for (int j = Nlevels/2; j < Nlevels; ++j) leftroot[j] = true;
  123. leftroot[0] = 0;
  124. leftroot[1] = 1;
  125. leftroot[2] = 0;
  126. leftroot[3] = 1;
  127. leftroot[4] = 0;
  128. leftroot[5] = 1;
  129. leftroot[6] = 1;
  130. leftroot[7] = 1;
  131. leftroot[8] = 1;
  132. leftroot[9] = 1;
  133. //for (int j = 0; j < Nlevels; ++j) leftroot[j] = !leftroot[j];
  134. cout << Solve_Richardson_Quad_S (g_int, epsilon, S, leftroot, req_prec) << endl;
  135. cout << leftroot << endl;
  136. for (int j = 0; j < Nlevels; ++j) S[j] *= g_int;
  137. cout << S << endl;
  138. return(0);
  139. }