Update project structure and configurations

This commit is contained in:
2026-05-23 10:19:55 +02:00
parent ab5dc7e568
commit 62efea0646
1832 changed files with 83568 additions and 51829 deletions

View File

@@ -555,7 +555,17 @@ pub struct PyFlowSource {
impl PyFlowSource {
#[new]
#[pyo3(signature = (pressure_pa=101325.0, temperature_k=300.0, fluid="Water"))]
fn new(pressure_pa: f64, temperature_k: f64, fluid: &str) -> PyResult<Self> {
fn new(py: Python<'_>, pressure_pa: f64, temperature_k: f64, fluid: &str) -> PyResult<Self> {
let warnings = py.import_bound("warnings")?;
warnings.call_method1(
"warn",
(
"FlowSource is deprecated. Use RefrigerantSource, BrineSource, or AirSource instead.",
py.get_type_bound::<pyo3::exceptions::PyDeprecationWarning>(),
2,
),
)?;
if pressure_pa <= 0.0 {
return Err(PyValueError::new_err("pressure_pa must be positive"));
}
@@ -600,8 +610,17 @@ pub struct PyFlowSink;
#[pymethods]
impl PyFlowSink {
#[new]
fn new() -> Self {
PyFlowSink
fn new(py: Python<'_>) -> PyResult<Self> {
let warnings = py.import_bound("warnings")?;
warnings.call_method1(
"warn",
(
"FlowSink is deprecated. Use RefrigerantSink, BrineSink, or AirSink instead.",
py.get_type_bound::<pyo3::exceptions::PyDeprecationWarning>(),
2,
),
)?;
Ok(PyFlowSink)
}
fn __repr__(&self) -> String {
@@ -657,6 +676,250 @@ impl PyOperationalState {
}
}
// =============================================================================
// Refrigerant Boundary Conditions
// =============================================================================
/// A boundary condition representing a refrigerant mass flow source.
#[pyclass(name = "RefrigerantSource", module = "entropyk")]
#[derive(Clone)]
pub struct PyRefrigerantSource {
pub(crate) fluid: String,
pub(crate) p_set_pa: f64,
pub(crate) quality: f64,
}
#[pymethods]
impl PyRefrigerantSource {
#[new]
#[pyo3(signature = (fluid="R410A", pressure_pa=101325.0, quality=1.0))]
fn new(fluid: &str, pressure_pa: f64, quality: f64) -> PyResult<Self> {
if pressure_pa <= 0.0 {
return Err(PyValueError::new_err("pressure_pa must be positive"));
}
if !(0.0..=1.0).contains(&quality) {
return Err(PyValueError::new_err("quality must be between 0.0 and 1.0"));
}
Ok(PyRefrigerantSource {
fluid: fluid.to_string(),
p_set_pa: pressure_pa,
quality,
})
}
fn __repr__(&self) -> String {
format!(
"RefrigerantSource(fluid={}, P={:.0} Pa, q={:.2})",
self.fluid, self.p_set_pa, self.quality
)
}
}
impl PyRefrigerantSource {
pub(crate) fn build(&self) -> Box<dyn Component> {
Box::new(entropyk_components::PyRefrigerantSourceReal::new(&self.fluid, self.p_set_pa, self.quality))
}
}
/// A boundary condition representing a refrigerant mass flow sink.
#[pyclass(name = "RefrigerantSink", module = "entropyk")]
#[derive(Clone)]
pub struct PyRefrigerantSink {
pub(crate) fluid: String,
pub(crate) p_back_pa: f64,
pub(crate) quality_opt: Option<f64>,
}
#[pymethods]
impl PyRefrigerantSink {
#[new]
#[pyo3(signature = (fluid="R410A", p_back_pa=101325.0, quality=None))]
fn new(fluid: &str, p_back_pa: f64, quality: Option<f64>) -> PyResult<Self> {
if p_back_pa <= 0.0 {
return Err(PyValueError::new_err("p_back_pa must be positive"));
}
if let Some(q) = quality {
if !(0.0..=1.0).contains(&q) {
return Err(PyValueError::new_err("quality must be between 0.0 and 1.0"));
}
}
Ok(PyRefrigerantSink {
fluid: fluid.to_string(),
p_back_pa,
quality_opt: quality,
})
}
fn __repr__(&self) -> String {
format!(
"RefrigerantSink(fluid={}, P_back={:.0} Pa, q={:?})",
self.fluid, self.p_back_pa, self.quality_opt
)
}
}
impl PyRefrigerantSink {
pub(crate) fn build(&self) -> Box<dyn Component> {
Box::new(entropyk_components::PyRefrigerantSinkReal::new(&self.fluid, self.p_back_pa, self.quality_opt))
}
}
// =============================================================================
// Brine Boundary Conditions
// =============================================================================
/// A boundary condition representing a brine mass flow source.
#[pyclass(name = "BrineSource", module = "entropyk")]
#[derive(Clone)]
pub struct PyBrineSource {
pub(crate) fluid: String,
pub(crate) concentration: f64,
pub(crate) temperature_k: f64,
pub(crate) pressure_pa: f64,
}
#[pymethods]
impl PyBrineSource {
#[new]
#[pyo3(signature = (fluid="Water", concentration=0.0, temperature_k=300.0, pressure_pa=101325.0))]
fn new(fluid: &str, concentration: f64, temperature_k: f64, pressure_pa: f64) -> PyResult<Self> {
if pressure_pa <= 0.0 {
return Err(PyValueError::new_err("pressure_pa must be positive"));
}
if temperature_k <= 0.0 {
return Err(PyValueError::new_err("temperature_k must be positive"));
}
if !(0.0..=1.0).contains(&concentration) {
return Err(PyValueError::new_err("concentration must be between 0.0 and 1.0"));
}
Ok(PyBrineSource {
fluid: fluid.to_string(),
concentration,
temperature_k,
pressure_pa,
})
}
fn __repr__(&self) -> String {
format!(
"BrineSource(fluid={}, c={:.2}, T={:.1} K, P={:.0} Pa)",
self.fluid, self.concentration, self.temperature_k, self.pressure_pa
)
}
}
impl PyBrineSource {
pub(crate) fn build(&self) -> Box<dyn Component> {
Box::new(entropyk_components::PyBrineSourceReal::new(&self.fluid, self.concentration, self.temperature_k, self.pressure_pa))
}
}
/// A boundary condition representing a brine mass flow sink.
#[pyclass(name = "BrineSink", module = "entropyk")]
#[derive(Clone)]
pub struct PyBrineSink {
pub(crate) p_back_pa: f64,
}
#[pymethods]
impl PyBrineSink {
#[new]
#[pyo3(signature = (p_back_pa=101325.0))]
fn new(p_back_pa: f64) -> PyResult<Self> {
if p_back_pa <= 0.0 {
return Err(PyValueError::new_err("p_back_pa must be positive"));
}
Ok(PyBrineSink { p_back_pa })
}
fn __repr__(&self) -> String {
format!("BrineSink(P_back={:.0} Pa)", self.p_back_pa)
}
}
impl PyBrineSink {
pub(crate) fn build(&self) -> Box<dyn Component> {
Box::new(entropyk_components::PyBrineSinkReal::new(self.p_back_pa))
}
}
// =============================================================================
// Air Boundary Conditions
// =============================================================================
/// A boundary condition representing an air mass flow source.
#[pyclass(name = "AirSource", module = "entropyk")]
#[derive(Clone)]
pub struct PyAirSource {
pub(crate) temperature_k: f64,
pub(crate) relative_humidity: f64,
pub(crate) pressure_pa: f64,
}
#[pymethods]
impl PyAirSource {
#[new]
#[pyo3(signature = (temperature_k=300.0, relative_humidity=0.5, pressure_pa=101325.0))]
fn new(temperature_k: f64, relative_humidity: f64, pressure_pa: f64) -> PyResult<Self> {
if pressure_pa <= 0.0 {
return Err(PyValueError::new_err("pressure_pa must be positive"));
}
if temperature_k <= 0.0 {
return Err(PyValueError::new_err("temperature_k must be positive"));
}
if !(0.0..=1.0).contains(&relative_humidity) {
return Err(PyValueError::new_err("relative_humidity must be between 0.0 and 1.0"));
}
Ok(PyAirSource {
temperature_k,
relative_humidity,
pressure_pa,
})
}
fn __repr__(&self) -> String {
format!(
"AirSource(T={:.1} K, RH={:.2}, P={:.0} Pa)",
self.temperature_k, self.relative_humidity, self.pressure_pa
)
}
}
impl PyAirSource {
pub(crate) fn build(&self) -> Box<dyn Component> {
Box::new(entropyk_components::PyAirSourceReal::new(self.temperature_k, self.relative_humidity, self.pressure_pa))
}
}
/// A boundary condition representing an air mass flow sink.
#[pyclass(name = "AirSink", module = "entropyk")]
#[derive(Clone)]
pub struct PyAirSink {
pub(crate) p_back_pa: f64,
}
#[pymethods]
impl PyAirSink {
#[new]
#[pyo3(signature = (p_back_pa=101325.0))]
fn new(p_back_pa: f64) -> PyResult<Self> {
if p_back_pa <= 0.0 {
return Err(PyValueError::new_err("p_back_pa must be positive"));
}
Ok(PyAirSink { p_back_pa })
}
fn __repr__(&self) -> String {
format!("AirSink(P_back={:.0} Pa)", self.p_back_pa)
}
}
impl PyAirSink {
pub(crate) fn build(&self) -> Box<dyn Component> {
Box::new(entropyk_components::PyAirSinkReal::new(self.p_back_pa))
}
}
// =============================================================================
// Component enum for type-erasure
// =============================================================================
@@ -676,6 +939,12 @@ pub(crate) enum AnyPyComponent {
FlowMerger(PyFlowMerger),
FlowSource(PyFlowSource),
FlowSink(PyFlowSink),
RefrigerantSource(PyRefrigerantSource),
RefrigerantSink(PyRefrigerantSink),
BrineSource(PyBrineSource),
BrineSink(PyBrineSink),
AirSource(PyAirSource),
AirSink(PyAirSink),
}
impl AnyPyComponent {
@@ -694,6 +963,12 @@ impl AnyPyComponent {
AnyPyComponent::FlowMerger(c) => c.build(),
AnyPyComponent::FlowSource(c) => c.build(),
AnyPyComponent::FlowSink(c) => c.build(),
AnyPyComponent::RefrigerantSource(c) => c.build(),
AnyPyComponent::RefrigerantSink(c) => c.build(),
AnyPyComponent::BrineSource(c) => c.build(),
AnyPyComponent::BrineSink(c) => c.build(),
AnyPyComponent::AirSource(c) => c.build(),
AnyPyComponent::AirSink(c) => c.build(),
}
}
}