[petsc-users] How to set boundary conditions for a structured finite volume (FV) discretization when using TS/SNES?
Mark Adams
mfadams at lbl.gov
Sun Nov 28 08:17:41 CST 2021
* I have used Matt's approach and it works but you do have to remember to
update the ghost cells after you update your solution and before you
use the operator again.
* I would use a convergence test to determine if the result is correct.
* Check that a constant function is a (trivial) solution to your
discretization.
On Sat, Nov 27, 2021 at 2:54 AM zhfreewill <zhfreewill at gmail.com> wrote:
> Hi,Barry,
> Thanks for reply. I meant I cannot get the right result as the FD version
> did, although the code did not report any error when running.
>
> Indeed, there were mistakes and I fixed it in the code (I also attached
> additional derivation and code this time, please see the attachment).
> Still, I cannot get the right output so far.
>
> Regards,
> Qw
>
> Barry Smith <bsmith at petsc.dev> 于2021年11月26日周五 下午11:31写道:
>
>>
>> Could you be more specific in saying how it fails (can you share the
>> actual prototype code?)
>>
>> Note here you seem to be missing a /dx term
>>
>> *G[i] = (u[i+1] - u[i]) - q_A; **//Neumann BC: du/dx(x=0.0)
>> = q_A;*
>>
>>
>> Barry
>>
>> On Nov 26, 2021, at 4:02 AM, zhfreewill <zhfreewill at gmail.com> wrote:
>>
>> Hi all,
>> I have a basic question on how to apply B.C. for a cell-centered
>> structured FV discretization when using the SNES and Ts object.
>> For instance, for a 1-D transient diffusion equation
>>
>> *u_t = u_xx, 0 < x < 1*
>>
>> with IC:
>>
>> *u(x,t=0) = 0;*
>>
>> and Dirichlet BC:
>>
>> *u(x=0) = u_A = 0.0;*
>> *u(x=1) = u_B = 1.0;*
>>
>> or Neumann BC:
>>
>> *du/dx(x=0.0) = q_A = 0.0;*
>> *du/dx(x=1.0) = q_B = 1.0;*
>>
>>
>> When using TS of PETSc, the equation can be organized in form of
>> *U_t = G(t,u)*
>> where *G* is the right-hand-side (RHS) function regardless of the
>> specific method of discretization.
>> *(1) For FD discretization*
>>
>> *A |---dx--| B*
>> *|-------|-------|-------|-------|-------| grid size = nx*
>> *0 i-1 i i+1 nx-1*
>>
>> the vertex-centered FD discretization of the domain is
>>
>> *x(i) = i*dx (i = 0,..., nx)), where dx = 1/nx*
>>
>> and the RHS function G of the equation is
>>
>> *G[i] = (u[i+1]-2*u[i]+u[i-1])/dx^2*
>>
>> There have been dozens of examples demonstrating way of BC setting with a
>> finite difference medthod, e.g.,
>>
>> https://github.com/petsc/petsc/blob/386ebab930a846575609b49074a40c46e7f8ed75/src/ts/tutorials/ex26.c#L293-L343
>> which I think I have understood how it works and the following lines of
>> code evaluate the RHS function *G(t,u)* in PETSc's *TSSetRHSFunction()*
>> routine
>> /*------------------FD discretization-------------------------*/
>> *for (i = xs; i < xs + xm; i++) {*
>>
>> *// left boundary*
>> *if (i == 0) {*
>>
>> *G[i] = u[i] - u_A; **// Dirichlet BC: u(x=0) = u_A;*
>> *G[i] = (u[i] - u[i+1])/dx - q_A; **// Neumann BC: du/dx(x=0.0) =
>> q_A;*
>>
>> *} *
>> *// right boundary*
>> *else if (i == mx - 1) {*
>>
>> *G[i] = u[i] - u_B; **// Dirichlet BC: u(x=1.0) = u_B;*
>> *G[i] = (u[i]-u[i-1])/dx - q_B; **// Neumann BC: du/dx(x=0.0) =
>> q_A;*
>>
>> *}*
>> *// internal*
>> *else {*
>>
>> *G[i] = (u[i-1] - 2 * u[i] + u[i + 1])/dx^2; **//u_xx*
>>
>> *}*
>>
>> *}**/*------------------------------------------------------------*/*
>>
>> The BCs, e.g., at the left boudnary, can be straightforwardly set as
>> follows:
>> Dirichlet BC:
>> *G[0] = u[0] - u_A*
>> which indicates *G[0] = u[0] - u_A = 0* and Dirichlet BC *u[0] = u_A* is
>> thus applied
>> Neumann BC:
>> *G[0] = (u[0] - u[1])/dx - q_A*
>> which indicates *G[0] = (u[0] - u[1])/dx - q_A = 0* and Neumann BC *du/dx
>> = (u[0] - u[1])/dx = q_A* is applied
>> This is the way the above examples apply BCs.
>>
>> For a structured, cell-centered FVM discretization, however, I tried and
>> found the BCs can not be applied in a similar way. I will explain how I
>> tried this as follows.
>> *(2) FV discretization*
>>
>> *A |---dx--| B*
>> *|---o---|---o---|---o---|---o---|---o---| cell size = nx*
>> *W w P e E *
>> *0 i-1 i i+1 nx-1*
>>
>> (NOTE: the center cell is denoted as P and its neighbouring cells as W,
>> E; cell faces are denoted as w, e; the left and right boundary faces are
>> A and B, respectively.)
>>
>> The cell-centered FV discretization of the domain is
>>
>> *x(i) = dx/2 + i*dx (i = 0,..., nx-1)), where dx = 1/nx*
>>
>> the diffusion term u_xx can be reorganized by using divergence theorem
>>
>> *(u_E-u_P) (u_P-u_W)*
>> *--------- - ---------*
>> * dx dx*
>>
>> and the RHS function G of the equation is
>>
>> *G[i] = (u_E-u_P)/dx - (u_P-u_W)/dx = (u[i+1]-2*u[i]+u[i-1])/dx*
>>
>> the key lines of code in RHS function G(t,u) in PETSc's
>> *TSSetRHSFunction()* routine can be
>>
>> */*------------------FV discretization-------------------------*/*
>> *for (i = xs; i < xs + xm; i++) {*
>>
>> *// left boundary*
>> *if (i == 0) {*
>>
>> *G[i] = 3.0 * u[i] - u[i+1] - 2.0 * u_A; **//Dirichlet BC: u(x=0.0) =
>> u_A, does not work*
>> *G[i] = (u[i+1] - u[i]) - q_A; **//Neumann BC: du/dx(x=0.0)
>> = q_A;*
>>
>> *}*
>> *// right boundary*
>> *else if (i == mx - 1) {*
>>
>> *G[i] = 3.0 * u[i] - u[i-1] - 2.0 * u_B; **//Dirichlet BC: u(x=1.0) =
>> u_B, does not work*
>> *G[i] = (u[i]-u[i-1])/dx - q_B; **//Neumann BC: du/dx(x=1.0)
>> = q_B, does not work*
>>
>> *}*
>> *// internal*
>> *else {*
>>
>> *G[i] = (u[i-1] - 2*u[i] + u[i+1])/dx; **//u_x*
>>
>> *}*
>>
>> *}**/*------------------------------------------------------------*/*
>>
>> I tried to apply BCs in a way similar to that of the FD discretization.
>> For the Dirichlet BC on the left boundary, because of the cell-centered
>> arrangement of u[i], the left BC is given as *u_A* at cell face A
>> instead of cell center.
>> So, I first applied a linear interpolation to get the cell-centered value
>> of *u[0]* from the left boundary value *u_A* and neighbouring *u[1]*
>>
>> *u[0] = (u[1]+2*u_A)/3.0 (equivalent to 3*u[0] - u[1] - 2*u_A = 0.0)*
>>
>> * |-dx/2-|------dx-----|*
>> * |------o------|------o------| linear interpolation: u[0] =
>> (u[1]+2*u_A)/3.0*
>> * A P e E*
>> * u_A u[0] u[1]*
>>
>> Dirichlet BC:
>> *G[0] = 3.0*u[0] - u[1] - 2.0*u_A*
>> in which *u[0] = (u[1]+2*u_A)/3.0* is implicitly calculated and I
>> expect the Dirichlet BC *u(x=0) = u_A* is applied
>>
>> For the Neumann BC, left BC is given as a gradient of *u*, *q_A*, at
>> cell face A
>> Neumann BC:
>> *G[i] = (u[1] - u[0])/dx - q_A*
>> in which Neumann BC *du/dx = (u[1] - u[0])/dx = q_A* is expected to
>> be applied.
>>
>> However, this FV discretization failed to work. Is there anything wrong
>> or could you give me a hint?
>>
>> Best,
>> Qw
>>
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/petsc-users/attachments/20211128/d1a11154/attachment-0001.html>
More information about the petsc-users
mailing list