zoomy_core.model.models.symbolic_integrator module

zoomy_core.model.models.symbolic_integrator module#

SymbolicIntegrator: unified interface for basis function integration.

Dispatches to the best available strategy based on basis capabilities: 1. Default: sympy.integrate (always works, can be slow) 2. Knot spans: split at knot boundaries, integrate simple polynomials per span (splines) 3. Quadrature: use analytical quadrature nodes if basis provides them (Chebyshev) 4. Parallel: farm independent integrals to processes (for large basis matrices)

The basis declares its capabilities via methods: - get_knot_spans() -> list of (a, b) intervals (splines) - quadrature_nodes(n) -> (nodes, weights) (Chebyshev) - bounds() -> [a, b] (all bases)

Usage:

integrator = SymbolicIntegrator(basis) M = integrator.mass_matrix(level) A = integrator.triple_product(level) val = integrator.integrate(expr, z, (0, 1))

class zoomy_core.model.models.symbolic_integrator.SymbolicIntegrator(basis, strategy='auto', n_workers=1, integral_timeout=30)#

Bases: object

Unified integration engine for basis functions.

By default, all integration is symbolic (sympy.integrate or knot-span piecewise integration). Numerical quadrature is available but must be requested explicitly via strategy='quadrature'.

If a single integral exceeds integral_timeout seconds a TimeoutError is raised so the caller can decide how to proceed.

property strategy#
integrate(expr, var, domain=None)#

Integrate expr over domain w.r.t. var.

Always symbolic unless the user explicitly selected ‘quadrature’. Raises TimeoutError if a single integral exceeds the timeout.

mass_matrix(level)#

Compute M[k,i] = integral(phi_k * phi_i * weight, domain). Symmetric.

triple_product(level)#

Compute A[k,i,j] = integral(phi_k * phi_i * phi_j * weight, domain).

Fully symmetric in (k,i,j) – only computes sorted indices k<=i<=j and fills all permutations. Saves 63% at n=3, 72% at n=5.

derivative_product(level)#

Compute D[k,i] = integral(dphi_k/dz * dphi_i/dz * weight, domain). Symmetric.

boundary_values(level)#

Compute phib[k] = phi_k(bounds[0]).

compute_all_matrices(level)#

Compute all standard basis matrices.

Exploits symmetry to minimize the number of integrals:

A[k,i,j]: fully symmetric -> only sorted k<=i<=j (63-72% savings) M, D, Dxi, Dxi2: symmetric -> upper triangle only (33-40% savings) DT[k,i,j]: symmetric in (k,i) -> k<=i only (33% savings) B[k,i,j]: no symmetry -> all entries

Basis evaluations phi_k(z), dphi_k(z), psi_k(z) are precomputed once.

project(expr, test_index, weight=None)#

Galerkin projection of expr onto test function phi_{test_index}. Returns integral(expr * phi_k * weight, domain) / M[k,k].