sc_neurocore_engine/neurons/rate/
astrocyte_model.rs1#[derive(Clone, Debug)]
11pub struct AstrocyteModel {
12 pub ca: f64,
13 pub h: f64,
14 pub ip3: f64,
15 pub v_er: f64,
16 pub k_er: f64,
17 pub v_serca: f64,
18 pub d1: f64,
19 pub d2: f64,
20 pub d3: f64,
21 pub d5: f64,
22 pub c0: f64,
23 pub c1: f64,
24 pub dt: f64,
25}
26
27impl AstrocyteModel {
28 pub fn new() -> Self {
29 Self {
30 ca: 0.05,
31 h: 0.8,
32 ip3: 0.5,
33 v_er: 0.9,
34 k_er: 0.15,
35 v_serca: 0.4,
36 d1: 0.13,
37 d2: 1.049,
38 d3: 0.9434,
39 d5: 0.08234,
40 c0: 2.0,
41 c1: 0.185,
42 dt: 0.01,
43 }
44 }
45 pub fn step(&mut self, current: f64) -> f64 {
46 let ca_er = (self.c0 - self.ca) / self.c1;
47 let m_inf = self.ip3 / (self.ip3 + self.d1);
48 let n_inf = self.ca / (self.ca + self.d5);
49 let j_chan = self.v_er * (m_inf * n_inf * self.h).powi(3) * (ca_er - self.ca);
50 let j_leak = self.k_er * (ca_er - self.ca);
51 let j_pump = self.v_serca * self.ca.powi(2) / (self.ca.powi(2) + self.k_er.powi(2));
52 let q2 = self.d2 * (self.ip3 + self.d1) / (self.ip3 + self.d3);
53 let h_inf = q2 / (q2 + self.ca);
54 let tau_h = 1.0 / (0.2 * (q2 + self.ca));
55 self.ca += (j_chan + j_leak - j_pump + current) * self.dt;
56 self.ca = self.ca.max(0.0);
57 self.h += (h_inf - self.h) / tau_h * self.dt;
58 self.ca
59 }
60 pub fn reset(&mut self) {
61 self.ca = 0.05;
62 self.h = 0.8;
63 self.ip3 = 0.5;
64 }
65}
66impl Default for AstrocyteModel {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn astrocyte_ca() {
78 let mut n = AstrocyteModel::new();
79 let mut max_ca = 0.0_f64;
80 for _ in 0..5000 {
81 let c = n.step(0.1);
82 max_ca = max_ca.max(c);
83 }
84 assert!(max_ca > 0.05);
85 }
86
87 #[test]
88 fn astrocyte_reset() {
89 let mut n = AstrocyteModel::new();
90 for _ in 0..1000 {
91 n.step(0.1);
92 }
93 n.reset();
94 assert!((n.ca - 0.05).abs() < 1e-10);
95 }
96
97 #[test]
98 fn astrocyte_nan_no_panic() {
99 AstrocyteModel::new().step(f64::NAN);
100 }
101
102 #[test]
103 fn astrocyte_ca_nonneg() {
104 let mut n = AstrocyteModel::new();
105 for _ in 0..5000 {
106 n.step(0.1);
107 }
108 assert!(n.ca >= 0.0, "Ca²⁺ must be non-negative");
109 }
110}