use thiserror::Error;
use uom::si::{
energy::joule,
f64::{Energy, Mass, MassDensity, Pressure, SpecificHeatCapacity, ThermodynamicTemperature},
mass::kilogram,
mass_density::kilogram_per_cubic_meter,
specific_heat_capacity::joule_per_kilogram_kelvin,
thermodynamic_temperature::kelvin,
};
use crate::support::{
thermo::{
PropertyError, State,
capability::{HasEnthalpy, StateFrom, ThermoModel},
model::perfect_gas::{PerfectGas, PerfectGasFluid, PerfectGasParameters},
},
units::{SpecificEnthalpy, SpecificEntropy, SpecificGasConstant},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) struct MockGas;
impl PerfectGasFluid for MockGas {
fn parameters() -> PerfectGasParameters {
PerfectGasParameters::new(
SpecificGasConstant::new::<joule_per_kilogram_kelvin>(2000.0 / 7.0),
SpecificHeatCapacity::new::<joule_per_kilogram_kelvin>(1000.0),
)
}
}
pub(crate) fn mock_gas_model() -> PerfectGas<MockGas> {
PerfectGas::<MockGas>::new().expect("mock gas parameters must be physically valid")
}
pub(crate) fn enth_si(value: f64) -> SpecificEnthalpy {
Energy::new::<joule>(value) / Mass::new::<kilogram>(1.0)
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) enum FakeMode {
FailStateFromPressureEntropy,
FailStateFromPressureEnthalpy,
FailEnthalpy,
FixedEnthalpy(SpecificEnthalpy),
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct FakeThermo {
pub(crate) mode: FakeMode,
}
#[derive(Debug, Error)]
#[error("fake state_from failure")]
pub(crate) struct FakeStateFromError;
fn fake_state() -> State<MockGas> {
State {
temperature: ThermodynamicTemperature::new::<kelvin>(1.0),
density: MassDensity::new::<kilogram_per_cubic_meter>(1.0),
fluid: MockGas,
}
}
impl ThermoModel for FakeThermo {
type Fluid = MockGas;
}
impl HasEnthalpy for FakeThermo {
fn enthalpy(&self, _state: &State<MockGas>) -> Result<SpecificEnthalpy, PropertyError> {
match self.mode {
FakeMode::FailEnthalpy => Err(PropertyError::Calculation {
context: "fake".into(),
}),
FakeMode::FixedEnthalpy(value) => Ok(value),
_ => Ok(enth_si(1.0)),
}
}
}
impl StateFrom<(MockGas, Pressure, SpecificEntropy)> for FakeThermo {
type Error = FakeStateFromError;
fn state_from(
&self,
(_fluid, _p, _s): (MockGas, Pressure, SpecificEntropy),
) -> Result<State<MockGas>, Self::Error> {
match self.mode {
FakeMode::FailStateFromPressureEntropy => Err(FakeStateFromError),
_ => Ok(fake_state()),
}
}
}
impl StateFrom<(MockGas, Pressure, SpecificEnthalpy)> for FakeThermo {
type Error = FakeStateFromError;
fn state_from(
&self,
(_fluid, _p, _h): (MockGas, Pressure, SpecificEnthalpy),
) -> Result<State<MockGas>, Self::Error> {
match self.mode {
FakeMode::FailStateFromPressureEnthalpy => Err(FakeStateFromError),
_ => Ok(fake_state()),
}
}
}