Advertisement
Guest User

Untitled

a guest
Apr 26th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.10 KB | None | 0 0
  1. #include <iostream>
  2. #include <cmath>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. // коэффициенты для прогоночной матрицы
  8. // tma (tridiagonal matrix algorithm) - метод прогонки
  9. struct tma{
  10.     double a;
  11.     double b;
  12.     double c;
  13.     double f;
  14. };
  15.  
  16. // вспомогательные прогоночные коэффициенты
  17. // forward sweep - прямая прогонка
  18. struct sweep{
  19.     double X;
  20.     double Z;
  21. };
  22.  
  23. // приближённое решение в узлах сетки
  24. struct dots{
  25.     double x;
  26.     double y;
  27. };
  28.  
  29. // граничные условия
  30. struct boundary{
  31.     double alpha_0;
  32.     double alpha_1;
  33.     double beta_0;
  34.     double beta_1;
  35.     double gamma_0;
  36.     double gamma_1;
  37. };
  38.  
  39. // вспомогательные коэффициенты
  40. struct additional{
  41.     double a;
  42.     double d;
  43.     double phi;
  44. };
  45.  
  46. // функция при первой производной
  47. double k(double x)
  48. {
  49.     return 1.0;
  50. }
  51.  
  52. // функция при "нулевой" производной
  53. double q(double x)
  54. {
  55.     return -4.0;
  56. }
  57.  
  58. // неоднородность в правой части уравнения
  59. double f(double x)
  60. {
  61.     return -cos(2.0 * x);
  62. }
  63.  
  64. // инициализация сетки
  65. void initGrid(vector<dots> &grid, double a, double h, size_t N)
  66. {
  67.     dots temp;
  68.  
  69.     for (size_t i = 0; i <= N; i++)
  70.     {
  71.         temp.x = a + i * h;
  72.         temp.y = 0.0;
  73.         grid.push_back(temp);
  74.     }
  75. }
  76.  
  77. // вычисление вспомогательных коэффициентов для метода прямоугольников
  78. void fillRectangle(vector<additional> &rectangle, const vector<dots> &grid, double h, size_t N)
  79. {
  80.     additional temp;
  81.     for (size_t i = 0; i < N; i++)
  82.     {
  83.         temp.a = k(grid[i + 1].x - 0.5 * h);
  84.         temp.d = q(grid[i + 1].x);
  85.         temp.phi = f(grid[i + 1].x);
  86.  
  87.         rectangle.push_back(temp);
  88.     }
  89. }
  90.  
  91. // вычисление вспомогательных коэффициентов для метода трапеций
  92. void fillTrapezium(vector<additional> &trapezium, const vector<dots> &grid, double h, size_t N)
  93. {
  94.     additional temp;
  95.     for (size_t i = 0; i < N; i++)
  96.     {
  97.         temp.a = 2.0 * k(grid[i + 1].x) * k(grid[i].x) / (k(grid[i + 1].x) + k(grid[i].x));
  98.         temp.d = (q(grid[i + 1].x - h / 2.0) + q(grid[i + 1].x + h / 2.0)) / 2.0;
  99.         temp.phi = (f(grid[i + 1].x - h / 2.0) + f(grid[i + 1].x + h / 2.0));
  100.  
  101.         trapezium.push_back(temp);
  102.     }
  103. }
  104.  
  105. // заполняется матрица коэффициентов
  106. void fillMatrix(vector<tma> &matrix, const vector<additional> &method, double h, size_t N)
  107. {
  108.     tma temp;
  109.  
  110.     for (size_t i = 0; i < N - 1; i++)                                  // Из N (количества точек разбиения) вычитается 1,
  111.     {                                                                   // так как число строк в прогоночной матрице на 1 меньше N
  112.         temp.a = method[i + 1].a / pow(h, 2.0);                         // и коэффициенты нумеруются с цифры 1.
  113.         temp.b = -(method[i + 1].a + method[i].a) / pow(h, 2.0)         // Коэффициенты с индексами 0 и N
  114.                  - method[i].d;                                         // используются при задании граничных условий.
  115.         temp.c = method[i].a / pow(h, 2.0);                             //
  116.         temp.f = method[i].phi;                                         //
  117.         matrix.push_back(temp);
  118.     }
  119. }
  120.  
  121. // заполняется вектор прогоночных коэффициентов
  122. void fillSweepCoefficients(vector<sweep> &coefficients, const vector<tma> &matrix, boundary conditions)
  123. {
  124.     size_t N = matrix.size();
  125.     sweep temp;
  126.     temp.X = -conditions.beta_0 / conditions.alpha_0;
  127.     temp.Z = conditions.gamma_0 / conditions.alpha_0;
  128.     coefficients.push_back(temp);
  129.  
  130.     for (size_t i = 0; i < N; i++)
  131.     {
  132.         temp.X = -matrix[i].a / (matrix[i].b + matrix[i].c * coefficients[i].X);
  133.         temp.Z = (matrix[i].f - matrix[i].c * coefficients[i].Z) / (matrix[i].b + matrix[i].c * coefficients[i].X);
  134.         coefficients.push_back(temp);
  135.     }
  136. }
  137.  
  138. // обратная прогонка, заполнение вектора значений искомой функции
  139. void fillSolution(const vector<sweep> &coefficients, vector<dots> &grid, boundary conditions, double a, double h)
  140. {
  141.     size_t N = coefficients.size();
  142.  
  143.     double y = (conditions.gamma_1 - conditions.alpha_1 * coefficients.back().Z) / (conditions.beta_1 + conditions.alpha_1 * coefficients.back().X);
  144.    
  145.     grid.back().y = y;
  146.  
  147.     for (size_t i = N - 1; i < N; i--)                          // Начинается отсчёт с N-1, так как
  148.     {                                                           // точка с индексом N уже посчитана.
  149.         y = coefficients[i].X * grid[i + 1].y + coefficients[i].Z;
  150.         grid[i].y = y;
  151.     }
  152. }
  153.  
  154. int main()
  155. {
  156.     double pi = 3.1415926;
  157.     size_t N = 2;                                   // число точек разбиения
  158.     double a = .0, b = pi / 4.0;                    // начало и конец отрезка
  159.     double h = (b - a) / N;                         // шаг разбиения
  160.     double mu_1 = pi / 8.0, mu_2 = 0.0, beta = 1.0;
  161.  
  162.     vector<dots> grid_rectangle, grid_trapezium;
  163.     vector<additional> rectangle, trapezium;
  164.     vector<tma> matrix_rectangle, matrix_trapezium;
  165.     vector<sweep> coefficients_rectangle, coefficients_trapezium;
  166.  
  167.     // вычисление коэффициентов с использованием метода прямоугольников
  168.     initGrid(grid_rectangle, a, h, N);
  169.     fillRectangle(rectangle, grid_rectangle, h, N);
  170.     fillMatrix(matrix_rectangle, rectangle, h, N);
  171.  
  172.     boundary conditions_rectangle;
  173.     conditions_rectangle.alpha_0 = beta + q(a) * h / 2.0 + rectangle[0].a / h;
  174.     conditions_rectangle.alpha_1 = 0.0;
  175.     conditions_rectangle.beta_0 = -rectangle[0].a / h;
  176.     conditions_rectangle.beta_1 = 1.0;
  177.     conditions_rectangle.gamma_0 = mu_1 + f(a) * h / 2.0;
  178.     conditions_rectangle.gamma_1 = mu_2;
  179.  
  180.     fillSweepCoefficients(coefficients_rectangle, matrix_rectangle, conditions_rectangle);
  181.     fillSolution(coefficients_rectangle, grid_rectangle, conditions_rectangle, a, h);
  182.  
  183.     // вычисление коэффициентов с использованием метода трапеций
  184.     initGrid(grid_trapezium, a, h, N);
  185.     fillTrapezium(trapezium, grid_trapezium, h, N);
  186.     fillMatrix(matrix_trapezium, trapezium, h, N);
  187.  
  188.     boundary conditions_trapezium;
  189.     conditions_trapezium.alpha_0 = beta + q(a) * h / 2.0 + trapezium[0].a / h;
  190.     conditions_trapezium.alpha_1 = 0.0;
  191.     conditions_trapezium.beta_0 = -trapezium[0].a / h;
  192.     conditions_trapezium.beta_1 = 1.0;
  193.     conditions_trapezium.gamma_0 = mu_1 + f(a) * h / 2.0;
  194.     conditions_trapezium.gamma_1 = mu_2;
  195.  
  196.     fillSweepCoefficients(coefficients_trapezium, matrix_trapezium, conditions_trapezium);
  197.     fillSolution(coefficients_trapezium, grid_trapezium, conditions_trapezium, a, h);
  198.  
  199.     // вывод результатов
  200.     cout.precision(10);
  201.     std::cout.setf(std::ios::fixed, std::ios::floatfield);
  202.     cout << "\t" << "x" << "\t" << "Rectangle method" << "\t" << "Trapezium method" << "\t" << "Analitic" << endl;
  203.     for (size_t i = 0; i <= N; i++)
  204.         cout << grid_rectangle[i].x << "\t" << grid_rectangle[i].y << "\t \t" << grid_trapezium[i].y << "\t \t"
  205.              << sin(2.0 * grid_trapezium[i].x) * (grid_trapezium[i].x / 4.0 - pi / 16.0) << endl;
  206.  
  207.     system("PAUSE");
  208.     return 0;
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement