Basis Functions#

Besides Integration, another basic building block of dealing with finite differential forms is basis functions. These determine values of the degrees of freedom actually mean. For a demonstration of what types of basis are available, see Basis Sets Visualization.

Basis Specifications#

To specify the basis that are to be used, the BasisSpecs type is used. This specifies the order of the basis and their type (using BasisType) for a single dimension.

class fdg.BasisSpecs(basis_type: fdg.enum_type.BasisType, order: int)#

Type that describes a set of basis functions.

Parameters:
derivatives(x: numpy.typing.ArrayLike, /) numpy.typing.NDArray[numpy.double]#

Evaluate basis function derivatives at given locations.

Parameters:

x (array_like) – Locations where the basis function derivatives should be evaluated.

Returns:

Array of basis function derivatives at the specified locations. It has one more dimension than x, with the last dimension corresponding to the basis function index.

Return type:

array

values(x: numpy.typing.ArrayLike, /) numpy.typing.NDArray[numpy.double]#

Evaluate basis functions at given locations.

Parameters:

x (array_like) – Locations where the basis functions should be evaluated.

Returns:

Array of basis function values at the specified locations. It has one more dimension than x, with the last dimension corresponding to the basis function index.

Return type:

array

order#

Order of the basis set.

Type:

int

type#

Type of the basis used for the set.

Type:

_BasisTypeHint

class fdg.BasisType(*values)[source]#

Type of basis that can be used for basis sets.

BERNSTEIN = 'bernstein'#
LAGRANGE_CHEBYSHEV_GAUSS = 'lagrange-chebyshev-gauss'#
LAGRANGE_UNIFORM = 'lagrange-uniform'#
LAGRNAGE_GAUSS = 'lagrange-gauss'#
LAGRNAGE_GAUSS_LOBATTO = 'lagrange-gauss-lobatto'#
LEGENDRE = 'legendre'#

While values of all basis functions can be computed with BasisSpecs, these are not cached. However, values of these bases at integration points are cached using BasisRegistry. Similarly to what was the case with IntegrationRegistry, there is a default one provided that is used if no other is specified.

class fdg.BasisRegistry#

Registry for basis sets.

This registry contains all available basis sets and caches them for efficient retrieval.

clear() None#

Release all held basis sets to reduce the memory usage.

usage() tuple[tuple[BasisSpecs, IntegrationSpecs], ...]#

Return the basis-integration pairs that are held by the registry.

Returns:

Tuple of basis-integration specifications pair for each of basis set held in the registry.

Return type:

tuple of (BasisSpecs, IntegrationSpecs)

fdg.DEFAULT_BASIS_REGISTRY = <fdg._fdg.BasisRegistry object>#

Registry for basis sets.

This registry contains all available basis sets and caches them for efficient retrieval.

The BasisRegistry registry used when another is not provided.

Function Spaces#

Just as was the case with IntegrationSpecs, when dealing with N-dimensional spaces BasisSpecs objects are bundled together into a FunctionSpace objects. These define the function space based on outer product of basis.

Given basis sets \(b^k = \left\{ b^k_1, \dots, b^k_{n_1} \right\}\) for \(k = 1, \dots, N\), the value of the different basis functions at point with position \(\vec{r} = \begin{bmatrix} x_1 \\ \vdots \\ x_N \end{bmatrix}\) is given by Equation (1). Based on this it is quite clear that the total number of basis functions in this case is \(\prod\limits_{i=1}^N n_i\).

(1)#\[\psi_{i_1, \dots, i_N} (\vec{r}) = \prod\limits_{j = 1}^N b^{j}_{i_1}(x_j)\]
class fdg.FunctionSpace(*specs: BasisSpec)#

Function space defined with basis.

Function space defined by tensor product of basis functions in each dimension. Basis for each dimension are defined by a BasisSpecs object.

Parameters:

*basis_specs (BasisSpecs) – Basis specifications for each dimension of the function space.

evaluate(*x: numpy.typing.NDArray[numpy.double], out: numpy.typing.NDArray[numpy.double] | None = None) numpy.typing.NDArray[numpy.double]:#

Evaluate basis functions at given locations.

Parameters:
  • *x (array) – Coordinates where the basis functions should be evaluated. Each array corresponds to a dimension in the function space.

  • out (array, optional) – Array where the results should be written to. If not given, a new one will be created and returned. It should have the same shape as x, but with an extra dimension added, the length of which is the total number of basis functions in the function space.

Returns:

Array of basis function values at the specified locations.

Return type:

array

lower_order(idim: int) FunctionSpace#

Create a copy of the space with a lowered order in the specified dimension.

Parameters:

idim (int) – Index of the dimension to lower the order on.

Returns:

New function space with a lower order in the specified dimension.

Return type:

FunctionSpace

values_at_integration_nodes(integration: IntegrationSpace, /, *, integration_registry: IntegrationRegistry = DEFAULT_INTEGRATION_REGISTRY, basis_registry: BasisRegistry = DEFAULT_BASIS_REGISTRY) numpy.typing.NDArray[numpy.double]#

Return values of basis at integration points.

Parameters:
  • integration (IntegrationSpace) – Integration space, the nodes of which are used to evaluate basis at.

  • integration_registry (IntegrationRegistry, defaul: DEFAULT_INTEGRATION_REGISTRY) – Registry used to obtain the integration rules from.

  • basis_registry (BasisRegistry, default: DEFAULT_BASIS_REGISTRY) – Registry used to look up basis values.

Returns:

Array of basis function values at the integration points locations.

Return type:

array

basis_specs#

Basis specifications that define the function space.

Type:

tuple[BasisSpecs, …]

dimension#

Number of dimensions in the function space.

Type:

int

orders#

Orders of the basis functions in the function space.

Type:

tuple[int, …]