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
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()