сохранение значения ImplicitSourceTerm

Я работаю с fipy и хочу смоделировать поток со свободным потоком BC на некоторых выбранных гранях. После other examples, я пробовал 2 разные техники:

from fipy import *
from fipy.meshes.nonUniformGrid1D import NonUniformGrid1D as Grid1D
from fipy.tools import numerix as np

dx = [1.,  1. , 0.78584047] 
coeff = 2.
dt = min(0.1, 0.9 * min(dx) ** 2 / (2 * coeff))
steps = 10

mesh = Grid1D(nx = len(dx), dx = dx)

#phi values 
phi = CellVariable(mesh = mesh, value=[10., 0., 0.], hasOld = True)
phi.constrain(0., mesh.facesRight) #dirichlet BC
phi2 = CellVariable(mesh = mesh, value=[10., 0., 0.], hasOld = True)
phi2.constrain(0., mesh.facesRight) #dirichlet BC

#outflow value
phi2Out = CellVariable(mesh = mesh, value=[0., 0., 0.], hasOld = True)

intCoef = FaceVariable(mesh, value=coeff)
extCoef = FaceVariable(mesh, value=coeff)
intCoef.constrain(0., where = mesh.facesRight)
extCoef.constrain(0., where = ~mesh.facesRight)

eq1= TransientTerm() == DiffusionTerm(coeff= intCoef * phi.faceValue) \
  + ImplicitSourceTerm(coeff= (extCoef * phi.faceGrad).divergence)
  
eq2 =TransientTerm() == DiffusionTerm(coeff= intCoef * phi2.faceValue) \
  + phi2 * (extCoef * phi2.faceGrad).divergence
  
eq3 =TransientTerm() == - phi2 * (extCoef * phi2.faceGrad).divergence

phi.updateOld()
phi2.updateOld()
phi2Out.updateOld()
    
for _ in range(steps):
    res =  1e+10
    loop = 0
    while res > 1e-4 and loop < 1000:
        res =  eq1.sweep(var= phi,dt= dt)
        res2 =  eq2.sweep(var=phi2 ,dt= dt)
        res3 =  eq3.sweep(var=phi2Out ,dt= dt)
        res = max(res, res2, res3)
        loop += 1
    if res > 1e-4:
        print('no convergence! res: ', res)
        break
        
    phi.updateOld()
    phi2.updateOld()
    phi2Out.updateOld()
    
    print('\nphi: ', phi * mesh.cellVolumes, sum(phi* mesh.cellVolumes))
    print('phi2: ', phi2* mesh.cellVolumes,sum(phi2* mesh.cellVolumes))
    print('phi2_outFlow: ', phi2Out* mesh.cellVolumes, sum(phi2Out* mesh.cellVolumes))
    print('phi2_total: ', sum(phi2* mesh.cellVolumes + phi2Out* mesh.cellVolumes))

Вывод после 10 шагов:

фи: [2,21786728 1,82700906 0,63381385] 4,678690190704105

phi2: [2,21786872 1,82701185 0,6338187] 4,678699267591382

phi2_outFlow: [0. 0. 5,32132192] 5,321321918864122

phi2_total: 10.000021186455504

В идеале я хотел бы извлечь значение оттока, чтобы проверить баланс масс и узнать точное значение каждого члена для каждой ячейки (другие термины приемник / источник будут добавлены позже, а также другие границы свободного потока).

Мои вопросы:

  1. почему значения phi и phi2 немного отличаются?
  2. как я могу извлечь член оттока для каждой ячейки (когда будет использоваться более сложная сетка), сохранив при этом «ImplicitSourceTerm», что более эффективно?

Спасибо за помощь!

PS: До сих пор я работал с python3, поэтому, хотя меня интересуют решения с участием других решателей, я особенно ищу что-то, что можно реализовать с помощью scipy.


person rbtlm640    schedule 08.04.2021    source источник


Ответы (1)


  1. почему значения phi и phi2 немного отличаются?

phi и phi2 разные, потому что eq2 не сходится так быстро, как eq1. Это потому, что eq1 более неявно, чем eq2. Если вы измените допуск для остатка, например, res > 1e-10, вы увидите, что два решения находятся в гораздо более близком соответствии.

  1. как я могу извлечь член оттока для каждой ячейки (когда будет использоваться более сложная сетка), сохранив при этом «ImplicitSourceTerm», что более эффективно?

Вы все еще можете оценить поток phi2 * extCoef * phi2.faceGrad, даже если используете ImplicitSourceTerm.

В общем, нелегко извлечь, что каждый Term делает физически (см. Проблему # 461). Чтобы узнать, как каждый Term вносит свой вклад в матрицу решения, но это может дать вам физическую интуицию, а может и не дать вам большого представления о том, что происходит.

person jeguyer    schedule 08.04.2021