scipy.integrate.odeint:odeint 如何访问独立于它演化的参数集?

计算科学 scipy 造型
2021-12-12 00:45:52

我可能有一些非线性 ODE 正在解决scipy.integrate.odeint但是,可能必须使用非 DE 规则更新每个时间步的参数,该规则使用 ODE 求解器在每个时间步的结果以及执行积分的变量,以更新参数. 例如,非 DE 规则可能是“背景”PDE 系统的粗略离散化。


这是一个玩具示例,与我现在正在做的事情有关:我们可能有一个粒子,它有一些与它相关的属性()随着时间的推移而演变——假设代表 2D粒子的位置,以及的“颜色”。粒子在二维空间上移动。二维空间是离散的,每个离散点都有一个与之相关的属性 - 假设通过以下规则演变:xyzxyzpp

  1. 某些预选的空间点有一个p
  2. 如果一个粒子最近访问了一个空间点,设置为零p
  3. 在每个时间步,选择 10 个(大小为 4)的相邻空间点的随机集合,并将它们的设置为集合中点的平均tpp

在计算 RHS( )时,我们需要知道离粒子当前位置最近的空间点上的平均值是多少。然而,将的演化作为一堆 DE 规则嵌入到空间点上并不简单……否则我们可以简单地通过像、 ... 之类的 ODE 系统, ) 到.dx/dtdy/dtdz/dtppdx/dtdy/dtdp1/dtdpn/dtodeint


假设我希望 ODE 结果位于t = [t1, ..., t2]. 然后,我可以设置程序,以便每次调用时odeint,我只让它在一个时间步之间给我结果,然后在odeint再次调用之前使用这些结果更新非 DE 规则。但是,这将是非常低效的,因为我会破坏odeint' 的内部流程?

有没有其他方法可以解决这个问题?难道我可以从“odeint”的面向对象版本继承,然后让我的班级在每个步骤之间执行非 DE 步骤?这会比上面建议的幼稚解决方案更有效吗?

2个回答

编辑:不,该过程将与任何自适应时间步进器不兼容。它不是确定性的,即使对于非自适应 ODE 求解器,您提出的过程也会降低解决方案的准确性。


您必须更详细地描述您想要做什么。

通常,更改参数会更改您要求解的方程。如果您的参数以平滑(无限连续可微,所有导数在您的积分区间内有界)方式变化,则取决于此“非微分方程规则”,最好弄清楚如何查询更新作为您的权利的一部分-手边函数评估(和雅可比函数评估)。

如果它没有以平滑的方式变化,这取决于你有多少有界、连续的导数。通常,微分方程求解器使用插值多项式来求解近似微分方程,k 阶方法的误差项阶导数有关。如果您有高达阶的有界连续导数,那么您可以使用高达阶的方法。如果没有连续导数,则必须使用收敛阶数较低的特殊方法。kk+1k+1k

如果您尝试像您提议的那样拼凑起来,可能会发生的情况是集成器将反复重新启动,这将是低效的,并且可能不准确。我不认为将面向对象版本的子类化odeint可以解决这个问题,因为正如我上面所描述的,这个问题是一个基本的数值分析问题。

当然,你可以一起破解一些可能有用的东西。

logger = [] # visible in odefunc

def odefunc(P,t):

    if logger: # if the list is not empty
        if logger[-1]: # then read the last values 
            pass # and do something based on them

    **your complex math here***
    some_calculated_value = 0.123    

    logger.append([t, some_calculated_value]) 

    return something

print(logger)