twine_models/support/hx/
stream.rs1use crate::support::units::TemperatureDifference;
2use uom::si::f64::ThermodynamicTemperature;
3
4use super::{CapacitanceRate, HeatFlow};
5
6#[derive(Debug, Clone, Copy)]
10pub struct StreamInlet {
11 pub(crate) capacitance_rate: CapacitanceRate,
12 pub(crate) temperature: ThermodynamicTemperature,
13}
14
15impl StreamInlet {
16 #[must_use]
18 pub fn new(capacitance_rate: CapacitanceRate, temperature: ThermodynamicTemperature) -> Self {
19 Self {
20 capacitance_rate,
21 temperature,
22 }
23 }
24
25 pub(crate) fn with_heat_flow(self, heat_flow: HeatFlow) -> Stream {
26 Stream::new_from_heat_flow(self.capacitance_rate, self.temperature, heat_flow)
27 }
28}
29
30#[derive(Debug, Clone, Copy, PartialEq)]
32pub struct Stream {
33 pub capacitance_rate: CapacitanceRate,
35 pub inlet_temperature: ThermodynamicTemperature,
37 pub outlet_temperature: ThermodynamicTemperature,
42 pub heat_flow: HeatFlow,
44}
45
46impl Stream {
47 #[must_use]
57 pub fn new_from_heat_flow(
58 capacitance_rate: CapacitanceRate,
59 inlet_temperature: ThermodynamicTemperature,
60 heat_flow: HeatFlow,
61 ) -> Self {
62 Self {
63 capacitance_rate,
64 inlet_temperature,
65 outlet_temperature: match heat_flow {
66 HeatFlow::In(heat_rate) => {
67 inlet_temperature + heat_rate.into_inner() / *capacitance_rate
68 }
69 HeatFlow::Out(heat_rate) => {
70 inlet_temperature - heat_rate.into_inner() / *capacitance_rate
71 }
72 HeatFlow::None => inlet_temperature,
73 },
74 heat_flow,
75 }
76 }
77
78 #[must_use]
97 pub fn new_from_outlet_temperature(
98 capacitance_rate: CapacitanceRate,
99 inlet_temperature: ThermodynamicTemperature,
100 outlet_temperature: ThermodynamicTemperature,
101 ) -> Self {
102 let heat_rate_magnitude =
103 *capacitance_rate * inlet_temperature.minus(outlet_temperature).abs();
104
105 Self {
106 capacitance_rate,
107 inlet_temperature,
108 outlet_temperature,
109 heat_flow: match inlet_temperature
110 .partial_cmp(&outlet_temperature)
111 .expect("temperatures to be comparable")
112 {
113 std::cmp::Ordering::Less => HeatFlow::incoming(heat_rate_magnitude)
114 .expect("heat rate magnitude should always be positive"),
115 std::cmp::Ordering::Equal => HeatFlow::None,
116 std::cmp::Ordering::Greater => HeatFlow::outgoing(heat_rate_magnitude)
117 .expect("heat rate magnitude should always be positive"),
118 },
119 }
120 }
121}
122
123impl From<Stream> for StreamInlet {
124 fn from(stream: Stream) -> Self {
125 Self {
126 capacitance_rate: stream.capacitance_rate,
127 temperature: stream.inlet_temperature,
128 }
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use crate::support::constraint::ConstraintResult;
135 use uom::si::{
136 f64::Power, power::watt, thermal_conductance::watt_per_kelvin,
137 thermodynamic_temperature::kelvin,
138 };
139
140 use super::*;
141
142 #[test]
143 fn stream_inlet_with_heat_flow() -> ConstraintResult<()> {
144 let capacitance_rate = CapacitanceRate::new::<watt_per_kelvin>(10.)?;
145 let inlet_temperature = ThermodynamicTemperature::new::<kelvin>(300.);
146 let heat_rate = Power::new::<watt>(20.);
147
148 let inlet = StreamInlet::new(capacitance_rate, inlet_temperature);
149
150 let no_heat = inlet.with_heat_flow(HeatFlow::None);
151 let incoming = inlet.with_heat_flow(HeatFlow::incoming(heat_rate)?);
152 let outgoing = inlet.with_heat_flow(HeatFlow::outgoing(heat_rate)?);
153
154 assert_eq!(
155 no_heat,
156 Stream {
157 capacitance_rate,
158 inlet_temperature,
159 outlet_temperature: inlet_temperature,
160 heat_flow: HeatFlow::None
161 }
162 );
163 assert_eq!(
164 incoming,
165 Stream {
166 capacitance_rate,
167 inlet_temperature,
168 outlet_temperature: ThermodynamicTemperature::new::<kelvin>(302.),
169 heat_flow: HeatFlow::incoming(heat_rate)?
170 }
171 );
172 assert_eq!(
173 outgoing,
174 Stream {
175 capacitance_rate,
176 inlet_temperature,
177 outlet_temperature: ThermodynamicTemperature::new::<kelvin>(298.),
178 heat_flow: HeatFlow::outgoing(heat_rate)?
179 }
180 );
181
182 Ok(())
183 }
184
185 #[test]
186 fn stream_new_from_heat_rate() -> ConstraintResult<()> {
187 let capacitance_rate = CapacitanceRate::new::<watt_per_kelvin>(10.)?;
188 let inlet_temperature = ThermodynamicTemperature::new::<kelvin>(300.);
189 let heat_flow = HeatFlow::incoming(Power::new::<watt>(20.))?;
190
191 let stream = Stream::new_from_heat_flow(capacitance_rate, inlet_temperature, heat_flow);
192
193 assert_eq!(
194 stream,
195 Stream {
196 capacitance_rate,
197 inlet_temperature,
198 outlet_temperature: ThermodynamicTemperature::new::<kelvin>(302.),
199 heat_flow
200 }
201 );
202
203 Ok(())
204 }
205
206 #[test]
207 fn stream_new_from_outlet_temperature() -> ConstraintResult<()> {
208 let capacitance_rate = CapacitanceRate::new::<watt_per_kelvin>(10.)?;
209 let inlet_temperature = ThermodynamicTemperature::new::<kelvin>(300.);
210 let outlet_temperature = ThermodynamicTemperature::new::<kelvin>(302.);
211
212 let stream = Stream::new_from_outlet_temperature(
213 capacitance_rate,
214 inlet_temperature,
215 outlet_temperature,
216 );
217
218 assert_eq!(
219 stream,
220 Stream {
221 capacitance_rate,
222 inlet_temperature,
223 outlet_temperature,
224 heat_flow: HeatFlow::incoming(Power::new::<watt>(20.))?
225 }
226 );
227
228 Ok(())
229 }
230}