예제 #1
0
def test_laplace_single_layer():
    """Test dense assembler for the Laplace operators."""
    grid = bempp.api.shapes.regular_sphere(2)
    space = function_space(grid, "DP", 0)

    op1 = laplace.single_layer(space, space, space, assembler="dense")
    op2 = laplace.single_layer(space, space, space, assembler="fmm")

    fun = bempp.api.GridFunction(
        space, coefficients=np.random.rand(space.global_dof_count)
    )

    assert np.allclose((op1 * fun).coefficients, (op2 * fun).coefficients)

    bempp.api.clear_fmm_cache()
예제 #2
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
예제 #3
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
예제 #4
0
    def _compute_near_field_matrix(self):
        """Compute the near-field matrix."""
        import bempp.api
        from bempp.api.operators.boundary.laplace import single_layer
        from bempp.core.near_field_assembler import NearFieldAssembler
        from scipy.sparse.linalg import aslinearoperator

        with bempp.api.Timer() as t:
            near_field_op = NearFieldAssembler(
                self, bempp.api.default_device(), bempp.api.DEVICE_PRECISION_CPU
            ).as_linear_operator()
        bempp.api.log(f"Near field setup time: {t.interval}")

        singular_interactions = single_layer(
            self._domain,
            self._domain,
            self._dual_to_range,
            assembler="only_singular_part",
        ).weak_form()

        source_op = self._source_transform
        target_op = self._target_transform

        self._near_field_matrix = (
            target_op @ near_field_op @ source_op + singular_interactions
        )
예제 #5
0
def test_laplace_single_layer_p0_p1(default_parameters, helpers, precision,
                                    device_interface):
    """Test dense assembler for the slp with disc. p0/p1 basis."""
    from bempp.api.operators.boundary.laplace import single_layer
    from bempp.api import function_space

    grid = helpers.load_grid("sphere")

    space0 = function_space(grid, "DP", 0)
    space1 = function_space(grid, "DP", 1)

    discrete_op = single_layer(
        space1,
        space1,
        space0,
        assembler="dense",
        precision=precision,
        device_interface=device_interface,
        parameters=default_parameters,
    ).weak_form()

    expected = helpers.load_npy_data("laplace_single_layer_boundary_p0_dp1")
    _np.testing.assert_allclose(discrete_op.A,
                                expected,
                                rtol=helpers.default_tolerance(precision))
예제 #6
0
def laplace_multitrace_scaled(dirichl_space, neumann_space, scaling_factors,
                              operator_assembler):
    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = scaling_factors[0][0] * (-1.0) * laplace.double_layer(
        dirichl_space,
        dirichl_space,
        dirichl_space,
        assembler=operator_assembler)
    A[0, 1] = scaling_factors[0][1] * laplace.single_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        assembler=operator_assembler)
    A[1, 0] = scaling_factors[1][0] * laplace.hypersingular(
        dirichl_space,
        neumann_space,
        neumann_space,
        assembler=operator_assembler)
    A[1, 1] = scaling_factors[1][1] * laplace.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        assembler=operator_assembler)

    return A
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)
예제 #8
0
def laplace_slp_small_sphere(small_piecewise_const_space, default_parameters):
    """The Laplace single layer operator on a small sphere."""
    from bempp.api.operators.boundary.laplace import single_layer

    return single_layer(
        small_piecewise_const_space,
        small_piecewise_const_space,
        small_piecewise_const_space,
    )
예제 #9
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
예제 #10
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
예제 #11
0
def test_laplace_single_layer(has_exafmm):
    """Test dense assembler for the Laplace operators."""
    if not has_exafmm and not check_for_fmm():
        pytest.skip("ExaFMM must be installed to run this test.")

    grid = bempp.api.shapes.regular_sphere(2)
    space = function_space(grid, "DP", 0)

    op1 = laplace.single_layer(space, space, space, assembler="dense")
    op2 = laplace.single_layer(space, space, space, assembler="fmm")

    fun = bempp.api.GridFunction(space,
                                 coefficients=np.random.rand(
                                     space.global_dof_count))

    assert np.allclose((op1 * fun).coefficients, (op2 * fun).coefficients)

    bempp.api.clear_fmm_cache()
