This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Using the PETSc PCFieldSplit in FEniCS

0 votes

Hi all,

Does anyone have an example of how to use the PETSC PCFieldSplit preconditioner from within FEniCS?

Thanks

asked Sep 3, 2014 by mwelland FEniCS User (8,410 points)

1 Answer

+6 votes
 
Best answer

The only way I know is to export the matrix to petsc4py and use the interface there.
The following code example uses all of
(1) MUMPS direct solver
(2) FEniCS implementation of a simple block preconditioner
(3) PETSc fieldsplit preconditioner
to solve the Stokes demo.

from dolfin import *
from petsc4py import *
import numpy as np

# basic setup copied from the fenics stokes demo
mesh = UnitCubeMesh(8, 8, 8)
V = VectorFunctionSpace(mesh, 'CG', 2)
Q = FunctionSpace(mesh, 'CG', 1)
W = V * Q
def right(x, on_boundary): return x[0] > (1.0 - DOLFIN_EPS)
def left(x, on_boundary): return x[0] < DOLFIN_EPS
def top_bottom(x, on_boundary):
    return x[1] > 1.0 - DOLFIN_EPS or x[1] < DOLFIN_EPS
noslip = Constant((0.0, 0.0, 0.0))
bc0 = DirichletBC(W.sub(0), noslip, top_bottom)
inflow = Expression(('-sin(x[1]*pi)', '0.0', '0.0'))
bc1 = DirichletBC(W.sub(0), inflow, right)
zero = Constant(0)
bc2 = DirichletBC(W.sub(1), zero, left)
bcs = [bc0, bc1, bc2]
(u, p) = TrialFunctions(W)
(v, q) = TestFunctions(W)
f = Constant((0.0, 0.0, 0.0))
a = inner(grad(u), grad(v))*dx + div(v)*p*dx + q*div(u)*dx
L = inner(f, v)*dx
m = inner(grad(u), grad(v))*dx + p*q*dx
(A, b) = assemble_system(a, L, bcs)
(M, _) = assemble_system(m, L, bcs)

# fenics direct solve
solver = LUSolver('mumps')
solver.set_operator(A)
U = Function(W)
solver.solve(U.vector(), b)

# fenics iterative solve
solver = KrylovSolver("tfqmr", "amg")
solver.set_operators(A, M)
U1 = Function(W)
solver.solve(U1.vector(), b)
diff = np.max(np.abs(U.vector().array()-U1.vector().array()))

# export to petsc4py
A = as_backend_type(A).mat()
b = as_backend_type(b).vec()
M = as_backend_type(M).mat()

# fieldsplit solve
ksp = PETSc.KSP().create()
ksp.setType(PETSc.KSP.Type.TFQMR)
pc = ksp.getPC()
pc.setType(PETSc.PC.Type.FIELDSPLIT)
is0 = PETSc.IS().createGeneral(W.sub(0).dofmap().dofs())
is1 = PETSc.IS().createGeneral(W.sub(1).dofmap().dofs())
pc.setFieldSplitIS(('u', is0), ('p', is1))
pc.setFieldSplitType(0) # 0=additive
subksps = pc.getFieldSplitSubKSP()
subksps[0].setType("preonly")
subksps[0].getPC().setType("hypre")
subksps[1].setType("preonly")
subksps[1].getPC().setType("hypre")
ksp.setOperators(A, M)
ksp.setFromOptions()
(x, _) = A.getVecs()
ksp.solve(b, x)
print(np.max(np.abs(U1.vector().array()-x.array)))
answered Sep 5, 2014 by lzlarryli FEniCS Novice (820 points)
selected Sep 8, 2014 by mwelland

Thanks, this really helps although I was hoping there would be functionality built into fenics directly... There seems to be the beginning of it in the PETScPreconditioner object...

...