1use crate::mol::PdeSystem;
8use numra_core::Scalar;
9
10#[derive(Clone, Debug)]
12pub struct HeatEquation1D<S: Scalar> {
13 pub alpha: S,
15}
16
17impl<S: Scalar> HeatEquation1D<S> {
18 pub fn new(alpha: S) -> Self {
19 Self { alpha }
20 }
21}
22
23impl<S: Scalar> PdeSystem<S> for HeatEquation1D<S> {
24 fn rhs(&self, _t: S, _x: S, _u: S, _du_dx: S, d2u_dx2: S) -> S {
25 self.alpha * d2u_dx2
26 }
27}
28
29#[derive(Clone)]
36pub struct DiffusionReaction1D<S: Scalar, R>
37where
38 R: Fn(S) -> S + Clone,
39{
40 pub diffusion: S,
42 pub reaction: R,
44}
45
46impl<S: Scalar, R: Fn(S) -> S + Clone> DiffusionReaction1D<S, R> {
47 pub fn new(diffusion: S, reaction: R) -> Self {
48 Self {
49 diffusion,
50 reaction,
51 }
52 }
53
54 pub fn fisher(diffusion: S, growth_rate: S) -> DiffusionReaction1D<S, impl Fn(S) -> S + Clone>
56 where
57 S: Copy,
58 {
59 let r = growth_rate;
60 DiffusionReaction1D::new(diffusion, move |u: S| r * u * (S::ONE - u))
61 }
62
63 pub fn allen_cahn(diffusion: S) -> DiffusionReaction1D<S, impl Fn(S) -> S + Clone>
65 where
66 S: Copy,
67 {
68 DiffusionReaction1D::new(diffusion, |u: S| u - u * u * u)
69 }
70}
71
72impl<S: Scalar, R: Fn(S) -> S + Clone> PdeSystem<S> for DiffusionReaction1D<S, R> {
73 fn rhs(&self, _t: S, _x: S, u: S, _du_dx: S, d2u_dx2: S) -> S {
74 self.diffusion * d2u_dx2 + (self.reaction)(u)
75 }
76}
77
78#[allow(dead_code)]
82#[derive(Clone, Debug)]
83pub struct AdvectionDiffusion1D<S: Scalar> {
84 pub diffusion: S,
86 pub velocity: S,
88}
89
90#[allow(dead_code)]
91impl<S: Scalar> AdvectionDiffusion1D<S> {
92 pub fn new(diffusion: S, velocity: S) -> Self {
93 Self {
94 diffusion,
95 velocity,
96 }
97 }
98}
99
100impl<S: Scalar> PdeSystem<S> for AdvectionDiffusion1D<S> {
101 fn rhs(&self, _t: S, _x: S, _u: S, du_dx: S, d2u_dx2: S) -> S {
102 self.diffusion * d2u_dx2 - self.velocity * du_dx
103 }
104}
105
106#[allow(dead_code)]
110#[derive(Clone, Debug)]
111pub struct Burgers1D<S: Scalar> {
112 pub viscosity: S,
114}
115
116#[allow(dead_code)]
117impl<S: Scalar> Burgers1D<S> {
118 pub fn new(viscosity: S) -> Self {
119 Self { viscosity }
120 }
121}
122
123impl<S: Scalar> PdeSystem<S> for Burgers1D<S> {
124 fn rhs(&self, _t: S, _x: S, u: S, du_dx: S, d2u_dx2: S) -> S {
125 self.viscosity * d2u_dx2 - u * du_dx
126 }
127}
128
129#[allow(dead_code)]
137#[derive(Clone, Debug)]
138pub struct Wave1D<S: Scalar> {
139 pub wave_speed: S,
141}
142
143#[allow(dead_code)]
144impl<S: Scalar> Wave1D<S> {
145 pub fn new(wave_speed: S) -> Self {
146 Self { wave_speed }
147 }
148}
149
150#[allow(dead_code)]
157#[derive(Clone)]
158pub struct HeatWithSource1D<S: Scalar, Q>
159where
160 Q: Fn(S, S) -> S + Clone,
161{
162 pub alpha: S,
164 pub source: Q,
166}
167
168#[allow(dead_code)]
169impl<S: Scalar, Q: Fn(S, S) -> S + Clone> HeatWithSource1D<S, Q> {
170 pub fn new(alpha: S, source: Q) -> Self {
171 Self { alpha, source }
172 }
173}
174
175impl<S: Scalar, Q: Fn(S, S) -> S + Clone> PdeSystem<S> for HeatWithSource1D<S, Q> {
176 fn rhs(&self, t: S, x: S, _u: S, _du_dx: S, d2u_dx2: S) -> S {
177 self.alpha * d2u_dx2 + (self.source)(x, t)
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184
185 #[test]
186 fn test_heat_equation() {
187 let heat = HeatEquation1D::new(0.1_f64);
188 let rhs = heat.rhs(0.0, 0.5, 0.25, 1.0, 2.0);
190 assert!((rhs - 0.2).abs() < 1e-10);
191 }
192
193 #[test]
194 fn test_fisher_equation() {
195 let fisher = DiffusionReaction1D::new(0.1_f64, |u: f64| u * (1.0 - u));
197 let rhs = fisher.rhs(0.0, 0.5, 0.5, 0.0, 2.0);
201 assert!((rhs - 0.45).abs() < 1e-10);
202 }
203
204 #[test]
205 fn test_burgers_equation() {
206 let burgers = Burgers1D::new(0.1_f64);
207 let rhs = burgers.rhs(0.0, 0.5, 1.0, 2.0, 0.0);
210 assert!((rhs - (-2.0)).abs() < 1e-10);
211 }
212
213 #[test]
214 fn test_heat_with_source() {
215 let heat = HeatWithSource1D::new(0.1_f64, |x: f64, _t: f64| x * x);
216 let rhs = heat.rhs(0.0, 0.5, 0.0, 0.0, 2.0);
220 assert!((rhs - 0.45).abs() < 1e-10);
221 }
222}