Hi Dan,

Thank you for the clarifications. Indeed they were quite helpful in getting a 
more concrete understanding of the issues

"I'm confused by your question. Backward Euler refers to the time stepping 
scheme, which is indeed first order. The spatial discretization scheme is 
second order and using the boundary condition trick that I demonstrated is 
second order and also implicit."

** yes. What I am conveying is that, the spatial equation   phi_at_boundary = 
phi_at_lastcell + (gradient/flux at boundary)*(distance between the boundary 
and last cell-node),  is  analogous to   future_value = present_value + (slope 
at future value * delta_t),  a Backward Euler step in the time-domain.

 n.grad(phi) = k * phi_at_boundary  = k * (phi_at_lastcell + (gradient/flux at 
boundary)*(distance between the boundary and last cell-node)),  might be a 
first order approximation ?   Again, I am unsure of this claim. At a very first 
glance, I thought the derivation was similar/analgous  to Backward Euler


Well, now getting into real issue/question. I am trying to extend this concept 
on a pseudo-2D domain.   Let me explain.

1.      The diffusion process happens only along the y-axis, ie. we have 
anisotropic diffusion.
2.      The same implicit Neumann BC applies for each x co-ordinate,   i.e. we 
have d_phi/dy along top surface  = - k * phi at the top surface

My code is shown below.

I think that your derivation also holds  good in this pseudo-2D diffusion case. 
 With that sorted out,
1.       I substituted the 2D equivalent constructions  instead of their 1D 
counterparts
2.      For this demo case,  I chose a 2x2 grid, with just nx=2 and ny=2 and 
unit spacing in each direction
3.      Defined the diffusion coefficient as a rank 2 faceVariable, and set its 
value to a suitable tensor, such as to restrict movement in 2D direction.
4.      Constrain the diffusion coefficient along the top boundary to be zero. 
This boundary is where the special implicit Neumann BC applies
5.      Calculate the implicitCoeff  with the same formula/code   (since the 
derivation is the same)
6.      Define the source term coefficient  as (mesh.faceNormals * 
implicitCoeff * mesh.facesTop).divergence)


Now, my problem is the following.  Although the simulation seems to yield a 
plausible-looking viewer animation, showing diffusion along y-axis,   the 
mesh.faceNormals * implicitCoeff * mesh.facesTop).divergence   return a  
'AddoverFaceVariable' object of a much reduced dimension.  The mesh.faceNormals 
* implicitCoeff * mesh.facesTop  correctly returns the expected vectors of size 
12    (for this 2x2 problem, with unit spacing, there are 12 faceCenters). It 
correctly sets only the top face to the implicit coefficient.    But the 
moment, the divergence operator is called upon,  the size of the returned 
'AddoverFaceVariable' object drops to 4, with the last 2 values being set to 
the ImplicitCoeff.   Also, it just becomes a 1D vector, with first two elements 
being zero.  Shouldn't this ImplicitSourceTerm coefficient  remain as a 2D 
matrix ?

The code runs, but I am worried if I am correctly implementing the boundary 
condition. Is there any (recommended/standard) way to validate my solution ? I 
don't have the analytical solution.

import fipy as fp

nx = 2
ny = nx
dx = 1.
dy = dx
mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)

phi = fp.CellVariable(name = "Field Variable",mesh = mesh)
valueBottom = 1.
phi.constrain(valueBottom, mesh.facesBottom)

D = 1.0
diffCoeff = fp.FaceVariable(mesh=mesh, rank=2, value=[[[0,0],[0,D]]])
diffCoeff.constrain(0., mesh.facesTop)

k = -1.0  # We are modelling the BC (d_phi/dx = k*phi) at the top surface
implicitCoeff = D*k / (1. - k*dx/2.)  # in order to model implicit BC

# print (mesh.faceNormals * implicitCoeff * mesh.facesTop).divergence
eq = (fp.TransientTerm() == fp.DiffusionTerm(diffCoeff)
      + fp.ImplicitSourceTerm((mesh.faceNormals * implicitCoeff * 
mesh.facesTop).divergence))

viewer = fp.Viewer(vars=phi, datamin=0., datamax=1.)
viewer.plot()

############Transient Simulation ################################
timeStep = 0.9 * dx**2 / (2 * D)
steps = 75
for step in range(steps):
    eq.solve(var=phi, dt=timeStep)
    viewer.plot()


