Skip to main content

twine_models/support/hx/
capacitance_rate.rs

1use std::ops::Deref;
2
3use crate::support::constraint::{Constrained, ConstraintResult, StrictlyPositive};
4use uom::si::f64::{MassRate, SpecificHeatCapacity, ThermalConductance};
5
6/// Capacitance rate (`m_dot` * `c_p`) of a working fluid in a heat exchanger.
7///
8/// The value must be strictly positive.
9#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
10pub struct CapacitanceRate(Constrained<ThermalConductance, StrictlyPositive>);
11
12impl CapacitanceRate {
13    /// Create a [`CapacitanceRate`] from a scalar value.
14    ///
15    /// # Errors
16    ///
17    /// Returns `Err` if the value is not strictly positive.
18    pub fn new<U>(value: f64) -> ConstraintResult<Self>
19    where
20        U: uom::si::thermal_conductance::Unit + uom::Conversion<f64, T = f64>,
21    {
22        let quantity = ThermalConductance::new::<U>(value);
23        Self::from_quantity(quantity)
24    }
25
26    /// Create a [`CapacitanceRate`] from a quantity with thermal-conductance units.
27    ///
28    /// # Errors
29    ///
30    /// Returns `Err` if the quantity is not strictly positive.
31    pub fn from_quantity(quantity: ThermalConductance) -> ConstraintResult<Self> {
32        Ok(Self(StrictlyPositive::new(quantity)?))
33    }
34
35    /// Create a [`CapacitanceRate`] from a mass rate and specific heat
36    /// capacity.
37    ///
38    /// # Errors
39    ///
40    /// Returns `Err` if either operand is not strictly positive.
41    pub fn from_mass_rate_and_specific_heat(
42        mass_rate: MassRate,
43        specific_heat: SpecificHeatCapacity,
44    ) -> ConstraintResult<Self> {
45        CapacitanceRate::from_quantity(mass_rate * specific_heat)
46    }
47}
48
49impl Deref for CapacitanceRate {
50    type Target = ThermalConductance;
51
52    fn deref(&self) -> &Self::Target {
53        self.0.as_ref()
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use approx::assert_relative_eq;
60    use uom::si::{
61        mass_rate::kilogram_per_second, specific_heat_capacity::joule_per_kilogram_kelvin,
62        thermal_conductance::watt_per_kelvin,
63    };
64
65    use super::*;
66
67    #[test]
68    fn from_mass_rate_and_specific_heat() -> ConstraintResult<()> {
69        let mass_rate = MassRate::new::<kilogram_per_second>(10.);
70        let specific_heat = SpecificHeatCapacity::new::<joule_per_kilogram_kelvin>(4000.);
71
72        let capacitance_rate =
73            CapacitanceRate::from_mass_rate_and_specific_heat(mass_rate, specific_heat)?;
74
75        assert_relative_eq!(capacitance_rate.get::<watt_per_kelvin>(), 40000.);
76        Ok(())
77    }
78}