def solve(self):
        """Solve for and return the computed displacement field, u"""

        # Create solver
        
        formulation = self.parameters['solver_parameters']['problem_formulation']
        if formulation == 'displacement':
            self.solver = StaticMomentumBalanceSolver_U(self, self.parameters["solver_parameters"],\
                                self.coordinate_system)
        elif formulation == 'mixed_up':
            self.solver = StaticMomentumBalanceSolver_UP(self, self.parameters['solver_parameters'],\
                                self.coordinate_system)

        # Call solver
        return self.solver.solve()
class StaticHyperelasticity(CBCProblem):
    """Base class for all static hyperelasticity problems"""

    def __init__(self, coordinate_system = None):
        """Create the static hyperelasticity problem"""

        # Set up parameters
        self.parameters = Parameters("problem_parameters")
        self.parameters.add(solver_parameters())
        self.coordinate_system = coordinate_system

    def solve(self):
        """Solve for and return the computed displacement field, u"""

        # Create solver
        
        formulation = self.parameters['solver_parameters']['problem_formulation']
        if formulation == 'displacement':
            self.solver = StaticMomentumBalanceSolver_U(self, self.parameters["solver_parameters"],\
                                self.coordinate_system)
        elif formulation == 'mixed_up':
            self.solver = StaticMomentumBalanceSolver_UP(self, self.parameters['solver_parameters'],\
                                self.coordinate_system)

        # Call solver
        return self.solver.solve()

    def body_force(self):
        """Return body force, B"""
        return []

    def body_force_u(self, u):
        # FIXME: This is currently only implemented for the cG(1) solver
        """Return body force, B, depending on displacement u"""
        return []

    def dirichlet_values(self):
        """Return Dirichlet boundary conditions for the displacment
        field"""
        return []

    def dirichlet_boundaries(self):
        """Return boundaries over which Dirichlet conditions act"""
        return []

    def neumann_conditions(self):
        """Return Neumann boundary conditions for the stress field"""
        return []

    def neumann_boundaries(self):
        """Return boundaries over which Neumann conditions act"""
        return []

    def periodic_boundaries(self):
        """ Return periodic boundaries """
        return []

    def material_model(self):
        pass

    def first_pk_stress(self, u):
        """Return the first Piola-Kirchhoff stress tensor, P, given a
        displacement field, u"""
        
        material_model = self.material_model()
        if isinstance(material_model, tuple):
            fpk_list = []
            material_list, subdomains_list = material_model
            for material in material_list:
                fpk_list.append(material.FirstPiolaKirchhoffStress(u, self.coordinate_system))
            return (fpk_list, subdomains_list)
        else:
            return material_model.FirstPiolaKirchhoffStress(u, self.coordinate_system)

    def second_pk_stress(self, u):
        """Return the second Piola-Kirchhoff stress tensor, S, given a
        displacement field, u"""
        material_model = self.material_model()
        if isinstance(material_model, tuple):
            spk_list = []
            material_list, subdomains_list = material_model
            for material in material_list:
                spk_list.append(material.SecondPiolaKirchhoffStress(u, self.coordinate_system))
            return (spk_list, subdomains_list)
        else:
            return self.material_model().SecondPiolaKirchhoffStress(u, self.coordinate_system)

    def strain_energy(self, u):
        """Return the strain (potential) energy density given a displacement
        field, u"""

        S = self.second_pk_stress(u)
        E = GreenLagrangeStrain(u)
        if isinstance(S, tuple):
            S_list, subdomains_list = S
            V = FunctionSpace(u.function_space().mesh(), 'DG', 0)
            temp = Function(V)
            psi = Function(V)
            subdomains = subdomains_list[0]
            for cell_no in range(len(subdomains[0].array())):
                subdomain_no = subdomains[0].array()[cell_no]
                temp = project(0.5*inner(S_list[int(subdomain_no - 1)], E), V)
                psi.vector()[cell_no] = temp.vector()[cell_no][0]
        else:
            psi = 0.5*inner(S, E)
        return psi

    def functional(self, u):
        """Return value of goal functional"""
        return None

    def reference(self):
        """Return reference value for the goal functional"""
        return None

    def __str__(self):
        """Return a short description of the problem"""
        return "Static hyperelasticity problem"