substrate/simulation/
options.rs

1//! Standard APIs for setting simulator options.
2
3use crate::simulation::{SimulationContext, Simulator};
4use rust_decimal::Decimal;
5use std::ops::{Deref, DerefMut};
6
7/// An option for a simulator.
8pub trait SimOption<S: Simulator> {
9    /// Modifies the simulator's options to enable this option.
10    fn set_option(self, opts: &mut <S as Simulator>::Options, ctx: &SimulationContext<S>);
11}
12
13/// A temperature to use in simulation.
14pub struct Temperature(Decimal);
15
16impl Deref for Temperature {
17    type Target = Decimal;
18
19    fn deref(&self) -> &Self::Target {
20        &self.0
21    }
22}
23
24impl DerefMut for Temperature {
25    fn deref_mut(&mut self) -> &mut Self::Target {
26        &mut self.0
27    }
28}
29
30impl From<Decimal> for Temperature {
31    fn from(value: Decimal) -> Self {
32        Self(value)
33    }
34}
35
36/// Initial conditions.
37pub mod ic {
38    use crate::simulation::{SimulationContext, Simulator};
39    use crate::types::schematic::{NestedNode, NestedTerminal, NodePath, TerminalPath};
40    use rust_decimal::Decimal;
41    use std::ops::{Deref, DerefMut};
42    use substrate::simulation::options::SimOption;
43    use type_dispatch::impl_dispatch;
44
45    /// An initial condition.
46    pub struct InitialCondition<K, V> {
47        /// A path referring to the item whose initial condition needs to be set.
48        pub path: K,
49        /// An initial condition that should be set at the above path.
50        pub value: V,
51    }
52
53    /// An initial voltage value.
54    pub struct Voltage(pub Decimal);
55
56    impl Deref for Voltage {
57        type Target = Decimal;
58
59        fn deref(&self) -> &Self::Target {
60            &self.0
61        }
62    }
63
64    impl DerefMut for Voltage {
65        fn deref_mut(&mut self) -> &mut Self::Target {
66            &mut self.0
67        }
68    }
69
70    #[impl_dispatch({NestedNode; &NestedNode})]
71    impl<N, V, S: Simulator> SimOption<S> for InitialCondition<N, V>
72    where
73        InitialCondition<NodePath, V>: SimOption<S>,
74    {
75        fn set_option(self, opts: &mut <S as Simulator>::Options, ctx: &SimulationContext<S>) {
76            InitialCondition {
77                path: self.path.path(),
78                value: self.value,
79            }
80            .set_option(opts, ctx)
81        }
82    }
83
84    #[impl_dispatch({TerminalPath; &TerminalPath})]
85    impl<N, V, S: Simulator> SimOption<S> for InitialCondition<N, V>
86    where
87        for<'a> InitialCondition<&'a NodePath, V>: SimOption<S>,
88    {
89        fn set_option(self, opts: &mut <S as Simulator>::Options, ctx: &SimulationContext<S>) {
90            InitialCondition {
91                path: self.path.as_ref(),
92                value: self.value,
93            }
94            .set_option(opts, ctx)
95        }
96    }
97
98    #[impl_dispatch({NestedTerminal; &NestedTerminal})]
99    impl<T, V, S: Simulator> SimOption<S> for InitialCondition<T, V>
100    where
101        InitialCondition<TerminalPath, V>: SimOption<S>,
102    {
103        fn set_option(self, opts: &mut <S as Simulator>::Options, ctx: &SimulationContext<S>) {
104            InitialCondition {
105                path: self.path.path(),
106                value: self.value,
107            }
108            .set_option(opts, ctx)
109        }
110    }
111}