You can reformulate the problem as a saddle point problem:
V = FunctionSpace(mesh, 'Lagrange', 1)
R = FunctionSpace(mesh, "R", 0)
W = V * R
u, r = TrialFunctions(W)
v, s = TestFunctions(W)
f = Expression('x[1]*x[1]')
a = inner(grad(u), grad(v))* dx + v * f * r *ds(1) \
+ u * f * s * ds(1) - r * s * ds(1)
This results in a variational formulation that you can assemble, but it is symmetric indefinite so you have to adapt the linear solver accordingly.
Alternatively, if you want to preserve the SPD structure of your variational form, you can form the operator without explicitly constructing the matrix:
a = inner(grad(u), grad(v))* dx
b = f * v * ds(1)
p = a + u * v * dx
A = assemble(a)
B = assemble(b)
P = assemble(p)
class CompositeOperator(object):
def __init__(self, A, B):
self.A_mat = as_backend_type(A).mat()
self.B_vec = as_backend_type(B).vec()
def mult(self, mat, x, y):
self.A_mat.mult(x, y)
a = self.B_vec.dot(x)
y.axpy(a, self.B_vec)
def as_petscmatrix(self):
from petsc4py import PETSc
mat = PETSc.Mat().createPython(self.A_mat.getSizes(),
comm = mpi_comm_world())
mat.setPythonContext(self)
return PETScMatrix(mat)
A_B = CompositeOperator(A, B).as_petscmatrix()
solver = PETScKrylovSolver("cg", "hypre_amg")
solver.set_operators(A_B, P)
This solution requires that you have compiled dolfin with petsc4py.