簡體   English   中英

Python 具有導數和可變擴散常數的 Fipy 顯式項

[英]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)表示\nabla \cdot \left(W c \nabla \rho \right) . 沒有理由運行鏈式規則來獲取顯式部分; 事實上,這樣做是不可取的。

進一步將方向轉換為 rank-1 CellVariable會產生更清晰的方程。 FiPy 無法將標量cm與矢量p耦合,但是pxpy方程無論如何都沒有耦合。

#!/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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM