feos_core/equation_of_state/
mod.rs

1use crate::EosResult;
2use ndarray::{Array1, ScalarOperand};
3use quantity::{
4    Diffusivity, MolarWeight, Moles, Temperature, ThermalConductivity, Viscosity, Volume,
5};
6use std::sync::Arc;
7
8mod ideal_gas;
9mod residual;
10
11pub use ideal_gas::IdealGas;
12pub use residual::{EntropyScaling, Molarweight, NoResidual, Residual};
13
14/// The number of components that the model is initialized for.
15pub trait Components {
16    /// Return the number of components of the model.
17    fn components(&self) -> usize;
18
19    /// Return a model consisting of the components
20    /// contained in component_list.
21    fn subset(&self, component_list: &[usize]) -> Self;
22}
23
24/// An equation of state consisting of an ideal gas model
25/// and a residual Helmholtz energy model.
26#[derive(Clone)]
27pub struct EquationOfState<I, R> {
28    pub ideal_gas: Arc<I>,
29    pub residual: Arc<R>,
30}
31
32impl<I, R> EquationOfState<I, R> {
33    /// Return a new [EquationOfState] with the given ideal gas
34    /// and residual models.
35    pub fn new(ideal_gas: Arc<I>, residual: Arc<R>) -> Self {
36        Self {
37            ideal_gas,
38            residual,
39        }
40    }
41}
42
43impl<I: IdealGas> EquationOfState<I, NoResidual> {
44    /// Return a new [EquationOfState] that only consists of
45    /// an ideal gas models.
46    pub fn ideal_gas(ideal_gas: Arc<I>) -> Self {
47        let residual = Arc::new(NoResidual(ideal_gas.components()));
48        Self {
49            ideal_gas,
50            residual,
51        }
52    }
53}
54
55impl<I: Components, R: Components> Components for EquationOfState<I, R> {
56    fn components(&self) -> usize {
57        assert_eq!(
58            self.residual.components(),
59            self.ideal_gas.components(),
60            "residual and ideal gas model differ in the number of components"
61        );
62        self.residual.components()
63    }
64
65    fn subset(&self, component_list: &[usize]) -> Self {
66        Self::new(
67            Arc::new(self.ideal_gas.subset(component_list)),
68            Arc::new(self.residual.subset(component_list)),
69        )
70    }
71}
72
73impl<I: IdealGas, R: Components + Sync + Send> IdealGas for EquationOfState<I, R> {
74    fn ln_lambda3<D: num_dual::DualNum<f64> + Copy>(&self, temperature: D) -> Array1<D> {
75        self.ideal_gas.ln_lambda3(temperature)
76    }
77
78    fn ideal_gas_model(&self) -> String {
79        self.ideal_gas.ideal_gas_model()
80    }
81}
82
83impl<I: IdealGas, R: Residual> Residual for EquationOfState<I, R> {
84    fn compute_max_density(&self, moles: &Array1<f64>) -> f64 {
85        self.residual.compute_max_density(moles)
86    }
87
88    fn residual_helmholtz_energy_contributions<D: num_dual::DualNum<f64> + Copy + ScalarOperand>(
89        &self,
90        state: &crate::StateHD<D>,
91    ) -> Vec<(String, D)> {
92        self.residual.residual_helmholtz_energy_contributions(state)
93    }
94}
95
96impl<I, R: Molarweight> Molarweight for EquationOfState<I, R> {
97    fn molar_weight(&self) -> MolarWeight<Array1<f64>> {
98        self.residual.molar_weight()
99    }
100}
101
102impl<I: IdealGas, R: Residual + EntropyScaling> EntropyScaling for EquationOfState<I, R> {
103    fn viscosity_reference(
104        &self,
105        temperature: Temperature,
106        volume: Volume,
107        moles: &Moles<Array1<f64>>,
108    ) -> EosResult<Viscosity> {
109        self.residual
110            .viscosity_reference(temperature, volume, moles)
111    }
112    fn viscosity_correlation(&self, s_res: f64, x: &Array1<f64>) -> EosResult<f64> {
113        self.residual.viscosity_correlation(s_res, x)
114    }
115    fn diffusion_reference(
116        &self,
117        temperature: Temperature,
118        volume: Volume,
119        moles: &Moles<Array1<f64>>,
120    ) -> EosResult<Diffusivity> {
121        self.residual
122            .diffusion_reference(temperature, volume, moles)
123    }
124    fn diffusion_correlation(&self, s_res: f64, x: &Array1<f64>) -> EosResult<f64> {
125        self.residual.diffusion_correlation(s_res, x)
126    }
127    fn thermal_conductivity_reference(
128        &self,
129        temperature: Temperature,
130        volume: Volume,
131        moles: &Moles<Array1<f64>>,
132    ) -> EosResult<ThermalConductivity> {
133        self.residual
134            .thermal_conductivity_reference(temperature, volume, moles)
135    }
136    fn thermal_conductivity_correlation(&self, s_res: f64, x: &Array1<f64>) -> EosResult<f64> {
137        self.residual.thermal_conductivity_correlation(s_res, x)
138    }
139}