archimedes.quadrature.TensorQuadratureRule¶

class archimedes.quadrature.TensorQuadratureRule(
rules: tuple[QuadratureRule, ...],
)¶

Cartesian product of one-dimensional quadrature rules.

Implements the Quadrature interface with ndim > 1. nodes is an (n, ndim) array with one row per node and one column per dimension. Each node still has a single scalar weight, so weights still has shape (n,).

Exactness is preserved dimension by dimension: if rule k is exact through degree \(p_k\), the product is exact for any polynomial whose degree in \(x_k\) is at most \(p_k\). In particular, the rule is exact for the tensor-product polynomial space.

The node count is \(\prod_k n_k\), exponential in ndim; sparse (Smolyak) quadrature is planned as a future alternative.

Parameters:

rules (tuple of QuadratureRule) – One rule per dimension, in order. Their measures may differ. Passing a single rule is allowed and gives a valid ndim == 1 tensor rule.

See also

tensor_quad

Constructor taking the per-dimension rules variadically.

composite_quad

Tile a rule across sub-elements within one dimension; apply it per-dimension before tensoring to get a rectilinear mesh.

Methods

integrate(f, *[, axis, args, density])

Approximate the weighted integral of f over the target domain.

map_to(*params, **kwparams)

A new tensor rule with every dimension mapped onto its target domain.

sum(values, *[, axis, density])

Quadrature applied to values already sampled at the nodes.

Attributes

breakpoints

Per-dimension element boundaries, one entry per dimension, each None unless that dimension's rule is composite.

elements

Owning sub-element per node and dimension, shape (n, ndim), or None if no dimension has element structure.

measures

the dimensions are independent and may use different families.

ndim

Number of dimensions, i.e. the number of rules tensored.

nodes

Nodes on the target domain, shape (n, ndim).

weights

Weights including the Jacobian of the target domain, shape (n,).

rules

__init__(
rules: tuple[QuadratureRule, ...],
) → None¶
integrate(
f: Callable[[...], ndarray],
*,
axis: int = 0,
args: Sequence[Any] | None = None,
density: bool = False,
) → ndarray¶

Approximate the weighted integral of f over the target domain.

Parameters:
  • f (callable) – Integrand, called once as f(x, *args) with the full (n, ndim) node array – so it must be vectorized over rows, and must index its own arguments out of the columns (e.g. lambda x: g(x[:, 0], x[:, 1])). This is the same convention as FunctionSpace.project.

  • axis (int, optional) – Axis of f’s output holding the nodes. Default 0, matching the nodes-first (n, ndim) input (unlike the one-dimensional QuadratureRule.integrate(), whose default is -1).

  • args (tuple, optional) – Extra arguments passed to f after the node array.

  • density (bool, optional) – Normalize by the total mass; see sum().

Returns:

integral – Shape (m,) for vector-valued integrands, or () for scalar ones.

Return type:

ndarray

map_to(
*params: Any,
**kwparams: Any,
) → TensorQuadratureRule¶

A new tensor rule with every dimension mapped onto its target domain.

See QuadratureRule.map_to(). Each dimension is delegated to independently.

Parameters:

dims (sequence, optional) – One entry per dimension, positionally or as dims=. Each entry is that dimension’s domain parameters in any of the forms accepted by its measure: None for the reference domain, a ReferenceDomain.Parameters struct, a tuple of positional arguments ((a, b) for an interval), or a dict of keyword arguments. Omitted entirely, every dimension is mapped onto its reference domain.

Raises:
  • TypeError – If called with anything other than a single dims sequence, or if an entry is not one of the accepted forms.

  • ValueError – If dims does not have exactly ndim entries.

sum(
values: ndarray,
*,
axis: int = 0,
density: bool = False,
) → ndarray¶

Quadrature applied to values already sampled at the nodes.

Parameters:
  • values (array_like) – Sampled values with the nodes along axis: shape (n,) for a scalar integrand or (n, m) for a vector-valued one under the default axis=0.

  • axis (int, optional) – Axis holding the nodes. Default 0.

  • density (bool, optional) – If True, normalize the weights so they sum to 1 – equivalently divide by the total mass of the mapped product measure, the product of the per-dimension masses. For a Wiener-Askey correspondence this makes them the quadrature weights of the joint probability density of independent inputs. Default False.

Raises:

ValueError – If values has more than 2 dimensions, or if values.shape[axis] does not match the number of nodes.

property breakpoints: tuple[ndarray | None, ...]¶

Per-dimension element boundaries, one entry per dimension, each None unless that dimension’s rule is composite.

property elements: ndarray | None¶

Owning sub-element per node and dimension, shape (n, ndim), or None if no dimension has element structure.

Mirrors nodes: column d indexes dimension d’s elements, and is all-zero for a dimension whose rule is not composite.

property measures: tuple[Measure, ...]¶

the dimensions are independent and may use different families.

Type:

The per-dimension measures. There is no single measure

property ndim: int¶

Number of dimensions, i.e. the number of rules tensored.

property nodes: ndarray¶

Nodes on the target domain, shape (n, ndim).

Ordered with the first dimension varying slowest (C order, i.e. np.meshgrid(..., indexing="ij")).

property weights: ndarray¶

Weights including the Jacobian of the target domain, shape (n,).

The Jacobian of a product of affine maps is the product of their scales, so this is \(\bigl(\prod_k \mathrm{scale}_k\bigr)\) times the reference weights.