Exemple #1
0
    def __init__(
        self,
        source_points,
        target_points,
        mode,
        wavenumber=None,
        depth=4,
        expansion_order=5,
        ncrit=400,
        precision="double",
        singular_correction=None,
    ):
        """Instantiate an Exafmm session."""
        import bempp.api
        import os
        from bempp.api.utils.helpers import create_unique_id

        global FMM_TMP_DIR

        if FMM_TMP_DIR is None:
            FMM_TMP_DIR = os.path.join(os.getcwd(), ".exafmm")
            if not os.path.isdir(FMM_TMP_DIR):
                try:
                    os.mkdir(FMM_TMP_DIR)
                except:
                    raise FileExistsError(
                        f"A file with the name {FMM_TMP_DIR} exists. Please delete it."
                    )

        for _ in range(10):
            tmp_name = create_unique_id() + ".tmp"
            fname = os.path.join(FMM_TMP_DIR, tmp_name)
            if not os.path.exists(fname):
                break
        else:
            raise FileExistsError(
                "Could not create temporary filename for Exafmm.")

        self._fname = fname
        self._singular_correction = singular_correction

        self._source_points = source_points
        self._target_points = target_points
        self._mode = mode

        if mode == "laplace":
            self._kernel_parameters = _np.array([], dtype="float64")
        elif mode == "helmholtz":
            self._kernel_parameters = _np.array(
                [_np.real(wavenumber),
                 _np.imag(wavenumber)], dtype="float64")
        elif mode == "modified_helmholtz":
            self._kernel_parameters = _np.array([wavenumber], dtype="float64")

        with bempp.api.Timer(message="Initialising Exafmm."):

            if mode == "laplace":
                import exafmm.laplace

                self._module = exafmm.laplace

                sources = exafmm.laplace.init_sources(
                    source_points,
                    _np.zeros(len(source_points), dtype=_np.float64))

                targets = exafmm.laplace.init_targets(target_points)

                self._fmm = exafmm.laplace.LaplaceFmm(expansion_order,
                                                      ncrit,
                                                      filename=fname)
                self._tree = exafmm.laplace.setup(sources, targets, self._fmm)

            elif mode == "helmholtz":
                import exafmm.helmholtz

                self._module = exafmm.helmholtz

                sources = exafmm.helmholtz.init_sources(
                    source_points,
                    _np.zeros(len(source_points), dtype=_np.float64))

                targets = exafmm.helmholtz.init_targets(target_points)

                self._fmm = exafmm.helmholtz.HelmholtzFmm(expansion_order,
                                                          ncrit,
                                                          wavenumber,
                                                          filename=fname)
                self._tree = exafmm.helmholtz.setup(sources, targets,
                                                    self._fmm)

            elif mode == "modified_helmholtz":
                import exafmm.modified_helmholtz

                self._module = exafmm.modified_helmholtz

                sources = exafmm.modified_helmholtz.init_sources(
                    source_points,
                    _np.zeros(len(source_points), dtype=_np.float64))

                targets = exafmm.modified_helmholtz.init_targets(target_points)

                self._fmm = exafmm.modified_helmholtz.ModifiedHelmholtzFmm(
                    expansion_order, ncrit, wavenumber, filename=fname)
                self._tree = exafmm.modified_helmholtz.setup(
                    sources, targets, self._fmm)
