代数约束终止与scipy的ODE集成

时间:2014-06-07 13:18:47

标签: python scipy

我正在使用Scipy 14.0来解决一个常微分方程系统,该系统描述了由于浮力而在静止流体中垂直(沿z方向)上升的气泡的动力学。特别是,我有一个方程表示上升速度U作为气泡半径R的函数,即U = dz / dt = f(R),一个表示半径变化作为R和U的函数,即dR / dT = F(R,U)。以下代码中出现的所有其他内容都是材料属性。 我想实现一些东西来解释z上的物理约束,这显然受到液体高度H的限制。因此我实现了一种z <= H约束,以便在需要时提前停止积分:我使用过set_solout是为了这样做。情况是代码运行并给出了良好的结果,但set_solout根本不工作(似乎z_constraint实际上从未被调用...)。你知道为什么吗? 是否有人有更聪明的想法,也可能是为了在z = H时确切地中断(即最终值问题)?这是正确的方法/工具,还是我应该重新解决问题?

提前致谢

惠美

from scipy.integrate import ode 

Db0 = 0.001 # init bubble radius
y0, t0 = [ Db0/2 , 0. ], 0. #init conditions
H = 1

def y_(t,y,g,p0,rho_g,mi_g,sig_g,H):
    R = y[0] 
    z = y[1]
    z_ = ( R**2 * g * rho_g ) / ( 3*mi_g )  #velocity
    R_ = ( R/3 * g * rho_g * z_ ) / ( p0 + rho_g*g*(H-z) + 4/3*sig_g/R ) #R dynamics    
    return [R_, z_]

def z_constraint(t,y):
    H = 1  #should rather be a variable..
    z = y[1] 
    if z >= H:
        flag = -1 
    else:
        flag = 0
    return flag

r = ode( y_ )
r.set_integrator('dopri5')
r.set_initial_value(y0, t0)
r.set_f_params(g, 5*1e5, 2000, 40, 0.31, H)
r.set_solout(z_constraint)

t1 = 6
dt = 0.1

while r.successful() and r.t < t1:
    r.integrate(r.t+dt)

1 个答案:

答案 0 :(得分:4)

你遇到了this issue。要使set_solout正常工作,必须在set_integratorset_initial_value之前调用它。如果您将此修改引入代码(并为g设置一个值),则集成将在z >= H时终止,如您所愿。

要查找气泡到达曲面的确切时间,您可以在solout终止积分后对变量进行更改,并与z进行积分(而不是{{1 }}}到t。描述该技术的论文是M. Henon, Physica 5D, 412 (1982);您可能还会发现this discussion有帮助。这是一个非常简单的示例,其中z = H时间为ty(t) = 0.5dy/dt = -y

import numpy as np
from scipy.integrate import ode

def f(t, y):
    """Exponential decay: dy/dt = -y."""
    return -y

def solout(t, y):
    if y[0] < 0.5:
        return -1
    else:
        return 0

y_initial = 1
t_initial = 0

r = ode(f).set_integrator('dopri5')
r.set_solout(solout)
r.set_initial_value(y_initial, t_initial)

# Integrate until solout constraint violated
r.integrate(2)

# New system with t as independent variable: see Henon's paper for details.
def g(y, t):
    return -1.0/y

r2 = ode(g).set_integrator('dopri5')
r2.set_initial_value(r.t, r.y)

r2.integrate(0.5)

y_final = r2.t
t_final = r2.y

# Error: difference between found and analytical solution
print t_final - np.log(2)