TX = TensorProductSpace(comm, (FXX, FXY))
TY = TensorProductSpace(comm, (FYX, FYY))

V = VectorSpace([TX, TY])

u = TrialFunction(V)
v = TestFunction(V)
mat = inner(grad(u), grad(v))
fj = Array(V, buffer=f)
rhs = inner(v, fj)

# boundary integrals
# x - component
v_bndry_x = TestFunction(FXY)
gn_x = Array(FXY, buffer=neumann_condition_x)
evaluate_bndry_x = FXX.evaluate_basis_all(-1)
project_gn_x = inner(gn_x, v_bndry_x)
bndry_integral_x = -np.outer(evaluate_bndry_x, project_gn_x)
# y - component
v_bndry_y = TestFunction(FYX)
gn_y = Array(FYX, buffer=neumann_condition_y)
evaluate_bndry_y = FYY.evaluate_basis_all(1)
project_gn_y = inner(gn_y, v_bndry_y)
bndry_integral_y = np.outer(project_gn_y, evaluate_bndry_y)

# add boundary integrals to rhs
rhs[0] += bndry_integral_x
rhs[1] += bndry_integral_y

M = BlockMatrix(mat)
neumann_condition = ua.diff(x).evalf(subs={x: -1})
FX = FunctionSpace(20, family='legendre', bc=(None, 0))
FY = FunctionSpace(20, family='legendre', bc=(0, 0))
T = TensorProductSpace(comm, (FX, FY))

u = TrialFunction(T)
v = TestFunction(T)
mat = inner(grad(u), grad(v))
fj = Array(T, buffer=f)
rhs = inner(v, fj)

v_bndry = TestFunction(FY)

gn = Array(FY, buffer=neumann_condition)
evaluate_x_bndry = FX.evaluate_basis_all(-1)
project_g = inner(gn, v_bndry)

bndry_integral = np.outer(evaluate_x_bndry, project_g)

rhs -= bndry_integral

Sol = sf.la.SolverGeneric2ND(mat)

u_hat = Function(T)
u_hat = Sol(rhs, u_hat)

u_ana = Array(T, buffer=ua)
l2_error = np.linalg.norm(u_hat.backward() - u_ana)
print(l2_error)
xx, yy = T.mesh()