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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
- Updated to `ndarray` 0.17 and `num-dual`0.13 to fix a broken dependency resolution. [#327](https://github.com/feos-org/feos/pull/327)
- Fixed calculation of parameter combination in entropy scaling for mixtures in `viscosity_correlation`, `diffusion_correlation`, `thermal_conductivity_correlation`. [#323](https://github.com/feos-org/feos/pull/323)

## [0.9.1] - 2025-11-24
### Fixed
Expand Down
63 changes: 43 additions & 20 deletions crates/feos/src/pcsaft/eos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,13 @@ impl EntropyScaling for PcSaft {
.viscosity
.as_ref()
.expect("Missing viscosity coefficients.");
let m = (x * &self.params.m).sum();
let m = x.dot(&self.params.m);
let s = s_res / m;
let pref = (x * &self.params.m) / m;
let a = coefficients.row(0).dot(x);
let b = coefficients.row(1).dot(&pref);
let c = coefficients.row(2).dot(&pref);
let d = coefficients.row(3).dot(&pref);
let pref = x.component_mul(&self.params.m) / m;
let a = coefficients.row(0).transpose().dot(x);
let b = coefficients.row(1).transpose().dot(&pref);
let c = coefficients.row(2).transpose().dot(&pref);
let d = coefficients.row(3).transpose().dot(&pref);
a + b * s + c * s.powi(2) + d * s.powi(3)
}

Expand Down Expand Up @@ -307,14 +307,14 @@ impl EntropyScaling for PcSaft {
.diffusion
.as_ref()
.expect("Missing diffusion coefficients.");
let m = (x * &self.params.m).sum();
let m = x.dot(&self.params.m);
let s = s_res / m;
let pref = (x * &self.params.m).map(|v| v / m);
let a = coefficients.row(0).dot(x);
let b = coefficients.row(1).dot(&pref);
let c = coefficients.row(2).dot(&pref);
let d = coefficients.row(3).dot(&pref);
let e = coefficients.row(4).dot(&pref);
let pref = x.component_mul(&self.params.m) / m;
let a = coefficients.row(0).transpose().dot(x);
let b = coefficients.row(1).transpose().dot(&pref);
let c = coefficients.row(2).transpose().dot(&pref);
let d = coefficients.row(3).transpose().dot(&pref);
let e = coefficients.row(4).transpose().dot(&pref);
a + b * s - c * (1.0 - s.exp()) * s.powi(2) - d * s.powi(4) - e * s.powi(8)
}

Expand Down Expand Up @@ -371,13 +371,13 @@ impl EntropyScaling for PcSaft {
.thermal_conductivity
.as_ref()
.expect("Missing thermal conductivity coefficients");
let m = (x * &self.params.m).sum();
let m = x.dot(&self.params.m);
let s = s_res / m;
let pref = (x * &self.params.m).map(|v| v / m);
let a = coefficients.row(0).dot(x);
let b = coefficients.row(1).dot(&pref);
let c = coefficients.row(2).dot(&pref);
let d = coefficients.row(3).dot(&pref);
let pref = x.component_mul(&self.params.m) / m;
let a = coefficients.row(0).transpose().dot(x);
let b = coefficients.row(1).transpose().dot(&pref);
let c = coefficients.row(2).transpose().dot(&pref);
let d = coefficients.row(3).transpose().dot(&pref);
a + b * s + c * (1.0 - s.exp()) + d * s.powi(2)
}
}
Expand All @@ -386,7 +386,8 @@ impl EntropyScaling for PcSaft {
mod tests {
use super::*;
use crate::pcsaft::parameters::utils::{
butane_parameters, propane_butane_parameters, propane_parameters,
butane_parameters, nonane_heptane_parameters, nonane_parameters, propane_butane_parameters,
propane_parameters,
};
use approx::assert_relative_eq;
use feos_core::*;
Expand Down Expand Up @@ -545,6 +546,28 @@ mod tests {
Ok(())
}

#[test]
fn viscosity_mix() -> FeosResult<()> {
// Test case: compare fig 15 of Lötgering-Lin 2018 (https://doi.org/10.1021/acs.iecr.7b04871)
let e = &nonane_heptane_parameters();
let nonane = &nonane_parameters();

let t = 303.15 * KELVIN;
let p = 500.0 * BAR;
let n = dvector![0.25, 0.75] * MOL;
let viscosity_mix = State::new_npt(&e, t, p, &n, None)?.viscosity();
let viscosity_paper = 0.68298 * MILLI * PASCAL * SECOND;
assert_relative_eq!(viscosity_paper, viscosity_mix, epsilon = 1e-8);

// Make sure pure substance case is recovered
let n_pseudo_mix = dvector![1.0, 0.0] * MOL;
let viscosity_pseudo_mix = State::new_npt(&e, t, p, &n_pseudo_mix, None)?.viscosity();
let n_nonane = dvector![1.0] * MOL;
let viscosity_nonane = State::new_npt(&nonane, t, p, &n_nonane, None)?.viscosity();
assert_relative_eq!(viscosity_pseudo_mix, viscosity_nonane, epsilon = 1e-15);
Ok(())
}

#[test]
fn diffusion() -> FeosResult<()> {
let e = &propane_parameters();
Expand Down
75 changes: 75 additions & 0 deletions crates/feos/src/pcsaft/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,33 @@ pub mod utils {
PcSaft::new(PcSaftParameters::new_pure(butane_record).unwrap())
}

pub fn nonane_parameters() -> PcSaft {
let nonane_json = r#"
{
"identifier": {
"cas": "111-84-2",
"name": "nonane",
"iupac_name": "nonane",
"smiles": "CCCCCCCCC",
"inchi": "InChI=1S/C9H20/c1-3-5-7-9-8-6-4-2/h3-9H2,1-2H3",
"formula": "C9H20"
},
"molarweight": 128.258,
"m": 4.2079,
"sigma": 3.8448,
"epsilon_k": 244.51,
"viscosity": [
-1.4629,
-3.0058,
-0.5842,
-0.1222
]
}"#;
let nonane_record: PureRecord<PcSaftRecord, PcSaftAssociationRecord> =
serde_json::from_str(nonane_json).expect("Unable to parse json.");
PcSaft::new(PcSaftParameters::new_pure(nonane_record).unwrap())
}

pub fn dme_parameters() -> PcSaftPars {
let dme_json = r#"
{
Expand Down Expand Up @@ -522,6 +549,54 @@ pub mod utils {
PcSaft::new(PcSaftParameters::new_binary(binary_record, None, vec![]).unwrap())
}

pub fn nonane_heptane_parameters() -> PcSaft {
let binary_json = r#"[
{
"identifier": {
"cas": "111-84-2",
"name": "nonane",
"iupac_name": "nonane",
"smiles": "CCCCCCCCC",
"inchi": "InChI=1S/C9H20/c1-3-5-7-9-8-6-4-2/h3-9H2,1-2H3",
"formula": "C9H20"
},
"molarweight": 128.258,
"m": 4.2079,
"sigma": 3.8448,
"epsilon_k": 244.51,
"viscosity": [
-1.4629,
-3.0058,
-0.5842,
-0.1222
]
},
{
"identifier": {
"cas": "142-82-5",
"name": "heptane",
"iupac_name": "heptane",
"smiles": "CCCCCCC",
"inchi": "InChI=1S/C7H16/c1-3-5-7-6-4-2/h3-7H2,1-2H3",
"formula": "C7H16"
},
"molarweight": 100.204,
"m": 3.4831,
"sigma": 3.8049,
"epsilon_k": 238.4,
"viscosity": [
-1.2979,
-2.6936,
-0.4951,
-0.0988
]
}
]"#;
let binary_record: [PureRecord<PcSaftRecord, PcSaftAssociationRecord>; 2] =
serde_json::from_str(binary_json).expect("Unable to parse json.");
PcSaft::new(PcSaftParameters::new_binary(binary_record, None, vec![]).unwrap())
}

#[test]
pub fn test_kij() -> FeosResult<()> {
let ch3: String = "CH3".into();
Expand Down