Exemple #2
0
    def __init__(
        self,
        grid,
        codomain_dimension,
        order,
        shapeset,
        local2global_map,
        global2local_map,
        local_multipliers,
        identifier,
        is_localised,
        support,
        normal_multipliers,
        requires_dof_transformation,
        is_barycentric,
        barycentric_representation,
        dof_transformation,
        numba_evaluator,
        numba_surface_gradient,
        collocation_points,
    ):
        """Initialize the space."""
        from .shapesets import Shapeset
        from scipy.sparse import coo_matrix
        from bempp.api.utils.helpers import create_unique_id

        self._grid = grid
        self._grid_id = self._grid.id
        self._codomain_dimension = codomain_dimension
        self._order = order
        self._shapeset = Shapeset(shapeset)
        self._local2global_map = local2global_map
        self._global2local_map = global2local_map
        self._local_multipliers = local_multipliers
        self._identifier = identifier
        self._support = support
        self._requires_dof_transformation = requires_dof_transformation
        self._is_barycentric = is_barycentric
        self._barycentric_representation = barycentric_representation
        self._dof_transformation = dof_transformation
        self._numba_evaluate = numba_evaluator
        self._numba_surface_gradient = numba_surface_gradient
        self._normal_multipliers = normal_multipliers
        self._number_of_support_elements = _np.count_nonzero(self._support)
        self._support_elements = _np.flatnonzero(
            self._support).astype("uint32")
        self._collocation_points = collocation_points

        self._id = create_unique_id()
        self._hash_string = None
        self._color_map = None
        self._mass_matrix = None
        self._inverse_mass_matrix = None
        self._sorted_indices = None
        self._indexptr = None
        self._is_scattered = False

        # Number of dofs for the space defined over the grid
        # This is different from the global_dof_count, which
        # takes the dof transformation matrix into account.

        number_of_grid_dofs = 1 + _np.max(self._local2global_map)
        self._grid_dof_count = number_of_grid_dofs

        # Number of shape functions
        nshape_fun = self.number_of_shape_functions

        # Generate map to localised space

        self._map_to_localised_space = coo_matrix(
            (
                self._local_multipliers[self._support].ravel(),
                (
                    _np.arange(nshape_fun * self._number_of_support_elements),
                    self._local2global_map[self._support].ravel(),
                ),
            ),
            shape=(nshape_fun * self._number_of_support_elements,
                   self._grid_dof_count),
            dtype="float64",
        ).tocsr()

        # Generate map to full grid
        # This works like the map to the localised grid.
        # But if the space is defined over a subgrid it
        # maps to the localised space on the full grid.

        self._map_to_full_grid = coo_matrix(
            (
                self._local_multipliers[self._support].ravel(),
                (
                    nshape_fun * _np.repeat(self._support_elements, nshape_fun)
                    + _np.tile(_np.arange(nshape_fun),
                               self._number_of_support_elements),
                    self._local2global_map[self._support].ravel(),
                ),
            ),
            shape=(nshape_fun * self._grid.number_of_elements,
                   number_of_grid_dofs),
            dtype="float64",
        ).tocsr()

        # Create localised space.

        # First check if space is already a localised space.
        # For this we need that all multipliers are 1 and all global
        # dofs are each only associated with one local dof.

        if is_localised:
            self._localised_space = self
        else:
            # Create a new localised space
            self._localised_space = make_localised_space(self)
Exemple #3
0
    def __init__(self,
                 vertices,
                 elements,
                 domain_indices=None,
                 grid_id=None,
                 scatter=True):
        """Create a grid from a vertices and an elements array."""
        from bempp.api import log
        from bempp.api.utils import pool
        from bempp.api.utils.helpers import create_unique_id

        self._vertices = None
        self._elements = None
        self._domain_indices = None
        self._edges = None
        self._element_edges = None
        self._edge_adjacency = None
        self._vertex_adjacency = None
        self._element_neighbors = None
        self._vertex_on_boundary = None
        self._edge_on_boundary = None
        self._edge_neighbors = None
        self._vertex_neighbors = None
        self._barycentric_grid = None
        if grid_id:
            self._id = grid_id
        else:
            self._id = create_unique_id()

        self._volumes = None
        self._normals = None
        self._jacobians = None
        self._jacobian_inverse_transposed = None
        self._diameters = None
        self._integration_elements = None
        self._centroids = None

        self._device_interfaces = {}

        self._element_to_vertex_matrix = None
        self._element_to_element_matrix = None

        self._normalize_and_assign_input(vertices, elements, domain_indices)
        self._enumerate_edges()

        self._get_element_adjacency_for_edges_and_vertices()
        self._compute_geometric_quantities()

        self._compute_boundary_information()

        self._compute_edge_neighbors()
        self._compute_vertex_neighbors()

        self._grid_data = GridData(self._vertices, self._elements, self._edges,
                                   self._element_edges, self._volumes,
                                   self._normals, self._jacobians,
                                   self._jacobian_inverse_transposed,
                                   self._diameters, self._integration_elements,
                                   self._centroids, self._domain_indices,
                                   self._vertex_on_boundary)
        self._is_scattered = False

        if scatter and pool.is_initialised() and not pool.is_worker():
            self._scatter()
        if not pool.is_worker():
            log((
                f"Created grid with id {self.id}. Elements: {self.number_of_elements}. "
                +
                f"Edges: {self.number_of_edges}. Vertices: {self.number_of_vertices}"
            ))