Elliptic_integrals.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "Elliptic_integrals.h"
  2. // std::string Error()
  3. // {
  4. // std::string mes = "Error! k should be from -1 to 1";
  5. // std::exception(mes);
  6. // }
  7. /**
  8. * Purpose: Constructor
  9. *
  10. * @return None
  11. * @throws None
  12. */
  13. Elliptic_Integrals::Elliptic_Integrals()
  14. {
  15. }
  16. /**
  17. * Purpose: Destructor
  18. *
  19. * @return None
  20. * @throws None
  21. */
  22. Elliptic_Integrals::~Elliptic_Integrals()
  23. {
  24. }
  25. /**
  26. * Purpose: Compute complete elliptic integrals K(k) and E(k)
  27. *
  28. * @param k - modulus k (-1 <= k <= 1)
  29. * @return Vector with values of K(k) (the first place) and E(k) (the second place)
  30. * @throws "Error! k should be from -1 to 1"
  31. */
  32. std::vector<double> Elliptic_Integrals::CompleteElliptic(const double k)
  33. {
  34. std::vector<double> result;
  35. double PK = 1.0 - k * k;
  36. if ((k > 1) || (k < -1))
  37. {
  38. std::cerr << "Parameter k must be in the range [-1, 1]" << std::endl;
  39. return result;
  40. }
  41. if (k == 1.0)
  42. {
  43. double CK = std::numeric_limits<double>::infinity();
  44. double CE = 1.0;
  45. result.push_back(CK);
  46. result.push_back(CE);
  47. }
  48. else
  49. {
  50. double AK = (((0.01451196212 * PK + 0.03742563713) * PK + 0.03590092383) * PK + 0.09666344259) * PK + 1.38629436112;
  51. double BK = (((0.00441787012 * PK + 0.03328355346) * PK + 0.06880248576) * PK + 0.12498593597) * PK + 0.5;
  52. double CK = AK - BK * log(PK);
  53. double AE = (((0.01736506451 * PK + 0.04757383546) * PK + 0.06260601220) * PK + 0.44325141463) * PK + 1.0;
  54. double BE = (((0.00526449639 * PK + 0.04069697526) * PK + 0.09200180037) * PK + 0.24998368310) * PK;
  55. double CE = AE - BE * log(PK);
  56. result.push_back(CK);
  57. result.push_back(CE);
  58. }
  59. return result;
  60. }
  61. /**
  62. * Purpose: Compute elliptic integrals F(phi, k) and E(phi, k)
  63. *
  64. * @param k - modulus k (-1 <= k <= 1)
  65. * @param phi - argument (in degrees)
  66. * @return Vector with values of F(phi, k)) (the first place) and E(phi, k) (the second place)
  67. * @throws "Error! k should be from -1 to 1"
  68. */
  69. std::vector<double> Elliptic_Integrals::Elliptic(const double phi, const double k)
  70. {
  71. std::vector<double> result;
  72. if ((k > 1) || (k < -1))
  73. {
  74. std::cerr << "Parameter k must be in the range [-1, 1]" << std::endl;
  75. return result;
  76. }
  77. double G = 0.0;
  78. double pi = M_PI;
  79. double A0 = 1.0;
  80. double B0 = sqrt(1.0 - k * k);
  81. double D0 = pi / 180.0 * phi;
  82. double R = k * k;
  83. if (k == 1 and phi == 90)
  84. {
  85. double FE = std::numeric_limits<double>::infinity();
  86. double EE = 1.0;
  87. result.push_back(FE);
  88. result.push_back(EE);
  89. }
  90. else if (k == 1)
  91. {
  92. double FE = log((1.0 + sin(D0)) / cos(D0));
  93. double EE = sin(D0);
  94. result.push_back(FE);
  95. result.push_back(EE);
  96. }
  97. else
  98. {
  99. double FAC = 1.0;
  100. double A;
  101. double B;
  102. double C;
  103. double D;
  104. for (int k = 1; k <= 1000; k++)
  105. {
  106. A = (A0 + B0) / 2.0;
  107. B = sqrt(A0 * B0);
  108. C = (A0 - B0) / 2.0;
  109. FAC = 2.0 * FAC;
  110. R = R + FAC * C * C;
  111. if (phi != 90)
  112. {
  113. D = D0 + atan((B0 / A0) * tan(D0));
  114. G = G + C * sin(D);
  115. D0 = D + pi * int(D / pi + 0.5);
  116. }
  117. A0 = A;
  118. B0 = B;
  119. if (C < 1e-7) goto stop;
  120. continue;
  121. }
  122. stop:
  123. double CK = pi / (2.0 * A);
  124. double CE = pi * (2.0 - R) / (4.0 * A);
  125. if (phi == 90)
  126. {
  127. double FE = CK;
  128. double EE = CE;
  129. result.push_back(FE);
  130. result.push_back(EE);
  131. }
  132. else
  133. {
  134. double FE = D / (FAC * A);
  135. double EE = FE * CE / CK + G;
  136. result.push_back(FE);
  137. result.push_back(EE);
  138. }
  139. }
  140. return result;
  141. }