Two questions about the Legendre-Galerkin method for the Cahn-Hilliard equation
liqihao2000 opened this issue · comments
Dear Mikael,
For the Allen-Cahn equation with homogeneous Neumann and periodic boundary conditions, I implement the code with Legendre and Fourier Galerkin method. Now, I have two questions about the Legendre-Galerkin method for the Cahn-Hilliard equation:
- In the case of the Fourier-Galerkin for the periodic boundary condition, the code with shenfun has been implemented. But I do not know how to implement the Legendre-Galerkin method for the Cahn-Hilliard equation in the case of the homogeneous Neumann boundary condition.
- How to impose boundary conditions in shenfun so that the Cahn-Hilliard equation can be solved in the following two weak forms?
Cahn-Hilliard equation
The Cahn-Hilliard equation is a parabolic equation and is typically used to model phase separation in binary mixtures. It involves first-order time derivatives, and second- and fourth-order spatial derivatives. The equation reads:
with initial data
where
1. Direct solver
Time discretisation
where
Weak formulation
2. Mixed solver
Mixed form
A solution is to rephrase the problem as two coupled second-order equations:
Time discretisation
where
Weak formulation
Demo parameters
The following domains, functions and time stepping parameters are used in this demo:
$\Omega = (0, 2) \times (0, 1),$ $F(\phi) = \frac{1}{4}(\phi^2-1)^2,$ $f(\phi) = \frac{d F}{d \phi} = \phi^3-\phi,$ $\epsilon = 1 \times 10^{-2},$ $M = 1 \times 10^{-2},$ $dt = 0.001,$ $S = 3,$ $[0, T] = [0, 5],$ $\phi^0({x}) = \cos(2 \pi x) + 0.001 \cos(16\pi x).$
Hi
Looking at your problem you seem to need a biharmonic basis with only Neumann boundary conditions. You can create such a space with
from shenfun import *
N = 10
D = FunctionSpace(N, 'L', bc={'left': {'N': 0, 'N3': 0}, 'right': {'N': 0, 'N3': 0}} )
The space has not been precomputed, so it will take some time to find the correct stencil. You should probably implement the space with hardcoded stencil, like this:
from shenfun.legendre.bases import CompositeBase
class MyBiharmonic(CompositeBase):
def __init__(self, N, quad="LG", bc=(0,)*8, domain=(-1, 1), dtype=float,
padding_factor=1, dealias_direct=False, coordinates=None, **kw):
CompositeBase.__init__(self, N, quad=quad, domain=domain, dtype=dtype, bc=bc,
padding_factor=padding_factor, dealias_direct=dealias_direct,
coordinates=coordinates)
from shenfun.utilities import n
self._stencil = {
0: 1,
2: -2*n*(2*n**2 + 7*n + 5)/(2*n**3 + 21*n**2 + 67*n + 63),
4: n*(2*n**4 + 11*n**3 + 16*n**2 + 4*n - 3)/(2*n**5 + 39*n**4 + 296*n**3 + 1086*n**2 + 1907*n + 1260)
}
@staticmethod
def boundary_condition():
return 'Biharmonic N1N3'
@staticmethod
def short_name():
return 'B3'
and then use it instead of the FunctionSpace, like
N = 10
D = MyBiharmonic(N, bc={'left': {'N': 0, 'N3': dfdx}, 'right': {'N': 0, 'N3': dfdx}})
where dfdx
is the nonhomogeneous function you want to use for the boundary condition. Not quite sure how this should be, but you can compute dfdx
from the Function
phi
.
Regarding the time discretization I recommend using the IMEX integrators in utilities.integrators (IMEXRK222, IMEXRK3, IMEXRK443). In ChannelFlow2D I solve a time-dependent biharmonic equation this way. Please have a look and see if you can copy this approach.
Hope this helps. I have never tried this basis before, and you may run into some unanticipated trouble. In that case, please let me know:-)