PDE Solver Registry System
MathHook uses a registry-based dispatch system for PDE solvers, eliminating hardcoded match statements and enabling O(1) solver lookup. This architecture is inspired by the ODE module registry and provides extensible, testable, and efficient solver selection.
π
Mathematical Definition
Registry-based dispatch uses a HashMap for O(1) lookup by PDE type:
Priority-based selection from multiple solvers per type ensures optimal solver choice.
Code Examples
Default Registry Usage
Create and use default registry with standard solvers
let registry = PDESolverRegistry::new();
// Automatically classify and solve
let solution = registry.solve(&pde)?;
Custom Poisson Solver
Register a custom solver for Poisson equation (non-homogeneous Laplace)
struct PoissonEquationSolver {
max_terms: usize,
}
impl PDESolver for PoissonEquationSolver {
fn solve(&self, pde: &Pde) -> PDEResult {
// Poisson solver logic here
Ok(PDESolution::laplace(solution, eigenvalues, coefficients))
}
fn can_solve(&self, pde_type: PdeType) -> bool {
matches!(pde_type, PdeType::Elliptic)
}
fn priority(&self) -> u8 {
90 // Lower than Laplace solver (100)
}
fn name(&self) -> &'static str {
"Poisson Equation Solver"
}
fn description(&self) -> &'static str {
"Solves Poisson equation βΒ²u = f with non-zero source term"
}
}
// Register custom solver
let mut registry = PDESolverRegistry::new();
registry.register(
PdeType::Elliptic,
Arc::new(PoissonEquationSolver { max_terms: 10 }),
);
Solver Discovery
List available solvers and inspect registry contents
let registry = PDESolverRegistry::new();
println!("Registered PDE types: {:?}", registry.registered_types());
// [Parabolic, Hyperbolic, Elliptic]
println!("Total solvers: {}", registry.solver_count());
// 3
// Get solver for specific type
if let Some(solver) = registry.get_solver(&PdeType::Parabolic) {
println!("Heat solver: {}", solver.name());
println!("Description: {}", solver.description());
}