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)
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))
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()
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()
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")
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()
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()
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))
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))
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))
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))
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) )
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))
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()
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()
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)
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
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)
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)
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)
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
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
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()
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)
def fs(grid, **kwargs): return bem.function_space(grid, "P", 1, **kwargs)
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)
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,
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)