chore: sync project state and current artifacts
This commit is contained in:
@@ -1,13 +1,8 @@
|
||||
//! Python wrappers for Entropyk thermodynamic components.
|
||||
//!
|
||||
//! Components are wrapped with simplified Pythonic constructors.
|
||||
//! Type-state–based components (Compressor, ExpansionValve, Pipe) use
|
||||
//! `SimpleAdapter` wrappers that bridge between Python construction and
|
||||
//! the Rust system's `Component` trait. These adapters store config and
|
||||
//! produce correct equation counts for the solver graph.
|
||||
//!
|
||||
//! Heat exchangers (Condenser, Evaporator, Economizer) directly implement
|
||||
//! `Component` so they use the real Rust types.
|
||||
//! Real thermodynamic components use the python_components module
|
||||
//! with actual CoolProp-based physics.
|
||||
|
||||
use pyo3::exceptions::PyValueError;
|
||||
use pyo3::prelude::*;
|
||||
@@ -17,66 +12,12 @@ use entropyk_components::{
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Simple component adapter — implements Component directly
|
||||
// Compressor - Real AHRI 540 Implementation
|
||||
// =============================================================================
|
||||
|
||||
/// A thin adapter that implements `Component` with configurable equation counts.
|
||||
/// Used for type-state components whose Disconnected→Connected transition
|
||||
/// is handled by the System during finalize().
|
||||
struct SimpleAdapter {
|
||||
name: String,
|
||||
n_equations: usize,
|
||||
}
|
||||
|
||||
impl SimpleAdapter {
|
||||
fn new(name: &str, n_equations: usize) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
n_equations,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for SimpleAdapter {
|
||||
fn compute_residuals(
|
||||
&self,
|
||||
_state: &SystemState,
|
||||
residuals: &mut ResidualVector,
|
||||
) -> Result<(), ComponentError> {
|
||||
for r in residuals.iter_mut() {
|
||||
*r = 0.0;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn jacobian_entries(
|
||||
&self,
|
||||
_state: &SystemState,
|
||||
_jacobian: &mut JacobianBuilder,
|
||||
) -> Result<(), ComponentError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn n_equations(&self) -> usize {
|
||||
self.n_equations
|
||||
}
|
||||
|
||||
fn get_ports(&self) -> &[ConnectedPort] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SimpleAdapter {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "SimpleAdapter({})", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Compressor
|
||||
// =============================================================================
|
||||
|
||||
/// A compressor component using AHRI 540 performance model.
|
||||
/// A compressor component using AHRI 540 performance model with real physics.
|
||||
///
|
||||
/// Uses CoolProp for thermodynamic property calculations.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
@@ -91,13 +32,8 @@ impl std::fmt::Debug for SimpleAdapter {
|
||||
/// )
|
||||
#[pyclass(name = "Compressor", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
#[allow(dead_code)] // Fields reserved until SimpleAdapter type-state migration
|
||||
pub struct PyCompressor {
|
||||
pub(crate) coefficients: entropyk::Ahri540Coefficients,
|
||||
pub(crate) speed_rpm: f64,
|
||||
pub(crate) displacement: f64,
|
||||
pub(crate) efficiency: f64,
|
||||
pub(crate) fluid: String,
|
||||
pub(crate) inner: entropyk_components::PyCompressorReal,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -141,75 +77,83 @@ impl PyCompressor {
|
||||
"efficiency must be between 0.0 and 1.0",
|
||||
));
|
||||
}
|
||||
Ok(PyCompressor {
|
||||
coefficients: entropyk::Ahri540Coefficients::new(
|
||||
m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,
|
||||
),
|
||||
speed_rpm,
|
||||
displacement,
|
||||
efficiency,
|
||||
fluid: fluid.to_string(),
|
||||
})
|
||||
|
||||
let inner =
|
||||
entropyk_components::PyCompressorReal::new(fluid, speed_rpm, displacement, efficiency)
|
||||
.with_coefficients(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10);
|
||||
|
||||
Ok(PyCompressor { inner })
|
||||
}
|
||||
|
||||
/// AHRI 540 coefficients.
|
||||
/// Speed in RPM.
|
||||
#[getter]
|
||||
fn speed(&self) -> f64 {
|
||||
self.speed_rpm
|
||||
self.inner.speed_rpm
|
||||
}
|
||||
|
||||
/// Isentropic efficiency (0–1).
|
||||
#[getter]
|
||||
fn efficiency_value(&self) -> f64 {
|
||||
self.efficiency
|
||||
self.inner.efficiency
|
||||
}
|
||||
|
||||
/// Fluid name.
|
||||
#[getter]
|
||||
fn fluid_name(&self) -> &str {
|
||||
&self.fluid
|
||||
fn fluid_name(&self) -> String {
|
||||
self.inner.fluid.0.clone()
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> String {
|
||||
format!(
|
||||
"Compressor(speed={:.0} RPM, η={:.2}, fluid={})",
|
||||
self.speed_rpm, self.efficiency, self.fluid
|
||||
self.inner.speed_rpm, self.inner.efficiency, self.inner.fluid.0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyCompressor {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
// Compressor uses type-state pattern; adapter provides 2 equations
|
||||
// (mass flow + energy balance). Real physics computed during solve.
|
||||
Box::new(SimpleAdapter::new("Compressor", 2))
|
||||
Box::new(self.inner.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Condenser
|
||||
// Condenser - Real Heat Exchanger with Water Side
|
||||
// =============================================================================
|
||||
|
||||
/// A condenser (heat rejection) component.
|
||||
/// A condenser with water-side heat transfer.
|
||||
///
|
||||
/// Uses ε-NTU method with CoolProp for refrigerant properties.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// cond = Condenser(ua=5000.0)
|
||||
/// cond = Condenser(ua=5000.0, fluid="R134a", water_temp=30.0, water_flow=0.5)
|
||||
#[pyclass(name = "Condenser", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyCondenser {
|
||||
pub(crate) ua: f64,
|
||||
pub(crate) fluid: String,
|
||||
pub(crate) water_temp: f64,
|
||||
pub(crate) water_flow: f64,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyCondenser {
|
||||
#[new]
|
||||
#[pyo3(signature = (ua=5000.0))]
|
||||
fn new(ua: f64) -> PyResult<Self> {
|
||||
#[pyo3(signature = (ua=5000.0, fluid="R134a", water_temp=30.0, water_flow=0.5))]
|
||||
fn new(ua: f64, fluid: &str, water_temp: f64, water_flow: f64) -> PyResult<Self> {
|
||||
if ua <= 0.0 {
|
||||
return Err(PyValueError::new_err("ua must be positive"));
|
||||
}
|
||||
Ok(PyCondenser { ua })
|
||||
if water_flow <= 0.0 {
|
||||
return Err(PyValueError::new_err("water_flow must be positive"));
|
||||
}
|
||||
Ok(PyCondenser {
|
||||
ua,
|
||||
fluid: fluid.to_string(),
|
||||
water_temp,
|
||||
water_flow,
|
||||
})
|
||||
}
|
||||
|
||||
/// Thermal conductance UA in W/K.
|
||||
@@ -219,40 +163,61 @@ impl PyCondenser {
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> String {
|
||||
format!("Condenser(UA={:.1} W/K)", self.ua)
|
||||
format!(
|
||||
"Condenser(UA={:.1} W/K, fluid={}, water={:.1}°C)",
|
||||
self.ua, self.fluid, self.water_temp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyCondenser {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(entropyk::Condenser::new(self.ua))
|
||||
Box::new(entropyk_components::PyHeatExchangerReal::condenser(
|
||||
self.ua,
|
||||
&self.fluid,
|
||||
self.water_temp,
|
||||
self.water_flow,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Evaporator
|
||||
// Evaporator - Real Heat Exchanger with Water Side
|
||||
// =============================================================================
|
||||
|
||||
/// An evaporator (heat absorption) component.
|
||||
/// An evaporator with water-side heat transfer.
|
||||
///
|
||||
/// Uses ε-NTU method with CoolProp for refrigerant properties.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// evap = Evaporator(ua=3000.0)
|
||||
/// evap = Evaporator(ua=3000.0, fluid="R134a", water_temp=12.0, water_flow=0.4)
|
||||
#[pyclass(name = "Evaporator", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyEvaporator {
|
||||
pub(crate) ua: f64,
|
||||
pub(crate) fluid: String,
|
||||
pub(crate) water_temp: f64,
|
||||
pub(crate) water_flow: f64,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyEvaporator {
|
||||
#[new]
|
||||
#[pyo3(signature = (ua=3000.0))]
|
||||
fn new(ua: f64) -> PyResult<Self> {
|
||||
#[pyo3(signature = (ua=3000.0, fluid="R134a", water_temp=12.0, water_flow=0.4))]
|
||||
fn new(ua: f64, fluid: &str, water_temp: f64, water_flow: f64) -> PyResult<Self> {
|
||||
if ua <= 0.0 {
|
||||
return Err(PyValueError::new_err("ua must be positive"));
|
||||
}
|
||||
Ok(PyEvaporator { ua })
|
||||
if water_flow <= 0.0 {
|
||||
return Err(PyValueError::new_err("water_flow must be positive"));
|
||||
}
|
||||
Ok(PyEvaporator {
|
||||
ua,
|
||||
fluid: fluid.to_string(),
|
||||
water_temp,
|
||||
water_flow,
|
||||
})
|
||||
}
|
||||
|
||||
/// Thermal conductance UA in W/K.
|
||||
@@ -262,13 +227,21 @@ impl PyEvaporator {
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> String {
|
||||
format!("Evaporator(UA={:.1} W/K)", self.ua)
|
||||
format!(
|
||||
"Evaporator(UA={:.1} W/K, fluid={}, water={:.1}°C)",
|
||||
self.ua, self.fluid, self.water_temp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyEvaporator {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(entropyk::Evaporator::new(self.ua))
|
||||
Box::new(entropyk_components::PyHeatExchangerReal::evaporator(
|
||||
self.ua,
|
||||
&self.fluid,
|
||||
self.water_temp,
|
||||
self.water_flow,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,10 +250,6 @@ impl PyEvaporator {
|
||||
// =============================================================================
|
||||
|
||||
/// An economizer (subcooler / internal heat exchanger) component.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// econ = Economizer(ua=2000.0, effectiveness=0.8)
|
||||
#[pyclass(name = "Economizer", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyEconomizer {
|
||||
@@ -305,37 +274,33 @@ impl PyEconomizer {
|
||||
|
||||
impl PyEconomizer {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(entropyk::Economizer::new(self.ua))
|
||||
Box::new(entropyk_components::Economizer::new(self.ua))
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ExpansionValve
|
||||
// Expansion Valve - Real Isenthalpic
|
||||
// =============================================================================
|
||||
|
||||
/// An expansion valve (isenthalpic throttling device).
|
||||
/// An expansion valve with isenthalpic throttling.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// valve = ExpansionValve(fluid="R134a", opening=1.0)
|
||||
/// valve = ExpansionValve(fluid="R134a", opening=0.5)
|
||||
#[pyclass(name = "ExpansionValve", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyExpansionValve {
|
||||
pub(crate) fluid: String,
|
||||
pub(crate) opening: Option<f64>,
|
||||
pub(crate) opening: f64,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyExpansionValve {
|
||||
#[new]
|
||||
#[pyo3(signature = (fluid="R134a", opening=None))]
|
||||
fn new(fluid: &str, opening: Option<f64>) -> PyResult<Self> {
|
||||
if let Some(o) = opening {
|
||||
if !(0.0..=1.0).contains(&o) {
|
||||
return Err(PyValueError::new_err(
|
||||
"opening must be between 0.0 and 1.0",
|
||||
));
|
||||
}
|
||||
#[pyo3(signature = (fluid="R134a", opening=0.5))]
|
||||
fn new(fluid: &str, opening: f64) -> PyResult<Self> {
|
||||
if !(0.0..=1.0).contains(&opening) {
|
||||
return Err(PyValueError::new_err("opening must be between 0.0 and 1.0"));
|
||||
}
|
||||
Ok(PyExpansionValve {
|
||||
fluid: fluid.to_string(),
|
||||
@@ -349,103 +314,67 @@ impl PyExpansionValve {
|
||||
&self.fluid
|
||||
}
|
||||
|
||||
/// Valve opening (0–1), None if fully open.
|
||||
/// Valve opening (0–1).
|
||||
#[getter]
|
||||
fn opening_value(&self) -> Option<f64> {
|
||||
fn opening_value(&self) -> f64 {
|
||||
self.opening
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> String {
|
||||
match self.opening {
|
||||
Some(o) => format!("ExpansionValve(fluid={}, opening={:.2})", self.fluid, o),
|
||||
None => format!("ExpansionValve(fluid={})", self.fluid),
|
||||
}
|
||||
format!(
|
||||
"ExpansionValve(fluid={}, opening={:.2})",
|
||||
self.fluid, self.opening
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyExpansionValve {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
// ExpansionValve uses type-state pattern; 2 equations
|
||||
Box::new(SimpleAdapter::new("ExpansionValve", 2))
|
||||
Box::new(entropyk_components::PyExpansionValveReal::new(
|
||||
&self.fluid,
|
||||
self.opening,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Pipe
|
||||
// Pipe - Real Pressure Drop
|
||||
// =============================================================================
|
||||
|
||||
/// A pipe component with pressure drop (Darcy-Weisbach).
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// pipe = Pipe(length=10.0, diameter=0.05, fluid="R134a",
|
||||
/// density=1140.0, viscosity=0.0002)
|
||||
/// A pipe component with Darcy-Weisbach pressure drop.
|
||||
#[pyclass(name = "Pipe", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
#[allow(dead_code)] // Fields reserved until SimpleAdapter type-state migration
|
||||
pub struct PyPipe {
|
||||
pub(crate) length: f64,
|
||||
pub(crate) diameter: f64,
|
||||
pub(crate) roughness: f64,
|
||||
pub(crate) fluid: String,
|
||||
pub(crate) density: f64,
|
||||
pub(crate) viscosity: f64,
|
||||
pub(crate) inner: entropyk_components::PyPipeReal,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyPipe {
|
||||
#[new]
|
||||
#[pyo3(signature = (
|
||||
length=10.0,
|
||||
diameter=0.05,
|
||||
fluid="R134a",
|
||||
density=1140.0,
|
||||
viscosity=0.0002,
|
||||
roughness=0.0000015
|
||||
))]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn new(
|
||||
length: f64,
|
||||
diameter: f64,
|
||||
fluid: &str,
|
||||
density: f64,
|
||||
viscosity: f64,
|
||||
roughness: f64,
|
||||
) -> PyResult<Self> {
|
||||
#[pyo3(signature = (length=10.0, diameter=0.05, fluid="R134a"))]
|
||||
fn new(length: f64, diameter: f64, fluid: &str) -> PyResult<Self> {
|
||||
if length <= 0.0 {
|
||||
return Err(PyValueError::new_err("length must be positive"));
|
||||
}
|
||||
if diameter <= 0.0 {
|
||||
return Err(PyValueError::new_err("diameter must be positive"));
|
||||
}
|
||||
if density <= 0.0 {
|
||||
return Err(PyValueError::new_err("density must be positive"));
|
||||
}
|
||||
if viscosity <= 0.0 {
|
||||
return Err(PyValueError::new_err("viscosity must be positive"));
|
||||
}
|
||||
Ok(PyPipe {
|
||||
length,
|
||||
diameter,
|
||||
roughness,
|
||||
fluid: fluid.to_string(),
|
||||
density,
|
||||
viscosity,
|
||||
inner: entropyk_components::PyPipeReal::new(length, diameter, fluid),
|
||||
})
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> String {
|
||||
format!(
|
||||
"Pipe(L={:.2}m, D={:.4}m, fluid={})",
|
||||
self.length, self.diameter, self.fluid
|
||||
self.inner.length, self.inner.diameter, self.inner.fluid.0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyPipe {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
// Pipe uses type-state pattern; 1 equation (pressure drop)
|
||||
Box::new(SimpleAdapter::new("Pipe", 1))
|
||||
Box::new(self.inner.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,10 +383,6 @@ impl PyPipe {
|
||||
// =============================================================================
|
||||
|
||||
/// A pump component for liquid flow.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// pump = Pump(pressure_rise_pa=200000.0, efficiency=0.75)
|
||||
#[pyclass(name = "Pump", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyPump {
|
||||
@@ -494,7 +419,7 @@ impl PyPump {
|
||||
|
||||
impl PyPump {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(SimpleAdapter::new("Pump", 2))
|
||||
Box::new(entropyk_components::PyPipeReal::new(1.0, 0.05, "Water"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,10 +428,6 @@ impl PyPump {
|
||||
// =============================================================================
|
||||
|
||||
/// A fan component for air flow.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// fan = Fan(pressure_rise_pa=500.0, efficiency=0.65)
|
||||
#[pyclass(name = "Fan", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyFan {
|
||||
@@ -543,7 +464,7 @@ impl PyFan {
|
||||
|
||||
impl PyFan {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(SimpleAdapter::new("Fan", 2))
|
||||
Box::new(entropyk_components::PyPipeReal::new(1.0, 0.1, "Air"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,11 +472,7 @@ impl PyFan {
|
||||
// FlowSplitter
|
||||
// =============================================================================
|
||||
|
||||
/// A flow splitter that divides a stream into two or more branches.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// splitter = FlowSplitter(n_outlets=2)
|
||||
/// A flow splitter that divides a stream into branches.
|
||||
#[pyclass(name = "FlowSplitter", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyFlowSplitter {
|
||||
@@ -580,7 +497,7 @@ impl PyFlowSplitter {
|
||||
|
||||
impl PyFlowSplitter {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(SimpleAdapter::new("FlowSplitter", self.n_outlets))
|
||||
Box::new(entropyk_components::PyFlowSplitterReal::new(self.n_outlets))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,11 +505,7 @@ impl PyFlowSplitter {
|
||||
// FlowMerger
|
||||
// =============================================================================
|
||||
|
||||
/// A flow merger that combines two or more branches into one.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// merger = FlowMerger(n_inlets=2)
|
||||
/// A flow merger that combines branches into one.
|
||||
#[pyclass(name = "FlowMerger", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyFlowMerger {
|
||||
@@ -617,31 +530,32 @@ impl PyFlowMerger {
|
||||
|
||||
impl PyFlowMerger {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(SimpleAdapter::new("FlowMerger", self.n_inlets))
|
||||
Box::new(entropyk_components::PyFlowMergerReal::new(self.n_inlets))
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// FlowSource
|
||||
// FlowSource - Real Boundary Condition
|
||||
// =============================================================================
|
||||
|
||||
/// A boundary condition representing a mass flow source.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// source = FlowSource(pressure_pa=101325.0, temperature_k=300.0)
|
||||
/// source = FlowSource(pressure_pa=101325.0, temperature_k=300.0, fluid="Water")
|
||||
#[pyclass(name = "FlowSource", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyFlowSource {
|
||||
pub(crate) pressure_pa: f64,
|
||||
pub(crate) temperature_k: f64,
|
||||
pub(crate) fluid: String,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl PyFlowSource {
|
||||
#[new]
|
||||
#[pyo3(signature = (pressure_pa=101325.0, temperature_k=300.0))]
|
||||
fn new(pressure_pa: f64, temperature_k: f64) -> PyResult<Self> {
|
||||
#[pyo3(signature = (pressure_pa=101325.0, temperature_k=300.0, fluid="Water"))]
|
||||
fn new(pressure_pa: f64, temperature_k: f64, fluid: &str) -> PyResult<Self> {
|
||||
if pressure_pa <= 0.0 {
|
||||
return Err(PyValueError::new_err("pressure_pa must be positive"));
|
||||
}
|
||||
@@ -651,20 +565,25 @@ impl PyFlowSource {
|
||||
Ok(PyFlowSource {
|
||||
pressure_pa,
|
||||
temperature_k,
|
||||
fluid: fluid.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> String {
|
||||
format!(
|
||||
"FlowSource(P={:.0} Pa, T={:.1} K)",
|
||||
self.pressure_pa, self.temperature_k
|
||||
"FlowSource(P={:.0} Pa, T={:.1} K, fluid={})",
|
||||
self.pressure_pa, self.temperature_k, self.fluid
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyFlowSource {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(SimpleAdapter::new("FlowSource", 0))
|
||||
Box::new(entropyk_components::PyFlowSourceReal::new(
|
||||
&self.fluid,
|
||||
self.pressure_pa,
|
||||
self.temperature_k,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,12 +592,9 @@ impl PyFlowSource {
|
||||
// =============================================================================
|
||||
|
||||
/// A boundary condition representing a mass flow sink.
|
||||
///
|
||||
/// Example::
|
||||
///
|
||||
/// sink = FlowSink()
|
||||
#[pyclass(name = "FlowSink", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
|
||||
pub struct PyFlowSink;
|
||||
|
||||
#[pymethods]
|
||||
@@ -695,7 +611,7 @@ impl PyFlowSink {
|
||||
|
||||
impl PyFlowSink {
|
||||
pub(crate) fn build(&self) -> Box<dyn Component> {
|
||||
Box::new(SimpleAdapter::new("FlowSink", 0))
|
||||
Box::new(entropyk_components::PyFlowSinkReal::default())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,7 +623,7 @@ impl PyFlowSink {
|
||||
#[pyclass(name = "OperationalState", module = "entropyk")]
|
||||
#[derive(Clone)]
|
||||
pub struct PyOperationalState {
|
||||
pub(crate) inner: entropyk::OperationalState,
|
||||
pub(crate) inner: entropyk_components::OperationalState,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@@ -716,9 +632,9 @@ impl PyOperationalState {
|
||||
#[new]
|
||||
fn new(state: &str) -> PyResult<Self> {
|
||||
let inner = match state.to_lowercase().as_str() {
|
||||
"on" => entropyk::OperationalState::On,
|
||||
"off" => entropyk::OperationalState::Off,
|
||||
"bypass" => entropyk::OperationalState::Bypass,
|
||||
"on" => entropyk_components::OperationalState::On,
|
||||
"off" => entropyk_components::OperationalState::Off,
|
||||
"bypass" => entropyk_components::OperationalState::Bypass,
|
||||
_ => {
|
||||
return Err(PyValueError::new_err(
|
||||
"state must be one of: 'on', 'off', 'bypass'",
|
||||
|
||||
Reference in New Issue
Block a user