Beispiel #1
0
def set_linear_dirichlet_constant(mesh,
                                  dt,
                                  var_name='Temperature',
                                  bc_temperature=1300.,
                                  temperature=300.,
                                  source_value=0.,
                                  axis=1,
                                  right=True,
                                  tol=1e-4,
                                  conductivity=1.,
                                  density=1.,
                                  specific_heat=1.):
    '''
    Heat equation problem where an edge/surface is set at a given temperature
    and everything else at another.

    Parameters
    ----------
    axis : int
        Controls boundary to which Dirichlet bc is applied.
    right : bool
        Dirichlet bc is applied to the planar and perpendicular face found in
        the max (True) or min (False) coordinate.
    '''

    # function space
    V = FunctionSpace(mesh, 'Lagrange', 1)

    # boundary conditions
    bcs = [
        set_dirichlet_bc_lim(V,
                             value=bc_temperature,
                             axis=axis,
                             right=right,
                             tol=tol)
    ]

    # initial condition
    u_initial = Constant(temperature)
    u_n = Function(V, name=var_name)
    u_n.interpolate(u_initial)

    # problem formulation
    f = Constant(source_value)
    u_n, a, L = get_formulation_constant_props(V,
                                               u_initial,
                                               f,
                                               dt,
                                               conductivity,
                                               density,
                                               specific_heat,
                                               var_name=var_name)

    u = Function(V, name=var_name)

    return u_n, a, L, u, bcs
Beispiel #2
0
def get_formulation(V, u_initial, f, dt, var_name='Temperature'):

    # interpolate initial condition
    u_n = Function(V, name=var_name)
    u_n.interpolate(u_initial)

    # function spaces
    u_h = TrialFunction(V)
    v = TestFunction(V)

    # formulation
    a = u_h * v * dx + dt * dot(grad(u_h), grad(v)) * dx
    L = (u_n + dt * f) * v * dx

    return u_n, a, L
Beispiel #3
0
def set_poisson_eq_2d(n=8):
    '''
    Basic example where only the mesh refinement is controlled.
    '''

    # mesh
    mesh = UnitSquareMesh(n, n)

    # function space
    V = FunctionSpace(mesh, 'P', 1)

    # bcs
    u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=2)

    def boundary(x, on_boundary):
        return on_boundary

    bc = DirichletBC(V, u_D, boundary)

    # variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    f = Constant(-6.0)
    a = dot(grad(u), grad(v)) * dx
    L = f * v * dx

    # define unknown
    u = Function(V)

    return a, L, u, bc
Beispiel #4
0
    def read_checkpoint(self, V, name: str, counter: int = -1) -> Function:
        """Read finite element Function from checkpointing format

        Parameters
        ----------
        V
            Function space of saved function.
        name
            Name of function as saved into XDMF file.
        counter : optional
            Position of function in the file within functions of the same
            name. Counter is used to read function saved as time series.
            To get last saved function use counter=-1, or counter=-2 for
            one before last, etc.
        Note
        ----
        Parameter `V: Function space` must be the same as saved function space
        except for ordering of mesh entities.
        Returns
        -------
        dolfin.function.function.Function
            The finite element Function read from checkpoint file
        """

        V_cpp = getattr(V, "_cpp_object", V)
        u_cpp = self._cpp_object.read_checkpoint(V_cpp, name, counter)
        return Function(V, u_cpp.vector())
Beispiel #5
0
def set_linear_equal_opposite(mesh,
                              dt,
                              var_name='Temperature',
                              axis=0,
                              bc_temperature=300.,
                              source_value=0.,
                              conductivity=1.,
                              density=1.,
                              specific_heat=1.,
                              V=None):
    '''
    Heat equation problem where two opposite edges/faces are set at the same
    temperature and the points in between follow a quadratic variation.

    Notes
    -----
    * assumes opposite faces of interest are planar and perpendicular to the
    axis.
    '''

    # function space
    if V is None:
        V = FunctionSpace(mesh, 'Lagrange', 1)

    # boundary conditions
    x_min, x_max = get_mesh_axis_lims(mesh, axis)
    bcs = [
        set_dirichlet_bc(V, x, bc_temperature, axis) for x in [x_min, x_max]
    ]

    # initial condition
    c = (x_max - x_min) / 2
    param = bc_temperature / (c**2)
    u_initial = Expression('param * (x[axis] - c) * (x[axis] - c)',
                           degree=2,
                           param=param,
                           c=c,
                           name='T',
                           axis=axis)

    # problem formulation
    f = Constant(source_value)
    u_n, a, L = get_formulation_constant_props(V,
                                               u_initial,
                                               f,
                                               dt,
                                               conductivity,
                                               density,
                                               specific_heat,
                                               var_name=var_name)

    u = Function(V, name=var_name)

    return u_n, a, L, u, bcs
Beispiel #6
0
def load_last_checkpoint(xdmf_filename, V, var_name):
    # TODO: file should be passed in order to open only once?

    # get times
    times = get_times_from_xdfm_checkpoints(xdmf_filename)

    # load last checkpoint
    with XDMFFile(MPI.comm_self, xdmf_filename) as file:
        u = Function(V, name=var_name)
        file.read_checkpoint(u, var_name, -1)

    return u, times[-1], len(times) - 1
Beispiel #7
0
def get_formulation_constant_props(V, u_initial, f, dt, conductivity, density,
                                   specific_heat, var_name='Temperature'):

    # medium properties
    k = Constant(conductivity)
    rho = Constant(density)
    c_p = Constant(specific_heat)

    # interpolate initial condition
    u_n = Function(V, name=var_name)
    u_n.interpolate(u_initial)

    # function spaces
    u_h = TrialFunction(V)
    v = TestFunction(V)

    # formulation
    param1 = rho * c_p
    param2 = k / param1
    a = u_h * v * dx + param2 * dt * dot(grad(u_h), grad(v)) * dx
    L = (u_n + param1 * dt * f) * v * dx

    return u_n, a, L
    def initialize_data(self):
        """
        Extract required objects for defining error control
        forms. This will be stored and reused.
        """
        # Developer's note: The UFL-FFC-DOLFIN--PyDOLFIN toolchain for
        # error control is quite fine-tuned. In particular, the order
        # of coefficients in forms is (and almost must be) used for
        # their assignment. This means that the order in which these
        # coefficients are defined matters and should be considered
        # fixed.

        # Primal trial element space
        self._V = self.u.function_space()

        # Primal test space == Dual trial space
        Vhat = self.weak_residual.arguments()[0].function_space()

        # Discontinuous version of primal trial element space
        self._dV = tear(self._V)

        # Extract cell and geometric dimension
        mesh = self._V.mesh()
        dim = mesh.topology().dim()

        # Function representing improved dual
        E = increase_order(Vhat)
        self._Ez_h = Function(E)

        # Function representing cell bubble function
        B = FunctionSpace(mesh, "B", dim + 1)
        self._b_T = Function(B)
        self._b_T.vector()[:] = 1.0

        # Function representing strong cell residual
        self._R_T = Function(self._dV)

        # Function representing cell cone function
        C = FunctionSpace(mesh, "DG", dim)
        self._b_e = Function(C)

        # Function representing strong facet residual
        self._R_dT = Function(self._dV)

        # Function for discrete dual on primal test space
        self._z_h = Function(Vhat)

        # Piecewise constants for assembling indicators
        self._DG0 = FunctionSpace(mesh, "DG", 0)
