def __init__(self, simulation, func_name): """ The given function space is for the function you will be convected. The convection scheme itself uses a discontinuous Trace zeroth order element to represent the blending function The blending function is a downstream blending factor (0=upstream, 1=downstream) The alpha function is the scalar function to be advected """ self.simulation = simulation self.func_name = func_name self.alpha_function = simulation.data[func_name] Va = self.alpha_function.function_space() self.alpha_dofmap = Va.dofmap().dofs() # Blending function self.mesh = Va.mesh() Vb = dolfin.FunctionSpace(self.mesh, 'DGT', 0) self.blending_function = dolfin.Function(Vb) # Mesh size self.ncells = self.mesh.num_cells() self.nfacets = self.mesh.num_facets() # Input for C++ code self.cpp_mod = load_module('linear_convection') self.cpp_inp = initialize_cpp_input(simulation, self.cpp_mod, Va, Vb)
def reconstruct(self): """ Reconstruct the gradient in each cell center TODO: handle boundary conditions for boundary cells, right now the boundary cell gradients are only influenced by the cell neighbours """ # Initialize the least squares gradient reconstruction matrices # needed to calculate the gradient of a DG0 field if not self.reconstruction_initialized: self.initialize() assert self.alpha_function.ufl_element().degree() == 0 if not self.use_cpp: # Pure Python version reconstructor = _reconstruct_gradient else: # Faster C++ version cpp_mod = load_module('linear_convection') reconstructor = cpp_mod.reconstruct_gradient # Run the gradient reconstruction reconstructor( self.alpha_function._cpp_object, self.num_neighbours, self.neighbours, self.lstsq_matrices, self.lstsq_inv_matrices, [gi._cpp_object for gi in self.gradient], )
def __init__(self, mesh, V, V0, use_cpp=True, trust_robin_dval=True): """ This class stores the connectivity and dof maps necessary to perform slope limiting in an efficient manner in the C++ code """ # Find the neighbour cells for each dof num_neighbours, neighbours = get_dof_neighbours(V) self.num_neighbours = num_neighbours self.neighbours = neighbours # Fast access to cell dofs dm, dm0 = V.dofmap(), V0.dofmap() indices = list(range(mesh.num_cells())) self.cell_dofs_V = numpy.array([dm.cell_dofs(i) for i in indices], dtype=numpy.intc) self.cell_dofs_V0 = numpy.array([dm0.cell_dofs(i) for i in indices], dtype=numpy.intc) tdim = mesh.topology().dim() self.num_cells_owned = mesh.topology().ghost_offset(tdim) # Find vertices for each cell mesh.init(tdim, 0) connectivity_CV = mesh.topology()(tdim, 0) cell_vertices = [] for ic in range(mesh.num_cells()): cell_vertices.append(connectivity_CV(ic)) self.cell_vertices = numpy.array(cell_vertices, dtype=numpy.intc) self.vertex_coordinates = mesh.coordinates() assert self.vertex_coordinates.shape[1] == tdim # Call the C++ method that makes the arrays available to the C++ limiter if use_cpp: self.cpp_mod = load_module('hierarchical_taylor') self.cpp_obj = self.cpp_mod.SlopeLimiterInput() self.cpp_obj.set_arrays( self.num_cells_owned, num_neighbours, neighbours, self.cell_dofs_V, self.cell_dofs_V0, self.cell_vertices, self.vertex_coordinates, ) self.cpp_obj.trust_robin_dval = trust_robin_dval
V, layers=0, dof_region_marks=drm, named_boundaries=skip_boundaries) if 'all' not in skip_boundaries: bcs.activate() # Construct the limiter limiter_class = get_slope_limiter(method) limiter = limiter_class( simulation, phi_name=phi_name, phi=phi, skip_cells=skip_cells, boundary_conditions=bcs, limiter_input=inp, ) if plot_exceedance: for func in limiter.additional_plot_funcs: simulation.io.add_extra_output_function(func) return limiter from ocellaris.cpp import load_module LocalMaximaMeasurer = load_module('measure_local_maxima').LocalMaximaMeasurer from . import hierarchical_taylor