In Bempp, data on a given grid is represented as a grid function object. A grid function consists of a set of basis function coefficients and a corresponding function space.
Initialising with a Python callable¶
Grid functions can be created from Python callables.
@bempp.api.complex_callable def fun(x, normal, domain_index, result): result = np.exp(1j * x)
The first argument
x is the coordinates 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.
A Python callable that you want to use to build a grid function should always have these four inputs. An optional fifth input may be used to pass parameters into the function.
In order for Bempp to assemble a grid function with coefficients of the correct data type,
these callables must be decorated with either
The projection of this callable into a Bempp space can be created with:
grid_fun = bempp.api.GridFunction(space, fun=fun)
Disabling just-in-time compilation¶
By default, Bempp with use Numba just-in-time compilation when creating grid functions from callables.
In some cases, this compilation is not possible and should be disabled. This can be
done by passing
jit=False into the decorator:
@bempp.api.complex_callable(jit=False) def fun(x, normal, domain_index, result): result = np.exp(1j * x) grid_fun = bempp.api.GridFunction(space, fun=fun)
The construction of this grid function will be slower as it is not sped up by Numba.
Initialising with coefficients or projections¶
Instead of a callable, we can initialise a grid function from a vector of coefficients or a vector of projections. This can be done as follows.
c = np.array([...]) # These are the coefficients grid_fun = GridFunction(space, coefficients=c) p = np.array([...]) # These are the projections grid_fun = GridFunction(space, projections=p, dual_space=dual)
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.
Coefficients and projections¶
The functions in a discrete function space are represented as a linear combination of some basis functions. The coefficients of a grid function are the scalars which each basis function is multiplied by in this combination. The coefficients of a grid function can be obtained using:
The projections of a grid function are calculated by applying a discrete mass matrix to the
coefficients. The mass matrix will be between the grid function’s space and a dual space
provided to the
projections call. These can be obtained using:
In some situations, for example when the space and the dual are RWG and SNC spaces, the mass matrix for projections may be numerically singular. In these cases, the coefficients of a grid function that has been initialised using projections cannot be accurately calculated. Bempp, however, can still use these grid functions by only querying the projections.
Plotting and exporting grid functions¶
To export a grid function, we can use the
This commands export the object
grid_fun as Gmsh file with the
In order to plot a grid function, we can simply use the command:
By default, this will plot using Gmsh (or plotly if you are inside a Jupyter notebook). The following command can be used to change the plotting backend.
bempp.api.PLOT_BACKEND = "gmsh" bempp.api.PLOT_BACKEND = "paraview"
This requires Gmsh or Paraview to be available in the system path.