diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d9ce071..fea4211a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added SAFT-VRQ Mie equation of state and Helmholtz energy functional for first order Feynman-Hibbs corrected Mie fluids. [#79](https://github.com/feos-org/feos/pull/79) - Added `estimator` module to documentation. [#86](https://github.com/feos-org/feos/pull/86) - Added benchmarks for the evaluation of the Helmholtz energy and some properties of the `State` object for PC-SAFT. [#89](https://github.com/feos-org/feos/pull/89) +- The Python class `StateVec` is exposed in both the `feos.eos` and `feos.dft` module. [#113](https://github.com/feos-org/feos/pull/113) ### Changed - Export `EosVariant` and `FunctionalVariant` directly in the crate root instead of their own modules. [#62](https://github.com/feos-org/feos/pull/62) diff --git a/feos-core/CHANGELOG.md b/feos-core/CHANGELOG.md index 5be9eec73..75dd1b99c 100644 --- a/feos-core/CHANGELOG.md +++ b/feos-core/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added - Added `PhaseDiagram::par_pure` that uses rayon to calculate phase diagrams in parallel. [#57](https://github.com/feos-org/feos/pull/57) +- Added `StateVec::moles` getter. [#113](https://github.com/feos-org/feos/pull/113) +- Added public constructors `PhaseDiagram::new` and `StateVec::new` that allow the creation of the respective structs from a list of `PhaseEquilibrium`s or `State`s in Rust and Python. [#113](https://github.com/feos-org/feos/pull/113) ### Changed - Added `Sync` and `Send` as supertraits to `EquationOfState`. [#57](https://github.com/feos-org/feos/pull/57) @@ -17,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `get_or_insert_with_d2_64` to `Cache`. [#94](https://github.com/feos-org/feos/pull/94) - The critical point algorithm now uses vector dual numbers to reduce the number of model evaluations and computation times. [#96](https://github.com/feos-org/feos/pull/96) - Renamed `State::molar_volume` to `State::partial_molar_volume` and `State::ln_phi_pure` to `State::ln_phi_pure_liquid`. [#107](https://github.com/feos-org/feos/pull/107) +- Added a const generic parameter to `PhaseDiagram` that accounts for the number of phases analogously to `PhaseEquilibrium`. [#113](https://github.com/feos-org/feos/pull/113) ## [0.3.1] - 2022-08-25 ### Added diff --git a/feos-core/src/phase_equilibria/phase_diagram_binary.rs b/feos-core/src/phase_equilibria/phase_diagram_binary.rs index b0a171fad..bb0be4836 100644 --- a/feos-core/src/phase_equilibria/phase_diagram_binary.rs +++ b/feos-core/src/phase_equilibria/phase_diagram_binary.rs @@ -11,7 +11,7 @@ use std::sync::Arc; const DEFAULT_POINTS: usize = 51; -impl PhaseDiagram { +impl PhaseDiagram { /// Create a new binary phase diagram exhibiting a /// vapor/liquid equilibrium. /// @@ -254,12 +254,12 @@ impl State { /// Phase diagram (Txy or pxy) for a system with heteroazeotropic phase behavior. pub struct PhaseDiagramHetero { - pub vle1: PhaseDiagram, - pub vle2: PhaseDiagram, - pub lle: Option>, + pub vle1: PhaseDiagram, + pub vle2: PhaseDiagram, + pub lle: Option>, } -impl PhaseDiagram { +impl PhaseDiagram { /// Create a new binary phase diagram exhibiting a /// vapor/liquid/liquid equilibrium. /// @@ -337,24 +337,23 @@ impl PhaseDiagram { .transpose()?; Ok(PhaseDiagramHetero { - vle1: PhaseDiagram { states: dia1 }, - vle2: PhaseDiagram { states: dia2 }, + vle1: PhaseDiagram::new(dia1), + vle2: PhaseDiagram::new(dia2), lle, }) } } impl PhaseDiagramHetero { - pub fn vle(&self) -> PhaseDiagram { - PhaseDiagram { - states: self - .vle1 + pub fn vle(&self) -> PhaseDiagram { + PhaseDiagram::new( + self.vle1 .states .iter() .chain(self.vle2.states.iter().rev()) .cloned() .collect(), - } + ) } } diff --git a/feos-core/src/phase_equilibria/phase_diagram_pure.rs b/feos-core/src/phase_equilibria/phase_diagram_pure.rs index 4dba91e47..016e0bc16 100644 --- a/feos-core/src/phase_equilibria/phase_diagram_pure.rs +++ b/feos-core/src/phase_equilibria/phase_diagram_pure.rs @@ -11,11 +11,11 @@ use rayon::{prelude::*, ThreadPool}; use std::sync::Arc; /// Pure component and binary mixture phase diagrams. -pub struct PhaseDiagram { - pub states: Vec>, +pub struct PhaseDiagram { + pub states: Vec>, } -impl Clone for PhaseDiagram { +impl Clone for PhaseDiagram { fn clone(&self) -> Self { Self { states: self.states.clone(), @@ -23,7 +23,14 @@ impl Clone for PhaseDiagram { } } -impl PhaseDiagram { +impl PhaseDiagram { + /// Create a phase diagram from a list of phase equilibria. + pub fn new(states: Vec>) -> Self { + Self { states } + } +} + +impl PhaseDiagram { /// Calculate a phase diagram for a pure component. pub fn pure( eos: &Arc, @@ -52,7 +59,7 @@ impl PhaseDiagram { } states.push(PhaseEquilibrium::from_states(sc.clone(), sc)); - Ok(PhaseDiagram { states }) + Ok(PhaseDiagram::new(states)) } /// Return the vapor states of the diagram. @@ -67,7 +74,7 @@ impl PhaseDiagram { } #[cfg(feature = "rayon")] -impl PhaseDiagram { +impl PhaseDiagram { fn solve_temperatures( eos: &Arc, temperatures: ArrayView1, @@ -125,6 +132,6 @@ impl PhaseDiagram { }); states.push(PhaseEquilibrium::from_states(sc.clone(), sc)); - Ok(PhaseDiagram { states }) + Ok(PhaseDiagram::new(states)) } } diff --git a/feos-core/src/phase_equilibria/phase_envelope.rs b/feos-core/src/phase_equilibria/phase_envelope.rs index a51c96eef..c05406423 100644 --- a/feos-core/src/phase_equilibria/phase_envelope.rs +++ b/feos-core/src/phase_equilibria/phase_envelope.rs @@ -6,7 +6,7 @@ use crate::{Contributions, EosUnit}; use quantity::{QuantityArray1, QuantityScalar}; use std::sync::Arc; -impl PhaseDiagram { +impl PhaseDiagram { /// Calculate the bubble point line of a mixture with given composition. pub fn bubble_point_line( eos: &Arc, @@ -56,7 +56,7 @@ impl PhaseDiagram { } states.push(PhaseEquilibrium::from_states(sc.clone(), sc)); - Ok(PhaseDiagram { states }) + Ok(PhaseDiagram::new(states)) } /// Calculate the dew point line of a mixture with given composition. @@ -102,7 +102,7 @@ impl PhaseDiagram { let n_p = npoints - n_t; if vle.is_none() { - return Ok(PhaseDiagram { states }); + return Ok(PhaseDiagram::new(states)); } let min_pressure = vle.as_ref().unwrap().vapor().pressure(Contributions::Total); @@ -124,7 +124,7 @@ impl PhaseDiagram { states.push(PhaseEquilibrium::from_states(sc.clone(), sc)); - Ok(PhaseDiagram { states }) + Ok(PhaseDiagram::new(states)) } /// Calculate the spinodal lines for a mixture with fixed composition. @@ -160,6 +160,6 @@ impl PhaseDiagram { } states.push(PhaseEquilibrium::from_states(sc.clone(), sc)); - Ok(PhaseDiagram { states }) + Ok(PhaseDiagram::new(states)) } } diff --git a/feos-core/src/python/phase_equilibria.rs b/feos-core/src/python/phase_equilibria.rs index 0f42288fb..017c71920 100644 --- a/feos-core/src/python/phase_equilibria.rs +++ b/feos-core/src/python/phase_equilibria.rs @@ -463,11 +463,25 @@ macro_rules! impl_phase_equilibrium { } /// Phase diagram for a pure component or a binary mixture. + /// + /// Parameters + /// ---------- + /// phase_equilibria : [PhaseEquilibrium] + /// A list of individual phase equilibria. + /// + /// Returns + /// ------- + /// PhaseDiagram : the resulting phase diagram #[pyclass(name = "PhaseDiagram")] - pub struct PyPhaseDiagram(PhaseDiagram); + pub struct PyPhaseDiagram(PhaseDiagram); #[pymethods] impl PyPhaseDiagram { + #[new] + fn new(phase_equilibria: Vec) -> Self { + Self(PhaseDiagram::new(phase_equilibria.into_iter().map(|p| p.0).collect())) + } + /// Calculate a pure component phase diagram. /// /// Parameters diff --git a/feos-core/src/python/state.rs b/feos-core/src/python/state.rs index 1a5e3f04d..6b29b2ff8 100644 --- a/feos-core/src/python/state.rs +++ b/feos-core/src/python/state.rs @@ -1010,6 +1010,17 @@ macro_rules! impl_state { } + /// A list of states that provides convenient getters + /// for properties of all the individual states. + /// + /// Parameters + /// ---------- + /// states : [State] + /// A list of individual states. + /// + /// Returns + /// ------- + /// StateVec #[pyclass(name = "StateVec")] pub struct PyStateVec(Vec>); @@ -1027,6 +1038,11 @@ macro_rules! impl_state { #[pymethods] impl PyStateVec { + #[new] + fn new(states: Vec) -> Self { + Self(states.into_iter().map(|s| s.0).collect()) + } + fn __len__(&self) -> PyResult { Ok(self.0.len()) } @@ -1043,10 +1059,7 @@ macro_rules! impl_state { Err(PyIndexError::new_err(format!("StateVec index out of range"))) } } - } - #[pymethods] - impl PyStateVec { #[getter] fn get_temperature(&self) -> PySIArray1{ StateVec::from(self).temperature().into() @@ -1067,6 +1080,11 @@ macro_rules! impl_state { StateVec::from(self).density().into() } + #[getter] + fn get_moles<'py>(&self, py: Python<'py>) -> PySIArray2 { + StateVec::from(self).moles().into() + } + #[getter] fn get_molefracs<'py>(&self, py: Python<'py>) -> &'py PyArray2 { StateVec::from(self).molefracs().view().to_pyarray(py) diff --git a/feos-core/src/state/properties.rs b/feos-core/src/state/properties.rs index c1a0a97f9..6901c109b 100644 --- a/feos-core/src/state/properties.rs +++ b/feos-core/src/state/properties.rs @@ -799,6 +799,12 @@ impl<'a, U: EosUnit, E: EquationOfState> StateVec<'a, U, E> { QuantityArray1::from_shape_fn(self.0.len(), |i| self.0[i].density) } + pub fn moles(&self) -> QuantityArray2 { + QuantityArray2::from_shape_fn((self.0.len(), self.0[0].eos.components()), |(i, j)| { + self.0[i].moles.get(j) + }) + } + pub fn molefracs(&self) -> Array2 { Array2::from_shape_fn((self.0.len(), self.0[0].eos.components()), |(i, j)| { self.0[i].molefracs[j] diff --git a/parameters/pcsaft/README.md b/parameters/pcsaft/README.md index ed770c94f..c3d7a957a 100644 --- a/parameters/pcsaft/README.md +++ b/parameters/pcsaft/README.md @@ -35,5 +35,5 @@ The files named according to the pattern `NameYear.json` correspond to published [`sauer2014_homo_joback.json`](sauer2014_homo.json) | GC segment parameters for homosegmented PC-SAFT including ideal gas parameters | [🔗](https://doi.org/10.1021/ie502203w) [🔗](https://doi.org/10.1080/00986448708960487)| [`sauer2014_hetero.json`](sauer2014_hetero.json) | GC segment parameters for heterosegmented PC-SAFT | [🔗](https://doi.org/10.1021/ie502203w) [`sauer2014_hetero_joback.json`](sauer2014_hetero.json) | GC segment parameters for heterosegmented PC-SAFT including ideal gas parameters | [🔗](https://doi.org/10.1021/ie502203w) [🔗](https://doi.org/10.1080/00986448708960487) -[`loetgeringlin2015_homo.json`](loetgeringlin2018.json) | GC segment parameters including for homosegmented PC-SAFT including viscosity parameter | [🔗](https://doi.org/10.1021/acs.iecr.5b01698) +[`loetgeringlin2015_homo.json`](loetgeringlin2018.json) | GC segment parameters for homosegmented PC-SAFT including viscosity parameter | [🔗](https://doi.org/10.1021/acs.iecr.5b01698) diff --git a/src/python/dft.rs b/src/python/dft.rs index 7f8bfcaa4..af57a4292 100644 --- a/src/python/dft.rs +++ b/src/python/dft.rs @@ -258,6 +258,7 @@ pub fn dft(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; diff --git a/src/python/eos.rs b/src/python/eos.rs index 8a549866e..8207c72a0 100644 --- a/src/python/eos.rs +++ b/src/python/eos.rs @@ -299,6 +299,7 @@ pub fn eos(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?;