-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathdual_numbers.rs
135 lines (126 loc) · 4.58 KB
/
dual_numbers.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! Benchmarks for the evaluation of the Helmholtz energy function
//! for a given `StateHD` for different types of dual numbers.
//! These should give an idea about the expected slow-down depending
//! on the dual number type used without the overhead of the `State`
//! creation.
use criterion::{criterion_group, criterion_main, Criterion};
use feos::pcsaft::{PcSaft, PcSaftParameters};
use feos_core::{
parameter::{IdentifierOption, Parameter},
Derivative, EquationOfState, HelmholtzEnergy, HelmholtzEnergyDual, State, StateHD,
};
use ndarray::{arr1, Array};
use num_dual::DualNum;
use quantity::si::*;
use std::sync::Arc;
/// Helper function to create a state for given parameters.
/// - temperature is 80% of critical temperature,
/// - volume is critical volume,
/// - molefracs (or moles) for equimolar mixture.
fn state_pcsaft(parameters: PcSaftParameters) -> State<PcSaft> {
let n = parameters.pure_records.len();
let eos = Arc::new(PcSaft::new(Arc::new(parameters)));
let moles = Array::from_elem(n, 1.0 / n as f64) * 10.0 * MOL;
let cp = State::critical_point(&eos, Some(&moles), None, Default::default()).unwrap();
let temperature = 0.8 * cp.temperature;
State::new_nvt(&eos, temperature, cp.volume, &moles).unwrap()
}
/// Residual Helmholtz energy given an equation of state and a StateHD.
fn a_res<D: DualNum<f64>, E: EquationOfState>(inp: (&Arc<E>, &StateHD<D>)) -> D
where
(dyn HelmholtzEnergy + 'static): HelmholtzEnergyDual<D>,
{
inp.0.evaluate_residual(inp.1)
}
/// Benchmark for evaluation of the Helmholtz energy for different dual number types.
fn bench_dual_numbers<E: EquationOfState>(c: &mut Criterion, group_name: &str, state: State<E>) {
let mut group = c.benchmark_group(group_name);
group.bench_function("a_f64", |b| {
b.iter(|| a_res((&state.eos, &state.derive0())))
});
group.bench_function("a_dual", |b| {
b.iter(|| a_res((&state.eos, &state.derive1(Derivative::DV))))
});
group.bench_function("a_dual2", |b| {
b.iter(|| a_res((&state.eos, &state.derive2(Derivative::DV))))
});
group.bench_function("a_hyperdual", |b| {
b.iter(|| {
a_res((
&state.eos,
&state.derive2_mixed(Derivative::DV, Derivative::DV),
))
})
});
group.bench_function("a_dual3", |b| {
b.iter(|| a_res((&state.eos, &state.derive3(Derivative::DV))))
});
}
/// Benchmark for the PC-SAFT equation of state
fn pcsaft(c: &mut Criterion) {
// methane
let parameters = PcSaftParameters::from_json(
vec!["methane"],
"./parameters/pcsaft/gross2001.json",
None,
IdentifierOption::Name,
)
.unwrap();
bench_dual_numbers(c, "dual_numbers_pcsaft_methane", state_pcsaft(parameters));
// water (4C, polar)
let parameters = PcSaftParameters::from_json(
vec!["water_4C_polar"],
"./parameters/pcsaft/rehner2020.json",
None,
IdentifierOption::Name,
)
.unwrap();
bench_dual_numbers(
c,
"dual_numbers_pcsaft_water_4c_polar",
state_pcsaft(parameters),
);
// methane, ethane, propane
let parameters = PcSaftParameters::from_json(
vec!["methane", "ethane", "propane"],
"./parameters/pcsaft/gross2001.json",
None,
IdentifierOption::Name,
)
.unwrap();
bench_dual_numbers(
c,
"dual_numbers_pcsaft_methane_ethane_propane",
state_pcsaft(parameters),
);
}
/// Benchmark for the PC-SAFT equation of state.
/// Binary system of methane and co2 used to model biogas.
fn methane_co2_pcsaft(c: &mut Criterion) {
let parameters = PcSaftParameters::from_multiple_json(
&[
(vec!["methane"], "./parameters/pcsaft/gross2001.json"),
(
vec!["carbon dioxide"],
"./parameters/pcsaft/gross2005_fit.json",
),
],
None,
IdentifierOption::Name,
)
.unwrap();
let k_ij = -0.0192211646;
let parameters =
PcSaftParameters::new_binary(parameters.pure_records, Some(k_ij.into())).unwrap();
let eos = Arc::new(PcSaft::new(Arc::new(parameters)));
// 230 K, 50 bar, x0 = 0.15
let temperature = 230.0 * KELVIN;
let density = 24.16896 * KILO * MOL / METER.powi(3);
let volume = 10.0 * MOL / density;
let x = arr1(&[0.15, 0.85]);
let moles = &x * 10.0 * MOL;
let state = State::new_nvt(&eos, temperature, volume, &moles).unwrap();
bench_dual_numbers(c, "dual_numbers_pcsaft_methane_co2", state);
}
criterion_group!(bench, pcsaft, methane_co2_pcsaft);
criterion_main!(bench);