Python scipy ode更新集合作为集合solout的函数集合内的集合参数
将ode与scipy集成时,ode接受的函数的参数多于t和y。例如:Python scipy ode更新集合作为集合solout的函数集合内的集合参数,python,scipy,ode,scientific-computing,Python,Scipy,Ode,Scientific Computing,将ode与scipy集成时,ode接受的函数的参数多于t和y。例如: def-fun(t,y,param1,param2): 这些参数的值可以使用set\u f_params方法设置 但是,当同时使用set_solout方法并尝试在该函数内使用set_f_params更新参数时,积分保持不变,就好像没有修改参数一样 您将如何使用sol_out修改参数我希望从dopri5密集输出中获益,但我需要在每个时间步更新非齐次项 下面是一个简单的例子 import numpy as np import ma
def-fun(t,y,param1,param2):
这些参数的值可以使用set\u f_params
方法设置
但是,当同时使用set_solout
方法并尝试在该函数内使用set_f_params
更新参数时,积分保持不变,就好像没有修改参数一样
您将如何使用sol_out修改参数我希望从dopri5密集输出中获益,但我需要在每个时间步更新非齐次项
下面是一个简单的例子
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import ode
def fun(t, x, param):
return x - param
def f_param(t):
return t
ode1 = ode(fun).set_integrator('dopri5').set_initial_value([10.0])
ode1.set_f_params(f_param(0))
results1 = ([], [])
ode2 = ode(fun).set_integrator('dopri5').set_initial_value([10.0])
ode2.set_f_params(f_param(0))
results2 = ([], [])
def callback1(t, x):
results1[0].append(t)
results1[1].append(x.copy())
def callback2(t, x):
results2[0].append(t)
results2[1].append(x.copy())
ode2.set_f_params(f_param(t))
ode1.set_solout(callback1)
ode2.set_solout(callback2)
ode1.integrate(3)
ode2.integrate(3)
plt.plot(results1[0], results1[1], 'o-', alpha=0.7, label='ode1')
plt.plot(results2[0], results2[1], '.--', label='ode2')
plt.legend()
结果如下所示:
受@Wrzlprmft评论的启发,如果参数不是常量,则不使用参数,并在要更新的函数中直接调用更新参数的函数,这样更安全。正如他所说,这意味着:
def fun(t, x):
return x - f_param(t)
但是,该函数(f_param
在这种情况下)可能无法在要集成的函数的命名空间中访问(在上面的示例中为fun
)。因此,将函数设置为要集成的函数的参数更方便,并且在开始时只使用一次set_f_params
来指定函数
作为问题代码的延续:
def fun3(t, x, fun):
return -x + fun(t)
def fun4(t, x):
return -x + t
ode3 = ode(fun3).set_integrator('dopri5').set_initial_value([10.0])
ode3.set_f_params(f_param)
results3 = ([], [])
ode4 = ode(fun4).set_integrator('dopri5').set_initial_value([10.0])
results4 = ([], [])
def callback3(t, x):
results3[0].append(t)
results3[1].append(x.copy())
def callback4(t, x):
results4[0].append(t)
results4[1].append(x.copy())
ode3.set_solout(callback3)
ode4.set_solout(callback4)
ode3.integrate(3)
ode4.integrate(3)
plt.figure(figsize=(8, 5))
plt.plot(results1[0], results1[1], 'o-', alpha=0.7, label='ode1')
plt.plot(results2[0], results2[1], '.--', label='ode2')
plt.plot(results3[0], results3[1], 's-.', label='ode3')
plt.plot(results4[0], results4[1], '^-.', label='ode3')
plt.legend()
如图所示,ode3和ode4提供相同的解决方案:
这是在SciPy 1.0中发布时的操作方式:
from functools import partial
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
def fun_fixed(t, x, param):
return x - param
sol_fixed = solve_ivp(
partial(fun_fixed, param=0), (0, 3), [10.0], dense_output=True)
def fun_param(t, x, fun):
return -x + fun(t)
def f_param(t):
return t
sol_param = solve_ivp(
partial(fun_param, fun=f_param), (0, 3), [10.0], dense_output=True)
t = np.linspace(0, 3, num=16)
plt.figure(figsize=(8, 5))
plt.plot(t, sol_fixed.sol(t)[0], 'o-', alpha=0.7, label='ode1')
plt.plot(t, sol_param.sol(t)[0], 's-.', label='ode3')
plt.legend()
请注意,在计算导数时,您最有可能通过完全不使用参数,而是采取一切必要的措施来获得与时间相关的参数来避免此问题。在您的示例中,您可以使用
deffun(t,x):返回x-f_参数(t)
。顾名思义,set\u solout
是指在每一个自适应集成步骤之后,如果您想要像输出这样的东西。还要注意,每个集成步骤在不同的时间包含多个函数求值。因此,使用set\u solout
更改参数的频率比我建议的备选方案要低。您是对的,使用set\u solout
更新参数不是最佳的备选方案,因为它们在自适应积分步骤中是固定的。但是,直接调用在要集成的函数中设置参数的函数并不总是一个选项。然而,该函数可以作为param本身传递,并且永远不需要更新!更容易和功能!伟大的谢谢@astrojuanlu@astrojuanlu是否可以将此解算器用于ode系统?当然,也可以用于较旧的解算器。你必须以向量/数组的形式写它们,查看文档。什么是有趣的(t)?这不是有点多余吗?不能在fun_param本身中包含f_param的代码吗?