Grid Functions

In BEM++ data on a given grid is represented as a GridFunction object. A GridFunction consists of a set of basis function coefficients and a corresponding Space object. In the following we will discuss the different ways of creating a grid function in BEM++.

Initializing a grid function from a Python callable

Often, in applications we are given an analytic expression for boundary data. This is for example the case in many acoustic scattering problems, where a typical scenario is that the incoming data is a plane wave or a sound source. The following code defines a wave travelling with unit wavenumber along the x-axis in the positive direction.

import numpy as np
def fun(x, normal, domain_index, result):
    result[0] = np.exp(1j * x[0])

A valid Python callable always has the same interface as shown above. The first argument x is the coordinate of an evaluation point. The second argument normal is the normal direction at the evaluation point. The third one is the domain_index. This corresponds to the physical id in Gmsh and can be used to assign different boundary data to different parts of the grid. The last argument result is the variable that stores the value of the callable. It is a numpy array with as many components as the basis functions of the underlying space have. If a scalar space is given then result only has one component.

In order to discretise this callable we need to define a suitable space object. Below we define a space of continuous, piecewise linear functions on a spherical grid.

import bempp.api
grid = bempp.api.shapes.regular_sphere(5)
space = bempp.api.function_space(grid, "DP", 1)

The next command now discretizes the Python callable by projecting it onto the space.

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

There is quite a lot going on now as shown by the output logging messages. Before we describe in detail what is happening we want to visualize the grid_fun object. This can be done with the command

grid_fun.plot()

This command opens Gmsh externally as a viewer to show the GridFunction object. The results should look like the following.

_images/grid_fun.png

By default the real part of grid_fun is plotted. There are more advanced functions to control this behavior.

Let us take a closer look at what happens in the initialization of this GridFunction. Denote the global basis functions of the space by \(\Psi_j\), \(j=1,\dots,N\). The computation of the grid function consists of two steps.

  1. Compute the projection coefficients \(p_j = \int_{\Gamma}\overline{\Psi_j}(\xi)f(\xi)d\xi\), where \(f\) is the analytic function to be converted into a grid function and \(\Gamma\) is the surface defined by the grid.
  2. Compute the basis coefficients \(c_j\) from \(Mc=p\), where \(M\) is the mass matrix defined by \(M_{ij} = \int_{\Gamma}\overline{\Psi_i}(\xi)\Psi_j(\xi)d\xi\).

This is an orthogonal \(L^2(\Gamma)\)-projection onto the basis given by the \(\Psi_j\).

Initializing a grid function from coefficients or projections

Instead of an analytic expression we can initialize a GridFunction object also from a vector c of coefficients or a vector p of projections. This can be done as follows.

grid_fun = GridFunction(space, coefficients=c)
grid_fun = GridFunction(space, projections=p, dual_space=dual)

The argument dual_space gives the space with which the projection coefficients were computed. The parameter is optional and if it is not given then space == dual_space is assumed (i.e. \(L^2(\Gamma)\)-projection).

Function and class reference

class bempp.api.GridFunction(space, dual_space=None, fun=None, coefficients=None, projections=None, parameters=None)

Representation of functions on a grid.

coefficients

np.ndarray – Return or set the vector of coefficients.

component_count

int – Return the number of components of the grid function values.

space

bemp.api.space.Space – Return the space over which the GridFunction is defined.

grid

bempp.api.grid.Grid – Return the underlying grid.

parameters

bempp.api.ParameterList – Return the set of parameters.

representation

string – Return ‘primal’ if the coefficients of the Gridfunction are known. Return ‘dual’ if only the coefficients in the dual space are known.

coefficients

Return the function coefficients.

component_count

Return the number of components of the grid function values.

dtype

Return the dtype.

dual_space

Return the dual space.

evaluate(element, local_coordinates)

Evaluate grid function on a single element.

evaluate_surface_gradient(element, local_coordinates)

Evaluate surface gradient of grid function for scalar spaces.

classmethod from_ones(space)

Create a grid function with all coefficients set to one.

classmethod from_random(space)

Create a random grid function normalized to unit norm.

classmethod from_zeros(space)

Create a grid function with all coefficients set to one.

grid

Return the underlying grid.

integrate(element=None)

Integrate the function over the grid or a single element.

l2_norm(element=None)

L^2 norm of the function on a single element or on the mesh.

parameters

Return the parameters.

plot()

Plot the grid function.

projections(dual_space=None)

Compute the vector of projections onto the given dual space.

Parameters:dual_space (bempp.api.space.Space) – A representation of the dual space. If not specified then fun.dual_space is used.
Returns:out – A vector of projections onto the dual space.
Return type:np.ndarray
relative_error(fun, element=None)

Relative L^2 error compared to a given analytic function.

Parameters:
  • fun (callable) – A python callable of the form f(p), where p is a point with the three space components x, y, z at which to evaluate the function.
  • element (bempp.api.grid.entity.Entity) – An entity of codimension 0.
representation

Return ‘dual’ or ‘primal’.

space

Return the Space object.

surface_grad_norm(element=None)

Norm of the surface gradient on a single element or on the mesh.