Пример #1
0
    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],
        )
Пример #3
0
    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
Пример #4
0
                                  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