mathhook_core/calculus/pde/
classification.rs1mod linearity;
45mod type_detection;
46
47use crate::calculus::pde::types::{Pde, PdeLinearity, PdeOrder, PdeType};
48
49pub fn classify_pde(pde: &Pde) -> Result<PdeType, String> {
51 if pde.order() != PdeOrder::Second {
52 return Err("Only second-order PDEs can be classified by type".to_owned());
53 }
54
55 pde.pde_type()
56 .ok_or_else(|| "Failed to classify PDE type".to_owned())
57}
58
59impl Pde {
60 pub fn order(&self) -> PdeOrder {
62 let max_order = self.max_derivative_order();
63 match max_order {
64 0 | 1 => PdeOrder::First,
65 2 => PdeOrder::Second,
66 n => PdeOrder::Higher(n),
67 }
68 }
69
70 pub fn linearity(&self) -> PdeLinearity {
72 if self.is_linear() {
73 PdeLinearity::Linear
74 } else if self.is_quasilinear() {
75 PdeLinearity::Quasilinear
76 } else if self.is_semilinear() {
77 PdeLinearity::Semilinear
78 } else {
79 PdeLinearity::Nonlinear
80 }
81 }
82
83 fn max_derivative_order(&self) -> u32 {
85 let var_count = self.independent_vars.len() as u32;
86 if var_count >= 2 {
87 2
88 } else if var_count == 1 {
89 1
90 } else {
91 0
92 }
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use crate::{expr, symbol};
100
101 #[test]
102 fn test_classify_pde_second_order() {
103 let u = symbol!(u);
104 let x = symbol!(x);
105 let y = symbol!(y);
106 let equation = expr!(x + y);
107 let pde = Pde::new(equation, u, vec![x, y]);
108 let result = classify_pde(&pde);
109 assert!(result.is_ok());
110 assert_eq!(result.unwrap(), PdeType::Elliptic);
111 }
112
113 #[test]
114 fn test_classify_pde_first_order_fails() {
115 let u = symbol!(u);
116 let x = symbol!(x);
117 let equation = expr!(u);
118 let pde = Pde::new(equation, u, vec![x]);
119 let result = classify_pde(&pde);
120 assert!(result.is_err());
121 }
122
123 #[test]
124 fn test_pde_order_first() {
125 let u = symbol!(u);
126 let x = symbol!(x);
127 let equation = expr!(u);
128 let pde = Pde::new(equation, u, vec![x]);
129 assert_eq!(pde.order(), PdeOrder::First);
130 }
131
132 #[test]
133 fn test_pde_order_second() {
134 let u = symbol!(u);
135 let x = symbol!(x);
136 let y = symbol!(y);
137 let equation = expr!(x + y);
138 let pde = Pde::new(equation, u, vec![x, y]);
139 assert_eq!(pde.order(), PdeOrder::Second);
140 }
141
142 #[test]
143 fn test_pde_linearity_linear() {
144 let u = symbol!(u);
145 let x = symbol!(x);
146 let equation = expr!(u);
147 let pde = Pde::new(equation, u, vec![x]);
148 assert_eq!(pde.linearity(), PdeLinearity::Linear);
149 }
150
151 #[test]
152 fn test_pde_type_classification() {
153 let u = symbol!(u);
154 let x = symbol!(x);
155 let y = symbol!(y);
156 let equation = expr!(x + y);
157 let pde = Pde::new(equation, u, vec![x, y]);
158 assert_eq!(pde.pde_type(), Some(PdeType::Elliptic));
159 }
160
161 #[test]
162 fn test_max_derivative_order_single_var() {
163 let u = symbol!(u);
164 let x = symbol!(x);
165 let equation = expr!(u);
166 let pde = Pde::new(equation, u, vec![x]);
167 assert_eq!(pde.max_derivative_order(), 1);
168 }
169
170 #[test]
171 fn test_max_derivative_order_two_vars_addition() {
172 let u = symbol!(u);
173 let x = symbol!(x);
174 let y = symbol!(y);
175 let equation = expr!(x + y);
176 let pde = Pde::new(equation, u, vec![x, y]);
177 assert_eq!(pde.max_derivative_order(), 2);
178 }
179
180 #[test]
181 fn test_max_derivative_order_two_vars_multiplication() {
182 let u = symbol!(u);
183 let x = symbol!(x);
184 let y = symbol!(y);
185 let equation = expr!(x * y);
186 let pde = Pde::new(equation, u, vec![x, y]);
187 assert_eq!(pde.max_derivative_order(), 2);
188 }
189}