solver – ODE, Difference, and PDE Solving Engine
ODE, difference, and PDE solving engine.
- solver.solve_difference(recur_func, n_min, n_max, y0, order)[source]
Solve a difference equation by iterating the recurrence.
The recurrence has the form y_{n+order} = f(n, [y_n, y_{n+1}, …, y_{n+order-1}]). State vector at step n: y[0]=y_n, y[1]=y_{n+1}, …, y[order-1]=y_{n+order-1}.
- Parameters:
- Return type:
- Returns:
A
DifferenceSolutionwith n and y arrays. y has shape (order, n_points) for compatibility with ODE pipeline.
- solver.get_difference_function(*, expression=None, function_name=None, order, parameters=None)[source]
Resolve a difference equation function from expression or Python function.
Exactly one of expression or function_name must be provided.
- Parameters:
- Return type:
- Returns:
A callable
f(n, y)that returns the next value (scalar).- Raises:
EquationParseError – If expression is invalid or function cannot be resolved.
ValueError – If neither or both expression and function_name are provided.
- solver.get_ode_function(*, expression=None, function_name=None, order, parameters=None)[source]
Resolve an ODE function from either an expression string or a Python function.
Exactly one of expression or function_name must be provided.
- Parameters:
- Return type:
- Returns:
A callable
f(x, y)that returnsdy/dxas a 1-D array.- Raises:
EquationParseError – If expression is invalid or function cannot be resolved.
ValueError – If neither or both expression and function_name are provided.
- solver.get_vector_ode_function(*, vector_expressions, function_name=None, order, vector_components, parameters=None)[source]
Resolve a vector ODE function from expressions or Python function.
Exactly one of vector_expressions or function_name must be provided.
- Parameters:
vector_expressions (
list[str]) – List of expressions for each component’s highest derivative.function_name (
str|None) – Name of function in config.equations (returns full dydt).order (
int) – Order of each ODE component.vector_components (
int) – Number of components (f_0, f_1, …).parameters (
dict[str,float] |None) – Named parameter values.
- Return type:
- Returns:
A callable f(x, y) that returns dy/dx.
- Raises:
ValueError – If both or neither of vector_expressions and function_name provided.
EquationParseError – If expressions are invalid or function not found.
- solver.parse_pde_rhs_expression(expression, variables, parameters=None)[source]
Parse a PDE RHS expression into a callable f(x, y, …) -> float.
The expression can use variable names (x, y, z, …) or indexed notation (x[0], x[1], …) and parameters. Used for the RHS of Poisson-type equations -u_xx - u_yy = f(x,y).
- Parameters:
- Return type:
- Returns:
A callable that takes (x, y, …) and returns the RHS value.
- Raises:
EquationParseError – If the expression is invalid.
- solver.compute_ode_residual_error(ode_func, x, y)[source]
Compute residual error: how well does y satisfy dy/dx = f(x, y)?
Compares the ODE right-hand side f(x,y) with the numerical derivative of the solution. Large residuals indicate the solution may not satisfy the ODE well (e.g. coarse tolerances, stiff problem).
- Parameters:
- Return type:
- Returns:
Dict with residual_max, residual_mean, residual_rms (L2 norm per point).
- class solver.FNotation(kind, n_components=1, order=1, n_independent_vars=1, component_orders=())[source]
Bases:
objectDescribes the notation context for a particular equation.
- Variables:
kind – One of
"ode","vector_ode","difference","pde".n_components – Number of components (1 for scalar ODE / PDE / difference).
order – ODE order per component, or max derivative order for PDE.
n_independent_vars – Number of independent variables (1 for ODE, >=1 for PDE).
- Parameters:
- solver.generate_derivative_labels(notation)[source]
Generate labels for every entry in the flat state vector.
- class solver.ODESolution(x, y, success, message, method_used, n_eval=0, raw=None)[source]
Bases:
objectContainer for ODE solution data.
- Variables:
x – Independent variable values.
y – Solution array — shape
(n_vars, n_points).success – Whether the solver converged.
message – Solver status message.
method_used – Name of the integration method.
n_eval – Number of function evaluations (if available).
raw – The original
OdeResultfrom SciPy.
- Parameters:
- solver.solve_multipoint(ode_func, conditions, order, x_min, x_max, method=None, t_eval=None, max_step=None, rtol=None, atol=None)[source]
Solve an ODE with initial conditions specified at possibly different x points.
Uses a shooting method: the full state at
x_minis found via root-finding so that all given conditionsy^(k)(x_i) = a_iare satisfied.- Parameters:
ode_func (
Callable[[float,ndarray],ndarray]) – Right-hand side of the ODE systemdy/dx = f(x, y).conditions (
list[tuple[int,float,float]]) – List of(k, x_i, a_i)meaningy^(k)(x_i) = a_i.order (
int) – ODE order (equals number of conditions).x_min (
float) – Domain start.x_max (
float) – Domain end.t_eval (
ndarray|None) – Points at which to store the final solution.
- Return type:
- Returns:
An
ODESolutionwith the results.- Raises:
SolverFailedError – If the solver or shooting method fails.
- solver.solve_ode(ode_func, t_span, y0, method=None, t_eval=None, max_step=None, rtol=None, atol=None)[source]
Solve an initial-value ODE problem using
scipy.integrate.solve_ivp.- Parameters:
ode_func (
Callable[[float,ndarray],ndarray]) – Right-hand side of the ODE systemdy/dx = f(x, y).t_span (
tuple[float,float]) – Integration interval(x_min, x_max).method (
str|None) – Integration method name. Falls back to env default.t_eval (
ndarray|None) – Times at which to store the solution. IfNone, a uniform grid is generated from env settings.max_step (
float|None) – Maximum allowed step size (0 →np.inf).
- Return type:
- Returns:
An
ODESolutionwith the results.- Raises:
SolverFailedError – If the solver reports failure.
- solver.solve_pde_2d(residual_func, x_min, x_max, y_min, y_max, nx, ny, bc_values=None, parameters=None, mask=None, bc_type=None, bc_neumann_value=None)[source]
Solve a general 2D linear elliptic PDE using finite differences.
The residual_func is called as
residual_func(x, y, f, f_x, f_y, f_xx, f_xy, f_yy, **params)and should return the value that must be zero at the solution.For example, for the equation
-f_xx - f_yy = sin(pi*x)*sin(pi*y), the residual is-f_xx - f_yy - sin(pi*x)*sin(pi*y).- Parameters:
residual_func (
Callable[...,float]) – Callable returning residual at (x,y) with derivatives.x_min (
float) – Domain x start.x_max (
float) – Domain x end.y_min (
float) – Domain y start.y_max (
float) – Domain y end.nx (
int) – Number of x grid points.ny (
int) – Number of y grid points.bc_values (
ndarray|None) – Dirichlet boundary values, shape (ny, nx). Default: zeros.parameters (
dict[str,float] |None) – Optional dict of parameters for residual_func.mask (
ndarray|None) – Boolean array (ny, nx). True = inside domain. None = full rectangle.bc_type (
ndarray|None) – String array (ny, nx) with “dirichlet” or “neumann” per point. Only boundary points are used. Default: all Dirichlet.bc_neumann_value (
ndarray|None) – Float array (ny, nx) with normal derivative values for Neumann boundary points. Default: zeros.
- Return type:
- Returns:
PDESolution with grid, solution array, and mask.
- solver.is_multivariate(variables)[source]
Return True if the equation has more than one independent variable.
- solver.load_predefined_equations()[source]
Load all predefined equations from the YAML file.
Results are cached after the first successful load to avoid redundant disk I/O on repeated calls.
- Return type:
- Returns:
Ordered dict mapping equation key to
PredefinedEquation.- Raises:
FileNotFoundError – If the YAML file is missing.
- solver.compute_statistics(x, y, selected=None)[source]
Compute requested statistics for the primary solution component.
- Parameters:
- Return type:
- Returns:
Dictionary mapping statistic names to their computed values.
- solver.compute_statistics_2d(x_grid, y_grid, u, selected=None)[source]
Compute statistics for a 2D scalar field u(x,y).
- Parameters:
- Return type:
- Returns:
Dictionary with mean, std, max, min, integral_2d.
- solver.validate_all_inputs(*, expression=None, function_name=None, order, x_min, x_max, y0, num_points, method, params=None, x0_list=None, equation_type='ode', vector_expressions=None, vector_components=1)[source]
Run all validations and return accumulated errors.
Either expression or function_name must be provided.
- Parameters:
expression (
str|None) – ODE/difference expression (optional).function_name (
str|None) – Name of function in config (optional).order (
int) – Equation order.x_min (
float) – Domain start (n_min for difference).x_max (
float) – Domain end (n_max for difference).num_points (
int) – Grid points (ODE only).method (
str) – Solver method (ODE only).x0_list (
list[float] |None) – Per-derivative initial condition points (ODE only).equation_type (
str) –"ode"or"difference".vector_components (int)
- Return type:
- Returns:
List of all error messages (empty if everything is valid).
solver.equation_parser
Safe parsing and evaluation of user-written ODE expressions.
Expressions may use either the legacy y[k] notation or the unified
f[...] notation. When f tokens are present they are automatically
rewritten to y[...] via solver.notation before compilation.
- solver.equation_parser.get_ode_function(*, expression=None, function_name=None, order, parameters=None)[source]
Resolve an ODE function from either an expression string or a Python function.
Exactly one of expression or function_name must be provided.
- Parameters:
- Return type:
- Returns:
A callable
f(x, y)that returnsdy/dxas a 1-D array.- Raises:
EquationParseError – If expression is invalid or function cannot be resolved.
ValueError – If neither or both expression and function_name are provided.
- solver.equation_parser.get_difference_function(*, expression=None, function_name=None, order, parameters=None)[source]
Resolve a difference equation function from expression or Python function.
Exactly one of expression or function_name must be provided.
- Parameters:
- Return type:
- Returns:
A callable
f(n, y)that returns the next value (scalar).- Raises:
EquationParseError – If expression is invalid or function cannot be resolved.
ValueError – If neither or both expression and function_name are provided.
- solver.equation_parser.parse_pde_rhs_expression(expression, variables, parameters=None)[source]
Parse a PDE RHS expression into a callable f(x, y, …) -> float.
The expression can use variable names (x, y, z, …) or indexed notation (x[0], x[1], …) and parameters. Used for the RHS of Poisson-type equations -u_xx - u_yy = f(x,y).
- Parameters:
- Return type:
- Returns:
A callable that takes (x, y, …) and returns the RHS value.
- Raises:
EquationParseError – If the expression is invalid.
- solver.equation_parser.get_vector_ode_function(*, vector_expressions, function_name=None, order, vector_components, parameters=None)[source]
Resolve a vector ODE function from expressions or Python function.
Exactly one of vector_expressions or function_name must be provided.
- Parameters:
vector_expressions (
list[str]) – List of expressions for each component’s highest derivative.function_name (
str|None) – Name of function in config.equations (returns full dydt).order (
int) – Order of each ODE component.vector_components (
int) – Number of components (f_0, f_1, …).parameters (
dict[str,float] |None) – Named parameter values.
- Return type:
- Returns:
A callable f(x, y) that returns dy/dx.
- Raises:
ValueError – If both or neither of vector_expressions and function_name provided.
EquationParseError – If expressions are invalid or function not found.
solver.ode_solver
Core ODE solving wrappers around SciPy integrators.
- class solver.ode_solver.ODESolution(x, y, success, message, method_used, n_eval=0, raw=None)[source]
Bases:
objectContainer for ODE solution data.
- Variables:
x – Independent variable values.
y – Solution array — shape
(n_vars, n_points).success – Whether the solver converged.
message – Solver status message.
method_used – Name of the integration method.
n_eval – Number of function evaluations (if available).
raw – The original
OdeResultfrom SciPy.
- Parameters:
- solver.ode_solver.solve_ode(ode_func, t_span, y0, method=None, t_eval=None, max_step=None, rtol=None, atol=None)[source]
Solve an initial-value ODE problem using
scipy.integrate.solve_ivp.- Parameters:
ode_func (
Callable[[float,ndarray],ndarray]) – Right-hand side of the ODE systemdy/dx = f(x, y).t_span (
tuple[float,float]) – Integration interval(x_min, x_max).method (
str|None) – Integration method name. Falls back to env default.t_eval (
ndarray|None) – Times at which to store the solution. IfNone, a uniform grid is generated from env settings.max_step (
float|None) – Maximum allowed step size (0 →np.inf).
- Return type:
- Returns:
An
ODESolutionwith the results.- Raises:
SolverFailedError – If the solver reports failure.
- solver.ode_solver.solve_multipoint(ode_func, conditions, order, x_min, x_max, method=None, t_eval=None, max_step=None, rtol=None, atol=None)[source]
Solve an ODE with initial conditions specified at possibly different x points.
Uses a shooting method: the full state at
x_minis found via root-finding so that all given conditionsy^(k)(x_i) = a_iare satisfied.- Parameters:
ode_func (
Callable[[float,ndarray],ndarray]) – Right-hand side of the ODE systemdy/dx = f(x, y).conditions (
list[tuple[int,float,float]]) – List of(k, x_i, a_i)meaningy^(k)(x_i) = a_i.order (
int) – ODE order (equals number of conditions).x_min (
float) – Domain start.x_max (
float) – Domain end.t_eval (
ndarray|None) – Points at which to store the final solution.
- Return type:
- Returns:
An
ODESolutionwith the results.- Raises:
SolverFailedError – If the solver or shooting method fails.
solver.difference_solver
Solver for difference equations (recurrence relations).
- class solver.difference_solver.DifferenceSolution(n, y, success, message)[source]
Bases:
objectContainer for difference equation solution data.
- Variables:
n – Discrete index values (0, 1, 2, …).
y – Solution array — shape
(n_vars, n_points).success – Whether the iteration completed without error.
message – Status message.
- Parameters:
- solver.difference_solver.solve_difference(recur_func, n_min, n_max, y0, order)[source]
Solve a difference equation by iterating the recurrence.
The recurrence has the form y_{n+order} = f(n, [y_n, y_{n+1}, …, y_{n+order-1}]). State vector at step n: y[0]=y_n, y[1]=y_{n+1}, …, y[order-1]=y_{n+order-1}.
- Parameters:
- Return type:
- Returns:
A
DifferenceSolutionwith n and y arrays. y has shape (order, n_points) for compatibility with ODE pipeline.
solver.pde_solver
PDE solver for multivariate scalar fields using finite differences.
Supports 2D elliptic PDEs of the general form:
a(x,y)*f_xx + b(x,y)*f_xy + c(x,y)*f_yy + d(x,y)*f_x + e(x,y)*f_y + g(x,y)*f = rhs(x,y)
The solver probes the user-supplied residual function at each grid point to extract local coefficients, then assembles a sparse linear system using central differences (5-point stencil for the Laplacian, central differences for first derivatives and mixed derivative).
Supports: - Arbitrary domain shapes via boolean masks - Dirichlet and Neumann boundary conditions
- class solver.pde_solver.PDESolution(grid, u, success, message, n_eval=0, mask=None)[source]
Bases:
objectContainer for PDE solution data.
- Variables:
grid – Tuple of 1D arrays, one per variable (e.g. (x_vals, y_vals)).
u – Solution array. For 2D: shape (ny, nx). Exterior points are NaN.
success – Whether the solver converged.
message – Solver status message.
n_eval – Number of iterations (if applicable).
mask – Optional boolean mask (ny, nx). True = inside domain.
- Parameters:
- solver.pde_solver.solve_pde_2d(residual_func, x_min, x_max, y_min, y_max, nx, ny, bc_values=None, parameters=None, mask=None, bc_type=None, bc_neumann_value=None)[source]
Solve a general 2D linear elliptic PDE using finite differences.
The residual_func is called as
residual_func(x, y, f, f_x, f_y, f_xx, f_xy, f_yy, **params)and should return the value that must be zero at the solution.For example, for the equation
-f_xx - f_yy = sin(pi*x)*sin(pi*y), the residual is-f_xx - f_yy - sin(pi*x)*sin(pi*y).- Parameters:
residual_func (
Callable[...,float]) – Callable returning residual at (x,y) with derivatives.x_min (
float) – Domain x start.x_max (
float) – Domain x end.y_min (
float) – Domain y start.y_max (
float) – Domain y end.nx (
int) – Number of x grid points.ny (
int) – Number of y grid points.bc_values (
ndarray|None) – Dirichlet boundary values, shape (ny, nx). Default: zeros.parameters (
dict[str,float] |None) – Optional dict of parameters for residual_func.mask (
ndarray|None) – Boolean array (ny, nx). True = inside domain. None = full rectangle.bc_type (
ndarray|None) – String array (ny, nx) with “dirichlet” or “neumann” per point. Only boundary points are used. Default: all Dirichlet.bc_neumann_value (
ndarray|None) – Float array (ny, nx) with normal derivative values for Neumann boundary points. Default: zeros.
- Return type:
- Returns:
PDESolution with grid, solution array, and mask.
solver.error_metrics
Compute error and quality metrics for ODE solutions.
- solver.error_metrics.compute_ode_residual_error(ode_func, x, y)[source]
Compute residual error: how well does y satisfy dy/dx = f(x, y)?
Compares the ODE right-hand side f(x,y) with the numerical derivative of the solution. Large residuals indicate the solution may not satisfy the ODE well (e.g. coarse tolerances, stiff problem).
- Parameters:
- Return type:
- Returns:
Dict with residual_max, residual_mean, residual_rms (L2 norm per point).
solver.predefined
Load and manage predefined ODE equations from YAML.
- class solver.predefined.PredefinedEquation(key, name, formula, description, order, parameters, expression, function_name, default_initial_conditions, default_domain=<factory>, vector_expressions=None, vector_components=1, equation_type='ode', category='Oscillators', variables=<factory>, partial_derivatives=None)[source]
Bases:
objectPredefined equation (ODE, difference, PDE, or vector ODE) loaded from YAML.
formula is always required for display. Either expression or function_name must be set for execution. If function_name is set, the equation is resolved by importing the function from config.equations; otherwise expression is used. For vector ODEs, use vector_expressions or function_name.
- Variables:
key – Unique identifier (YAML key).
name – Human-readable name.
formula – Compact human-readable equation string (e.g.
"y'' + ω²y = 0").description – Multi-line description with formula and context.
order – Equation order (1, 2, …) for ODE/difference. For vector: order per component.
parameters – Mapping of param name to
{default, description}.expression – Python expression for execution (optional if function_name set).
function_name – Name of function in config.equations to import (optional).
vector_expressions – For vector ODEs, list of expressions (one per component).
vector_components – Number of components [f_0, f_1, …] for vector ODEs.
default_initial_conditions – Default y0 vector.
default_domain – Default
[x_min, x_max]for ODE or[n_min, n_max]for difference. For PDE:[x_min, x_max, y_min, y_max, ...]per variable.equation_type –
"ode"(differential),"difference","pde", or"vector_ode".category – Display category (e.g.
"Oscillators","Population") for UI grouping.variables – Independent variable names, e.g.
["x"]for 1D,["x","y"]for 2D. If absent or["x"], treated as 1D ODE.partial_derivatives – For PDEs, maps derivative keys (e.g.
"f_xx","f_xy") to expression strings. Only needed for PDE type.
- Parameters:
- solver.predefined.load_predefined_equations()[source]
Load all predefined equations from the YAML file.
Results are cached after the first successful load to avoid redundant disk I/O on repeated calls.
- Return type:
- Returns:
Ordered dict mapping equation key to
PredefinedEquation.- Raises:
FileNotFoundError – If the YAML file is missing.
solver.notation
Notation translation between user-facing f[…] and internal flat y[j] arrays.
The user writes expressions using f[i,k] (vector ODE), f[k] (scalar ODE /
difference), or f[a,b,...] (PDE derivatives). Internally, scipy’s solve_ivp
operates on a flat state vector y. This module bridges the two representations.
- class solver.notation.FNotation(kind, n_components=1, order=1, n_independent_vars=1, component_orders=())[source]
Bases:
objectDescribes the notation context for a particular equation.
- Variables:
kind – One of
"ode","vector_ode","difference","pde".n_components – Number of components (1 for scalar ODE / PDE / difference).
order – ODE order per component, or max derivative order for PDE.
n_independent_vars – Number of independent variables (1 for ODE, >=1 for PDE).
- Parameters:
- solver.notation.generate_derivative_labels(notation)[source]
Generate labels for every entry in the flat state vector.
solver.statistics
Compute statistics and physical magnitudes from ODE solutions.
- solver.statistics.compute_statistics(x, y, selected=None)[source]
Compute requested statistics for the primary solution component.
- Parameters:
- Return type:
- Returns:
Dictionary mapping statistic names to their computed values.
solver.validators
Input validation for DifferentialLab solver parameters.
- solver.validators.validate_all_inputs(*, expression=None, function_name=None, order, x_min, x_max, y0, num_points, method, params=None, x0_list=None, equation_type='ode', vector_expressions=None, vector_components=1)[source]
Run all validations and return accumulated errors.
Either expression or function_name must be provided.
- Parameters:
expression (
str|None) – ODE/difference expression (optional).function_name (
str|None) – Name of function in config (optional).order (
int) – Equation order.x_min (
float) – Domain start (n_min for difference).x_max (
float) – Domain end (n_max for difference).num_points (
int) – Grid points (ODE only).method (
str) – Solver method (ODE only).x0_list (
list[float] |None) – Per-derivative initial condition points (ODE only).equation_type (
str) –"ode"or"difference".vector_components (int)
- Return type:
- Returns:
List of all error messages (empty if everything is valid).