1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
use RefCell;
use ;
use crateMatrix;
use crate;
use crateGenericNode;
/// The function signature for a `neapolitan`-compatible element constructor function.
///
/// # Design Philosophy:
/// Because Rust does not support inheritance of shared data between types,
/// extending `neapolitan` requires that authors write a constructor *function* rather than a method that
/// packs the relevant data into a `GenericElement` for use by the solver engine. This
/// design pattern ensures that when an user needs to add a new variety of element for a model, it has all the
/// data required by the solver engine to properly solve the model.
///
/// # Argument Types:
/// The type `T` is left as a parameter to allow authors to control what type of data is
/// used in deriving the `gain` value as well as additional metadata used in flux calculations. For example, in
/// steady-state DC circuitry, `T` is simply `f64` to represent a real value for the voltage,
/// resistance, or current of the element being created. In AC circuitry problems,
/// however, this type would be `(f64, f64)` to represent the real and imaginary components of
/// current at that location.
///
/// Constructor functions operate on `Weak<RefCell<GenericNode>>` smart pointers in order to
/// properly create the network structure used to model problems. These node references must
/// be passed on to the created element, but may be operated on prior to element creation.
/// E.g. `voltage_source` sets a driven node's voltage to the driving node's potential +/- the
/// potential difference specified prior to connecting the element to the network.
pub type ElementConstructor = fn ;
/// The function signature used to calculate flux between nodes.
///
/// # Design Philosophy
/// Flux calculation functions are the other function that must be defined in order to extend
/// `neapolitan`. They are implemented as a single function pointer rather than a trait object
/// for simplicity. This ensures that implementors do not have to define a type that does not
/// cleanly mimic a `GenericElement` just to implement a common method.
///
/// These functions get called by the `GenericElement::get_flux` method. They must
/// return a `Matrix<f64>` containing the flux value that the element should have based on its
/// nodal potentials and `gain` value. Similarly to `ElementConstructor<T>`, this function type
/// must work with smart pointers to `GenericNode`s, but this time must work with `Rc<RefCell<GenericNode>>`
/// instead of `Weak<RefCell<GenericNode>>` as the type. They additionally take a `&Matrix<f64>`
/// argument that will be equivalent to the element's `gain` value and a `bool` that indicates
/// the directionality of some quantity. This value is fairly arbitrary and it is up to the
/// implementor to choose its meaning.
///
/// # Note on Runtime Borrowing:
/// Upon being called, these functions may have more or less whatever side effects they need to in
/// order to make their calculations work. One key thing to keep in mind however, is that elements
/// that require calculating a node's flux discrepancy value in order to determine a flux must **not**
/// mutably borrow that node or any other node used in the flux discrepancy calculation to avoid
/// raising an `AlreadyMutablyBorrowed` error.
pub type FluxCalculation = fn ;
/// A struct representing an element in a nodal analysis problem.
///
/// # Concept:
/// Elements are conductors for some "flux" value between nodes in a
/// nodal analysis problem. In DC circuits models, resistors, voltage
/// sources, and current sources are examples of elements as they
/// allow current (i.e. flux) to "travel" between two nodes. The way in
/// which this flux value is calculated may vary wildly between elements,
/// but **must** operate only on knowing which nodes they connect, their
/// own gain value (e.g. resistance, voltage, and current, respectively in this case),
/// and which node's potential they drive, if they drive one at all.