在 Python 中从 MATLAB 中模仿 ode45 函数
Imitate ode45 function from MATLAB in Python
我想知道如何将 MATLAB 函数 ode45 导出到 python。根据文档应该如下:
MATLAB: [t,y]=ode45(@vdp1,[0 20],[2 0]);
Python: import numpy as np
def vdp1(t,y):
dydt= np.array([y[1], (1-y[0]**2)*y[1]-y[0]])
return dydt
import scipy integrate
l=scipy.integrate.ode(vdp1([0,20],[2,0])).set_integrator("dopri5")
结果完全不同,Matlab returns 维度与 Python 不同。
integrate.ode is not as intuitive as of a simpler method odeint的接口,但是不支持选择ODE积分器。主要区别在于 ode
不会为您 运行 循环;如果你在一堆点上需要一个解决方案,你必须说出在哪些点上,然后一次计算一个点。
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
def vdp1(t, y):
return np.array([y[1], (1 - y[0]**2)*y[1] - y[0]])
t0, t1 = 0, 20 # start and end
t = np.linspace(t0, t1, 100) # the points of evaluation of solution
y0 = [2, 0] # initial value
y = np.zeros((len(t), len(y0))) # array for solution
y[0, :] = y0
r = integrate.ode(vdp1).set_integrator("dopri5") # choice of method
r.set_initial_value(y0, t0) # initial values
for i in range(1, t.size):
y[i, :] = r.integrate(t[i]) # get one more value, add it to the array
if not r.successful():
raise RuntimeError("Could not integrate")
plt.plot(t, y)
plt.show()
如@LutzL 所述,您可以使用较新的 API、solve_ivp
。
results = solve_ivp(obj_func, t_span, y0, t_eval = time_series)
如果未指定 t_eval
,那么每个时间戳将不会有一条记录,这是我假设的大多数情况。
另一个注意事项是,对于 odeint
和其他积分器,输出数组是 ndarray
形状 [len(time), len(states)]
,但是对于 solve_ivp
,输出是一维 ndarray 的 list(length of state vector)
(长度等于 t_eval
)。
所以如果你想要相同的订单,你必须合并它。您可以通过以下方式进行:
Y =results
merged = np.hstack([i.reshape(-1,1) for i in Y.y])
首先需要reshape使其成为[n,1]
数组,然后横向合并。
希望这对您有所帮助!
函数scipy.integrate.solve_ivp默认使用方法RK45,类似Matlab的函数使用的方法]ODE45 因为两者都使用具有四阶方法精度的 Dormand-Pierce 公式。
vdp1 = @(T,Y) [Y(2); (1 - Y(1)^2) * Y(2) - Y(1)];
[T,Y] = ode45 (vdp1, [0, 20], [2, 0]);
from scipy.integrate import solve_ivp
vdp1 = lambda T,Y: [Y[1], (1 - Y[0]**2) * Y[1] - Y[0]]
sol = solve_ivp (vdp1, [0, 20], [2, 0])
T = sol.t
Y = sol.y
我想知道如何将 MATLAB 函数 ode45 导出到 python。根据文档应该如下:
MATLAB: [t,y]=ode45(@vdp1,[0 20],[2 0]);
Python: import numpy as np
def vdp1(t,y):
dydt= np.array([y[1], (1-y[0]**2)*y[1]-y[0]])
return dydt
import scipy integrate
l=scipy.integrate.ode(vdp1([0,20],[2,0])).set_integrator("dopri5")
结果完全不同,Matlab returns 维度与 Python 不同。
integrate.ode is not as intuitive as of a simpler method odeint的接口,但是不支持选择ODE积分器。主要区别在于 ode
不会为您 运行 循环;如果你在一堆点上需要一个解决方案,你必须说出在哪些点上,然后一次计算一个点。
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
def vdp1(t, y):
return np.array([y[1], (1 - y[0]**2)*y[1] - y[0]])
t0, t1 = 0, 20 # start and end
t = np.linspace(t0, t1, 100) # the points of evaluation of solution
y0 = [2, 0] # initial value
y = np.zeros((len(t), len(y0))) # array for solution
y[0, :] = y0
r = integrate.ode(vdp1).set_integrator("dopri5") # choice of method
r.set_initial_value(y0, t0) # initial values
for i in range(1, t.size):
y[i, :] = r.integrate(t[i]) # get one more value, add it to the array
if not r.successful():
raise RuntimeError("Could not integrate")
plt.plot(t, y)
plt.show()
如@LutzL 所述,您可以使用较新的 API、solve_ivp
。
results = solve_ivp(obj_func, t_span, y0, t_eval = time_series)
如果未指定 t_eval
,那么每个时间戳将不会有一条记录,这是我假设的大多数情况。
另一个注意事项是,对于 odeint
和其他积分器,输出数组是 ndarray
形状 [len(time), len(states)]
,但是对于 solve_ivp
,输出是一维 ndarray 的 list(length of state vector)
(长度等于 t_eval
)。
所以如果你想要相同的订单,你必须合并它。您可以通过以下方式进行:
Y =results
merged = np.hstack([i.reshape(-1,1) for i in Y.y])
首先需要reshape使其成为[n,1]
数组,然后横向合并。
希望这对您有所帮助!
函数scipy.integrate.solve_ivp默认使用方法RK45,类似Matlab的函数使用的方法]ODE45 因为两者都使用具有四阶方法精度的 Dormand-Pierce 公式。
vdp1 = @(T,Y) [Y(2); (1 - Y(1)^2) * Y(2) - Y(1)];
[T,Y] = ode45 (vdp1, [0, 20], [2, 0]);
from scipy.integrate import solve_ivp
vdp1 = lambda T,Y: [Y[1], (1 - Y[0]**2) * Y[1] - Y[0]]
sol = solve_ivp (vdp1, [0, 20], [2, 0])
T = sol.t
Y = sol.y