Beispiel #9
0
    def initialize_data(self):
        """
        Extract required objects for defining error control
        forms. This will be stored and reused.
        """
        # Developer's note: The UFL-FFC-DOLFIN--PyDOLFIN toolchain for
        # error control is quite fine-tuned. In particular, the order
        # of coefficients in forms is (and almost must be) used for
        # their assignment. This means that the order in which these
        # coefficients are defined matters and should be considered
        # fixed.

        # Primal trial element space
        self._V = self.u.function_space()

        # Primal test space == Dual trial space
        Vhat = self.weak_residual.arguments()[0].function_space()

        # Discontinuous version of primal trial element space
        self._dV = tear(self._V)

        # Extract cell and geometric dimension
        mesh = self._V.mesh()
        dim = mesh.topology().dim()

        # Function representing improved dual
        E = increase_order(Vhat)
        self._Ez_h = Function(E)

        # Function representing cell bubble function
        B = FunctionSpace(mesh, "B", dim + 1)
        self._b_T = Function(B)
        self._b_T.vector()[:] = 1.0

        # Function representing strong cell residual
        self._R_T = Function(self._dV)

        # Function representing cell cone function
        C = FunctionSpace(mesh, "DG", dim)
        self._b_e = Function(C)

        # Function representing strong facet residual
        self._R_dT = Function(self._dV)

        # Function for discrete dual on primal test space
        self._z_h = Function(Vhat)

        # Piecewise constants for assembling indicators
        self._DG0 = FunctionSpace(mesh, "DG", 0)
def interpolate(v, V):
    """Return interpolation of a given function into a given finite
    element space.

    *Arguments*
        v
            a :py:class:`Function <dolfin.function.function.Function>` or
            a :py:class:`MultiMeshFunction
                         <dolfin.function.function.MultiMeshFunction>` or
            an :py:class:`Expression <dolfin.functions.expression.Expression>`
        V
            a :py:class:`FunctionSpace (standard, mixed, etc.)
            <dolfin.functions.functionspace.FunctionSpace>`
            or a :py:class:`MultiMeshFunctionSpace
            <dolfin.function.MultiMeshFunctionSpace>`.


    *Example of usage*

        .. code-block:: python

            v = Expression("sin(pi*x[0])")
            V = FunctionSpace(mesh, "Lagrange", 1)
            Iv = interpolate(v, V)

    """

    # Check arguments
    # if not isinstance(V, cpp.functionFunctionSpace):
    #     cpp.dolfin_error("interpolation.py",
    #                      "compute interpolation",
    #                      "Illegal function space for interpolation, not a FunctionSpace (%s)" % str(v))

    if isinstance(V, MultiMeshFunctionSpace):
        Pv = MultiMeshFunction(V)
    else:
        Pv = Function(V)

    # Compute interpolation
    if hasattr(v, "_cpp_object"):
        Pv.interpolate(v._cpp_object)
    else:
        Pv.interpolate(v)

    return Pv
Beispiel #11
0
def convert_xdmf_checkpoints_to_vtk(xdmf_filename,
                                    V,
                                    var_name,
                                    vtk_filename=None):

    # get times
    times = get_times_from_xdfm_checkpoints(xdmf_filename)

    # create vtk file
    if vtk_filename is None:
        vtk_filename = xdmf_filename.split('.')[0] + '.pvd'
    vtkfile = File(vtk_filename)

    # load variable and save as vtk
    with XDMFFile(xdmf_filename) as file:
        for i, t in enumerate(times):
            u = Function(V, name=var_name)

            file.read_checkpoint(u, var_name, i)

            vtkfile << (u, t)
Beispiel #12
0
    def read_function(self, V, name: str):
        """Read finite element Function from file

        Parameters
        ----------
        V
            Function space of saved function.
        name
            Name of function as saved into HDF file.
        Returns
        -------
        dolfin.function.function.Function
            Function read from file

        Note
        ----
        Parameter `V: Function space` must be the same as saved function space
        except for ordering of mesh entities.
        """

        V_cpp = getattr(V, "_cpp_object", V)
        u_cpp = self._cpp_object.read(V_cpp, name)
        return Function(V, u_cpp.vector())
