@@ -355,55 +355,60 @@ impl<U: EosUnit, E: EquationOfState> State<U, E> {
355355 ) ) ) ;
356356 }
357357 let x = partial_density
358- . map ( |pd| pd / pd. sum ( ) )
359- . or_else ( || moles. map ( |ms| ms / ms. sum ( ) ) ) ;
358+ . map ( |pd| pd. to_reduced ( pd. sum ( ) ) )
359+ . or_else ( || moles. map ( |ms| ms. to_reduced ( ms. sum ( ) ) ) )
360+ . transpose ( ) ?;
360361 let x_u = match ( x, molefracs, eos. components ( ) ) {
361362 ( Some ( _) , Some ( _) , _) => {
362363 return Err ( EosError :: UndeterminedState ( String :: from (
363364 "Composition is overdetermined." ,
364365 ) ) )
365366 }
366367 ( Some ( x) , None , _) => x,
367- ( None , Some ( x) , _) => x. clone ( ) . into ( ) ,
368- ( None , None , 1 ) => arr1 ( & [ 1.0 ] ) . into ( ) ,
368+ ( None , Some ( x) , _) => x. clone ( ) ,
369+ ( None , None , 1 ) => arr1 ( & [ 1.0 ] ) ,
369370 _ => {
370371 return Err ( EosError :: UndeterminedState ( String :: from (
371372 "Missing composition." ,
372373 ) ) )
373374 }
374375 } ;
375376
376- // If no extensive property is given, moles is set to reference moles.
377- // Therefore, moles and composition are known from this point on.
378- let n_t = n. unwrap_or_else ( U :: reference_moles) ;
379- let n_i = x_u * n_t;
380- let v = volume. or_else ( || rho. map ( |d| n_t / d) ) ;
377+ // If no extensive property is given, moles is set to the reference value.
378+ if let ( None , None ) = ( volume, n) {
379+ n = Some ( U :: reference_moles ( ) )
380+ }
381+ let n_i = n. map ( |n| & x_u * n) ;
382+ let v = volume. or_else ( || rho. and_then ( |d| n. map ( |n| n / d) ) ) ;
381383
382384 // check if new state can be created using default constructor
383- if let ( Some ( v) , Some ( t) ) = ( v, temperature) {
384- return State :: new_nvt ( eos, t, v, & n_i) ;
385+ if let ( Some ( v) , Some ( t) , Some ( n_i ) ) = ( v, temperature, & n_i ) {
386+ return State :: new_nvt ( eos, t, v, n_i) ;
385387 }
386388
387389 // Check if new state can be created using density iteration
388- if let ( Some ( p) , Some ( t) ) = ( pressure, temperature) {
389- return State :: new_npt ( eos, t, p, & n_i, density_initialization) ;
390+ if let ( Some ( p) , Some ( t) , Some ( n_i) ) = ( pressure, temperature, & n_i) {
391+ return State :: new_npt ( eos, t, p, n_i, density_initialization) ;
392+ }
393+ if let ( Some ( p) , Some ( t) , Some ( v) ) = ( pressure, temperature, v) {
394+ return State :: new_npvx ( eos, t, p, v, & x_u, density_initialization) ;
390395 }
391396
392397 // Check if new state can be created using molar_enthalpy and temperature
393- if let ( Some ( p) , Some ( h) ) = ( pressure, molar_enthalpy) {
394- return State :: new_nph ( eos, p, h, & n_i, density_initialization, initial_temperature) ;
398+ if let ( Some ( p) , Some ( h) , Some ( n_i ) ) = ( pressure, molar_enthalpy, & n_i ) {
399+ return State :: new_nph ( eos, p, h, n_i, density_initialization, initial_temperature) ;
395400 }
396- if let ( Some ( p) , Some ( s) ) = ( pressure, molar_entropy) {
397- return State :: new_nps ( eos, p, s, & n_i, density_initialization, initial_temperature) ;
401+ if let ( Some ( p) , Some ( s) , Some ( n_i ) ) = ( pressure, molar_entropy, & n_i ) {
402+ return State :: new_nps ( eos, p, s, n_i, density_initialization, initial_temperature) ;
398403 }
399- if let ( Some ( t) , Some ( h) ) = ( temperature, molar_enthalpy) {
400- return State :: new_nth ( eos, t, h, & n_i, density_initialization) ;
404+ if let ( Some ( t) , Some ( h) , Some ( n_i ) ) = ( temperature, molar_enthalpy, & n_i ) {
405+ return State :: new_nth ( eos, t, h, n_i, density_initialization) ;
401406 }
402- if let ( Some ( t) , Some ( s) ) = ( temperature, molar_entropy) {
403- return State :: new_nts ( eos, t, s, & n_i, density_initialization) ;
407+ if let ( Some ( t) , Some ( s) , Some ( n_i ) ) = ( temperature, molar_entropy, & n_i ) {
408+ return State :: new_nts ( eos, t, s, n_i, density_initialization) ;
404409 }
405- if let ( Some ( u) , Some ( v) ) = ( molar_internal_energy, volume) {
406- return State :: new_nvu ( eos, v, u, & n_i, initial_temperature) ;
410+ if let ( Some ( u) , Some ( v) , Some ( n_i ) ) = ( molar_internal_energy, volume, & n_i ) {
411+ return State :: new_nvu ( eos, v, u, n_i, initial_temperature) ;
407412 }
408413 Err ( EosError :: UndeterminedState ( String :: from (
409414 "Missing input parameters." ,
@@ -478,6 +483,21 @@ impl<U: EosUnit, E: EquationOfState> State<U, E> {
478483 }
479484 }
480485
486+ /// Return a new `State` for given pressure $p$, volume $V$, temperature $T$ and composition $x_i$.
487+ pub fn new_npvx (
488+ eos : & Rc < E > ,
489+ temperature : QuantityScalar < U > ,
490+ pressure : QuantityScalar < U > ,
491+ volume : QuantityScalar < U > ,
492+ molefracs : & Array1 < f64 > ,
493+ density_initialization : DensityInitialization < U > ,
494+ ) -> EosResult < Self > {
495+ let moles = molefracs * U :: reference_moles ( ) ;
496+ let state = Self :: new_npt ( eos, temperature, pressure, & moles, density_initialization) ?;
497+ let moles = state. partial_density * volume;
498+ Self :: new_nvt ( eos, temperature, volume, & moles)
499+ }
500+
481501 /// Return a new `State` for given pressure $p$ and molar enthalpy $h$.
482502 pub fn new_nph (
483503 eos : & Rc < E > ,
0 commit comments