Krishna

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Daniel 
Wheeler
Sent: 13 June 2016 03:17
To: Multiple recipients of list <[email protected]>
Subject: Re: casting implicit Boundary Conditions in FiPy

On Sun, Jun 12, 2016 at 8:14 AM, Gopalakrishnan, Krishnakumar 
<[email protected]<mailto:[email protected]>> 
wrote:
>
> 1.   The backward Euler method is used in formulating the equation,
> "n.grad(phi) = k * (phi_P + n.grad(phi) * dx / 2) " .  But  Backward Euler
> is a first order method, isn't it ?   I am a bit confused about the second
> order accuracy statement.

I'm confused by your question. Backward Euler refers to the time stepping 
scheme, which is indeed first order. The spatial discretization scheme is 
second order and using the boundary condition trick that I demonstrated is 
second order and also implicit.

> 2.  In,  the equation,  "eq = (fp.TransientTerm() ==
> fp.DiffusionTerm(diffCoeff) - \
>
>       fp.ImplicitSourceTerm((mesh.faceNormals * implicitCoeff *
> mesh.facesRight).divergence)) "  ,
>
>  from what I understand the 'ImplicitCoeff' is zeroed out in all other
> locations other than the right boundary by the boolean method
> 'mesh.facesRight' , right ?

Exactly, mesh.facesRight is just evaluates to a boolean array. There is also 
mesh.exteriorFaces which gets you all exterior faces and then you can also do 
logical operations based on physical location to get more specific masks to 
capture boundaries or internal regions.

> If this is being implemented, do we have the restriction to use fixed dx ?

I guess not if you're careful, but it could be a bit fiddly getting the correct 
distance.

> Although dx  appears in the Implicit term, it can just be set to the
> value of  'dx' of the last node (i.e. length of the last segment in a
> variable-mesh sized 1D geometry file).    Am I missing something here ?

No, but you need to know how to get the correct distance. There are arrays of 
cell to face distances, but I'd have to think about how to get that working 
right.

> 3.  Also, I am a bit confused about the negative signs used in the  equation
> above.    The implicitCoeff is given a negative sign, and the equation's
> ImplicitSourceTerm is also given a negative sign.     From what I undertand,
> this is what we intend to  do ?

I was just flipping signs to make it work so I'm not sure. Maybe it would be 
better to have them both positive and it would make more sense that way.

> Assign the diffusion coefficient D throughout the domain, using the
> faceVariable method.
> Manually set it to zero at the right boundary Then **add** the
> Diffusion achieved by the div.(D grad( phi))  by using the
> ImplicitSourceTerm method, and ensure that this effect gets added only
> at the right boundary.

You got it.

> If this is the workflow,  then perhaps we just have to declare the
> ImplicitSourceTerm to be positive, and use the addition sign instead
> of subtraction sign  for the implicitSourceTerm in the equation ?

Yup, I think so.

> 5.  Taking one massive step to get to the answer.   Here is a big question
> (due to my poor knowledge in the subject)
>
> I understand that the implicitness enables us to take these large time-steps
> due to the affine and A-stable properties of Implicit Methods.    But are we
> required to do this ?

Oh no. You can still take as small a time step as necessary to capture the 
dynamics at the time scale of interest. It's just that you're not limited by 
the horrible dx**2 / D time step limit associated with explicit diffusion. 
Typically it's best to resolve to some dx based time scale (rather than dx**2) 
that captures an interface being tracked or some feature of interest moving 
around.

>    My problem is that, I am solving a coupled system of PDEs and my
> other equations, require me to step very very slowly, due to the
> inherent stiffness of my system.  The PDEs describe processes of varying
> time-constants.      So,  does taking the timestep to be small inhibit  us
> in any way ?

The only down side to small time steps is that their small :-)

> Once again, thanks a lot for your solution.  Based on the discusssions with
> Ray and  from this particular method from your posting to the list,   I
> think I shall be able to solve the problem in 1D.   The issues you pointed
> out about using this approach in 2D went right over my head.  I have
> to think about this, when I implement them perhaps in a week or so.

Good luck with it.

--
Daniel Wheeler
_______________________________________________
fipy mailing list
[email protected]<mailto:[email protected]>
http://www.ctcms.nist.gov/fipy
  [ NIST internal ONLY: https://email.nist.gov/mailman/listinfo/fipy ]

_______________________________________________
fipy mailing list
[email protected]
http://www.ctcms.nist.gov/fipy
  [ NIST internal ONLY: https://email.nist.gov/mailman/listinfo/fipy ]

Reply via email to