///|
/// Calculate the distribution coefficient `K_D = y / x`.
pub fn distribution_coefficient(
raffinate_concentration : Double,
extract_concentration : Double,
) -> Double raise @domain.ExtractionError {
@domain.require_positive("raffinate concentration", raffinate_concentration)
@domain.require_non_negative("extract concentration", extract_concentration)
extract_concentration / raffinate_concentration
}
///|
/// Calculate separation selectivity `(y_a/x_a) / (y_b/x_b)`.
pub fn selectivity(
solute_a_raffinate~ : Double,
solute_a_extract~ : Double,
solute_b_raffinate~ : Double,
solute_b_extract~ : Double,
) -> Double raise @domain.ExtractionError {
let k_a = distribution_coefficient(solute_a_raffinate, solute_a_extract)
let k_b = distribution_coefficient(solute_b_raffinate, solute_b_extract)
if k_b <= 0.0 {
raise @domain.ExtractionError::SingularBalance(
context="reference solute has zero distribution coefficient",
)
}
k_a / k_b
}
///|
pub fn extraction_factor(
distribution~ : Double,
solvent_flow~ : Double,
carrier_flow~ : Double,
) -> Double raise @domain.ExtractionError {
@domain.require_non_negative("distribution coefficient", distribution)
@domain.require_positive("solvent flow", solvent_flow)
@domain.require_positive("carrier flow", carrier_flow)
distribution * solvent_flow / carrier_flow
}
///|
pub fn recovery_fraction(
inlet_solute : Double,
raffinate_solute : Double,
) -> Double raise @domain.ExtractionError {
@domain.require_positive("inlet solute", inlet_solute)
@domain.require_non_negative("raffinate solute", raffinate_solute)
if raffinate_solute > inlet_solute {
raise @domain.ExtractionError::InvalidArgument(
message="raffinate solute cannot exceed inlet solute",
)
}
(inlet_solute - raffinate_solute) / inlet_solute
}