【问题标题】:How to Couple Advection Diffusion Reaction PDEs with FiPy如何将平流扩散反应 PDE 与 FiPy 耦合
【发布时间】:2019-02-15 01:49:21
【问题描述】:

我尝试使用 Matlab 函数 Pdepe (https://www.mathworks.com/help/matlab/ref/pdepe.html) 解决对流-扩散-反应问题的一维耦合偏微分方程。与扩散项相比,在对流项较高的情况下,此功能无法正常工作。 因此,我搜索并找到了使用 Python 库 FiPy 来解决我的 PDEs 系统的选项。 我的初始条件是 4*L/10 的 u1=1

我的耦合方程具有以下形式:

du1/dt = d/dx(D1 * du1/dx) + g * x * du1/dx - mu1 * u1 / (K + u1) * u2

du2/dt = d/dx(D2 * du2/dx) + g * x * du2/dx + mu2 * u1 / (K + u1) * u2

我尝试通过结合 FiPy 示例(examples.convection.exponential1DSource.mesh1D、examples.levelSet.advection.mesh1D、examples.cahnHilliard.mesh2DCoupled)来编写它。

以下行不是一个工作示例,而是我第一次尝试编写代码。这是我第一次使用 FiPy(在文档的测试和示例之外),所以对于普通用户来说,这似乎完全没有抓住重点。

from fipy import *

g = 0.66
L = 10.
nx = 1000
mu1 = 1.
mu2 = 1.
K = 1.
D1 = 1.
D2 = 1.

mesh = Grid1D(dx=L / 1000, nx=nx)

x = mesh.cellCenters[0]
convCoeff = g*(x-L/2)

u10 = 4*L/10 < x < 6*L/10
u20 = 1.

u1 = CellVariable(name="u1", mesh=mesh, value=u10)
u2 = CellVariable(name="u2", mesh=mesh, value=u20)

## Neumann boundary conditions
u1.faceGrad.constrain(0., where=mesh.facesLeft)
u1.faceGrad.constrain(0., where=mesh.facesRight)
u2.faceGrad.constrain(0., where=mesh.facesLeft)
u2.faceGrad.constrain(0., where=mesh.facesRight)

sourceCoeff1 = -1*mu1*u1/(K+u1)*u2
sourceCoeff2 = 1*mu2*u1/(K+u1)*u2

eq11 = (TransientTerm(var=u1) == DiffusionTerm(coeff=D1, var=u1) + ConvectionTerm(coeff=convCoeff))
eq21 = (TransientTerm(var=u2) == DiffusionTerm(coeff=D2, var=u2) + ConvectionTerm(coeff=convCoeff))

eq12 = ImplicitSourceTerm(coeff=sourceCoeff1, var=u1)
eq22 = ImplicitSourceTerm(coeff=sourceCoeff2, var=u2)

eq1 = eq11 & eq12
eq2 = eq21 & eq22

eqn = eq1 & eq2
vi = Viewer((u1, u2))

for t in range(100):
    u1.updateOld()
    u2.updateOld()
    eqn.solve(dt=1.e-3)
    vi.plot()

感谢您的任何建议或更正。 如果您碰巧知道针对此类特定问题的好教程,我会很乐意阅读它,因为我没有找到比 FiPy 文档中的示例更好的东西。

【问题讨论】:

  • 不清楚您要就什么问题寻求建议/更正?如果只是整体代码审查,我建议在codereview.stackexchange.com 发帖。
  • 谢谢,没听说过。把它贴出来可能会更好。
  • 有四个方程,但只有两个变量。变量的数量必须等于方程的数量才能有一个封闭的解决方案。

标签: python pde fipy


【解决方案1】:

几个问题:

  • python chained comparisons 在 numpy 中不起作用,因此在 FiPy 中不起作用。所以,写
    u10 = (4*L/10 < x) & (x < 6*L/10)
    
    此外,这使u10 成为布尔字段,这使 FiPy 感到困惑,所以 写
    u10 = ((4*L/10 < x) & (x < 6*L/10)) * 1.
    
    或者,更好的是,写
    u1 = CellVariable(name="u1", mesh=mesh, value=0., hasOld=True)
    u2 = CellVariable(name="u2", mesh=mesh, value=1., hasOld=True)
    u1.setValue(1., where=(4*L/10 < x) & (x < 6*L/10))
    
  • ConvectionTerm 采用向量系数。一种方法是
    convCoeff = g*(x-L/2) * [[1.]]
    
    表示一维 rank-1 变量
  • 如果您声明 VariableTerm 适用于哪个 Term,则必须为所有 Terms 执行此操作,因此请编写,例如,
    ConvectionTerm(coeff=convCoeff, var=u1)
    
  • ConvectionTerm(coeff=g*x, var=u1) 不代表 g * x * du1/dx。它表示 d(g * x * u1)/dx。所以,我相信你会想要
    ConvectionTerm(coeff=convCoeff, var=u1) - ImplicitSourceTerm(coeff=g, var=u1)
    
  • ImplicitSourceTerm(coeff=sourceCoeff1, var=u1不代表 -1*mu1*u1/(K+u1)*u2,而是代表-1*mu1*u1/(K+u1)*u2*u1。所以,为了方程之间的最佳耦合,写

    sourceCoeff1 = -mu1*u1/(K+u1)
    sourceCoeff2 = mu2*u2/(K+u1)
    
    ... ImplicitSourceTerm(coeff=sourceCoeff1, var=u2) ...
    ... ImplicitSourceTerm(coeff=sourceCoeff2, var=u1) ...
    
  • 正如@wd15 在 cmets 中指出的那样,您正在为两个未知数声明四个方程。 &amp; 并不意味着“将两个方程加在一起”(可以使用 + 完成),而是意味着“同时求解这两个方程”。所以,写

    sourceCoeff1 = mu1*u1/(K+u1)
    sourceCoeff2 = mu2*u2/(K+u1)
    
    eq1 = (TransientTerm(var=u1) 
           == DiffusionTerm(coeff=D1, var=u1) 
           + ConvectionTerm(coeff=convCoeff, var=u1) 
           - ImplicitSourceTerm(coeff=g, var=u1) 
           - ImplicitSourceTerm(coeff=sourceCoeff1, var=u2))
    eq2 = (TransientTerm(var=u2) 
           == DiffusionTerm(coeff=D2, var=u2) 
           + ConvectionTerm(coeff=convCoeff, var=u2) 
           - ImplicitSourceTerm(coeff=g, var=u2) 
           + ImplicitSourceTerm(coeff=sourceCoeff2, var=u1))
    
    eqn = eq1 & eq2
    
  • 必须用hasOld=True 声明CellVariable 才能调用updateOld(),所以
    u1 = CellVariable(name="u1", mesh=mesh, value=u10, hasOld=True)
    u2 = CellVariable(name="u2", mesh=mesh, value=u20, hasOld=True)
    

似乎有效的完整代码是here

【讨论】:

  • 非常感谢您提供完整的答案。我花了很长时间检查,因为我被拖到另一个项目,我才回到这个。在这种情况下如何使用 Fipy 一切都很清楚。谢谢!
  • 我很乐意提供帮助
  • @jeguyer,有没有办法在每个时间步更新变量 u1 和 u2?
  • 和边界条件
  • @IgorMarkelov:我不确定你的意思。 u1 和 u2 是解变量,因此它们在每个时间步都会自动更新。如果您希望在每个时间步强制 u1 或 u2 的某些部分与解决方案不同,您可以使用 .setValue() 执行此操作。时间相关的边界条件在examples/diffusion/mesh1D.py 的大约 1/3 处进行了说明。请打开一个新问题以进一步讨论这些问题。
猜你喜欢
  • 1970-01-01
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-30
  • 1970-01-01
  • 2017-06-22
  • 2012-05-21
相关资源
最近更新 更多