Beispiel #13
0
def r2_errornorm(u, uh, norm_type="l2", degree_rise=3, mesh=None ):
    """
    This function is a modification of FEniCS's built-in errornorm function that adopts the :math:`r^2dr`
    measure as opposed to the standard Cartesian :math:`dx` measure.

    For documentation and usage, see the 
    original module <https://bitbucket.org/fenics-project/dolfin/src/master/python/dolfin/fem/norms.py>_.

    """


    # Get mesh
    if isinstance(u, cpp.function.Function) and mesh is None:
        mesh = u.function_space().mesh()
    if isinstance(uh, cpp.function.Function) and mesh is None:
        mesh = uh.function_space().mesh()
    # if isinstance(uh, MultiMeshFunction) and mesh is None:
    #     mesh = uh.function_space().multimesh()
    if hasattr(uh, "_cpp_object") and mesh is None:
        mesh = uh._cpp_object.function_space().mesh()
    if hasattr(u, "_cpp_object") and mesh is None:
        mesh = u._cpp_object.function_space().mesh()
    if mesh is None:
        raise RuntimeError("Cannot compute error norm. Missing mesh.")

    # Get rank
    if not u.ufl_shape == uh.ufl_shape:
        raise RuntimeError("Cannot compute error norm. Value shapes do not match.")
    
    shape = u.ufl_shape
    rank = len(shape)

    # Check that uh is associated with a finite element
    if uh.ufl_element().degree() is None:
        raise RuntimeError("Cannot compute error norm. Function uh must have a finite element.")

    # Degree for interpolation space. Raise degree with respect to uh.
    degree = uh.ufl_element().degree() + degree_rise

    # Check degree of 'exact' solution u
    degree_u = u.ufl_element().degree()
    if degree_u is not None and degree_u < degree:
        cpp.warning("Degree of exact solution may be inadequate for accurate result in errornorm.")

    # Create function space
    if rank == 0:
        V = FunctionSpace(mesh, "Discontinuous Lagrange", degree)
    elif rank == 1:
        V = VectorFunctionSpace(mesh, "Discontinuous Lagrange", degree,
                                dim=shape[0])
    elif rank > 1:
        V = TensorFunctionSpace(mesh, "Discontinuous Lagrange", degree,
                                shape=shape)

    # Interpolate functions into finite element space
    pi_u = interpolate(u, V)
    pi_uh = interpolate(uh, V)

    # Compute the difference
    e = Function(V)
    e.assign(pi_u)
    e.vector().axpy(-1.0, pi_uh.vector())

    # Compute norm
    return r2_norm(e, func_degree=degree, norm_type=norm_type, mesh=mesh )
def _rush_larsen_scheme_generator_adm(rhs_form, solution, time, order,
                                      generalized, perturbation):
    """Generates a list of forms and solutions for the adjoint
    linearisation of the Rush-Larsen scheme

    *Arguments*
        rhs_form (ufl.Form)
            A UFL form representing the rhs for a time differentiated equation
        solution (_Function_)
            The prognostic variable
        time (_Constant_)
            A Constant holding the time at the start of the time step
        order (int)
            The order of the scheme
        generalized (bool)
            If True generate a generalized Rush Larsen scheme, linearizing all
            components.
        perturbation (Function)
            The vector on which we compute the adjoint action.

    """

    DX = _check_form(rhs_form)

    if DX != ufl.dP:
        raise TypeError("Expected a form with a Pointintegral.")

    # Create time step
    dt = Constant(0.1)

    # Get test function
    #    arguments = rhs_form.arguments()
    #    coefficients = rhs_form.coefficients()

    # Get time dependent expressions
    time_dep_expressions = _time_dependent_expressions(rhs_form, time)

    # Extract rhs expressions from form
    rhs_integrand = rhs_form.integrals()[0].integrand()
    rhs_exprs, v = extract_tested_expressions(rhs_integrand)
    vector_rhs = len(v.ufl_shape) > 0 and v.ufl_shape[0] > 1

    system_size = v.ufl_shape[0] if vector_rhs else 1

    # Fix for indexing of v for scalar expressions
    v = v if vector_rhs else [v]

    # Extract linear terms if not using generalized Rush Larsen
    if not generalized:
        linear_terms = _find_linear_terms(rhs_exprs, solution)
    else:
        linear_terms = [True for _ in range(system_size)]

    # Wrap the rhs expressions into a ufl vector type
    rhs_exprs = ufl.as_vector([rhs_exprs[i] for i in range(system_size)])
    rhs_jac = ufl.diff(rhs_exprs, solution)

    # Takes time!
    if vector_rhs:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[ind, ind]))
                          for ind in range(system_size)]
        soln = solution
    else:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[0]))]
        solution = [solution]
        soln = solution[0]

    ufl_stage_forms = []
    dolfin_stage_forms = []
    dt_stage_offsets = []
    trial = TrialFunction(soln.function_space())

    # Stage solutions (3 per order rhs, linearized, and final step)
    # If 2nd order the final step for 1 step is a stage
    if order == 1:
        stage_solutions = []

        # Fetch the original step
        rl_ufl_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                        linear_terms, system_size,
                                        solution, None, dt, time, 1.0,
                                        0.0, v, DX,
                                        time_dep_expressions)

        # If this is commented out, we don't get NaNs.  Yhy is
        # solution a list of length zero anyway?
        rl_ufl_form = safe_action(safe_adjoint(derivative(rl_ufl_form, soln, trial)),
                                  perturbation)

    elif order == 2:
        # Stage solution for order 2
        fn_space = soln.function_space()

        stage_solutions = [Function(fn_space, name="y_1/2"),
                           Function(fn_space, name="y_1"),
                           Function(fn_space, name="y_bar_1/2")]

        y_half_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                        linear_terms, system_size,
                                        solution, None, dt, time, 0.5,
                                        0.0, v, DX,
                                        time_dep_expressions)

        y_one_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                       linear_terms, system_size,
                                       solution, stage_solutions[0],
                                       dt, time, 1.0, 0.5, v, DX,
                                       time_dep_expressions)

        y_bar_half_form = safe_action(safe_adjoint(derivative(y_one_form,
                                                              stage_solutions[0], trial)), perturbation)

        rl_ufl_form = safe_action(safe_adjoint(derivative(y_one_form, soln, trial)), perturbation) + \
            safe_action(safe_adjoint(derivative(y_half_form, soln, trial)), stage_solutions[2])

        ufl_stage_forms.append([y_half_form])
        ufl_stage_forms.append([y_one_form])
        ufl_stage_forms.append([y_bar_half_form])
        dolfin_stage_forms.append([Form(y_half_form)])
        dolfin_stage_forms.append([Form(y_one_form)])
        dolfin_stage_forms.append([Form(y_bar_half_form)])

    # Get last stage form
    last_stage = Form(rl_ufl_form)

    human_form = "%srush larsen %s" % ("generalized " if generalized else "",
                                       str(order))

    return rhs_form, linear_terms, ufl_stage_forms, dolfin_stage_forms, last_stage, \
        stage_solutions, dt, dt_stage_offsets, human_form, perturbation
