Skip to content
This repository was archived by the owner on Jul 28, 2022. It is now read-only.

Commit 8d63e8d

Browse files
authored
Merge pull request #13 from feos-org/pore_volume
Add calculation of reference pore volumes
2 parents 4eeeb7c + f2453e6 commit 8d63e8d

File tree

6 files changed

+101
-31
lines changed

6 files changed

+101
-31
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Added
9+
- The pore volume using Helium at 298 K as reference is now directly accesible from `Pore1D` and `Pore3D`. [#12](https://github.com/feos-org/feos-core/pull/12)
810

911
## [0.1.1] - 2022-02-14
1012
### Added

examples/FundamentalMeasureTheory.ipynb

Lines changed: 11 additions & 11 deletions
Large diffs are not rendered by default.

src/adsorption/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ where
5555
})
5656
}
5757

58-
fn equilibrium<D: Dimension, F: HelmholtzEnergyFunctional>(
58+
fn equilibrium<D: Dimension, F: HelmholtzEnergyFunctional + FluidParameters>(
5959
&self,
6060
equilibrium: &Adsorption<U, D, F>,
6161
) -> EosResult<(QuantityArray1<U>, QuantityArray1<U>)>
@@ -111,12 +111,12 @@ pub type Adsorption1D<U, F> = Adsorption<U, Ix1, F>;
111111
/// Container structure for adsorption isotherms in 3D pores.
112112
pub type Adsorption3D<U, F> = Adsorption<U, Ix3, F>;
113113

114-
impl<U: EosUnit, D: Dimension, F: HelmholtzEnergyFunctional> Adsorption<U, D, F>
114+
impl<U: EosUnit, D: Dimension, F: HelmholtzEnergyFunctional + FluidParameters> Adsorption<U, D, F>
115115
where
116116
QuantityScalar<U>: std::fmt::Display,
117117
D::Larger: Dimension<Smaller = D>,
118118
{
119-
fn new<S: PoreSpecification<U, D, F>>(
119+
fn new<S: PoreSpecification<U, D>>(
120120
functional: &Rc<DFT<F>>,
121121
pore: &S,
122122
profiles: Vec<EosResult<PoreProfile<U, D, F>>>,
@@ -129,7 +129,7 @@ where
129129
}
130130

131131
/// Calculate an adsorption isotherm (starting at low pressure)
132-
pub fn adsorption_isotherm<S: PoreSpecification<U, D, F>>(
132+
pub fn adsorption_isotherm<S: PoreSpecification<U, D>>(
133133
functional: &Rc<DFT<F>>,
134134
temperature: QuantityScalar<U>,
135135
pressure: &PressureSpecification<U>,
@@ -142,7 +142,7 @@ where
142142
}
143143

144144
/// Calculate an desorption isotherm (starting at high pressure)
145-
pub fn desorption_isotherm<S: PoreSpecification<U, D, F>>(
145+
pub fn desorption_isotherm<S: PoreSpecification<U, D>>(
146146
functional: &Rc<DFT<F>>,
147147
temperature: QuantityScalar<U>,
148148
pressure: &PressureSpecification<U>,
@@ -162,7 +162,7 @@ where
162162
}
163163

164164
/// Calculate an equilibrium isotherm
165-
pub fn equilibrium_isotherm<S: PoreSpecification<U, D, F>>(
165+
pub fn equilibrium_isotherm<S: PoreSpecification<U, D>>(
166166
functional: &Rc<DFT<F>>,
167167
temperature: QuantityScalar<U>,
168168
pressure: &PressureSpecification<U>,
@@ -241,7 +241,7 @@ where
241241
}
242242
}
243243

244-
fn isotherm<S: PoreSpecification<U, D, F>>(
244+
fn isotherm<S: PoreSpecification<U, D>>(
245245
functional: &Rc<DFT<F>>,
246246
temperature: QuantityScalar<U>,
247247
pressure: &QuantityArray1<U>,
@@ -291,7 +291,7 @@ where
291291
}
292292

293293
/// Calculate the phase transition from an empty to a filled pore.
294-
pub fn phase_equilibrium<S: PoreSpecification<U, D, F>>(
294+
pub fn phase_equilibrium<S: PoreSpecification<U, D>>(
295295
functional: &Rc<DFT<F>>,
296296
temperature: QuantityScalar<U>,
297297
p_min: QuantityScalar<U>,

src/adsorption/pore.rs

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
use crate::adsorption::{ExternalPotential, FluidParameters};
22
use crate::convolver::ConvolverFFT;
33
use crate::functional::{HelmholtzEnergyFunctional, DFT};
4+
use crate::functional_contribution::FunctionalContribution;
45
use crate::geometry::{Axis, AxisGeometry, Grid};
56
use crate::profile::{DFTProfile, CUTOFF_RADIUS, MAX_POTENTIAL};
67
use crate::solver::DFTSolver;
7-
use feos_core::{Contributions, EosResult, EosUnit, State};
8+
use feos_core::{Contributions, EosResult, EosUnit, State, StateBuilder};
89
use ndarray::prelude::*;
910
use ndarray::Axis as Axis_nd;
1011
use ndarray::Zip;
1112
use ndarray_stats::QuantileExt;
1213
use quantity::{QuantityArray2, QuantityScalar};
14+
use std::rc::Rc;
1315

1416
const POTENTIAL_OFFSET: f64 = 2.0;
1517
const DEFAULT_GRID_POINTS: usize = 2048;
@@ -76,16 +78,36 @@ impl<U> Pore3D<U> {
7678
}
7779

7880
/// Trait for the generic implementation of adsorption applications.
79-
pub trait PoreSpecification<U, D: Dimension, F> {
81+
pub trait PoreSpecification<U: EosUnit, D: Dimension> {
8082
/// Initialize a new single pore.
81-
fn initialize(
83+
fn initialize<F: HelmholtzEnergyFunctional + FluidParameters>(
8284
&self,
8385
bulk: &State<U, DFT<F>>,
8486
external_potential: Option<&Array<f64, D::Larger>>,
8587
) -> EosResult<PoreProfile<U, D, F>>;
8688

8789
/// Return the number of spatial dimensions of the pore.
8890
fn dimension(&self) -> i32;
91+
92+
/// Return the pore volume using Helium at 298 K as reference.
93+
fn pore_volume(&self) -> EosResult<QuantityScalar<U>>
94+
where
95+
D::Larger: Dimension<Smaller = D>,
96+
{
97+
let bulk = StateBuilder::new(&Rc::new(Helium::new()))
98+
.temperature(298.0 * U::reference_temperature())
99+
.volume(U::reference_volume())
100+
.build()?;
101+
let pore = self.initialize(&bulk, None)?;
102+
let pot = pore
103+
.profile
104+
.external_potential
105+
.index_axis(Axis(0), 0)
106+
.mapv(|v| (-v).exp())
107+
* U::reference_temperature()
108+
/ U::reference_temperature();
109+
Ok(pore.profile.integrate(&pot))
110+
}
89111
}
90112

91113
/// Density profile and properties of a confined system in arbitrary dimensions.
@@ -149,10 +171,8 @@ where
149171
}
150172
}
151173

152-
impl<U: EosUnit, F: HelmholtzEnergyFunctional + FluidParameters> PoreSpecification<U, Ix1, F>
153-
for Pore1D<U>
154-
{
155-
fn initialize(
174+
impl<U: EosUnit> PoreSpecification<U, Ix1> for Pore1D<U> {
175+
fn initialize<F: HelmholtzEnergyFunctional + FluidParameters>(
156176
&self,
157177
bulk: &State<U, DFT<F>>,
158178
external_potential: Option<&Array2<f64>>,
@@ -203,10 +223,8 @@ impl<U: EosUnit, F: HelmholtzEnergyFunctional + FluidParameters> PoreSpecificati
203223
}
204224
}
205225

206-
impl<U: EosUnit, F: HelmholtzEnergyFunctional + FluidParameters> PoreSpecification<U, Ix3, F>
207-
for Pore3D<U>
208-
{
209-
fn initialize(
226+
impl<U: EosUnit> PoreSpecification<U, Ix3> for Pore3D<U> {
227+
fn initialize<F: HelmholtzEnergyFunctional + FluidParameters>(
210228
&self,
211229
bulk: &State<U, DFT<F>>,
212230
external_potential: Option<&Array4<f64>>,
@@ -420,3 +438,47 @@ fn calculate_distance2(
420438
rx.powi(2) + ry.powi(2) + rz.powi(2)
421439
})
422440
}
441+
442+
const EPSILON_HE: f64 = 10.9;
443+
const SIGMA_HE: f64 = 2.64;
444+
445+
struct Helium {
446+
epsilon: Array1<f64>,
447+
sigma: Array1<f64>,
448+
}
449+
450+
impl Helium {
451+
fn new() -> DFT<Self> {
452+
let epsilon = arr1(&[EPSILON_HE]);
453+
let sigma = arr1(&[SIGMA_HE]);
454+
DFT::new_homosegmented(Self { epsilon, sigma }, &Array1::ones(1))
455+
}
456+
}
457+
458+
impl HelmholtzEnergyFunctional for Helium {
459+
fn contributions(&self) -> &[Box<dyn FunctionalContribution>] {
460+
&[]
461+
}
462+
463+
fn subset(&self, _: &[usize]) -> DFT<Self> {
464+
Self::new()
465+
}
466+
467+
fn compute_max_density(&self, _: &Array1<f64>) -> f64 {
468+
1.0
469+
}
470+
}
471+
472+
impl FluidParameters for Helium {
473+
fn epsilon_k_ff(&self) -> Array1<f64> {
474+
self.epsilon.clone()
475+
}
476+
477+
fn sigma_ff(&self) -> &Array1<f64> {
478+
&self.sigma
479+
}
480+
481+
fn m(&self) -> Array1<f64> {
482+
arr1(&[1.0])
483+
}
484+
}

src/python/adsorption/external_potential.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ impl PyExternalPotential {
222222
/// Returns
223223
/// -------
224224
/// Geometry
225-
#[pyclass(name = "Geometry", unsendable)]
225+
#[pyclass(name = "Geometry")]
226226
#[derive(Clone)]
227227
pub struct PyGeometry(pub AxisGeometry);
228228

src/python/adsorption/pore.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ macro_rules! impl_pore {
7474
external_potential.map(|e| e.to_owned_array()).as_ref(),
7575
)?))
7676
}
77+
78+
/// The pore volume using Helium at 298 K as reference.
79+
#[getter]
80+
fn get_pore_volume(&self) -> PyResult<PySINumber> {
81+
Ok(self.0.pore_volume()?.into())
82+
}
7783
}
7884

7985
#[pymethods]

0 commit comments

Comments
 (0)