mathhook_core/calculus/pde/common/domain.rs
1//! Domain extraction utilities for PDE boundary value problems
2
3use crate::calculus::pde::registry::PDEError;
4use crate::calculus::pde::types::{BoundaryCondition, BoundaryLocation};
5use crate::core::{Expression, Symbol};
6
7/// Extracts domain length from boundary conditions.
8///
9/// Assumes domain [0, L] with boundary conditions specified at x=0 and x=L.
10/// Searches for the right boundary value (non-zero location) and returns it as domain length.
11///
12/// # Arguments
13/// * `boundary_conditions` - Boundary conditions
14/// * `spatial_var` - Spatial variable symbol
15///
16/// # Returns
17/// Domain length L. Defaults to π if no explicit length found.
18///
19/// # Examples
20/// ```rust
21/// use mathhook_core::calculus::pde::common::extract_domain_length;
22/// use mathhook_core::calculus::pde::types::{BoundaryCondition, BoundaryLocation};
23/// use mathhook_core::{symbol, expr};
24///
25/// let x = symbol!(x);
26/// let bc = BoundaryCondition::dirichlet(
27/// expr!(0),
28/// BoundaryLocation::Simple { variable: x.clone(), value: expr!(10) }
29/// );
30/// let length = extract_domain_length(&[bc], &x).unwrap();
31/// ```
32pub fn extract_domain_length(
33 boundary_conditions: &[BoundaryCondition],
34 spatial_var: &Symbol,
35) -> Result<Expression, PDEError> {
36 for bc in boundary_conditions {
37 let location = match bc {
38 BoundaryCondition::Dirichlet { location, .. } => location,
39 BoundaryCondition::Neumann { location, .. } => location,
40 BoundaryCondition::Robin { location, .. } => location,
41 };
42
43 if let BoundaryLocation::Simple {
44 variable,
45 value: location_value,
46 } = location
47 {
48 if variable == spatial_var
49 && !matches!(location_value, Expression::Number(n) if n.is_zero())
50 {
51 return Ok(location_value.clone());
52 }
53 }
54 }
55
56 Ok(Expression::pi())
57}