def test_maxwell_electric_field_screen(default_parameters, helpers,
                                       device_interface, precision):
    """Test Maxwell electric field on sphere."""
    from bempp.api import get_precision
    from bempp.api import function_space
    from bempp.api.operators.boundary.maxwell import electric_field

    grid = helpers.load_grid("structured_grid")

    space1 = function_space(grid, "RWG", 0)
    space2 = function_space(grid, "SNC", 0)

    discrete_op = electric_field(
        space1,
        space1,
        space2,
        2.5,
        assembler="dense",
        device_interface=device_interface,
        precision=precision,
        parameters=default_parameters,
    ).weak_form()

    if precision == "single":
        rtol = 1e-5
        atol = 1e-7
    else:
        rtol = 1e-10
        atol = 1e-14

    expected = helpers.load_npy_data(
        "maxwell_electric_field_structured_boundary")
    _np.testing.assert_allclose(discrete_op.A, expected, rtol=rtol, atol=atol)
Exemple #2
0
def test_sparse_identity_snc_bc(default_parameters, helpers, device_interface,
                                precision):
    """Test singular assembler for the sparse L^2 identity with snc/bc basis."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.sparse import identity

    grid = helpers.load_grid("sphere")
    expected = helpers.load_npy_data("sparse_identity_snc_bc")

    bc = function_space(grid, "BC", 0)
    snc = function_space(grid, "SNC", 0)

    actual = (identity(
        bc,
        bc,
        snc,
        parameters=default_parameters,
        device_interface=device_interface,
        precision=precision,
    ).weak_form().A.todense())

    if precision == "single":
        atol = 1e-7
    else:
        atol = 1e-14

    _np.testing.assert_allclose(actual, expected, atol=atol)
def test_maxwell_far_field_segments(default_parameters, helpers,
                                    device_interface, precision):
    """Test Maxwell far field on segments."""
    import bempp.api
    from bempp.api import function_space
    from bempp.api.operators.far_field.maxwell import electric_field
    from bempp.api.operators.far_field.maxwell import magnetic_field
    from bempp.api.grid.grid import grid_from_segments

    grid = bempp.api.shapes.multitrace_cube()

    seglists = [[1, 2, 3, 4, 5, 6], [6, 7, 8, 9, 10, 11]]
    swapped_normal_lists = [{}, {6}]

    rand = _np.random.RandomState(0)
    points = rand.randn(3, 10)
    points /= _np.linalg.norm(points, axis=0)

    for op in [electric_field, magnetic_field]:
        for seglist, swapped_normals in zip(seglists, swapped_normal_lists):
            new_grid = grid_from_segments(grid, seglist)

            coeffs = rand.rand(new_grid.number_of_edges)

            space1 = function_space(
                grid,
                "RWG",
                0,
                segments=seglist,
                swapped_normals=swapped_normals,
                include_boundary_dofs=True,
            )
            space2 = function_space(new_grid,
                                    "RWG",
                                    0,
                                    swapped_normals=swapped_normals)

            fun1 = bempp.api.GridFunction(space1, coefficients=coeffs)
            fun2 = bempp.api.GridFunction(space2, coefficients=coeffs)

            actual = (op(
                space1,
                points,
                2.5,
                parameters=default_parameters,
                precision=precision,
                device_interface=device_interface,
            ) * fun1)
            expected = (op(
                space2,
                points,
                2.5,
                parameters=default_parameters,
                precision=precision,
                device_interface=device_interface,
            ) * fun2)

            _np.testing.assert_allclose(
                actual, expected, rtol=helpers.default_tolerance(precision))
def test_helmholtz_far_field_segments_complex_coeffs(default_parameters,
                                                     helpers, device_interface,
                                                     precision):
    """Test Maxwell potentials on segments with complex coeffs."""
    import bempp.api
    from bempp.api import function_space
    from bempp.api.operators.far_field.helmholtz import single_layer
    from bempp.api.operators.far_field.helmholtz import double_layer
    from bempp.api.grid.grid import grid_from_segments

    grid = bempp.api.shapes.multitrace_cube()

    seglists = [[1, 2, 3, 4, 5, 6], [6, 7, 8, 9, 10, 11]]
    swapped_normal_lists = [{}, {6}]

    rand = _np.random.RandomState(0)
    points = rand.randn(3, 10)
    points /= _np.linalg.norm(points, axis=0)

    for op in [single_layer, double_layer]:
        for seglist, swapped_normals in zip(seglists, swapped_normal_lists):
            new_grid = grid_from_segments(grid, seglist)

            coeffs = rand.rand(new_grid.number_of_vertices) + 1j * rand.rand(
                new_grid.number_of_vertices)

            space1 = function_space(
                grid,
                "P",
                1,
                segments=seglist,
                swapped_normals=swapped_normals,
                include_boundary_dofs=True,
            )
            space2 = function_space(new_grid,
                                    "P",
                                    1,
                                    swapped_normals=swapped_normals)

            fun1 = bempp.api.GridFunction(space1, coefficients=coeffs)
            fun2 = bempp.api.GridFunction(space2, coefficients=coeffs)

            actual = (op(
                space1,
                points,
                2.5,
                device_interface=device_interface,
                precision=precision,
            ) * fun1)
            expected = (op(
                space2,
                points,
                2.5,
                device_interface=device_interface,
                precision=precision,
            ) * fun2)

            _np.testing.assert_allclose(
                actual, expected, rtol=helpers.default_tolerance(precision))
Exemple #5
0
def test_laplace_operators(operator, type0, type1):
    """Test dense assembler for the Laplace operators."""
    grid = bempp.api.shapes.regular_sphere(0)
    space0 = function_space(grid, *type0)
    space1 = function_space(grid, *type1)

    op = operator(space0, space1, space1, assembler="dense")
    op.weak_form()
Exemple #6
0
def test_modified_helmholtz_operators(operator, wavenumber, type0, type1):
    """Test dense assembler for the modified Helmholtz operators."""
    grid = bempp.api.shapes.regular_sphere(0)
    space0 = function_space(grid, *type0)
    space1 = function_space(grid, *type1)

    op = operator(space0, space1, space1, wavenumber, assembler="dense")
    op.weak_form()
Exemple #7
0
def test_maxwell_operators(operator, wavenumber, type0, type1):
    """Test dense assembler for the Maxwell operators."""
    grid = bempp.api.shapes.regular_sphere(0)
    space0 = function_space(grid, *type0)
    space1 = function_space(grid, *type1)

    op = operator(space0, space0, space1, wavenumber, assembler="dense")
    op.weak_form()

    # Check that we cannot swap curl and div conforming spaces for Maxwell

    with pytest.raises(ValueError):
        op = operator(space1, space1, space0, wavenumber, assembler="dense")
Exemple #8
0
def create_spaces(grid, diri, neum):

    trial, test = diri
    triad = bem.function_space(grid, trial[0], trial[1])
    testd = bem.function_space(grid, test[0], test[1])
    spaced = (triad, testd)

    trial, test = neum
    trian = bem.function_space(grid, trial[0], trial[1])
    testn = bem.function_space(grid, test[0], test[1])
    spacen = (trian, testn)

    return spaced, spacen
def test_maxwell_electric_field_rbc_bc_sphere(default_parameters, helpers,
                                              device_interface, precision,
                                              skip):
    """Test Maxwell electric field on sphere with RBC/BC basis."""
    if skip == "circleci":
        pytest.skip()

    import bempp.api
    from bempp.api import function_space
    from bempp.api.operators.boundary.maxwell import electric_field

    grid = helpers.load_grid("sphere")

    space1 = function_space(grid, "BC", 0)
    space2 = function_space(grid, "RBC", 0)

    rand = _np.random.RandomState(0)
    vec = rand.rand(space1.global_dof_count)

    bempp.api.GLOBAL_PARAMETERS.fmm.dense_evaluation = True

    discrete_op = electric_field(
        space1,
        space1,
        space2,
        2.5,
        assembler="fmm",
        device_interface=device_interface,
        precision=precision,
        parameters=default_parameters,
    ).weak_form()

    actual = discrete_op @ vec

    bempp.api.GLOBAL_PARAMETERS.fmm.dense_evaluation = False

    if precision == "single":
        rtol = 5e-5
        atol = 5e-6
    else:
        rtol = 1e-10
        atol = 1e-14

    mat = helpers.load_npy_data("maxwell_electric_field_boundary_rbc_bc")

    expected = mat @ vec

    _np.testing.assert_allclose(actual, expected, rtol=rtol, atol=atol)

    bempp.api.clear_fmm_cache()
Exemple #10
0
def test_helmholtz_single_layer(has_exafmm, wavenumber):
    """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 = helmholtz.single_layer(space,
                                 space,
                                 space,
                                 wavenumber,
                                 assembler="dense")
    op2 = helmholtz.single_layer(space,
                                 space,
                                 space,
                                 wavenumber,
                                 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()
Exemple #11
0
def test_helmholtz_single_layer_potential_p1_complex_coeffs(
        default_parameters, helpers, device_interface, precision):
    """Test Helmholtz slp potential with p1 basis and complex coeffs."""
    from bempp.api import function_space
    from bempp.api import GridFunction
    from bempp.api.operators.potential.helmholtz import single_layer

    grid = helpers.load_grid("sphere")
    space = function_space(grid, "P", 1)

    data = helpers.load_npz_data("helmholtz_single_layer_potential_p1")

    points = data["points"]
    coefficients = _np.random.rand(
        space.global_dof_count) + 1j * _np.random.rand(space.global_dof_count)

    fun = GridFunction(space, coefficients=coefficients)
    fun_real = GridFunction(space, coefficients=_np.real(coefficients))
    fun_complex = GridFunction(space, coefficients=_np.imag(coefficients))

    op = single_layer(
        space,
        points,
        WAVENUMBER,
        parameters=default_parameters,
        precision=precision,
        device_interface=device_interface,
    )

    expected = op.evaluate(fun_real) + 1j * op.evaluate(fun_complex)
    actual = op.evaluate(fun)

    _np.testing.assert_allclose(actual,
                                expected,
                                rtol=helpers.default_tolerance(precision))
Exemple #12
0
    def __init__(self,
                 kcomplex,
                 n,
                 geofile='sphere-simple.script.geo',
                 meshname='tmp.msh'):
        self.ks = [kcomplex]
        self.kExt = kcomplex
        self.n = n
        self.kInt = kcomplex * np.sqrt(n)

        self.geofile = geofile
        self.meshname = meshname

        with open('in.geo', 'w') as fp:
            fp.write("k = {};".format(np.abs(self.kInt)))
        with open('out.geo', 'w') as fp:
            fp.write('\nSave "{}";\n'.format(meshname))
        call(['gmsh', geofile, '-'])

        self.grid = grid = bem.import_grid(meshname)
        self.space = space = bem.function_space(grid, "P", 1)
        self.shape = self.space.global_dof_count

        self.collect()
        self.weak_form()
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.to_dense(),
                                expected,
                                rtol=helpers.default_tolerance(precision))
Exemple #14
0
def test_maxwell_magnetic_field_potential_rwg(default_parameters, helpers,
                                              device_interface, precision):
    """Test Maxwell magnetic potential."""
    from bempp.api import function_space
    from bempp.api import GridFunction
    from bempp.api.operators.potential.maxwell import magnetic_field

    grid = helpers.load_grid("sphere")
    space = function_space(grid, "RWG", 0)

    data = helpers.load_npz_data("maxwell_magnetic_field_potential")

    coefficients = data["vec"]
    points = data["points"]
    expected = data["result"]

    fun = GridFunction(space, coefficients=coefficients)

    actual = magnetic_field(
        space,
        points,
        WAVENUMBER,
        parameters=default_parameters,
        precision=precision,
        device_interface=device_interface,
    ).evaluate(fun)

    _np.testing.assert_allclose(actual,
                                expected,
                                rtol=helpers.default_tolerance(precision))
Exemple #15
0
def test_laplace_single_layer_potential_p0(default_parameters, helpers,
                                           device_interface, precision):
    """Test Laplace slp potential with p0 basis."""
    from bempp.api import function_space
    from bempp.api import GridFunction
    from bempp.api.operators.potential.laplace import single_layer

    grid = helpers.load_grid("sphere")
    space = function_space(grid, "DP", 0)

    data = helpers.load_npz_data("laplace_single_layer_potential_p0")

    coefficients = data["vec"]
    points = data["points"]
    expected = data["result"]

    fun = GridFunction(space, coefficients=coefficients)

    actual = single_layer(
        space,
        points,
        parameters=default_parameters,
        precision=precision,
        device_interface=device_interface,
    ).evaluate(fun)

    _np.testing.assert_allclose(actual,
                                expected,
                                rtol=helpers.default_tolerance(precision))
