Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom PhaseDiagram constructor #113

Merged
merged 2 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions feos-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
23 changes: 11 additions & 12 deletions feos-core/src/phase_equilibria/phase_diagram_binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::sync::Arc;

const DEFAULT_POINTS: usize = 51;

impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E, 2> {
/// Create a new binary phase diagram exhibiting a
/// vapor/liquid equilibrium.
///
Expand Down Expand Up @@ -254,12 +254,12 @@ impl<U: EosUnit, E: EquationOfState> State<U, E> {

/// Phase diagram (Txy or pxy) for a system with heteroazeotropic phase behavior.
pub struct PhaseDiagramHetero<U, E> {
pub vle1: PhaseDiagram<U, E>,
pub vle2: PhaseDiagram<U, E>,
pub lle: Option<PhaseDiagram<U, E>>,
pub vle1: PhaseDiagram<U, E, 2>,
pub vle2: PhaseDiagram<U, E, 2>,
pub lle: Option<PhaseDiagram<U, E, 2>>,
}

impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E, 2> {
/// Create a new binary phase diagram exhibiting a
/// vapor/liquid/liquid equilibrium.
///
Expand Down Expand Up @@ -337,24 +337,23 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
.transpose()?;

Ok(PhaseDiagramHetero {
vle1: PhaseDiagram { states: dia1 },
vle2: PhaseDiagram { states: dia2 },
vle1: PhaseDiagram::new(dia1),
vle2: PhaseDiagram::new(dia2),
lle,
})
}
}

impl<U: Clone, E> PhaseDiagramHetero<U, E> {
pub fn vle(&self) -> PhaseDiagram<U, E> {
PhaseDiagram {
states: self
.vle1
pub fn vle(&self) -> PhaseDiagram<U, E, 2> {
PhaseDiagram::new(
self.vle1
.states
.iter()
.chain(self.vle2.states.iter().rev())
.cloned()
.collect(),
}
)
}
}

Expand Down
21 changes: 14 additions & 7 deletions feos-core/src/phase_equilibria/phase_diagram_pure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,26 @@ use rayon::{prelude::*, ThreadPool};
use std::sync::Arc;

/// Pure component and binary mixture phase diagrams.
pub struct PhaseDiagram<U, E> {
pub states: Vec<PhaseEquilibrium<U, E, 2>>,
pub struct PhaseDiagram<U, E, const N: usize> {
pub states: Vec<PhaseEquilibrium<U, E, N>>,
}

impl<U: Clone, E> Clone for PhaseDiagram<U, E> {
impl<U: Clone, E, const N: usize> Clone for PhaseDiagram<U, E, N> {
fn clone(&self) -> Self {
Self {
states: self.states.clone(),
}
}
}

impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
impl<U, E, const N: usize> PhaseDiagram<U, E, N> {
/// Create a phase diagram from a list of phase equilibria.
pub fn new(states: Vec<PhaseEquilibrium<U, E, N>>) -> Self {
Self { states }
}
}

impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E, 2> {
/// Calculate a phase diagram for a pure component.
pub fn pure(
eos: &Arc<E>,
Expand Down Expand Up @@ -52,7 +59,7 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
}
states.push(PhaseEquilibrium::from_states(sc.clone(), sc));

Ok(PhaseDiagram { states })
Ok(PhaseDiagram::new(states))
}

/// Return the vapor states of the diagram.
Expand All @@ -67,7 +74,7 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
}

#[cfg(feature = "rayon")]
impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E, 2> {
fn solve_temperatures(
eos: &Arc<E>,
temperatures: ArrayView1<f64>,
Expand Down Expand Up @@ -125,6 +132,6 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
});

states.push(PhaseEquilibrium::from_states(sc.clone(), sc));
Ok(PhaseDiagram { states })
Ok(PhaseDiagram::new(states))
}
}
10 changes: 5 additions & 5 deletions feos-core/src/phase_equilibria/phase_envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{Contributions, EosUnit};
use quantity::{QuantityArray1, QuantityScalar};
use std::sync::Arc;

impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E, 2> {
/// Calculate the bubble point line of a mixture with given composition.
pub fn bubble_point_line(
eos: &Arc<E>,
Expand Down Expand Up @@ -56,7 +56,7 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
}
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.
Expand Down Expand Up @@ -102,7 +102,7 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {

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);
Expand All @@ -124,7 +124,7 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {

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.
Expand Down Expand Up @@ -160,6 +160,6 @@ impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
}
states.push(PhaseEquilibrium::from_states(sc.clone(), sc));

Ok(PhaseDiagram { states })
Ok(PhaseDiagram::new(states))
}
}
16 changes: 15 additions & 1 deletion feos-core/src/python/phase_equilibria.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<SIUnit, $eos>);
pub struct PyPhaseDiagram(PhaseDiagram<SIUnit, $eos, 2>);

