def test_taylor_values(dim, degree):
    """
    Check that the Lagrange -> Taylor projection gives the correct Taylor values
    """
    if dim == 2:
        mesh = dolfin.UnitSquareMesh(4, 4)
    else:
        mesh = dolfin.UnitCubeMesh(2, 2, 2)

    # Setup Lagrange function with given derivatives and constants
    V = dolfin.FunctionSpace(mesh, 'DG', degree)
    u = dolfin.Function(V)
    if dim == 2:
        coeffs = [1, 2, -3.0] if degree == 1 else [1, 2, -3.0, -2.5, 4.2, -1.0]
    else:
        coeffs = ([1, 2, -3.0, 2.5] if degree == 1 else
                  [1, 2, -3.0, 2.5, -1.3, 4.2, -1.0, -4.2, 2.66, 3.14])
    make_taylor_func(u, coeffs)

    # Convert to Taylor
    t = dolfin.Function(V)
    lagrange_to_taylor(u, t)

    # Check that the target values are obtained
    dm = V.dofmap()
    vals = t.vector().get_local()
    for cell in dolfin.cells(mesh):
        cell_dofs = dm.cell_dofs(cell.index())
        cell_vals = vals[cell_dofs]
        assert all(abs(cell_vals - coeffs) < 1e-13)
def test_taylor_projections_2D(degree):
    """
    Check that the 2D Lagrange -> Taylor -> Lagrange projection is an identity projection
    """
    mesh = dolfin.UnitSquareMesh(4, 4)
    V = dolfin.FunctionSpace(mesh, 'DG', degree)

    # Setup Lagrange function with random data
    f1 = dolfin.Function(V)
    N = f1.vector().local_size()
    f1.vector().set_local(numpy.random.rand(N))

    # Convert to Taylor representation
    f2 = dolfin.Function(V)
    lagrange_to_taylor(f1, f2)

    # Create a new Lagrange function from the Taylor representation
    f3 = dolfin.Function(V)
    taylor_to_lagrange(f2, f3)

    error = dolfin.errornorm(f1, f3, degree_rise=0)
    assert error < 1e-15
Esempio n. 3
0
    def run(self, use_weak_bcs=None):
        """
        Perform slope limiting of DG Lagrange functions
        """
        # No limiter needed for piecewice constant functions
        if self.degree == 0:
            return
        timer = df.Timer('Ocellaris HierarchalTaylorSlopeLimiter')

        # Update the Taylor function with the current Lagrange values
        lagrange_to_taylor(self.phi, self.taylor)
        taylor_arr = get_local(self.taylor)
        alpha_arrs = [alpha.vector().get_local() for alpha in self.alpha_funcs]

        # Get global bounds, see SlopeLimiterBase.set_initial_field()
        global_min, global_max = self.global_bounds

        # Update previous field values Taylor functions
        if self.phi_old is not None:
            lagrange_to_taylor(self.phi_old, self.taylor_old)
            taylor_arr_old = get_local(self.taylor_old)
        else:
            taylor_arr_old = taylor_arr

        # Get updated boundary conditions
        weak_vals = None
        use_weak_bcs = self.use_weak_bcs if use_weak_bcs is None else use_weak_bcs
        if use_weak_bcs:
            weak_vals = self.phi.vector().get_local()
        boundary_dof_type, boundary_dof_value = self.boundary_conditions.get_bcs(
            weak_vals)

        # Run the limiter implementation
        if self.use_cpp:
            self._run_cpp(
                taylor_arr,
                taylor_arr_old,
                alpha_arrs,
                global_min,
                global_max,
                boundary_dof_type,
                boundary_dof_value,
            )
        elif self.degree == 1 and self.ndim == 2:
            self._run_dg1(
                taylor_arr,
                taylor_arr_old,
                alpha_arrs[0],
                global_min,
                global_max,
                boundary_dof_type,
                boundary_dof_value,
            )
        elif self.degree == 2 and self.ndim == 2:
            self._run_dg2(
                taylor_arr,
                taylor_arr_old,
                alpha_arrs[0],
                alpha_arrs[1],
                global_min,
                global_max,
                boundary_dof_type,
                boundary_dof_value,
            )
        else:
            raise OcellarisError(
                'Unsupported dimension for Python version of the HierarchalTaylor limiter',
                'Only 2D is supported',
            )

        # Update the Lagrange function with the limited Taylor values
        set_local(self.taylor, taylor_arr, apply='insert')
        taylor_to_lagrange(self.taylor, self.phi)

        # Enforce boundary conditions
        if self.enforce_boundary_conditions:
            has_dbc = boundary_dof_type == self.boundary_conditions.BC_TYPE_DIRICHLET
            vals = self.phi.vector().get_local()
            vals[has_dbc] = boundary_dof_value[has_dbc]
            self.phi.vector().set_local(vals)
            self.phi.vector().apply('insert')

        # Update the secondary output arrays, alphas
        for alpha, alpha_arr in zip(self.alpha_funcs, alpha_arrs):
            alpha.vector().set_local(alpha_arr)
            alpha.vector().apply('insert')

        timer.stop()