我有一个问题,需要解决一个ODE系统,并且我正在使用scipy.integrate.solve_ivp。致电集成商时,我要指定集成的时间间隔以及要评估解决方案的时间点。呼叫看起来像这样:
Z_solution = solve_ivp( fun= lambda t, y: rhs_of_differential_equation( t, y, args_tuple ),
t_span= time_interval, y0 = initial_array,
method='RK45',
t_eval = np.array( [ 0.0 ] ),
max_step = parameters.max_step,
first_step = parameters.initial_step,
rtol = parameters.adaptive_step_relative_tolerance,
atol = parameters.adaptive_step_absolute_tolerance,
)
这意味着我只对t = 0时的解决方案感兴趣,而介于两者之间的其他任何内容都与我的情况无关。但是,在调用solve_ivp时,我正在跟踪积分器正在使用的t值,因此,我正在跟踪算法中的所有“中间”步骤。但是我想知道是否有一种方法可以真正查看哪些步骤成功了,而不是中间步骤。在我看来,上面的调用将整合所有直到t = 0.0的内容,但并没有告诉您整合步骤是否成功...在此,我将不胜感激,谢谢!
附加信息:我的解向量y实际上依赖于一个也随t缩放的网格。也就是说,如果y是我对ODE的解,它将由N个点组成,其中N是网格的大小(对于t的固定值)。这意味着,对于积分t = 0.0的终点,我的解决方案y是具有N个元素的数组。但是,计算值的网格也取决于t的值。有没有办法在整个集成算法中一致地更改网格?我试图在初始条件数组中传递网格,但似乎无法正常工作。
EDIT-2:在这里,我写了一些代码来理解这一点。我的问题的规模变化很大,因此,我想让积分器为我选择必要的时间步长,因此,我不想事先将t_evals选择为固定的点数;我只需要间隔的开始和结束时间。在此期间,积分器将进行必要的步长调整,以不超出公差范围。然后,我的问题是要确定这些内部点(积分器能够计算的[0,10]之间的点)。由solve_ivp函数返回的束对象中的对象SolveODE似乎具有“ ts”值,以及 call 方法,该方法原则上在那些时间步中检索生成的解决方案。这是一个简单的指数衰减函数的代码:
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as pyt
def my_fun2( t, y, *args ):
return -0.5*y
vals = np.array( [ 100 ] )
args_tuple = ( 0.01, 0.5 )
Z_solution = solve_ivp( fun= lambda t, y: my_fun2( t, y, args_tuple ),
t_span= [0.0, 10], y0 = vals,
method='RK45',
t_eval = [0.0, 10],
dense_output = True,
rtol=1e-7, atol = 1e-7,
)
OdeSol = Z_solution.sol
y_sol = OdeSol.__call__( OdeSol.ts )[0]
ts = OdeSol.ts
x = np.linspace( 0, 10, 1000 )
analytic = 100*np.exp( -0.5*x )
for s in range( 0, len(vals) ):
pyt.plot( ts, y_sol, 'ob', x, analytic, '-r' )
pyt.show()
以及解析解和(ts,y_sol)的点给出:
然后,如果我理解正确的话,蓝色点是积分器在[0,10]区间内未超过公差的范围内找到解的点。如果您减小公差,那么蓝点数量当然会减少,有人可以确认吗?
最重要的是,我的系统需要以某种方式告诉每个ts点该函数停止,对在该点找到的y_sol进行一些网格调整,然后继续集成。有没有办法通过使用solve_ivp来做到这一点?我只能考虑自己在Solve_ivp中包含此功能,但我真的不希望这样做,因为这将意味着修改Solve_ivp代码以允许此类功能,非常感谢!