Skip to main content

phyz_format/
coupling.rs

1//! Coupling definitions between physics domains.
2
3use serde::{Deserialize, Serialize};
4
5/// Coupling between two physics domains.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Coupling {
8    /// Coupling name.
9    pub name: String,
10    /// Source domain name.
11    pub source: String,
12    /// Target domain name.
13    pub target: String,
14    /// Type of coupling.
15    #[serde(rename = "type")]
16    pub coupling_type: CouplingType,
17    /// Force transfer mechanism.
18    pub force_transfer: ForceTransfer,
19    /// Coupling strength/stiffness.
20    #[serde(default = "default_coupling_strength")]
21    pub strength: f64,
22}
23
24fn default_coupling_strength() -> f64 {
25    1.0
26}
27
28/// Type of coupling between domains.
29#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
30#[serde(rename_all = "kebab-case")]
31pub enum CouplingType {
32    /// One-way coupling (source affects target).
33    OneWay,
34    /// Two-way coupling (mutual interaction).
35    TwoWay,
36    /// Overlap region coupling.
37    OverlapRegion,
38    /// Interface boundary coupling.
39    Interface,
40}
41
42/// Mechanism for transferring forces between domains.
43#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
44#[serde(rename_all = "lowercase")]
45pub enum ForceTransfer {
46    /// Direct force transfer.
47    Direct,
48    /// Lorentz force (EM coupling).
49    Lorentz,
50    /// Contact forces.
51    Contact,
52    /// Penalty-based coupling.
53    Penalty,
54    /// Lagrange multiplier constraints.
55    Lagrange,
56}
57
58/// Region definition for overlap coupling.
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct OverlapRegion {
61    /// Region type.
62    #[serde(rename = "type")]
63    pub region_type: RegionType,
64    /// Region parameters (e.g., min/max for AABB).
65    #[serde(flatten)]
66    pub params: std::collections::HashMap<String, serde_json::Value>,
67}
68
69/// Type of overlap region.
70#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
71#[serde(rename_all = "lowercase")]
72pub enum RegionType {
73    /// Axis-aligned bounding box.
74    Aabb,
75    /// Sphere.
76    Sphere,
77    /// Cylinder.
78    Cylinder,
79    /// Custom mesh.
80    Mesh,
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn test_coupling_serialization() {
89        let coupling = Coupling {
90            name: "rigid-em".to_string(),
91            source: "rigid_body".to_string(),
92            target: "em".to_string(),
93            coupling_type: CouplingType::TwoWay,
94            force_transfer: ForceTransfer::Lorentz,
95            strength: 1.0,
96        };
97
98        let json = serde_json::to_string(&coupling).unwrap();
99        let parsed: Coupling = serde_json::from_str(&json).unwrap();
100
101        assert_eq!(parsed.name, "rigid-em");
102        assert_eq!(parsed.coupling_type, CouplingType::TwoWay);
103        assert_eq!(parsed.force_transfer, ForceTransfer::Lorentz);
104    }
105
106    #[test]
107    fn test_coupling_type_serialization() {
108        let ct = CouplingType::OverlapRegion;
109        let json = serde_json::to_string(&ct).unwrap();
110        assert_eq!(json, "\"overlap-region\"");
111    }
112
113    #[test]
114    fn test_force_transfer_serialization() {
115        let ft = ForceTransfer::Penalty;
116        let json = serde_json::to_string(&ft).unwrap();
117        assert_eq!(json, "\"penalty\"");
118    }
119}