Skip to content

Numerical Methods Policy ​

Scope ​

This document defines the numerical integration policy for FluxGraph models. It complements docs/semantics_spec.md and is authoritative for solver selection and stability interpretation. Validation protocol details are documented in docs/validation-methodology.md.

Current Policy ​

  1. For ODE-based models, integration method selection is explicit via model parameters.
  2. If not specified for ODE models, the deterministic default is forward_euler.
  3. Methods are selected at compile time and remain fixed at runtime.
  4. Runtime behavior must be deterministic for identical inputs and dt.

ODE Model Integration Methods ​

The following built-in models support integration_method:

  1. thermal_mass
  2. thermal_rc2
  3. first_order_process
  4. second_order_process

Discrete-time structured model:

  1. state_space_siso_discrete does not use integration_method.
  2. Its update law is natively discrete (x[k+1] = A_d x[k] + B_d u[k]).
  3. compute_stability_limit() returns infinity for this model because no continuous-time explicit integration step is performed.

Supported methods:

  1. forward_euler (default)
  2. rk4 (classic fourth-order Runge-Kutta)

Selection is provided via:

cpp
model.params["integration_method"] = std::string("forward_euler");
// or
model.params["integration_method"] = std::string("rk4");

Unknown method names are compile-time errors.

Stability Limits ​

For the linear thermal mass model dT/dt = (P - h*(T - T_amb)) / C, with k = h/C, the stability limits are:

  1. forward_euler: dt < 2/k = 2*C/h
  2. rk4: dt < 2.785293563/k = 2.785293563*C/h

If h <= 0, the model is treated as unconditionally stable for this criterion.

For the two-node thermal RC model, the system is linear: dT/dt = A*T + c. Let lambda_min be the most negative eigenvalue of A (largest magnitude on the negative real axis). The stability limits use:

  1. forward_euler: dt < 2/|lambda_min|
  2. rk4: dt < 2.785293563/|lambda_min|

FluxGraph enforces these via IModel::compute_stability_limit().

For the process primitives:

  1. first_order_process: equivalent to lambda = -1/tau_s, so the same negative-real-axis limits apply.
  2. second_order_process: eigenvalues may be complex; stability is evaluated using the selected method's stability function R(z) along z = lambda*dt, requiring |R(lambda*dt)| <= 1 for each eigenvalue.

Validation Expectations ​

Validation runs must report:

  1. Error metrics (L2, Linf) versus analytical references.
  2. Convergence behavior as dt is refined.
  3. Determinism checks for each supported integration method.

Forward Compatibility ​

Future methods (for example trapezoidal or implicit schemes) must define:

  1. Stability policy and limits.
  2. Deterministic selection and defaults.
  3. Regression and analytical validation coverage before release.

Reproducible Validation Run ​

Use the validation runner to produce validation artifacts:

bash
python scripts/run_numerical_validation.py --preset dev-release --enforce-order

Windows example:

powershell
python .\scripts\run_numerical_validation.py --preset dev-windows-release --config Release --enforce-order

CI evidence runs are produced by:

  1. .github/workflows/numerical-validation-evidence.yml