General boundary conditions

烂漫一生 提交于 2019-12-12 04:23:39

问题


I’d appreciate help on setting general boundary conditions, -grad(y) + g(y) = 0 where g is some function of the unknown y. Here’s a simple 1D example that I can’t get to work:

N=3
h=1./(float(N)-1.)

mesh = Grid1D(nx=N, dx=h)

c=CellVariable(mesh=mesh,value=0.5)

## Dirichlet boundary conditions
#c.constrain(2., mesh.facesLeft)
#c.constrain(1., mesh.facesRight)

## Neumann boundary conditions
c.faceGrad.constrain(-1, where=mesh.facesLeft)
c.faceGrad.constrain( -c.faceValue , where=mesh.facesRight)

Eq = DiffusionTerm(coeff=1.0)
Eq.cacheMatrix()
Eq.cacheRHSvector()
Eq.solve(var=c)
m = Eq.matrix.numpyArray
b = Eq.RHSvector

This code won’t solve but I do get to see the matrix and RHS:

m= array([[-2.,  2.,  0.],
          [ 2., -4.,  2.],
          [ 0.,  2., -2.]])

b= array([-1. ,  0. ,  0.5])

The matrix, m, is clearly singular because the source term was not included in the last line. Any suggestions on how to include it?


回答1:


[edit: add derivation and demonstration of 1st order implementation]

There are known issues with general boundary conditions.

It is possible to implement such a boundary condition as a source. Using the discretization of the DiffusionTerm $\sum_f D_f (n\cdot\nabla(y))_f A_f$ we treat $f=R$ as a special case and substitute of the desired boundary condition -n\cdot\nabla(y) - y = 0. We accomplish this by zeroing D_(f=R) in the DiffusionTerm

c.faceGrad.constrain([-1], where=mesh.facesLeft)

D = 1.
Dface = FaceVariable(mesh=mesh, value=D)
Dface.setValue(0., where=mesh.facesRight)

and then adding an implicit source D_(f=R) (n\cdot\nabla(y))_(f=R) A_(f=R) or D_(f=R) (-y)_(f=R) A_(f=R). Sources are defined at cell centers, so we locate the cell adjacent to $f=R$

mask_coeff = (mesh.facesRight * mesh.faceNormals).divergence

and then add the source

Af = mesh._faceAreas[mesh.facesRight.value][0]
Eq = DiffusionTerm(coeff=Dface) - ImplicitSourceTerm(coeff=mask_coeff * D * Af)

This treatment is only 0th order accurate as the ImplicitSourceTerm operates on the value at the cell center, whereas the boundary condition is defined at the adjacent face center.

We can make the boundary condition 1st order accurate in space by projecting the cell value to the face along the gradient from the boundary condition: y_(f=R) ~ y_P + n\cdot\nabla(y)_(f=R) dPR where y_P is the value of y at the cell center closest to f=R and dPR is the distance from point P to face R.

Thus the boundary condition -n\cdot\nabla(y)_(f=R) - y_(f=R) = 0 becomes -n\cdot\nabla(y)_(f=R) - (y_P + n\cdot\nabla(y)_(f=R) dPR) = 0, which we can solve for n\cdot\nabla(y)_(f=R) = -y_P / (1 + dPR). The implicit source corresponding to the boundary for the DiffusionTerm is thus D_(f=R) (-y_P / (1 + dPR)) A_(f=R)

dPR = mesh._cellDistances[mesh.facesRight.value][0]
Af = mesh._faceAreas[mesh.facesRight.value][0]
Eq = DiffusionTerm(coeff=Dface) - ImplicitSourceTerm(coeff=mask_coeff * D * Af / (1 + dPR))

This was discussed last summer on the FiPy mailing list, starting at https://www.mail-archive.com/fipy@nist.gov/msg03671.html. Yes, it's all pretty clumsy right now.



来源:https://stackoverflow.com/questions/42769749/general-boundary-conditions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!