///|
pub(all) struct LeachingStageResult {
equilibrium_concentration : Double
retained_solution : Double
overflow_solution : Double
solute_in_underflow : Double
solute_in_overflow : Double
dissolved_recovery : Double
balance_residual : Double
} derive(Debug, Eq, ToJson)
///|
/// Solve one ideal solid-liquid washing/leaching contact.
///
/// `retention_ratio` is kg solution retained per kg insoluble dry solid.
pub fn single_stage_leach(
dry_solid_mass~ : Double,
initial_solution_mass~ : Double,
initial_solute_fraction~ : Double,
wash_solution_mass~ : Double,
wash_solute_fraction? : Double = 0.0,
retention_ratio~ : Double,
) -> LeachingStageResult raise @domain.ExtractionError {
@domain.require_positive("dry solid mass", dry_solid_mass)
@domain.require_non_negative("initial solution mass", initial_solution_mass)
@domain.require_fraction("initial solute fraction", initial_solute_fraction)
@domain.require_non_negative("wash solution mass", wash_solution_mass)
@domain.require_fraction("wash solute fraction", wash_solute_fraction)
@domain.require_non_negative("retention ratio", retention_ratio)
let total_solution = initial_solution_mass + wash_solution_mass
if total_solution <= 0.0 {
raise @domain.ExtractionError::InvalidFlow(
name="total solution",
value=total_solution,
)
}
let inlet_solute = initial_solution_mass * initial_solute_fraction +
wash_solution_mass * wash_solute_fraction
let concentration = inlet_solute / total_solution
let retained_capacity = retention_ratio * dry_solid_mass
let retained = retained_capacity.min(total_solution)
let overflow = total_solution - retained
let solute_underflow = retained * concentration
let solute_overflow = overflow * concentration
{
equilibrium_concentration: concentration,
retained_solution: retained,
overflow_solution: overflow,
solute_in_underflow: solute_underflow,
solute_in_overflow: solute_overflow,
dissolved_recovery: if inlet_solute > 0.0 {
solute_overflow / inlet_solute
} else {
0.0
},
balance_residual: inlet_solute - solute_underflow - solute_overflow,
}
}