Skip to main content

pcb_toolkit/
materials.rs

1//! PCB substrate material database.
2
3use serde::{Deserialize, Serialize};
4
5/// A PCB substrate material with dielectric properties.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct Material {
8    pub name: &'static str,
9    /// Relative permittivity (dielectric constant).
10    pub er: f64,
11    /// Glass transition temperature (°C), if known.
12    pub tg: Option<f64>,
13    /// Surface roughness correction factor (0.98 for FR-4 variants, 1.0 for smooth).
14    pub roughness_factor: f64,
15}
16
17/// Built-in material database.
18///
19/// Roughness factor: 0.98 for FR-4 family, 1.0 for others.
20pub static MATERIALS: &[Material] = &[
21    Material { name: "FR-4 STD", er: 4.60, tg: Some(130.0), roughness_factor: 0.98 },
22    Material { name: "FR-5", er: 4.30, tg: Some(170.0), roughness_factor: 0.98 },
23    Material { name: "FR406", er: 4.60, tg: Some(170.0), roughness_factor: 0.98 },
24    Material { name: "FR408", er: 3.80, tg: Some(180.0), roughness_factor: 0.98 },
25    Material { name: "Getek ML200C", er: 3.80, tg: Some(175.0), roughness_factor: 0.98 },
26    Material { name: "Getek ML200D", er: 3.90, tg: Some(175.0), roughness_factor: 0.98 },
27    Material { name: "Getek ML200M", er: 3.80, tg: Some(175.0), roughness_factor: 0.98 },
28    Material { name: "Getek RG200D", er: 4.20, tg: Some(175.0), roughness_factor: 0.98 },
29    Material { name: "Isola P95", er: 3.78, tg: Some(260.0), roughness_factor: 1.0 },
30    Material { name: "Isola P96", er: 3.78, tg: Some(260.0), roughness_factor: 1.0 },
31    Material { name: "Isola P26N", er: 3.90, tg: Some(250.0), roughness_factor: 1.0 },
32    Material { name: "RO2800", er: 2.94, tg: None, roughness_factor: 1.0 },
33    Material { name: "RO3003", er: 3.00, tg: None, roughness_factor: 1.0 },
34    Material { name: "RO3006", er: 6.15, tg: None, roughness_factor: 1.0 },
35    Material { name: "RO3010", er: 10.20, tg: None, roughness_factor: 1.0 },
36    Material { name: "RO4003", er: 3.38, tg: Some(280.0), roughness_factor: 1.0 },
37    Material { name: "RO4350", er: 3.66, tg: Some(280.0), roughness_factor: 1.0 },
38    Material { name: "RT5500", er: 2.50, tg: Some(260.0), roughness_factor: 1.0 },
39    Material { name: "RT5870", er: 2.35, tg: Some(260.0), roughness_factor: 1.0 },
40    Material { name: "RT5880", er: 2.20, tg: Some(260.0), roughness_factor: 1.0 },
41    Material { name: "RT6002", er: 2.94, tg: None, roughness_factor: 1.0 },
42    Material { name: "RT6006", er: 6.15, tg: None, roughness_factor: 1.0 },
43    Material { name: "RT6010", er: 10.20, tg: None, roughness_factor: 1.0 },
44    Material { name: "Teflon PTFE", er: 2.10, tg: Some(240.0), roughness_factor: 1.0 },
45    Material { name: "Arlon 25N", er: 3.38, tg: Some(260.0), roughness_factor: 1.0 },
46    Material { name: "Arlon 33N", er: 4.25, tg: Some(250.0), roughness_factor: 1.0 },
47    Material { name: "Arlon 85N", er: 4.20, tg: Some(250.0), roughness_factor: 1.0 },
48    Material { name: "PCL-FR-226", er: 4.50, tg: Some(140.0), roughness_factor: 0.98 },
49    Material { name: "PCL-FR-240", er: 4.50, tg: Some(140.0), roughness_factor: 0.98 },
50    Material { name: "PCL-FR-370", er: 4.50, tg: Some(175.0), roughness_factor: 0.98 },
51    Material { name: "PCL-FR-370HR", er: 4.60, tg: Some(180.0), roughness_factor: 0.98 },
52    Material { name: "N4000-7 EF", er: 4.10, tg: Some(165.0), roughness_factor: 0.98 },
53    Material { name: "N4000-13", er: 3.70, tg: Some(210.0), roughness_factor: 0.98 },
54    Material { name: "N4000-13SI", er: 3.40, tg: Some(210.0), roughness_factor: 0.98 },
55    Material { name: "N4000-13 EP", er: 3.70, tg: Some(210.0), roughness_factor: 0.98 },
56    Material { name: "N4000-13 EPSI", er: 3.40, tg: Some(210.0), roughness_factor: 0.98 },
57    Material { name: "N4000-29", er: 4.50, tg: Some(185.0), roughness_factor: 0.98 },
58    Material { name: "N7000-1", er: 3.90, tg: Some(260.0), roughness_factor: 1.0 },
59    Material { name: "Ventec VT-47", er: 4.60, tg: Some(180.0), roughness_factor: 0.98 },
60    Material { name: "Ventec VT-901", er: 4.15, tg: Some(250.0), roughness_factor: 1.0 },
61    Material { name: "Ventec VT-90H", er: 4.15, tg: Some(250.0), roughness_factor: 1.0 },
62    Material { name: "Megtron6", er: 3.40, tg: Some(185.0), roughness_factor: 1.0 },
63    Material { name: "Kappa 438", er: 4.38, tg: Some(280.0), roughness_factor: 1.0 },
64    Material { name: "Kapton", er: 3.40, tg: Some(400.0), roughness_factor: 1.0 },
65    Material { name: "Air", er: 1.00, tg: None, roughness_factor: 1.0 },
66];
67
68/// Look up a material by name (case-insensitive).
69pub fn lookup(name: &str) -> Option<&'static Material> {
70    MATERIALS.iter().find(|m| m.name.eq_ignore_ascii_case(name))
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn material_count() {
79        assert_eq!(MATERIALS.len(), 45);
80    }
81
82    #[test]
83    fn lookup_fr4() {
84        let m = lookup("FR-4 STD").unwrap();
85        assert!((m.er - 4.6).abs() < 1e-10);
86        assert_eq!(m.tg, Some(130.0));
87        assert!((m.roughness_factor - 0.98).abs() < 1e-10);
88    }
89
90    #[test]
91    fn lookup_ro4350() {
92        let m = lookup("RO4350").unwrap();
93        assert!((m.er - 3.66).abs() < 1e-10);
94        assert_eq!(m.tg, Some(280.0));
95        assert!((m.roughness_factor - 1.0).abs() < 1e-10);
96    }
97
98    #[test]
99    fn lookup_kapton() {
100        let m = lookup("Kapton").unwrap();
101        assert!((m.er - 3.40).abs() < 1e-10);
102        assert_eq!(m.tg, Some(400.0));
103    }
104
105    #[test]
106    fn lookup_air() {
107        let m = lookup("Air").unwrap();
108        assert!((m.er - 1.0).abs() < 1e-10);
109        assert_eq!(m.tg, None);
110    }
111
112    #[test]
113    fn lookup_case_insensitive() {
114        assert!(lookup("fr-4 std").is_some());
115        assert!(lookup("AIR").is_some());
116        assert!(lookup("megtron6").is_some());
117    }
118
119    #[test]
120    fn lookup_unknown() {
121        assert!(lookup("unobtanium").is_none());
122    }
123}