Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python scipy ode更新集合作为集合solout的函数集合内的集合参数_Python_Scipy_Ode_Scientific Computing - Fatal编程技术网

Python scipy ode更新集合作为集合solout的函数集合内的集合参数

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

将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 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的代码吗?