Advertisement
575

lab4_1

575
Oct 10th, 2022
948
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.19 KB | None | 0 0
  1. from copy import deepcopy
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4.  
  5. # Вторая производная, выраженная через x, f, f'
  6. def ddf(x, f, df):
  7.     return 4 * x * df - (4 * x ** 2 - 3) * f - np.e ** (x ** 2)
  8.  
  9. # Точное решение
  10. def f(x):
  11.     return (np.e ** x + np.e ** (-x) - 1) * np.e ** (x ** 2)
  12.  
  13. # Явный метод Эйлера
  14. def Euler(ddy, borders, y0, z0, h):
  15.     x = np.arange(borders[0], borders[1]+h, h)
  16.     N = np.shape(x)[0]
  17.     y = np.zeros(N)
  18.     z = np.zeros(N)
  19.     y[0] = y0; z[0] = z0
  20.     for i in range(0, N-1):
  21.         z[i+1] = z[i]+h*ddy(x[i], y[i], z[i])
  22.         y[i+1] = y[i]+h*z[i]
  23.     return y
  24.  
  25. # Явный метод Эйлера-Коши
  26. def EulerCauchy(ddy, borders, y0, z0, h):
  27.     x = np.arange(borders[0], borders[1]+h, h)
  28.     N = np.shape(x)[0]
  29.     y = np.zeros(N)
  30.     z = np.zeros(N)
  31.     y[0] = y0; z[0] = z0
  32.     for i in range(0, N-1):
  33.         pre_z = z[i]+h*ddy(x[i], y[i], z[i])
  34.         pre_y = y[i]+h*z[i]
  35.         z[i+1] = z[i]+h*(ddy(x[i], y[i], z[i])+ddy(x[i+1], pre_y, pre_z))/2
  36.         y[i+1] = y[i]+h*z[i]
  37.     return y
  38.  
  39. def RungeKutta(ddy, borders, y0, z0, h):
  40.     x = np.arange(borders[0], borders[1] + h, h)
  41.     N = np.shape(x)[0]
  42.     y = np.zeros(N)
  43.     z = np.zeros(N)
  44.     y[0] = y0; z[0] = z0
  45.     for i in range(N-1):
  46.         K1 = h * z[i]
  47.         L1 = h * ddy(x[i], y[i], z[i])
  48.         K2 = h * (z[i] + 0.5 * L1)
  49.         L2 = h * ddy(x[i] + 0.5 * h, y[i] + 0.5 * K1, z[i] + 0.5 * L1)
  50.         K3 = h * (z[i] + 0.5 * L2)
  51.         L3 = h * ddy(x[i] + 0.5 * h, y[i] + 0.5 * K2, z[i] + 0.5 * L2)
  52.         K4 = h * (z[i] + L3)
  53.         L4 = h * ddy(x[i] + h, y[i] + K3, z[i] + L3)
  54.         delta_y = (K1 + 2 * K2 + 2 * K3 + K4) / 6
  55.         delta_z = (L1 + 2 * L2 + 2 * L3 + L4) / 6
  56.         y[i+1] = y[i] + delta_y
  57.         z[i+1] = z[i] + delta_z
  58.     return y, z
  59.  
  60. def Adams(ddy, borders, calc_y, calc_z, h):
  61.     x = np.arange(borders[0], borders[1] + h, h)
  62.     N = np.shape(x)[0]
  63.     y = calc_y[:4]
  64.     z = calc_z[:4]
  65.     for i in range(3, N-1):
  66.         # Этап: предиктор
  67.         z_next = z[i] + (h/24) * (55 * ddy(x[i], y[i], z[i]) -
  68.                           59 * ddy(x[i-1], y[i-1], z[i-1]) +
  69.                           37 * ddy(x[i-2], y[i-2], z[i-2]) -
  70.                           9 * ddy(x[i-3], y[i-3], z[i-3]))
  71.         y_next = y[i] + (h/24)*(55*z[i]-59*z[i-1]+37*z[i-2]-9*z[i-3])
  72.  
  73.         # Этап: корректор
  74.         z_i = z[i] + (h/24) * (9 * ddy(x[i+1], y_next, z_next) +
  75.                           19 * ddy(x[i], y[i], z[i]) -
  76.                           5 * ddy(x[i - 1], y[i - 1], z[i - 1]) +
  77.                           1 * ddy(x[i - 2], y[i - 2], z[i - 2]))
  78.         z = np.append(z, z_i)
  79.  
  80.         y_i = y[i] + (h/24)*(9*z_next + 19*z[i] - 5*z[i-1] + 1*z[i-2])
  81.         y = np.append(y, y_i)
  82.     return y
  83.  
  84. def sqr_error(y, y_correct):
  85.     return np.sqrt(np.sum((y-y_correct)**2))
  86.  
  87. def RungeRombert(y1, y2, h1, h2, p):
  88.     if h1 > h2:
  89.         k = int(h1 / h2)
  90.         y = np.zeros(np.shape(y1)[0])
  91.         for i in range(np.shape(y1)[0]):
  92.             y[i] = y2[i*k]+(y2[i*k]-y1[i])/(k**p-1)
  93.         return y
  94.     else:
  95.         k = int(h2 / h1)
  96.         y = np.zeros(np.shape(y2)[0])
  97.         for i in range(np.shape(y2)[0]):
  98.             y[i] = y1[i * k] + (y1[i * k] - y2[i]) / (k ** p - 1)
  99.         return y
  100.  
  101. borders = (0, 1)
  102. y0 = 1
  103. z0 = 1
  104. h = 0.1
  105. x = np.arange(borders[0], borders[1]+h, h)
  106. y = f(x)
  107. y1 = Euler(ddf, borders, y0, z0, h)
  108. y2 = EulerCauchy(ddf, borders, y0, z0, h)
  109. y3, z = RungeKutta(ddf, borders, y0, z0, h)
  110. y4 = Adams(ddf, borders, deepcopy(y3), z, h)
  111. # Получаем решения методов для шага h/2
  112. h2 = h/2
  113. y1_2 = Euler(ddf, borders, y0, z0, h2)
  114. y2_2 = EulerCauchy(ddf, borders, y0, z0, h2)
  115. y3_2, z2 = RungeKutta(ddf, borders, y0, z0, h2)
  116. y4_2 = Adams(ddf, borders, deepcopy(y3_2), z2, h2)
  117. print("Оценка погрешности методом Рунге-Ромберта:")
  118. print("Для явного метода Эйлера:", sqr_error(y1, RungeRombert(y1, y1_2, h, h2, 1)))
  119. print("Для явного метода Эйлера-Коши:", sqr_error(y2, RungeRombert(y2, y2_2, h, h2, 1)))
  120. print("Для метода Рунге-Кутты:", sqr_error(y3, RungeRombert(y3, y3_2, h, h2, 4)))
  121. print("Для метода Адамса:", sqr_error(y4, RungeRombert(y4, y4_2, h, h2, 4)))
  122. print("\nСравнение с точным решением:")
  123. print("Для явного метода Эйлера:", sqr_error(y1, y))
  124. print("Для явного метода Эйлера-Коши:", sqr_error(y1, y))
  125. print("Для метода Рунге-Кутты:", sqr_error(y3, y))
  126. print("Для метода Адамса:", sqr_error(y4, y))
  127. plt.figure(figsize=(12, 7))
  128. plt.plot(x, y, label='Точное решение', linewidth=1, color="green")
  129. plt.plot(x, y1, label='Явный метод Эйлера', linewidth=1, color="yellow")
  130. plt.plot(x, y2, label='Явный метод Эйлера-Коши', linewidth=1, color="orange")
  131. plt.plot(x, y3, label='Метод Рунге-Кутты', linewidth=1, color="red")
  132. plt.plot(x, y4, label='Метод Адамса', linewidth=1, color="blue")
  133. plt.grid()
  134. plt.legend()
  135. plt.show()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement