bempp 0.2.0

Boundary element method library.
import pytest
import numpy as np
from ndelement.reference_cell import ReferenceCellType
from bempp.assembly.boundary import OperatorType, create_laplace_assembler
from bempp.function_space import function_space
from ndgrid.shapes import regular_sphere
from ndelement.ciarlet import create_family, Family, Continuity


@pytest.mark.parametrize(
    "otype",
    [
        OperatorType.SingleLayer,
        OperatorType.DoubleLayer,
        OperatorType.AdjointDoubleLayer,
        OperatorType.Hypersingular,
    ],
)
def test_create_assembler(otype):
    a = create_laplace_assembler(otype)

    assert a.quadrature_degree(ReferenceCellType.Triangle) != 3
    a.set_quadrature_degree(ReferenceCellType.Triangle, 3)
    assert a.quadrature_degree(ReferenceCellType.Triangle) == 3
    with pytest.raises(ValueError):
        a.set_quadrature_degree(ReferenceCellType.Interval, 3)
    with pytest.raises(ValueError):
        a.quadrature_degree(ReferenceCellType.Interval)

    assert a.singular_quadrature_degree(ReferenceCellType.Triangle, ReferenceCellType.Triangle) != 3
    a.set_singular_quadrature_degree(ReferenceCellType.Triangle, ReferenceCellType.Triangle, 3)
    assert a.singular_quadrature_degree(ReferenceCellType.Triangle, ReferenceCellType.Triangle) == 3
    with pytest.raises(ValueError):
        a.set_singular_quadrature_degree(ReferenceCellType.Interval, ReferenceCellType.Interval, 3)

    assert a.batch_size != 4
    a.set_batch_size(4)
    assert a.batch_size == 4

    assert a.dtype == np.float64


@pytest.mark.parametrize(
    "operator",
    [
        OperatorType.SingleLayer,
        OperatorType.DoubleLayer,
        OperatorType.AdjointDoubleLayer,
        OperatorType.Hypersingular,
    ],
)
@pytest.mark.parametrize("test_degree", range(3))
@pytest.mark.parametrize("trial_degree", range(3))
def test_assemble_singular(operator, test_degree, trial_degree):
    grid = regular_sphere(0)
    test_element = create_family(Family.Lagrange, test_degree, Continuity.Discontinuous)
    test_space = function_space(grid, test_element)
    trial_element = create_family(Family.Lagrange, trial_degree, Continuity.Discontinuous)
    trial_space = function_space(grid, trial_element)

    a = create_laplace_assembler(operator)
    mat = a.assemble_singular(trial_space, test_space)

    dense = a.assemble_into_dense(trial_space, test_space)
    for i, j, value in zip(mat.row, mat.col, mat.data):
        assert np.isclose(dense[i, j], value)


@pytest.mark.parametrize(
    "operator",
    [
        OperatorType.SingleLayer,
        OperatorType.DoubleLayer,
        OperatorType.AdjointDoubleLayer,
        OperatorType.Hypersingular,
    ],
)
@pytest.mark.parametrize(
    "test_degree, test_continuity",
    [
        (0, Continuity.Discontinuous),
        (1, Continuity.Discontinuous),
        (1, Continuity.Standard),
        (2, Continuity.Standard),
    ],
)
@pytest.mark.parametrize(
    "trial_degree, trial_continuity",
    [
        (0, Continuity.Discontinuous),
        (1, Continuity.Discontinuous),
        (1, Continuity.Standard),
        (2, Continuity.Standard),
    ],
)
def test_assemble_singular_sparse_vs_dense(
    operator, test_degree, test_continuity, trial_degree, trial_continuity
):
    grid = regular_sphere(0)
    test_element = create_family(Family.Lagrange, test_degree, test_continuity)
    test_space = function_space(grid, test_element)
    trial_element = create_family(Family.Lagrange, trial_degree, trial_continuity)
    trial_space = function_space(grid, trial_element)

    a = create_laplace_assembler(operator)
    mat = a.assemble_singular(trial_space, test_space)

    dense = a.assemble_singular_into_dense(trial_space, test_space)
    assert np.allclose(dense, mat.todense())


