Skip to main content

diffsol_c/
lib.rs

1//! # Diffsol-c
2//!
3//! Diffsol-c is a companion crate to [Diffsol](https://crates.io/crates/diffsol) that
4//! provides two higher-level APIs on top of the core `diffsol` library:
5//!
6//! 1. A **dynamic dispatch** API that wraps the generic solver in runtime-dispatched types,
7//!    allowing you to select the matrix backend, scalar type, linear solver, ODE solver method,
8//!    and JIT backend at runtime rather than at compile time.
9//! 2. A **C FFI** API that exposes the dynamic dispatch API via `extern "C"` functions,
10//!    enabling integration with C, Wasm, Matlab and other languages
11//!    with a C-compatible interface.
12//!
13//! ## Dynamic Dispatch API
14//!
15//! The core of the dynamic dispatch API is the [OdeWrapper] struct. It wraps the internal
16//! solver state in an `Arc<Mutex<...>>` so that it can be shared across threads and across
17//! FFI boundaries. Unlike the core `diffsol` crate — which requires you to specify the matrix
18//! type, code generation backend, ODE equation type, linear solver, and solver method all as
19//! generic parameters — `OdeWrapper` erases these type parameters behind trait objects so you
20//! can choose them at runtime.
21//!
22//! To create an `OdeWrapper`, use one of the feature-gated constructors:
23//! - `new_jit` if you have DiffSL code to JIT-compile (requires the
24//!   `diffsl-cranelift` or `diffsl-llvm` feature).
25//! - `new_external` if you have pre-compiled DiffSL symbols (requires the
26//!   `external` feature).
27//! - `new_external_dynamic` if you have a shared library with pre-compiled
28//!   DiffSL symbols (requires the `diffsl-external-dynamic` feature).
29//!
30//! Once created, the `OdeWrapper` provides methods to configure solver tolerances and options
31//! (e.g. [OdeWrapper::set_rtol], [OdeWrapper::set_atol], [OdeWrapper::set_t0],
32//! [OdeWrapper::set_h0]), query equation metadata (e.g. [OdeWrapper::get_nstates],
33//! [OdeWrapper::get_nparams], [OdeWrapper::get_nout]), and access separate option handles
34//! via [OdeWrapper::get_options] (returning an [OdeSolverOptions]) and
35//! [OdeWrapper::get_ic_options] (returning an [InitialConditionSolverOptions]).
36//!
37//! Solving is done via the following methods:
38//! - [OdeWrapper::solve] — adaptive-time integration to a final time.
39//! - [OdeWrapper::solve_dense] — integration to a specified set of time points.
40//! - [OdeWrapper::solve_fwd_sens] — forward sensitivity analysis.
41//! - [OdeWrapper::solve_continuous_adjoint] — continuous adjoint sensitivity analysis.
42//! - [OdeWrapper::solve_adjoint_fwd] / [OdeWrapper::solve_adjoint_bkwd] — discrete adjoint
43//!   sensitivity analysis (forward + backward pass).
44//!
45//! Each solve method returns a [SolutionWrapper], from which you can extract the solution
46//! values via [SolutionWrapper::get_ys], [SolutionWrapper::get_ts], and
47//! [SolutionWrapper::get_sens]. These methods return [HostArray] objects, which are
48//! read-only views of the Rust-allocated data that can be safely accessed from the host
49//! language without copying.
50//!
51//! The adoint solve methods involve an [AdjointCheckpointWrapper] that stores forward-pass
52//! checkpoint data required for the backward pass.
53//!
54//! ### Runtime configuration types
55//!
56//! The dynamic dispatch API uses the following enums to configure the solver at runtime:
57//! - [OdeSolverType] — the ODE solver method ([OdeSolverType::Bdf],
58//!   [OdeSolverType::Esdirk34], [OdeSolverType::TrBdf2], [OdeSolverType::Tsit45]).
59//! - [MatrixType] — the matrix backend ([MatrixType::NalgebraDense],
60//!   [MatrixType::FaerDense], [MatrixType::FaerSparse]).
61//! - [ScalarType] — the floating-point type ([ScalarType::F32], [ScalarType::F64]).
62//! - [LinearSolverType] — the linear solver for implicit methods
63//!   ([LinearSolverType::Default], [LinearSolverType::Lu], [LinearSolverType::Klu]).
64//! - [JitBackendType] — the JIT backend for compiling DiffSL code
65//!   (`Cranelift` or `Llvm` depending on enabled features).
66//!
67//! ### Error handling
68//!
69//! All operations that can fail in the dynamic dispatch API return
70//! `Result<_, [DiffsolRtError]>`, a runtime error type wrapping the core
71//! [DiffsolError](diffsol::error::DiffsolError).
72//!
73//! ## C FFI API
74//!
75//! The C FFI API is exposed via `extern "C"` functions across several modules suffixed `_c`.
76//! These functions wrap the dynamic dispatch API using raw pointers and integer error codes
77//! so that they can be called from C or any language with C interop. The public `_c` modules
78//! are:
79//! - [ode_c] — create, configure, solve, and destroy [OdeWrapper] handles.
80//! - [solution_wrapper_c] — extract solution data and destroy [SolutionWrapper] handles.
81//! - [ode_options_c] — get/set solver convergence and performance options.
82//! - [initial_condition_options_c] — get/set initial condition solver options.
83//! - [matrix_type_c], [scalar_type_c], [linear_solver_type_c],
84//!   [ode_solver_type_c], [jit_c] — query and convert enum values.
85//! - [host_array_c] — inspect and free [HostArray] data.
86//! - [error_c] — retrieve and clear thread-local error messages.
87//! - [string_c] — allocate and free Rust-owned strings from C.
88//!
89//! All C FFI functions follow a common pattern:
90//! - Return `i32` (0 = success, negative = error).
91//! - Store error details in a thread-local variable retrievable via functions in [error_c].
92//! - Use raw pointers for ownership transfer (caller allocates/frees via dedicated functions).
93//!
94//! See [c_api_utils] for the internal macros and helper functions used by the C FFI layer.
95//!
96//! ## Feature flags
97//!
98//! The crate requires at least one of the following features to be enabled:
99//! - `diffsl-cranelift` — enable the Cranelift JIT backend for DiffSL code.
100//! - `diffsl-llvm` — enable the LLVM JIT backend for DiffSL code (requires an LLVM
101//!   installation; use a version-specific feature like `diffsl-llvm21`).
102//! - `external` — enable statically linked pre-compiled DiffSL symbols.
103//! - `external-dynamic` — enable dynamically loaded pre-compiled DiffSL symbols.
104//!
105//! Additional features:
106//! - `suitesparse` — enable the KLU sparse linear solver.
107//! - `sundials` — enable SUNDIALS support (via the core `diffsol` crate).
108//! - `cuda` — enable CUDA GPU support (via the core `diffsol` crate).
109//!
110//! ## Utility functions
111//!
112//! The [utils] module provides a few standalone functions:
113//! - [utils::version] — returns the crate version.
114//! - [utils::is_klu_available] — checks whether KLU was compiled in.
115//! - [utils::is_sens_available] — checks whether sensitivity analysis is supported on this platform.
116
117// Configure dlmalloc as the global allocator for WASM targets
118// dlmalloc is a maintained alternative to the unmaintained wee_alloc
119#[cfg(target_arch = "wasm32")]
120use dlmalloc::GlobalDlmalloc;
121
122#[cfg(not(any(
123    feature = "external",
124    feature = "external-dynamic",
125    feature = "diffsl-cranelift",
126    feature = "diffsl-llvm"
127)))]
128compile_error!(
129    "diffsol-c requires one of `external`, `external-dynamic`, `diffsl-cranelift`, or `diffsl-llvm`."
130);
131
132#[cfg(target_arch = "wasm32")]
133#[global_allocator]
134static ALLOCATOR: GlobalDlmalloc = GlobalDlmalloc;
135
136#[cfg(all(feature = "diffsl-llvm15", feature = "diffsl-llvm16"))]
137compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
138#[cfg(all(feature = "diffsl-llvm15", feature = "diffsl-llvm17"))]
139compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
140#[cfg(all(feature = "diffsl-llvm15", feature = "diffsl-llvm18"))]
141compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
142#[cfg(all(feature = "diffsl-llvm15", feature = "diffsl-llvm19"))]
143compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
144#[cfg(all(feature = "diffsl-llvm15", feature = "diffsl-llvm20"))]
145compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
146#[cfg(all(feature = "diffsl-llvm15", feature = "diffsl-llvm21"))]
147compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
148#[cfg(all(feature = "diffsl-llvm16", feature = "diffsl-llvm17"))]
149compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
150#[cfg(all(feature = "diffsl-llvm16", feature = "diffsl-llvm18"))]
151compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
152#[cfg(all(feature = "diffsl-llvm16", feature = "diffsl-llvm19"))]
153compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
154#[cfg(all(feature = "diffsl-llvm16", feature = "diffsl-llvm20"))]
155compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
156#[cfg(all(feature = "diffsl-llvm16", feature = "diffsl-llvm21"))]
157compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
158#[cfg(all(feature = "diffsl-llvm17", feature = "diffsl-llvm18"))]
159compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
160#[cfg(all(feature = "diffsl-llvm17", feature = "diffsl-llvm19"))]
161compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
162#[cfg(all(feature = "diffsl-llvm17", feature = "diffsl-llvm20"))]
163compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
164#[cfg(all(feature = "diffsl-llvm17", feature = "diffsl-llvm21"))]
165compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
166#[cfg(all(feature = "diffsl-llvm18", feature = "diffsl-llvm19"))]
167compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
168#[cfg(all(feature = "diffsl-llvm18", feature = "diffsl-llvm20"))]
169compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
170#[cfg(all(feature = "diffsl-llvm18", feature = "diffsl-llvm21"))]
171compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
172#[cfg(all(feature = "diffsl-llvm19", feature = "diffsl-llvm20"))]
173compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
174#[cfg(all(feature = "diffsl-llvm19", feature = "diffsl-llvm21"))]
175compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
176#[cfg(all(feature = "diffsl-llvm20", feature = "diffsl-llvm21"))]
177compile_error!("diffsol-c cannot enable more than one `diffsl-llvm*` feature.");
178
179/// Adjoint checkpoint wrapper for storing and retrieving forward-pass checkpoint data.
180///
181/// This module provides [AdjointCheckpointWrapper], a thread-safe wrapper around the
182/// internal `AdjointCheckpoint` trait object. It is created during the forward pass of a
183/// discrete adjoint solve (via [OdeWrapper::solve_adjoint_fwd](crate::ode::OdeWrapper::solve_adjoint_fwd))
184/// and consumed during the backward pass (via [OdeWrapper::solve_adjoint_bkwd](crate::ode::OdeWrapper::solve_adjoint_bkwd)).
185///
186/// The internal `AdjointCheckpoint` trait erases the concrete matrix, codegen, and solver tag
187/// types, allowing the checkpoint to be shared between the forward and backward solvers which
188/// may use different ODE solver methods (e.g. BDF forward, ESDIRK backward).
189///
190/// The `AdjointCheckpointData<M, CG, Tag>` struct stores the concrete [CheckpointingPath](diffsol::CheckpointingPath)
191/// plus the forward solver metadata (method, linear solver, parameters).
192pub mod adjoint_checkpoint;
193/// Macros and helper functions for the C FFI layer.
194///
195/// This module provides the internal infrastructure used by the `*_c` modules to implement
196/// `extern "C"` functions. It defines:
197/// - Return code constants: `DIFFSOL_OK` (0), `DIFFSOL_ERR` (-1), `DIFFSOL_BAD_ARG` (-2).
198/// - Conversion traits `CMapTo<Out>` / `CMapFrom<In>` for mapping between Rust and C types.
199/// - Helper functions for common patterns: `map_get`, `map_set`, `invalid_arg_at`, `error_at`,
200///   `null_err_at`, `valid_f64_ptr`.
201/// - Convenience macros: `c_invalid_arg!`, `c_error!`, `c_null_err!`, `c_getter_simple!`,
202///   `c_setter_simple!`.
203///
204/// This module is not intended for external use; it exists to share boilerplate across the
205/// `_c` modules.
206pub mod c_api_utils;
207/// Runtime error type for the dynamic dispatch API.
208///
209/// This module defines [DiffsolRtError], a newtype wrapper around
210/// [DiffsolError](diffsol::error::DiffsolError). It implements
211/// `Display`, `std::error::Error`, and `From<DiffsolError>`. All operations in the
212/// dynamic dispatch API that can fail return `Result<_, DiffsolRtError>`.
213pub mod error;
214/// C FFI error handling.
215///
216/// This module provides thread-local error storage and `extern "C"` functions for retrieving
217/// and clearing error information from C code:
218/// - `diffsol_error_code` — returns `DIFFSOL_OK`, `DIFFSOL_ERR`, or `DIFFSOL_BAD_ARG`.
219/// - `diffsol_last_error_message` — returns a pointer to the last error message.
220/// - `diffsol_last_error_file` / `diffsol_last_error_line` — return the source location of the last error.
221/// - `diffsol_clear_last_error` — clears the thread-local error state.
222#[path = "error_c.rs"]
223pub mod error_c;
224/// Read-only array allocated in Rust, safe to access from the host language without copying.
225///
226/// This module defines [HostArray], a bridge between Rust-owned numeric arrays
227/// and the host language (Python, C, Wasm/JS). A `HostArray` stores a raw data pointer together
228/// with shape, strides, and scalar type metadata. It optionally owns the underlying allocation
229/// via a `Box<dyn Any>`, ensuring the data remains valid for as long as the `HostArray` exists.
230///
231/// `HostArray` is the return type of
232/// [SolutionWrapper::get_ys],
233/// [SolutionWrapper::get_ts], and
234/// [SolutionWrapper::get_sens].
235///
236/// # Conversion traits
237/// - [ToHostArray] — convert owned Rust types (e.g. `Vec<T>`,
238///   `nalgebra::DMatrix<T>`, `faer::Mat<T>`) into a `HostArray`.
239/// - [FromHostArray] — convert a `HostArray` back into a Rust type (e.g.
240///   `Vec<f64>`, `Vec<Vec<f64>>`, `ndarray::ArrayView2`).
241///
242/// # Key methods
243/// - [HostArray::new], [HostArray::new_vector],
244///   [HostArray::alloc_vector],
245///   [HostArray::new_col_major] — constructors.
246/// - [HostArray::as_array] — view as `ndarray::ArrayView2`.
247/// - [HostArray::as_slice] — view as `&[T]`.
248/// - `HostArray::data_ptr`, `HostArray::ndim`,
249///   `HostArray::dim`, `HostArray::stride`,
250///   `HostArray::dtype` — metadata accessors.
251pub mod host_array;
252/// C FFI functions for inspecting and freeing [HostArray] objects.
253///
254/// Provides `extern "C"` functions for querying `HostArray` metadata (dimensions, strides,
255/// data type, raw pointer) and for freeing a `HostArray` previously returned by this library.
256#[path = "host_array_c.rs"]
257pub mod host_array_c;
258/// Options for the initial condition solver used before integration.
259///
260/// This module defines [InitialConditionSolverOptions], a handle obtained via
261/// [OdeWrapper::get_ic_options](crate::ode::OdeWrapper::get_ic_options). It provides
262/// getters and setters for configuring the nonlinear root-finding solver that computes
263/// the initial state of the ODE system:
264/// - Line search settings: [InitialConditionSolverOptions::get_use_linesearch],
265///   [InitialConditionSolverOptions::get_max_linesearch_iterations].
266/// - Newton iteration limits: [InitialConditionSolverOptions::get_max_newton_iterations],
267///   [InitialConditionSolverOptions::get_max_linear_solver_setups].
268/// - Step control: [InitialConditionSolverOptions::get_step_reduction_factor],
269///   [InitialConditionSolverOptions::get_armijo_constant].
270///
271/// Also includes [InitialConditionSolverOptionsSnapshot], a serializable snapshot used
272/// for serde round-tripping of solver configuration.
273pub mod initial_condition_options;
274/// C FFI functions for getting and setting [InitialConditionSolverOptions].
275///
276/// Provides `extern "C"` getter/setter functions for each option field exposed by
277/// `InitialConditionSolverOptions`, using `i32` for boolean values and `f64`/`usize`
278/// for numeric fields.
279#[path = "initial_condition_options_c.rs"]
280pub mod initial_condition_options_c;
281/// JIT backend type for compiling DiffSL code at runtime.
282///
283/// This module defines [JitBackendType], an enum representing the available JIT
284/// compilation backends for DiffSL code:
285/// - `Cranelift` — available when the `diffsl-cranelift` feature is enabled.
286/// - `Llvm` — available when the `diffsl-llvm` feature is enabled.
287///
288/// The function [default_enabled_jit_backend] returns the preferred backend based on which
289/// features are compiled in (LLVM is preferred over Cranelift if both are available).
290pub mod jit;
291/// C FFI functions for querying [JitBackendType] enum values.
292///
293/// Provides `extern "C"` functions to enumerate available JIT backends, check whether a
294/// backend value is valid, and get the name string of a backend.
295#[path = "jit_c.rs"]
296pub mod jit_c;
297/// Linear solver type for implicit ODE solvers.
298///
299/// This module defines [LinearSolverType], an enum specifying which linear solver to use
300/// inside implicit ODE methods (BDF, ESDIRK, TR-BDF2):
301/// - [LinearSolverType::Default] — the solver's default choice (typically LU).
302/// - [LinearSolverType::Lu] — LU decomposition (dense or sparse as appropriate).
303/// - [LinearSolverType::Klu] — KLU sparse linear solver (requires `suitesparse` feature).
304pub mod linear_solver_type;
305/// C FFI functions for querying and converting [LinearSolverType] enum values.
306///
307/// Provides `extern "C"` functions to map between `i32` values and the `LinearSolverType`
308/// enum variants, and to get the name of a linear solver type as a C string.
309#[path = "linear_solver_type_c.rs"]
310pub mod linear_solver_type_c;
311/// Matrix backend type for the ODE solver.
312///
313/// This module defines [MatrixType], an enum specifying the matrix/linear algebra backend:
314/// - [MatrixType::NalgebraDense] — dense matrix using the [nalgebra](https://nalgebra.org) crate.
315/// - [MatrixType::FaerDense] — dense matrix using the [faer](https://github.com/sarah-ek/faer-rs) crate.
316/// - [MatrixType::FaerSparse] — sparse matrix using the [faer](https://github.com/sarah-ek/faer-rs) crate.
317pub mod matrix_type;
318/// C FFI functions for querying and converting [MatrixType] enum values.
319///
320/// Provides `extern "C"` functions to map between `i32` values and the `MatrixType` enum
321/// variants, and to get the name of a matrix type as a C string.
322#[path = "matrix_type_c.rs"]
323pub mod matrix_type_c;
324/// Dynamic dispatch ODE wrapper — the primary entry point for the dynamic dispatch API.
325///
326/// This module defines [OdeWrapper], a thread-safe handle around an internal ODE solver.
327/// `OdeWrapper` erases the generic type parameters of the core `diffsol` solver (matrix type,
328/// codegen backend, linear solver, solver method) so that they can be chosen at runtime rather
329/// than compile time. The internal state is stored behind an `Arc<Mutex<...>>` for safe sharing
330/// across threads.
331///
332/// # Constructors
333/// - `new_jit` — JIT-compile DiffSL code (requires `diffsl-cranelift` or `diffsl-llvm`).
334/// - `new_external` — use statically linked pre-compiled DiffSL symbols (requires `external`).
335/// - `new_external_dynamic` — load pre-compiled DiffSL symbols from a shared library
336///   (requires `diffsl-external-dynamic`).
337///
338/// # Configuration
339/// Tolerances: [OdeWrapper::set_rtol], [OdeWrapper::set_atol], [OdeWrapper::set_t0],
340/// [OdeWrapper::set_h0], [OdeWrapper::set_integrate_out].
341/// Sensitivity tolerances: [OdeWrapper::set_sens_rtol], [OdeWrapper::set_sens_atol],
342/// [OdeWrapper::set_out_rtol], [OdeWrapper::set_out_atol],
343/// [OdeWrapper::set_param_rtol], [OdeWrapper::set_param_atol].
344/// Solver selection: [OdeWrapper::set_ode_solver], [OdeWrapper::set_linear_solver].
345///
346/// # Solving
347/// - [OdeWrapper::solve] — adaptive-time integration.
348/// - [OdeWrapper::solve_dense] — integration to specified time points.
349/// - [OdeWrapper::solve_fwd_sens] — forward sensitivity analysis.
350/// - [OdeWrapper::solve_continuous_adjoint] — continuous adjoint.
351/// - [OdeWrapper::solve_adjoint_fwd] / [OdeWrapper::solve_adjoint_bkwd] — discrete adjoint.
352///
353/// # Low-level evaluation
354/// - [OdeWrapper::y0] — compute initial state.
355/// - [OdeWrapper::rhs] — evaluate the RHS function.
356/// - [OdeWrapper::rhs_jac_mul] — evaluate the Jacobian-vector product.
357///
358/// # Serialization
359/// `OdeWrapper` implements `Serialize`/`Deserialize` for JIT-backed solvers.
360pub mod ode;
361/// C FFI functions for creating, configuring, solving, and destroying [OdeWrapper] objects.
362///
363/// Provides `extern "C"` functions for the full lifecycle of an ODE solver:
364/// - `diffsol_ode_wrapper_new_*` — constructors (feature-gated by JIT backend or external).
365/// - `diffsol_ode_wrapper_get_*` / `diffsol_ode_wrapper_set_*` — getters/setters for tolerances,
366///   time settings, solver type, and linear solver.
367/// - `diffsol_ode_wrapper_y0`, `diffsol_ode_wrapper_rhs`, `diffsol_ode_wrapper_rhs_jac_mul` —
368///   low-level RHS evaluation.
369/// - `diffsol_ode_wrapper_solve`, `diffsol_ode_wrapper_solve_dense`,
370///   `diffsol_ode_wrapper_solve_fwd_sens`, `diffsol_ode_wrapper_solve_continuous_adjoint`,
371///   `diffsol_ode_wrapper_solve_adjoint_fwd`, `diffsol_ode_wrapper_solve_adjoint_bkwd` —
372///   solve functions returning [SolutionWrapper] pointers.
373/// - `diffsol_ode_wrapper_free` — free an `OdeWrapper`.
374/// - Serialization: `diffsol_ode_wrapper_serialize`, `diffsol_ode_wrapper_deserialize`.
375#[path = "ode_c.rs"]
376pub mod ode_c;
377/// ODE solver convergence and performance options for the dynamic dispatch API.
378///
379/// This module defines [OdeSolverOptions], a handle obtained via
380/// [OdeWrapper::get_options](crate::ode::OdeWrapper::get_options). It provides getters and
381/// setters for tuning the nonlinear solver and time-stepping behaviour of the ODE integrator:
382/// - Nonlinear solver: [OdeSolverOptions::get_max_nonlinear_solver_iterations],
383///   [OdeSolverOptions::get_max_error_test_failures].
384/// - Jacobian updates: [OdeSolverOptions::get_update_jacobian_after_steps],
385///   [OdeSolverOptions::get_update_rhs_jacobian_after_steps],
386///   [OdeSolverOptions::get_threshold_to_update_jacobian],
387///   [OdeSolverOptions::get_threshold_to_update_rhs_jacobian].
388/// - Step size: [OdeSolverOptions::get_min_timestep].
389///
390/// Also includes [OdeSolverOptionsSnapshot], a serializable snapshot used for serde
391/// round-tripping of solver configuration.
392pub mod ode_options;
393/// C FFI functions for getting and setting [OdeSolverOptions].
394///
395/// Provides `extern "C"` getter/setter functions for each option field exposed by
396/// `OdeSolverOptions`, using `f64` for floating-point values and `usize` for integer fields.
397#[path = "ode_options_c.rs"]
398pub mod ode_options_c;
399mod ode_solver_tag;
400/// ODE solver method type.
401///
402/// This module defines [OdeSolverType], an enum specifying which ODE integration method to use:
403/// - [OdeSolverType::Bdf] — Backward Differentiation Formula (stiff ODEs, singular mass matrices).
404/// - [OdeSolverType::Esdirk34] — Explicit Singly Diagonally Implicit Runge-Kutta (moderately stiff).
405/// - [OdeSolverType::TrBdf2] — Trapezoidal BDF of order 2 (moderately stiff).
406/// - [OdeSolverType::Tsit45] — Tsitouras 4/5th order Explicit Runge-Kutta (non-stiff, explicit).
407///
408/// The internal `solve` methods on this enum dispatch to the appropriate diffsol solver type
409/// via tag structs defined in the private `ode_solver_tag` module.
410pub mod ode_solver_type;
411/// C FFI functions for querying and converting [OdeSolverType] enum values.
412///
413/// Provides `extern "C"` functions to map between `i32` values and the `OdeSolverType` enum
414/// variants, and to get the name of an ODE solver type as a C string.
415#[path = "ode_solver_type_c.rs"]
416pub mod ode_solver_type_c;
417/// Floating-point scalar type for diffisol.
418///
419/// This module defines [ScalarType], an enum identifying the floating-point type used
420/// by the solver:
421/// - [ScalarType::F32] — 32-bit single precision.
422/// - [ScalarType::F64] — 64-bit double precision.
423///
424/// It also defines the [Scalar] trait (combining [DiffSlScalar](diffsol::DiffSlScalar)
425/// with [ToScalarType]) and the [ToScalarType] trait for mapping Rust types (`f32`, `f64`)
426/// to their `ScalarType` variant.
427pub mod scalar_type;
428/// C FFI functions for querying and converting [ScalarType] enum values.
429///
430/// Provides `extern "C"` functions to map between `i32` values and the `ScalarType` enum
431/// variants (`F32` / `F64`), and to get the name of a scalar type as a C string.
432#[path = "scalar_type_c.rs"]
433pub mod scalar_type_c;
434/// Internal trait used by [SolutionWrapper] for type-erased solution access.
435///
436/// The `Solution` trait provides the object-safe interface that `SolutionWrapper` wraps.
437/// It is implemented for [diffsol::Solution] for all compatible vector
438/// types `V`. The trait is `pub(crate)` — the public API is exposed through `SolutionWrapper`.
439pub mod solution;
440/// Solution wrapper for the dynamic dispatch API.
441///
442/// This module defines [SolutionWrapper], a thread-safe handle around a type-erased ODE
443/// solution. Returned by all solve methods on [OdeWrapper], it
444/// provides methods to extract the solution data:
445/// - [SolutionWrapper::get_ys] — the state values at each time point (returns [HostArray]).
446/// - [SolutionWrapper::get_ts] — the time points (returns [HostArray]).
447/// - [SolutionWrapper::get_sens] — the sensitivity matrices (returns `Vec<HostArray>`).
448///
449/// `SolutionWrapper` implements `Serialize`, serializing as `{ts, ys, sensitivities}`.
450pub mod solution_wrapper;
451/// C FFI functions for extracting data from and freeing [SolutionWrapper] objects.
452///
453/// Provides `extern "C"` functions to retrieve the time points, state values, and sensitivities
454/// from a `SolutionWrapper`, and to free the wrapper when no longer needed.
455#[path = "solution_wrapper_c.rs"]
456pub mod solution_wrapper_c;
457/// Core dynamic dispatch trait and its implementation.
458///
459/// Defines the `Solve` trait, the object-safe trait that erases the generic type parameters
460/// of the core `diffsol` solver. Each combination of matrix type, codegen backend, and solver
461/// method implements this trait. The concrete `GenericSolve<M, CG>` struct provides the
462/// implementation.
463///
464/// Also provides factory functions (`solve_factory_jit`, `solve_factory_external`,
465/// `solve_factory_external_dynamic`) that create the appropriate `Box<dyn Solve>` for a given
466/// configuration. These are called by [OdeWrapper]'s constructors.
467///
468/// All items in this module are `pub(crate)`; the public API is exposed through `OdeWrapper`.
469pub mod solve;
470/// Internal macros for generating ODE solver option accessor methods.
471///
472/// This module provides macros used by the `Solve` trait implementation
473/// to automatically generate getter/setter methods for initial condition and ODE solver options.
474/// The macros are `pub(crate)` and intended only for internal use within the `diffsol-c` crate.
475pub mod solve_macros;
476/// Internal serialization utilities for the dynamic dispatch solver types.
477///
478/// Defines the `SolveSerialization<M>` trait and implementations for various codegen backends
479/// (LLVM, Cranelift, external). Used by [OdeWrapper] during
480/// serialization/deserialization. All items are `pub(crate)`.
481mod solve_serialization;
482/// C FFI memory management helpers for string and byte buffer allocation.
483///
484/// Provides `extern "C"` functions for allocating and freeing Rust-owned memory from C code:
485/// - `diffsol_alloc_string` / `diffsol_free_string` — allocate/free Rust-owned C strings.
486/// - `diffsol_alloc` / `diffsol_free` — allocate/free byte buffers.
487///
488/// These are used by the other `_c` modules when returning dynamically sized data (e.g.
489/// serialized equation blobs) to C callers.
490#[path = "string_c.rs"]
491pub mod string_c;
492/// Utility functions for querying library capabilities.
493///
494/// Provides standalone functions useful for runtime capability checks:
495/// - [version] — returns the crate version string.
496/// - [is_klu_available] — returns `true` if the `suitesparse` feature (KLU sparse linear solver) was enabled at compile time.
497/// - [is_sens_available] — returns `true` if sensitivity analysis is supported on the current platform (not Windows).
498pub mod utils;
499/// Internal validation of linear solver compatibility with matrix types.
500///
501/// Provides `validate_linear_solver::<M>(linear_solver)` which checks that a given
502/// [LinearSolverType] is compatible with a
503/// matrix type `M`. For example, KLU is only valid for `FaerSparseMat<f64>` when the
504/// `suitesparse` feature is enabled. Uses `LuValidator<M>` and `KluValidator<M>` traits
505/// to associate each matrix type with its valid linear solver implementations.
506pub mod valid_linear_solver;
507
508#[cfg(test)]
509mod test_support;
510
511pub use adjoint_checkpoint::AdjointCheckpointWrapper;
512pub use error::DiffsolRtError;
513pub use host_array::{FromHostArray, HostArray, ToHostArray};
514pub use initial_condition_options::{
515    InitialConditionSolverOptions, InitialConditionSolverOptionsSnapshot,
516};
517pub use jit::{default_enabled_jit_backend, JitBackendType};
518pub use linear_solver_type::LinearSolverType;
519pub use matrix_type::MatrixType;
520pub use ode::OdeWrapper;
521pub use ode_options::{OdeSolverOptions, OdeSolverOptionsSnapshot};
522pub use ode_solver_type::OdeSolverType;
523pub use scalar_type::{Scalar, ScalarType, ToScalarType};
524pub use solution_wrapper::SolutionWrapper;
525pub use utils::{is_klu_available, is_sens_available, version};