Ejemplo n.º 1
0
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
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
def result_to_grid(res):
    '''
    Return a BEM++ grid object made from the larf.model.Result
    '''
    arrs = res.array_data_by_name()
    pts, tri, dom = arrs['vertices'],arrs['elements'],arrs['domains']
    assert pts.shape[1] == 3
    assert len(tri) == len(dom)
    pts, tri = make_unique(pts, tri)
    return bem.grid_from_element_data(pts.T,tri.T,dom)
Ejemplo n.º 4
0
def boundary_grid_from_fenics_mesh(fenics_mesh):
    """
    Return a boundary grid from a FEniCS Mesh.
    """
    from bempp.api import grid_from_element_data

    bm = _dolfin.BoundaryMesh(fenics_mesh, "exterior", False)
    bm_coords = bm.coordinates()
    bm_cells  = bm.cells()
    bempp_boundary_grid = grid_from_element_data(bm_coords.transpose(),bm_cells.transpose())
    return bempp_boundary_grid
Ejemplo n.º 5
0
def boundary_grid_from_fenics_mesh(fenics_mesh):
    """
    Return a boundary grid from a FEniCS Mesh.
    """
    from bempp.api import grid_from_element_data

    boundary_mesh = _dolfin.BoundaryMesh(fenics_mesh, "exterior", False)
    bm_coords = boundary_mesh.coordinates()
    bm_cells = boundary_mesh.cells()
    bempp_boundary_grid = grid_from_element_data(bm_coords.transpose(),
                                                 bm_cells.transpose())
    return bempp_boundary_grid
Ejemplo n.º 6
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
Ejemplo n.º 7
0
    def grid(self):
        "Return a BEM++ grid object for the scene."
        points = list()
        domains = list()
        triangles = list()
        point_offset = 0
        for domain, mobjs in sorted(self.objects.items()):
            for mobj in mobjs:
                for p in mobj.points:
                    points.append(p)
                for tri in mobj.triangle:
                    triangles.append(point_offset + tri)
                    domains.append(domain)
                point_offset += len(mobj.points)

        points, triangles = make_unique(numpy.asarray(points), numpy.asarray(triangles))
        return bem.grid_from_element_data(points.T,triangles.T,domains)
Ejemplo n.º 8
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
Ejemplo n.º 9
0
    def test_grid_from_element_data(self):
        """Test grid generation from element data."""

        from bempp.api import grid_from_element_data

        grid = grid_from_element_data(VERTICES, ELEMENTS)

        box = grid.bounding_box
        self.assertTrue(np.all(box == np.array([[0, 0, 0], [1, 1, 0]])))
        self.assertEqual(grid.leaf_view.entity_count(0), 2)
        self.assertEqual(grid.leaf_view.entity_count(2), 4)

        actual_vertices = grid.leaf_view.vertices
        actual_elements = grid.leaf_view.elements

        self.assertEqual(actual_vertices.shape[1], 4)
        self.assertEqual(actual_elements.shape[1], 2)

        for vert in VERTICES.T:
            self.assertIn(vert, actual_vertices.T)
