在FiPy中使用扫描功能时的求解器公差和残差

时间:2019-02-11 15:50:19

标签: python scipy fipy

当我意识到 sweep 命令无法按我预期的方式工作时,我试图使用FiPy解决一组PDE。这里是带有部分代码的示例:

from pylab import *
import sys
from fipy import *

viscosity = 5.55555555556e-06 

Pe =5.

pfi=100.
lfi=0.01

Ly=1.
Nx =200
Ny=100
Lx=Ly*Nx/Ny
dL=Ly/Ny
mesh = PeriodicGrid2DTopBottom(nx=Nx, ny=Ny, dx=dL, dy=dL)

x, y = mesh.cellCenters

xVelocity = CellVariable(mesh=mesh, hasOld=True,  name='X velocity')

xVelocity.constrain(Pe, mesh.facesLeft)
xVelocity.constrain(Pe, 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_fi= CellVariable(mesh=mesh, value=0.,name='Fluid-interface energy map')
pi_fi.setValue(pfi*exp(-1.*(var1-rad)/lfi), where=(var1 > rad) )
pi_fi.setValue(pfi, where=(var1 <= rad))

xVelocityEq = DiffusionTerm(coeff=viscosity) - ImplicitSourceTerm(pi_fi)

xres=10.
while (xres > 1.e-6) :
        xVelocity.updateOld()
        mySolver = LinearGMRESSolver(iterations=1000,tolerance=1.e-6)
        xres = xVelocityEq.sweep(var=xVelocity,solver=mySolver)
        print 'Result = ', xres
#Thats it

简而言之,我要声明一个名为 xVelocityEq 的函数,并使用 sweep 对其进行求解。这是我的输出:

Result =  0.0007856742013190237
Result =  6.414470433257661e-07

如您所见,while循环在两次迭代后结束。我的第一个问题是:为什么我的第一个残差(= 0.0007856742013190237)高于求解器的公差?我以为,因为 xVelocityEq 对应于线性系统,所以求解器公差和残余误差将表示同一件事。

如果我增加编号。在 mySolver 中从1000到10000的迭代次数,我得到以下输出:

Result =  0.0007856742013190237
Result =  2.4619110931978988e-09

为什么第二个残差发生变化,因为第一个残差保持不变?

如果将 mySolver 中的容差从1.e-6增加到7.e-4,则会得到以下输出:

Result =  0.0007856742013190237
Result =  6.414470433257661e-07

请注意,这些残差与第一个输出中的相同。现在,如果我尝试将公差进一步提高到8.e-4,这是我得到的输出:

Result =  0.0007856742013190237
Result =  0.0007856742013190237
Result =  0.0007856742013190237
Result =  0.0007856742013190237
Result =  0.0007856742013190237
...

这时我完全迷路了。 为什么对于所有小于7.e-4的求解器公差,残差具有相同的值?以及为什么对于求解器公差高于7.e-4的情况,这些残差恒定且等于0.0007856742013190237?

如果我将mySolver更改为 LinearLUSolver (迭代次数= 1000,公差= 1.e-6),这就是我得到的:

Result =  0.0007856742013190237
Result =  1.6772757200988522e-18

即使更改了求解器,为什么我的第一个残差与以前一样?

1 个答案:

答案 0 :(得分:1)

  

为什么我的第一个残差(= 0.0007856742013190237)高于求解器的公差?

.sweep()计算的残差是在调用求解器以计算新的求解矢量之前 进行计算的。矩阵 L 和右侧矢量 b 是根据解矢量 x 的初始值计算的。

残差用于衡量当前解矢量满足非线性 PDE的程度。求解器公差限制了求解器满足PDE离散化的 linear 方程组的工作难度。

即使PDE是线性的(例如,扩散系数不是解变量的函数),其初始值大概也不能解决PDE,因此残差很大。调用求解器后, x 应该在求解器公差范围内求解PDE。如果PDE是非线性的,那么线性代数的良好收敛解可能仍然不是PDE的良好解决方案。那就是扫地的目的。

  

我认为,由于xVelocityEq对应于线性系统,所以求解器的容差和残余误差将意味着同一件事。

跟踪两者都没有任何实用程序。除了用于求解之前的残差和用于终止求解的求解器公差之外,还可以使用不同的规范化,并且许多求解器文档都可能是粗略的。 FiPy使用| L x - b | _2作为残差。解算器可能会根据 b 的大小, L 的对角线或月球的相位进行归一化,所有这些都可能使得很难直接比较残差和容差

  

为什么第二个残差发生变化,而第一个残差保持不变?

通过允许1000次迭代而不是100次迭代,求解器能够驱动到更严格​​的公差,从而导致下一次扫描的残差较小。

  

为什么对于所有小于7.e-4的求解器公差,残差具有相同的值?又为什么对于求解器公差高于7.e-4的情况,这些残差是恒定的并且等于0.0007856742013190237?

可能是因为求解器发生故障,因此没有更改求解矢量的值。一些求解器不报告此情况。在其他情况下,我们应该更好地向您报告该事实。

  

即使更改了求解器,为什么我的第一个残差与以前一样?

残差不是求解器的属性。它是离散化方程组的一个属性,它近似于您的PDE。然后,这些线性代数方程式便成为求解器的输入。