def test_helmholtz_adjoint_double_layer_p1_cont(default_parameters, helpers,
                                                precision, device_interface):
    """Test dense assembler for the Helmholtz adjoint dlp with p1 basis."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.helmholtz import adjoint_double_layer

    grid = helpers.load_grid("sphere")

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

    discrete_op = adjoint_double_layer(
        space,
        space,
        space,
        WAVENUMBER,
        assembler="dense",
        precision=precision,
        device_interface=device_interface,
        parameters=default_parameters,
    ).weak_form()

    expected = helpers.load_npy_data("helmholtz_adj_double_layer_boundary")
    _np.testing.assert_allclose(discrete_op.to_dense(),
                                expected,
                                rtol=helpers.default_tolerance(precision))
Exemple #17
0
def test_laplace_hypersingular(default_parameters, helpers, precision,
                               device_interface):
    """Test dense assembler for the Laplace hypersingular operator."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.laplace import hypersingular

    grid = helpers.load_grid("sphere")

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

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

    expected = helpers.load_npy_data("laplace_hypersingular_boundary")

    _np.testing.assert_allclose(discrete_op.A,
                                expected,
                                rtol=helpers.default_tolerance(precision))
def test_modified_helmholtz_adjoint_double_layer(
    default_parameters, helpers, precision, device_interface
):
    """Test dense assembler for the Helmholtz adjoint dlp."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.modified_helmholtz import adjoint_double_layer

    grid = helpers.load_grid("sphere")

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

    discrete_op = adjoint_double_layer(
        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_adj_double_layer_boundary")
    )
    _np.testing.assert_allclose(
        discrete_op.A, expected, rtol=helpers.default_tolerance(precision)
    )
Exemple #19
0
def test_helmholtz_double_layer_potential_p1(default_parameters, helpers,
                                             device_interface, precision):
    """Test Helmholtz dlp potential with p1 basis."""
    from bempp.api import function_space
    from bempp.api import GridFunction
    from bempp.api.operators.potential.helmholtz import double_layer

    grid = helpers.load_grid("sphere")
    space = function_space(grid, "P", 1)

    data = helpers.load_npz_data("helmholtz_double_layer_potential_p1")

    coefficients = data["vec"]
    points = data["points"]
    expected = data["result"]

    fun = GridFunction(space, coefficients=coefficients)

    actual = double_layer(
        space,
        points,
        WAVENUMBER,
        parameters=default_parameters,
        precision=precision,
        device_interface=device_interface,
    ).evaluate(fun)

    _np.testing.assert_allclose(actual,
                                expected,
                                rtol=helpers.default_tolerance(precision))
Exemple #20
0
    def __init__(self, kcomplex, eps, nlambda,
                 geofile='sphere-simple.script.geo', meshname='sphere.msh'):
        self.ks = [kcomplex]
        self.kExt = kcomplex
        self.eps = eps
        self.nlambda = nlambda
        self.kInt = kcomplex * np.sqrt(eps)

        self.geofile = geofile
        self.meshname = meshname

        with open('in.geo', 'w') as fp:
            fp.write("k = {};".format(np.abs(self.kExt)))
            fp.write("eps = {};".format(np.abs(self.eps)))
            fp.write("nlambda = {};".format(np.abs(self.nlambda)))
        with open('out.geo', 'w') as fp:
            fp.write('\nSave "{}";\n'.format(meshname))
        call(['gmsh', geofile, '-'])

        self.grid = grid = bem.import_grid(meshname)
        self.space = space = bem.function_space(grid, "P", 1)
        self.shape = self.space.global_dof_count

        self.collect()
        self.weak_form()
Exemple #21
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()
Exemple #22
0
def helmholtz_potential_dense_large_p0_benchmark(benchmark,
                                                 default_parameters):
    """Benchmark for Helmholtz potential evaluation on large sphere"""

    from bempp.api.operators.potential.helmholtz import single_layer
    from bempp.api import function_space
    import numpy as np

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

    npoints = 10000

    theta = np.linspace(0, 2 * np.pi, npoints)
    points = np.vstack(
        [np.cos(theta),
         np.sin(theta), 3 * np.ones(npoints, dtype="float64")])

    coefficients = np.random.randn(
        space.global_dof_count) + 1j * np.random.randn(space.global_dof_count)

    grid_fun = bempp.api.GridFunction(space, coefficients=coefficients)

    fun = lambda: single_layer(
        space, points, 2.5, parameters=default_parameters).evaluate(grid_fun)

    benchmark(fun)
Exemple #23
0
def test_helmholtz_single_layer_p0(
    default_parameters, helpers, precision, device_interface
):
    """Test dense assembler for the Helmholtz slp with p0 basis."""
    from bempp.api import function_space
    from bempp.api.operators.boundary.helmholtz import single_layer

    grid = helpers.load_grid("sphere")

    space = function_space(grid, "DP", 0)

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

    expected = helpers.load_npy_data("helmholtz_single_layer_boundary_p0_p0")
    _np.testing.assert_allclose(
        discrete_op.A, expected, rtol=helpers.default_tolerance(precision)
    )
def test_maxwell_magnetic_field_complex_sphere_evaluator(
        default_parameters, helpers, device_interface, precision):
    """Test Maxwell magnetic field evaluator on sphere with complex wavenumber."""
    from bempp.api import get_precision
    from bempp.api import function_space
    from bempp.api.operators.boundary.maxwell import magnetic_field

    grid = helpers.load_grid("sphere")

    space1 = function_space(grid, "RWG", 0)
    space2 = function_space(grid, "SNC", 0)

    discrete_op = magnetic_field(
        space1,
        space1,
        space2,
        2.5 + 1j,
        assembler="dense_evaluator",
        device_interface=device_interface,
        precision=precision,
        parameters=default_parameters,
    ).weak_form()

    mat = magnetic_field(
        space1,
        space1,
        space2,
        2.5 + 1j,
        assembler="dense",
        device_interface=device_interface,
        precision=precision,
        parameters=default_parameters,
    ).weak_form()

    x = _np.random.RandomState(0).randn(space1.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)
def test_maxwell_operators(points, operator, wavenumber, space_type):
    """Test dense assembler for the Helmholtz operators."""
    grid = bempp.api.shapes.regular_sphere(0)
    space = function_space(grid, *space_type)
    fun = bempp.api.GridFunction(space,
                                 coefficients=np.random.rand(
                                     space.global_dof_count))

    operator(space, points, wavenumber).evaluate(fun)
def p1_trace(fenics_space):
    """
    Return the P1 trace operator.

    This function returns a pair (space, trace_matrix),
    where space is a BEM++ space object and trace_matrix is the corresponding
    matrix that maps the coefficients of a FEniCS function to its boundary
    trace coefficients in the corresponding BEM++ space.

    """

    import dolfin  #pylint: disable=import-error
    from bempp.api.fenics_interface.coupling import fenics_space_info
    from bempp.api import function_space, grid_from_element_data
    import numpy as np

    family, degree = fenics_space_info(fenics_space)
    if not (family == 'Lagrange' and degree == 1):
        raise ValueError("fenics_space must be a p1 Lagrange space")

    mesh = fenics_space.mesh()

    boundary_mesh = dolfin.BoundaryMesh(mesh, "exterior", False)
    bm_nodes = boundary_mesh.entity_map(0).array().astype(np.int64)
    bm_coords = boundary_mesh.coordinates()
    bm_cells = boundary_mesh.cells()
    bempp_boundary_grid = grid_from_element_data(bm_coords.transpose(),
                                                 bm_cells.transpose())

    # First get trace space
    space = function_space(bempp_boundary_grid, "P", 1)

    # Now compute the mapping from FEniCS dofs to BEM++ dofs.

    # First the BEM++ dofs from the boundary vertices
    from scipy.sparse import coo_matrix
    bempp_dofs_from_b_vertices = p1_dof_to_vertex_matrix(space).transpose()

    # Now FEniCS vertices to boundary dofs
    b_vertices_from_vertices = coo_matrix(
        (np.ones(len(bm_nodes)), (np.arange(len(bm_nodes)), bm_nodes)),
        shape=(len(bm_nodes), mesh.num_vertices()),
        dtype='float64').tocsc()

    # Finally FEniCS dofs to vertices.
    vertices_from_fenics_dofs = coo_matrix(
        (np.ones(mesh.num_vertices()), (dolfin.dof_to_vertex_map(fenics_space),
                                        np.arange(mesh.num_vertices()))),
        shape=(mesh.num_vertices(), mesh.num_vertices()),
        dtype='float64').tocsc()

    # Get trace matrix by multiplication
    trace_matrix = bempp_dofs_from_b_vertices * \
        b_vertices_from_vertices * vertices_from_fenics_dofs

    # Now return everything
    return space, trace_matrix
Exemple #27
0
def test_helmholtz_potentials_segments(default_parameters, helpers,
                                       device_interface, precision):
    """Test Helmholtz potentials on segments."""
    import bempp.api
    from bempp.api import function_space
    from bempp.api.operators.potential.helmholtz import single_layer
    from bempp.api.operators.potential.helmholtz import double_layer
    from bempp.api.grid.grid import grid_from_segments

    grid = bempp.api.shapes.multitrace_cube()

    seglists = [[1, 2, 3, 4, 5, 6], [6, 7, 8, 9, 10, 11]]
    swapped_normal_lists = [{}, {6}]

    rand = _np.random.RandomState(0)

    for op in [single_layer, double_layer]:
        for seglist, swapped_normals in zip(seglists, swapped_normal_lists):
            new_grid = grid_from_segments(grid, seglist)

            coeffs = rand.rand(new_grid.number_of_vertices)

            space1 = function_space(
                grid,
                "P",
                1,
                segments=seglist,
                swapped_normals=swapped_normals,
                include_boundary_dofs=True,
            )
            space2 = function_space(new_grid,
                                    "P",
                                    1,
                                    swapped_normals=swapped_normals)

            points = _np.array([2.3, 1.3, 1.5]).reshape(3, 1) + rand.rand(3, 5)
            fun1 = bempp.api.GridFunction(space1, coefficients=coeffs)
            fun2 = bempp.api.GridFunction(space2, coefficients=coeffs)

            actual = op(space1, points, 2.5) * fun1
            expected = op(space2, points, 2.5) * fun2

            _np.testing.assert_allclose(
                actual, expected, rtol=helpers.default_tolerance(precision))
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)
Exemple #29
0
def perturbate(grid, t, kappa_pert=None):
    P1 = bem.function_space(grid, 'P', 1)
    grid_funz = bem.GridFunction(P1, fun=Phiz)
    elements = grid.leaf_view.elements
    vertices = grid.leaf_view.vertices
    normals = P1.global_dof_normals
    x, y, z = vertices

    vertices[2, :] = z + t * grid_funz.coefficients
    return bem.grid_from_element_data(vertices, elements)
Exemple #30
0
def discretize(grid, *methods_list):
    """
    Returns a named tuple containing the discretised boundaries of the
    given grid according to the method specified.
    """
    space = {}
    methods = list(set(methods_list))
    assert len(methods) > 0, "You must provide disretisation methods."
    for method_key in methods:
        method = method_key.split(".")[0]
        space[method_key] = function_space(grid, method, 0)
    return space
def test_maxwell_electric_field_bc_sphere(default_parameters, helpers,
                                          device_interface, precision):
    """Test Maxwell electric field on sphere with BC basis."""
    from bempp.api import get_precision
    from bempp.api import function_space
    from bempp.api.operators.boundary.maxwell import electric_field

    grid = helpers.load_grid("sphere")

    space1 = function_space(grid, "BC", 0)
    space2 = function_space(grid, "SNC", 0)

    rand = _np.random.RandomState(0)
    vec = rand.rand(space1.global_dof_count)

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

    actual = discrete_op @ vec

    if precision == "single":
        rtol = 1e-5
        atol = 1e-6
    else:
        rtol = 1e-10
        atol = 1e-14

    mat = helpers.load_npy_data("maxwell_electric_field_boundary_bc")

    expected = mat @ vec

    _np.testing.assert_allclose(actual, expected, rtol=rtol, atol=atol)
Exemple #32
0
def generic_pn_trace(fenics_space):
    import dolfin
    from .coupling import fenics_space_info
    from bempp.api import function_space, grid_from_element_data, GridFunction
    from bempp.api.common import global_parameters
    import numpy as np

    family,degree = fenics_space_info(fenics_space)
    if not (family=='Lagrange'):
        raise ValueError("fenics_space different from Lagrange space not yet tested!")

    mesh = fenics_space.mesh()

    bm = dolfin.BoundaryMesh(mesh, "exterior", False)
    bm_nodes  = bm.entity_map(0).array().astype(np.int64)
    bm_coords = bm.coordinates()
    bm_cells  = bm.cells()
    bempp_boundary_grid = grid_from_element_data(bm_coords.transpose(), bm_cells.transpose())

    # Create compatible trace function space
    space = function_space(bempp_boundary_grid, "P", degree)

    # Now compute the mapping from BEM++ dofs to FEniCS dofs
    from scipy.sparse import coo_matrix

    parameters = global_parameters()
    parameters.quadrature.far.single_order = 5 # TODO: use interplolation order accoriding to target space order

    def FenicsData(x, n, domain_index, result):
        value = np.empty(1)
        u_FEM.eval(value, x)
        result[0] = value

    u_FEM = dolfin.Function(fenics_space)
    N = u_FEM.vector().size()
    u_FEM.vector()[:] = np.arange(N)
    u_BEM = GridFunction(space, dual_space=space, fun=FenicsData, parameters=parameters)
    FEM2BEM = np.rint(u_BEM.coefficients).astype(np.int64)
    if max(abs(FEM2BEM-u_BEM.coefficients)) > 0.1:
        raise ValueError("interpolation from FEM to BEM space too inaccurate.")
    NB = len(FEM2BEM)
    trace_matrix = coo_matrix((
        np.ones(NB),(np.arange(NB),FEM2BEM)),
        shape=(NB,N),dtype='float64').tocsc()

    # Now return everything
    return space, trace_matrix
Exemple #33
0
def p1_trace(fenics_space):
    import dolfin
    from .coupling import fenics_space_info
    from bempp.api import function_space, grid_from_element_data
    import numpy as np

    family, degree = fenics_space_info(fenics_space)
    if not (family == 'Lagrange' and degree == 1):
        raise ValueError("fenics_space must be a p1 Lagrange space")

    mesh = fenics_space.mesh()

    bm = dolfin.BoundaryMesh(mesh, "exterior", False)
    bm_nodes = bm.entity_map(0).array().astype(np.int64)
    bm_coords = bm.coordinates()
    bm_cells = bm.cells()
    bempp_boundary_grid = grid_from_element_data(bm_coords.transpose(), bm_cells.transpose())

    # First get trace space 
    space = function_space(bempp_boundary_grid, "P", 1)

    # Now compute the mapping from BEM++ dofs to FEniCS dofs

    # First the BEM++ dofs to the boundary vertices
    from scipy.sparse import coo_matrix

    vertex_indices = np.arange(space.global_dof_count)
    data = np.ones(space.global_dof_count)
    bempp_dofs_from_b_vertices = p1_dof_to_vertex_matrix(space).transpose()

    # Now the boundary vertices to all the vertices
    b_vertices_from_vertices = coo_matrix((
        np.ones(len(bm_nodes)), (np.arange(len(bm_nodes)), bm_nodes)),
        shape=(len(bm_nodes), mesh.num_vertices()), dtype='float64').tocsc()

    # Finally the vertices to FEniCS dofs
    vertices_from_fenics_dofs = coo_matrix((
        np.ones(mesh.num_vertices()), (dolfin.dof_to_vertex_map(fenics_space), np.arange(mesh.num_vertices()))),
        shape=(mesh.num_vertices(), mesh.num_vertices()), dtype='float64').tocsc()

    # Get trace matrix by multiplication
    trace_matrix = bempp_dofs_from_b_vertices * b_vertices_from_vertices * vertices_from_fenics_dofs

    # Now return everything
    return space, trace_matrix
Exemple #34
0
    def __init__(self, kcomplex, n, geofile="sphere-simple.script.geo", meshname="tmp.msh"):
        self.ks = [kcomplex]
        self.kExt = kcomplex
        self.n = n
        self.kInt = kcomplex * np.sqrt(n)

        self.geofile = geofile
        self.meshname = meshname

        with open("in.geo", "w") as fp:
            fp.write("k = {};".format(np.abs(self.kInt)))
        with open("out.geo", "w") as fp:
            fp.write('\nSave "{}";\n'.format(meshname))
        call(["gmsh", geofile, "-"])

        self.grid = grid = bem.import_grid(meshname)
        self.space = space = bem.function_space(grid, "P", 1)
        self.shape = self.space.global_dof_count

        self.collect()
        self.weak_form()
Exemple #35
0
import numpy as np
import scipy.linalg as la
import scipy.sparse as sp
import scipy.sparse.linalg as spla
import  matplotlib.pyplot as plt

import bempp.api as bem

k = 0.2
lmbda = 2 * np.pi / k
nlmbda = 15

grid = bem.shapes.sphere(h=lmbda/nlmbda)

P1 = bem.function_space(grid, "P", 1)
#P0 = bem.function_space(grid, "DP", 0)
P0 = bem.function_space(grid, "P", 1)

N0, N1 = P0.global_dof_count, P1.global_dof_count

opV = bem.operators.boundary.helmholtz.single_layer(P0, P0, P0, k)
opI0 = bem.operators.boundary.sparse.identity(P0, P0, P0)

opK = bem.operators.boundary.helmholtz.double_layer(P1, P0, P0, k)
opI10 = bem.operators.boundary.sparse.identity(P1, P0, P0)

opQ = bem.operators.boundary.helmholtz.adjoint_double_layer(P0, P1, P1, k)
opI01 = bem.operators.boundary.sparse.identity(P0, P1, P1)

opW = bem.operators.boundary.helmholtz.hypersingular(P1, P1, P1, k)
Exemple #36
0
def fs(grid, **kwargs):
    return bem.function_space(grid, "P", 1, **kwargs)
Exemple #37
0
def evalZeros(point, normal, dom_ind, result):
    result[0] = 0. + 1j * 0.

inf = '0'

rhss = [] * len(domains)

rhs = [] * len(domains)
neighbors = domains.getNeighborOf(inf)
for ii in range(len(domains)):
    name = domains.getName(ii)
    dom = domains.getEntry(name)
    jj = domains.getIndexDom(dom['name'])
    print('==Domain: {0} #{1}'.format(dom['name'], ii))

    space_d = bem.function_space(grid, kind_d[0], kind_d[1], domains=dom['interfaces'])
    space_n = bem.function_space(grid, kind_n[0], kind_n[1], domains=dom['interfaces'])

    if dom['name'] == inf:
        IncDirichletTrace = bem.GridFunction(space_d, fun=evalIncDirichletTrace)
        IncNeumannTrace = bem.GridFunction(space_n, fun=evalIncNeumannTrace)
        idir, ineu = IncDirichletTrace, - IncNeumannTrace

    elif dom in neighbors:
        IncDirichletTrace = bem.GridFunction(space_d, fun=evalIncDirichletTrace)
        IncNeumannTrace = bem.GridFunction(space_n, fun=evalIncNeumannTrace)
        idir, ineu = - IncDirichletTrace, - IncNeumannTrace

    else:
        IncDirichletTrace = bem.GridFunction(space_d, fun=evalZeros)
        IncNeumannTrace = bem.GridFunction(space_n, fun=evalZeros)
Exemple #38
0
        resn = [-1]
    return resn, ts, x
#

H = [1., 0.75, 0.5, 0.25, 0.1, 0.075] #, 0.05, 0.025]

Dof = np.zeros((len(H), 7))
Its = np.zeros((len(H), 7))
Tps = np.zeros((len(H), 7))
STps = np.zeros((len(H), 7))

for i, h in enumerate(H):
    print(h)
    grid = bem.shapes.sphere(h=h)

    P0 = bem.function_space(grid, "DP", 0)
    P1 = bem.function_space(grid, "P", 1)

    P0d = bem.function_space(grid, "DUAL", 0)
    P1b = bem.function_space(grid, "B-P", 1)

    opV00 = bem.operators.boundary.laplace.single_layer(P0, P1, P0)
    # opW00 = bem.operators.boundary.helmholtz.hypersingular(P0, P1, P0,
    #                                                        wave_number=0.1)
    opJ00 = bem.operators.boundary.sparse.identity(P0, P1, P0)

    opV = bem.operators.boundary.laplace.single_layer(P0d, P1b, P0d)
    opW = bem.operators.boundary.laplace.hypersingular(P1b, P0d, P1b)

    opJ = bem.operators.boundary.sparse.identity(opV.domain,
                                                 opW.dual_to_range,
Exemple #39
0
t = 2*np.pi * np.linspace(0, 1, N)
Psi = psi(t)

kRef = Psi[0]
kRef = 1.

kExt, kInt = kRef, np.sqrt(n) * kRef

with open('in.geo', 'w') as fp:
    fp.write("k = {};".format(np.abs(kInt)))
    from subprocess import call
call(['gmsh', 'sphere-simple.script.geo', '-'])
meshname = 'sphere-simple.msh'

grid = bem.import_grid(meshname)
space = bem.function_space(grid, "P", 1)
shape = space.global_dof_count

K0 = bem.operators.boundary.helmholtz.double_layer(space, space, space, kExt)
V0 = bem.operators.boundary.helmholtz.single_layer(space, space, space, kExt)
W0 = bem.operators.boundary.helmholtz.hypersingular(space, space, space, kExt)
Q0 = bem.operators.boundary.helmholtz.adjoint_double_layer(space, space, space, kExt)

sK0, sQ0 = -K0, -Q0

K1 = bem.operators.boundary.helmholtz.double_layer(space, space, space, kInt)
V1 = bem.operators.boundary.helmholtz.single_layer(space, space, space, kInt)
W1 = bem.operators.boundary.helmholtz.hypersingular(space, space, space, kInt)
Q1 = bem.operators.boundary.helmholtz.adjoint_double_layer(space, space, space, kInt)

Id = bem.operators.boundary.sparse.identity(space, space, space)