#[pymethods]
impl PyPhaseDiagram {
#[new]
fn new(phase_equilibria: Vec<PyPhaseEquilibrium>) -> Self {
Self(PhaseDiagram::new(phase_equilibria.into_iter().map(|p| p.0).collect()))
}

/// Calculate a pure component phase diagram.
///
/// Parameters
Expand Down
24 changes: 21 additions & 3 deletions feos-core/src/python/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<State<SIUnit, $eos>>);

Expand All @@ -1027,6 +1038,11 @@ macro_rules! impl_state {

#[pymethods]
impl PyStateVec {
#[new]
fn new(states: Vec<PyState>) -> Self {
Self(states.into_iter().map(|s| s.0).collect())
}

fn __len__(&self) -> PyResult<usize> {
Ok(self.0.len())
}
Expand All @@ -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()
Expand All @@ -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<f64> {
StateVec::from(self).molefracs().view().to_pyarray(py)
Expand Down
6 changes: 6 additions & 0 deletions feos-core/src/state/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<U> {
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<f64> {
Array2::from_shape_fn((self.0.len(), self.0[0].eos.components()), |(i, j)| {
self.0[i].molefracs[j]
Expand Down
2 changes: 1 addition & 1 deletion parameters/pcsaft/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 | [&#128279;](https://doi.org/10.1021/ie502203w) [&#128279;](https://doi.org/10.1080/00986448708960487)|
[`sauer2014_hetero.json`](sauer2014_hetero.json) | GC segment parameters for heterosegmented PC-SAFT | [&#128279;](https://doi.org/10.1021/ie502203w)
[`sauer2014_hetero_joback.json`](sauer2014_hetero.json) | GC segment parameters for heterosegmented PC-SAFT including ideal gas parameters | [&#128279;](https://doi.org/10.1021/ie502203w) [&#128279;](https://doi.org/10.1080/00986448708960487)
[`loetgeringlin2015_homo.json`](loetgeringlin2018.json) | GC segment parameters including for homosegmented PC-SAFT including viscosity parameter | [&#128279;](https://doi.org/10.1021/acs.iecr.5b01698)
[`loetgeringlin2015_homo.json`](loetgeringlin2018.json) | GC segment parameters for homosegmented PC-SAFT including viscosity parameter | [&#128279;](https://doi.org/10.1021/acs.iecr.5b01698)

1 change: 1 addition & 0 deletions src/python/dft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ pub fn dft(_py: Python<'_>, m: &PyModule) -> PyResult<()> {

m.add_class::<PyFunctionalVariant>()?;
m.add_class::<PyState>()?;
m.add_class::<PyStateVec>()?;
m.add_class::<PyPhaseDiagram>()?;
m.add_class::<PyPhaseEquilibrium>()?;
m.add_class::<FMTVersion>()?;
Expand Down
1 change: 1 addition & 0 deletions src/python/eos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ pub fn eos(_py: Python<'_>, m: &PyModule) -> PyResult<()> {

m.add_class::<PyEosVariant>()?;
m.add_class::<PyState>()?;
m.add_class::<PyStateVec>()?;
m.add_class::<PyPhaseDiagram>()?;
m.add_class::<PyPhaseEquilibrium>()?;

Expand Down