def _butcher_scheme_generator_adm(a, b, c, time, solution, rhs_form, adj):
    """Generates a list of forms and solutions for a given Butcher tableau

    *Arguments*
        a (2 dimensional numpy array)
            The a matrix of the Butcher tableau.
        b (1-2 dimensional numpy array)
            The b vector of the Butcher tableau. If b is 2 dimensional the
            scheme includes an error estimator and can be used in adaptive
            solvers.
        c (1 dimensional numpy array)
            The c vector the Butcher tableau.
        time (_Constant_)
            A Constant holding the time at the start of the time step
        solution (_Function_)
            The prognostic variable
        rhs_form (ufl.Form)
            A UFL form representing the rhs for a time differentiated equation
        adj (_Function_)
            The derivative of the functional with respect to y_n+1

    """

    a = _check_abc(a, b, c)
    size = a.shape[0]

    DX = _check_form(rhs_form)

    # Get test function
    arguments = rhs_form.arguments()
    # coefficients = rhs_form.coefficients()
    v = arguments[0]

    # Create time step
    dt = Constant(0.1)

    # rhs forms
    dolfin_stage_forms = []
    ufl_stage_forms = []

    # Stage solutions
    k = [Function(solution.function_space(), name="k_%d" % i) for i in range(size)]
    kbar = [Function(solution.function_space(), name="kbar_%d" % i)
            for i in range(size)]

    # Create the stage forms
    y_ = solution
    time_ = time
    time_dep_expressions = _time_dependent_expressions(rhs_form, time)
    zero_ = ufl.zero(*y_.ufl_shape)
    forward_forms = []
    stage_solutions = []
    jacobian_indices = []

    # The recomputation of the forward run:
    for i, ki in enumerate(k):

        # Check whether the stage is explicit
        explicit = a[i, i] == 0

        # Evaluation arguments for the ith stage
        evalargs = y_ + dt * sum([float(a[i, j]) * k[j]
                                  for j in range(i + 1)], zero_)
        time = time_ + dt * c[i]

        replace_dict = _replace_dict_time_dependent_expression(
            time_dep_expressions, time_, dt, c[i])

        replace_dict[y_] = evalargs
        replace_dict[time_] = time
        stage_form = ufl.replace(rhs_form, replace_dict)

        forward_forms.append(stage_form)

        if explicit:
            stage_forms = [stage_form]
            jacobian_indices.append(-1)
        else:
            # Create a F=0 form and differentiate it
            stage_form_implicit = stage_form - ufl.inner(ki, v) * DX
            stage_forms = [stage_form_implicit, derivative(
                stage_form_implicit, ki)]
            jacobian_indices.append(0)

        ufl_stage_forms.append(stage_forms)
        dolfin_stage_forms.append([Form(form) for form in stage_forms])
        stage_solutions.append(ki)

    for i, kbari in reversed(list(enumerate(kbar))):

        # Check whether the stage is explicit
        explicit = a[i, i] == 0

        # And now the adjoint linearisation:
        stage_form_adm = ufl.inner(dt * b[i] * adj, v) * DX + sum(
            [dt * float(a[j, i]) * safe_action(safe_adjoint(derivative(
                forward_forms[j], y_)), kbar[j]) for j in range(i, size)])
        if explicit:
            stage_forms_adm = [stage_form_adm]
            jacobian_indices.append(-1)
        else:
            # Create a F=0 form and differentiate it
            stage_form_adm -= ufl.inner(kbar[i], v) * DX
            stage_forms_adm = [stage_form_adm, derivative(stage_form_adm, kbari)]
            jacobian_indices.append(1)

        ufl_stage_forms.append(stage_forms_adm)
        dolfin_stage_forms.append([Form(form) for form in stage_forms_adm])
        stage_solutions.append(kbari)

    # Only one last stage
    if len(b.shape) == 1:
        last_stage = Form(ufl.inner(adj, v) * DX + sum(
            [safe_action(safe_adjoint(derivative(forward_forms[i], y_)), kbar[i])
             for i in range(size)]))
    else:
        raise Exception("Not sure what to do here")

    human_form = "unimplemented"

    return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage, \
        stage_solutions, dt, human_form, adj
def _rush_larsen_scheme_generator(rhs_form, solution, time, order, generalized):
    """Generates a list of forms and solutions for a given Butcher
    tableau

    *Arguments*
        rhs_form (ufl.Form)
            A UFL form representing the rhs for a time differentiated equation
        solution (_Function_)
            The prognostic variable
        time (_Constant_)
            A Constant holding the time at the start of the time step
        order (int)
            The order of the scheme
        generalized (bool)
            If True generate a generalized Rush Larsen scheme, linearizing all
            components.

    """

    DX = _check_form(rhs_form)

    if DX != ufl.dP:
        raise TypeError("Expected a form with a Pointintegral.")

    # Create time step
    dt = Constant(0.1)

    # Get test function
    #    arguments = rhs_form.arguments()
    #    coefficients = rhs_form.coefficients()

    # Get time dependent expressions
    time_dep_expressions = _time_dependent_expressions(rhs_form, time)

    # Extract rhs expressions from form
    rhs_integrand = rhs_form.integrals()[0].integrand()
    rhs_exprs, v = extract_tested_expressions(rhs_integrand)
    vector_rhs = len(v.ufl_shape) > 0 and v.ufl_shape[0] > 1

    system_size = v.ufl_shape[0] if vector_rhs else 1

    # Fix for indexing of v for scalar expressions
    v = v if vector_rhs else [v]

    # Extract linear terms if not using generalized Rush Larsen
    if not generalized:
        linear_terms = _find_linear_terms(rhs_exprs, solution)
    else:
        linear_terms = [True for _ in range(system_size)]

    # Wrap the rhs expressions into a ufl vector type
    rhs_exprs = ufl.as_vector([rhs_exprs[i] for i in range(system_size)])
    rhs_jac = ufl.diff(rhs_exprs, solution)

    # Takes time!
    if vector_rhs:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[ind, ind]))
                          for ind in range(system_size)]
    else:
        diff_rhs_exprs = [expand_indices(expand_derivatives(rhs_jac[0]))]
        solution = [solution]

    ufl_stage_forms = []
    dolfin_stage_forms = []
    dt_stage_offsets = []

    # Stage solutions (3 per order rhs, linearized, and final step)
    # If 2nd order the final step for 1 step is a stage
    if order == 1:
        stage_solutions = []
        rl_ufl_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs, linear_terms,
                                        system_size, solution, None, dt, time, 1.0,
                                        0.0, v, DX, time_dep_expressions)
    elif order == 2:

        # Stage solution for order 2
        if vector_rhs:
            stage_solutions = [Function(solution.function_space(), name="y_1/2")]
        else:
            stage_solutions = [Function(solution[0].function_space(), name="y_1/2")]

        stage_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                       linear_terms, system_size,
                                       solution, None, dt, time, 0.5,
                                       0.0, v, DX,
                                       time_dep_expressions)

        rl_ufl_form = _rush_larsen_step(rhs_exprs, diff_rhs_exprs,
                                        linear_terms, system_size,
                                        solution, stage_solutions[0],
                                        dt, time, 1.0, 0.5, v, DX,
                                        time_dep_expressions)

        ufl_stage_forms.append([stage_form])
        dolfin_stage_forms.append([Form(stage_form)])

    # Get last stage form
    last_stage = Form(rl_ufl_form)

    human_form = "%srush larsen %s" % ("generalized " if generalized else "",
                                       str(order))

    return rhs_form, linear_terms, ufl_stage_forms, dolfin_stage_forms, last_stage, \
        stage_solutions, dt, dt_stage_offsets, human_form, None
