Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
adjust dft
  • Loading branch information
prehner committed Feb 16, 2024
commit f45378d830af40d9a1590f01c6634516dec73af0
14 changes: 2 additions & 12 deletions feos-core/src/cubic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::equation_of_state::{Components, Residual};
use crate::parameter::{Identifier, Parameter, ParameterError, PureRecord};
use crate::si::{MolarWeight, GRAM, MOL};
use crate::state::StateHD;
use ndarray::{Array1, Array2};
use ndarray::{Array1, Array2, ScalarOperand};
use num_dual::DualNum;
use serde::{Deserialize, Serialize};
use std::f64::consts::SQRT_2;
Expand Down Expand Up @@ -146,16 +146,6 @@ impl Parameter for PengRobinsonParameters {
}
}

struct PengRobinsonContribution {
parameters: Arc<PengRobinsonParameters>,
}

impl fmt::Display for PengRobinsonContribution {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Peng Robinson")
}
}

/// A simple version of the Peng-Robinson equation of state.
pub struct PengRobinson {
/// Parameters
Expand Down Expand Up @@ -215,7 +205,7 @@ impl Residual for PengRobinson {
* ((v + b * n * (1.0 + SQRT_2)) / (v + b * n * (1.0 - SQRT_2))).ln())
}

fn residual_helmholtz_energy_contributions<D: DualNum<f64> + Copy>(
fn residual_helmholtz_energy_contributions<D: DualNum<f64> + Copy + ScalarOperand>(
&self,
state: &StateHD<D>,
) -> Vec<(String, D)> {
Expand Down
5 changes: 3 additions & 2 deletions feos-core/src/equation_of_state/ideal_gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use super::Components;
use crate::StateHD;
use ndarray::Array1;
use num_dual::DualNum;
use std::fmt::Display;

/// Ideal gas Helmholtz energy contribution.
pub trait IdealGas: Components + Sync + Send + Display {
pub trait IdealGas: Components + Sync + Send {
fn ln_lambda3<D: DualNum<f64> + Copy>(&self, temperature: D) -> Array1<D>;

fn ideal_gas_model(&self) -> String;

/// Evaluate the ideal gas Helmholtz energy contribution for a given state.
///
/// In some cases it could be advantageous to overwrite this
Expand Down
23 changes: 7 additions & 16 deletions feos-core/src/equation_of_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::{
si::{Diffusivity, MolarWeight, Moles, Temperature, ThermalConductivity, Viscosity, Volume},
EosResult,
};
use ndarray::Array1;
use std::{fmt::Display, sync::Arc};
use ndarray::{Array1, ScalarOperand};
use std::sync::Arc;

mod ideal_gas;
mod residual;
Expand Down Expand Up @@ -52,12 +52,6 @@ impl<I: IdealGas> EquationOfState<I, NoResidual> {
}
}

impl<I: IdealGas, R> Display for EquationOfState<I, R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.ideal_gas)
}
}

