firedrakeproject / firedrake

Firedrake is an automated system for the portable solution of partial differential equations using the finite element method (FEM)
https://firedrakeproject.org
Other
498 stars 157 forks source link

Mixed Function Space Problem #2389

Closed zhyxue0 closed 2 years ago

zhyxue0 commented 2 years ago

​I try to solve the heat equation

with periodic boundary conditions . The exact solution is

​ Local Discontinuous Galerkin(LDG) method is used for spatial discretization, we first introduce an auxiliary vector-valued variable

then find , s.t.

where the flux is

​ Two-stage, second-order DIRK method is used for time discretization, to discretise we set

where

I follow the example of Mixed formulation for the Poisson , but there are some problems. Here is my code:

from firedrake import *
import math

Nx = 10; Ny = 10; 
Pk = 1
CFL = 0.1

Lx = 2*math.pi; Ly = 2*math.pi
Hx = Lx/Nx
mesh = PeriodicRectangleMesh(Nx, Ny, Lx, Ly, direction='both',quadrilateral=False, reorder=None, diagonal="right")
x, y = SpatialCoordinate(mesh)
n = FacetNormal(mesh)

V = FunctionSpace(mesh, "DG", Pk)
Simga = VectorFunctionSpace(mesh, "DG", Pk)
W = V * Simga

T = 0.001
dt = CFL * Hx
dtc = Constant(dt)

u_init = Function(V).interpolate(sin(x) * sin(y))
u = Function(W.sub(0))
u.assign(u_init)

# coefficients of SDIRK 
alpha = 1.0 - math.sqrt(2.0)/2.0
RK_a = Constant(alpha); RK_a21 = Constant(1.0 - alpha)
RK_b1 = Constant(1.0 - alpha); RK_b2 = Constant(alpha)

u_trial, p_trial = TrialFunctions(W)
v, w = TestFunctions(W)

LHS = u_trial * v *dx \
    - dtc*RK_a * ( -dot(p_trial,grad(v))*dx +  dot(p_trial('+'),jump( v,n))*dS ) \
    + dot(p_trial,w)*dx \
    - (-u_trial*div(w)*dx + u_trial('-')*jump(w,n)*dS)  
A = assemble(LHS)                                                                           
M = assemble( u_trial*v *dx)

p1 = Function(W.sub(1))
p2 = Function(W.sub(1))

L1 = u*v *dx
L2 =  u*v *dx + dtc * RK_a21 *(-dot(p1,grad(v))*dx +  dot( p1('+'),jump(v,n) )*dS)          
L = dtc * (RK_b1 * (-dot(p1,grad(v))*dx +  dot( p1('+'), jump(v,n) )*dS) \
        + RK_b2 * (-dot(p2,grad(v))*dx +  dot( p2('+'), jump(v,n) )*dS) )                  

w_solution = Function(W)

b = assemble(L1)
solve(A, w_solution, b)
p1.assign(w_solution.sub(1))

b = assemble(L2)
solve(A, w_solution, b)
p2.assign(w_solution.sub(1))

b = assemble(L)
solve(M, w_solution, b)
u.assign(u + w_solution.sub(0))

u_exact = pow(e, -2*T) * sin(x) * sin(y)
L2_error = norms.errornorm( u_exact, u, norm_type = "L2")

print("Nx = ",Nx ,", L2_error = ", L2_error)

Error:

Traceback (most recent call last):
  File "/home/mycode/Code/firedrake_code/Heat_LDG.py", line 71, in <module>
    solve(M, w_solution, b)
  File "PETSc/Log.pyx", line 115, in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
  File "PETSc/Log.pyx", line 116, in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
  File "/home/mycode/firedrake/src/firedrake/firedrake/adjoint/solving.py", line 53, in wrapper
    output = solve(*args, **kwargs)
  File "/home/mycode/firedrake/src/firedrake/firedrake/solving.py", line 133, in solve
    return _la_solve(*args, **kwargs)
  File "/home/mycode/firedrake/src/firedrake/firedrake/solving.py", line 244, in _la_solve
    solver.solve(x, b)
  File "PETSc/Log.pyx", line 115, in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
  File "PETSc/Log.pyx", line 116, in petsc4py.PETSc.Log.EventDecorator.decorator.wrapped_func
  File "/home/mycode/firedrake/src/firedrake/firedrake/linear_solver.py", line 162, in solve
    raise ConvergenceError("LinearSolver failed to converge after %d iterations with reason: %s", self.ksp.getIterationNumber(), solving_utils.KSPReasons[r])
firedrake.exceptions.ConvergenceError: ('LinearSolver failed to converge after %d iterations with reason: %s', 0, 'DIVERGED_PCSETUP_FAILED')
zhyxue0 commented 2 years ago

I probably know why, the last term

written in matrix form is .

But when written as a mixed function space, we get

the matrix is singular.

But how to deal with it?

wence- commented 2 years ago

I think you figured out a solution, do you mind mentioning it so that anyone hitting the same kind of problem can benefit from the result?

zhyxue0 commented 2 years ago

I think you figured out a solution, do you mind mentioning it so that anyone hitting the same kind of problem can benefit from the result?

OK, inspired by ksagiyam in issue #2399 , define a new trial function u_trial_V and test function v_V

u_trial_V = TrialFunction(V)
v_V = TestFunctions(V)

M_V = assemble( u_trial_V  * v_V *dx)
L = dtc * (RK_b1 * (-dot(p1,grad(v_V))*dx +  dot( p1('+'), jump(v_V,n) )*dS) \
        + RK_b2 * (-dot(p2,grad(v_V))*dx +  dot( p2('+'), jump(v_V,n) )*dS) )  

u_solution = Function(V)        
b = assemble(L)
solve(M_V, u_solution, b)
u.assign(u + u_solution)