Für Vorlesungen, bitte die Webseite verwenden. https://flavigny.de/lecture
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

162 行
5.3KB

  1. #include <vector>
  2. #include "hdnum.hh" // hdnum header
  3. template<typename REAL>
  4. void solveTriDiag(hdnum::DenseMatrix<REAL> &A, std::vector<REAL> &x, std::vector<REAL> &b) {
  5. int N = b.size();
  6. x[0] = A[0][0];
  7. // LU Zerlegung
  8. REAL l;
  9. for (int j=1; j<N; j++) {
  10. // berechne l faktor
  11. l = A[j][j-1] / x[j-1];
  12. // modifiziere diagonalelemente und rechte seite
  13. x[j] = A[j][j] - l * A[j-1][j];
  14. b[j] = b[j] - l * b[j-1];
  15. }
  16. // Loesen durch Rueckwaertseinsetzen
  17. x[N-1] = b[N-1] / x[N-1];
  18. for (int j=N-2; j>=0; j--) {
  19. x[j] = (b[j] - A[j][j+1]*x[j+1])/x[j];
  20. }
  21. }
  22. template<typename REAL>
  23. class CubicSpline {
  24. public:
  25. // erstelle einen kubischen spline mit vorgegebenen stuetzstellen
  26. // und werten
  27. CubicSpline(std::vector<REAL> xs, std::vector<REAL> ys) {
  28. calculateCoefficients(xs, ys);
  29. }
  30. // erstelle einen kubischen spline mit vorgegebenen stuetzstellen
  31. // und einer zu interpolierenden funktion
  32. CubicSpline(std::vector<REAL> xs, REAL(*f)(REAL)) {
  33. int N = xs.size();
  34. std::vector<double> ys(N);
  35. for (int i=0; i<N; i++) {
  36. ys[i] = f(xs[i]);
  37. }
  38. calculateCoefficients(xs, ys);
  39. }
  40. // erstelle einen kubischen spline an aequidistanten stuetzstellen
  41. // und einer zu interpolierenden funktion
  42. CubicSpline(REAL a, REAL b, int N, REAL(*f)(REAL)) {
  43. std::vector<double> xs(N+1);
  44. std::vector<double> ys(N+1);
  45. for (int i=0; i<=N; i++) {
  46. xs[i] = a + (1.0*i)/N*(b-a);
  47. ys[i] = f(xs[i]);
  48. }
  49. calculateCoefficients(xs, ys);
  50. }
  51. // werte kubischen spline an vorgegebener stelle aus
  52. REAL evaluate(REAL x) {
  53. for (int i=1; i<x_s.size(); i++) {
  54. if (x > x_s[i] && i < x_s.size() - 1) {
  55. continue;
  56. } else {
  57. return a_0[i-1] + a_1[i-1] *(x - x_s[i]) + a_2[i-1]*std::pow(x - x_s[i], 2) + a_3[i-1]*std::pow(x-x_s[i], 3);
  58. }
  59. }
  60. return 0;
  61. }
  62. // gebe alle interpolations polynome aus
  63. void print() {
  64. for(int i=0; i<x_s.size()-1; i++) {
  65. printf("p_%d(x) = %4.2f + %4.2f(x - %4.2f) + %4.2f(x - %4.2f)^2 + %4.2f(x - %4.2f)^3\n",
  66. i, a_0[i], a_1[i], x_s[i], a_2[i], x_s[i], a_3[i], x_s[i]);
  67. }
  68. }
  69. private:
  70. // stuetzstellen
  71. std::vector<REAL> x_s;
  72. // koeffizienten
  73. std::vector<REAL> a_0;
  74. std::vector<REAL> a_1;
  75. std::vector<REAL> a_2;
  76. std::vector<REAL> a_3;
  77. void calculateCoefficients(std::vector<REAL> xs, std::vector<REAL> ys) {
  78. // stuetzstellen from x_0 ... to x_n
  79. int n = xs.size()-1;
  80. // copy stuetzstellen
  81. x_s = std::vector<double>(n+1);
  82. x_s = xs;
  83. // setup (n-1)x(n-1) matrix for a_2
  84. hdnum::DenseMatrix<REAL> A(n-1,n-1);
  85. std::vector<REAL> b(n-1);
  86. std::vector<REAL> x(n-1);
  87. REAL h; // h_i
  88. REAL h1; // h_{i+1}
  89. // setup LGS for a_2
  90. // A has tridiagonal structure
  91. for (int i = 1; i<n; i++) {
  92. h = xs[i] - xs[i-1];
  93. h1 = xs[i+1] - xs[i];
  94. b[i-1] = 3 * ((ys[i+1] - ys[i])/h1 - (ys[i] - ys[i-1])/h);
  95. if (i > 1) {
  96. A[i-1][i-2] = h;
  97. } if (i < n-1) {
  98. A[i-1][i] = h1;
  99. }
  100. A[i-1][i-1] = 2 * (h + h1);
  101. }
  102. // initialize vectors
  103. a_0 = std::vector<double>(n);
  104. a_1 = std::vector<double>(n);
  105. a_2 = std::vector<double>(n);
  106. a_3 = std::vector<double>(n);
  107. solveTriDiag(A,a_2,b);
  108. // natuerliche randbedingung
  109. a_2[n-1] = 0;
  110. // berechne restliche koeffizienten
  111. for (int i = 1; i<=n; i++) {
  112. h = xs[i] - xs[i-1]; // h_i
  113. h1 = xs[i+1] - xs[i]; // h_{i+1}
  114. a_0[i-1] = ys[i];
  115. if (i == 1) { // a_2[-1] = 0
  116. a_1[i-1] = (ys[i] - ys[i-1])/h + (h/3)*(2*a_2[i-1]);
  117. a_3[i-1] = (a_2[i-1])/(3*h);
  118. } else {
  119. a_1[i-1] = (ys[i] - ys[i-1])/h + h/3*(2*a_2[i-1] + a_2[i-2]);
  120. a_3[i-1] = (a_2[i-1] - a_2[i-2])/(3 * h);
  121. }
  122. }
  123. }
  124. };
  125. double f1(double x) {
  126. return std::pow(x,3);
  127. }
  128. int main() {
  129. // std::vector<double> xs = {0, 1, 2};
  130. // CubicSpline<double> phi(xs, f1);
  131. // phi.print();
  132. // saurier fundstellen
  133. std::vector<double> xs = {3.75, 3.75, 2.25, 1.25, 0.25, 0.75, 4.00, 5.50, 6.25, 9.00, 12.5, 12.75, 12.25};
  134. std::vector<double> ys = {0.25, 1.50, 3.25, 4.25, 4.65, 4.83, 2.50, 3.25, 3.65, 3.00, 1.25, 2.150, 3.500};
  135. std::vector<double> ts(13);
  136. ts[0] = 0;
  137. for (int i = 1; i<=12; i++) {
  138. ts[i] = ts[i-1] + std::sqrt(std::pow(xs[i] - xs[i-1], 2) + std::pow(ys[i] - ys[i-1], 2));
  139. }
  140. CubicSpline<double> phi(ts, xs);
  141. CubicSpline<double> psi(ts, ys);
  142. double xi;
  143. for (int j = 0; j<=100; j++) {
  144. xi = j*ts[12] / 100;
  145. std::cout << phi.evaluate(xi) << " " << psi.evaluate(xi) << std::endl;
  146. }
  147. }