Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Adjusted all models' implementation of the `Parameter` trait which now requires `Result`s in some methods. [#161](https://github.com/feos-org/feos/pull/161)
- Renamed `EosVariant` to `ResidualModel`. [#158](https://github.com/feos-org/feos/pull/158)
- Added methods to add an ideal gas contribution to an initialized equation of state object in Python. [#158](https://github.com/feos-org/feos/pull/158)
- Moved `molar_weight` impls to `Residual` due to removal of `MolarWeight` trait. [#177](https://github.com/feos-org/feos/pull/158)

### Packaging
- Updated `num-dual` dependency to 0.7. [#137](https://github.com/feos-org/feos/pull/137)
Expand Down
8 changes: 6 additions & 2 deletions benches/state_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ fn properties_pcsaft(c: &mut Criterion) {
b.iter(|| property_no_contributions((&eos, S::ln_phi, t, v, &m)))
});
group.bench_function("c_v", |b| {
b.iter(|| property_no_contributions((&eos, S::c_v_res, t, v, &m)))
b.iter(|| {
property_no_contributions((&eos, S::residual_molar_isochoric_heat_capacity, t, v, &m))
})
});
group.bench_function("partial_molar_volume", |b| {
b.iter(|| property_no_contributions((&eos, S::partial_molar_volume, t, v, &m)))
Expand Down Expand Up @@ -94,7 +96,9 @@ fn properties_pcsaft_polar(c: &mut Criterion) {
b.iter(|| property_no_contributions((&eos, S::ln_phi, t, v, &m)))
});
group.bench_function("c_v", |b| {
b.iter(|| property_no_contributions((&eos, S::c_v_res, t, v, &m)))
b.iter(|| {
property_no_contributions((&eos, S::residual_molar_isochoric_heat_capacity, t, v, &m))
})
});
group.bench_function("partial_molar_volume", |b| {
b.iter(|| property_no_contributions((&eos, S::partial_molar_volume, t, v, &m)))
Expand Down
16 changes: 15 additions & 1 deletion docs/api/eos.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,24 @@ If you want to adjust parameters of a model to experimental data you can use cla
EquationOfState.gc_pcsaft
EquationOfState.peng_robinson
EquationOfState.pets
EquationOfState.python
EquationOfState.python_residual
EquationOfState.python_ideal_gas
EquationOfState.uvtheory
EquationOfState.saftvrqmie
```

### Models defined in Python

```{eval-rst}
.. currentmodule:: feos.eos

.. autosummary::
:toctree: generated/

EquationOfState.python_residual
EquationOfState.python_ideal_gas
```

## Other data types

```{eval-rst}
Expand All @@ -34,6 +47,7 @@ If you want to adjust parameters of a model to experimental data you can use cla
Contributions
Verbosity
State
StateVec
PhaseEquilibrium
PhaseDiagram
```
Expand Down
1 change: 0 additions & 1 deletion docs/api/gc_pcsaft.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ from feos.gc_pcsaft import GcPcSaftParameters
Identifier
IdentifierOption
ChemicalRecord
JobackRecord
AssociationRecord
SegmentRecord
BinarySegmentRecord
Expand Down
33 changes: 33 additions & 0 deletions docs/api/ideal_gas.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# `feos.ideal_gas`

Utilities to build parameters for ideal gas models.

## Example: Combine the ideal gas model of Joback & Reid with PC-SAFT

```python
from feos.eos import EquationOfState
from feos.pcsaft import PcSaftParameters
from feos.ideal_gas import JobackParameters

pc_saft_parameters = PcSaftParameters.from_json(
['methane', 'ethane'],
'pc_saft_parameters.json'
)
joback_parameters = JobackParameters.from_json(
['methane', 'ethane'],
'joback_parameters.json'
)
eos = EquationOfState.pcsaft(pc_saft_parameters).joback(joback_parameters)
```

## Data types

```{eval-rst}
.. currentmodule:: feos.ideal_gas

.. autosummary::
:toctree: generated/

JobackRecord
JobackParameters
```
1 change: 1 addition & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
:maxdepth: 1

si
ideal_gas
eos
dft
```
Expand Down
1 change: 0 additions & 1 deletion docs/api/pcsaft.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ parameters = PcSaftParameters.from_json(['methane', 'ethane'], 'parameters.json'

Identifier
ChemicalRecord
JobackRecord
PureRecord
SegmentRecord
BinaryRecord
Expand Down
1 change: 0 additions & 1 deletion docs/api/peng_robinson.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

Identifier
ChemicalRecord
JobackRecord
PureRecord
BinaryRecord
PengRobinsonRecord
Expand Down
1 change: 0 additions & 1 deletion docs/api/pets.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

Identifier
ChemicalRecord
JobackRecord
PureRecord
BinaryRecord
PetsRecord
Expand Down
1 change: 0 additions & 1 deletion docs/api/saftvrqmie.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ parameters = SaftVRQMieParameters.from_json(['hydrogen', 'neon'], 'parameters.js

FeynmanHibbsOrder
Identifier
JobackRecord
PureRecord
BinaryRecord
SaftVRQMieRecord
Expand Down
31 changes: 12 additions & 19 deletions docs/theory/eos/properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ Due to different language paradigms, $\text{FeO}_\text{s}$ handles the ideal gas

| Name | definition | ideal gas model required? | residual? |
|-|:-:|-|-|
| Total molar weight $MW$ | $\sum_ix_iMW_i$ | no | no |
| Mass of each component $m_i$ | $n_iMW_i$ | no | no |
| Total mass $m$ | $\sum_im_i=nMW$ | no | no |
| Mass density $\rho^{(m)}$ | $\frac{m}{V}$ | no | no |
| Mass fractions $w_i$ | $\frac{m_i}{m}$ | no | no |
| Pressure $p$ | $-\left(\frac{\partial A}{\partial V}\right)_{T,n_i}$ | no | yes |
| Compressibility factor $Z$ | $\frac{pV}{nRT}$ | no | yes |
| Partial derivative of pressure w.r.t. volume | $\left(\frac{\partial p}{\partial V}\right)_{T,n_i}$ | no | yes |
Expand All @@ -85,15 +90,20 @@ Due to different language paradigms, $\text{FeO}_\text{s}$ handles the ideal gas
| Entropy $S$ | $-\left(\frac{\partial A}{\partial T}\right)_{V,n_i}$ | yes | yes |
| Partial derivative of the entropy w.r.t. temperature | $\left(\frac{\partial S}{\partial T}\right)_{V,n_i}$ | yes | yes |
| Second partial derivative of the entropy w.r.t. temperature | $\left(\frac{\partial^2 S}{\partial T^2}\right)_{V,n_i}$ | yes | yes |
| Molar entropy $s$ | $\frac{S}{n}$ | yes | yes
| Molar entropy $s$ | $\frac{S}{n}$ | yes | yes |
| Specific entropy $s^{(m)}$ | $\frac{S}{m}$ | yes | yes |
| Enthalpy $H$ | $A+TS+pV$ | yes | yes |
| Molar enthalpy $h$ | $\frac{H}{n}$ | yes | yes |
| Specific enthalpy $h^{(m)}$ | $\frac{H}{m}$ | yes | yes |
| Helmholtz energy $A$ | | yes | yes |
| Molar Helmholtz energy $a$ | $\frac{A}{n}$ | yes | yes |
| Specific Helmholtz energy $a^{(m)}$ | $\frac{A}{m}$ | yes | yes |
| Internal energy $U$ | $A+TS$ | yes | yes |
| Molar internal energy $u$ | $\frac{U}{n}$ | yes | yes |
| Specific internal energy $u^{(m)}$ | $\frac{U}{m}$ | yes | yes |
| Gibbs energy $G$ | $A+pV$ | yes | yes |
| Molar Gibbs energy $g$ | $\frac{G}{n}$ | yes | yes |
| Specific Gibbs energy $g^{(m)}$ | $\frac{G}{m}$ | yes | yes |
| Partial molar entropy $s_i$ | $\left(\frac{\partial S}{\partial n_i}\right)_{T,p,n_j}$ | yes | no |
| Partial molar enthalpy $h_i$ | $\left(\frac{\partial H}{\partial n_i}\right)_{T,p,n_j}$ | yes | no |
| Joule Thomson coefficient $\mu_\mathrm{JT}$ | $\left(\frac{\partial T}{\partial p}\right)_{H,n_i}$ | yes | no |
Expand All @@ -103,21 +113,4 @@ Due to different language paradigms, $\text{FeO}_\text{s}$ handles the ideal gas
| Thermal expansivity $\alpha_p$ | $-\frac{1}{V}\left(\frac{\partial V}{\partial T}\right)_{p,n_i}$ | yes | no |
| Grüneisen parameter $\phi$ | $V\left(\frac{\partial p}{\partial U}\right)_{V,n_i}=\frac{v}{c_v}\left(\frac{\partial p}{\partial T}\right)_{v,n_i}=\frac{\rho}{T}\left(\frac{\partial T}{\partial \rho}\right)_{s, n_i}$ | yes | no |
| (Static) structure factor $S(0)$ | $RT\left(\frac{\partial\rho}{\partial p}\right)_{T,n_i}$ | no | no |

## Additional properties for fluids with known molar weights

If the Helmholtz energy model includes information about the molar weigt $MW_i$ of each species, additional properties are available in $\text{FeO}_\text{s}$

| Name | definition | ideal gas model required? | residual? |
|-|:-:|-|-|
| Total molar weight $MW$ | $\sum_ix_iMW_i$ | no | no |
| Mass of each component $m_i$ | $n_iMW_i$ | no | no |
| Total mass $m$ | $\sum_im_i=nMW$ | no | no |
| Mass density $\rho^{(m)}$ | $\frac{m}{V}$ | no | no |
| Mass fractions $w_i$ | $\frac{m_i}{m}$ | no | no |
| Specific entropy $s^{(m)}$ | $\frac{S}{m}$ | yes | yes |
| Specific enthalpy $h^{(m)}$ | $\frac{H}{m}$ | yes | yes |
| Specific Helmholtz energy $a^{(m)}$ | $\frac{A}{m}$ | yes | yes |
| Specific internal energy $u^{(m)}$ | $\frac{U}{m}$ | yes | yes |
| Specific Gibbs energy $g^{(m)}$ | $\frac{G}{m}$ | yes | yes |
| Speed of sound $c$ | $\sqrt{\left(\frac{\partial p}{\partial\rho^{(m)}}\right)_{S,n_i}}$ | yes | no |
| Speed of sound $c$ | $\sqrt{\left(\frac{\partial p}{\partial\rho^{(m)}}\right)_{S,n_i}}$ | yes | no |
7 changes: 7 additions & 0 deletions feos-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `JobackParameters` struct that implements `Parameters` including Python bindings. [#158](https://github.com/feos-org/feos/pull/158)
- Added `Parameter::from_model_records` as a simpler interface to generate parameters. [#169](https://github.com/feos-org/feos/pull/169)
- Added optional `Phase` argument for constructors of dynamic properties of `DataSet`s. [#174](https://github.com/feos-org/feos/pull/174)
- Added `molar_weight` method to `Residual` trait. [#177](https://github.com/feos-org/feos/pull/158)
- Added molar versions for entropy, enthalpy, etc. for residual properties. [#177](https://github.com/feos-org/feos/pull/158)

### Changed
- Changed constructors of `Parameter` trait to return `Result`s. [#161](https://github.com/feos-org/feos/pull/161)
Expand All @@ -26,11 +28,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bubble and dew point iterations will not attempt a second iteration if no solution is found for the given initial pressure. [#166](https://github.com/feos-org/feos/pull/166)
- Made the binary records in the constructions and getters of the `Parameter` trait optional. [#169](https://github.com/feos-org/feos/pull/169)
- Changed the second argument of `new_binary` in Python from a `BinaryRecord` to the corresponding binary model record (analogous to the Rust implementation). [#169](https://github.com/feos-org/feos/pull/169)
- Renamed `c_v` and `c_p` to `isochoric_heat_capacity` and `isobaric_heat_capacity`, respectively, and added prefixes for molar and specific properties. [#177](https://github.com/feos-org/feos/pull/158)
- `State.helmholtz_energy_contributions` in Python now accepts optional `Contributions`. [#177](https://github.com/feos-org/feos/pull/158)
- Changed `StateVec` Python getters for entropy and enthalpy to functions that accept optional `Contributions`. [#177](https://github.com/feos-org/feos/pull/158)
- `PhaseDiagram.to_dict` in Python now accepts optional `Contributions` and includes mass specific properties. [#177](https://github.com/feos-org/feos/pull/158)

### Removed
- Removed `EquationOfState` trait. [#158](https://github.com/feos-org/feos/pull/158)
- Removed ideal gas dependencies from `PureRecord` and `SegmentRecord`. [#158](https://github.com/feos-org/feos/pull/158)
- Removed Python getter and setter functions and optional arguments for ideal gas records in macros. [#158](https://github.com/feos-org/feos/pull/158)
- Removed `MolarWeight` trait. [#177](https://github.com/feos-org/feos/pull/158)

### Fixed
- The vapor and liquid states in a bubble or dew point iteration are assigned correctly according to the inputs, rather than based on the mole density which can be incorrect for mixtures with large differences in molar weights. [#166](https://github.com/feos-org/feos/pull/166)
Expand Down
3 changes: 0 additions & 3 deletions feos-core/src/cubic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::equation_of_state::{Components, HelmholtzEnergy, HelmholtzEnergyDual,
use crate::parameter::{Identifier, Parameter, ParameterError, PureRecord};
use crate::si::{GRAM, MOL};
use crate::state::StateHD;
use crate::MolarWeight;
use ndarray::{Array1, Array2};
use num_dual::DualNum;
use quantity::si::SIArray1;
Expand Down Expand Up @@ -232,9 +231,7 @@ impl Residual for PengRobinson {
fn contributions(&self) -> &[Box<dyn HelmholtzEnergy>] {
&self.contributions
}
}

impl MolarWeight for PengRobinson {
fn molar_weight(&self) -> SIArray1 {
self.parameters.molarweight.clone() * GRAM / MOL
}
Expand Down
10 changes: 0 additions & 10 deletions feos-core/src/equation_of_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@ pub use helmholtz_energy::{HelmholtzEnergy, HelmholtzEnergyDual};
pub use ideal_gas::{DeBroglieWavelength, DeBroglieWavelengthDual, IdealGas};
pub use residual::{EntropyScaling, Residual};

/// Molar weight of all components.
///
/// The trait is required to be able to calculate (mass)
/// specific properties.
pub trait MolarWeight {
fn molar_weight(&self) -> SIArray1;
}

/// The number of components that the model is initialized for.
pub trait Components {
/// Return the number of components of the model.
Expand Down Expand Up @@ -80,9 +72,7 @@ impl<I: IdealGas, R: Residual> Residual for EquationOfState<I, R> {
fn contributions(&self) -> &[Box<dyn HelmholtzEnergy>] {
self.residual.contributions()
}
}

impl<I, R: MolarWeight> MolarWeight for EquationOfState<I, R> {
fn molar_weight(&self) -> SIArray1 {
self.residual.molar_weight()
}
Expand Down
5 changes: 5 additions & 0 deletions feos-core/src/equation_of_state/residual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ pub trait Residual: Components + Send + Sync {
/// of the equation of state.
fn contributions(&self) -> &[Box<dyn HelmholtzEnergy>];

/// Molar weight of all components.
///
/// Enables calculation of (mass) specific properties.
fn molar_weight(&self) -> SIArray1;

/// Evaluate the residual reduced Helmholtz energy $\beta A^\mathrm{res}$.
fn evaluate_residual<D: DualNum<f64> + Copy>(&self, state: &StateHD<D>) -> D
where
Expand Down
24 changes: 17 additions & 7 deletions feos-core/src/joback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,12 @@ impl Joback {
Self { parameters }
}

/// Directly calculates the ideal gas heat capacity from the Joback model.
pub fn c_p(&self, temperature: SINumber, molefracs: &Array1<f64>) -> EosResult<SINumber> {
/// Directly calculates the molar ideal gas heat capacity from the Joback model.
pub fn molar_isobaric_heat_capacity(
&self,
temperature: SINumber,
molefracs: &Array1<f64>,
) -> EosResult<SINumber> {
let t = temperature.to_reduced(SIUnit::reference_temperature())?;
let p = &self.parameters;
let c_p = (molefracs
Expand Down Expand Up @@ -255,6 +259,12 @@ mod tests {
fn contributions(&self) -> &[Box<dyn crate::HelmholtzEnergy>] {
&[]
}

fn molar_weight(&self) -> SIArray1 {
SIArray1::from_shape_fn(self.components(), |i| {
self.parameters.pure_records[i].molarweight * GRAM / MOL
})
}
}

#[test]
Expand Down Expand Up @@ -351,7 +361,7 @@ mod tests {
)?;
assert!(
(state
.c_p(Contributions::IdealGas)
.molar_isobaric_heat_capacity(Contributions::IdealGas)
.to_reduced(JOULE / MOL / KELVIN)?
- 224.6)
.abs()
Expand Down Expand Up @@ -384,12 +394,12 @@ mod tests {
.build()?;
println!(
"{} {}",
joback.c_p(temperature, &state.molefracs)?,
state.c_p(Contributions::IdealGas)
joback.molar_isobaric_heat_capacity(temperature, &state.molefracs)?,
state.molar_isobaric_heat_capacity(Contributions::IdealGas)
);
assert_relative_eq!(
joback.c_p(temperature, &state.molefracs)?,
state.c_p(Contributions::IdealGas),
joback.molar_isobaric_heat_capacity(temperature, &state.molefracs)?,
state.molar_isobaric_heat_capacity(Contributions::IdealGas),
max_relative = 1e-10
);
Ok(())
Expand Down
Loading