feos_core/equation_of_state/
mod.rs1use 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
14pub trait Components {
16 fn components(&self) -> usize;
18
19 fn subset(&self, component_list: &[usize]) -> Self;
22}
23
24#[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 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 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}