Skip to content

Commit c42a197

Browse files
committed
Update num-dual dependency to 0.7 (#137)
1 parent 5dfbdc2 commit c42a197

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+611
-544
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: Test
22

33
on:
44
push:
5-
branches: [main]
5+
branches: [main, development]
66
pull_request:
7-
branches: [main]
7+
branches: [main, development]
88

99
env:
1010
CARGO_TERM_COLOR: always

.github/workflows/wheels.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: Build Wheels
22
on:
33
push:
4-
branches: [main]
4+
branches: [main, development]
55
pull_request:
6-
branches: [main]
6+
branches: [main, development]
77
jobs:
88
linux:
99
runs-on: ubuntu-latest

CHANGELOG.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
- Changed the internal implementation of the association contribution to accomodate more general association schemes. [#150](https://github.com/feos-org/feos/pull/150)
1010
- To comply with the new association implementation, the default values of `na` and `nb` are now `0` rather than `1`. Parameter files have been adapted accordingly. [#150](https://github.com/feos-org/feos/pull/150)
1111
- Added the possibility to specify a pure component correction parameter `phi` for the heterosegmented gc PC-SAFT equation of state. [#157](https://github.com/feos-org/feos/pull/157)
12-
13-
### Changed
1412
- 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)
1513

14+
### Packaging
15+
- Updated `num-dual` dependency to 0.7. [#137](https://github.com/feos-org/feos/pull/137)
16+
1617
## [0.4.3] - 2023-03-20
1718
- Python only: Release the changes introduced in `feos-core` 0.4.2.
1819

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ crate-type = ["rlib", "cdylib"]
2323

2424
[dependencies]
2525
quantity = "0.6"
26-
num-dual = "0.6"
26+
num-dual = "0.7"
2727
feos-core = { version = "0.4", path = "feos-core" }
2828
feos-dft = { version = "0.4", path = "feos-dft", optional = true }
2929
feos-derive = { version = "0.2", path = "feos-derive" }

benches/dual_numbers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn state_pcsaft(parameters: PcSaftParameters) -> State<PcSaft> {
2828
}
2929

3030
/// Residual Helmholtz energy given an equation of state and a StateHD.
31-
fn a_res<D: DualNum<f64>, E: EquationOfState>(inp: (&Arc<E>, &StateHD<D>)) -> D
31+
fn a_res<D: DualNum<f64> + Copy, E: EquationOfState>(inp: (&Arc<E>, &StateHD<D>)) -> D
3232
where
3333
(dyn HelmholtzEnergy + 'static): HelmholtzEnergyDual<D>,
3434
{

feos-core/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
### Changed
1313
- Changed constructors of `Parameter` trait to return `Result`s. [#161](https://github.com/feos-org/feos/pull/161)
1414

15+
### Packaging
16+
- Updated `num-dual` dependency to 0.7. [#137](https://github.com/feos-org/feos/pull/137)
17+
1518
## [0.4.2] - 2023-04-03
1619
### Fixed
1720
- Fixed a wrong reference state in the implementation of the Peng-Robinson equation of state. [#151](https://github.com/feos-org/feos/pull/151)

feos-core/Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ features = [ "rayon" ]
1919

2020
[dependencies]
2121
quantity = "0.6"
22-
num-dual = { version = "0.6", features = ["linalg"] }
22+
num-dual = { version = "0.7", features = ["linalg"] }
2323
ndarray = { version = "0.15", features = ["serde"] }
24+
nalgebra = "0.32"
2425
num-traits = "0.2"
2526
thiserror = "1.0"
2627
serde = { version = "1.0", features = ["derive"] }
@@ -37,4 +38,4 @@ approx = "0.4"
3738
[features]
3839
default = []
3940
rayon = ["dep:rayon", "ndarray/rayon"]
40-
python = ["pyo3", "numpy", "quantity/python", "num-dual/python", "rayon"]
41+
python = ["pyo3", "numpy", "quantity/python", "num-dual/python_macro", "rayon"]

feos-core/src/cubic.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct PengRobinsonContribution {
167167
parameters: Arc<PengRobinsonParameters>,
168168
}
169169

170-
impl<D: DualNum<f64>> HelmholtzEnergyDual<D> for PengRobinsonContribution {
170+
impl<D: DualNum<f64> + Copy> HelmholtzEnergyDual<D> for PengRobinsonContribution {
171171
fn helmholtz_energy(&self, state: &StateHD<D>) -> D {
172172
// temperature dependent a parameter
173173
let p = &self.parameters;

feos-core/src/equation_of_state.rs

+58-53
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use crate::state::StateHD;
33
use crate::EosUnit;
44
use ndarray::prelude::*;
55
use num_dual::{
6-
Dual, Dual2_64, Dual3, Dual3_64, Dual64, DualNum, DualVec64, HyperDual, HyperDual64,
6+
first_derivative, second_derivative, third_derivative, Dual, Dual2, Dual2_64, Dual3, Dual3_64,
7+
Dual64, DualNum, DualSVec64, HyperDual, HyperDual64,
78
};
8-
use num_traits::{One, Zero};
9+
use num_traits::Zero;
910
use quantity::si::{SIArray1, SINumber, SIUnit};
1011
use std::fmt;
1112

@@ -28,16 +29,17 @@ pub trait HelmholtzEnergyDual<D: DualNum<f64>> {
2829
pub trait HelmholtzEnergy:
2930
HelmholtzEnergyDual<f64>
3031
+ HelmholtzEnergyDual<Dual64>
31-
+ HelmholtzEnergyDual<Dual<DualVec64<3>, f64>>
32+
+ HelmholtzEnergyDual<Dual<DualSVec64<3>, f64>>
3233
+ HelmholtzEnergyDual<HyperDual64>
3334
+ HelmholtzEnergyDual<Dual2_64>
3435
+ HelmholtzEnergyDual<Dual3_64>
3536
+ HelmholtzEnergyDual<HyperDual<Dual64, f64>>
36-
+ HelmholtzEnergyDual<HyperDual<DualVec64<2>, f64>>
37-
+ HelmholtzEnergyDual<HyperDual<DualVec64<3>, f64>>
37+
+ HelmholtzEnergyDual<HyperDual<DualSVec64<2>, f64>>
38+
+ HelmholtzEnergyDual<HyperDual<DualSVec64<3>, f64>>
39+
+ HelmholtzEnergyDual<Dual2<Dual64, f64>>
3840
+ HelmholtzEnergyDual<Dual3<Dual64, f64>>
39-
+ HelmholtzEnergyDual<Dual3<DualVec64<2>, f64>>
40-
+ HelmholtzEnergyDual<Dual3<DualVec64<3>, f64>>
41+
+ HelmholtzEnergyDual<Dual3<DualSVec64<2>, f64>>
42+
+ HelmholtzEnergyDual<Dual3<DualSVec64<3>, f64>>
4143
+ fmt::Display
4244
+ Send
4345
+ Sync
@@ -47,16 +49,17 @@ pub trait HelmholtzEnergy:
4749
impl<T> HelmholtzEnergy for T where
4850
T: HelmholtzEnergyDual<f64>
4951
+ HelmholtzEnergyDual<Dual64>
50-
+ HelmholtzEnergyDual<Dual<DualVec64<3>, f64>>
52+
+ HelmholtzEnergyDual<Dual<DualSVec64<3>, f64>>
5153
+ HelmholtzEnergyDual<HyperDual64>
5254
+ HelmholtzEnergyDual<Dual2_64>
5355
+ HelmholtzEnergyDual<Dual3_64>
5456
+ HelmholtzEnergyDual<HyperDual<Dual64, f64>>
55-
+ HelmholtzEnergyDual<HyperDual<DualVec64<2>, f64>>
56-
+ HelmholtzEnergyDual<HyperDual<DualVec64<3>, f64>>
57+
+ HelmholtzEnergyDual<HyperDual<DualSVec64<2>, f64>>
58+
+ HelmholtzEnergyDual<HyperDual<DualSVec64<3>, f64>>
59+
+ HelmholtzEnergyDual<Dual2<Dual64, f64>>
5760
+ HelmholtzEnergyDual<Dual3<Dual64, f64>>
58-
+ HelmholtzEnergyDual<Dual3<DualVec64<2>, f64>>
59-
+ HelmholtzEnergyDual<Dual3<DualVec64<3>, f64>>
61+
+ HelmholtzEnergyDual<Dual3<DualSVec64<2>, f64>>
62+
+ HelmholtzEnergyDual<Dual3<DualSVec64<3>, f64>>
6063
+ fmt::Display
6164
+ Send
6265
+ Sync
@@ -70,7 +73,7 @@ impl<T> HelmholtzEnergy for T where
7073
/// the specific types in the supertraits of [IdealGasContribution]
7174
/// so that the implementor can be used as an ideal gas
7275
/// contribution in the equation of state.
73-
pub trait IdealGasContributionDual<D: DualNum<f64>> {
76+
pub trait IdealGasContributionDual<D: DualNum<f64> + Copy> {
7477
/// The thermal de Broglie wavelength of each component in the form $\ln\left(\frac{\Lambda^3}{\AA^3}\right)$
7578
fn de_broglie_wavelength(&self, temperature: D, components: usize) -> Array1<D>;
7679

@@ -101,39 +104,41 @@ pub trait IdealGasContributionDual<D: DualNum<f64>> {
101104
pub trait IdealGasContribution:
102105
IdealGasContributionDual<f64>
103106
+ IdealGasContributionDual<Dual64>
104-
+ IdealGasContributionDual<Dual<DualVec64<3>, f64>>
107+
+ IdealGasContributionDual<Dual<DualSVec64<3>, f64>>
105108
+ IdealGasContributionDual<HyperDual64>
106109
+ IdealGasContributionDual<Dual2_64>
107110
+ IdealGasContributionDual<Dual3_64>
108111
+ IdealGasContributionDual<HyperDual<Dual64, f64>>
109-
+ IdealGasContributionDual<HyperDual<DualVec64<2>, f64>>
110-
+ IdealGasContributionDual<HyperDual<DualVec64<3>, f64>>
112+
+ IdealGasContributionDual<HyperDual<DualSVec64<2>, f64>>
113+
+ IdealGasContributionDual<HyperDual<DualSVec64<3>, f64>>
114+
+ IdealGasContributionDual<Dual2<Dual64, f64>>
111115
+ IdealGasContributionDual<Dual3<Dual64, f64>>
112-
+ IdealGasContributionDual<Dual3<DualVec64<2>, f64>>
113-
+ IdealGasContributionDual<Dual3<DualVec64<3>, f64>>
116+
+ IdealGasContributionDual<Dual3<DualSVec64<2>, f64>>
117+
+ IdealGasContributionDual<Dual3<DualSVec64<3>, f64>>
114118
+ fmt::Display
115119
{
116120
}
117121

118122
impl<T> IdealGasContribution for T where
119123
T: IdealGasContributionDual<f64>
120124
+ IdealGasContributionDual<Dual64>
121-
+ IdealGasContributionDual<Dual<DualVec64<3>, f64>>
125+
+ IdealGasContributionDual<Dual<DualSVec64<3>, f64>>
122126
+ IdealGasContributionDual<HyperDual64>
123127
+ IdealGasContributionDual<Dual2_64>
124128
+ IdealGasContributionDual<Dual3_64>
125129
+ IdealGasContributionDual<HyperDual<Dual64, f64>>
126-
+ IdealGasContributionDual<HyperDual<DualVec64<2>, f64>>
127-
+ IdealGasContributionDual<HyperDual<DualVec64<3>, f64>>
130+
+ IdealGasContributionDual<HyperDual<DualSVec64<2>, f64>>
131+
+ IdealGasContributionDual<HyperDual<DualSVec64<3>, f64>>
132+
+ IdealGasContributionDual<Dual2<Dual64, f64>>
128133
+ IdealGasContributionDual<Dual3<Dual64, f64>>
129-
+ IdealGasContributionDual<Dual3<DualVec64<2>, f64>>
130-
+ IdealGasContributionDual<Dual3<DualVec64<3>, f64>>
134+
+ IdealGasContributionDual<Dual3<DualSVec64<2>, f64>>
135+
+ IdealGasContributionDual<Dual3<DualSVec64<3>, f64>>
131136
+ fmt::Display
132137
{
133138
}
134139

135140
struct DefaultIdealGasContribution;
136-
impl<D: DualNum<f64>> IdealGasContributionDual<D> for DefaultIdealGasContribution {
141+
impl<D: DualNum<f64> + Copy> IdealGasContributionDual<D> for DefaultIdealGasContribution {
137142
fn de_broglie_wavelength(&self, _: D, components: usize) -> Array1<D> {
138143
Array1::zeros(components)
139144
}
@@ -175,7 +180,7 @@ pub trait EquationOfState: Send + Sync {
175180
fn residual(&self) -> &[Box<dyn HelmholtzEnergy>];
176181

177182
/// Evaluate the residual reduced Helmholtz energy $\beta A^\mathrm{res}$.
178-
fn evaluate_residual<D: DualNum<f64>>(&self, state: &StateHD<D>) -> D
183+
fn evaluate_residual<D: DualNum<f64> + Copy>(&self, state: &StateHD<D>) -> D
179184
where
180185
dyn HelmholtzEnergy: HelmholtzEnergyDual<D>,
181186
{
@@ -187,7 +192,7 @@ pub trait EquationOfState: Send + Sync {
187192

188193
/// Evaluate the reduced Helmholtz energy of each individual contribution
189194
/// and return them together with a string representation of the contribution.
190-
fn evaluate_residual_contributions<D: DualNum<f64>>(
195+
fn evaluate_residual_contributions<D: DualNum<f64> + Copy>(
191196
&self,
192197
state: &StateHD<D>,
193198
) -> Vec<(String, D)>
@@ -252,12 +257,10 @@ pub trait EquationOfState: Send + Sync {
252257
) -> EosResult<SINumber> {
253258
let mr = self.validate_moles(moles)?;
254259
let x = mr.to_reduced(mr.sum())?;
255-
let mut rho = HyperDual64::zero();
256-
rho.eps1[0] = 1.0;
257-
rho.eps2[0] = 1.0;
258-
let t = HyperDual64::from(temperature.to_reduced(SIUnit::reference_temperature())?);
259-
let s = StateHD::new_virial(t, rho, x);
260-
Ok(self.evaluate_residual(&s).eps1eps2[(0, 0)] * 0.5 / SIUnit::reference_density())
260+
let t = temperature.to_reduced(SIUnit::reference_temperature())?;
261+
let a_res = |rho| self.evaluate_residual(&StateHD::new_virial(t.into(), rho, x));
262+
let (_, _, b) = second_derivative(a_res, 0.0);
263+
Ok(b * 0.5 / SIUnit::reference_density())
261264
}
262265

263266
/// Calculate the third virial coefficient $C(T)$
@@ -268,10 +271,10 @@ pub trait EquationOfState: Send + Sync {
268271
) -> EosResult<SINumber> {
269272
let mr = self.validate_moles(moles)?;
270273
let x = mr.to_reduced(mr.sum())?;
271-
let rho = Dual3_64::zero().derive();
272-
let t = Dual3_64::from(temperature.to_reduced(SIUnit::reference_temperature())?);
273-
let s = StateHD::new_virial(t, rho, x);
274-
Ok(self.evaluate_residual(&s).v3 / 3.0 / SIUnit::reference_density().powi(2))
274+
let t = temperature.to_reduced(SIUnit::reference_temperature())?;
275+
let a_res = |rho| self.evaluate_residual(&StateHD::new_virial(t.into(), rho, x));
276+
let (_, _, _, c) = third_derivative(a_res, 0.0);
277+
Ok(c / 3.0 / SIUnit::reference_density().powi(2))
275278
}
276279

277280
/// Calculate the temperature derivative of the second virial coefficient $B'(T)$
@@ -282,15 +285,16 @@ pub trait EquationOfState: Send + Sync {
282285
) -> EosResult<SINumber> {
283286
let mr = self.validate_moles(moles)?;
284287
let x = mr.to_reduced(mr.sum())?;
285-
let mut rho = HyperDual::zero();
286-
rho.eps1[0] = Dual64::one();
287-
rho.eps2[0] = Dual64::one();
288-
let t = HyperDual::from_re(
289-
Dual64::from(temperature.to_reduced(SIUnit::reference_temperature())?).derive(),
290-
);
291-
let s = StateHD::new_virial(t, rho, x);
292-
Ok(self.evaluate_residual(&s).eps1eps2[(0, 0)].eps[0] * 0.5
293-
/ (SIUnit::reference_density() * SIUnit::reference_temperature()))
288+
let t = temperature.to_reduced(SIUnit::reference_temperature())?;
289+
let b = |t| {
290+
let a_res = |rho: Dual2<Dual64, f64>| {
291+
self.evaluate_residual(&StateHD::new_virial(Dual2::from_re(t), rho, x))
292+
};
293+
let (_, _, b) = second_derivative(a_res, Dual64::zero());
294+
b
295+
};
296+
let (_, b_t) = first_derivative(b, t);
297+
Ok(b_t * 0.5 / (SIUnit::reference_density() * SIUnit::reference_temperature()))
294298
}
295299

296300
/// Calculate the temperature derivative of the third virial coefficient $C'(T)$
@@ -301,14 +305,15 @@ pub trait EquationOfState: Send + Sync {
301305
) -> EosResult<SINumber> {
302306
let mr = self.validate_moles(moles)?;
303307
let x = mr.to_reduced(mr.sum())?;
304-
let rho = Dual3::zero().derive();
305-
let t = Dual3::from_re(
306-
Dual64::from(temperature.to_reduced(SIUnit::reference_temperature())?).derive(),
307-
);
308-
let s = StateHD::new_virial(t, rho, x);
309-
Ok(self.evaluate_residual(&s).v3.eps[0]
310-
/ 3.0
311-
/ (SIUnit::reference_density().powi(2) * SIUnit::reference_temperature()))
308+
let t = temperature.to_reduced(SIUnit::reference_temperature())?;
309+
let c = |t| {
310+
let a_res =
311+
|rho| self.evaluate_residual(&StateHD::new_virial(Dual3::from_re(t), rho, x));
312+
let (_, _, _, c) = third_derivative(a_res, Dual64::zero());
313+
c
314+
};
315+
let (_, c_t) = first_derivative(c, t);
316+
Ok(c_t / 3.0 / (SIUnit::reference_density().powi(2) * SIUnit::reference_temperature()))
312317
}
313318
}
314319

feos-core/src/joback.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ const P0: f64 = 1.0e5;
107107
const A3: f64 = 1e-30;
108108
const KB: f64 = 1.38064852e-23;
109109

110-
impl<D: DualNum<f64>> IdealGasContributionDual<D> for Joback {
110+
impl<D: DualNum<f64> + Copy> IdealGasContributionDual<D> for Joback {
111111
fn de_broglie_wavelength(&self, temperature: D, components: usize) -> Array1<D> {
112112
let t = temperature;
113113
let t2 = t * t;

feos-core/src/python/user_defined.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -205,30 +205,36 @@ state!(PyStateF, f64, f64);
205205
helmholtz_energy!(PyStateF, f64, f64);
206206

207207
impl_dual_state_helmholtz_energy!(PyStateD, PyDual64, Dual64, f64);
208-
dual_number!(PyDualVec3, DualVec64<3>, f64);
208+
dual_number!(PyDualVec3, DualSVec64<3>, f64);
209209
impl_dual_state_helmholtz_energy!(
210210
PyStateDualDualVec3,
211211
PyDualDualVec3,
212-
Dual<DualVec64<3>, f64>,
212+
Dual<DualSVec64<3>, f64>,
213213
PyDualVec3
214214
);
215215
impl_dual_state_helmholtz_energy!(PyStateHD, PyHyperDual64, HyperDual64, f64);
216216
impl_dual_state_helmholtz_energy!(PyStateD2, PyDual2_64, Dual2_64, f64);
217217
impl_dual_state_helmholtz_energy!(PyStateD3, PyDual3_64, Dual3_64, f64);
218218
impl_dual_state_helmholtz_energy!(PyStateHDD, PyHyperDualDual64, HyperDual<Dual64, f64>, PyDual64);
219-
dual_number!(PyDualVec2, DualVec64<2>, f64);
219+
dual_number!(PyDualVec2, DualSVec64<2>, f64);
220220
impl_dual_state_helmholtz_energy!(
221221
PyStateHDDVec2,
222222
PyHyperDualVec2,
223-
HyperDual<DualVec64<2>, f64>,
223+
HyperDual<DualSVec64<2>, f64>,
224224
PyDualVec2
225225
);
226226
impl_dual_state_helmholtz_energy!(
227227
PyStateHDDVec3,
228228
PyHyperDualVec3,
229-
HyperDual<DualVec64<3>, f64>,
229+
HyperDual<DualSVec64<3>, f64>,
230230
PyDualVec3
231231
);
232+
impl_dual_state_helmholtz_energy!(
233+
PyStateD2D,
234+
PyDual2Dual64,
235+
Dual2<Dual64, f64>,
236+
PyDual64
237+
);
232238
impl_dual_state_helmholtz_energy!(
233239
PyStateD3D,
234240
PyDual3Dual64,
@@ -238,12 +244,12 @@ impl_dual_state_helmholtz_energy!(
238244
impl_dual_state_helmholtz_energy!(
239245
PyStateD3DVec2,
240246
PyDual3DualVec2,
241-
Dual3<DualVec64<2>, f64>,
247+
Dual3<DualSVec64<2>, f64>,
242248
PyDualVec2
243249
);
244250
impl_dual_state_helmholtz_energy!(
245251
PyStateD3DVec3,
246252
PyDual3DualVec3,
247-
Dual3<DualVec64<3>, f64>,
253+
Dual3<DualSVec64<3>, f64>,
248254
PyDualVec3
249255
);

0 commit comments

Comments
 (0)