mod linearity;
mod type_detection;
use crate::calculus::pde::types::{Pde, PdeLinearity, PdeOrder, PdeType};
pub fn classify_pde(pde: &Pde) -> Result<PdeType, String> {
if pde.order() != PdeOrder::Second {
return Err("Only second-order PDEs can be classified by type".to_owned());
}
pde.pde_type()
.ok_or_else(|| "Failed to classify PDE type".to_owned())
}
impl Pde {
pub fn order(&self) -> PdeOrder {
let max_order = self.max_derivative_order();
match max_order {
0 | 1 => PdeOrder::First,
2 => PdeOrder::Second,
n => PdeOrder::Higher(n),
}
}
pub fn linearity(&self) -> PdeLinearity {
if self.is_linear() {
PdeLinearity::Linear
} else if self.is_quasilinear() {
PdeLinearity::Quasilinear
} else if self.is_semilinear() {
PdeLinearity::Semilinear
} else {
PdeLinearity::Nonlinear
}
}
fn max_derivative_order(&self) -> u32 {
let var_count = self.independent_vars.len() as u32;
if var_count >= 2 {
2
} else if var_count == 1 {
1
} else {
0
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{expr, symbol};
#[test]
fn test_classify_pde_second_order() {
let u = symbol!(u);
let x = symbol!(x);
let y = symbol!(y);
let equation = expr!(x + y);
let pde = Pde::new(equation, u, vec![x, y]);
let result = classify_pde(&pde);
assert!(result.is_ok());
assert_eq!(result.unwrap(), PdeType::Elliptic);
}
#[test]
fn test_classify_pde_first_order_fails() {
let u = symbol!(u);
let x = symbol!(x);
let equation = expr!(u);
let pde = Pde::new(equation, u, vec![x]);
let result = classify_pde(&pde);
assert!(result.is_err());
}
#[test]
fn test_pde_order_first() {
let u = symbol!(u);
let x = symbol!(x);
let equation = expr!(u);
let pde = Pde::new(equation, u, vec![x]);
assert_eq!(pde.order(), PdeOrder::First);
}
#[test]
fn test_pde_order_second() {
let u = symbol!(u);
let x = symbol!(x);
let y = symbol!(y);
let equation = expr!(x + y);
let pde = Pde::new(equation, u, vec![x, y]);
assert_eq!(pde.order(), PdeOrder::Second);
}
#[test]
fn test_pde_linearity_linear() {
let u = symbol!(u);
let x = symbol!(x);
let equation = expr!(u);
let pde = Pde::new(equation, u, vec![x]);
assert_eq!(pde.linearity(), PdeLinearity::Linear);
}
#[test]
fn test_pde_type_classification() {
let u = symbol!(u);
let x = symbol!(x);
let y = symbol!(y);
let equation = expr!(x + y);
let pde = Pde::new(equation, u, vec![x, y]);
assert_eq!(pde.pde_type(), Some(PdeType::Elliptic));
}
#[test]
fn test_max_derivative_order_single_var() {
let u = symbol!(u);
let x = symbol!(x);
let equation = expr!(u);
let pde = Pde::new(equation, u, vec![x]);
assert_eq!(pde.max_derivative_order(), 1);
}
#[test]
fn test_max_derivative_order_two_vars_addition() {
let u = symbol!(u);
let x = symbol!(x);
let y = symbol!(y);
let equation = expr!(x + y);
let pde = Pde::new(equation, u, vec![x, y]);
assert_eq!(pde.max_derivative_order(), 2);
}
#[test]
fn test_max_derivative_order_two_vars_multiplication() {
let u = symbol!(u);
let x = symbol!(x);
let y = symbol!(y);
let equation = expr!(x * y);
let pde = Pde::new(equation, u, vec![x, y]);
assert_eq!(pde.max_derivative_order(), 2);
}
}