Skip to main content

numra_pde/
lib.rs

1// Allow some clippy lints that are prevalent in numerical code
2#![allow(clippy::assign_op_pattern)]
3#![allow(clippy::needless_range_loop)]
4#![allow(clippy::manual_range_contains)]
5#![allow(clippy::identity_op)]
6
7//! PDE (Partial Differential Equation) solvers for Numra.
8//!
9//! This crate provides the Method of Lines (MOL) approach for solving PDEs:
10//!
11//! 1. Discretize spatial derivatives using finite differences (FDM)
12//! 2. Convert the PDE to a system of ODEs in time
13//! 3. Solve using ODE solvers from `numra-ode`
14//!
15//! # Supported Equation Types
16//!
17//! - **Parabolic PDEs**: Heat equation, diffusion equations
18//! - **Moving boundary problems**: Stefan problem, phase change
19//! - **Reaction-diffusion**: Turing patterns, combustion
20//!
21//! # Example: 1D Heat Equation
22//!
23//! ```
24//! use numra_pde::{Grid1D, HeatEquation1D, MOLSystem};
25//! use numra_pde::boundary::DirichletBC;
26//! use numra_ode::{DoPri5, Solver, SolverOptions};
27//!
28//! // Create spatial grid
29//! let grid = Grid1D::uniform(0.0_f64, 1.0, 51);
30//!
31//! // Heat equation with diffusivity α = 0.01
32//! let pde = HeatEquation1D::new(0.01);
33//!
34//! // Boundary conditions: T(0) = 1, T(1) = 0
35//! let bc_left = DirichletBC::new(1.0);
36//! let bc_right = DirichletBC::new(0.0);
37//!
38//! // Create MOL system
39//! let mol = MOLSystem::new(pde, grid.clone(), bc_left, bc_right);
40//!
41//! // Initial condition: T(x,0) = sin(πx)
42//! let u0: Vec<f64> = grid.points()
43//!     .iter()
44//!     .map(|&x| (std::f64::consts::PI * x).sin())
45//!     .collect();
46//!
47//! // Solve (interior points only)
48//! let options = SolverOptions::default().rtol(1e-6);
49//! let result = DoPri5::solve(&mol, 0.0, 0.5, &u0[1..u0.len()-1], &options);
50//! ```
51//!
52//! # Moving Boundary Problems
53//!
54//! For problems like the Stefan problem where the domain boundary moves:
55//!
56//! ```text
57//! ∂T/∂t = α ∂²T/∂x²,  0 < x < s(t)
58//! T(0,t) = T_hot
59//! T(s(t),t) = T_melt
60//! ds/dt = -k ∂T/∂x |_{x=s(t)}  (Stefan condition)
61//! ```
62//!
63//! Use the `moving` module with coordinate transforms.
64//!
65//! Author: Moussa Leblouba
66//! Date: 9 February 2026
67//! Modified: 2 May 2026
68
69pub use numra_core::Scalar;
70
71pub mod boundary;
72pub mod boundary2d;
73mod discretize;
74mod equations;
75mod equations2d;
76mod equations3d;
77mod grid;
78mod mol;
79mod mol2d;
80mod mol2d_parametric;
81mod mol3d;
82mod mol3d_parametric;
83pub mod moving;
84mod sparse_assembly;
85
86pub use boundary::{BoundaryCondition, DirichletBC, NeumannBC, PeriodicBC, RobinBC};
87pub use boundary2d::{BoundaryConditions2D, BoundaryConditions3D};
88pub use discretize::{DifferenceScheme, Stencil, FDM};
89pub use equations::{DiffusionReaction1D, HeatEquation1D};
90pub use equations2d::{AdvectionDiffusion2D, HeatEquation2D, ReactionDiffusion2D};
91pub use equations3d::{AdvectionDiffusion3D, HeatEquation3D, ReactionDiffusion3D};
92pub use grid::{Grid1D, Grid2D, Grid3D};
93pub use mol::{MOLSystem, PdeSystem};
94pub use mol2d::MOLSystem2D;
95pub use mol2d_parametric::ParametricMOLSystem2D;
96pub use mol3d::MOLSystem3D;
97pub use mol3d_parametric::ParametricMOLSystem3D;
98pub use moving::{Bound, CoordinateTransform, Domain1D, MovingBound, StefanCondition};
99pub use sparse_assembly::{
100    assemble_laplacian_2d, assemble_laplacian_3d, assemble_operator_2d, assemble_operator_3d,
101    Operator2DCoefficients, Operator3DCoefficients, SparseScalar,
102};