Ваше начальное условие для численного решения - y(-4)=y0
, поскольку odeint
принимает первую точку временного интервала в качестве начального времени.Соответственно, вам придется изменить ваше точное решение на
y_exact = 1+((y0-1)*(1-xs[0]**2))/(1-xs**2)
, поскольку вы можете проверить с помощью инструмента по вашему выбору, например WA y'(x)=2*x*(y(x)-1)/(1-x^2), y(a)=b
.
AsВы также заметили, что ваш ODE является единичным в x=-1
и x=1
, так что любое решение имеет в качестве домена только один из 3 подинтервалов, созданных этими точками, а именно тот, который содержит начальное время.Кроме того, численные методы не очень хорошо работают с особенностями, поэтому вам придется ограничить область интеграции до [-4, -1-delta]
для некоторых маленьких, но не слишком маленьких delta
.Или, если вы действительно хотите исследовать средний интервал с начальным временем в 0
, вам нужно выполнить две интеграции: одну от 0
до -1+delta
и одну от 0
до 1-delta
.
Если вы рассматриваете соответствующее дифференциальное уравнение без вещественных особенностей
y'(x) = -2*x*(y-1)/(1+x^2), y(x0) = y0
с точным решением
y(x) = 1 + (y0-1)*(1+x0^2)/(1+x^2)
, реализованное с помощью модифицированного кода
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
# Define a function which calculates the derivative
def dy_dx(y,x): return -2.0*x*(y-1)/(1+x**2) #
# Flow function
def phi(x,x0,y0): return 1 + (y0-1)*(1+x0**2)/(1+x**2)
xs = np.linspace(-4,4,100)
for i in range(-10,10,2):
y0 = 1+0.1*i
ys = odeint(dy_dx, y0, xs)
ys = ys.flatten()
plt.plot(xs, phi(xs,xs[0],y0),c='lightgray', lw=4);
plt.plot(xs, ys, lw=1, label='$y_0=%.2f$'%y0);
plt.grid(); plt.xlim(-5.5,4.2); plt.legend(); plt.show()
, выПолучите следующий график, где вы найдете (цветное) численное решение, точно отцентрированное внутри (подкладка серого) точного решения.