chrom_rs/lib.rs
1//! chrom-rs: Chromatography Simulation Framework
2//!
3//! A flexible and extensible framework for simulating liquid chromatographic
4//! processes using numerical methods. Built with Rust for performance and safety.
5//!
6//! # Architecture
7//!
8//! chrom-rs is built on two core principles:
9//!
10//! 1. **Separation of physics and numerics** — physical models define the
11//! equations (what to solve); numerical solvers provide the integration
12//! method (how to solve them). The same model can be solved with any
13//! solver, and the same solver can integrate any model.
14//!
15//! 2. **Extensibility and type safety** — all extension points are traits;
16//! state is managed through typed containers; the API is stable from
17//! v0.1.0 onwards.
18//!
19//! # Quick Start
20//!
21//! ```rust
22//! use chrom_rs::physics::{PhysicalModel, PhysicalState, PhysicalQuantity, PhysicalData};
23//! use chrom_rs::solver::{EulerSolver, Solver, SolverConfiguration, Scenario, DomainBoundaries};
24//! use nalgebra::DVector;
25//! use serde::{Deserialize, Serialize};
26//!
27//! # #[derive(Deserialize, Serialize)]
28//! # struct MyModel;
29//! # #[typetag::serde]
30//! # impl PhysicalModel for MyModel {
31//! # fn points(&self) -> usize { 1 }
32//! # fn compute_physics(&self, state: &PhysicalState, _ctx: &chrom_rs::physics::ComputeContext) -> PhysicalState { state.clone() }
33//! # fn setup_initial_state(&self) -> PhysicalState {
34//! # PhysicalState::new(PhysicalQuantity::Concentration, PhysicalData::Vector(nalgebra::DVector::from_vec(vec![1.0])))
35//! # }
36//! # fn name(&self) -> &str { "MyModel" }
37//! # }
38//! # fn main() -> Result<(), String> {
39//! // 1. Configure physical model and scenario
40//! let model = Box::new(MyModel);
41//! let initial_state = model.setup_initial_state();
42//! let boundaries = DomainBoundaries::temporal(initial_state);
43//! let scenario = Scenario::new(model, boundaries);
44//!
45//! // 2. Configure solver
46//! let config = SolverConfiguration::time_evolution(
47//! 600.0, // 10 minutes total time
48//! 1000, // 1000 time steps
49//! );
50//!
51//! // 3. Run simulation
52//! let solver = EulerSolver::new();
53//! let result = solver.solve(&scenario, &config)?;
54//!
55//! // 4. Access results
56//! println!("Simulation completed!");
57//! println!("Trajectory length: {}", result.len());
58//! # Ok(())
59//! # }
60//! ```
61//!
62//! # Modules
63//!
64//! | Module | Role |
65//! |--------|------|
66//! | [`physics`] | Core traits and data types for physical models |
67//! | [`models`] | Concrete chromatography models (Langmuir single and multi-species) |
68//! | [`solver`] | Numerical solvers, scenario definition, and simulation result |
69//! | [`config`] | YAML/JSON configuration file loaders |
70//! | [`output`] | CSV export, JSON export, and chromatogram visualisation |
71//! | [`cli`] | Command-line interface built on `dynamic-cli` |
72//! | [`prelude`] | Convenience re-exports for the most common types |
73
74/// Physical domain model — equipment description layer.
75///
76/// Provides validated, model-agnostic types for the physical equipment:
77/// [`domain::Column`], [`domain::MobilePhase`], [`domain::Sample`], and
78/// [`domain::Detector`]. These types serve as a construction facade for all
79/// physical models ([`models::LangmuirSingle`], [`models::LangmuirMulti`], …)
80/// via their `from_domain` constructors.
81///
82/// See [DD-011](https://github.com/biface/chromatography/issues/16) for the
83/// design rationale.
84pub mod domain;
85
86/// Physical model traits, state containers, and data types.
87///
88/// Defines the extension points that all physical models must implement,
89/// as well as the typed containers ([`physics::PhysicalState`],
90/// [`physics::PhysicalData`]) used to exchange state between models and
91/// solvers.
92pub mod physics;
93
94/// Concrete chromatography models.
95///
96/// Contains [`models::LangmuirSingle`] for single-species simulations and
97/// [`models::LangmuirMulti`] for competitive multi-species adsorption, along
98/// with the [`models::TemporalInjection`] type that defines inlet boundary
99/// conditions as a function of time.
100pub mod models;
101
102/// Numerical solvers and simulation infrastructure.
103///
104/// Provides [`solver::Solver`] implementations (Forward Euler, RK4), the
105/// [`solver::Scenario`] type that binds a model to its boundary conditions,
106/// [`solver::SolverConfiguration`] for numerical parameters, and
107/// [`solver::SimulationResult`] which holds the computed trajectory.
108pub mod solver;
109
110/// Result visualisation and data export.
111///
112/// Sub-modules cover CSV export, JSON export, and chromatogram plots via
113/// `plotters`. See [`output::export`] and [`output::visualization`].
114pub mod output;
115
116/// Configuration file loaders for the three-file layout.
117///
118/// Each loader reads one YAML or JSON file and returns the corresponding
119/// domain object: [`config::model::load_model`] → `Box<dyn PhysicalModel>`,
120/// [`config::scenario::load_scenario`] → [`solver::DomainBoundaries`],
121/// [`config::solver::load_solver`] → [`solver::SolverConfiguration`].
122pub mod config;
123
124/// Command-line interface.
125///
126/// Entry point is [`cli::build_app`], which assembles the `dynamic-cli`
127/// application from the embedded `commands.yml` declaration and wires
128/// [`cli::app::RunHandler`] to the simulation pipeline.
129pub mod cli;
130
131/// Convenient re-exports for the most commonly used types.
132///
133/// Import everything with `use chrom_rs::prelude::*` to get the core traits
134/// and types without writing long paths.
135///
136/// ```rust
137/// use chrom_rs::prelude::*;
138/// ```
139pub mod prelude {
140 pub use crate::domain::{
141 Column, ColumnError, Detector, DetectorPosition, MobilePhase, MobilePhaseError, Sample,
142 };
143 pub use crate::models::TemporalInjection;
144 pub use crate::physics::{PhysicalData, PhysicalModel, PhysicalQuantity, PhysicalState};
145 pub use crate::solver::{
146 EulerSolver, RK4Solver, Scenario, SimulationResult, Solver, SolverConfiguration, SolverType,
147 };
148}