Ejemplo n.º 1
0
def test_modified_helmholtz_hypersingular(
    default_parameters, helpers, precision, device_interface
):
    """Test dense assembler for the modified Helmholtz hypersingular operator."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.modified_helmholtz import hypersingular

    grid = helpers.load_grid("sphere")

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

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

    expected = _np.real(
        helpers.load_npy_data("modified_helmholtz_hypersingular_boundary")
    )
    _np.testing.assert_allclose(
        discrete_op.A, expected, rtol=helpers.default_tolerance(precision)
    )
Ejemplo n.º 2
0
def test_hypersingular_fails_for_wrong_space(type0, type1):
    """Expected failure for wrong spaces."""
    grid = bempp.api.shapes.regular_sphere(0)
    space0 = function_space(grid, *type0)
    space1 = function_space(grid, *type1)

    with pytest.raises(ValueError):
        laplace.hypersingular(space0, space1, space1, assembler="dense").weak_form()
    with pytest.raises(ValueError):
        helmholtz.hypersingular(
            space0, space1, space1, 1.5, assembler="dense"
        ).weak_form()
    with pytest.raises(ValueError):
        modified_helmholtz.hypersingular(
            space0, space1, space1, 1.5, assembler="dense"
        ).weak_form()
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
0
    def test_multitrace_hypersingular_agrees_with_standard_hypersingular_lin(
            self):
        """Multitrace hyp agrees with standard hyp on linear spaces."""
        parameters = bempp.api.common.global_parameters()
        parameters.assembly.boundary_operator_assembly_type = 'dense'

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


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

        actual = multitrace[1, 0]

        expected = hypersingular(
            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, 3)
Ejemplo n.º 6
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
Ejemplo n.º 7
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
Ejemplo n.º 8
0
    def test_compound_hypersingular_agrees_with_standard_hypersingular_operator_lin(self):
        from bempp.api.operators.boundary.modified_helmholtz import hypersingular
        import numpy as np

        parameters = bempp.api.common.global_parameters()
        parameters.assembly.boundary_operator_assembly_type = 'dense'

        standard_hypersingular = hypersingular(self._lin_space, self._lin_space, self._lin_space,
                                               WAVE_NUMBER,
                                               parameters=parameters).weak_form()
        compound_hypersingular = hypersingular(self._lin_space, self._lin_space, self._lin_space,
                                               WAVE_NUMBER,
                                               parameters=parameters, use_slp=True).weak_form()

        mat1 = bempp.api.as_matrix(standard_hypersingular)
        mat2 = bempp.api.as_matrix(compound_hypersingular)

        self.assertAlmostEqual(np.linalg.norm(mat1 - mat2) / np.linalg.norm(mat1), 0)
Ejemplo n.º 9
0
def test_modified_helmholtz_hypersingular_evaluator(default_parameters,
                                                    helpers, precision,
                                                    device_interface):
    """Test dense evaluator for modified Helmholtz hypersingular."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.modified_helmholtz import hypersingular

    grid = helpers.load_grid("sphere")

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

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

    mat = hypersingular(
        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)
Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 12
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
Ejemplo n.º 13
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
Ejemplo n.º 14
0
    def test_compound_hyp_agrees_with_standard_hyp_lin(self):
        """Compount HYP agrees with standard HYP for linear spaces."""
        from bempp.api.operators.boundary.modified_helmholtz import \
            hypersingular

        parameters = bempp.api.common.global_parameters()
        parameters.assembly.boundary_operator_assembly_type = 'dense'

        standard_hypersingular = hypersingular(
            self._lin_space, self._lin_space, self._lin_space,
            WAVE_NUMBER,
            parameters=parameters, use_slp=False).weak_form()
        compound_hypersingular = hypersingular(
            self._lin_space, self._lin_space, self._lin_space,
            WAVE_NUMBER,
            parameters=parameters, use_slp=True).weak_form()

        mat1 = bempp.api.as_matrix(standard_hypersingular)
        mat2 = bempp.api.as_matrix(compound_hypersingular)

        self.assertAlmostEqual(np.linalg.norm(
            mat1 - mat2) / np.linalg.norm(mat1), 0)
Ejemplo n.º 15
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)
Ejemplo n.º 16
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
Ejemplo n.º 17
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
Ejemplo n.º 18
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
Ejemplo n.º 19
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