Skip to content
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
385 changes: 385 additions & 0 deletions examples/pc_saft_phase_diagram_to_dict.ipynb

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions feos-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- Added specific isochoric and isobaric heat capacities to the Python interface. [#223](https://github.com/feos-org/feos/pull/223))
- Added `to_dict` method for `PyStateVec`. [#224](https://github.com/feos-org/feos/pull/224)

### Fixed
- Added comparison for pressures of both phases in `PyPhaseDiagram.to_dict` to make the method work with `spinodal` constructor. [#224](https://github.com/feos-org/feos/pull/224)

## [0.6.1] 2024-01-11
### Fixed
Expand Down
15 changes: 13 additions & 2 deletions feos-core/src/python/phase_equilibria.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ macro_rules! impl_phase_equilibrium {
#[pyo3(signature = (contributions=Contributions::Total), text_signature = "($self, contributions)")]
pub fn to_dict(&self, contributions: Contributions) -> HashMap<String, Vec<f64>> {
let n = self.0.states[0].liquid().eos.components();
let mut dict = HashMap::with_capacity(8 + 2 * n);
let mut dict = HashMap::with_capacity(16 + 2 * n);
if n != 1 {
let xs = self.0.liquid().molefracs();
let ys = self.0.vapor().molefracs();
Expand All @@ -916,7 +916,18 @@ macro_rules! impl_phase_equilibrium {
}
}
dict.insert(String::from("temperature"), self.0.vapor().temperature().convert_into(KELVIN).into_raw_vec());
dict.insert(String::from("pressure"), self.0.vapor().pressure().convert_into(PASCAL).into_raw_vec());

// Check if liquid and vapor pressures are different (e.g. if )
let p_v = self.0.vapor().pressure().convert_into(PASCAL).into_raw_vec();
let p_l = self.0.liquid().pressure().convert_into(PASCAL).into_raw_vec();
let different_pressures = p_v.iter().zip(p_l.iter()).any(|(pv, pl)| (pv - pl).abs() / pv > 1e-3);

if different_pressures {
dict.insert(String::from("pressure vapor"), p_v);
dict.insert(String::from("pressure liquid"), p_l);
}else {
dict.insert(String::from("pressure"), p_v);
}
dict.insert(String::from("density liquid"), self.0.liquid().density().convert_into(MOL / METER.powi::<P3>()).into_raw_vec());
dict.insert(String::from("density vapor"), self.0.vapor().density().convert_into(MOL / METER.powi::<P3>()).into_raw_vec());
dict.insert(String::from("mass density liquid"), self.0.liquid().mass_density().convert_into(KILOGRAM / METER.powi::<P3>()).into_raw_vec());
Expand Down
47 changes: 47 additions & 0 deletions feos-core/src/python/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,53 @@ macro_rules! impl_state {
fn get_massfracs<'py>(&self, py: Python<'py>) -> &'py PyArray2<f64> {
StateVec::from(self).massfracs().view().to_pyarray(py)
}

/// Returns selected properties of a StateVec as dictionary.
///
/// Parameters
/// ----------
/// contributions : Contributions, optional
/// The contributions to consider when calculating properties.
/// Defaults to Contributions.Total.
///
/// Returns
/// -------
/// Dict[str, List[float]]
/// Keys: property names. Values: property for each state.
///
/// Notes
/// -----
/// - temperature : K
/// - pressure : Pa
/// - densities : mol / m³
/// - mass densities : kg / m³
/// - molar enthalpies : kJ / mol
/// - molar entropies : kJ / mol / K
/// - specific enthalpies : kJ / kg
/// - specific entropies : kJ / kg / K
/// - xi: molefraction of component i
/// - component index `i` matches to order of components in parameters.
#[pyo3(signature = (contributions=Contributions::Total), text_signature = "($self, contributions)")]
pub fn to_dict(&self, contributions: Contributions) -> HashMap<String, Vec<f64>> {
let states = StateVec::from(self);
let n = states.0[0].eos.components();
let mut dict = HashMap::with_capacity(8 + n);
if n != 1 {
let xs = states.molefracs();
for i in 0..n {
dict.insert(String::from(format!("x{}", i)), xs.column(i).to_vec());
}
}
dict.insert(String::from("temperature"), states.temperature().convert_into(KELVIN).into_raw_vec());
dict.insert(String::from("pressure"), states.pressure().convert_into(PASCAL).into_raw_vec());
dict.insert(String::from("density"), states.density().convert_into(MOL / METER.powi::<P3>()).into_raw_vec());
dict.insert(String::from("mass density"), states.mass_density().convert_into(KILOGRAM / METER.powi::<P3>()).into_raw_vec());
dict.insert(String::from("molar enthalpy"), states.molar_enthalpy(contributions).convert_into(KILO * JOULE / MOL).into_raw_vec());
dict.insert(String::from("molar entropy"), states.molar_entropy(contributions).convert_into(KILO * JOULE / KELVIN / MOL).into_raw_vec());
dict.insert(String::from("specific enthalpy"), states.specific_enthalpy(contributions).convert_into(KILO * JOULE / KILOGRAM).into_raw_vec());
dict.insert(String::from("specific entropy"), states.specific_entropy(contributions).convert_into(KILO * JOULE / KELVIN / KILOGRAM).into_raw_vec());
dict
}
}
};
}
Expand Down