Advertisement
575

numlab3

575
Mar 7th, 2023 (edited)
517
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.48 KB | None | 0 0
  1. import numpy as np, matplotlib.pyplot as plt, copy
  2.  
  3. class Equation:
  4.     def __init__(self, params):
  5.         self.bx = params['bx']
  6.         self.by = params['by']
  7.         self.c = params['c']
  8.  
  9.         self.alpha_x0 = params['alpha_x0']
  10.         self.beta_x0 = params['beta_x0']
  11.         self.f_phi_x0 = params['f_phi_x0']
  12.  
  13.         self.alpha_xl = params['alpha_xl']
  14.         self.beta_xl = params['beta_xl']
  15.         self.f_phi_xl = params['f_phi_xl']
  16.  
  17.         self.alpha_y0 = params['alpha_y0']
  18.         self.beta_y0 = params['beta_y0']
  19.         self.f_phi_y0 = params['f_phi_y0']
  20.  
  21.         self.alpha_yl = params['alpha_yl']
  22.         self.beta_yl = params['beta_yl']
  23.         self.f_phi_yl = params['f_phi_yl']
  24.  
  25.         self.interval_x = params['interval_x']
  26.         self.interval_y = params['interval_y']
  27.         self.analytical_solution = params['analytical_solution']
  28.  
  29.     def solve(self, nx, ny, method, omega=1.0, eps=1e-8, quiet=False):
  30.         hx, hy = self.__prepare(self.interval_x[0], self.interval_x[1], nx,
  31.                                 self.interval_y[0], self.interval_y[1], ny)
  32.         if method == 'simple_iterations':
  33.             u = self.__simple_iterations_method(nx, ny, hx, hy, eps, quiet)
  34.         elif method == 'seidel':
  35.             u = self.__seidel_method(nx, ny, hx, hy, 1.0, eps, quiet)
  36.         elif method == 'top_relaxation':
  37.             u = self.__seidel_method(nx, ny, hx, hy, omega, eps, quiet)
  38.         return u
  39.  
  40.     def __simple_iterations_method(self, nx, ny, hx, hy, eps, quiet):
  41.         u_new = np.ones((nx, ny))
  42.         u = np.ones((nx, ny))
  43.         iter = 0
  44.         while True:
  45.             for i in range(1, nx - 1):
  46.                 for j in range(1, ny - 1):
  47.                     u_new[i][j] = ((u[i + 1][j] - u[i - 1][j]) * self.bx * hx * hy ** 2 + \
  48.                                    (u[i][j + 1] - u[i][j - 1]) * self.by * hy * hx ** 2 - \
  49.                                    2 * hy ** 2 * (u[i - 1][j] + u[i + 1][j]) - \
  50.                                    2 * hx ** 2 * (u[i][j - 1] + u[i][j + 1])) / \
  51.                                   (-4 * hy ** 2 - 4 * hx ** 2 - 2 * hx ** 2 * hy ** 2 * self.c)
  52.             for j in range(ny):
  53.                 u_new[0][j] = (hx * self.f_phi_x0(j * hy) - self.alpha_x0 * u_new[1][j]) / (
  54.                             hx * self.beta_x0 - self.alpha_x0)
  55.                 u_new[-1][j] = (hx * self.f_phi_xl(j * hy) + self.alpha_xl * u_new[-2][j]) / (
  56.                             hx * self.beta_xl + self.alpha_xl)
  57.             for i in range(nx):
  58.                 u_new[i][0] = (hy * self.f_phi_y0(i * hx) - self.alpha_y0 * u_new[i][1]) / (
  59.                             hy * self.beta_y0 - self.alpha_y0)
  60.                 u_new[i][-1] = (hy * self.f_phi_yl(i * hx) + self.alpha_yl * u_new[i][-2]) / (
  61.                             hy * self.beta_yl + self.alpha_yl)
  62.             eps_k = max([max(np.absolute(u_new[i] - u[i])) for i in range(nx)])
  63.             iter += 1
  64.             if eps_k < eps:
  65.                 if not quiet:
  66.                     print('Итераций (метод простых итераций): ', iter)
  67.                 return u_new
  68.             u = copy.deepcopy(u_new)
  69.  
  70.     def __seidel_method(self, nx, ny, hx, hy, omega, eps, quiet):
  71.         u_prev = np.ones((nx, ny))
  72.         u = np.ones((nx, ny))
  73.         iter = 0
  74.         while True:
  75.             for i in range(1, nx - 1):
  76.                 for j in range(1, ny - 1):
  77.                     u[i][j] = ((u[i + 1][j] - u[i - 1][j]) * self.bx * hx * hy ** 2 + \
  78.                                (u[i][j + 1] - u[i][j - 1]) * self.by * hy * hx ** 2 - \
  79.                                2 * hy ** 2 * (u[i - 1][j] + u[i + 1][j]) - \
  80.                                2 * hx ** 2 * (u[i][j - 1] + u[i][j + 1])) / \
  81.                               (-4 * hy ** 2 - 4 * hx ** 2 - 2 * hx ** 2 * hy ** 2 * self.c)
  82.             for j in range(ny):
  83.                 u[0][j] = (hx * self.f_phi_x0(j * hy) - self.alpha_x0 * u[1][j]) / (hx * self.beta_x0 - self.alpha_x0)
  84.                 u[-1][j] = (hx * self.f_phi_xl(j * hy) + self.alpha_xl * u[-2][j]) / (hx * self.beta_xl + self.alpha_xl)
  85.             for i in range(nx):
  86.                 u[i][0] = (hy * self.f_phi_y0(i * hx) - self.alpha_y0 * u[i][1]) / (hy * self.beta_y0 - self.alpha_y0)
  87.                 u[i][-1] = (hy * self.f_phi_yl(i * hx) + self.alpha_yl * u[i][-2]) / (hy * self.beta_yl + self.alpha_yl)
  88.             for i in range(nx):
  89.                 for j in range(ny):
  90.                     u[i][j] = omega * u[i][j] + (1.0 - omega) * u_prev[i][j]
  91.             eps_k = max([max(np.absolute(u[i] - u_prev[i])) for i in range(nx)])
  92.             iter += 1
  93.             if eps_k < eps:
  94.                 if not quiet:
  95.                     print('Итераций (метод Зейделя): ', iter)
  96.                 return u
  97.             u_prev = copy.deepcopy(u)
  98.  
  99.     def solution(self, nx, ny, u):
  100.         x = np.linspace(self.interval_x[0], self.interval_x[1], u.shape[1])
  101.         y = np.linspace(self.interval_y[0], self.interval_y[1], u.shape[0])
  102.         X, Y = np.meshgrid(x, y)
  103.         return self.analytical_solution(Y, X)
  104.  
  105.     def __prepare(self, begin_x, end_x, nx, begin_y, end_y, ny):
  106.         hx = (end_x - begin_x) / (nx - 1)
  107.         hy = (end_y - begin_y) / (ny - 1)
  108.         return hx, hy
  109.  
  110. def draw(x_bounds, t_bounds, n, max_time, res, orig):
  111.     x = np.linspace(x_bounds[0], x_bounds[1], n)
  112.     y = np.linspace(t_bounds[0], t_bounds[1], max_time)
  113.     X, Y = np.meshgrid(x, y)
  114.     ax = plt.axes(projection='3d')
  115.     ax.plot_surface(X, Y, res, color='blue')
  116.     ax.plot_wireframe(X, Y, orig, color='red')
  117.     #ax.contour3D(X, Y, res, X, Y, 50, cmap='binary')
  118.     plt.show()
  119.  
  120. def norm(cur_u, prev_u):
  121.     max = 0
  122.     for i in range(cur_u.shape[0]):
  123.         for j in range(cur_u.shape[1]):
  124.             if abs(cur_u[i, j] - prev_u[i, j]) > max:
  125.                 max = abs(cur_u[i, j] - prev_u[i, j])
  126.    
  127.     return max
  128.  
  129. def main():
  130.     params = {
  131.         'bx': -2.0,
  132.         'by': 0,
  133.         'c': -3.0,
  134.  
  135.         'alpha_x0': 0.0,
  136.         'beta_x0': 1.0,
  137.         'f_phi_x0': lambda y: np.cos(y),
  138.  
  139.         'alpha_xl': 0.0,
  140.         'beta_xl': 1.0,
  141.         'f_phi_xl': lambda y: 0.0,
  142.  
  143.         'alpha_y0': 0.0,
  144.         'beta_y0': 1.0,
  145.         'f_phi_y0': lambda x: np.exp(-x) * np.cos(x),
  146.  
  147.         'alpha_yl': 0.0,
  148.         'beta_yl': 1.0,
  149.         'f_phi_yl': lambda x: 0.0,
  150.  
  151.         'interval_x': (0.0, np.pi / 2),
  152.         'interval_y': (0.0, np.pi / 2),
  153.         'analytical_solution': lambda x, y: np.exp(-x) * np.cos(x) * np.cos(y)
  154.     }
  155.  
  156.     equation = Equation(params)
  157.  
  158.     # ['simple_iterations', 'seidel', 'top_relaxation']
  159.     method = 'top_relaxation'
  160.     nx = 25
  161.     ny = 25
  162.     omega = 1.7
  163.  
  164.     u = equation.solve(nx=nx, ny=ny, method=method, omega=omega, eps=1e-8)
  165.     u_orig = equation.solution(nx=nx, ny=ny, u=u)
  166.  
  167.     #draw(equation.interval_x, equation.interval_y, u_orig.shape[1], u_orig.shape[0], u_orig)
  168.     draw(equation.interval_x, equation.interval_y, u.shape[1], u.shape[0], u, u_orig)
  169.  
  170.     plt.show()
  171.     er_l = []
  172.     h = []
  173.     for i in range(25, 5, -1):
  174.         nx = i
  175.         ny = i
  176.         h.append(np.pi / (2 * nx))
  177.        
  178.         u = equation.solve(nx=nx, ny=ny, method=method, omega=omega, eps=1e-8)
  179.         u_orig = equation.solution(nx=nx, ny=ny, u=u)
  180.         er_l.append(norm(u_orig, u))
  181.     plt.title('Ошибка метода простых итераций')
  182.     plt.xlabel('h')
  183.     plt.ylabel('error')
  184.     plt.plot(h, er_l)
  185.     plt.show()
  186.  
  187. if __name__ == '__main__':
  188.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement