Example #1
0
def derivative_ex(dirichl_space, neumann_space, ep_in, ep_ex, kappa,
                  operator_assembler):
    """
    Construct the system matrix and RHS grid functions using derivative formulation with interior values.
    """
    phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    dph_id = sparse.identity(neumann_space, neumann_space, neumann_space)
    ep = ep_ex / ep_in

    dF = laplace.double_layer(dirichl_space,
                              dirichl_space,
                              dirichl_space,
                              assembler=operator_assembler)
    dP = modified_helmholtz.double_layer(dirichl_space,
                                         dirichl_space,
                                         dirichl_space,
                                         kappa,
                                         assembler=operator_assembler)
    B = 1 / ep * dF - dP

    F = laplace.single_layer(neumann_space,
                             dirichl_space,
                             dirichl_space,
                             assembler=operator_assembler)
    P = modified_helmholtz.single_layer(neumann_space,
                                        dirichl_space,
                                        dirichl_space,
                                        kappa,
                                        assembler=operator_assembler)
    A = F - P

    ddF = laplace.hypersingular(dirichl_space,
                                neumann_space,
                                neumann_space,
                                assembler=operator_assembler)
    ddP = modified_helmholtz.hypersingular(dirichl_space,
                                           neumann_space,
                                           neumann_space,
                                           kappa,
                                           assembler=operator_assembler)
    D = 1 / ep * (ddP - ddF)

    dF0 = laplace.adjoint_double_layer(neumann_space,
                                       neumann_space,
                                       neumann_space,
                                       assembler=operator_assembler)
    dP0 = modified_helmholtz.adjoint_double_layer(neumann_space,
                                                  neumann_space,
                                                  neumann_space,
                                                  kappa,
                                                  assembler=operator_assembler)
    C = dF0 - 1.0 / ep * dP0

    A_sys = bempp.api.BlockedOperator(2, 2)
    A_sys[0, 0] = (0.5 * (1.0 + (1.0 / ep)) * phi_id) + B
    A_sys[0, 1] = -A
    A_sys[1, 0] = D
    A_sys[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - C

    return A_sys
Example #2
0
def alpha_beta_single_blocked_operator(dirichl_space, neumann_space, ep_in,
                                       ep_ex, kappa, alpha, beta,
                                       operator_assembler):
    dlp_in = laplace.double_layer(dirichl_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    slp_in = laplace.single_layer(neumann_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    hlp_in = laplace.hypersingular(dirichl_space,
                                   neumann_space,
                                   neumann_space,
                                   assembler=operator_assembler)
    adlp_in = laplace.adjoint_double_layer(neumann_space,
                                           neumann_space,
                                           neumann_space,
                                           assembler=operator_assembler)

    dlp_out = modified_helmholtz.double_layer(dirichl_space,
                                              dirichl_space,
                                              dirichl_space,
                                              kappa,
                                              assembler=operator_assembler)
    slp_out = modified_helmholtz.single_layer(neumann_space,
                                              dirichl_space,
                                              dirichl_space,
                                              kappa,
                                              assembler=operator_assembler)
    hlp_out = modified_helmholtz.hypersingular(dirichl_space,
                                               neumann_space,
                                               neumann_space,
                                               kappa,
                                               assembler=operator_assembler)
    adlp_out = modified_helmholtz.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler=operator_assembler)

    phi_identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    dph_identity = sparse.identity(neumann_space, neumann_space, neumann_space)

    ep = ep_ex / ep_in

    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = (-0.5 * (1 + alpha)) * phi_identity + (alpha * dlp_out) - dlp_in
    A[0, 1] = slp_in - ((alpha / ep) * slp_out)
    A[1, 0] = hlp_in - (beta * hlp_out)
    A[1,
      1] = (-0.5 *
            (1 +
             (beta / ep))) * dph_identity + adlp_in - ((beta / ep) * adlp_out)

    return A
Example #3
0
def juffer(dirichl_space, neumann_space, ep_in, ep_ex, kappa,
           operator_assembler):
    phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    dph_id = sparse.identity(neumann_space, neumann_space, neumann_space)
    ep = ep_ex / ep_in

    dF = laplace.double_layer(dirichl_space,
                              dirichl_space,
                              dirichl_space,
                              assembler=operator_assembler)
    dP = modified_helmholtz.double_layer(dirichl_space,
                                         dirichl_space,
                                         dirichl_space,
                                         kappa,
                                         assembler=operator_assembler)
    L1 = (ep * dP) - dF

    F = laplace.single_layer(neumann_space,
                             dirichl_space,
                             dirichl_space,
                             assembler=operator_assembler)
    P = modified_helmholtz.single_layer(neumann_space,
                                        dirichl_space,
                                        dirichl_space,
                                        kappa,
                                        assembler=operator_assembler)
    L2 = F - P

    ddF = laplace.hypersingular(dirichl_space,
                                neumann_space,
                                neumann_space,
                                assembler=operator_assembler)
    ddP = modified_helmholtz.hypersingular(dirichl_space,
                                           neumann_space,
                                           neumann_space,
                                           kappa,
                                           assembler=operator_assembler)
    L3 = ddP - ddF

    dF0 = laplace.adjoint_double_layer(neumann_space,
                                       neumann_space,
                                       neumann_space,
                                       assembler=operator_assembler)
    dP0 = modified_helmholtz.adjoint_double_layer(neumann_space,
                                                  neumann_space,
                                                  neumann_space,
                                                  kappa,
                                                  assembler=operator_assembler)
    L4 = dF0 - ((1.0 / ep) * dP0)

    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = (0.5 * (1.0 + ep) * phi_id) - L1
    A[0, 1] = (-1.0) * L2
    A[1, 0] = L3  # Sign change due to bempp definition
    A[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4

    return A
Example #4
0
def discrete_coefficient_projection(space, new_space):
    """Return a discrete operator that projects coefficients from space into new_space."""

    from bempp.api.operators.boundary.sparse import identity
    from bempp.api.assembly.discrete_boundary_operator import InverseSparseDiscreteBoundaryOperator

    ident1 = identity(space, new_space, new_space).weak_form()
    ident2 = identity(new_space, new_space, new_space).weak_form()

    return InverseSparseDiscreteBoundaryOperator(ident2) * ident1
Example #5
0
def lu(dirichl_space, neumann_space, ep_in, ep_ex, kappa, operator_assembler):
    dlp_in = laplace.double_layer(dirichl_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    slp_in = laplace.single_layer(neumann_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    hlp_in = laplace.hypersingular(dirichl_space,
                                   neumann_space,
                                   neumann_space,
                                   assembler=operator_assembler)
    adlp_in = laplace.adjoint_double_layer(neumann_space,
                                           neumann_space,
                                           neumann_space,
                                           assembler=operator_assembler)

    dlp_ex = modified_helmholtz.double_layer(dirichl_space,
                                             dirichl_space,
                                             dirichl_space,
                                             kappa,
                                             assembler=operator_assembler)
    slp_ex = modified_helmholtz.single_layer(neumann_space,
                                             dirichl_space,
                                             dirichl_space,
                                             kappa,
                                             assembler=operator_assembler)
    hlp_ex = modified_helmholtz.hypersingular(dirichl_space,
                                              neumann_space,
                                              neumann_space,
                                              kappa,
                                              assembler=operator_assembler)
    adlp_ex = modified_helmholtz.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler=operator_assembler)

    phi_identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    dph_identity = sparse.identity(neumann_space, neumann_space, neumann_space)

    ep = ep_ex / ep_in

    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = (0.5 *
               (1 + (1.0 / ep))) * phi_identity - dlp_ex + (1.0 / ep) * dlp_in
    A[0, 1] = slp_ex - slp_in
    A[1, 0] = (1.0 / ep) * hlp_ex - (1.0 / ep) * hlp_in
    A[1,
      1] = (0.5 * (1 +
                   (1.0 / ep))) * dph_identity + (1.0 / ep) * adlp_ex - adlp_in

    return A
    def test_mass_matrix_of_barycentric_space_agrees_with_non_barycentric_space(self):

        from bempp.api.operators.boundary.sparse import identity

        barycentric_ident = identity(self._bary_space, self._bary_space, self._bary_space).weak_form().sparse_operator
        ident = identity(self._space, self._space, self._space).weak_form().sparse_operator

        diff = barycentric_ident - ident

        self.assertAlmostEqual(diff.max(), 0, 15)
        self.assertAlmostEqual(diff.min(), 0, 15)
Example #7
0
def muller_internal(dirichl_space, neumann_space, ep_in, ep_ex, kappa,
                    operator_assembler):
    dlp_in = laplace.double_layer(dirichl_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    slp_in = laplace.single_layer(neumann_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    hlp_in = laplace.hypersingular(dirichl_space,
                                   neumann_space,
                                   neumann_space,
                                   assembler=operator_assembler)
    adlp_in = laplace.adjoint_double_layer(neumann_space,
                                           neumann_space,
                                           neumann_space,
                                           assembler=operator_assembler)

    dlp_ex = modified_helmholtz.double_layer(dirichl_space,
                                             dirichl_space,
                                             dirichl_space,
                                             kappa,
                                             assembler=operator_assembler)
    slp_ex = modified_helmholtz.single_layer(neumann_space,
                                             dirichl_space,
                                             dirichl_space,
                                             kappa,
                                             assembler=operator_assembler)
    hlp_ex = modified_helmholtz.hypersingular(dirichl_space,
                                              neumann_space,
                                              neumann_space,
                                              kappa,
                                              assembler=operator_assembler)
    adlp_ex = modified_helmholtz.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler=operator_assembler)

    phi_identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    dph_identity = sparse.identity(neumann_space, neumann_space, neumann_space)

    ep = ep_ex / ep_in

    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = phi_identity + dlp_in - dlp_ex
    A[0, 1] = -slp_in + ((1.0 / ep) * slp_ex)
    A[1, 0] = -hlp_in + (ep * hlp_ex)
    A[1, 1] = dph_identity - adlp_in + adlp_ex

    return A
Example #8
0
def juffer(dirichl_space, neumann_space, q, x_q, ep_in, ep_ex, kappa):
    from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz

    phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    dph_id = sparse.identity(neumann_space, neumann_space, neumann_space)
    ep = ep_ex / ep_in

    dF = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space)
    dP = modified_helmholtz.double_layer(dirichl_space, dirichl_space,
                                         dirichl_space, kappa)
    L1 = (ep * dP) - dF

    F = laplace.single_layer(neumann_space, dirichl_space, dirichl_space)
    P = modified_helmholtz.single_layer(neumann_space, dirichl_space,
                                        dirichl_space, kappa)
    L2 = F - P

    ddF = laplace.hypersingular(dirichl_space, neumann_space, neumann_space)
    ddP = modified_helmholtz.hypersingular(dirichl_space, neumann_space,
                                           neumann_space, kappa)
    L3 = ddP - ddF

    dF0 = laplace.adjoint_double_layer(neumann_space, neumann_space,
                                       neumann_space)
    dP0 = modified_helmholtz.adjoint_double_layer(neumann_space, neumann_space,
                                                  neumann_space, kappa)
    L4 = dF0 - ((1.0 / ep) * dP0)

    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = (0.5 * (1.0 + ep) * phi_id) - L1
    A[0, 1] = (-1.0) * L2
    A[1, 0] = L3  # Cambio de signo por definicion de bempp
    A[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4

    @bempp.api.real_callable
    def d_green_func(x, n, domain_index, result):
        nrm = np.sqrt((x[0] - x_q[:, 0])**2 + (x[1] - x_q[:, 1])**2 +
                      (x[2] - x_q[:, 2])**2)

        const = -1. / (4. * np.pi * ep_in)
        result[:] = const * np.sum(q * np.dot(x - x_q, n) / (nrm**3))

    @bempp.api.real_callable
    def green_func(x, n, domain_index, result):
        nrm = np.sqrt((x[0] - x_q[:, 0])**2 + (x[1] - x_q[:, 1])**2 +
                      (x[2] - x_q[:, 2])**2)

        result[:] = np.sum(q / nrm) / (4. * np.pi * ep_in)

    rhs_1 = bempp.api.GridFunction(dirichl_space, fun=green_func)
    rhs_2 = bempp.api.GridFunction(dirichl_space, fun=d_green_func)

    return A, rhs_1, rhs_2
Example #9
0
    def _compute_burton_miller(self):

        from bempp.api.operators.boundary.sparse import identity
        from bempp.api.operators.boundary.helmholtz import double_layer
        from bempp.api.operators.boundary.helmholtz import hypersingular
        from bempp.api.operators.boundary.helmholtz import osrc_ntd

        space = self._space
        wavenumber = self._wavenumber

        if self._id is None:
            self._id = identity(space, space, space)

        if self._double_layer is None:
            self._double_layer = double_layer(space, space,
                                              space, wavenumber)

        if self._hypersingular is None:
            self._hypersingular = hypersingular(space, space,
                                                space, wavenumber, use_slp=True)

        if self._coupling == 'osrc' and self._osrc is None:
            self._osrc = osrc_ntd(space, wavenumber)

        if self._burton_miller_operator is None:
            if self._coupling == 'osrc':
                self._burton_miller_operator = (
                    .5 * self._id - self._double_layer - self._osrc * self._hypersingular)
            else:
                self._burton_miller_operator = (
                    .5 * self._id - self._double_layer - (1j / self._wavenumber) * self._hypersingular)
Example #10
0
def direct(dirichl_space, neumann_space, q, x_q, ep_in, ep_out, kappa): 
    
    from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz
    identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    slp_in   = laplace.single_layer(neumann_space, dirichl_space, dirichl_space)
    dlp_in   = laplace.double_layer(dirichl_space, dirichl_space, dirichl_space)
    slp_out  = modified_helmholtz.single_layer(neumann_space, dirichl_space, dirichl_space, kappa)
    dlp_out  = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dirichl_space, kappa)

    # Matrix Assembly
    blocked = bempp.api.BlockedOperator(2, 2)
    blocked[0, 0] = 0.5*identity + dlp_in
    blocked[0, 1] = -slp_in
    blocked[1, 0] = 0.5*identity - dlp_out
    blocked[1, 1] = (ep_in/ep_out)*slp_out
    #A = blocked.strong_form()
    A = blocked
   
    
    @bempp.api.real_callable
    def charges_fun(x, n, domain_index, result):
        nrm = np.sqrt((x[0]-x_q[:,0])**2 + (x[1]-x_q[:,1])**2 + (x[2]-x_q[:,2])**2)
        aux = np.sum(q/nrm)
        
        result[0] = aux/(4*np.pi*ep_in)
        
    @bempp.api.real_callable
    def zero(x, n, domain_index, result):
        result[0] = 0

    rhs_1 = bempp.api.GridFunction(dirichl_space, fun=charges_fun)
    rhs_2 = bempp.api.GridFunction(neumann_space, fun=zero)

    return A, rhs_1, rhs_2
Example #11
0
    def strong_form(self, mode='simple'):

        if not self._fill_complete():
            raise ValueError("Each row and column must have at least one operator")


        if mode=='full':
            discrete_operator = BlockedDiscreteOperator(self._m, self._n)

            for i in range(self._m):
                for j in range(self._n):
                    if self._operators[i, j] is not None:
                        discrete_operator[i, j] = self._operators[i, j].strong_form()
            return discrete_operator           

        elif mode=='simple':
            from bempp.api import InverseSparseDiscreteBoundaryOperator
            from bempp.api.operators.boundary.sparse import identity

            blocked = BlockedDiscreteOperator(self.ndims[0], self.ndims[0])

            for i in range(self.ndims[0]):
                op = None
                for j in range(self.ndims[1]):
                    if self[i, j] is not None:
                        op = self[i, j]
                        break

                blocked[i, i] = InverseSparseDiscreteBoundaryOperator(
                        identity(op.range, op.dual_to_range, 
                            op.dual_to_range).weak_form())
            return blocked * self.weak_form() 
        else:
            raise ValueError("Unknown value for 'mode'. Allowed values are 'simple' and 'full'")
Example #12
0
    def projections(self, dual_space=None):
        """

        Compute the vector of projections onto the
        given dual space.

        Parameters
        ----------
        dual_space : bempp.api.space.Space
            A representation of the dual space. If not specified
            then space == dual_space is assumed (optional).

        Returns
        -------
        out : np.ndarray
            A vector of projections onto the dual space.

        """

        from bempp.api.operators.boundary.sparse import identity

        if dual_space is None:
            dual_space = self.space

        ident = identity(self.space, self.space, dual_space).weak_form()
        return ident * self.coefficients
Example #13
0
    def _weak_form_impl(self):
        from bempp.api.operators.boundary.sparse import identity
        from bempp.api.operators.boundary.sparse import laplace_beltrami
        from bempp.api import ZeroBoundaryOperator
        from bempp.api import InverseSparseDiscreteBoundaryOperator

        import numpy as np

        space = self._space

        # Get the operators
        mass = identity(space, space, space, parameters=self._parameters).weak_form()
        stiff = laplace_beltrami(space, space, space, parameters=self._parameters).weak_form()

        # Compute damped wavenumber

        bbox = self._space.grid.bounding_box
        rad = np.linalg.norm(bbox[1, :] - bbox[0, :]) / 2
        dk = self._wave_number + 1j * 0.4 * self._wave_number ** (1.0 / 3.0) * rad ** (-2.0 / 3.0)

        # Get the Pade coefficients

        c0, alpha, beta = _pade_coeffs(self._npade, self._theta)

        # Now put all operators together

        term = ZeroBoundaryOperator(space, space, space).weak_form()

        for i in range(self._npade):
            term -= (alpha[i] / (dk ** 2) * stiff *
                     InverseSparseDiscreteBoundaryOperator(
                         mass - beta[i] / (dk ** 2) * stiff))
        result = 1j * self._wave_number * (c0 * mass + term * mass)

        return result
def block_diagonal_precon_direct_external(dirichl_space,
                                          neumann_space,
                                          ep_in,
                                          ep_ex,
                                          kappa,
                                          permuted_rows=False):
    from scipy.sparse import diags, bmat
    from scipy.sparse.linalg import aslinearoperator
    from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz

    # block-diagonal preconditioner
    identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    identity_diag = identity.weak_form().to_sparse().diagonal()
    slp_in_diag = laplace.single_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        assembler="only_diagonal_part").weak_form().get_diagonal()
    dlp_in_diag = laplace.double_layer(
        dirichl_space,
        dirichl_space,
        dirichl_space,
        assembler="only_diagonal_part").weak_form().get_diagonal()
    slp_out_diag = modified_helmholtz.single_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler="only_diagonal_part").weak_form().get_diagonal()
    dlp_out_diag = modified_helmholtz.double_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler="only_diagonal_part").weak_form().get_diagonal()

    if permuted_rows:
        diag11 = 0.5 * identity_diag + dlp_in_diag
        diag12 = -(ep_ex / ep_in) * slp_in_diag
        diag21 = 0.5 * identity_diag - dlp_out_diag
        diag22 = slp_out_diag
    else:
        diag11 = 0.5 * identity_diag - dlp_out_diag
        diag12 = slp_out_diag
        diag21 = 0.5 * identity_diag + dlp_in_diag
        diag22 = -(ep_ex / ep_in) * slp_in_diag

    d_aux = 1 / (diag22 - diag21 * diag12 / diag11)
    diag11_inv = 1 / diag11 + 1 / diag11 * diag12 * d_aux * diag21 / diag11
    diag12_inv = -1 / diag11 * diag12 * d_aux
    diag21_inv = -d_aux * diag21 / diag11
    diag22_inv = d_aux

    block_mat_precond = bmat([[diags(diag11_inv),
                               diags(diag12_inv)],
                              [diags(diag21_inv),
                               diags(diag22_inv)]]).tocsr()

    return aslinearoperator(block_mat_precond)
Example #15
0
    def _weak_form_impl(self):

        from bempp.api.operators.boundary.sparse import identity
        from .discrete_boundary_operator import InverseSparseDiscreteBoundaryOperator

        projected_weak_form = self._operator.weak_form()

        if self._dual_to_range is not None:
            ident = identity(self._operator.dual_to_range, self._dual_to_range, self._dual_to_range).weak_form()
            projected_weak_form = ident * InverseSparseDiscreteBoundaryOperator(
                identity(self._operator.dual_to_range, self._operator.dual_to_range,
                         self._operator.dual_to_range).weak_form()) * projected_weak_form

        if self._domain is not None:
            from bempp.api.space.projection import discrete_coefficient_projection

            projected_weak_form *= discrete_coefficient_projection(self._domain, self._operator.domain)

        return projected_weak_form
Example #16
0
def laplace_beltrami_eigenpairs(space, k=6, tol=1E-5):
    """Compute k Laplace Beltrami eigenpairs over a given space."""
    from scipy.sparse.linalg import eigs
    from bempp.api.operators.boundary.sparse import \
        laplace_beltrami
    from bempp.api.operators.boundary.sparse import \
        identity

    operator = laplace_beltrami(space, space, space)
    ident = identity(space, space, space)

    return eigs(operator, M=ident, sigma=0, tol=tol, k=k)
def direct(dirichl_space, neumann_space, assembler, q, x_q):
    """
    Construct the system matrix and RHS grid functions using direct formulation.
    """
    ep_in = PARAMS.ep_in
    ep_ex = PARAMS.ep_ex
    kappa = PARAMS.kappa

    identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    slp_in = laplace.single_layer(neumann_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=assembler)
    dlp_in = laplace.double_layer(dirichl_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=assembler)
    slp_out = modified_helmholtz.single_layer(neumann_space,
                                              dirichl_space,
                                              dirichl_space,
                                              kappa,
                                              assembler=assembler)
    dlp_out = modified_helmholtz.double_layer(dirichl_space,
                                              dirichl_space,
                                              dirichl_space,
                                              kappa,
                                              assembler=assembler)

    A_sys = bempp.api.BlockedOperator(2, 2)
    A_sys[0, 0] = 0.5 * identity + dlp_in
    A_sys[0, 1] = -slp_in
    A_sys[1, 0] = 0.5 * identity - dlp_out
    A_sys[1, 1] = (ep_in / ep_ex) * slp_out

    @bempp.api.callable(vectorized=True)
    def rhs1_fun(x, n, domain_index, result):
        import exafmm.laplace as _laplace
        sources = _laplace.init_sources(x_q, q)
        targets = _laplace.init_targets(x.T)
        fmm = _laplace.LaplaceFmm(p=10, ncrit=500, filename='.rhs.tmp')
        tree = _laplace.setup(sources, targets, fmm)
        values = _laplace.evaluate(tree, fmm)
        os.remove('.rhs.tmp')
        result[:] = values[:, 0] / ep_in

    @bempp.api.real_callable
    def rhs2_fun(x, n, domain_index, result):
        result[0] = 0

    rhs1 = bempp.api.GridFunction(dirichl_space, fun=rhs1_fun)
    rhs2 = bempp.api.GridFunction(neumann_space, fun=rhs2_fun)

    return A_sys, rhs1, rhs2
Example #18
0
def alpha_beta_external(dirichl_space, neumann_space, ep_in, ep_ex, kappa,
                        alpha, beta, operator_assembler):
    phi_id = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    dph_id = sparse.identity(neumann_space, neumann_space, neumann_space)

    ep = ep_ex / ep_in

    A_in = laplace_multitrace(dirichl_space, neumann_space, operator_assembler)
    A_ex = mod_helm_multitrace(dirichl_space, neumann_space, kappa,
                               operator_assembler)

    D = bempp.api.BlockedOperator(2, 2)
    D[0, 0] = alpha * phi_id
    D[0, 1] = 0.0 * phi_id
    D[1, 0] = 0.0 * phi_id
    D[1, 1] = beta * dph_id

    E_1 = bempp.api.BlockedOperator(2, 2)
    E_1[0, 0] = phi_id
    E_1[0, 1] = 0.0 * phi_id
    E_1[1, 0] = 0.0 * phi_id
    E_1[1, 1] = dph_id * ep

    F = bempp.api.BlockedOperator(2, 2)
    F[0, 0] = alpha * phi_id
    F[0, 1] = 0.0 * phi_id
    F[1, 0] = 0.0 * phi_id
    F[1, 1] = dph_id * (beta / ep)

    Id = bempp.api.BlockedOperator(2, 2)
    Id[0, 0] = phi_id
    Id[0, 1] = 0.0 * phi_id
    Id[1, 0] = 0.0 * phi_id
    Id[1, 1] = dph_id

    interior_projector = ((0.5 * Id) + A_in) * E_1
    scaled_exterior_projector = D * ((0.5 * Id) - A_ex)
    A = (((0.5 * Id) + A_in) * E_1) + (D * ((0.5 * Id) - A_ex)) - D - E_1

    return A, A_in, A_ex, interior_projector, scaled_exterior_projector
Example #19
0
    def __init__(self, space, dual_space=None, fun=None, coefficients=None,
                 projections=None, parameters=None):

        import bempp.api
        import numpy as np

        if space is None:
            raise ValueError("space must not be None.")

        if parameters is None:
            parameters = bempp.api.global_parameters

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

        self._coefficients = None
        self._space = space
        self._parameters = parameters

        if coefficients is not None:
            self.coefficients = coefficients

        if fun is not None:
            from bempp.core.assembly.function_projector import calculate_projection

            if dual_space is not None:
                proj_space = dual_space
            else:
                proj_space = self.space

            projections = calculate_projection(parameters, fun, proj_space._impl)

        if projections is not None:
            np_proj = 1.0 * np.asarray(projections).squeeze()
            if np_proj.ndim > 1:
                raise ValueError("'projections' must be a 1-d array.")

            from bempp.api.assembly import InverseSparseDiscreteBoundaryOperator

            if dual_space is not None:
                proj_space = dual_space
            else:
                proj_space = self.space

            from bempp.api.operators.boundary.sparse import identity
            inv_ident = InverseSparseDiscreteBoundaryOperator(\
                    identity(self.space, self.space, proj_space).weak_form())


            self._coefficients = inv_ident * projections
Example #20
0
def block_diagonal(dirichl_space, neumann_space, A):
    """
    Compute the block-diagonal preconditioner for system matrix A.
    Suitable for direct formulation.
    """
    ep_in = PARAMS.ep_in
    ep_ex = PARAMS.ep_ex
    kappa = PARAMS.kappa

    identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    identity_diag = identity.weak_form().A.diagonal()
    slp_in_diag = laplace.single_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        assembler="only_diagonal_part").weak_form().A
    dlp_in_diag = laplace.double_layer(
        dirichl_space,
        dirichl_space,
        dirichl_space,
        assembler="only_diagonal_part").weak_form().A
    slp_out_diag = modified_helmholtz.single_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A
    dlp_out_diag = modified_helmholtz.double_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A

    diag11 = .5 * identity_diag + dlp_in_diag
    diag12 = -slp_in_diag
    diag21 = .5 * identity_diag - dlp_out_diag
    diag22 = (ep_in / ep_ex) * slp_out_diag

    d_aux = 1 / (diag22 - diag21 * diag12 / diag11)
    diag11_inv = 1 / diag11 + 1 / diag11 * diag12 * d_aux * diag21 / diag11
    diag12_inv = -1 / diag11 * diag12 * d_aux
    diag21_inv = -d_aux * diag21 / diag11
    diag22_inv = d_aux

    block_mat_precond = bmat([[diags(diag11_inv),
                               diags(diag12_inv)],
                              [diags(diag21_inv),
                               diags(diag22_inv)]]).tocsr()

    return aslinearoperator(block_mat_precond)
