我目前正在使用扫描环在python中使用FiPy求解关于单元格变量 phi 的微分方程( eq0 )。因为我的方程是非线性的,所以我使用了 sweep 循环,如下面的代码摘录所示。
while res0 > resphi_tol:
res0 = eq0.sweep(var=phi, dt=dt)
但是我不断收到以下错误:
C:\ Python27 \ lib \ site-packages \ fipy \ variables \ variable.py:1100:RuntimeWarning:power中遇到无效值 返回self._BinaryOperatorVariable(lambda a,b:pow(a,b),其他,value1mattersForUnit = True)
C:\ Python27 \ lib \ site-packages \ fipy \ variables \ variable.py:1186:RuntimeWarning:在less_equal中遇到无效值 返回self._BinaryOperatorVariable(lambda a,b:a <= b,其他)
追溯(最近一次通话):
..
中的文件“ SBM_sphere3.py”,第59行 .... res0 = eq0.sweep(var = phi,dt = dt)
.. 清除文件“ C:\ Python27 \ lib \ site-packages \ fipy \ terms \ term.py”,行207
.... solver._solve()
..文件“ C:\ Python27 \ lib \ site-packages \ fipy \ solvers \ pysparse \ pysparseSolver.py”,第68行,位于_solve
.... self。 solve (self.matrix,array,self.RHSvector)
..文件“ C:\ Python27 \ lib \ site-packages \ fipy \ solvers \ pysparse \ linearLUSolver.py”,第53行,在_solve__
.... LU = superlu.factorize(L.matrix.to_csr())
..文件“ C:\ Python27 \ lib \ site-packages \ pysparse \ misc__init __。py”,第29行,位于newFunc
.... return func(* args,** kwargs)
..文件“ C:\ Python27 \ lib \ site-packages \ pysparse__init __。py”,第47行,分解为
....返回self.factorizeFnc(* args,** kwargs)
RuntimeError:因子完全是奇数
我非常确定此错误是由于 eq0 中出现的词phi ^(2/3)引起的。如果我用abs(phi)^(2/3)代替这个术语,错误就会消失。
我假设扫描循环有时会为 phi 中的几个单元格返回负值,这会导致错误,因为我们不能使用非整数指数来赋负值。
所以我的问题是:有没有一种方法可以强制进行扫频以避免出现负面解决方案?
我尝试添加一行以在扫描前将所有负值设置为0:
while res0 > resphi_tol:
phi.setValue(0.,where=phi<0.)
res0 = eq0.sweep(var=phi, dt=dt)
错误仍然存在(因为在求解线性化系统后,扫掠会尝试计算新的系数矩阵?)
编辑:我正在将Python 2.7.14与FiPy 3.2结合使用。我在我认为与查询相关的代码部分下面共享。整个代码相当广泛。 一些背景:我正在求解悬架流量的平衡方程。 eq0 对应于粒子相的质量平衡方程, phi 是粒子的体积分数。
from pylab import *
from fipy import *
from fipy.tools import numerix
from scipy import misc
import osmotic_pressure_functions as opf
kic=96.91
lic=0.049
dt=1.e-2
steps=10
tol=1.e-6
Nx=8
Ny=4
Lx=Nx/Ny
dL=1./Ny
mesh = PeriodicGrid2DTopBottom(nx=Nx, ny=Ny, dx=dL, dy=dL)
x, y = mesh.cellCenters
phi = CellVariable(mesh=mesh, hasOld=True, value=0.,name='Volume fraction')
phi.constrain(0.01, mesh.facesLeft)
phi.constrain(0., mesh.facesRight)
rad=0.1
var1 = DistanceVariable(name='distance to center', mesh=mesh, value=numerix.sqrt((x-Nx*dL/2.)**2+(y-Ny*dL/2.)**2))
pi_ci = CellVariable(mesh=mesh, value=0.,name='Colloid-interface energy map')
pi_ci.setValue(kic*exp(-1.*(var1-rad)/(1.*lic)), where=(var1 > rad))
pi_ci.setValue(kic, where=(var1 <= rad))
def pi_cc_entr(x):
return opf.vantHoff(x)
def pi_cc_vdw(x):
return opf.van_der_waals(x,0.74,0.1)
def pi_cc(x):
return pi_cc_entr(x) + pi_cc_vdw(x)
diffusioncoeff = misc.derivative(pi_cc,phi,dx=1.e-6)
eq0 = TransientTerm() + ConvectionTerm(-pi_ci.faceGrad) == DiffusionTerm(coeff=diffusioncoeff)
step=0
t=0.
for step in range(steps):
print 'Step ', step
phi.updateOld()
res0 = 1e+10
while res0 > tol :
phi.setValue(0., where=phi<0)
res0 = eq0.sweep(var=phi, dt=dt) #ERROR HAPPENS HERE
函数 vantHoff 和 van_der_waals 在单独的文件中定义。
def vantHoff(phi):
return phi
def van_der_waals(phi,phi_cp,nd_v):
return (nd_v*phi**3) / ((phi_cp-(phi_cp)**(1./3.)*(phi)**(2./3.))**2)
答案 0 :(得分:0)
由于DiffusionTerm
的系数均为nan
,因此会出现错误。这又是因为扩散系数定义为
(((((((Volume fraction + -1e-06) + (((pow((Volume fraction + -1e-06), 3)) * 0.1) / (pow((0.74 - ((pow((Volume fraction + -1e-06), 0.6666666666666666)) * 0.9045041696510275)), 2)))) * -0.5) + 0.0) + (((Volume fraction + 0.0) + (((pow((Volume fraction + 0.0), 3)) * 0.1) / (pow((0.74 - ((pow((Volume fraction + 0.0), 0.6666666666666666)) * 0.9045041696510275)), 2)))) * 0.0)) + (((Volume fraction + 1e-06) + (((pow((Volume fraction + 1e-06), 3)) * 0.1) / (pow((0.74 - ((pow((Volume fraction + 1e-06), 0.6666666666666666)) * 0.9045041696510275)), 2)))) * 0.5)) / 1e-06)
和Volume fraction
(phi
)都为零,因此-1e-06
被提高为小数幂,这是不确定的。
-1e-06
的因素是由于您使用scipy.misc.derivative()
来显然地计算符号导数?我不认为这是为了这样做。 SymPy可能会带来更好的运气。