def _butcher_scheme_generator_tlm(a, b, c, time, solution, rhs_form,
                                  perturbation):
    """Generates a list of forms and solutions for a given Butcher tableau

    *Arguments*
        a (2 dimensional numpy array)
            The a matrix of the Butcher tableau.
        b (1-2 dimensional numpy array)
            The b vector of the Butcher tableau. If b is 2 dimensional the
            scheme includes an error estimator and can be used in adaptive
            solvers.
        c (1 dimensional numpy array)
            The c vector the Butcher tableau.
        time (_Constant_)
            A Constant holding the time at the start of the time step
        solution (_Function_)
            The prognostic variable
        rhs_form (ufl.Form)
            A UFL form representing the rhs for a time differentiated equation
        perturbation (_Function_)
            The perturbation in the initial condition of the solution

    """

    a = _check_abc(a, b, c)
    size = a.shape[0]

    DX = _check_form(rhs_form)

    # Get test function
    arguments = rhs_form.arguments()
    # coefficients = rhs_form.coefficients()
    v = arguments[0]

    # Create time step
    dt = Constant(0.1)

    # rhs forms
    dolfin_stage_forms = []
    ufl_stage_forms = []

    # Stage solutions
    k = [Function(solution.function_space(), name="k_%d" % i) for i in range(size)]
    kdot = [Function(solution.function_space(), name="kdot_%d" % i)
            for i in range(size)]

    # Create the stage forms
    y_ = solution
    time_ = time
    time_dep_expressions = _time_dependent_expressions(rhs_form, time)
    zero_ = ufl.zero(*y_.ufl_shape)
    forward_forms = []
    stage_solutions = []
    jacobian_indices = []

    for i, ki in enumerate(k):

        # Check whether the stage is explicit
        explicit = a[i, i] == 0

        # Evaluation arguments for the ith stage
        evalargs = y_ + dt * sum([float(a[i, j]) * k[j]
                                  for j in range(i + 1)], zero_)
        time = time_ + dt * c[i]

        replace_dict = _replace_dict_time_dependent_expression(time_dep_expressions,
                                                               time_, dt, c[i])

        replace_dict[y_] = evalargs
        replace_dict[time_] = time
        stage_form = ufl.replace(rhs_form, replace_dict)

        forward_forms.append(stage_form)

        # The recomputation of the forward run:

        if explicit:
            stage_forms = [stage_form]
            jacobian_indices.append(-1)
        else:
            # Create a F=0 form and differentiate it
            stage_form_implicit = stage_form - ufl.inner(ki, v) * DX
            stage_forms = [stage_form_implicit, derivative(stage_form_implicit, ki)]
            jacobian_indices.append(0)

        ufl_stage_forms.append(stage_forms)
        dolfin_stage_forms.append([Form(form) for form in stage_forms])
        stage_solutions.append(ki)

        # And now the tangent linearisation:
        stage_form_tlm = safe_action(derivative(stage_form, y_), perturbation) + \
            sum([dt * float(a[i, j]) * safe_action(derivative(
                forward_forms[j], y_), kdot[j]) for j in range(i + 1)])
        if explicit:
            stage_forms_tlm = [stage_form_tlm]
            jacobian_indices.append(-1)
        else:
            # Create a F=0 form and differentiate it
            stage_form_tlm -= ufl.inner(kdot[i], v) * DX
            stage_forms_tlm = [stage_form_tlm, derivative(stage_form_tlm, kdot[i])]
            jacobian_indices.append(1)

        ufl_stage_forms.append(stage_forms_tlm)
        dolfin_stage_forms.append([Form(form) for form in stage_forms_tlm])
        stage_solutions.append(kdot[i])

    # Only one last stage
    if len(b.shape) == 1:
        last_stage = Form(ufl.inner(perturbation + sum(
            [dt * float(bi) * kdoti for bi, kdoti in zip(b, kdot)], zero_), v) * DX)
    else:
        raise Exception("Not sure what to do here")

    human_form = []
    for i in range(size):
        kterm = " + ".join("%sh*k_%s" % ("" if a[i, j] == 1.0 else
                                         "%s*" % a[i, j], j)
                           for j in range(size) if a[i, j] != 0)
        if c[i] in [0.0, 1.0]:
            cih = " + h" if c[i] == 1.0 else ""
        else:
            cih = " + %s*h" % c[i]

        kdotterm = " + ".join("%(a)sh*action(derivative(f(t_n%(cih)s, y_n + "
                              "%(kterm)s), kdot_%(i)s" %
                              {"a": ("" if a[i, j] == 1.0 else "%s*" % a[i, j], j),
                               "i": i,
                               "cih": cih,
                               "kterm": kterm}
                              for j in range(size) if a[i, j] != 0)

        if len(kterm) == 0:
            human_form.append("k_%(i)s = f(t_n%(cih)s, y_n)" % {"i": i, "cih": cih})
            human_form.append("kdot_%(i)s = action(derivative("
                              "f(t_n%(cih)s, y_n), y_n), ydot_n)" %
                              {"i": i, "cih": cih})
        else:
            human_form.append("k_%(i)s = f(t_n%(cih)s, y_n + %(kterm)s)" %
                              {"i": i, "cih": cih, "kterm": kterm})
            human_form.append("kdot_%(i)s = action(derivative(f(t_n%(cih)s, "
                              "y_n + %(kterm)s), y_n) + %(kdotterm)s" %
                              {"i": i, "cih": cih, "kterm": kterm, "kdotterm": kdotterm})

    parentheses = "(%s)" if np.sum(b > 0) > 1 else "%s"
    human_form.append("ydot_{n+1} = ydot_n + h*" + parentheses % (" + ".join(
        "%skdot_%s" % ("" if b[i] == 1.0 else "%s*" % b[i], i)
        for i in range(size) if b[i] > 0)))

    human_form = "\n".join(human_form)

    return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage, \
        stage_solutions, dt, human_form, perturbation