Example #21
0
    def _weak_form_impl(self):

        from bempp.api.operators.boundary.sparse import identity

        from .discrete_boundary_operator import ZeroDiscreteBoundaryOperator
        from .discrete_boundary_operator import InverseSparseDiscreteBoundaryOperator

        discrete_op = ZeroDiscreteBoundaryOperator(self.dual_to_range.global_dof_count,
                                                   self.domain.global_dof_count)

        test_inverse = InverseSparseDiscreteBoundaryOperator(
            identity(self._test_local_ops[0].domain, self._kernel_op.domain,
                     self._kernel_op.dual_to_range,
                     parameters=self._parameters).weak_form())
        trial_inverse = InverseSparseDiscreteBoundaryOperator(identity(self._kernel_op.domain, self._kernel_op.domain,
                                                                       self._trial_local_ops[0].dual_to_range,
                                                                       parameters=self._parameters).weak_form())

        kernel_discrete_op = self._kernel_op.weak_form()
        for i in range(self._number_of_ops):
            discrete_op += (self._test_local_ops[i].weak_form() * test_inverse * kernel_discrete_op *
                            trial_inverse * self._trial_local_ops[i].weak_form())
        return discrete_op
Example #22
0
    def strong_form(self):
        """Return a discrete operator  that maps into the range space."""
        if self._range_map is None:

            # This is the most frequent case and we cache the mass
            # matrix from the space object.
            if self.range == self.dual_to_range:
                self._range_map = self.dual_to_range.inverse_mass_matrix()
            else:
                from bempp.api.assembly.discrete_boundary_operator import (
                    InverseSparseDiscreteBoundaryOperator, )
                from bempp.api.operators.boundary.sparse import identity

                self._range_map = InverseSparseDiscreteBoundaryOperator(
                    identity(self.range, self.range,
                             self.dual_to_range).weak_form())

        return self._range_map * self.weak_form()
