コード例 #1
0
ファイル: sparse.py プロジェクト: Lyu721/bempp-cl
def sigma_identity(
    domain,
    range_,
    dual_to_range,
    parameters=None,
    device_interface=None,
    precision=None,
):
    """
    Evaluate the sigma identity operator. 

    For Galerkin methods this operator is equivalent to .5 * identity. For
    collocation methods the value may differ from .5 on piecewise smooth
    domains.
    """
    from bempp.api.utils.helpers import assign_parameters

    parameters = assign_parameters(parameters)

    if parameters.assembly.discretization_type == "galerkin":
        return 0.5 * identity(
            domain,
            range_,
            dual_to_range,
            parameters=parameters,
            device_interface=device_interface,
            precision=precision,
        )
    elif parameters.assembly.discretization_type == "collocation":
        raise ValueError("Not yet implemented.")
コード例 #2
0
    def __init__(
        self,
        space,
        dual_space=None,
        fun=None,
        coefficients=None,
        projections=None,
        parameters=None,
    ):
        """
        Construct a grid function.

        A grid function can be initialized in three different ways.

        1. By providing a Python callable. Any Python callable of the
           following form is valid.::

                callable(x,n,domain_index,result)

           Here, x, n, and result are all numpy arrays. x contains the current
           evaluation point, n the associated outward normal direction and
           result is a numpy array that will store the result of the Python
           callable. The variable domain_index stores the index of the
           subdomain on which x lies (default 0). This makes it possible to
           define different functions for different subdomains.

           The following example defines input data that is the inner product
           of the coordinate x with the normal direction n.::

                fun(x,n,domain_index,result):
                    result[0] =  np.dot(x,n)

        2. By providing a vector of coefficients at the nodes. This is
           preferable if the coefficients of the data are coming from an
           external code.

        3. By providing a vector of projection data and a corresponding
           dual space.

        Parameters
        ----------
        space : bempp.api.space.Space
            The space over which the GridFunction is defined.
        dual_space : bempp.api.Space
            A representation of the dual space. If not specified
            then space == dual_space is assumed (optional).
        fun : callable
            A Python function from which the GridFunction is constructed
            (optional).
        coefficients : np.ndarray
            A 1-dimensional array with the coefficients of the GridFunction
            at the interpolatoin points of the space (optional).
        projections : np.ndarray
            A 1-dimensional array with the projections of the GridFunction
            onto a dual space (optional).
        parameters : bempp.api.ParameterList
            A ParameterList object used for the assembly of
            the GridFunction (optional).

        Notes
        -----
        * Only one of projections, coefficients, or fun is allowed as
          parameter.

        Examples
        --------
        To create a GridFunction from a Python callable my_fun use

        >>> grid_function = GridFunction(space, fun=my_fun)

        To create a GridFunction from a vector of coefficients coeffs use

        >>> grid_function = GridFunction(space,coefficients=coeffs)

        To create a GridFunction from a vector of projections proj use

        >>> grid_function = GridFunction(
                space,dual_space=dual_space, projections=proj)

        """
        from bempp.api.utils.helpers import assign_parameters
        from bempp.api.space.space import return_compatible_representation

        self._space = None
        self._dual_space = None
        self._coefficients = None
        self._grid_coefficients = None
        self._projections = None
        self._representation = None

        if dual_space is None:
            dual_space = space

        self._space, self._dual_space = space, dual_space

        # Now check that space and dual are defined over same grid
        # with the same normal directions. If one space is barycentric,
        # need to take this into account.

        comp_domain, comp_dual = return_compatible_representation(space, dual_space)
        self._comp_domain = comp_domain
        self._comp_dual = comp_dual

        if (
            not comp_domain.grid == comp_dual.grid
            or not _np.all(
                comp_domain.normal_multipliers == comp_dual.normal_multipliers
            )
        ):
            raise ValueError(
                "Space and dual space must be defined on the "
                + "same grid with same normal directions."
            )

        self._parameters = assign_parameters(parameters)

        if sum(1 for e in [fun, coefficients, projections] if e is not None) != 1:
            raise ValueError(
                "Exactly one of 'fun', 'coefficients' or 'projections' "
                + "must be nonzero."
            )

        if coefficients is not None:
            self._coefficients = coefficients
            self._representation = "primal"

        if projections is not None:
            self._projections = projections
            self._representation = "dual"

        if fun is not None:
            from bempp.api.integration.triangle_gauss import rule

            points, weights = rule(self._parameters.quadrature.regular)

            if fun.bempp_type == "real":
                dtype = "float64"
            else:
                dtype = "complex128"

            grid_projections = _np.zeros(comp_dual.grid_dof_count, dtype=dtype)

            # Create a Numba callable from the function

            _project_function(
                fun,
                comp_dual.grid.data,
                comp_dual.support_elements,
                comp_dual.local2global,
                comp_dual.local_multipliers,
                comp_dual.normal_multipliers,
                comp_dual.numba_evaluate,
                comp_dual.shapeset.evaluate,
                points,
                weights,
                comp_domain.codomain_dimension,
                grid_projections,
            )

            self._projections = comp_dual.dof_transformation.T @ grid_projections

            self._representation = "dual"
コード例 #3
0
ファイル: boundary_operator.py プロジェクト: Lyu721/bempp-cl
    def __init__(
        self,
        grid_function,
        domain,
        range_,
        dual_to_range,
        parameters=None,
        mode="component",
    ):
        """
        Initialize the multiplication operator.

        This class initializes a multiplication operator mult from a given
        grid function g, such that the result h = mult @ f for a given
        grid function f is the result of projecting g * f onto the 
        space `dual_to_range`.

        The number of components of the shapesets of grid_function.space,
        domain and dual_to_range must be compatible. For example, grid_function
        could be scalar, and space and dual_to_range vectorial with 3 components.


        Parameters
        ----------
        grid_function : GridFunction object
            The grid function object from which the multiplication operator is
            built. It needs to allow representation in primal (coordinate) form.
        domain : Space object
            The domain space of the operator.
        range_ : Space object
            The range space of the operator
        dual_to_range : Space object
            The dual space on which the result of the multiplication is projected.
        parameters : Parameters object
            The parameters associated with this operator.
        mode : string
            Either 'component' or 'inner'. If mode is 'component' (default) then
            the multiplication is componentwise at each quadrature point. Hence,
            if the shapesets of grid_function.space and domain.space both have
            dimension 3, then the result of the multiplication is also of dimension
            3, and the dual_to_range space needs to be compatible to it. If mode
            is 'inner', then inner product is taken of the values of grid_function
            at the quadrature point and the basis functions in space at the
            quadrature points.

        """
        from bempp.api.utils.helpers import assign_parameters

        self._mode = mode
        self._grid_fun = grid_function

        # Check compatibility

        dim = grid_function.component_count
        dual_dim = dual_to_range.codomain_dimension
        dimensions_compatible = False
        if mode == "component":
            dimensions_compatible = dim == domain.codomain_dimension and dim == dual_dim
        elif mode == "inner":
            dimensions_compatible = dim == domain.codomain_dimension and dual_dim == 1
        else:
            raise ValueError(
                "Unknown value for 'mode'. Allowed: 'component', 'inner'")
        if not dimensions_compatible:
            raise ValueError("Incompatible codomain dimensions.")

        super().__init__(domain, range_, dual_to_range,
                         assign_parameters(parameters))