Source code for CADETProcess.fractionation.fractions
import numpy as np
from CADETProcess import CADETProcessError
from CADETProcess.dataStructure import Structure
from CADETProcess.dataStructure import (
UnsignedInteger, UnsignedFloat, Vector
)
[docs]
class Fraction(Structure):
"""A class representing a fraction of a mixture.
A fraction is defined by its mass and volume, and can be used to calculate
properties such as cumulative mass, purity, and concentration.
Attributes
----------
mass : np.ndarray
The mass of each component in the fraction. The array is 1-dimensional.
volume : float
The volume of the fraction.
"""
mass = Vector()
volume = UnsignedFloat()
def __init__(self, mass, volume):
"""Initialize a Fraction instance.
Parameters
----------
mass : numpy.ndarray
The mass of each component in the fraction.
The array should be 1-dimensional.
volume : float
The volume of the fraction.
"""
self.mass = mass
self.volume = volume
@property
def n_comp(self):
"""int: Number of components in the fraction."""
return self.mass.size
@property
def fraction_mass(self):
"""np.ndarray: Cumulative mass all species in the fraction.
See Also
--------
mass
purity
concentration
"""
return sum(self.mass)
@property
def purity(self):
"""np.ndarray: Purity of the fraction.
Invalid values are replaced by zero.
See Also
--------
mass
fraction_mass
concentration
"""
with np.errstate(divide='ignore', invalid='ignore'):
purity = self.mass / self.fraction_mass
return np.nan_to_num(purity)
@property
def concentration(self):
"""np.ndarray: Component concentrations of the fraction.
Invalid values are replaced by zero.
See Also
--------
mass
volume
"""
with np.errstate(divide='ignore', invalid='ignore'):
concentration = self.mass / self.volume
return np.nan_to_num(concentration)
def __repr__(self):
return \
f"{self.__class__.__name__}" \
f"(mass={self.mass},volume={self.volume})"
[docs]
class FractionPool(Structure):
"""Collection of pooled fractions.
This class manages multiple fractions of a mixture, facilitating the
calculation of cumulative properties of the pool, such as total volume,
total mass, average purity, and average concentration.
Attributes
----------
n_comp : int
The number of components each fraction in the pool should have.
See Also
--------
CADETProcess.fractionation.Fraction
CADETProcess.fractionation.Fractionator
"""
n_comp = UnsignedInteger()
def __init__(self, n_comp):
"""Initialize a FractionPool instance.
Parameters
----------
n_comp : int
The number of components each fraction in the pool should have.
"""
self._fractions = []
self.n_comp = n_comp
[docs]
def add_fraction(self, fraction):
"""Add a fraction to the fraction pool.
Parameters
----------
fraction : Fraction
The fraction to be added to the pool.
Raises
------
CADETProcessError
If the fraction is not an instance of the Fraction class, or if
the number of components in the fraction does not match the number
of components in the pool.
"""
if not isinstance(fraction, Fraction):
raise CADETProcessError('Expected Fraction')
if fraction.n_comp != self.n_comp:
raise CADETProcessError('Number of components does not match.')
self._fractions.append(fraction)
@property
def fractions(self):
"""list: List of fractions in the pool."""
if len(self._fractions) == 0:
return [Fraction(np.zeros((self.n_comp,)), 0)]
return self._fractions
@property
def n_fractions(self):
"""int: Number of fractions in the pool."""
return len(self._fractions)
@property
def volume(self):
"""float: Sum of all fraction volumes in the fraction pool."""
return sum(frac.volume for frac in self.fractions)
@property
def mass(self):
"""np.ndarray: Cumulative component mass in the fraction pool."""
return np.sum([frac.mass for frac in self.fractions], axis=0)
@property
def pool_mass(self):
"""float: Sum of cumulative component mass in the fraction pool."""
return sum(frac.fraction_mass for frac in self.fractions)
@property
def purity(self):
"""Total purity of components in the fraction pool.
Invalid values are replaced by zero.
Returns
-------
purity : np.ndarray
Purity of each component in the fraction pool.
See Also
--------
mass
pool_mass
concentration
"""
with np.errstate(divide='ignore', invalid='ignore'):
purity = self.mass / self.pool_mass
return np.nan_to_num(purity)
@property
def concentration(self):
"""Total concentration of components in the fraction pool.
Invalid values are replaced by zero.
Returns
-------
concentration : np.ndarray
Average concentration of the fraction pool.
See Also
--------
mass
volume
"""
with np.errstate(divide='ignore', invalid='ignore'):
concentration = self.mass / self.volume
return np.nan_to_num(concentration)
def __repr__(self):
return f"{self.__class__.__name__}(n_comp={self.n_comp})"