@pytest.mark.parametrize(
    "operator",
    [
        OperatorType.SingleLayer,
        OperatorType.DoubleLayer,
        OperatorType.AdjointDoubleLayer,
        OperatorType.Hypersingular,
    ],
)
@pytest.mark.parametrize("test_degree", range(3))
@pytest.mark.parametrize("trial_degree", range(3))
def test_assemble_singular_correction(operator, test_degree, trial_degree):
    grid = regular_sphere(0)
    test_element = create_family(Family.Lagrange, test_degree, Continuity.Discontinuous)
    test_space = function_space(grid, test_element)
    trial_element = create_family(Family.Lagrange, trial_degree, Continuity.Discontinuous)
    trial_space = function_space(grid, trial_element)

    a = create_laplace_assembler(operator)
    a.assemble_singular_correction(trial_space, test_space)


@pytest.mark.parametrize(
    "operator",
    [
        OperatorType.SingleLayer,
        OperatorType.DoubleLayer,
        OperatorType.AdjointDoubleLayer,
        OperatorType.Hypersingular,
    ],
)
@pytest.mark.parametrize(
    "test_degree, test_continuity",
    [
        (0, Continuity.Discontinuous),
        (1, Continuity.Discontinuous),
        (1, Continuity.Standard),
        (2, Continuity.Standard),
    ],
)
@pytest.mark.parametrize(
    "trial_degree, trial_continuity",
    [
        (0, Continuity.Discontinuous),
        (1, Continuity.Discontinuous),
        (1, Continuity.Standard),
        (2, Continuity.Standard),
    ],
)
def test_assemble_singular_and_nonsingular(
    operator, test_degree, test_continuity, trial_degree, trial_continuity
):
    grid = regular_sphere(0)
    test_element = create_family(Family.Lagrange, test_degree, test_continuity)
    test_space = function_space(grid, test_element)
    trial_element = create_family(Family.Lagrange, trial_degree, trial_continuity)
    trial_space = function_space(grid, trial_element)

    a = create_laplace_assembler(operator)
    mat = a.assemble_singular_into_dense(trial_space, test_space)
    mat += a.assemble_nonsingular_into_dense(trial_space, test_space)

    mat2 = a.assemble_into_dense(trial_space, test_space)
    assert np.allclose(mat, mat2)


def test_single_layer_sphere0_dp0():
    grid = regular_sphere(0)
    element = create_family(Family.Lagrange, 0, Continuity.Discontinuous)
    space = function_space(grid, element)

    a = create_laplace_assembler(OperatorType.SingleLayer)

    mat = a.assemble_into_dense(space, space)

    from_cl = np.array(
        [
            [
                0.1854538822982487,
                0.08755414595678074,
                0.05963897421514472,
                0.08755414595678074,
                0.08755414595678074,
                0.05963897421514473,
                0.04670742127454548,
                0.05963897421514472,
            ],
            [
                0.08755414595678074,
                0.1854538822982487,
                0.08755414595678074,
                0.05963897421514472,
                0.05963897421514472,
                0.08755414595678074,
                0.05963897421514473,
                0.04670742127454548,
            ],
            [
                0.05963897421514472,
                0.08755414595678074,
                0.1854538822982487,
                0.08755414595678074,
                0.04670742127454548,
                0.05963897421514472,
                0.08755414595678074,
                0.05963897421514473,
            ],
            [
                0.08755414595678074,
                0.05963897421514472,
                0.08755414595678074,
                0.1854538822982487,
                0.05963897421514473,
                0.04670742127454548,
                0.05963897421514472,
                0.08755414595678074,
            ],
            [
                0.08755414595678074,
                0.05963897421514472,
                0.046707421274545476,
                0.05963897421514473,
                0.1854538822982487,
                0.08755414595678074,
                0.05963897421514472,
                0.08755414595678074,
            ],
            [
                0.05963897421514473,
                0.08755414595678074,
                0.05963897421514472,
                0.046707421274545476,
                0.08755414595678074,
                0.1854538822982487,
                0.08755414595678074,
                0.05963897421514472,
            ],
            [
                0.046707421274545476,
                0.05963897421514473,
                0.08755414595678074,
                0.05963897421514472,
                0.05963897421514472,
                0.08755414595678074,
                0.1854538822982487,
                0.08755414595678074,
            ],
            [
                0.05963897421514472,
                0.046707421274545476,
                0.05963897421514473,
                0.08755414595678074,
                0.08755414595678074,
                0.05963897421514472,
                0.08755414595678074,
                0.1854538822982487,
            ],
        ]
    )

    assert np.allclose(mat, from_cl, rtol=1e-4)