1- use feos_core:: { Components , IdealGas , Residual , StateHD } ;
2- use nalgebra:: { Const , SVector , U1 } ;
3- use ndarray:: { Array1 , ScalarOperand , arr1} ;
4- use num_dual:: { Derivative , DualNum , DualVec } ;
5- use std:: sync:: Arc ;
1+ use std:: ops:: Deref ;
62
7- mod phase_equilibria;
3+ use nalgebra:: { Const , U1 } ;
4+ use num_dual:: { Derivative , DualNum , DualSVec } ;
5+
6+ // mod phase_equilibria;
87mod residual;
98mod state;
109mod total;
11- pub use phase_equilibria:: PhaseEquilibriumAD ;
12- pub use residual:: { ParametersAD , ResidualHelmholtzEnergy } ;
13- pub use state:: { Eigen , StateAD } ;
10+ // pub use phase_equilibria::PhaseEquilibriumAD;
11+ pub use residual:: ResidualHelmholtzEnergy ;
12+ pub use state:: { Eigen , PhaseEquilibriumAD , StateAD } ;
1413pub use total:: { EquationOfStateAD , IdealGasAD , TotalHelmholtzEnergy } ;
1514
16- /// Used internally to implement the [Residual] and [IdealGas] traits from FeOs.
17- pub struct FeOsWrapper < E , const N : usize > ( E ) ;
18-
19- impl < R : ParametersAD , const N : usize > Components for FeOsWrapper < R , N > {
20- fn components ( & self ) -> usize {
21- N
22- }
15+ /// A model that can be evaluated with derivatives of its parameters.
16+ pub trait ParametersAD : Sized + Deref < Target = Self :: Parameters < f64 > > {
17+ /// The type of the structure that stores the parameters internally.
18+ type Parameters < D : DualNum < f64 > + Copy > : Clone ;
2319
24- fn subset ( & self , _: & [ usize ] ) -> Self {
25- panic ! ( "Calculating properties of subsets of models is not possible with AD." )
26- }
27- }
20+ // /// Return a reference to the parameters.
21+ // fn params(&self) -> &Self::Parameters<f64>;
2822
29- impl < R : ResidualHelmholtzEnergy < N > , const N : usize > Residual for FeOsWrapper < R , N > {
30- fn compute_max_density ( & self , moles : & Array1 < f64 > ) -> f64 {
31- let total_moles = moles. sum ( ) ;
32- let molefracs = SVector :: from_fn ( |i, _| moles[ i] / total_moles) ;
33- self . 0 . compute_max_density ( & molefracs)
34- }
23+ /// Lift the parameters to the given type of dual number.
24+ fn params_from_inner < D : DualNum < f64 > + Copy , D2 : DualNum < f64 , Inner = D > + Copy > (
25+ parameters : & Self :: Parameters < D > ,
26+ ) -> Self :: Parameters < D2 > ;
3527
36- fn residual_helmholtz_energy_contributions < D : DualNum < f64 > + Copy + ScalarOperand > (
37- & self ,
38- state : & StateHD < D > ,
39- ) -> Vec < ( String , D ) > {
40- let temperature = state. temperature ;
41- let volume = state. volume ;
42- let density = SVector :: from_column_slice ( state. partial_density . as_slice ( ) . unwrap ( ) ) ;
43- let parameters = self . 0 . params ( ) ;
44- let a = R :: residual_helmholtz_energy_density ( & parameters, temperature, & density) * volume
45- / temperature;
46- vec ! [ ( R :: RESIDUAL . into( ) , a) ]
47- }
48- }
49-
50- impl < E : TotalHelmholtzEnergy < N > , const N : usize > IdealGas for FeOsWrapper < E , N > {
51- fn ln_lambda3 < D : DualNum < f64 > + Copy > ( & self , temperature : D ) -> Array1 < D > {
52- let parameters = self . 0 . params ( ) ;
53- arr1 ( & E :: ln_lambda3 ( & parameters, temperature) . data . 0 [ 0 ] )
28+ /// Wraps the model in the [HelmholtzEnergyWrapper] struct, so that it can be used
29+ /// as an argument to [StateAD](crate::StateAD) and [PhaseEquilibriumAD](crate::PhaseEquilibriumAD) constructors.
30+ fn wrap < ' a , const N : usize > ( & ' a self ) -> HelmholtzEnergyWrapper < ' a , Self , f64 , N > {
31+ HelmholtzEnergyWrapper {
32+ eos : self ,
33+ parameters : self ,
34+ }
5435 }
5536
56- fn ideal_gas_model ( & self ) -> String {
57- E :: IDEAL_GAS . into ( )
37+ /// Manually set the parameters and their derivatives.
38+ fn derivatives < ' a , D : DualNum < f64 > + Copy , const N : usize > (
39+ & ' a self ,
40+ parameters : & ' a Self :: Parameters < D > ,
41+ ) -> HelmholtzEnergyWrapper < ' a , Self , D , N > {
42+ HelmholtzEnergyWrapper {
43+ eos : self ,
44+ parameters,
45+ }
5846 }
5947}
6048
6149/// Struct that stores the reference to the equation of state together with the (possibly) dual parameters.
62- pub struct HelmholtzEnergyWrapper < E : ParametersAD , D : DualNum < f64 > + Copy , const N : usize > {
63- pub eos : Arc < FeOsWrapper < E , N > > ,
64- pub parameters : E :: Parameters < D > ,
50+ #[ derive( Copy ) ]
51+ pub struct HelmholtzEnergyWrapper < ' a , E : ParametersAD , D : DualNum < f64 > + Copy , const N : usize > {
52+ pub eos : & ' a E ,
53+ pub parameters : & ' a E :: Parameters < D > ,
6554}
6655
67- impl < E : ParametersAD , const N : usize > HelmholtzEnergyWrapper < E , f64 , N > {
68- /// Manually set the parameters and their derivatives.
69- pub fn derivatives < D : DualNum < f64 > + Copy > (
70- & self ,
71- parameters : E :: Parameters < D > ,
72- ) -> HelmholtzEnergyWrapper < E , D , N > {
73- HelmholtzEnergyWrapper {
74- eos : self . eos . clone ( ) ,
75- parameters,
56+ impl < ' a , E : ParametersAD , D : DualNum < f64 > + Copy , const N : usize > Clone
57+ for HelmholtzEnergyWrapper < ' a , E , D , N >
58+ {
59+ fn clone ( & self ) -> Self {
60+ Self {
61+ eos : self . eos ,
62+ parameters : self . parameters ,
7663 }
7764 }
7865}
@@ -84,19 +71,17 @@ pub trait NamedParameters: ParametersAD + for<'a> From<&'a [f64]> {
8471 parameters : & ' a mut Self :: Parameters < D > ,
8572 index : & str ,
8673 ) -> & ' a mut D ;
87- }
8874
89- impl < E : NamedParameters , const N : usize > HelmholtzEnergyWrapper < E , f64 , N > {
90- /// Initialize the parameters to calculate their derivatives.
91- pub fn named_derivatives < const P : usize > (
75+ /// Return the parameters with the appropriate derivatives.
76+ fn named_derivatives < const P : usize > (
9277 & self ,
9378 parameters : [ & str ; P ] ,
94- ) -> HelmholtzEnergyWrapper < E , DualVec < f64 , f64 , Const < P > > , N > {
95- let mut params: E :: Parameters < DualVec < f64 , f64 , Const < P > > > = self . eos . 0 . params ( ) ;
79+ ) -> Self :: Parameters < DualSVec < f64 , f64 , P > > {
80+ let mut params: Self :: Parameters < DualSVec < f64 , f64 , P > > = Self :: params_from_inner ( self ) ;
9681 for ( i, p) in parameters. into_iter ( ) . enumerate ( ) {
97- E :: index_parameters_mut ( & mut params, p) . eps =
82+ Self :: index_parameters_mut ( & mut params, p) . eps =
9883 Derivative :: derivative_generic ( Const :: < P > , U1 , i)
9984 }
100- self . derivatives ( params)
85+ params
10186 }
10287}
0 commit comments