Skip to main content

nereids_fitting/
forward_model.rs

1//! Solver-agnostic forward model trait.
2//!
3//! Unlike [`FitModel`](crate::lm::FitModel), which is LM-specific (evaluates
4//! residuals + Jacobian in chi-squared space), `ForwardModel` exposes the
5//! raw model prediction and parameter Jacobian.  Each solver wraps this to
6//! compute its own objective and gradient:
7//!
8//! - **LM**: residuals = `(data - predict) / σ`, J_lm = `-jacobian / σ`
9//! - **KL**: gradient = `Σ (1 - data/predict) · jacobian`
10//!
11//! This makes new model extensions (background, temperature, etc.) work with
12//! both solvers automatically — implement `ForwardModel` once, both solvers
13//! benefit.
14
15use crate::error::FittingError;
16
17/// Solver-agnostic forward model.
18///
19/// Implementations provide the model prediction and (optionally) its
20/// analytical Jacobian.  Solvers wrap this trait to compute solver-specific
21/// objectives (chi-squared, Poisson NLL, etc.).
22pub trait ForwardModel {
23    /// Predict model output for the given parameter vector.
24    ///
25    /// Returns a vector of predicted values (transmission, counts, etc.)
26    /// with length equal to the number of data points.
27    fn predict(&self, params: &[f64]) -> Result<Vec<f64>, FittingError>;
28
29    /// Analytical Jacobian (column-major layout).
30    ///
31    /// Returns a `Vec` of column vectors: `result[j]` is the j-th column
32    /// (partial derivatives of all data points w.r.t. the j-th free
33    /// parameter), so `result[j][i] = ∂predict[i] / ∂params[free_param_indices[j]]`.
34    ///
35    /// Only the columns corresponding to `free_param_indices` are needed.
36    /// Returns `None` to signal "use finite differences" (the default).
37    ///
38    /// `y_current` is the output of `predict(params)`, provided so
39    /// implementations can avoid redundant computation.
40    fn jacobian(
41        &self,
42        _params: &[f64],
43        _free_param_indices: &[usize],
44        _y_current: &[f64],
45    ) -> Option<Vec<Vec<f64>>> {
46        None
47    }
48
49    /// Number of data points in the model output.
50    fn n_data(&self) -> usize;
51
52    /// Number of parameters (total, including fixed).
53    fn n_params(&self) -> usize;
54}