예제 #12
0
def test_laplace_single_layer_evaluator_complex(default_parameters, helpers,
                                                precision, device_interface):
    """Test dense evaluator with complex vector."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.laplace import single_layer

    grid = helpers.load_grid("sphere")

    space1 = function_space(grid, "DP", 0)
    space2 = function_space(grid, "DP", 0)

    discrete_op = single_layer(
        space1,
        space1,
        space2,
        assembler="dense_evaluator",
        parameters=default_parameters,
        device_interface=device_interface,
        precision=precision,
    ).weak_form()

    mat = single_layer(
        space1,
        space1,
        space2,
        assembler="dense",
        parameters=default_parameters,
        device_interface=device_interface,
        precision=precision,
    ).weak_form()

    x = _np.random.RandomState(0).rand(
        space1.global_dof_count) + 1j * _np.random.RandomState(0).rand(
            space1.global_dof_count)

    actual = discrete_op @ x
    expected = mat @ x

    if precision == "single":
        tol = 2e-4
    else:
        tol = 1e-12

    _np.testing.assert_allclose(actual, expected, rtol=tol)
예제 #13
0
def laplaceMultitrace(dirichl_space, neumann_space):
    from bempp.api.operators.boundary import laplace

    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = (-1.0)*laplace.double_layer(dirichl_space, dirichl_space, dirichl_space)
    A[0, 1] = laplace.single_layer(neumann_space, dirichl_space, dirichl_space)
    A[1, 0] = laplace.hypersingular(dirichl_space, neumann_space, neumann_space)
    A[1, 1] = laplace.adjoint_double_layer(neumann_space, neumann_space, neumann_space)

    return A
예제 #14
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
예제 #15
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
예제 #16
0
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
예제 #17
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
예제 #18
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)
예제 #19
0
def laplace_single_layer_dense_large_benchmark(benchmark, default_parameters):
    """Benchmark for Laplace assembly on a larger sphere"""

    from bempp.api.operators.boundary.laplace import single_layer
    from bempp.api import function_space

    grid = bempp.api.shapes.regular_sphere(5)
    space = function_space(grid, "DP", 0)

    fun = lambda: single_layer(
        space, space, space, assembler="dense", parameters=default_parameters
    ).weak_form()

    benchmark(fun)
예제 #20
0
    def test_slp_hyp_pair_on_dual_grids(self):
        """SLP and HYP Pair on dual grids."""

        lin_space = self._lin_space

        parameters = bempp.api.common.global_parameters()
        parameters.assembly.boundary_operator_assembly_type = 'dense'
        parameters.quadrature.double_singular = 9
        parameters.quadrature.near.double_order = 9
        parameters.quadrature.medium.double_order = 9
        parameters.quadrature.far.double_order = 9

        from bempp.api.operators.boundary.laplace import \
            single_layer_and_hypersingular_pair, single_layer, hypersingular

        actual_ops_dual = single_layer_and_hypersingular_pair(
            self._grid,
            spaces='dual',
            stabilization_factor=0,
            parameters=parameters)

        dual_space = bempp.api.function_space(self._grid, "DUAL", 0)
        expected_slp = bempp.api.as_matrix(
            single_layer(dual_space,
                         dual_space,
                         dual_space,
                         parameters=parameters).weak_form())
        actual_slp = bempp.api.as_matrix(actual_ops_dual[0].weak_form())

        expected_hyp = bempp.api.as_matrix(
            hypersingular(lin_space,
                          lin_space,
                          lin_space,
                          parameters=parameters).weak_form())
        actual_hyp = bempp.api.as_matrix(actual_ops_dual[1].weak_form())

        diff_norm_slp = np.linalg.norm(expected_slp -
                                       actual_slp) / np.linalg.norm(actual_slp)
        diff_norm_hyp = np.linalg.norm(expected_hyp -
                                       actual_hyp) / np.linalg.norm(actual_hyp)

        self.assertAlmostEqual(diff_norm_slp, 0, 6)
        self.assertAlmostEqual(diff_norm_hyp, 0, 4)
예제 #21
0
def laplace_multitrace(dirichl_space, neumann_space, operator_assembler):
    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = (-1.0) * laplace.double_layer(dirichl_space,
                                            dirichl_space,
                                            dirichl_space,
                                            assembler=operator_assembler)
    A[0, 1] = laplace.single_layer(neumann_space,
                                   dirichl_space,
                                   dirichl_space,
                                   assembler=operator_assembler)
    A[1, 0] = laplace.hypersingular(dirichl_space,
                                    neumann_space,
                                    neumann_space,
                                    assembler=operator_assembler)
    A[1, 1] = laplace.adjoint_double_layer(neumann_space,
                                           neumann_space,
                                           neumann_space,
                                           assembler=operator_assembler)

    return A
예제 #22
0
def helmholtz_single_layer_dense_p1_cont_large_benchmark(
        benchmark, default_parameters):
    """Helmholtz benchmark with P1 functions on large grid."""
    from bempp.api.operators.boundary.helmholtz import single_layer
    from bempp.api import function_space

    grid = bempp.api.shapes.regular_sphere(5)
    space = function_space(grid, "P", 1)

    wavenumber = 2.5

    fun = lambda: single_layer(
        space,
        space,
        space,
        wavenumber,
        assembler="dense",
        parameters=default_parameters,
    ).weak_form()

    benchmark(fun)
예제 #23
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
예제 #24
0
def first_kind_external(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)

    ep = ep_ex / ep_in

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

    calderon_int_scal = bempp.api.BlockedOperator(2, 2)
    calderon_int_scal[0, 0] = -1.0 * dlp_in
    calderon_int_scal[0, 1] = ep * slp_in
    calderon_int_scal[1, 0] = (1.0 / ep) * hlp_in
    calderon_int_scal[1, 1] = adlp_in

    calderon_ext = bempp.api.BlockedOperator(2, 2)
    calderon_ext[0, 0] = -1.0 * dlp_ex
    calderon_ext[0, 1] = slp_ex
    calderon_ext[1, 0] = hlp_ex
    calderon_ext[1, 1] = adlp_ex

    return A, calderon_int_scal, calderon_ext
예제 #25
0
def derivative_in(dirichl_space, neumann_space, assembler, q, x_q):
    """
    Construct the system matrix and RHS grid functions using derivative formulation with interior values.
    """
    ep_in = PARAMS.ep_in
    ep_ex = PARAMS.ep_ex
    kappa = PARAMS.kappa

    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=assembler)
    dP = modified_helmholtz.double_layer(dirichl_space,
                                         dirichl_space,
                                         dirichl_space,
                                         kappa,
                                         assembler=assembler)
    L1 = (ep * dP) - dF

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

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

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

    A_sys = bempp.api.BlockedOperator(2, 2)
    A_sys[0, 0] = (0.5 * (1.0 + ep) * phi_id) - L1
    A_sys[0, 1] = (-1.0) * L2
    A_sys[1, 0] = L3
    A_sys[1, 1] = (0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4

    @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.callable(vectorized=True)
    def rhs2_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[:] = np.sum(values[:, 1:] * n.T, axis=1) / ep_in

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

    return A_sys, rhs1, rhs2
예제 #26
0
def block_diagonal_precon_alpha_beta(dirichl_space, neumann_space, ep_in,
                                     ep_ex, kappa, alpha, beta):
    from scipy.sparse import diags, bmat
    from scipy.sparse.linalg import factorized, LinearOperator
    from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz

    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
    hlp_in_diag = laplace.hypersingular(
        dirichl_space,
        neumann_space,
        neumann_space,
        assembler="only_diagonal_part").weak_form().A
    adlp_in_diag = laplace.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_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(
        dirichl_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A
    hlp_out_diag = modified_helmholtz.hypersingular(
        dirichl_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A
    adlp_out_diag = modified_helmholtz.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A

    phi_identity_diag = sparse.identity(
        dirichl_space, dirichl_space, dirichl_space).weak_form().A.diagonal()
    dph_identity_diag = sparse.identity(
        neumann_space, neumann_space, neumann_space).weak_form().A.diagonal()

    ep = ep_ex / ep_in

    diag11 = diags((-0.5 * (1 + alpha)) * phi_identity_diag +
                   (alpha * dlp_out_diag) - dlp_in_diag)
    diag12 = diags(slp_in_diag - ((alpha / ep) * slp_out_diag))
    diag21 = diags(hlp_in_diag - (beta * hlp_out_diag))
    diag22 = diags((-0.5 * (1 + (beta / ep))) * dph_identity_diag +
                   adlp_in_diag - ((beta / ep) * adlp_out_diag))
    block_mat_precond = bmat([[diag11, diag12],
                              [diag21, diag22]]).tocsr()  # csr_matrix

    solve = factorized(
        block_mat_precond
    )  # a callable for solving a sparse linear system (treat it as an inverse)
    precond = LinearOperator(matvec=solve,
                             dtype='float64',
                             shape=block_mat_precond.shape)

    return precond
예제 #27
0
def stern_formulation(dirichl_space_in, neumann_space_in, dirichl_space_ex,
                      neumann_space_ex, ep_in, ep_ex, q, x_q, kappa):

    # Functions to proyect the carges potential to the boundary with constants
    def green_func(x, n, domain_index, result):
        result[:] = np.sum(
            q / np.linalg.norm(x - x_q, axis=1)) / (4. * np.pi * ep_in)

    print "\nProjecting charges over surface..."
    charged_grid_fun = bempp.api.GridFunction(dirichl_space_in, fun=green_func)

    rhs = np.concatenate([
        charged_grid_fun.coefficients,
        np.zeros(neumann_space_in.global_dof_count),
        np.zeros(dirichl_space_ex.global_dof_count),
        np.zeros(neumann_space_ex.global_dof_count)
    ])

    print "Defining operators..."
    # OPERATOR FOR INTERNAL SURFACE
    from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz
    idn_in = sparse.identity(dirichl_space_in, dirichl_space_in,
                             dirichl_space_in)

    # Ec 1
    slp_in = laplace.single_layer(neumann_space_in, dirichl_space_in,
                                  dirichl_space_in)
    dlp_in = laplace.double_layer(dirichl_space_in, dirichl_space_in,
                                  dirichl_space_in)
    # Ec 2
    # adj_1T1 = laplace.single_layer(neumann_space_in, dirichl_space_in, dirichl_space_in)
    # adj_1T1 = laplace.double_layer(dirichl_space_in, dirichl_space_in, dirichl_space_in)

    slp_2T1 = laplace.single_layer(neumann_space_ex, dirichl_space_in,
                                   dirichl_space_in)
    dlp_2T1 = laplace.double_layer(dirichl_space_ex, dirichl_space_in,
                                   dirichl_space_in)

    # OPERATOR FOR EXTERNAL SURFACE
    idn_ex = sparse.identity(dirichl_space_ex, dirichl_space_ex,
                             dirichl_space_ex)
    # Internal Boudary
    slp_1T2 = laplace.single_layer(neumann_space_in, dirichl_space_ex,
                                   dirichl_space_ex)
    # dlp_1T2 = laplace.double_layer(dirichl_space_in, dirichl_space_ex, dirichl_space_ex)

    slp_2T2 = laplace.single_layer(neumann_space_ex, dirichl_space_ex,
                                   dirichl_space_ex)
    dlp_2T2 = laplace.double_layer(dirichl_space_ex, dirichl_space_ex,
                                   dirichl_space_ex)
    # External Boundary
    slp_ex = modified_helmholtz.single_layer(neumann_space_ex,
                                             dirichl_space_ex,
                                             dirichl_space_ex, kappa)
    dlp_ex = modified_helmholtz.double_layer(dirichl_space_ex,
                                             dirichl_space_ex,
                                             dirichl_space_ex, kappa)

    ep = (ep_in / ep_ex)

    print "Creating operators..."
    # Matrix Assemble
    blocked = bempp.api.BlockedOperator(4, 4)
    blocked[0, 0] = .5 * idn_in + dlp_in
    blocked[0, 1] = -slp_in
    # blocked[0, 2] = 0
    # blocked[0, 3] = 0

    # Original formulation
    blocked[1, 0] = .5 * idn_in - dlp_in  # dlp_in = dlp_1T1
    blocked[1, 1] = ep * slp_in  # slp_in = slp_1T1
    blocked[1, 2] = dlp_2T1
    blocked[1, 3] = -slp_2T1

    # blocked[2, 0] = -dlp_1T2    ## eliminar**
    blocked[2, 1] = ep * slp_1T2
    blocked[2, 2] = .5 * idn_ex + dlp_2T2
    blocked[2, 3] = -slp_2T2

    # blocked[3, 0] = 0
    # blocked[3, 1] = 0
    blocked[3, 2] = .5 * idn_ex - dlp_ex
    blocked[3, 3] = slp_ex
    A = blocked.strong_form()

    return A, rhs
예제 #28
0
def block_diagonal_precon_juffer(dirichl_space, neumann_space, ep_in, ep_ex,
                                 kappa):
    from scipy.sparse import diags, bmat
    from scipy.sparse.linalg import factorized, LinearOperator
    from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz

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

    dF = laplace.double_layer(dirichl_space,
                              dirichl_space,
                              dirichl_space,
                              assembler="only_diagonal_part").weak_form().A
    dP = modified_helmholtz.double_layer(
        dirichl_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A
    L1 = (ep * dP) - dF

    F = laplace.single_layer(neumann_space,
                             dirichl_space,
                             dirichl_space,
                             assembler="only_diagonal_part").weak_form().A
    P = modified_helmholtz.single_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A
    L2 = F - P

    ddF = laplace.hypersingular(dirichl_space,
                                neumann_space,
                                neumann_space,
                                assembler="only_diagonal_part").weak_form().A
    ddP = modified_helmholtz.hypersingular(
        dirichl_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A
    L3 = ddP - ddF

    dF0 = laplace.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        assembler="only_diagonal_part").weak_form().A
    dP0 = modified_helmholtz.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler="only_diagonal_part").weak_form().A
    L4 = dF0 - ((1.0 / ep) * dP0)

    diag11 = diags((0.5 * (1.0 + ep) * phi_id) - L1)
    diag12 = diags((-1.0) * L2)
    diag21 = diags(L3)
    diag22 = diags((0.5 * (1.0 + (1.0 / ep)) * dph_id) - L4)
    block_mat_precond = bmat([[diag11, diag12],
                              [diag21, diag22]]).tocsr()  # csr_matrix

    solve = factorized(
        block_mat_precond
    )  # a callable for solving a sparse linear system (treat it as an inverse)
    precond = LinearOperator(matvec=solve,
                             dtype='float64',
                             shape=block_mat_precond.shape)

    return precond
예제 #29
0
# Para nuestro caso utilizaremos DP-0, es decir, valores constantes por elemento
dirichl_space = bempp.api.function_space(grid,  "DP", 0)
neumann_space = bempp.api.function_space(grid,  "DP", 0) 
dual_to_dir_s = bempp.api.function_space(grid,  "DP", 0)

# Se crea u_s y su derivada normal du_s en la frontera
u_s  = bempp.api.GridFunction(dirichl_space, fun=u_s_G)
du_s = bempp.api.GridFunction(neumann_space, fun=du_s_G) 

# Se crean los operadores asociados al sistema, que dependen de los espacios de las soluciones
# identity : I  : matriz identidad
# dlp_in : K_in : Double-Layer operator para la region interior
# slp_in : V_in : Single-Layer operator para la region interior
# _out : Mismos operadores pero para la región exterior, con k=kappa=0.125
identity = sparse.identity(     dirichl_space, dirichl_space, dual_to_dir_s)
slp_in   = laplace.single_layer(neumann_space, dirichl_space, dual_to_dir_s)
dlp_in   = laplace.double_layer(dirichl_space, dirichl_space, dual_to_dir_s)
slp_out  = modified_helmholtz.single_layer(neumann_space, dirichl_space, dual_to_dir_s, k)
dlp_out  = modified_helmholtz.double_layer(dirichl_space, dirichl_space, dual_to_dir_s, k)


# 4.1 Solución armónica ---------------------------------------------------------------

# Dada por V_in du_s = (1/2+K_in)u_h = -(1/2+K_in)u_s (BC)
sol, info,it_count = bempp.api.linalg.gmres( slp_in, -(dlp_in+0.5*identity)*u_s , return_iteration_count=True, tol=1e-4)
print("The linear system for du_h was solved in {0} iterations".format(it_count))

u_h = -u_s
du_h = sol

예제 #30
0
def stern_asc(neumann_space_in, dirichl_space_ex, neumann_space_ex, ep_in,
              ep_ex, q, x_q, kappa):

    # Functions to proyect the carges potential to the boundary with constants
    def d_green_func(x, n, domain_index, result):
        const = -1. / (4. * np.pi * ep_in)
        result[:] = const * np.sum(q * np.dot(x - x_q, n) /
                                   (np.linalg.norm(x - x_q, axis=1)**3))

    print "\nProjecting charges over surface..."
    charged_grid_fun = bempp.api.GridFunction(neumann_space_in,
                                              fun=d_green_func)

    rhs = np.concatenate([
        charged_grid_fun.coefficients,
        np.zeros(dirichl_space_ex.global_dof_count),
        np.zeros(neumann_space_ex.global_dof_count)
    ])

    print "Defining operators..."
    # OPERATORS FOR INTERNAL SURFACE
    from bempp.api.operators.boundary import sparse, laplace, modified_helmholtz
    idn_in = sparse.identity(neumann_space_in, neumann_space_in,
                             neumann_space_in)

    adj_1T1 = laplace.adjoint_double_layer(neumann_space_in, neumann_space_in,
                                           neumann_space_in)
    hyp_2T1 = laplace.hypersingular(dirichl_space_ex, neumann_space_in,
                                    neumann_space_in)
    adj_2T1 = laplace.adjoint_double_layer(neumann_space_ex, neumann_space_in,
                                           neumann_space_in)

    # OPERATORS FOR EXTERNAL SURFACE
    idn_ex = sparse.identity(dirichl_space_ex, dirichl_space_ex,
                             dirichl_space_ex)

    slp_1T2 = laplace.single_layer(neumann_space_in, dirichl_space_ex,
                                   dirichl_space_ex)
    dlp_2T2 = laplace.double_layer(dirichl_space_ex, dirichl_space_ex,
                                   dirichl_space_ex)
    slp_2T2 = laplace.single_layer(neumann_space_ex, dirichl_space_ex,
                                   dirichl_space_ex)

    dlp_ex = modified_helmholtz.double_layer(dirichl_space_ex,
                                             dirichl_space_ex,
                                             dirichl_space_ex, kappa)
    slp_ex = modified_helmholtz.single_layer(neumann_space_ex,
                                             dirichl_space_ex,
                                             dirichl_space_ex, kappa)

    ep = (ep_in / ep_ex)

    print "Creating operators..."
    # Matrix Assemble
    blocked = bempp.api.BlockedOperator(3, 3)
    blocked[0, 0] = idn_in + (ep - 1.) * adj_1T1
    blocked[0, 1] = -hyp_2T1
    blocked[0, 2] = -adj_2T1

    blocked[1, 0] = ep * slp_1T2
    blocked[1, 1] = .5 * idn_ex + dlp_2T2
    blocked[1, 2] = -slp_2T2

    #blocked[2, 0] = 0
    blocked[2, 1] = .5 * idn_ex - dlp_ex
    blocked[2, 2] = slp_ex

    A = blocked.weak_form()

    return A, rhs