Example #23
0
    def _weak_form_impl(self):
        from bempp.api.operators.boundary.sparse import identity
        from bempp.api.operators.boundary.sparse import laplace_beltrami
        from bempp.api import ZeroBoundaryOperator
        from bempp.api import InverseSparseDiscreteBoundaryOperator

        space = self._space

        # Get the operators
        mass = identity(space, space, space,
                        parameters=self._parameters).weak_form()
        stiff = laplace_beltrami(space,
                                 space,
                                 space,
                                 parameters=self._parameters).weak_form()

        # Compute damped wavenumber

        if self._damped_wavenumber is None:
            bbox = self._space.grid.bounding_box
            rad = _np.linalg.norm(bbox[1, :] - bbox[0, :]) / 2
            dk = self._wave_number + 1j * 0.4 * \
                self._wave_number ** (1.0 / 3.0) * rad ** (-2.0 / 3.0)
        else:
            dk = self._damped_wavenumber

        # Get the Pade coefficients

        c0, alpha, beta = _pade_coeffs(self._npade, self._theta)

        # Now put all operators together

        term = ZeroBoundaryOperator(space, space, space).weak_form()

        for i in range(self._npade):
            term -= (alpha[i] / (dk**2) * stiff *
                     InverseSparseDiscreteBoundaryOperator(mass - beta[i] /
                                                           (dk**2) * stiff))
        result = 1. / (1j * self._wave_number) * (
            mass * InverseSparseDiscreteBoundaryOperator(mass - 1. /
                                                         (dk**2) * stiff) *
            (c0 * mass + term * mass))

        return result