impl<I: Components, R: Components> Components for EquationOfState<I, R> {
fn components(&self) -> usize {
assert_eq!(
Expand All @@ -80,21 +74,18 @@ impl<I: IdealGas, R: Components + Sync + Send> IdealGas for EquationOfState<I, R
fn ln_lambda3<D: num_dual::DualNum<f64> + Copy>(&self, temperature: D) -> Array1<D> {
self.ideal_gas.ln_lambda3(temperature)
}

fn ideal_gas_model(&self) -> String {
self.ideal_gas.ideal_gas_model()
}
}

impl<I: IdealGas, R: Residual> Residual for EquationOfState<I, R> {
fn compute_max_density(&self, moles: &Array1<f64>) -> f64 {
self.residual.compute_max_density(moles)
}

fn residual_helmholtz_energy<D: num_dual::DualNum<f64> + Copy>(
&self,
state: &crate::StateHD<D>,
) -> D {
self.residual.residual_helmholtz_energy(state)
}

fn residual_helmholtz_energy_contributions<D: num_dual::DualNum<f64> + Copy>(
fn residual_helmholtz_energy_contributions<D: num_dual::DualNum<f64> + Copy + ScalarOperand>(
&self,
state: &crate::StateHD<D>,
) -> Vec<(String, D)> {
Expand Down
8 changes: 6 additions & 2 deletions feos-core/src/equation_of_state/residual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::si::*;
use crate::StateHD;
use crate::{EosError, EosResult};
use ndarray::prelude::*;
use ndarray::ScalarOperand;
use num_dual::*;
use num_traits::{One, Zero};
use std::ops::Div;
Expand All @@ -24,13 +25,16 @@ pub trait Residual: Components + Send + Sync {

/// Evaluate the reduced Helmholtz energy of each individual contribution
/// and return them together with a string representation of the contribution.
fn residual_helmholtz_energy_contributions<D: DualNum<f64> + Copy>(
fn residual_helmholtz_energy_contributions<D: DualNum<f64> + Copy + ScalarOperand>(
&self,
state: &StateHD<D>,
) -> Vec<(String, D)>;

/// Evaluate the residual reduced Helmholtz energy $\beta A^\mathrm{res}$.
fn residual_helmholtz_energy<D: DualNum<f64> + Copy>(&self, state: &StateHD<D>) -> D {
fn residual_helmholtz_energy<D: DualNum<f64> + Copy + ScalarOperand>(
&self,
state: &StateHD<D>,
) -> D {
self.residual_helmholtz_energy_contributions(state)
.iter()
.fold(D::zero(), |acc, (_, a)| acc + a)
Expand Down
11 changes: 4 additions & 7 deletions feos-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,18 +126,11 @@ mod tests {
use crate::EosResult;
use crate::StateBuilder;
use approx::*;
use std::fmt::Display;
use std::sync::Arc;

// Only to be able to instantiate an `EquationOfState`
struct NoIdealGas;

impl Display for NoIdealGas {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "NoIdealGas")
}
}

impl Components for NoIdealGas {
fn components(&self) -> usize {
1
Expand All @@ -155,6 +148,10 @@ mod tests {
) -> ndarray::prelude::Array1<D> {
unreachable!()
}

fn ideal_gas_model(&self) -> String {
"NoIdealGas".into()
}
}

fn pure_record_vec() -> Vec<PureRecord<PengRobinsonRecord>> {
Expand Down
2 changes: 1 addition & 1 deletion feos-core/src/parameter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ where
/// `pure_records`, the `Default` implementation of Self::Binary is used.
#[allow(clippy::expect_fun_call)]
fn binary_matrix_from_records(
pure_records: &Vec<PureRecord<Self::Pure>>,
pure_records: &[PureRecord<Self::Pure>],
binary_records: &[BinaryRecord<Identifier, Self::Binary>],
identifier_option: IdentifierOption,
) -> Option<Array2<Self::Binary>> {
Expand Down
2 changes: 1 addition & 1 deletion feos-core/src/state/properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ impl<E: Residual + IdealGas> State<E> {
let contributions = self.eos.residual_helmholtz_energy_contributions(&new_state);
let mut res = Vec::with_capacity(contributions.len() + 1);
res.push((
self.eos.to_string(),
self.eos.ideal_gas_model(),
MolarEnergy::from_reduced(
(self.eos.ideal_gas_helmholtz_energy(&new_state) * new_state.temperature).eps,
),
Expand Down
6 changes: 3 additions & 3 deletions feos-core/tests/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ fn from_records() -> Result<(), ParameterError> {
}
]
"#;
let pure_records = serde_json::from_str(pr_json).expect("Unable to parse json.");
let pure_records: Vec<_> = serde_json::from_str(pr_json).expect("Unable to parse json.");
let binary_records: Vec<_> = serde_json::from_str(br_json).expect("Unable to parse json.");
let binary_matrix = MyParameter::binary_matrix_from_records(
&pure_records,
Expand Down Expand Up @@ -201,7 +201,7 @@ fn from_records_missing_binary() -> Result<(), ParameterError> {
}
]
"#;
let pure_records = serde_json::from_str(pr_json).expect("Unable to parse json.");
let pure_records: Vec<_> = serde_json::from_str(pr_json).expect("Unable to parse json.");
let binary_records: Vec<_> = serde_json::from_str(br_json).expect("Unable to parse json.");
let binary_matrix = MyParameter::binary_matrix_from_records(
&pure_records,
Expand Down Expand Up @@ -266,7 +266,7 @@ fn from_records_correct_binary_order() -> Result<(), ParameterError> {
}
]
"#;
let pure_records = serde_json::from_str(pr_json).expect("Unable to parse json.");
let pure_records: Vec<_> = serde_json::from_str(pr_json).expect("Unable to parse json.");
let binary_records: Vec<_> = serde_json::from_str(br_json).expect("Unable to parse json.");
let binary_matrix = MyParameter::binary_matrix_from_records(
&pure_records,
Expand Down
5 changes: 3 additions & 2 deletions feos-derive/src/dft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fn impl_helmholtz_energy_functional(
let contributions = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional) => functional.contributions()
Self::#name(functional) => Box::new(functional.contributions().map(FunctionalContributionVariant::from))
}
});

Expand All @@ -121,6 +121,7 @@ fn impl_helmholtz_energy_functional(

Ok(quote! {
impl HelmholtzEnergyFunctional for FunctionalVariant {
type Contribution = FunctionalContributionVariant;
fn molecule_shape(&self) -> MoleculeShape {
match self {
#(#molecule_shape,)*
Expand All @@ -131,7 +132,7 @@ fn impl_helmholtz_energy_functional(
#(#compute_max_density,)*
}
}
fn contributions(&self) -> &[Box<dyn FunctionalContribution>] {
fn contributions(&self) -> Box<dyn Iterator<Item = FunctionalContributionVariant>> {
match self {
#(#contributions,)*
}
Expand Down
115 changes: 115 additions & 0 deletions feos-derive/src/functional_contribution.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use quote::quote;
use syn::{DeriveInput, Ident};

pub(crate) fn expand_functional_contribution(
input: DeriveInput,
) -> syn::Result<proc_macro2::TokenStream> {
let ident = input.ident;
let variants = match input.data {
syn::Data::Enum(syn::DataEnum { ref variants, .. }) => variants,
_ => panic!("this derive macro only works on enums"),
};

let functional_contribution = impl_functional_contribution(&ident, variants);
let display = impl_display(&ident, variants);
let from = impl_from(&ident, variants);
Ok(quote! {
#functional_contribution
#display
#from
})
}

fn impl_functional_contribution(
ident: &Ident,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) -> proc_macro2::TokenStream {
let weight_functions = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.weight_functions(temperature)
}
});
let weight_functions_pdgt = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.weight_functions_pdgt(temperature)
}
});
let helmholtz_energy_density = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.helmholtz_energy_density(temperature, weighted_densities)
}
});

quote! {
impl FunctionalContribution for #ident {
fn weight_functions<N: DualNum<f64> + Copy+ScalarOperand>(&self, temperature: N) -> WeightFunctionInfo<N> {
match self {
#(#weight_functions,)*
}
}
fn weight_functions_pdgt<N: DualNum<f64> + Copy+ScalarOperand>(&self, temperature: N) -> WeightFunctionInfo<N> {
match self {
#(#weight_functions_pdgt,)*
}
}
fn helmholtz_energy_density<N: DualNum<f64> + Copy+ScalarOperand>(
&self,
temperature: N,
weighted_densities: ArrayView2<N>,
) -> EosResult<Array1<N>> {
match self {
#(#helmholtz_energy_density,)*
}
}
}
}
}

fn impl_display(
ident: &Ident,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) -> proc_macro2::TokenStream {
let fmt = variants.iter().map(|v| {
let name = &v.ident;
quote! {
Self::#name(functional_contribution) => functional_contribution.fmt(f)
}
});

quote! {
impl std::fmt::Display for #ident {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
#(#fmt,)*
}
}
}
}
}

fn impl_from(
ident: &Ident,
variants: &syn::punctuated::Punctuated<syn::Variant, syn::token::Comma>,
) -> proc_macro2::TokenStream {
let from = variants.iter().map(|v| {
let name = &v.ident;
let syn::Fields::Unnamed(syn::FieldsUnnamed { unnamed, .. }) = &v.fields else {
panic!("All variants must be tuple structs!")
};
let inner = &unnamed.first().unwrap().ty;
quote! {
impl From<#inner> for #ident {
fn from(variant: #inner) -> Self {
Self::#name(variant)
}
}
}
});

quote! {
#(#from)*
}
}
Loading