我正在尝试用欧拉方法求解常微分方程组,但当我尝试打印速度时我得到了
RuntimeWarning: overflow encountered in double_scalars
而不是打印数字我得到nan
(不是数字)。我认为问题可能在于定义加速度时,但我不确定,如果有人能帮助我,我真的很感激。
from numpy import *
from math import pi,exp
d=0.0005*10**-6
a=[]
while d<1.0*10**-6 :
d=d*2
a.append(d)
D=array(a)
def a_particula (D,x, v, t):
cc=((1.00+((2.00*lam)/D))*(1.257+(0.400*exp((-1.10*D)/(2.00*lam)))))
return (g-((densaire*g)/densparticula)-((mu*18.0*v)/(cc*densparticula* (D**2.00))))
def euler (acel,D, x, v, tv, n=15):
nv, xv, vv = tv.size, zeros_like(tv), zeros_like(tv)
xv[0], vv[0] = x, v
for k in range(1, nv):
t, Dt = tv[k-1], (tv[k]-tv[k-1])/float(n)
for i in range(n):
a = acel(D,x, v, t)
t, v = t+Dt, v+a*Dt
x = x+v*Dt
xv[k], vv[k] = x, v
return (xv, vv)
g=(9.80)
densaire= 1.225
lam=0.70*10**-6
densparticula=1000.00
mu=(1.785*10**-5)
tv = linspace(0, 5, 50)
x, v = 0, 0 #initial conditions
for j in range(len(D)):
xx, vv = euler(a_particula, D[j], x, v, tv)
print(D[j],xx,vv)
答案 0 :(得分:4)
将来如果您在问题中包含完整的警告信息会有所帮助 - 它将包含出现问题的行:
tmp/untitled.py:15: RuntimeWarning: overflow encountered in double_scalars
return (g-((densaire*g)/densparticula)-((mu*18.0*v)/(cc*densparticula* (D**2.00))))
当变量的大小超过可以表示的最大值时,会发生 Overflow。在这种情况下,double_scalars
指的是64位浮点数,其最大值为:
print(np.finfo(float).max)
# 1.79769313486e+308
因此表达式中有一个标量值:
(g-((densaire*g)/densparticula)-((mu*18.0*v)/(cc*densparticula* (D**2.00))))
超过~1.79e308。要找出哪一个,当发生这种情况时,您可以使用np.errstate
引发FloatingPointError
,然后抓住它并启动Python debugger:
...
with errstate(over='raise'):
try:
ret = (g-((densaire*g)/densparticula)-((mu*18.0*v)/(cc*densparticula* (D**2.00))))
except FloatingPointError:
import pdb
pdb.set_trace()
return ret
...
然后,您可以在调试器中检查此表达式各个部分的值。溢出似乎发生在:
(mu*18.0*v)/(cc*densparticula* (D**2.00))
第一次发出警告时,(cc*densparticula* (D**2.00)
评估为2.3210168586496022e-12,而(mu*18.0*v)
评估为-9.9984582297025182e + 299。
基本上,您将一个非常大的数字除以一个非常小的数字,结果的大小超过了可以表示的最大值。这可能是您的数学问题,或者可能是您对函数的输入没有合理缩放。
答案 1 :(得分:3)
您的系统缩减为
dv/dt = a = K - L*v
K
10
和L
介于1e+5
到1e+10
之间。使用的实际系数证实:
D=1.0000e-09 K= 9.787995 L=1.3843070e+08
D=3.2000e-08 K= 9.787995 L=4.2570244e+06
D=1.0240e-06 K= 9.787995 L=9.0146813e+04
速度的欧拉步骤是
v[j+1]=v[j]+(K-L*v[j])*dt =(1-L*dt)*v[j] + K*dt
对于任何类似于预期摩擦效应的东西,即速度降至K/L
,需要abs(1-L*dt)<1
,如果可能0<1-L*dt<1
,即dt < 1/L
。这意味着dt < 1e-10
。
为了能够使用更大的时间步长,您需要使用刚性微分方程的方法,这意味着隐式方法。最简单的是隐式Euler方法,中点方法和梯形方法。
由于线性,中点和梯形方法达到相同的公式
v[j+1] = v[j] + dt * ( K - L*(v[j]+v[j+1])/2 )
或
v[j+1] = ( (1-L*dt/2)*v[j] + K*dt ) / (1+L*dt/2)
当然,最简单的方法是完全整合ODE
(-L*v')/(K-L*v)=-L => K-L*v(t)=C*exp(-L*t), C=K-L*v(0)
v(t)=K/L + exp(-L*t)*(v(0)-K/L)
整合到
x(t)=x(0)+K/L*t+(1-exp(-L*t))/L*(v(0)-K/L).
或者有可能在将物理定律转录为公式时出错,因此常数的大小都是错误的。