【问题标题】:how to update parameter and pass to solve_ivp in Python如何在Python中更新参数并传递给solve_ivp
【发布时间】:2020-11-28 11:17:43
【问题描述】:

在我的 ODE 函数中,我需要迭代求解一个参数的方程,直到在每个时间步收敛。我想传递最新的参数值以用作下一个时间步的初始值,因此当函数对参数进行迭代更新时,它将花费更少的时间。但我不知道该怎么做。 ODE函数的代码结构是这样的:

    from scipy.integrate import solve_ivp

    def run(t, y):
      if t==0:
        a = 1e-8
      nn = 0
      while nn<=100:
        nn = nn +1
        #update a until convergence
    return a*y

在某种语言中,我可以返回更新后的参数以供集成商使用,但我不知道solve_ivp 是如何实现的

【问题讨论】:

  • 为了更清楚你想要实现的目标,正如我之前看到的那样:你想要解决一些隐式 ODE,比如y'=v, F(t,y,v)=0。您已经有一些等价于这个方程v=g(t,y,v) 的定点迭代,它收敛得相当快。剩下的就是为定点迭代找到一个好的初始猜测,并且您想使用最后一个值还是一个好的外推值?
  • 当然,如果 scipy.integrate 有 DAE 求解器,我建议将公式 y'=v, 0=F(t,y,v) 视为半显式 index-1 微分代数方程组。然后自动/内部解决隐式解决方案和良好初始点的问题。
  • 没错!该参数满足非线性代数方程。它的解对初始猜测很敏感,因此最好使用当前时间步的值作为初始猜测来开始下一个时间步的非线性求解器迭代。
  • 我看到了使用 DAE 的意义。但我觉得更普遍的一点是,是否可以让 ODE 函数返回导数以外的值,以及求解器是否可以使用非导数的返回值。我之前使用过 R 和 Julia,它们都允许某种回调来让 ODE 函数返回不限于导数的值。
  • 您描述的更专业的情况是y'=a*y, 0=F(t,y,a) 与适应参数aa 可以有多个根,但您希望 a(t) 的曲线是连续的。当活动根接近另一个根时,这会成为问题。有时它有助于强制a(t) 的导数也是连续的。

标签: python scipy ode


【解决方案1】:

不清楚你在追求什么:你想在一系列参数值处获得一个 ODE 的解(即,对于你求解完整 ODE 的每个参数值)还是你正在更改参数 以及与 ODE 迭代(IOW,您想要内部或外部迭代)。

如果是前者,那么只需对参数执行一个 for 循环。如果是后者,使用实现特定求解器(DOPRI、Radau、RK、BDF 等)的求解器类可能会更容易和更清晰,solve_ivp 将工作委托给这些求解器。他们提供了一个step 方法,它只执行一个步骤。这样您就可以以与此特定情况最相关的方式调整参数、控制收敛等。

【讨论】:

  • 我想要的是后者。参数取决于状态。在实践中,我不需要将参数值传递给下一个时间步,因为它可以在每个时间步迭代地求解。但这会耗费时间。因此,如果我可以将当​​前值传递给下一个时间步,那么将需要更少的迭代来收敛到一个新参数。所以关键点是否可以让ODE函数返回除导数以外的值,以及求解器是否可以使用返回值。
【解决方案2】:

我认为您正在寻找的是以下形式的东西:

class test:
    a = 1e-8
    def f(self, t, y):
        ## do iter on self.a
        return self.a*y
        
t = test()
# solve_ivp(t.f, .....)

这样,您始终可以使用 a 的最后一个值,因为它是您的 test 类实例的一部分。这并不完全是您所要求的,因为这将在每次solve_ivp 评估f 时调用迭代,每个时间步将多次。但是,我认为这是您可以获得的最接近的值,因为 solve_ivp 似乎没有在每个时间步之后调用 callback 函数

【讨论】:

    猜你喜欢
    • 2020-10-24
    • 2022-01-04
    • 2018-06-23
    • 2018-05-28
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多