From ebcd7024a7c65d10ec8dfa05f2dafaf4cb99c576 Mon Sep 17 00:00:00 2001 From: Philipp Rehner Date: Wed, 20 Sep 2023 18:01:42 +0200 Subject: [PATCH] Go back to eigenvalue calculation in num_dual --- feos-core/src/state/critical_point.rs | 39 ++++++--------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/feos-core/src/state/critical_point.rs b/feos-core/src/state/critical_point.rs index 72d34df9e..471dd37d6 100644 --- a/feos-core/src/state/critical_point.rs +++ b/feos-core/src/state/critical_point.rs @@ -3,8 +3,9 @@ use crate::equation_of_state::Residual; use crate::errors::{EosError, EosResult}; use crate::si::{Density, Moles, Pressure, Temperature, Volume}; use crate::{SolverOptions, Verbosity}; -use nalgebra::{DMatrix, DVector, SVector, SymmetricEigen}; -use ndarray::{arr1, Array1}; +use nalgebra::SVector; +use ndarray::{arr1, Array1, Array2}; +use num_dual::linalg::smallest_ev; use num_dual::{ first_derivative, try_first_derivative, try_jacobian, Dual, Dual3, Dual64, DualNum, DualSVec64, DualVec, HyperDual, @@ -436,7 +437,7 @@ fn critical_point_objective( // calculate second partial derivatives w.r.t. moles let t = HyperDual::from_re(temperature); let v = HyperDual::from_re(density.recip() * moles.sum()); - let qij = DMatrix::from_fn(eos.components(), eos.components(), |i, j| { + let qij = Array2::from_shape_fn((eos.components(), eos.components()), |(i, j)| { let mut m = moles.mapv(HyperDual::from); m[i].eps1 = DualSVec64::one(); m[j].eps2 = DualSVec64::one(); @@ -474,7 +475,7 @@ fn critical_point_objective_t( // calculate second partial derivatives w.r.t. moles let t = HyperDual::from(temperature); let v = HyperDual::from(1.0); - let qij = DMatrix::from_fn(eos.components(), eos.components(), |i, j| { + let qij = Array2::from_shape_fn((eos.components(), eos.components()), |(i, j)| { let mut m = density.map(HyperDual::from_re); m[i].eps1 = DualSVec64::one(); m[j].eps2 = DualSVec64::one(); @@ -509,7 +510,7 @@ fn critical_point_objective_p( // calculate second partial derivatives w.r.t. moles let t = HyperDual::from_re(temperature); let v = HyperDual::from(1.0); - let qij = DMatrix::from_fn(eos.components(), eos.components(), |i, j| { + let qij = Array2::from_shape_fn((eos.components(), eos.components()), |(i, j)| { let mut m = density.map(HyperDual::from_re); m[i].eps1 = DualSVec64::one(); m[j].eps2 = DualSVec64::one(); @@ -554,7 +555,7 @@ fn spinodal_objective( // calculate second partial derivatives w.r.t. moles let t = HyperDual::from_re(temperature); let v = HyperDual::from_re(density.recip() * moles.sum()); - let qij = DMatrix::from_fn(eos.components(), eos.components(), |i, j| { + let qij = Array2::from_shape_fn((eos.components(), eos.components()), |(i, j)| { let mut m = moles.mapv(HyperDual::from); m[i].eps1 = Dual64::one(); m[j].eps2 = Dual64::one(); @@ -563,35 +564,11 @@ fn spinodal_objective( }); // calculate smallest eigenvalue of q - let (eval, _) = smallest_ev_scalar(qij); + let (eval, _) = smallest_ev(qij); Ok(eval) } -fn smallest_ev( - m: DMatrix>, -) -> (DualSVec64, DVector>) { - let eig = SymmetricEigen::new(m); - let (e, ev) = eig - .eigenvalues - .iter() - .zip(eig.eigenvectors.column_iter()) - .reduce(|e1, e2| if e1.0 < e2.0 { e1 } else { e2 }) - .unwrap(); - (*e, ev.into()) -} - -fn smallest_ev_scalar(m: DMatrix) -> (Dual64, DVector) { - let eig = SymmetricEigen::new(m); - let (e, ev) = eig - .eigenvalues - .iter() - .zip(eig.eigenvectors.column_iter()) - .reduce(|e1, e2| if e1.0 < e2.0 { e1 } else { e2 }) - .unwrap(); - (*e, ev.into()) -} - fn kronecker(i: usize, j: usize) -> f64 { if i == j { 1.0