def _butcher_scheme_generator(a, b, c, time, solution, rhs_form):
    """Generates a list of forms and solutions for a given Butcher tableau

    *Arguments*
        a (2 dimensional numpy array)
            The a matrix of the Butcher tableau.
        b (1-2 dimensional numpy array)
            The b vector of the Butcher tableau. If b is 2 dimensional the
            scheme includes an error estimator and can be used in adaptive
            solvers.
        c (1 dimensional numpy array)
            The c vector the Butcher tableau.
        time (_Constant_)
            A Constant holding the time at the start of the time step
        solution (_Function_)
            The prognostic variable
        rhs_form (ufl.Form)
            A UFL form representing the rhs for a time differentiated equation

    """

    a = _check_abc(a, b, c)
    size = a.shape[0]

    DX = _check_form(rhs_form)

    # Get test function
    arguments = rhs_form.arguments()
    # coefficients = rhs_form.coefficients()
    v = arguments[0]

    # Create time step
    dt = Constant(0.1)

    # rhs forms
    dolfin_stage_forms = []
    ufl_stage_forms = []

    # Stage solutions
    k = [Function(solution.function_space(), name="k_%d" % i) for i in range(size)]

    jacobian_indices = []

    # Create the stage forms
    y_ = solution
    time_ = time
    time_dep_expressions = _time_dependent_expressions(rhs_form, time)
    zero_ = ufl.zero(*y_.ufl_shape)
    for i, ki in enumerate(k):

        # Check whether the stage is explicit
        explicit = a[i, i] == 0

        # Evaluation arguments for the ith stage
        evalargs = y_ + dt * sum([float(a[i, j]) * k[j]
                                  for j in range(i + 1)], zero_)
        time = time_ + dt * c[i]

        replace_dict = _replace_dict_time_dependent_expression(time_dep_expressions,
                                                               time_, dt, c[i])

        replace_dict[y_] = evalargs
        replace_dict[time_] = time
        stage_form = ufl.replace(rhs_form, replace_dict)

        if explicit:
            stage_forms = [stage_form]
            jacobian_indices.append(-1)
        else:
            # Create a F=0 form and differentiate it
            stage_form -= ufl.inner(ki, v) * DX
            stage_forms = [stage_form, derivative(stage_form, ki)]
            jacobian_indices.append(0)
        ufl_stage_forms.append(stage_forms)

        dolfin_stage_forms.append([Form(form) for form in stage_forms])

    # Only one last stage
    if len(b.shape) == 1:
        last_stage = Form(ufl.inner(y_ + sum([dt * float(bi) * ki for bi, ki in
                                              zip(b, k)], zero_), v) * DX)
    else:
        # FIXME: Add support for adaptivity in RKSolver and
        # MultiStageScheme
        last_stage = [Form(ufl.inner(y_ + sum([dt * float(bi) * ki for bi, ki in
                                               zip(b[0, :], k)], zero_), v) * DX),
                      Form(ufl.inner(y_ + sum([dt * float(bi) * ki for bi, ki in
                                               zip(b[1, :], k)], zero_), v) * DX)]

    # Create the Function holding the solution at end of time step
    # k.append(solution.copy())

    # Generate human form of MultiStageScheme
    human_form = []
    for i in range(size):
        kterm = " + ".join("%sh*k_%s" % ("" if a[i, j] == 1.0 else
                                         "%s*" % a[i, j], j)
                           for j in range(size) if a[i, j] != 0)
        if c[i] in [0.0, 1.0]:
            cih = " + h" if c[i] == 1.0 else ""
        else:
            cih = " + %s*h" % c[i]

        if len(kterm) == 0:
            human_form.append("k_%(i)s = f(t_n%(cih)s, y_n)" % {"i": i, "cih": cih})
        else:
            human_form.append("k_%(i)s = f(t_n%(cih)s, y_n + %(kterm)s)" %
                              {"i": i, "cih": cih, "kterm": kterm})

    parentheses = "(%s)" if np.sum(b > 0) > 1 else "%s"
    human_form.append("y_{n+1} = y_n + h*" + parentheses % (" + ".join(
        "%sk_%s" % ("" if b[i] == 1.0 else "%s*" % b[i], i)
        for i in range(size) if b[i] > 0)))

    human_form = "\n".join(human_form)

    return ufl_stage_forms, dolfin_stage_forms, jacobian_indices, last_stage, \
        k, dt, human_form, None
class DOLFINErrorControlGenerator(ErrorControlGenerator):
    """
    This class provides a realization of
    ffc.errorcontrol.errorcontrolgenerators.ErrorControlGenerator for
    use with UFL forms defined over DOLFIN objects
    """

    def __init__(self, F, M, u):
        """
        *Arguments*

            F (tuple or Form)
               tuple of (bilinear, linear) forms or linear form

            M (Form)
               functional or linear form

            u (Coefficient)
              The coefficient considered as the unknown.
        """
        ErrorControlGenerator.__init__(self, __import__("dolfin"), F, M, u)

    def initialize_data(self):
        """
        Extract required objects for defining error control
        forms. This will be stored and reused.
        """
        # Developer's note: The UFL-FFC-DOLFIN--PyDOLFIN toolchain for
        # error control is quite fine-tuned. In particular, the order
        # of coefficients in forms is (and almost must be) used for
        # their assignment. This means that the order in which these
        # coefficients are defined matters and should be considered
        # fixed.

        # Primal trial element space
        self._V = self.u.function_space()

        # Primal test space == Dual trial space
        Vhat = self.weak_residual.arguments()[0].function_space()

        # Discontinuous version of primal trial element space
        self._dV = tear(self._V)

        # Extract cell and geometric dimension
        mesh = self._V.mesh()
        dim = mesh.topology().dim()

        # Function representing improved dual
        E = increase_order(Vhat)
        self._Ez_h = Function(E)

        # Function representing cell bubble function
        B = FunctionSpace(mesh, "B", dim + 1)
        self._b_T = Function(B)
        self._b_T.vector()[:] = 1.0

        # Function representing strong cell residual
        self._R_T = Function(self._dV)

        # Function representing cell cone function
        C = FunctionSpace(mesh, "DG", dim)
        self._b_e = Function(C)

        # Function representing strong facet residual
        self._R_dT = Function(self._dV)

        # Function for discrete dual on primal test space
        self._z_h = Function(Vhat)

        # Piecewise constants for assembling indicators
        self._DG0 = FunctionSpace(mesh, "DG", 0)
