Elliptic_integrals.cpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "Elliptic_integrals.h"
  2. /**
  3. * Purpose: Compute elliptic integrals F(phi, k) and E(phi, k). Take from Shanjie Zhang, Jian-Ming Jin, "Computation of Special Functions", page 664-665
  4. *
  5. * @param k - modulus k (-1 <= k <= 1)
  6. * @param phi - argument (in degrees), 0 <= phi <= 90
  7. * @return Vector with values of F(phi, k)) (the first place) and E(phi, k) (the second place)
  8. * @throws "Error! k should be from -1 to 1", "Error! phi should be from 0 to 90"
  9. */
  10. std::vector<double> Elliptic(const double phi, const double k)
  11. {
  12. std::vector<double> result;
  13. if ((phi > 90) || (phi < 0))
  14. {
  15. std::cerr << "Parameter phi must be in the range [0, 90]" << std::endl;
  16. return result;
  17. }
  18. if ((k > 1) || (k < -1))
  19. {
  20. std::cerr << "Parameter k must be in the range [-1, 1]" << std::endl;
  21. return result;
  22. }
  23. double G = 0.0;
  24. double pi = M_PI;
  25. double A0 = 1.0;
  26. double B0 = sqrt(1.0 - k * k);
  27. double D0 = pi / 180.0 * phi;
  28. double R = k * k;
  29. if (k == 1 and phi == 90)
  30. {
  31. double FE = std::numeric_limits<double>::infinity();
  32. double EE = 1.0;
  33. result.push_back(FE);
  34. result.push_back(EE);
  35. }
  36. else if (k == 1)
  37. {
  38. double FE = log((1.0 + sin(D0)) / cos(D0));
  39. double EE = sin(D0);
  40. result.push_back(FE);
  41. result.push_back(EE);
  42. }
  43. else
  44. {
  45. double FAC = 1.0;
  46. double A;
  47. double B;
  48. double C;
  49. double D;
  50. for (int k = 1; k <= 1000; k++)
  51. {
  52. A = (A0 + B0) / 2.0;
  53. B = sqrt(A0 * B0);
  54. C = (A0 - B0) / 2.0;
  55. FAC = 2.0 * FAC;
  56. R = R + FAC * C * C;
  57. if (phi != 90)
  58. {
  59. D = D0 + atan((B0 / A0) * tan(D0));
  60. G = G + C * sin(D);
  61. D0 = D + pi * int(D / pi + 0.5);
  62. }
  63. A0 = A;
  64. B0 = B;
  65. if (C < 1e-7) goto stop;
  66. continue;
  67. }
  68. stop:
  69. double CK = pi / (2.0 * A);
  70. double CE = pi * (2.0 - R) / (4.0 * A);
  71. if (phi == 90)
  72. {
  73. double FE = CK;
  74. double EE = CE;
  75. result.push_back(FE);
  76. result.push_back(EE);
  77. }
  78. else
  79. {
  80. double FE = D / (FAC * A);
  81. double EE = FE * CE / CK + G;
  82. result.push_back(FE);
  83. result.push_back(EE);
  84. }
  85. }
  86. return result;
  87. }