Skip to main content

deep_causality_physics/quantities/mhd/
mod.rs

1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) 2023 - 2026. The DeepCausality Authors and Contributors. All Rights Reserved.
4 */
5
6use crate::PhysicsError;
7
8/// Alfven Speed ($v_A$). Characteristic speed of magnetic waves in plasma.
9/// Unit: m/s. Constraint: >= 0.
10#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
11pub struct AlfvenSpeed<R: deep_causality_algebra::RealField>(R);
12
13impl<R: deep_causality_algebra::RealField> Default for AlfvenSpeed<R> {
14    fn default() -> Self {
15        Self(R::zero())
16    }
17}
18
19impl<R: deep_causality_algebra::RealField> AlfvenSpeed<R> {
20    pub fn new(val: R) -> Result<Self, PhysicsError> {
21        if !val.is_finite() {
22            return Err(PhysicsError::PhysicalInvariantBroken(
23                "Alfven Speed must be finite".into(),
24            ));
25        }
26        if val < R::zero() {
27            return Err(PhysicsError::PhysicalInvariantBroken(
28                "Alfven Speed cannot be negative".into(),
29            ));
30        }
31        Ok(Self(val))
32    }
33    /// Creates a new `AlfvenSpeed` without validation.
34    /// Use only if the value is guaranteed to be non-negative.
35    pub fn new_unchecked(val: R) -> Self {
36        Self(val)
37    }
38    pub fn value(&self) -> R {
39        self.0
40    }
41}
42
43impl<R: deep_causality_algebra::RealField + Into<f64>> From<AlfvenSpeed<R>> for f64 {
44    fn from(val: AlfvenSpeed<R>) -> Self {
45        val.0.into()
46    }
47}
48
49/// Plasma Beta ($\beta$). Ratio of thermal to magnetic pressure.
50/// Unit: Dimensionless. Constraint: >= 0.
51#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
52pub struct PlasmaBeta<R: deep_causality_algebra::RealField>(R);
53
54impl<R: deep_causality_algebra::RealField> Default for PlasmaBeta<R> {
55    fn default() -> Self {
56        Self(R::zero())
57    }
58}
59
60impl<R: deep_causality_algebra::RealField> PlasmaBeta<R> {
61    pub fn new(val: R) -> Result<Self, PhysicsError> {
62        if !val.is_finite() {
63            return Err(PhysicsError::PhysicalInvariantBroken(
64                "Plasma Beta must be finite".into(),
65            ));
66        }
67        if val < R::zero() {
68            return Err(PhysicsError::PhysicalInvariantBroken(
69                "Plasma Beta cannot be negative".into(),
70            ));
71        }
72        Ok(Self(val))
73    }
74    pub fn new_unchecked(val: R) -> Self {
75        Self(val)
76    }
77    pub fn value(&self) -> R {
78        self.0
79    }
80}
81
82impl<R: deep_causality_algebra::RealField + Into<f64>> From<PlasmaBeta<R>> for f64 {
83    fn from(val: PlasmaBeta<R>) -> Self {
84        val.0.into()
85    }
86}
87
88/// Magnetic Pressure ($P_B$). Energy density of the magnetic field.
89/// Unit: Pascals (Pa). Constraint: >= 0.
90#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
91pub struct MagneticPressure<R: deep_causality_algebra::RealField>(R);
92
93impl<R: deep_causality_algebra::RealField> Default for MagneticPressure<R> {
94    fn default() -> Self {
95        Self(R::zero())
96    }
97}
98
99impl<R: deep_causality_algebra::RealField> MagneticPressure<R> {
100    pub fn new(val: R) -> Result<Self, PhysicsError> {
101        if !val.is_finite() {
102            return Err(PhysicsError::PhysicalInvariantBroken(
103                "Magnetic Pressure must be finite".into(),
104            ));
105        }
106        if val < R::zero() {
107            return Err(PhysicsError::PhysicalInvariantBroken(
108                "Magnetic Pressure cannot be negative".into(),
109            ));
110        }
111        Ok(Self(val))
112    }
113    pub fn new_unchecked(val: R) -> Self {
114        Self(val)
115    }
116    pub fn value(&self) -> R {
117        self.0
118    }
119}
120
121impl<R: deep_causality_algebra::RealField + Into<f64>> From<MagneticPressure<R>> for f64 {
122    fn from(val: MagneticPressure<R>) -> Self {
123        val.0.into()
124    }
125}
126
127/// Larmor Radius ($r_L$). Gyroradius of a charged particle.
128/// Unit: Meters (m). Constraint: > 0.
129#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
130pub struct LarmorRadius<R: deep_causality_algebra::RealField>(R);
131
132impl<R: deep_causality_algebra::RealField> LarmorRadius<R> {
133    pub fn new(val: R) -> Result<Self, PhysicsError> {
134        if !val.is_finite() {
135            return Err(PhysicsError::PhysicalInvariantBroken(
136                "Larmor Radius must be finite".into(),
137            ));
138        }
139        if val <= R::zero() {
140            return Err(PhysicsError::PhysicalInvariantBroken(
141                "Larmor Radius must be positive".into(),
142            ));
143        }
144        Ok(Self(val))
145    }
146    pub fn new_unchecked(val: R) -> Self {
147        Self(val)
148    }
149    pub fn value(&self) -> R {
150        self.0
151    }
152}
153
154impl<R: deep_causality_algebra::RealField> Default for LarmorRadius<R> {
155    /// Returns machine epsilon as the smallest representable positive value
156    /// that satisfies the > 0 constraint.
157    fn default() -> Self {
158        Self(R::epsilon())
159    }
160}
161
162impl<R: deep_causality_algebra::RealField + Into<f64>> From<LarmorRadius<R>> for f64 {
163    fn from(val: LarmorRadius<R>) -> Self {
164        val.0.into()
165    }
166}
167
168/// Debye Length ($\lambda_D$). Screening length in plasma.
169/// Unit: Meters (m). Constraint: > 0.
170#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
171pub struct DebyeLength<R: deep_causality_algebra::RealField>(R);
172
173impl<R: deep_causality_algebra::RealField> DebyeLength<R> {
174    pub fn new(val: R) -> Result<Self, PhysicsError> {
175        if !val.is_finite() {
176            return Err(PhysicsError::PhysicalInvariantBroken(
177                "Debye Length must be finite".into(),
178            ));
179        }
180        if val <= R::zero() {
181            return Err(PhysicsError::PhysicalInvariantBroken(
182                "Debye Length must be positive".into(),
183            ));
184        }
185        Ok(Self(val))
186    }
187    pub fn new_unchecked(val: R) -> Self {
188        Self(val)
189    }
190    pub fn value(&self) -> R {
191        self.0
192    }
193}
194
195impl<R: deep_causality_algebra::RealField> Default for DebyeLength<R> {
196    /// Returns machine epsilon as the smallest representable positive value
197    /// that satisfies the > 0 constraint.
198    fn default() -> Self {
199        Self(R::epsilon())
200    }
201}
202
203impl<R: deep_causality_algebra::RealField + Into<f64>> From<DebyeLength<R>> for f64 {
204    fn from(val: DebyeLength<R>) -> Self {
205        val.0.into()
206    }
207}
208
209/// Plasma Frequency ($\omega_{pe}$). Natural oscillation frequency.
210/// Unit: Rad/s. Constraint: > 0.
211#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
212pub struct PlasmaFrequency<R: deep_causality_algebra::RealField>(R);
213
214impl<R: deep_causality_algebra::RealField> PlasmaFrequency<R> {
215    pub fn new(val: R) -> Result<Self, PhysicsError> {
216        if !val.is_finite() {
217            return Err(PhysicsError::PhysicalInvariantBroken(
218                "Plasma Frequency must be finite".into(),
219            ));
220        }
221        if val <= R::zero() {
222            return Err(PhysicsError::PhysicalInvariantBroken(
223                "Plasma Frequency must be positive".into(),
224            ));
225        }
226        Ok(Self(val))
227    }
228    pub fn new_unchecked(val: R) -> Self {
229        Self(val)
230    }
231    pub fn value(&self) -> R {
232        self.0
233    }
234}
235
236impl<R: deep_causality_algebra::RealField> Default for PlasmaFrequency<R> {
237    /// Returns machine epsilon as the smallest representable positive value
238    /// that satisfies the > 0 constraint.
239    fn default() -> Self {
240        Self(R::epsilon())
241    }
242}
243
244impl<R: deep_causality_algebra::RealField + Into<f64>> From<PlasmaFrequency<R>> for f64 {
245    fn from(val: PlasmaFrequency<R>) -> Self {
246        val.0.into()
247    }
248}
249
250/// Electrical Conductivity ($\sigma$).
251/// Unit: Siemens/m (S/m). Constraint: > 0.
252#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
253pub struct Conductivity<R: deep_causality_algebra::RealField>(R);
254
255impl<R: deep_causality_algebra::RealField> Conductivity<R> {
256    pub fn new(val: R) -> Result<Self, PhysicsError> {
257        if !val.is_finite() {
258            return Err(PhysicsError::PhysicalInvariantBroken(
259                "Conductivity must be finite".into(),
260            ));
261        }
262        if val <= R::zero() {
263            return Err(PhysicsError::PhysicalInvariantBroken(
264                "Conductivity must be positive".into(),
265            ));
266        }
267        Ok(Self(val))
268    }
269    pub fn new_unchecked(val: R) -> Self {
270        Self(val)
271    }
272    pub fn value(&self) -> R {
273        self.0
274    }
275}
276
277impl<R: deep_causality_algebra::RealField> Default for Conductivity<R> {
278    /// Returns machine epsilon as the smallest representable positive value
279    /// that satisfies the > 0 constraint.
280    fn default() -> Self {
281        Self(R::epsilon())
282    }
283}
284
285impl<R: deep_causality_algebra::RealField + Into<f64>> From<Conductivity<R>> for f64 {
286    fn from(val: Conductivity<R>) -> Self {
287        val.0.into()
288    }
289}
290
291/// Magnetic Diffusivity ($\eta$).
292/// Unit: $m^2/s$. Constraint: >= 0.
293#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
294pub struct Diffusivity<R: deep_causality_algebra::RealField>(R);
295
296impl<R: deep_causality_algebra::RealField> Default for Diffusivity<R> {
297    fn default() -> Self {
298        Self(R::zero())
299    }
300}
301
302impl<R: deep_causality_algebra::RealField> Diffusivity<R> {
303    pub fn new(val: R) -> Result<Self, PhysicsError> {
304        if !val.is_finite() {
305            return Err(PhysicsError::PhysicalInvariantBroken(
306                "Diffusivity must be finite".into(),
307            ));
308        }
309        if val < R::zero() {
310            return Err(PhysicsError::PhysicalInvariantBroken(
311                "Diffusivity cannot be negative".into(),
312            ));
313        }
314        Ok(Self(val))
315    }
316    pub fn new_unchecked(val: R) -> Self {
317        Self(val)
318    }
319    pub fn value(&self) -> R {
320        self.0
321    }
322}
323
324impl<R: deep_causality_algebra::RealField + Into<f64>> From<Diffusivity<R>> for f64 {
325    fn from(val: Diffusivity<R>) -> Self {
326        val.0.into()
327    }
328}