Beispiel #20
0
def project(v, V=None, bcs=None, mesh=None,
            function=None,
            solver_type="lu",
            preconditioner_type="default",
            form_compiler_parameters=None):
    """Return projection of given expression *v* onto the finite element
    space *V*.

    *Arguments*
        v
            a :py:class:`Function <dolfin.functions.function.Function>` or
            an :py:class:`Expression <dolfin.functions.expression.Expression>`
        bcs
            Optional argument :py:class:`list of DirichletBC
            <dolfin.fem.bcs.DirichletBC>`
        V
            Optional argument :py:class:`FunctionSpace
            <dolfin.functions.functionspace.FunctionSpace>`
        mesh
            Optional argument :py:class:`mesh <dolfin.cpp.Mesh>`.
        solver_type
            see :py:func:`solve <dolfin.fem.solving.solve>` for options.
        preconditioner_type
            see :py:func:`solve <dolfin.fem.solving.solve>` for options.
        form_compiler_parameters
            see :py:class:`Parameters <dolfin.cpp.Parameters>` for more
            information.

    *Example of usage*

        .. code-block:: python

            v = Expression("sin(pi*x[0])")
            V = FunctionSpace(mesh, "Lagrange", 1)
            Pv = project(v, V)

        This is useful for post-processing functions or expressions
        which are not readily handled by visualization tools (such as
        for example discontinuous functions).

    """

    # Try figuring out a function space if not specified
    if V is None:
        # Create function space based on Expression element if trying
        # to project an Expression
        if isinstance(v, dolfin.function.expression.Expression):
            if mesh is not None and isinstance(mesh, cpp.mesh.Mesh):
                V = FunctionSpace(mesh, v.ufl_element())
            # else:
            #     cpp.dolfin_error("projection.py",
            #                      "perform projection",
            #                      "Expected a mesh when projecting an Expression")
        else:
            # Otherwise try extracting function space from expression
            V = _extract_function_space(v, mesh)

    # Projection into a MultiMeshFunctionSpace
    if isinstance(V, MultiMeshFunctionSpace):

        # Create the measuresum of uncut and cut-cells
        dX = ufl.dx() + ufl.dC()

        # Define variational problem for projection
        w = TestFunction(V)
        Pv = TrialFunction(V)
        a = ufl.inner(w, Pv) * dX
        L = ufl.inner(w, v) * dX

        # Assemble linear system
        A = assemble_multimesh(a, form_compiler_parameters=form_compiler_parameters)
        b = assemble_multimesh(L, form_compiler_parameters=form_compiler_parameters)

        # Solve linear system for projection
        if function is None:
            function = MultiMeshFunction(V)
        cpp.la.solve(A, function.vector(), b, solver_type, preconditioner_type)

        return function

    # Ensure we have a mesh and attach to measure
    if mesh is None:
        mesh = V.mesh()
    dx = ufl.dx(mesh)

    # Define variational problem for projection
    w = TestFunction(V)
    Pv = TrialFunction(V)
    a = ufl.inner(w, Pv) * dx
    L = ufl.inner(w, v) * dx

    # Assemble linear system
    A, b = assemble_system(a, L, bcs=bcs,
                           form_compiler_parameters=form_compiler_parameters)

    # Solve linear system for projection
    if function is None:
        function = Function(V)
    cpp.la.solve(A, function.vector(), b, solver_type, preconditioner_type)

    return function
Beispiel #21
0
def project(v, V=None, func_degree=None, bcs=None, mesh=None,
            function=None,
            solver_type="lu",
            preconditioner_type="default",
            form_compiler_parameters=None):
    """
    This function is a modification of FEniCS's built-in project function that adopts the :math:`r^2dr`
    measure as opposed to the standard Cartesian :math:`dx` measure.

    For documentation and usage, see the 
    `original module <https://bitbucket.org/fenics-project/dolfin/src/master/python/dolfin/fem/projection.py>`_.

    .. note:: Note the extra argument func_degree: this is used to interpolate the :math:`r^2` 
              Expression to the same degree as used in the definition of the Trial and Test function
              spaces.

    """

    # Try figuring out a function space if not specified
    if V is None:
        # Create function space based on Expression element if trying
        # to project an Expression
        if isinstance(v, Expression):
            # FIXME: Add handling of cpp.MultiMesh
            if mesh is not None and isinstance(mesh, cpp.mesh.Mesh):
                V = FunctionSpace(mesh, v.ufl_element())
            # else:
            #     cpp.dolfin_error("projection.py",
            #                      "perform projection",
            #                      "Expected a mesh when projecting an Expression")
        else:
            # Otherwise try extracting function space from expression
            V = _extract_function_space(v, mesh)



    # Ensure we have a mesh and attach to measure
    if mesh is None:
        mesh = V.mesh()
    dx = ufl.dx(mesh)

    # Define variational problem for projection
    
    # DS: HERE IS WHERE I MODIFY
    r2 = Expression('pow(x[0],2)', degree=func_degree)
    
    w = TestFunction(V)
    Pv = TrialFunction(V)
    a = ufl.inner(w, Pv) * r2 * dx
    L = ufl.inner(w, v) * r2 * dx

    # Assemble linear system
    A, b = assemble_system(a, L, bcs=bcs,
                           form_compiler_parameters=form_compiler_parameters)

    # Solve linear system for projection
    if function is None:
        function = Function(V)
    cpp.la.solve(A, function.vector(), b, solver_type, preconditioner_type)

    return function
 def part(self, i, deepcopy=False):
     f = Function(self._cpp_object.part(i, deepcopy))
     f.rename(self._cpp_object.name(), self._cpp_object.label())
     return f
