@@ -34,14 +34,24 @@ pub enum DFTSpecification {
3434}
3535
3636impl DFTSpecification {
37- fn calculate_fugacity ( & self , z : & Array1 < f64 > ) -> FeosResult < Array1 < f64 > > {
38- Ok ( match self {
37+ fn calculate_fugacity ( & self , z : & Array1 < f64 > ) -> Array1 < f64 > {
38+ match self {
3939 Self :: ChemicalPotential ( fugacity) => fugacity. clone ( ) ,
4040 Self :: Moles ( moles) => moles / z,
4141 Self :: TotalMoles ( total_moles, fugacity) => {
4242 fugacity * * total_moles / ( fugacity * z) . sum ( )
4343 }
44- } )
44+ }
45+ }
46+
47+ pub ( crate ) fn delta_fugacity ( & self , z : & Array1 < f64 > , delta_z : & Array1 < f64 > ) -> Array1 < f64 > {
48+ match self {
49+ Self :: ChemicalPotential ( fugacity) => Array1 :: zeros ( fugacity. len ( ) ) ,
50+ Self :: Moles ( _) => -delta_z / z,
51+ Self :: TotalMoles ( _, fugacity) => {
52+ -( fugacity * delta_z) . sum ( ) / ( fugacity * z) . sum ( ) * Array1 :: ones ( fugacity. len ( ) )
53+ }
54+ }
4555 }
4656
4757 pub fn from_state < F : HelmholtzEnergyFunctional > ( state : & State < F > ) -> Self {
@@ -216,7 +226,7 @@ where
216226 profile. sum ( ) * functional_determinant
217227 }
218228
219- fn integrate_reduced_comp < S : Data < Elem = N > , N : DualNum < Primitive = f64 > + Copy > (
229+ pub ( crate ) fn integrate_reduced_comp < S : Data < Elem = N > , N : DualNum < Primitive = f64 > + Copy > (
220230 & self ,
221231 profile : & ArrayBase < S , D :: Larger > ,
222232 ) -> Array1 < N > {
@@ -320,15 +330,20 @@ where
320330
321331 pub fn residual ( & self , log : bool ) -> FeosResult < ( Array < f64 , D :: Larger > , f64 ) > {
322332 let density = self . density . to_reduced ( ) ;
323- let ( res, res_norm, _, _) = self . euler_lagrange_equation ( & density, log) ?;
333+ let ( res, res_norm, _, _, _ ) = self . euler_lagrange_equation ( & density, log) ?;
324334 Ok ( ( res, res_norm) )
325335 }
326336
327337 #[ expect( clippy:: type_complexity) ]
328338 fn fugacity (
329339 & self ,
330340 density : & Array < f64 , D :: Larger > ,
331- ) -> FeosResult < ( Array < f64 , D :: Larger > , Array < f64 , D :: Larger > , Array1 < f64 > ) > {
341+ ) -> FeosResult < (
342+ Array < f64 , D :: Larger > ,
343+ Array1 < f64 > ,
344+ Array < f64 , D :: Larger > ,
345+ Array1 < f64 > ,
346+ ) > {
332347 // calculate reduced temperature
333348 let temperature = self . temperature . to_reduced ( ) ;
334349
@@ -352,14 +367,21 @@ where
352367 . bulk
353368 . eos
354369 . bond_integrals ( temperature, & exp_dfdrho, self . convolver . as_ref ( ) ) ;
355- let z = & exp_dfdrho * bonds;
370+ let mut rho_projected = & exp_dfdrho * bonds;
371+ let z = self . integrate_reduced_comp ( & rho_projected) ;
356372
357373 // calculate fugacity based on the given specification
358- let fugacity = self
359- . specification
360- . calculate_fugacity ( & self . integrate_reduced_comp ( & z) ) ?;
374+ let fugacity = self . specification . calculate_fugacity ( & z) ;
375+
376+ // multiply fugacity
377+ rho_projected
378+ . outer_iter_mut ( )
379+ . zip ( fugacity. iter ( ) )
380+ . for_each ( |( mut x, & f) | {
381+ x *= f;
382+ } ) ;
361383
362- Ok ( ( exp_dfdrho, z, fugacity) )
384+ Ok ( ( exp_dfdrho, z, rho_projected , fugacity) )
363385 }
364386
365387 #[ expect( clippy:: type_complexity) ]
@@ -371,18 +393,11 @@ where
371393 Array < f64 , D :: Larger > ,
372394 f64 ,
373395 Array < f64 , D :: Larger > ,
396+ Array1 < f64 > ,
374397 Array < f64 , D :: Larger > ,
375398 ) > {
376399 // calculate functional derivatives and fugacity
377- let ( exp_dfdrho, mut rho_projected, fugacity) = self . fugacity ( density) ?;
378-
379- // multiply fugacity
380- rho_projected
381- . outer_iter_mut ( )
382- . zip ( fugacity. iter ( ) )
383- . for_each ( |( mut x, & f) | {
384- x *= f;
385- } ) ;
400+ let ( exp_dfdrho, z, rho_projected, _) = self . fugacity ( density) ?;
386401
387402 // calculate residual
388403 let mut res = if log {
@@ -402,7 +417,7 @@ where
402417 ( density - & rho_projected) . mapv ( |x| x * x) . sum ( ) . sqrt ( ) / ( res. len ( ) as f64 ) . sqrt ( ) ;
403418
404419 if res_norm. is_finite ( ) {
405- Ok ( ( res, res_norm, exp_dfdrho, rho_projected) )
420+ Ok ( ( res, res_norm, exp_dfdrho, z , rho_projected) )
406421 } else {
407422 Err ( FeosError :: IterationFailed ( "Euler-Lagrange equation" . into ( ) ) )
408423 }
@@ -423,7 +438,7 @@ where
423438 // solve a bulk profile with the Newton solver
424439 let mut bulk_profile =
425440 DFTProfile :: < Ix0 , _ > :: new ( Grid :: Bulk , & self . bulk , None , None , None ) ;
426- let ( _, _, fugacity) = self . fugacity ( & density) ?;
441+ let ( _, _, _ , fugacity) = self . fugacity ( & density) ?;
427442 bulk_profile. specification = DFTSpecification :: ChemicalPotential ( fugacity) ;
428443 let solver = DFTSolver :: new ( None ) . newton ( None , None , None , None ) ;
429444 bulk_profile. solve ( Some ( & solver) , false ) ?;
0 commit comments