Python中的ODE求解器将函数的RHS作为参数。这个函数应该签名f(t, y *args)
。通常,y
可以是一个numpy数组,f
将返回一个与y
大小相同的数组ydot
。然而,语法要求f
应该只返回一个东西,并且只返回一个东西:ydot
数组(或者float is y也是float)。ODE求解器在内部根据需要多次调用f
,以达到收敛。
但是在我的例子中,这个f
返回一个元组。不仅仅是ydot
,还有更多的数组。现在我可以将这部分移到f
之外,并在求解器达到收敛后调用它。但是我改变了行为,因为这些参数并没有在每个时间步计算时更新(这应该发生)。所以我需要这部分代码。但是像scipy.integrate_solve_ivp
这样的求解器的语法要求f
应该只返回ydot
。因此,我没有办法“捕获”额外的参数,并在求解器再次调用它时传递回f
。
下面是一段代码,给出了大致的想法(注意,这段代码只是我的实际代码的替身,我不能分享,但要点是一样的,我的函数的RHS返回一个元组):
import numpy as np
from scipy.integrate import solve_ivp
# Define the RHS function
def f(t, y, param1, param2):
# Calculate the derivative dy/dt
ydot = np.sin(t) * y[0] + np.cos(t) * y[1] # Example derivative equation
# Calculate additional parameters
param1 = some_func_1(ydot, param1)
param2 = some_func_1(ydot, param2)
# Return ydot and additional parameters as a tuple
return ydot, param1, param2
# Define the time span and initial condition
t_span = (0, 5)
y0 = np.random.rand(2) # Random initial condition
# Solve the ODE using solve_ivp
sol = solve_ivp(f, t_span, y0, args=(param1, param2))
字符串some_func_1
和some_func_2
是接受param1和param2并对其进行修改的函数。
我试着查看solve_ivp
的events
参数,但它不起作用。我想是为了别的事。
但这似乎是一个问题,一定有人遇到过,对不对?我可以看到的一个解决方法是使用全局变量,我不返回额外的参数,而是将它们存储在全局列表或全局变量或其他东西中。但我认为全局变量是危险的,因为它们可能会引入bug。所以我在寻找一种更接近的方法。
编辑:
我刚意识到一件事:args
或solve_ivp
是否可以自己执行功能?因此表达式变为:
sol = solve_ivp(f, t_span, y0, args=(some_func_1(param1), some_func_2(param2))
型
但即使在这里,通过some_func_1
捕获返回的问题仍然存在。
2条答案
按热度按时间plicqrtu1#
小心地传递
args
对象给函数并修改它们是可能的。对象需要是可变的,比如数组或列表。例如,以
expoential_decay
为例,让我们添加一种收集所有t
值的方法。我将par
定义为一个列表,并使用append
就地修改它。我可以用数组做些什么,但这是最容易想到的事情。字符串
0x6upsns2#
您的ODE似乎不受
param1
和param2
值的影响。因此,我建议将它们从ODE中删除,然后使用从solve_ivp
获得的解决方案简单地计算它们。字符串