Ejemplo n.º 10
0
def HCurl_trace(ng_space, boundaries=None):
    """
    Return the lowest oder Nedelec 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 NGsolve function to its boundary
    trace coefficients in the corresponding BEM++ space.
    """

    import ngsolve as ngs
    from ngbem import surface_mesh_from_ng

    if (ng_space.type != 'hcurlho' or ng_space.globalorder != 0):
        raise ValueError("ng_space must be a valid  lowest order HCurl space")

    import ngsolve as ngs
    from bempp.api import function_space, grid_from_element_data, ALL
    import bempp.api
    import numpy as np

    mesh = ng_space.mesh

    [bm_coords, bm_cells, domain_indices,
     bm_nodes] = surface_mesh_from_ng(mesh)

    bempp_boundary_grid = grid_from_element_data(bm_coords, bm_cells,
                                                 domain_indices)

    # First get trace space
    space = function_space(bempp_boundary_grid, "RT", 0)

    # Now compute the mapping from NGSolve dofs to BEM++ dofs.
    bem_elements = list(bempp_boundary_grid.leaf_view.entity_iterator(0))

    n_bem = space.global_dof_count
    n_ng = ng_space.ndof

    k = 1
    print("doing order ", k, "dofs=", space.global_dof_count)
    nd = 3  ##number of degrees of freedom on the reference element
    from math import sqrt

    #setup the lagrange interpolation points for the BEM++ local basis

    eval_pts = np.asarray([[0.5, 0], [0, 0.5], [0.5, 0.5]]).T
    local_normals = np.asarray([[0, -1], [-1, 0], [1, 1]])

    local_tangentials = np.asarray([[-1, 1], [1, 0], [0, -1]])
    #the tangential vectors used by ngsolve
    ##local_tangentials=np.asarray([[-1,1],[1,0],[0,-1]]); #the tangential vectors used by ngsolve

    local_bem_to_ng = np.zeros([nd, nd])

    #NGSolve and BEM++ use a different reference element.
    #The map TA x + b does this transformatuib
    TA = np.asarray([[-1, -1], [1, 0]])
    Tb = np.asarray([1, 0])

    todo = np.ones([n_bem])
    #stores  which indices we already visited

    iis = np.zeros([nd * n_bem], dtype=np.int64)
    ijs = np.zeros([nd * n_bem], dtype=np.int64)
    data = np.zeros([nd * n_bem])

    elId = 0

    idCnt = 0
    #on each element, we map from ngsolve to the reference element,
    #do the local transformation there and then transform back to the global BEM++ dofs
    for el in ng_space.Elements(ngs.BND):
        bem_el = bem_elements[elId]
        ng_dofs = el.dofs

        bem_global_dofs, bem_weights = space.get_global_dofs(bem_el,
                                                             dof_weights=True)

        ngshape = ng_space.GetFE(ngs.ElementId(el))

        #evaluate the NGSolve basis in the midpoint of edges times the tangential vectors
        # this corresponds to the functionals assigned to the Nedelec basis functions,
        # and most notably gives how the local DOFs are assigned to the edges (including the weights)
        # local_bem_to_ng should be  a permutation matrix up to signs
        for j in range(0, nd):
            tx = TA.dot(eval_pts[:, j]) + Tb
            # transfer to NGSolves reference element
            tangential = local_tangentials[j]
            #the tangentials are already stored transformed

            uj = ngshape.CalcShape(tx[0], tx[1], 0)

            for l in range(0, nd):
                local_bem_to_ng[l, j] = np.dot(uj[l, :], tangential)

        local_ndofs = len(ng_dofs)
        assert (nd == local_ndofs)

        bem_global_dofs, bem_weights = space.get_global_dofs(bem_el,
                                                             dof_weights=True)

        assert (len(bem_global_dofs) == len(ng_dofs))

        for i in range(0, local_ndofs):
            gbid = bem_global_dofs[i]
            if (todo[gbid] == 1):  ##we havent dealt with this index before
                for j in range(0, local_ndofs):
                    gngid = ng_dofs[j]
                    iis[idCnt] = gbid
                    ijs[idCnt] = gngid
                    data[idCnt] = bem_weights[i] * local_bem_to_ng[j, i]

                    idCnt += 1
                todo[gbid] -= 1

        elId += 1

    assert (np.count_nonzero(todo) == 0)
    assert (idCnt == nd * n_bem)

    # build up the sparse matrix containing our transformation
    from scipy.sparse import coo_matrix

    trace_matrix = coo_matrix((data, (iis, ijs)),
                              shape=(space.global_dof_count, ng_space.ndof))

    # Now return everything
    return space, trace_matrix
Ejemplo n.º 11
0
def p1_trace(ng_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 NGsolve function to its boundary
    trace coefficients in the corresponding BEM++ space.
    """

    import ngsolve as ngs

    if (ng_space.globalorder != 1):
        raise ValueError("ng_space must be a p1 H1 space")

    import ngsolve as ngs
    from bempp.api import function_space, grid_from_element_data
    import numpy as np

    mesh = ng_space.mesh

    [bm_coords, bm_cells, domain_indices,
     bm_nodes] = surface_mesh_from_ng(mesh)

    [bm_coords, bm_cells, domain_indices,
     bm_nodes] = surface_mesh_from_ng(mesh)

    bempp_boundary_grid = grid_from_element_data(bm_coords, bm_cells,
                                                 domain_indices)

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

    # Now compute the mapping from NGSolve 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()

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

    # Finally NGSolve dofs to vertices.
    dofmap = np.zeros([ng_space.ndof], dtype='int64')
    for el in ng_space.Elements(ngs.BND):
        dofs = el.dofs
        vs = el.vertices
        dofmap[dofs] = [vs[j].nr for j in range(0, len(vs))]

    vertices_from_ngs_dofs = coo_matrix(
        (np.ones(mesh.nv), (dofmap, np.arange(mesh.nv))),
        shape=(mesh.nv, mesh.nv),
        dtype='float64').tocsc()

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

    # Now return everything
    return space, trace_matrix
Ejemplo n.º 12
0
def bempp_grid_from_data_set(grid_data_set):
    """Convert a grid data set to Bempp grid."""
    from bempp.api import grid_from_element_data

    return grid_from_element_data(grid_data_set.grid.vertices,
            grid_data_set.grid.elements, grid_data_set.grid.domain_indices)