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