[英]Python Fipy explicit terms with derivatives and variable diffusion constant
我正在嘗試求解四個耦合 PDE(兩個標量密度場和一個矢量場 - 但我以分量方式求解)。
現在,在 Fipy 代碼中(\rho 和矢量分量分別用 m、px 和 py 表示)我將它們寫下來:
mesh = PeriodicGrid2D(dx, dy, nx, ny)
# Variables to use
c = CellVariable(name='c', mesh=mesh, hasOld=1)
m = CellVariable(name='m', mesh=mesh, hasOld=1)
px = CellVariable(name='px', mesh=mesh, hasOld=1)
py = CellVariable(name='py', mesh=mesh, hasOld=1)
x_hat = [1.0, 0.0]
y_hat = [0.0, 1.0]
#-------------------------------------------------------------------------
eq_c = (TransientTerm(var=c) ==
W*(c.grad.dot(x_hat)*m.grad.dot(x_hat) + c.grad.dot(y_hat)*m.grad.dot(y_hat))
- ExponentialConvectionTerm(coeff=x_hat * px*v0 + y_hat * py*v0, var=c)
+ DiffusionTerm(coeff=Da, var=c) + DiffusionTerm(coeff=W*c, var=m) )
eq_m = (TransientTerm(var=m) ==
kb*(c/(c+ch)) - ImplicitSourceTerm(coeff=ku, var=m)
- ExponentialConvectionTerm(coeff=x_hat * px*v0 + y_hat * py*v0, var=m)
+ DiffusionTerm(coeff=Dm, var=m) )
eq_px = (TransientTerm(var=px) ==
DiffusionTerm(coeff=K, var=px) - zeta0*c.grad.dot(x_hat) + zeta*m.grad.dot(x_hat)
+ ImplicitSourceTerm(coeff=((c/cs)-1 -((c/cs)+1)*(px*px+py*py)), var=px) )
eq_py = (TransientTerm(var=py) ==
DiffusionTerm(coeff=K, var=py) - zeta0*c.grad.dot(y_hat) + zeta*m.grad.dot(y_hat)
+ ImplicitSourceTerm(coeff=((c/cs)-1 -((c/cs)+1)*(px*px+py*py)), var=py) )
# Couple them into one big equation
eq = eq_c & eq_m & eq_px & eq_py
c 方程中第二項的 Fipy 實現是否正確? 代碼沒有出現任何錯誤,但我沒有得到預期的結果,應該是本文中描述的紫苑。 但是我得到的解決方案最初顯示為紫苑,但擴散接管了,從長遠來看,我得到了均質的解決方案。 我在這里和這里看到了以前的相關問題,但不完全確定如何使用它們。 在此先感謝並為可憐的數字感到抱歉!
這是一個最小的工作代碼:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
First version with no polarity dynamics, no equation for n-field
"""
from fipy import (CellVariable, PeriodicGrid2D, TransientTerm, DiffusionTerm, ExplicitDiffusionTerm,
UniformNoiseVariable, Variable, FaceVariable, ImplicitSourceTerm, ExponentialConvectionTerm)
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import cm
matplotlib.rcParams.update({'font.size': 16})
import numpy as np
def run_sim(savename,K,zeta):
#------------ parameters -------------
Da=1.0
Dm=1.0
W=-30.0
kb=1.0/4.0
ku=1.0/8.0
ch=1.0/4.0
cs=1.0/64.0
zeta0=1.0
# zeta=1.0
v0=0.1
#-------------- Mesh --------------------
duration=1
dt=0.5
# Define mesh size and number of points
nx = 60
ny = nx
L = 20
dx = L / nx
dy = dx
mesh = PeriodicGrid2D(dx, dy, nx, ny)
xval = mesh.x
yval = mesh.y
# Variables to use
c = CellVariable(name='c', mesh=mesh, hasOld=1)
m = CellVariable(name='m', mesh=mesh, hasOld=1)
px = CellVariable(name='px', mesh=mesh, hasOld=1)
py = CellVariable(name='py', mesh=mesh, hasOld=1)
# Initial condition + some random noise
c.setValue( 0.1*np.exp(-0.25*(mesh.x-L/2)*(mesh.x-L/2)-0.25*(mesh.y-L/2)*(mesh.y-L/2)) )
m.setValue( UniformNoiseVariable(mesh=mesh, minimum=0.4*(kb/ku), maximum=0.5*(kb/ku)) )
px.setValue( UniformNoiseVariable(mesh=mesh, minimum=0.0, maximum=0.1) )
py.setValue( UniformNoiseVariable(mesh=mesh, minimum=0.0, maximum=0.1) )
x_hat = [1.0, 0.0]
y_hat = [0.0, 1.0]
#-------------------------------------------------------------------------
eq_c = (TransientTerm(var=c) ==
W*(c.grad.dot(x_hat)*m.grad.dot(x_hat) + c.grad.dot(y_hat)*m.grad.dot(y_hat))
- ExponentialConvectionTerm(coeff=x_hat * px*v0 + y_hat * py*v0, var=c)
+ DiffusionTerm(coeff=Da, var=c) + DiffusionTerm(coeff=W*c, var=m) )
eq_m = (TransientTerm(var=m) ==
kb*(c/(c+ch)) - ImplicitSourceTerm(coeff=ku, var=m)
- ExponentialConvectionTerm(coeff=x_hat * px*v0 + y_hat * py*v0, var=m)
+ DiffusionTerm(coeff=Dm, var=m) )
eq_px = (TransientTerm(var=px) ==
DiffusionTerm(coeff=K, var=px) - zeta0*c.grad.dot(x_hat) + zeta*m.grad.dot(x_hat)
+ ImplicitSourceTerm(coeff=((c/cs)-1 -((c/cs)+1)*(px*px+py*py)), var=px) )
eq_py = (TransientTerm(var=py) ==
DiffusionTerm(coeff=K, var=py) - zeta0*c.grad.dot(y_hat) + zeta*m.grad.dot(y_hat)
+ ImplicitSourceTerm(coeff=((c/cs)-1 -((c/cs)+1)*(px*px+py*py)), var=py) )
# Couple them into one big equation
eq = eq_c & eq_m & eq_px & eq_py
elapsed = 0.0
while elapsed < duration:
c.updateOld()
m.updateOld()
px.updateOld()
py.updateOld()
elapsed += dt
res = 1e5
old_res = res * 2
step = 0
while res > 1e-5 and step < 15 and old_res / res > 1.01:
old_res = res
res = eq.sweep(dt=dt)
step += 1
if __name__ == '__main__':
"""
comments
"""
path = 'result/'
def name(K, zeta):
return 'K_{:.2f}_zeta_{:.2f}'.format(K, zeta)
Ks = [1]
zetas = [30.0]
for K in Ks:
for zeta in zetas:
run_sim(name(K, zeta), K=K, zeta=zeta)
c 方程中第二項的 Fipy 實現是否正確?
不。術語DiffusionTerm(coeff=W*c, var=m)
表示 . 沒有理由運行鏈式規則來獲取顯式部分; 事實上,這樣做是不可取的。
進一步將方向轉換為 rank-1 CellVariable
會產生更清晰的方程。 FiPy 無法將標量c
和m
與矢量p
耦合,但是px
和py
方程無論如何都沒有耦合。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
First version with no polarity dynamics, no equation for n-field
"""
from fipy import (CellVariable, Grid2D, PeriodicGrid2D, TransientTerm, DiffusionTerm, ExplicitDiffusionTerm,
UniformNoiseVariable, Variable, FaceVariable, ImplicitSourceTerm, ExponentialConvectionTerm, Viewer)
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import cm
matplotlib.rcParams.update({'font.size': 16})
import numpy as np
def run_sim(savename,K,zeta):
#------------ parameters -------------
Da=1.0
Dm=1.0
W=-30.0
kb=1.0/4.0
ku=1.0/8.0
ch=1.0/4.0
cs=1.0/64.0
zeta0=1.0
# zeta=1.0
v0=0.1
#-------------- Mesh --------------------
duration=1
dt=0.05
# Define mesh size and number of points
nx = 60
ny = nx
L = 20
dx = L / nx
dy = dx
mesh = Grid2D(dx, dy, nx, ny)
xval = mesh.x
yval = mesh.y
# Variables to use
c = CellVariable(name='c', mesh=mesh, hasOld=1)
m = CellVariable(name='m', mesh=mesh, hasOld=1)
p = CellVariable(name='p', mesh=mesh, rank=1, hasOld=True)
# Initial condition + some random noise
c.setValue( 0.1*np.exp(-0.25*(mesh.x-L/2)*(mesh.x-L/2)-0.25*(mesh.y-L/2)*(mesh.y-L/2)) )
m.setValue( UniformNoiseVariable(mesh=mesh, minimum=0.4*(kb/ku), maximum=0.5*(kb/ku)) )
p[0] = UniformNoiseVariable(mesh=mesh, minimum=0.0, maximum=0.1)
p[1] = UniformNoiseVariable(mesh=mesh, minimum=0.0, maximum=0.1)
x_hat = [1.0, 0.0]
y_hat = [0.0, 1.0]
#-------------------------------------------------------------------------
eq_c = (TransientTerm(var=c) ==
- ExponentialConvectionTerm(coeff=p*v0, var=c)
+ DiffusionTerm(coeff=Da, var=c) + DiffusionTerm(coeff=W*c, var=m) )
eq_m = (TransientTerm(var=m) ==
ImplicitSourceTerm(coeff=kb/(c+ch), var=c) - ImplicitSourceTerm(coeff=ku, var=m)
- ExponentialConvectionTerm(coeff=p*v0, var=m)
+ DiffusionTerm(coeff=Dm, var=m) )
eq_p = (TransientTerm(var=p) ==
DiffusionTerm(coeff=[[[K, 0],
[0, K]]], var=p) - zeta0*c.grad + zeta*m.grad
+ ImplicitSourceTerm(coeff=((c/cs)-1 -((c/cs)+1)*p.mag**2), var=p) )
# Couple them into one big equation
eq = eq_c & eq_m
elapsed = 0.0
viewer = Viewer(vars=c)
viewer.plot()
while elapsed < duration:
c.updateOld()
m.updateOld()
p.updateOld()
elapsed += dt
res = 1e5
old_res = res * 2
step = 0
while res > 1e-5 and step < 15 and old_res / res > 1.01:
old_res = res
res = eq.sweep(dt=dt)
eq_p.sweep(dt=dt)
step += 1
viewer.plot()
if __name__ == '__main__':
"""
comments
"""
path = 'result/'
def name(K, zeta):
return 'K_{:.2f}_zeta_{:.2f}'.format(K, zeta)
Ks = [1]
zetas = [30.0]
for K in Ks:
for zeta in zetas:
run_sim(name(K, zeta), K=K, zeta=zeta)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.