archimedes.approximation.ConstrainedBasis¶
- class archimedes.approximation.ConstrainedBasis( )¶
A basis whose functions are fixed linear combinations of another’s
Usually built so that every combination satisfies a set of linear constraints on the reference domain, for example to satisfy a boundary condition by construction.
Given a constraint matrix \(A\) (one row per constraint, one column per
basefunction), the new basis functions are\[\phi_i(x) = \sum_j N_{ji} \, \psi_j(x)\]where the columns of \(N\) span \(\mathrm{null}(A)\), i.e. \(A N \approx 0\). Every function in the new basis therefore satisfies every constraint row to numerical precision.
Should typically not be constructed directly; use one of the classmethod constructors instead.
Methods
boundary_dofs([order])Indices of the degrees of freedom at the left/right ends of the domain.
dirichlet(base)Construct a basis that vanishes at both reference endpoints.
evaluate(x[, deriv, side])Evaluate all
n_basisbasis functions atx.from_constraints(base, constraints)Construct a basis from the nullspace of a provided matrix.
neumann(base)Construct a basis whose derivatives vanish at both reference endpoints.
Attributes
The target-domain parameters this basis expects.
Whether this basis is orthonormal with respect to a probability measure (unit mass) rather than the raw weight of the associated
Measure.Number of independent variables the basis functions take.
The basis that is recombined to form the constrained basis.
Constraint matrix defining the new basis as linear combinations of
base.- classmethod dirichlet(
- base: Basis,
Construct a basis that vanishes at both reference endpoints.
The resulting basis satisfies the Dirichlet boundary condition \(\phi(-1) = \phi(1) = 0\).
Spans the same space as the classical hand-derived combinations (e.g. Shen’s Chebyshev-Galerkin basis \(T_k - T_{k+2}\)), but is not necessarily numerically identical to them. Both are valid bases of \(\mathrm{null}(A)\).
This cannot be constructed to hold nonzero values at the endpoints; see
ConcatBasisfor combining this with another “vertex” basis to hold nonzero endpoint values.Examples
>>> import numpy as np >>> from archimedes.approximation import ( ... ConstrainedBasis, ... OrthogonalPolynomialBasis, ... ) >>> from archimedes.measure import LegendreMeasure >>> legendre = OrthogonalPolynomialBasis(LegendreMeasure(), 6) >>> basis = ConstrainedBasis.dirichlet(legendre) >>> basis.n_basis 4 >>> x = np.array([-1.0, 1.0]) >>> bool(np.allclose(basis.evaluate(x), 0.0)) True
- classmethod from_constraints( ) ConstrainedBasis¶
Construct a basis from the nullspace of a provided matrix.
The constraint matrix is
null(A), whereA = constraints(base).A useful way to construct the
constraintsfunction is by evaluating thebasebasis.Basis.evaluate()returns a Vandermonde-like matrix with one row per point and one column per basis function. IfA = base.evaluate(x), thenA @ cevaluates the function defined by coefficient vectorcatx. Hence the condition that the function vanish atxis the same asA @ c = 0; in other wordsnull(A)is the set of coefficient vectors whose function vanishes atx. See example below.- Parameters:
base (Basis) – The basis to combine.
constraints (callable) –
constraints(base) -> ndarrayof shape(n_constraints, base.n_basis).
Examples
Build a basis where every function vanishes at the left endpoint only:
>>> import numpy as np >>> from archimedes.approximation import ( ... ConstrainedBasis, ... FunctionSpace, ... OrthogonalPolynomialBasis, ... ) >>> from archimedes.measure import LegendreMeasure, UnitInterval >>> legendre = OrthogonalPolynomialBasis(LegendreMeasure(), 6) >>> basis = ConstrainedBasis.from_constraints( ... legendre, lambda base: base.evaluate(np.array([-1.0])) ... ) >>> basis.n_basis 5
Any combination of the new functions satisfies the constraint:
>>> coeffs = np.random.default_rng(0).standard_normal(basis.n_basis) >>> x = np.array([-1.0, 0.0, 1.0]) >>> u = basis.evaluate(x) @ coeffs >>> bool(np.isclose(u[0], 0.0)) True
The constraint is imposed on the reference domain, so it holds at the left endpoint of any target interval:
>>> space = FunctionSpace(basis, UnitInterval.Parameters(a=0.0, b=2.0)) >>> f = space.project(np.sin) >>> bool(np.isclose(f(np.array([0.0]))[0], 0.0)) True
- classmethod neumann(
- base: Basis,
Construct a basis whose derivatives vanish at both reference endpoints.
The resulting basis satisfies the Neumann boundary condition \(\phi'(-1) = \phi'(1) = 0\).
Examples
>>> import numpy as np >>> from archimedes.approximation import ( ... ConstrainedBasis, ... OrthogonalPolynomialBasis, ... ) >>> from archimedes.measure import LegendreMeasure >>> legendre = OrthogonalPolynomialBasis(LegendreMeasure(), 6) >>> basis = ConstrainedBasis.neumann(legendre) >>> basis.n_basis 4 >>> x = np.array([-1.0, 1.0]) >>> dphi = basis.evaluate(x, deriv=1) >>> bool(np.allclose(dphi, 0.0)) True
- boundary_dofs(order: int = 0) tuple[int | None, int | None]¶
Indices of the degrees of freedom at the left/right ends of the domain.
Can be used for example to set boundary conditions or enforce continuity at the domain endpoints.
- Parameters:
order (int, optional) – Derivative order to look up. Default 0 (the endpoint value).
- Returns:
left, right – Index into this basis’s functions, or
Nonewhere there is no degree of freedom of that order at that end.- Return type:
int or None
Notes
Only meaningful for nodal families (e.g.
LagrangeBasis) with nodes at the endpoints. Modal families (e.g.OrthogonalPolynomialBasis) and nodal bases with interior-only nodes (Gauss-Legendre points, for instance) do not have boundary DOFs.
- evaluate(x, deriv: int = 0, *, side: str = RIGHT, **domain_kwargs)¶
Evaluate all
n_basisbasis functions atx.- Parameters:
x (array_like) – Evaluation points, shape
(npts,).deriv (int, optional) – Order of derivative to evaluate. Default 0.
side ({"right", "left"}, optional) – Which one-sided limit to take where the basis is two-valued. Default
"right". Irrelevant for smooth bases.**domain_kwargs – Target-domain parameters; see the subclass docstring.
- Returns:
phi – Basis values (or
deriv-th derivatives), shape(npts, n_basis).- Return type:
ndarray
- property Parameters: type¶
The target-domain parameters this basis expects.
A
Parameterssubclass (e.g.UnitInterval.Parameters). Returns the type, not an instance.Determines which reference domain the basis is defined on, for example:
UnitIntervalfor \([-1, 1]\).HalfLinefor \([0, \infty)\).RealLinefor \((-\infty, \infty)\).
- density: bool = False¶
Whether this basis is orthonormal with respect to a probability measure (unit mass) rather than the raw weight of the associated
Measure.Only meaningful for orthogonal polynomial families based on a
Measure(in particularOrthogonalPolynomialBasis); other families should leave thisFalse.
- property n_basis: int¶
- ndim: int = 1¶
Number of independent variables the basis functions take.
Typically 1, since most bases are univariate.
TensorBasisis the exception, with one variable per tensored factor.