Example #24
0
    def strong_form(self, recompute=False):
        """Return a discrete operator  that maps into the range space.

        Parameters
        ----------
        recompute : bool
            Usually the strong form is cached. If this parameter is set to
            `true` the strong form is recomputed.
        """
        if recompute is True:
            self._range_map = None

        if self._range_map is None:
            from bempp.api.operators.boundary.sparse import identity
            from bempp.api.assembly import InverseSparseDiscreteBoundaryOperator

            self._range_map = InverseSparseDiscreteBoundaryOperator( \
                identity(self.range, self.range, self.dual_to_range).weak_form())

        return self._range_map * self.weak_form(recompute)
Example #25
0
def direct(dirichl_space,
           neumann_space,
           ep_in,
           ep_out,
           kappa,
           operator_assembler,
           permute_rows=False):
    identity = sparse.identity(dirichl_space, dirichl_space, dirichl_space)
    slp_in = laplace.single_layer(neumann_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    dlp_in = laplace.double_layer(dirichl_space,
                                  dirichl_space,
                                  dirichl_space,
                                  assembler=operator_assembler)
    slp_out = modified_helmholtz.single_layer(neumann_space,
                                              dirichl_space,
                                              dirichl_space,
                                              kappa,
                                              assembler=operator_assembler)
    dlp_out = modified_helmholtz.double_layer(dirichl_space,
                                              dirichl_space,
                                              dirichl_space,
                                              kappa,
                                              assembler=operator_assembler)

    A = bempp.api.BlockedOperator(2, 2)
    if permute_rows:  #Use permuted rows formulation
        A[0, 0] = 0.5 * identity - dlp_out
        A[0, 1] = (ep_in / ep_out) * slp_out
        A[1, 0] = 0.5 * identity + dlp_in
        A[1, 1] = -slp_in
    else:  #Normal direct formulation
        A[0, 0] = 0.5 * identity + dlp_in
        A[0, 1] = -slp_in
        A[1, 0] = 0.5 * identity - dlp_out
        A[1, 1] = (ep_in / ep_out) * slp_out

    return A
Example #26
0
    def test_dolfin_p1_identity_equals_bempp_p1_identity(self):

        import dolfin
        from bempp.api.fenics_interface import fenics_to_bempp_trace_data
        from bempp.api.fenics_interface import FenicsOperator

        mesh = dolfin.UnitCubeMesh(5, 5, 5)
        V = dolfin.FunctionSpace(mesh, "CG", 1)

        space, trace_matrix = fenics_to_bempp_trace_data(V)

        u = dolfin.TestFunction(V)
        v = dolfin.TrialFunction(V)
        a = dolfin.inner(u, v) * dolfin.ds
        fenics_mass = FenicsOperator(a).weak_form().sparse_operator
        actual = trace_matrix * fenics_mass * trace_matrix.transpose()

        from bempp.api.operators.boundary import sparse

        expected = sparse.identity(space, space, space).weak_form().sparse_operator
        diff = actual - expected
        self.assertAlmostEqual(np.max(np.abs(diff.data)), 0)