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
use super::{PhaseEquilibrium, SolverOptions};
use crate::equation_of_state::EquationOfState;
use crate::errors::EosResult;
use crate::state::{State, StateVec};
use crate::EosUnit;
use ndarray::prelude::*;
use quantity::QuantityScalar;
use std::rc::Rc;
pub struct PhaseDiagram<U, E> {
pub states: Vec<PhaseEquilibrium<U, E, 2>>,
}
impl<U: Clone, E> Clone for PhaseDiagram<U, E> {
fn clone(&self) -> Self {
Self {
states: self.states.clone(),
}
}
}
impl<U: EosUnit, E: EquationOfState> PhaseDiagram<U, E> {
pub fn pure(
eos: &Rc<E>,
min_temperature: QuantityScalar<U>,
npoints: usize,
critical_temperature: Option<QuantityScalar<U>>,
options: SolverOptions,
) -> EosResult<Self>
where
QuantityScalar<U>: std::fmt::Display + std::fmt::LowerExp,
{
let mut states = Vec::with_capacity(npoints);
let sc = State::critical_point(eos, None, critical_temperature, SolverOptions::default())?;
let max_temperature = min_temperature
+ (sc.temperature - min_temperature) * ((npoints - 2) as f64 / (npoints - 1) as f64);
let temperatures = Array::linspace(0.0, 1.0, npoints - 1)
.map(|&i| min_temperature + (max_temperature - min_temperature) * i);
let mut vle = None;
for &ti in temperatures.iter() {
vle = PhaseEquilibrium::pure(eos, ti, vle.as_ref(), options).ok();
if let Some(vle) = vle.as_ref() {
states.push(vle.clone());
}
}
states.push(PhaseEquilibrium::from_states(sc.clone(), sc));
Ok(PhaseDiagram { states })
}
pub fn vapor(&self) -> StateVec<'_, U, E> {
self.states.iter().map(|s| s.vapor()).collect()
}
pub fn liquid(&self) -> StateVec<'_, U, E> {
self.states.iter().map(|s| s.liquid()).collect()
}
}