Beispiel #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
Beispiel #2
0
    def test_multitrace_single_layer_agrees_with_standard_single_layer_dual_lin(
            self):
        """Multitrace SLP agrees with standard SLP."""
        parameters = bempp.api.common.global_parameters()
        parameters.assembly.boundary_operator_assembly_type = 'dense'

        from bempp.api.operators.boundary.modified_helmholtz import \
            multitrace_operator, single_layer

        multitrace = multitrace_operator(
            self._grid, WAVE_NUMBER, parameters=parameters)

        actual = multitrace[0, 1]

        expected = single_layer(
            self._lin_space, self._lin_space, self._lin_space, WAVE_NUMBER,
            parameters=parameters)

        mat_expected = bempp.api.as_matrix(expected.weak_form())
        mat_actual = bempp.api.as_matrix(actual.weak_form())

        diff_norm = np.linalg.norm(
            mat_expected - mat_actual) / np.linalg.norm(mat_actual)

        self.assertAlmostEqual(diff_norm, 0)
Beispiel #3
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
Beispiel #4
0
def mod_helm_multitrace_scaled(dirichl_space, neumann_space, kappa,
                               scaling_factors, operator_assembler):
    A = bempp.api.BlockedOperator(2, 2)
    A[0, 0] = scaling_factors[0][0] * (-1.0) * modified_helmholtz.double_layer(
        dirichl_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler=operator_assembler)
    A[0, 1] = scaling_factors[0][1] * modified_helmholtz.single_layer(
        neumann_space,
        dirichl_space,
        dirichl_space,
        kappa,
        assembler=operator_assembler)
    A[1, 0] = scaling_factors[1][0] * modified_helmholtz.hypersingular(
        dirichl_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler=operator_assembler)
    A[1, 1] = scaling_factors[1][1] * modified_helmholtz.adjoint_double_layer(
        neumann_space,
        neumann_space,
        neumann_space,
        kappa,
        assembler=operator_assembler)

    return A
def test_modified_helmholtz_single_layer(
    default_parameters, helpers, precision, device_interface
):
    """Test dense assembler for modified Helmholtz."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.modified_helmholtz import single_layer

    grid = helpers.load_grid("sphere")

    space = function_space(grid, "P", 1)

    discrete_op = single_layer(
        space,
        space,
        space,
        OMEGA,
        assembler="dense",
        precision=precision,
        device_interface=device_interface,
        parameters=default_parameters,
    ).weak_form()

    # Bempp 3 assembles modified Helmholtz as complex type, so cast to real.
    expected = _np.real(
        helpers.load_npy_data("modified_helmholtz_single_layer_boundary")
    )
    _np.testing.assert_allclose(
        discrete_op.A, expected, rtol=helpers.default_tolerance(precision)
    )
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)
Beispiel #7
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
Beispiel #8
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
def test_modified_helmholtz_single_layer_evaluator(default_parameters, helpers,
                                                   precision,
                                                   device_interface):
    """Test dense evaluator for modified Helmholtz slp."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.modified_helmholtz import single_layer

    grid = helpers.load_grid("sphere")

    space = function_space(grid, "P", 1)

    discrete_op = single_layer(
        space,
        space,
        space,
        OMEGA,
        assembler="dense_evaluator",
        precision=precision,
        device_interface=device_interface,
        parameters=default_parameters,
    ).weak_form()

    mat = single_layer(
        space,
        space,
        space,
        OMEGA,
        assembler="dense",
        precision=precision,
        device_interface=device_interface,
        parameters=default_parameters,
    ).weak_form()

    x = _np.random.RandomState(0).randn(space.global_dof_count)

    actual = discrete_op @ x
    expected = mat @ x

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

    _np.testing.assert_allclose(actual, expected, rtol=tol)
Beispiel #10
0
def modHelmMultitrace(dirichl_space, neumann_space, kappa):
    from bempp.api.operators.boundary import modified_helmholtz

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

    return A
Beispiel #11
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
Beispiel #12
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
Beispiel #13
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
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
Beispiel #15
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)
Beispiel #16
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
Beispiel #17
0
    def test_slp_hyp_pair_linear_space(self):
        """SLP and HYP pair on linear spaces."""

        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.modified_helmholtz import \
            single_layer_and_hypersingular_pair, single_layer, hypersingular


        actual_ops_dual = single_layer_and_hypersingular_pair(
            self._grid, WAVE_NUMBER, spaces='linear', parameters=parameters)

        expected_slp = bempp.api.as_matrix(single_layer(
            lin_space, lin_space, lin_space, WAVE_NUMBER,
            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, WAVE_NUMBER,
            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, 6)
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
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
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



# 4.2 Solución regular -----------------------------------------------------------------
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
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
Beispiel #23
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
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