Beispiel #23
0
class DOLFINErrorControlGenerator(ErrorControlGenerator):
    """
    This class provides a realization of
    ffc.errorcontrol.errorcontrolgenerators.ErrorControlGenerator for
    use with UFL forms defined over DOLFIN objects
    """
    def __init__(self, F, M, u):
        """
        *Arguments*

            F (tuple or Form)
               tuple of (bilinear, linear) forms or linear form

            M (Form)
               functional or linear form

            u (Coefficient)
              The coefficient considered as the unknown.
        """
        ErrorControlGenerator.__init__(self, __import__("dolfin"), F, M, u)

    def initialize_data(self):
        """
        Extract required objects for defining error control
        forms. This will be stored and reused.
        """
        # Developer's note: The UFL-FFC-DOLFIN--PyDOLFIN toolchain for
        # error control is quite fine-tuned. In particular, the order
        # of coefficients in forms is (and almost must be) used for
        # their assignment. This means that the order in which these
        # coefficients are defined matters and should be considered
        # fixed.

        # Primal trial element space
        self._V = self.u.function_space()

        # Primal test space == Dual trial space
        Vhat = self.weak_residual.arguments()[0].function_space()

        # Discontinuous version of primal trial element space
        self._dV = tear(self._V)

        # Extract cell and geometric dimension
        mesh = self._V.mesh()
        dim = mesh.topology().dim()

        # Function representing improved dual
        E = increase_order(Vhat)
        self._Ez_h = Function(E)

        # Function representing cell bubble function
        B = FunctionSpace(mesh, "B", dim + 1)
        self._b_T = Function(B)
        self._b_T.vector()[:] = 1.0

        # Function representing strong cell residual
        self._R_T = Function(self._dV)

        # Function representing cell cone function
        C = FunctionSpace(mesh, "DG", dim)
        self._b_e = Function(C)

        # Function representing strong facet residual
        self._R_dT = Function(self._dV)

        # Function for discrete dual on primal test space
        self._z_h = Function(Vhat)

        # Piecewise constants for assembling indicators
        self._DG0 = FunctionSpace(mesh, "DG", 0)
Beispiel #24
0
def errornorm(u, uh, norm_type="l2", degree_rise=3, mesh=None):
    """
    Compute and return the error :math:`e = u - u_h` in the given norm.

    *Arguments*
        u, uh
            :py:class:`Functions <dolfin.functions.function.Function>`
        norm_type
            Type of norm. The :math:`L^2` -norm is default.
            For other norms, see :py:func:`norm <dolfin.fem.norms.norm>`.
        degree_rise
            The number of degrees above that of u_h used in the
            interpolation; i.e. the degree of piecewise polynomials used
            to approximate :math:`u` and :math:`u_h` will be the degree
            of :math:`u_h` + degree_raise.
        mesh
            Optional :py:class:`Mesh <dolfin.cpp.Mesh>` on
            which to compute the error norm.

    In simple cases, one may just define

    .. code-block:: python

        e = u - uh

    and evalute for example the square of the error in the :math:`L^2` -norm by

    .. code-block:: python

        assemble(e**2*dx(mesh))

    However, this is not stable w.r.t. round-off errors considering that
    the form compiler may expand(#) the expression above to::

        e**2*dx = u**2*dx - 2*u*uh*dx + uh**2*dx

    and this might get further expanded into thousands of terms for
    higher order elements. Thus, the error will be evaluated by adding
    a large number of terms which should sum up to something close to
    zero (if the error is small).

    This module computes the error by first interpolating both
    :math:`u` and :math:`u_h` to a common space (of high accuracy),
    then subtracting the two fields (which is easy since they are
    expressed in the same basis) and then evaluating the integral.

    (#) If using the tensor representation optimizations.
    The quadrature represenation does not suffer from this problem.
    """

    # Check argument
    # if not isinstance(u, cpp.function.GenericFunction):
    #     cpp.dolfin_error("norms.py",
    #                      "compute error norm",
    #                      "Expecting a Function or Expression for u")
    # if not isinstance(uh, cpp.function.Function):
    #     cpp.dolfin_error("norms.py",
    #                      "compute error norm",
    #                      "Expecting a Function for uh")

    # Get mesh
    if isinstance(u, cpp.function.Function) and mesh is None:
        mesh = u.function_space().mesh()
    if isinstance(uh, cpp.function.Function) and mesh is None:
        mesh = uh.function_space().mesh()
    if hasattr(uh, "_cpp_object") and mesh is None:
        mesh = uh._cpp_object.function_space().mesh()
    if hasattr(u, "_cpp_object") and mesh is None:
        mesh = u._cpp_object.function_space().mesh()
    if mesh is None:
        cpp.dolfin_error("norms.py",
                         "compute error norm",
                         "Missing mesh")

    # Get rank
    if not u.ufl_shape == uh.ufl_shape:
        cpp.dolfin_error("norms.py",
                         "compute error norm",
                         "Value shapes don't match")
    shape = u.ufl_shape
    rank = len(shape)

    # Check that uh is associated with a finite element
    if uh.ufl_element().degree() is None:
        cpp.dolfin_error("norms.py",
                         "compute error norm",
                         "Function uh must have a finite element")

    # Degree for interpolation space. Raise degree with respect to uh.
    degree = uh.ufl_element().degree() + degree_rise

    # Check degree of 'exact' solution u
    degree_u = u.ufl_element().degree()
    if degree_u is not None and degree_u < degree:
        cpp.warning("Degree of exact solution may be inadequate for accurate result in errornorm.")

    # Create function space
    if rank == 0:
        V = FunctionSpace(mesh, "Discontinuous Lagrange", degree)
    elif rank == 1:
        V = VectorFunctionSpace(mesh, "Discontinuous Lagrange", degree,
                                dim=shape[0])
    elif rank > 1:
        V = TensorFunctionSpace(mesh, "Discontinuous Lagrange", degree,
                                shape=shape)

    # Interpolate functions into finite element space
    pi_u = interpolate(u, V)
    pi_uh = interpolate(uh, V)

    # Compute the difference
    e = Function(V)
    e.assign(pi_u)
    e.vector().axpy(-1.0, pi_uh.vector())

    # Compute norm
    return norm(e, norm_type=norm_type, mesh=mesh)
Beispiel #25
0
 def part(self, i, deepcopy=False):
     f = Function(self._cpp_object.part(i, deepcopy))
     f.rename(self._cpp_object.name(), self._cpp_object.label())
     return f