Advertisement
575

numlab4

575
Mar 7th, 2023 (edited)
600
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.10 KB | None | 0 0
  1. import numpy as np, math as math, matplotlib.pyplot as plt, copy
  2.  
  3. def plotErrorsByT(time, errors):
  4.     errors.reverse()
  5.     plt.figure(figsize=(12, 8))
  6.     plt.xlabel('time')
  7.     plt.ylabel('error')
  8.     plt.title('Errors by time')
  9.     plt.plot(time, errors, color = 'b')
  10.  
  11. class Data:
  12.  
  13.     def __init__(self, ia, ib, iff, iax0, ibx0, ifx0, iaxl, ibxl, ifxl, iay0, iby0, ify0, iayl, ibyl, ifyl, ifpsi, iintervalOnX, iintervalOnY, inx, iny, itime, irealFunction):
  14.         self.a = ia
  15.         self.b = ib
  16.         self.f = iff
  17.  
  18.         self.ax0 = iax0
  19.         self.bx0 = ibx0
  20.         self.fx0 = ifx0
  21.  
  22.         self.axl = iaxl
  23.         self.bxl = ibxl
  24.         self.fxl = ifxl
  25.  
  26.         self.ay0 = iay0
  27.         self.by0 = iby0
  28.         self.fy0 = ify0
  29.  
  30.         self.ayl = iayl
  31.         self.byl = ibyl
  32.         self.fyl = ifyl
  33.  
  34.         self.fpsi = ifpsi
  35.  
  36.         self.intervalOnX = iintervalOnX
  37.         self.intervalOnY = iintervalOnY
  38.  
  39.         self.nx = inx
  40.         self.ny = iny
  41.  
  42.         self.time = itime
  43.  
  44.         self.realFunction = irealFunction
  45.  
  46. class Solution:
  47.  
  48.     @classmethod
  49.     def process(cls, data : Data, method):
  50.         stepX = (data.intervalOnX[1] - data.intervalOnX[0]) / (data.nx - 1)
  51.         stepY = (data.intervalOnY[1] - data.intervalOnY[0]) / (data.ny - 1)
  52.         tau = cls.__sigma / (data.a / stepX ** 2 + data.b / stepY ** 2)
  53.         time_cnt = int(data.time / tau)
  54.  
  55.         x = np.array([stepX * i for i in range(data.nx)])
  56.         y = np.array([stepY * i for i in range(data.ny)])
  57.         t = np.array([tau * k for k in range(time_cnt)])
  58.  
  59.         if (method == "Alternative directions"):
  60.             resU = cls.alternativeDirectionsMethod(data, time_cnt, stepX, stepY, tau)
  61.  
  62.         elif (method == "Fractional steps"):
  63.             resU = cls.fractionalStepsMethod(data, time_cnt, stepX, stepY, tau)
  64.  
  65.         return x, y, t, resU
  66.  
  67.     @classmethod
  68.     def alternativeDirectionsMethod(cls, data : Data, time_cnt, stepX, stepY, tau):
  69.         u = np.zeros((time_cnt, data.nx, data.ny))
  70.        
  71.         a_1 = np.array([0.0] + [-data.a * tau * stepY ** 2 for _ in range(1, data.nx - 1)] + [0.0])
  72.         b_1 = np.array([0.0] + [2 * stepX ** 2 * stepY ** 2 + 2 * data.a * stepY ** 2 * tau for _ in range(1, data.nx - 1)] + [0.0])
  73.         c_1 = np.array([0.0] + [-data.a * tau * stepY ** 2 for _ in range(1, data.nx - 1)] + [0.0])
  74.        
  75.         b_1[0] = stepX * data.bx0 - data.ax0
  76.         c_1[0] = data.ax0
  77.         a_1[-1] = -data.axl
  78.         b_1[-1] = data.axl + stepX * data.bxl
  79.        
  80.         a_2 = np.array([0.0] + [-data.b * tau * stepX ** 2 for _ in range(1, data.ny - 1)] + [0.0])
  81.         b_2 = np.array([0.0] + [2 * stepX ** 2 * stepY ** 2 + 2 * data.b * stepX ** 2 * tau for _ in range(1, data.ny - 1)] + [0.0])
  82.         c_2 = np.array([0.0] + [-data.b * tau * stepX ** 2 for _ in range(1, data.ny - 1)] + [0.0])
  83.        
  84.         b_2[0] = stepY * data.by0 - data.ay0
  85.         c_2[0] = data.ay0
  86.         a_2[-1] = -data.ayl
  87.         b_2[-1] = data.ayl + stepY * data.byl
  88.        
  89.         for i in range(data.nx):
  90.             for j in range(data.ny):
  91.                 u[0][i][j] = data.fpsi(stepX * i, stepY * j)
  92.                
  93.         for k in range(1, time_cnt):
  94.             u_1 = np.zeros((data.ny, data.nx))
  95.             d_1 = np.zeros(data.nx)
  96.             u_2 = np.zeros((data.nx, data.ny))
  97.             d_2 = np.zeros(data.ny)
  98.             for j in range (1, data.ny - 1):
  99.                 for i in range(1, data.nx - 1):
  100.                     d_1[i] = (u[k - 1][i][j - 1] - 2 * u[k - 1][i][j] + u[k - 1][i][j + 1]) * data.b * stepX ** 2 * tau + \
  101.                               2 * stepX ** 2 * stepY ** 2 * u[k - 1][i][j] + \
  102.                               stepX ** 2 * stepY ** 2 * tau * data.f(stepX * i, stepY * j, tau * (k - 0.5))
  103.                 d_1[0] = stepX * data.fx0(stepY * j ,tau * (k - 0.5))
  104.                 d_1[-1] = stepX * data.fxl(stepY * j ,tau * (k - 0.5))
  105.                
  106.                 u_1_j = cls.__tma(a_1, b_1, c_1, d_1, data.nx)
  107.                 u_1[j] = copy.deepcopy(u_1_j)
  108.             for i in range(data.nx):
  109.                 u_1[0][i] = (stepY * data.fy0(i * stepX, tau * (k - 0.5)) - data.ay0 * u_1[1][i]) / (stepY * data.by0 - data.ay0)
  110.                 u_1[-1][i] = (stepY * data.fyl(i * stepX, tau * (k - 0.5)) + data.ayl * u_1[-2][i]) / (stepY * data.byl + data.ayl)
  111.             u_1 = u_1.transpose()
  112.            
  113.             for i in range(1, data.nx - 1):
  114.                 for j in range(1, data.ny - 1):
  115.                     d_2[j] = (u_1[i - 1][j] - 2 * u_1[i][j] + u_1[i + 1][j]) * data.a * stepY ** 2 * tau + \
  116.                               2 * stepX ** 2 * stepY ** 2 * u_1[i][j] + \
  117.                               stepX ** 2 * stepY ** 2 * tau * data.f(stepX * i, stepY * j, tau * k)
  118.                 d_2[0] = stepY * data.fy0(stepX * i ,tau * k)
  119.                 d_2[-1] = stepY * data.fyl(stepX * i ,tau * k)
  120.                
  121.                 u_2_i = cls.__tma(a_2, b_2, c_2, d_2, data.ny)
  122.                 u_2[i] = copy.deepcopy(u_2_i)
  123.             for j in range(data.ny):
  124.                 u_2[0][j] = (stepX * data.fx0(j * stepY, tau * k) - data.ax0 * u_2[1][j]) / (stepX * data.bx0 - data.ax0)
  125.                 u_2[-1][j] = (stepX * data.fxl(j * stepY, tau * k) + data.axl * u_2[-2][j]) / (stepX * data.bxl + data.axl)
  126.             u[k] = copy.deepcopy(u_2)
  127.         return u
  128.  
  129.     @classmethod
  130.     def fractionalStepsMethod(cls, data : Data, time_cnt, stepX, stepY, tau):
  131.         u = np.zeros((time_cnt, data.nx, data.ny))
  132.        
  133.         a_1 = np.array([0.0] + [-2 * data.a * tau for _ in range(1, data.nx - 1)] + [0.0])
  134.         b_1 = np.array([0.0] + [2 * stepX ** 2 + 4 * tau * data.a for _ in range(1, data.nx - 1)] + [0.0])
  135.         c_1 = np.array([0.0] + [-2 * data.a * tau for _ in range(1, data.nx - 1)] + [0.0])
  136.        
  137.         b_1[0] = stepX * data.bx0 - data.ax0
  138.         c_1[0] = data.ax0
  139.         a_1[-1] = -data.axl
  140.         b_1[-1] = data.axl + stepX * data.bxl
  141.        
  142.         a_2 = np.array([0.0] + [-2 * data.b * tau for _ in range(1, data.ny - 1)] + [0.0])
  143.         b_2 = np.array([0.0] + [2 * stepY ** 2 + 4 * tau * data.b for _ in range(1, data.ny - 1)] + [0.0])
  144.         c_2 = np.array([0.0] + [-2 * data.b * tau for _ in range(1, data.ny - 1)] + [0.0])
  145.        
  146.         b_2[0] = stepY * data.by0 - data.ay0
  147.         c_2[0] = data.ay0
  148.         a_2[-1] = -data.ayl
  149.         b_2[-1] = data.ayl + stepY * data.byl
  150.        
  151.         for i in range(data.nx):
  152.             for j in range(data.ny):
  153.                 u[0][i][j] = data.fpsi(stepX * i, stepY * j)
  154.                
  155.         for k in range(1, time_cnt):
  156.             u_1 = np.zeros((data.ny, data.nx))
  157.             d_1 = np.zeros(data.nx)
  158.             u_2 = np.zeros((data.nx, data.ny))
  159.             d_2 = np.zeros(data.ny)
  160.             for j in range (1, data.ny - 1):
  161.                 for i in range(1, data.nx - 1):
  162.                     d_1[i] = 2 * stepX ** 2 * u[k - 1][i][j] + tau * stepX ** 2 * data.f(stepX * i, stepY * j, tau * (k - 0.5))
  163.                 d_1[0] = stepX * data.fx0(stepY * j ,tau * (k - 0.5))
  164.                 d_1[-1] = stepX * data.fxl(stepY * j ,tau * (k - 0.5))
  165.                
  166.                 u_1_j = cls.__tma(a_1, b_1, c_1, d_1, data.nx)
  167.                 u_1[j] = copy.deepcopy(u_1_j)
  168.             for i in range(data.nx):
  169.                 u_1[0][i] = (stepY * data.fy0(i * stepX, tau * (k - 0.5)) - data.ay0 * u_1[1][i]) / (stepY * data.by0 - data.ay0)
  170.                 u_1[-1][i] = (stepY * data.fyl(i * stepX, tau * (k - 0.5)) + data.ayl * u_1[-2][i]) / (stepY * data.byl + data.ayl)
  171.             u_1 = u_1.transpose()
  172.            
  173.             for i in range(1, data.nx - 1):
  174.                 for j in range(1, data.ny - 1):
  175.                     d_2[j] = 2 * stepY ** 2 * u_1[i][j] + tau * stepY ** 2 * data.f(stepX * i, stepY * j, tau * k)
  176.                 d_2[0] = stepY * data.fy0(stepX * i ,tau * k)
  177.                 d_2[-1] = stepY * data.fyl(stepX * i ,tau * k)
  178.                
  179.                 u_2_i = cls.__tma(a_2, b_2, c_2, d_2, data.ny)
  180.                 u_2[i] = copy.deepcopy(u_2_i)
  181.             for j in range(data.ny):
  182.                 u_2[0][j] = (stepX * data.fx0(j * stepY, tau * k) - data.ax0 * u_2[1][j]) / (stepX * data.bx0 - data.ax0)
  183.                 u_2[-1][j] = (stepX * data.fxl(j * stepY, tau * k) + data.axl * u_2[-2][j]) / (stepX * data.bxl + data.axl)
  184.             u[k] = copy.deepcopy(u_2)
  185.         return u
  186.  
  187.     @classmethod
  188.     def realFunctionSolution(cls, data : Data):
  189.         stepX = (data.intervalOnX[1] - data.intervalOnX[0]) / (data.nx - 1)
  190.         stepY = (data.intervalOnY[1] - data.intervalOnY[0]) / (data.ny - 1)
  191.         tau = cls.__sigma / (data.a / stepX ** 2 + data.b / stepY ** 2)
  192.         time_cnt = int(data.time / tau)
  193.  
  194.         ans = np.zeros((time_cnt, data.nx, data.ny))
  195.         for k in range(time_cnt):
  196.             for i in range(data.nx):
  197.                 for j in range(data.ny):
  198.                     ans[k][i][j] = data.realFunction(stepX * i, stepY * j, tau * k)
  199.         return ans
  200.  
  201.     @classmethod
  202.     def __tma(cls, a, b, c, d, n):
  203.         A = np.zeros(n)
  204.         B = np.zeros(n)
  205.         x = np.zeros(n)
  206.         A[0] = -c[0] / b[0]
  207.         B[0] = d[0] / b[0]
  208.        
  209.         for j in range(1, n):
  210.             A[j] = -c[j] / (b[j] + a[j] * A[j - 1])
  211.             B[j] = (d[j] - a[j] * B[j - 1]) / (b[j] + a[j] * A[j - 1])
  212.         x[-1] = B[-1]
  213.         for j in range(n - 2, -1, -1):
  214.             x[j] = A[j] * x[j + 1] + B[j]
  215.         return x
  216.  
  217.     __sigma = 0.4
  218.  
  219. def plotErrors(data : Data, method, start, where, amount):
  220.     errors = []
  221.     dataTmp = data
  222.     if (where == 'x'):
  223.         dataTmp.nx = start
  224.     elif (where == 'y'):
  225.         dataTmp.ny = start
  226.  
  227.     if (method == "Alternative directions"):
  228.         if (where == 'x'):
  229.             for i in range(amount):
  230.                 dataTmp.nx += 1
  231.                 realSolution = Solution.realFunctionSolution(data)
  232.                 x, y, t, utmp = Solution.process(dataTmp, method)
  233.                 errorTmp = max([max([max(np.absolute(utmp[k][i] - realSolution[k][i])) for i in range(len(x))]) for k in range(len(t))])
  234.                 errors.append(errorTmp)
  235.         elif (where == 'y'):
  236.             for i in range(amount):
  237.                 dataTmp.ny += 1
  238.                 realSolution = Solution.realFunctionSolution(data)
  239.                 x, y, t, utmp = Solution.process(dataTmp, method)
  240.                 errorTmp = max([max([max(np.absolute(utmp[k][i] - realSolution[k][i])) for i in range(len(x))]) for k in range(len(t))])
  241.                 errors.append(errorTmp)
  242.        
  243.     elif (method == "Fractional steps"):
  244.         if (where == 'x'):
  245.             for i in range(amount):
  246.                 dataTmp.nx += 1
  247.                 realSolution = Solution.realFunctionSolution(data)
  248.                 x, y, t, utmp = Solution.process(data, method)
  249.                 errorTmp = max([max([max(np.absolute(utmp[k][i] - realSolution[k][i])) for i in range(len(x))]) for k in range(len(t))])
  250.                 errors.append(errorTmp)
  251.         elif (where == 'y'):
  252.             for i in range(amount):
  253.                 dataTmp.ny += 1
  254.                 realSolution = Solution.realFunctionSolution(data)
  255.                 x, y, t, utmp = Solution.process(data, method)
  256.                 errorTmp = max([max([max(np.absolute(utmp[k][i] - realSolution[k][i])) for i in range(len(x))]) for k in range(len(t))])
  257.                 errors.append(errorTmp)
  258.  
  259.     nums = [i for i in range(start, start + amount)]
  260.     if (where == 'x'):
  261.         errors.reverse()
  262.  
  263.     plt.figure(figsize=(12, 8))
  264.     plt.plot(nums, errors, color = 'r')
  265.     plt.title('Errors with different ' + where)
  266.  
  267. a = 1
  268. b = 1
  269.  
  270. f = lambda x, y, t: -x * y * np.sin(t)
  271.  
  272. alphax0 = 0
  273. alphaxl = -1
  274. alphay0 = 0
  275. alphayl = -1
  276.  
  277. betax0 = 1
  278. betaxl = 1
  279. betay0 = 1
  280. betayl = 1
  281.  
  282. fx0 = lambda y, t: 0.0
  283. fxl = lambda y, t: 0.0
  284. fy0 = lambda x, t: 0.0
  285. fyl = lambda x, t: 0.0
  286.  
  287. fpsi = lambda x, y: x * y
  288.  
  289. intervalOnX = (0.0, 1.0)
  290. intervalOnY = (0.0, 1.0)
  291.  
  292. realFunction = lambda x, y, t: x * y * np.cos(t)
  293.  
  294. nx = 20
  295. ny = 20
  296. time = 3
  297. data = Data(a, b, f, alphax0, betax0, fx0, alphaxl, betaxl, fxl, alphay0, betay0, fy0, alphayl, betayl, fyl, fpsi, intervalOnX, intervalOnY, nx, ny, time, realFunction)
  298.  
  299. realSolution = Solution.realFunctionSolution(data)
  300.  
  301. method = "Alternative directions"
  302. nx1 = 20
  303. ny1 = 20
  304. time1 = 3
  305. data1 = Data(a, b, f, alphax0, betax0, fx0, alphaxl, betaxl, fxl, alphay0, betay0, fy0, alphayl, betayl, fyl, fpsi, intervalOnX, intervalOnY, nx1, ny1, time1, realFunction)
  306. xAD, yAD, tAD, uAD = Solution.process(data1, method)
  307.  
  308. errorAD = max(np.array([max([max(np.absolute(uAD[k][i] - realSolution[k][i])) for i in range(len(xAD))]) for k in range(len(tAD))]))
  309. fig = plt.figure()
  310. ax = fig.add_subplot(projection='3d')
  311. ax.set_title("График точного и численного решения задачи")
  312. ax.plot_wireframe(X, Y, U_analytic, color = "red", label = "Точное решение")
  313. ax.plot_wireframe(xAD, yAD, uAD, color = "blue", label = "Численное решение")
  314. ax.set_xlabel("x")
  315. ax.set_ylabel("y")
  316. ax.set_zlabel("U")
  317. ax.legend()
  318. plt.show()
  319.  
  320. method = "Fractional steps"
  321. nx2 = 20
  322. ny2 = 20
  323. time2 = 3
  324. data2 = Data(a, b, f, alphax0, betax0, fx0, alphaxl, betaxl, fxl, alphay0, betay0, fy0, alphayl, betayl, fyl, fpsi, intervalOnX, intervalOnY, nx2, ny2, time2, realFunction)
  325. xFS, yFS, tFS, uFS = Solution.process(data2, method)
  326.  
  327. errorFS = max(np.array([max([max(np.absolute(uFS[k][i] - realSolution[k][i])) for i in range(len(xFS))]) for k in range(len(tFS))]))
  328.  
  329. plt.figure(figsize=(14, 14))
  330. t = np.linspace(0, len(tAD) - 1, num=5, endpoint=True, dtype=int)
  331.  
  332. ax = plt.axes(projection='3d')
  333.  
  334. X, Y = np.meshgrid(xAD, yAD)
  335.  
  336. colors = ['b', 'orange','green', 'r', 'purple', 'yellow']
  337. c = 0
  338. for i in t:
  339.     ax.plot_wireframe(X, Y, uAD[i], color = colors[c])
  340.     c += 1
  341.  
  342. legends = ["t=" + str(tAD[i]) for i in t]
  343. ax.legend(legends)
  344. ax.set_xlabel("x")
  345. ax.set_ylabel("y")
  346. ax.set_zlabel("U(x, y, t)")
  347.  
  348. plt.title('Решение при различных t')
  349. plt.show()
  350.  
  351. errorsAD = [max([max(np.absolute(uAD[k][i] - realSolution[k][i])) for i in range(len(xAD))]) for k in range(len(tAD))]
  352. plotErrorsByT(tAD, errorsAD)
  353. plt.show()
  354.  
  355. plt.figure(figsize=(14, 14))
  356. t = np.linspace(0, len(tFS) - 1, num=5, endpoint=True, dtype=int)
  357.  
  358.  
  359. ax = plt.axes(projection='3d')
  360.  
  361. X, Y = np.meshgrid(xFS, yFS)
  362.  
  363. colors = [ 'b', 'orange','green', 'r', 'purple']
  364. c = 0
  365. for i in t:
  366.     ax.plot_wireframe(X, Y, uFS[i], color = colors[c])
  367.     c += 1
  368.  
  369. legends = ["t=" + str(tFS[i]) for i in t]
  370. ax.legend(legends)
  371. ax.set_xlabel("x")
  372. ax.set_ylabel("y")
  373. ax.set_zlabel("U(x, y, t)")
  374.  
  375. plt.show()
  376.  
  377. errorsFS = [max([max(np.absolute(uAD[k][i] - realSolution[k][i])) for i in range(len(xAD))]) for k in range(len(tAD))]
  378. plotErrorsByT(tFS, errorsFS)
  379. plt.show()
  380.  
  381. id = 400
  382.  
  383. plt.figure(figsize=(14, 14))
  384.  
  385. ax = plt.axes(projection='3d')
  386.  
  387. X, Y = np.meshgrid(xAD, yAD)
  388.  
  389.  
  390. ax.plot_wireframe(X, Y, realSolution[id], color = 'b', label='Real function')
  391. ax.plot_wireframe(X, Y, uAD[id], color = 'g', label='Alternative directions')
  392. ax.plot_wireframe(X, Y, uFS[id], color = 'r', label ='Fractional steps')
  393. plt.legend()
  394. ax.set_xlabel("x")
  395. ax.set_ylabel("y")
  396. ax.set_zlabel("U(x, y, t)")
  397.  
  398. plt.title("Решения методов в t = " + str(tAD[id]))
  399. def norm(cur_u, prev_u):
  400.     max = 0
  401.     for i in range(cur_u.shape[0]):
  402.         for j in range(cur_u.shape[1]):
  403.             if abs(cur_u[i, j] - prev_u[i, j]) > max:
  404.                 max = abs(cur_u[i, j] - prev_u[i, j])
  405.    
  406.     return max
  407. er_l = []
  408. h = []
  409. method = "Alternative directions"
  410. for i in range(20, 5, -1):
  411.     nx1 = i
  412.     ny1 = i
  413.     h.append(1 / (nx1 - 1))
  414.     time1 = 3
  415.     data1 = Data(a, b, f, alphax0, betax0, fx0, alphaxl, betaxl, fxl, alphay0, betay0, fy0, alphayl, betayl, fyl, fpsi, intervalOnX, intervalOnY, nx1, ny1, time1, realFunction)
  416.     xAD, yAD, tAD, uAD = Solution.process(data1, method)
  417.  
  418.     realSolution = Solution.realFunctionSolution(data1)
  419.  
  420.     er_l.append(norm(realSolution[10], uAD[10]))
  421. plt.title('Ошибка метода переменных направлений')
  422. plt.xlabel('h')
  423. plt.ylabel('error')
  424. plt.plot(h, er_l)
  425. plt.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement