feat: implement mass balance validation for Story 7.1

- Added port_mass_flows to Component trait and implements for core components.
- Added System::check_mass_balance and integrated it into the solver.
- Restored connect methods for ExpansionValve, Compressor, and Pipe to fix integration tests.
- Updated Python and C bindings for validation errors.
- Updated sprint status and story documentation.
This commit is contained in:
Sepehr
2026-02-21 23:21:34 +01:00
parent 4440132b0a
commit fa480ed303
55 changed files with 5987 additions and 31 deletions

View File

@@ -222,6 +222,36 @@ impl ExpansionValve<Disconnected> {
pub fn is_effectively_off(&self) -> bool {
is_effectively_off_impl(self.operational_state, self.opening)
}
/// Connects the expansion valve to inlet and outlet ports.
///
/// This consumes the disconnected valve and returns a connected one,
/// transitioning the state at compile time.
pub fn connect(
self,
inlet: Port<Disconnected>,
outlet: Port<Disconnected>,
) -> Result<ExpansionValve<Connected>, ComponentError> {
let (p_in, _) = self
.port_inlet
.connect(inlet)
.map_err(|e| ComponentError::InvalidState(e.to_string()))?;
let (p_out, _) = self
.port_outlet
.connect(outlet)
.map_err(|e| ComponentError::InvalidState(e.to_string()))?;
Ok(ExpansionValve {
port_inlet: p_in,
port_outlet: p_out,
calib: self.calib,
calib_indices: self.calib_indices,
operational_state: self.operational_state,
opening: self.opening,
fluid_id: self.fluid_id,
circuit_id: self.circuit_id,
_state: PhantomData,
})
}
}
/// Phase region at a thermodynamic state point.
@@ -603,6 +633,18 @@ impl Component for ExpansionValve<Connected> {
2
}
fn port_mass_flows(&self, state: &SystemState) -> Result<Vec<entropyk_core::MassFlow>, ComponentError> {
if state.len() < MIN_STATE_DIMENSIONS {
return Err(ComponentError::InvalidStateDimensions {
expected: MIN_STATE_DIMENSIONS,
actual: state.len(),
});
}
let m_in = entropyk_core::MassFlow::from_kg_per_s(state[0]);
let m_out = entropyk_core::MassFlow::from_kg_per_s(-state[1]); // Negative because it's leaving
Ok(vec![m_in, m_out])
}
fn get_ports(&self) -> &[ConnectedPort] {
&[]
}