use super::*;
#[serde_api]
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, SetCumulative)]
#[cfg_attr(feature = "pyo3", pyclass(module = "fastsim", subclass, eq))]
#[non_exhaustive]
#[serde(deny_unknown_fields)]
pub struct FuelStorage {
pub pwr_out_max: si::Power,
pub pwr_ramp_lag: si::Time,
pub energy_capacity: si::Energy,
pub(in super::super) specific_energy: Option<si::SpecificEnergy>,
#[serde(default)]
pub(in super::super) mass: Option<si::Mass>,
}
#[pyo3_api]
impl FuelStorage {
}
impl SerdeAPI for FuelStorage {}
impl Init for FuelStorage {}
impl Mass for FuelStorage {
fn mass(&self) -> anyhow::Result<Option<si::Mass>> {
let derived_mass = self
.derived_mass()
.with_context(|| anyhow!(format_dbg!()))?;
if let (Some(derived_mass), Some(set_mass)) = (derived_mass, self.mass) {
ensure!(
utils::almost_eq_uom(&set_mass, &derived_mass, None),
format!(
"{}",
format_dbg!(utils::almost_eq_uom(&set_mass, &derived_mass, None)),
)
);
}
Ok(self.mass)
}
fn set_mass(
&mut self,
new_mass: Option<si::Mass>,
side_effect: MassSideEffect,
) -> anyhow::Result<()> {
let derived_mass = self
.derived_mass()
.with_context(|| anyhow!(format_dbg!()))?;
if let (Some(derived_mass), Some(new_mass)) = (derived_mass, new_mass) {
if derived_mass != new_mass {
match side_effect {
MassSideEffect::Extensive => {
self.energy_capacity = self.specific_energy.with_context(|| {
format!(
"{}\nExpected `self.specific_energy` to be `Some`.",
format_dbg!()
)
})? * new_mass;
}
MassSideEffect::Intensive => {
self.specific_energy = Some(self.energy_capacity / new_mass);
}
MassSideEffect::None => {
self.specific_energy = None;
}
}
}
} else if new_mass.is_none() {
self.specific_energy = None;
}
self.mass = new_mass;
Ok(())
}
fn derived_mass(&self) -> anyhow::Result<Option<si::Mass>> {
Ok(self
.specific_energy
.map(|specific_energy| self.energy_capacity / specific_energy))
}
fn expunge_mass_fields(&mut self) {
self.mass = None;
self.specific_energy = None;
}
}