Skip to content

Commit 76b9672

Browse files
doc: improve API docs (#229)
* doc: add some api docs for problem struct * finish adding docstring for problem * finish more docstrings * doc: fill out documentation for builder * doc: checkpointing, state * doc: improve OdeSolverMethod * doc: improve Vector * doc: improve Matrix * fix combine * doc: improve Scalar * remove some commented out code * cargo fmt * doc: diffsl, ops and jacobian * cargo fmt * doc: line_search * doc: modules * fix some bad links * free up some disk space on ubuntu * free disk space
1 parent 30939b4 commit 76b9672

File tree

22 files changed

+1114
-215
lines changed

22 files changed

+1114
-215
lines changed

.github/workflows/rust.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ jobs:
148148
if: matrix.os == 'windows-latest'
149149
run: |
150150
echo "ADDITIONAL_FEATURES_FLAGS=--features diffsl-cranelift" >> $GITHUB_ENV
151+
- name: Free Disk Space (Ubuntu)
152+
if: matrix.os == 'ubuntu-latest'
153+
uses: jlumbroso/free-disk-space@main
154+
with:
155+
android: true
156+
dotnet: true
157+
haskell: true
158+
large-packages: false
159+
docker-images: true
160+
swap-storage: true
151161
- name: Run tests - default features
152162
if: matrix.tests == true
153163
run: cargo test --verbose

diffsol/src/jacobian/mod.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,31 @@ gen_find_non_zeros_linear!(
119119

120120
use std::cell::RefCell;
121121

122+
/// A structure for efficiently computing sparse Jacobians using graph coloring.
123+
///
124+
/// This struct uses graph coloring to group matrix columns that can be computed simultaneously
125+
/// using finite differences. By identifying columns that don't share any non-zero rows (i.e.,
126+
/// are structurally orthogonal), multiple Jacobian columns can be computed in parallel with a
127+
/// single function evaluation per color.
128+
///
129+
/// # Algorithm
130+
///
131+
/// The algorithm works as follows:
132+
/// 1. Construct a graph where each column is a node, and edges connect columns that share at least one non-zero row
133+
/// 2. Apply greedy graph coloring to assign colors to columns such that no two adjacent columns share the same color
134+
/// 3. For each color, perturb all columns of that color simultaneously and compute the corresponding Jacobian entries
135+
///
136+
/// To enable 3., we pre-calculate for all colors:
137+
/// - all the indices in the peturbed vector to peterb (i.e. set to 1) which is stored in `input_indices_per_color`.
138+
/// - all the indices in the output vector to read the results from which is stored in `src_indices_per_color`.
139+
/// - all the indices in the Jacobian matrix data vector to write the results to which is stored in `dst_indices_per_color`.
140+
///
141+
/// This reduces the number of function evaluations from O(n) to O(χ), where χ is the chromatic number
142+
/// of the graph (typically much smaller than n for sparse matrices).
143+
///
144+
/// # Type Parameters
145+
///
146+
/// * `M` - The matrix type used to store the Jacobian
122147
pub struct JacobianColoring<M: Matrix> {
123148
dst_indices_per_color: Vec<<M::V as Vector>::Index>,
124149
src_indices_per_color: Vec<<M::V as Vector>::Index>,
@@ -140,6 +165,21 @@ impl<M: Matrix> Clone for JacobianColoring<M> {
140165
}
141166

142167
impl<M: Matrix> JacobianColoring<M> {
168+
/// Create a new Jacobian coloring from a sparsity pattern and list of non-zero entries.
169+
///
170+
/// This method constructs the graph coloring and organizes the indices for efficient
171+
/// Jacobian computation. The coloring is computed using a greedy algorithm that aims
172+
/// to minimize the number of colors (and thus function evaluations) needed.
173+
///
174+
/// # Arguments
175+
///
176+
/// * `sparsity` - The sparsity pattern of the Jacobian matrix
177+
/// * `non_zeros` - A list of (row, column) pairs indicating non-zero entries in the Jacobian
178+
/// * `ctx` - The context for creating vectors and indices
179+
///
180+
/// # Returns
181+
///
182+
/// A new `JacobianColoring` instance ready to compute Jacobians efficiently.
143183
pub fn new(sparsity: &impl MatrixSparsity<M>, non_zeros: &[(usize, usize)], ctx: M::C) -> Self {
144184
let ncols = sparsity.ncols();
145185
let graph = nonzeros2graph(non_zeros, ncols);
@@ -189,6 +229,22 @@ impl<M: Matrix> JacobianColoring<M> {
189229
// Self::new_from_non_zeros(op, non_zeros)
190230
//}
191231

232+
/// Compute the Jacobian matrix in-place using the coloring scheme.
233+
///
234+
/// This method uses the pre-computed coloring to efficiently compute the Jacobian by
235+
/// evaluating `jac_mul` once per color instead of once per column. For each color group,
236+
/// it perturbs multiple columns simultaneously and extracts the corresponding Jacobian entries.
237+
///
238+
/// # Arguments
239+
///
240+
/// * `op` - The nonlinear operator whose Jacobian is being computed
241+
/// * `x` - The state vector at which to evaluate the Jacobian
242+
/// * `t` - The time at which to evaluate the Jacobian
243+
/// * `y` - The matrix to store the computed Jacobian (modified in-place)
244+
///
245+
/// # Note
246+
///
247+
/// The sparsity pattern of `y` must match the sparsity pattern used to create this coloring.
192248
pub fn jacobian_inplace<F: NonLinearOpJacobian<M = M, V = M::V, T = M::T, C = M::C>>(
193249
&self,
194250
op: &F,
@@ -209,6 +265,18 @@ impl<M: Matrix> JacobianColoring<M> {
209265
}
210266
}
211267

268+
/// Compute the sensitivity matrix (∂F/∂p) in-place using the coloring scheme.
269+
///
270+
/// Similar to `jacobian_inplace`, but computes the sensitivity of the right-hand side
271+
/// with respect to parameters rather than the state variables. This is used for forward
272+
/// sensitivity analysis.
273+
///
274+
/// # Arguments
275+
///
276+
/// * `op` - The nonlinear operator whose sensitivity matrix is being computed
277+
/// * `x` - The state vector at which to evaluate the sensitivities
278+
/// * `t` - The time at which to evaluate the sensitivities
279+
/// * `y` - The matrix to store the computed sensitivity matrix (modified in-place)
212280
pub fn sens_inplace<F: NonLinearOpSens<M = M, V = M::V, T = M::T, C = M::C>>(
213281
&self,
214282
op: &F,
@@ -229,6 +297,18 @@ impl<M: Matrix> JacobianColoring<M> {
229297
}
230298
}
231299

300+
/// Compute the transposed Jacobian (adjoint) matrix in-place using the coloring scheme.
301+
///
302+
/// This method computes the transpose of the Jacobian, which is used in adjoint sensitivity
303+
/// analysis. The coloring is applied to the columns of the transposed matrix (which correspond
304+
/// to the rows of the original Jacobian).
305+
///
306+
/// # Arguments
307+
///
308+
/// * `op` - The nonlinear operator whose transposed Jacobian is being computed
309+
/// * `x` - The state vector at which to evaluate the transposed Jacobian
310+
/// * `t` - The time at which to evaluate the transposed Jacobian
311+
/// * `y` - The matrix to store the computed transposed Jacobian (modified in-place)
232312
pub fn adjoint_inplace<F: NonLinearOpAdjoint<M = M, V = M::V, T = M::T, C = M::C>>(
233313
&self,
234314
op: &F,

diffsol/src/lib.rs

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,126 @@ pub use diffsl::CraneliftJitModule;
142142
#[cfg(feature = "diffsl-llvm")]
143143
pub use diffsl::LlvmModule;
144144

145+
/// Context objects for managing device resources for vectors and matrices (e.g. device streams, threading pools, etc.).
146+
///
147+
/// This module provides context types that encapsulate information about where data is stored and computed
148+
/// (CPU, GPU, etc.). Different backends like nalgebra and faer may require different context implementations.
149+
/// The [Context] trait defines the interface that must be implemented.
145150
pub mod context;
151+
152+
/// Jacobian computation and coloring algorithms for efficient Jacobian evaluation.
153+
///
154+
/// This module provides utilities for:
155+
/// - Detecting the sparsity pattern of Jacobian matrices using NaN propagation
156+
/// - Computing efficient graph colorings of the Jacobian sparsity pattern
157+
/// - Using the coloring to compute sparse Jacobians with fewer function evaluations
158+
///
159+
/// The [JacobianColoring] struct is the main entry point for computing Jacobians efficiently.
146160
pub mod jacobian;
161+
162+
/// Linear solver implementations and traits.
163+
///
164+
/// This module defines the [LinearSolver] trait for solving linear systems and provides implementations:
165+
/// - Direct solvers: [NalgebraLU], [FaerLU], [FaerSparseLU]
166+
/// - Optional sparse solvers: `KLU` (requires `suitesparse` feature)
167+
/// - GPU solvers: `CudaLU` (requires `cuda` feature)
168+
///
169+
/// The linear solver is a critical component used internally by nonlinear solvers to solve Newton systems.
147170
pub mod linear_solver;
171+
172+
/// Matrix types and operations.
173+
///
174+
/// This module defines the [Matrix] trait and related traits for matrix operations:
175+
/// - [DenseMatrix] for dense column-major matrices
176+
/// - [MatrixView] and [MatrixViewMut] for borrowed views
177+
/// - Sparsity detection and handling
178+
///
179+
/// Implementations are provided for:
180+
/// - Dense matrices: [NalgebraMat], [FaerMat]
181+
/// - Sparse matrices: [FaerSparseMat]
182+
/// - GPU matrices: `CudaMat` (requires `cuda` feature)
148183
pub mod matrix;
184+
185+
/// Nonlinear solver implementations and traits.
186+
///
187+
/// This module defines the [NonLinearSolver] trait and provides the [NewtonNonlinearSolver] implementation.
188+
/// It also includes:
189+
/// - [LineSearch] implementations for globalization ([NoLineSearch], [BacktrackingLineSearch])
190+
/// - Root finding algorithms via [RootFinder]
191+
/// - Convergence testing via [Convergence]
192+
///
193+
/// Nonlinear solvers are used internally by ODE solvers to solve implicit equations.
149194
pub mod nonlinear_solver;
195+
196+
/// ODE equations and traits.
197+
///
198+
/// This module defines the [OdeEquations] trait and specialized variants:
199+
/// - [OdeEquationsImplicit] for implicit ODEs with mass matrices
200+
/// - [OdeEquationsImplicitSens] for forward sensitivity equations
201+
/// - [OdeEquationsAdjoint] for adjoint sensitivity equations
202+
///
203+
/// It also provides implementations:
204+
/// - [DiffSl] for equations specified in the DiffSL domain-specific language
205+
/// - [SensEquations] and [AdjointEquations] for sensitivity computations
206+
///
207+
/// All the test equations used in Diffsol's test suite are also provided here.
150208
pub mod ode_equations;
209+
210+
/// ODE solver implementations and traits.
211+
///
212+
/// This module provides the complete ODE solving interface including:
213+
/// - [OdeSolverMethod] trait with implementations: [Bdf], [Sdirk], [ExplicitRk]
214+
/// - [OdeSolverProblem] for problem setup (equations, parameters, tolerances, solver options etc.)
215+
/// - [OdeSolverState] for managing solution state (including state vector, sensitivities, time, step size etc.)
216+
/// - [OdeBuilder] for convenient problem construction (builds and configures [OdeSolverProblem])
217+
/// - [Checkpointing] and [HermiteInterpolator] for solution interpolation
151218
pub mod ode_solver;
219+
220+
/// Operator types and traits (e.g. non-linear, linear and constant operators; as well as their jacobians).
221+
///
222+
/// This module defines fundamental operator traits, for example:
223+
/// - [NonLinearOp] and variants for Jacobians and sensitivities
224+
/// - [LinearOp] for linear operators
225+
/// - [ConstantOp] for constants
226+
///
227+
/// It also provides concrete implementations, for example:
228+
/// - [Closure] for wrapping user-provided closures
229+
/// - [LinearClosure] for linear operators
230+
/// - [ConstantClosure] for constants
231+
/// - [MatrixOp] for explicit matrix operators
152232
pub mod op;
233+
234+
/// Scalar types and traits.
235+
///
236+
/// This module defines the [Scalar] trait that all floating-point types used in DiffSol must implement.
237+
/// It aggregates requirements from nalgebra, faer, and num_traits to ensure compatibility with linear algebra operations.
238+
///
239+
/// Implementations are provided for `f32` and `f64`.
240+
/// GPU scalar types are available via `ScalarCuda` (requires `cuda` feature).
153241
pub mod scalar;
154-
pub mod solver;
242+
243+
/// Vector types and traits.
244+
///
245+
/// This module defines the [Vector] trait and related traits for vector operations:
246+
/// - [VectorView] and [VectorViewMut] for borrowed views
247+
/// - [VectorIndex] for index collections
248+
/// - [VectorHost] for CPU-resident vectors with direct access
249+
///
250+
/// Implementations are provided for:
251+
/// - [NalgebraVec] using nalgebra vectors
252+
/// - [FaerVec] using faer vectors
253+
/// - `CudaVec` for GPU computation (requires `cuda` feature)
155254
pub mod vector;
156255

256+
/// Error types and handling.
257+
///
258+
/// This module defines the [DiffsolError] enum and specialized error variants
259+
/// for different failure modes in ODE solving, including parsing, compilation,
260+
/// and numerical errors.
261+
pub mod error;
262+
263+
pub use error::DiffsolError;
264+
157265
#[cfg(feature = "sundials")]
158266
pub mod sundials_sys;
159267

@@ -258,5 +366,3 @@ pub use scalar::cuda::{CudaType, ScalarCuda};
258366
pub use vector::cuda::{CudaIndex, CudaVec, CudaVecMut, CudaVecRef};
259367

260368
pub use scalar::scale;
261-
262-
pub mod error;

0 commit comments

Comments
 (0)