Вы допустили небольшую ошибку, и вам нужно сохранить результаты в контейнере, если вы хотите построить их. Я немного переписал твой код. Сначала я дам вам полный код, прежде чем обсуждать, что не так с вашим кодом. Может быть, вы сами заметите ошибки. Я также добавил расчет аналитического решения и некоторые другие небольшие улучшения, которые должны вам понравиться. Итак, вот код:
import matplotlib.pyplot as plt
import numpy as np
from math import exp # exponential function
dy = lambda x, y: x * y
f = lambda x: exp(x ** 2 / 2) # analytical solution function
x_final = 2
# analytical solution
x_a = np.arange(0, x_final, 0.01)
y_a = np.zeros(len(x_a))
for i in range(len(x_a)):
y_a[i] = f(x_a[i])
plt.plot(x_a, y_a, label="analytical")
# Container for step sizes
h = [0.5, 0.2, 0.1]
for j in range(len(h)):
x = 0
y = 1
print("h = " + str(h[j]))
print("x \t\t y (Euler) \t y (analytical)")
print("%f \t %f \t %f" % (x, y, f(x)))
n = int((x_final - x) / h[j])
x_n = np.zeros(n + 1)
y_n = np.zeros(n + 1)
x_n[0] = x
y_n[0] = y
for i in range(n):
y += dy(x, y) * h[j]
x += h[j]
print("%f \t %f \t %f" % (x, y, f(x)))
x_n[i + 1] = x
y_n[i + 1] = y
plt.plot(x_n, y_n, "x-", label="h=" + str(h[j]))
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.show()
На моем компьютере показано следующее: ![Euler Plot](https://i.stack.imgur.com/AqO6K.png)
Обратите внимание, что я переименовал вашу переменную xn
в x_final
чтобы избежать путаницы с введенными мною переменными. Как указано выше, вам необходимо хранить каждое из ваших значений x и y в контейнере. Для этого я использовал NumPy массивы, но вы также можете использовать список. Этот
n = int((x_final - x) / h[j])
x_n = np.zeros(n + 1)
y_n = np.zeros(n + 1)
x_n[0] = x
y_n[0] = y
просто создает 2 массива нулей, размер которых равен числу подэтапов +1. Затем я устанавливаю первые значения равными начальным значениям. Это должно быть внутри l oop сверх h
, так как число подшагов n
отличается для каждого h.
В конце вашего i
-l oop, я просто пишу текущие значения x
и y
для правильной позиции в массивах.
for i in range(n):
y += dy(x, y) * h[j]
x += h[j]
print("%f \t %f \t %f" % (x, y, f(x)))
x_n[i + 1] = x
y_n[i + 1] = y
Вместо вызова plt.plot
с x
и y
, который просто отображает одну точку, так как они являются sclars, вам нужно передать массивы в функцию:
plt.plot(x_n, y_n, "x-", label="h=" + str(h[j]))
Я также добавил метку, которая будет отображаться в легенде, и изменил тип линии на "x-"
.
Вы допустили одну ошибку, из-за которой ваши i
l oop были выполнены только для первых h
, заключались в том, что вы не сбросили x
и y
к их начальным значениям. Таким образом, ваш n
всегда был 0
после первого запуска внешнего l oop.
Конечно, есть несколько вещей, которые вы можете оптимизировать, например, использовать что-то вроде
for h in h_list:
...
который был бы немного более читабельным, чем всегда, используя h[j]
вместо просто h
, но я думаю, что пока этого достаточно. ;)