# Poisson equation
# ================
#
# It is what it is, a conforming discretization on a regular mesh using
# piecewise quadratic elements.
#
# As usual we start by importing firedrake and setting up the problem.::
from firedrake import *
N = 128
mesh = UnitSquareMesh(N, N)
V = FunctionSpace(mesh, "CG", 2)
u = TrialFunction(V)
v = TestFunction(V)
a = inner(grad(u), grad(v)) * dx
x = SpatialCoordinate(mesh)
F = Function(V)
F.interpolate(sin(x[0]*pi)*sin(2*x[1]*pi))
L = F*v*dx
bcs = [DirichletBC(V, Constant(2.0), (1,))]
uu = Function(V)
# With the setup out of the way, we now demonstrate various ways of
# configuring the solver. First, a direct solve with an assembled
# operator.::
solve(a == L, uu, bcs=bcs, solver_parameters={"ksp_type": "preonly",
"pc_type": "lu"})
# Next, we use unpreconditioned conjugate gradients using matrix-free
# actions. This is not very efficient due to the :math:`h^{-2}`
# conditioning of the Laplacian, but demonstrates how to request an
# unassembled operator using the ``"mat_type"`` solver parameter.::
uu.assign(0)
solve(a == L, uu, bcs=bcs, solver_parameters={"mat_type": "matfree",
"ksp_type": "cg",
"pc_type": "none",
"ksp_monitor": None})
# Finally, we demonstrate the use of a :class:`.AssembledPC`
# preconditioner. This uses matrix-free actions but preconditions the
# Krylov iterations with an incomplete LU factorisation of the assembled
# operator.::
uu.assign(0)
solve(a == L, uu, bcs=bcs, solver_parameters={"mat_type": "matfree",
"ksp_type": "cg",
"ksp_monitor": None,
# To use the assembled matrix for the preconditioner we select a
# ``"python"`` type::
"pc_type": "python",
# and set its type, by providing the name of the class constructor to
# PETSc.::
"pc_python_type": "firedrake.AssembledPC",
# Finally, we set the preconditioner type for the assembled operator::
"assembled_pc_type": "ilu"})
# This demo is available as a runnable python file :demo:`here
# `.