# Bilinear and linear forms  a = dot(grad(v), grad(u))*dx + k*djump(v)*djump(u)*dc  L = v*f*dx
### Surface representation
A user of any library which supports UFC can use the generated code by just providing their own sub-class of GenericPUM. To ensure that the jump in a solution goes to zero at the boundary of a discontinuity surface which does not intersect the boundary of the domain, the enriched degrees of freedom are carefully selected close to the boundary of a discontinuity surface, as described in [19]. We are now in a position to define function spaces and variational forms which are represented by the DOLFIN classes FunctionSpace and Form, respectively. A FunctionSpace represents the mathematical function space within which a solution is sought, such as those defined in Equation (20) which describe the type of finite element functions. A FunctionSpace is also aware of the domain \(\Omega\) and the degree of freedom map (which in part defines the regularity of the function space). A Form is defined by the variational problem and the relevant function space(s). A Form can be assembled into a global matrix (in the case of a bilinear form) or a global vector (in the case of a linear form). These concepts and abstractions are explained in detail in [7] for conventional finite element methods. For the Poisson problem presented in Section 3.2., a function space, and bilinear and linear forms are created by  
* Poisson::FunctionSpaceV(mesh, pump_objects); Poisson::BilinearForma(V, V); Poisson::LinearFormL(V);  
with the form objects being initialised with function spaces. The code for the above function space and form classes is generated by the form compiler. The form classes are essentially wrappers for the UFC_PoissonBilinearForm and UFC_PoissonLinearForm objects and are created to simply the interaction with the DOLFIN environment. For a problem with multiple fields, such as three-dimensional incompressible elasticity, a PUM object is associated with each field (one for each displacement component plus one for the pressure field), therefore to create a function space we would have
```
std::vector<constGenericPUM*>pum_objects; pum_objects.push_back(&pum_u); pum_objects.push_back(&pum_u); pum_objects.push_back(&pum_u); pum_objects.push_back(&pum_p); Incompressible3D::FunctionSpaceV(mesh,pum_objects);
```  
Since the displacement components are all discontinuous across the same surface and they share the same finite element type, they can share the same PUM object. Usually the finite element field used for the pressure field differs from that used for the displacement components, therefore it requires its own PUM object. An incompressible elasticity formulation is elaborated in Section 5..  
With the exception of Dirichlet boundary conditions, the finite element variational problem is completely defined by the Form objects and the mesh. They can be passed to the assembler to compute the global matrix and vector. ```
MatrixA; Vectorb; Assembler::assemble(A,a); Assembler::assemble(b,L);
```  
Once the global matrix and vector have been assembled, Dirichlet boundary conditions can be applied to the linear system if necessary, and the system of linear equations can be solved as usual.