我正在使用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)
答案 0 :(得分:4)
你遇到了this issue。要使set_solout
正常工作,必须在set_integrator
后set_initial_value
之前调用它。如果您将此修改引入代码(并为g
设置一个值),则集成将在z >= H
时终止,如您所愿。
要查找气泡到达曲面的确切时间,您可以在solout
终止积分后对变量进行更改,并与z
进行积分(而不是{{1 }}}到t
。描述该技术的论文是M. Henon, Physica 5D, 412 (1982);您可能还会发现this discussion有帮助。这是一个非常简单的示例,其中z = H
时间为t
,y(t) = 0.5
为dy/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)