vatman

Untitled

May 31st, 2024
918
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.88 KB | None | 0 0
  1. #include <cmath>
  2. #include <fstream>
  3. #include <iomanip>
  4. #include <iostream>
  5. #include <ostream>
  6. #include <vector>
  7.  
  8. double f(double x, double y) {
  9.   double T = M_PI * x * y;
  10.   double sin2T = std::pow(std::sin(T), 2);
  11.   double cos2T = std::pow(std::cos(T), 2);
  12.   double y2_x2 = y * y + x * x;
  13.   return -2 * M_PI * std::exp(std::pow(std::sin(T), 2)) *
  14.          (2 * M_PI * y2_x2 * cos2T * sin2T - M_PI * y2_x2 * sin2T +
  15.           M_PI * y2_x2 * cos2T);
  16. }
  17.  
  18. double u(double x, double y) {
  19.   return std::exp(std::pow(std::sin(M_PI * x * y), 2));
  20. }
  21.  
  22. std::vector<std::vector<double>> MinimalResiduals(const int nmax = 1000,
  23.                                                   const double _eps = 0.0000001,
  24.                                                   const int _n = 3,
  25.                                                   const int _m = 3) {
  26.   int Nmax = nmax; // максимальное число итераций (не менее 1)
  27.   std::vector<std::vector<double>> v; // сеточная функция ѵ (x, y)
  28.   v.resize(_n + 1);
  29.   for (size_t i = 0; i < _n + 1; ++i) {
  30.     v[i].resize(_m + 1);
  31.     for (size_t j = 0; j < _m + 1; ++j) {
  32.       v[i][j] = 0;
  33.     }
  34.   }
  35.   std::vector<std::vector<double>> r_vec; // вектор невязки
  36.   r_vec.resize(_n + 1);
  37.   for (size_t i = 0; i < _n + 1; ++i) {
  38.     r_vec[i].resize(_m + 1);
  39.     for (size_t j = 0; j < _m + 1; ++j) {
  40.       r_vec[i][j] = 0;
  41.     }
  42.   }
  43.   std::vector<std::vector<double>> ar; // вектор невязки
  44.   ar.resize(_n + 1);
  45.   for (size_t i = 0; i < _n + 1; ++i) {
  46.     ar[i].resize(_m + 1);
  47.     for (size_t j = 0; j < _m + 1; ++j) {
  48.       ar[i][j] = 0;
  49.     }
  50.   }
  51.   double r1 = 0;
  52.   int S = 0;         // счетчик итераций
  53.   double eps = _eps; // заданная точность
  54.   double eps_max = 0; // точность, достигнутая на текущей итерации
  55.   double eps_cur = 0; // для подсчета точности на текущей итерации
  56.   double a2, k2, h2; // ненулевые элементы матрицы (-А)
  57.   const int n = _n, m = _m; // размерность сетки
  58.   double r_max = 0;
  59.   double a = 0;
  60.   double b = 1;
  61.   double c = 0;
  62.   double d = 1; // границы области определения уравнения
  63.   int i, j; // индексы
  64.   double r = 0;
  65.   double v_old; // старое значение преобразуемой компоненты вектора
  66.   double v_new; // новое значение преобразуемой компоненты вектора и
  67.   bool flag = false; // условие остановки
  68.   double h = ((b - a) / n);
  69.   double k = ((d - c) / m);
  70.   double z = 0;
  71.   double z_max = 0;
  72.   double tau_s = 0;
  73.   double num = 0; // tau=num/denominator
  74.   double denominator = 1;
  75.   double x, y;
  76.   h2 = -std::pow((n / (b - a)), 2);
  77.   k2 = -std::pow((m / (d - c)), 2);
  78.   a2 = -2 * (h2 + k2);
  79.   for (int i = 0; i < n + 1; ++i) {
  80.     v[i][0] = u(a + i * h, a);
  81.     v[i][m] = u(a + i * h, b);
  82.   }
  83.   for (int j = 0; j < m + 1; ++j) {
  84.     v[0][j] = u(c, c + j * k);
  85.     v[n][j] = u(d, c + j * k);
  86.   }
  87.   do {
  88.     z = 0;
  89.     z_max = 0;
  90.     eps_max = 0;
  91.     r_max = -20;
  92.     num = 0;
  93.     denominator = 0;
  94.     for (j = 1; j < m; ++j) {
  95.       for (i = n - 1; i > 0; --i) {
  96.         r_vec[i][j] = f(a + i * h, c + j * k) -
  97.                       (h2 * (v[i + 1][j] + v[i - 1][j]) +
  98.                        k2 * (v[i][j + 1] + v[i][j - 1]) + v[i][j] * a2);
  99.       }
  100.     }
  101.     for (j = 1; j < m; ++j) {
  102.       for (i = n - 1; i > 0; --i) {
  103.         ar[i][j] =
  104.             (h2 * (r_vec[i + 1][j] + r_vec[i - 1][j]) +
  105.              k2 * (r_vec[i][j + 1] + r_vec[i][j - 1]) + r_vec[i][j] * a2);
  106.         num += ar[i][j] * r_vec[i][j];
  107.         denominator += ar[i][j] * ar[i][j];
  108.       }
  109.     }
  110.     tau_s = num / denominator;
  111.     for (j = 1; j < m; ++j) {
  112.       for (i = n - 1; i > 0; --i) {
  113.         v_old = v[i][j];
  114.         v_new = v_old + tau_s * r_vec[i][j];
  115.         eps_cur = std::fabs(v_old - v_new);
  116.         if (eps_cur > eps_max) {
  117.           eps_max = eps_cur;
  118.         }
  119.         v[i][j] = v_new;
  120.         r = fabs(f(a + i * h, c + j * k) -
  121.                  (h2 * (v[i + 1][j] + v[i - 1][j]) +
  122.                   k2 * (v[i][j + 1] + v[i][j - 1]) + v_old * a2));
  123.         if (r > r_max)
  124.           r_max = r;
  125.         z = u(a + i * h, c + j * k) - v[i][j];
  126.         if (z > z_max) {
  127.           z_max = z;
  128.           x = i;
  129.           y = j + 1;
  130.         }
  131.       }
  132.     }
  133.  
  134.     S = S + 1;
  135.     if ((eps_max <= eps) or (S >= Nmax)) {
  136.       flag = true;
  137.     }
  138.   } while (!flag);
  139.  
  140.   std::ofstream in("./"
  141.                    "param_test.txt"); // подключение текстового файла для записи
  142.   in << "\nСПРАВКА:" << std::endl;
  143.   in << "Разбиений по x: " << n << '\t' << "разбиений по y:" << n << std::endl;
  144.   in << "Максимальное количество шагов = " << Nmax << std::endl;
  145.   in << "Количество выполненных итераций = " << S << std::endl;
  146.   in << "Требуемая точность = " << eps << std::endl;
  147.   in << "Точность на выходе = " << eps_max << std::endl;
  148.   in << "Невязка = " << r_max << std::endl;
  149.   in << "Норма общей погрешности = " << z_max << std::endl;
  150.   in << "Максимальное отклонение в узле x= " << double(x) / double(n)
  151.      << ", y= " << double(y) / double(m) << std::endl;
  152.   in << "в качестве начального приближения использовано нулевое приближение"
  153.      << std::endl;
  154.   return v;
  155. }
  156.  
  157. int main() {
  158.   int n = 400;
  159.   int m = 400;
  160.   std::vector<std::vector<double>> v(n, std::vector<double>(m, 0));
  161.   v = MinimalResiduals(2e6, 1e-12, n, m);
  162.   n++;
  163.   m++;
  164.   std::ofstream in("./"
  165.                    "data_test.txt"); // подключение текстового файла для записи
  166.   in << "Результат:" << std::endl;
  167.   for (int i = n - 1; i >= 0; --i) {
  168.     for (int j = 0; j < m; ++j)
  169.       in << std::left << std::setw(10) << v[i][j];
  170.     in << "\n";
  171.   }
  172.   std::ofstream in1(
  173.       "./"
  174.       "data_test_u.txt"); // подключение текстового файла для записи
  175.   in1 << "Результат:" << std::endl;
  176.   for (int i = n - 1; i >= 0; --i) {
  177.     for (int j = 0; j < m; ++j)
  178.       in1 << std::left << std::setw(10) << u(1 / double(i), 1 / double(j));
  179.     in1 << "\n";
  180.   }
  181.   std::ofstream in2(
  182.       "./"
  183.       "data_test_u_v.txt"); // подключение текстового файла для записи
  184.   in2 << "Результат:" << std::endl;
  185.   for (int i = n - 1; i >= 0; --i) {
  186.     for (int j = 0; j < m; ++j)
  187.       in2 << std::left << std::setw(15)
  188.           << std::fabs(u(double(i) / n, double(j) / m) - v[i][j]);
  189.  
  190.     in2 << "\n";
  191.   }
  192.   return 0;
  193. }
  194.  
Advertisement
Add Comment
Please, Sign In to add comment