liquid_liquid_extraction#
Abstract Unit Operations#
- class LLEUnit(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Abstract class for simulating liquid-liquid equilibrium.
- Parameters:
ins (
Stream
], optional) – Inlet fluid.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
top_chemical (str, optional) – Identifier of chemical that will be favored in the low density phase.
efficiency=1. (float, optional) – Fraction of feed in liquid-liquid equilibrium. The rest of the feed is divided equally between phases.
cache_tolerance=1e-6 (float, optional) – Reuse previous partition coefficients to calculate LLE when the change in molar fraction of all chemicals is below this tolerance.
forced_split_IDs (tuple[str], optional) – IDs of component with a user defined split.
forced_split (1d array, optional) – Component-wise split to 0th stream.
Examples
>>> from biorefineries.lipidcane import chemicals >>> from biosteam import units, settings, Stream >>> settings.set_thermo(chemicals['Methanol', 'Glycerol', 'Biodiesel', 'TAG']) >>> feed = Stream('feed', T=333.15, ... TAG=0.996, Biodiesel=26.9, ... Methanol=32.9, Glycerol=8.97) >>> C1 = units.LLEUnit('C1', ins=feed, outs=('light', 'heavy')) >>> C1.simulate() >>> C1.outs[0].show() Stream: light from <LLEUnit: C1> phase: 'l', T: 333.15 K, P: 101325 Pa flow (kmol/hr): Methanol 10.2 Glycerol 0.0239 Biodiesel 26.9 TriOlein 0.996
- class LiquidsCentrifuge(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Abstract class for liquid centrifuges.
- Parameters:
ins (
Stream
], optional) – Inlet fluid.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
Notes
The f.o.b purchase cost is given by [1]:
\[C_{f.o.b}^{2007} = 28100 Q^{0.574} \ (Q < 100 \frac{m^3}{h})\]
- class LiquidsSettler(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Abstract Settler class for liquid-liquid extraction.
- Parameters:
ins (
Stream
], optional) – Inlet fluid with two liquid phases.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
steel' (vessel_material='Carbon) – Vessel construction material.
vessel_type='Horizontal' ('Horizontal' or 'Vertical', optional) – Vessel type.
length_to_diameter=4 (float) – Length to diameter ratio.
area_to_feed=0.1 (float) – Diameter * length per gpm of feed [ft2/gpm].
Centrifuges#
- class LiquidsSplitCentrifuge(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a liquids centrifuge simulated by component splits.
- Parameters:
ins (
Stream
], optional) – Inlet fluid.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
split (Should be one of the following) –
[float] The fraction of net feed in the 0th outlet stream.
[array_like] Componentwise split of feed to 0th outlet stream.
[dict] ID-split pairs of feed to 0th outlet stream.
order=None (Iterable[str], defaults to biosteam.settings.chemicals.IDs) – Chemical order of split.
Notes
The f.o.b purchase cost is given by [1]:
\[C_{f.o.b}^{2007} = 28100 Q^{0.574} (Q < 100 \frac{m^3}{h})\]
- class LLECentrifuge(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a liquids centrifuge simulated by liquid-liquid equilibrium.
- Parameters:
ins (
Stream
], optional) – Inlet fluid.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
top_chemical (str, optional) – Identifier of chemical that will be favored in the low density phase.
efficiency (float,) – Fraction of feed in liquid-liquid equilibrium. The rest of the feed is divided equally between phases.
Notes
The f.o.b purchase cost is given by [1]:
\[C_{f.o.b}^{2007} = 28100 Q^{0.574} (Q < 100 \frac{m^3}{h})\]Examples
>>> from biorefineries.lipidcane import chemicals >>> from biosteam import units, settings, Stream >>> settings.set_thermo(chemicals['Methanol', 'Glycerol', 'Biodiesel', 'TAG']) >>> feed = Stream('feed', T=333.15, ... TAG=0.996, Biodiesel=26.9, ... Methanol=32.9, Glycerol=8.97) >>> C1 = units.LLECentrifuge('C1', ins=feed, outs=('light', 'heavy')) >>> C1.simulate() >>> C1.outs[0].show() Stream: light from <LLECentrifuge: C1> phase: 'l', T: 333.15 K, P: 101325 Pa flow (kmol/hr): Methanol 10.2 Glycerol 0.0239 Biodiesel 26.9 TriOlein 0.996 >>> C1.results() Liquids centrifuge Units C1 Electricity Power kW 17.5 Cost USD/hr 1.37 Design Flow rate m^3/hr 12.5 Purchase cost Liquids centrifuge USD 1.29e+05 Total purchase cost USD 1.29e+05 Utility cost USD/hr 1.37
- class SLLECentrifuge(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a SLLECentrifuge object that separates the feed into solid, oil, and aqueous phases.
- Parameters:
ins (
Stream
], optional) – feedouts (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
[2] Solids.
solids_split (dict[str, float]) – Splits to 2nd outlet stream.
top_chemical (str, optional) – Identifier of chemical that will be favored in the low density phase.
efficiency (float, optional) – Fraction of feed in liquid-liquid equilibrium. The rest of the feed is divided equally between phases. Defaults to 1.0.
moisture_content (float, optional) – Moisture content of solids. Defaults to 0.5.
Notes
Cost algorithm is based on a 3-phase decanter centrifuge from a conventional dry-grind corn ethanol plant that separates aqueous, oil, and solid fractions (i.e. DDGS) from the bottoms product of the beer column [2].
Examples
>>> import biosteam as bst >>> bst.settings.set_thermo(['Water', 'Hexane', bst.Chemical('Solids', search_db=False, default=True, phase='s')], cache=True) >>> feed = bst.Stream('feed', Water=100, Hexane=100, Solids=10) >>> C1 = bst.SLLECentrifuge('C1', feed, ['oil', 'aqueous', 'solids'], top_chemical='Hexane', solids_split={'Solids':1.0}) >>> C1.simulate() >>> C1.show() SLLECentrifuge: C1 ins... [0] feed phase: 'l', T: 298.15 K, P: 101325 Pa flow (kmol/hr): Water 100 Hexane 100 Solids 10 outs... [0] oil phase: 'l', T: 298.15 K, P: 101325 Pa flow (kmol/hr): Water 0.791 Hexane 100 [1] aqueous phase: 'l', T: 298.15 K, P: 101325 Pa flow (kmol/hr): Water 98.7 Hexane 0.015 [2] solids phase: 'l', T: 298.15 K, P: 101325 Pa flow (kmol/hr): Water 0.555 Solids 10
>>> C1.results() 3-Phase decanter centrifuge Units C1 Electricity Power kW 0.0101 Cost USD/hr 0.000792 Design Flow rate L/min 250 Purchase cost 3-Phase decanter centrifuge USD 2.88e+05 Total purchase cost USD 2.88e+05 Utility cost USD/hr 0.000792
- class SolidLiquidsSplitCentrifuge(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a SolidLiquidsSplitCentrifuge object that separates the feed into solid, oil, and aqueous phases.
- Parameters:
ins (
Stream
], optional) – feedouts (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
[2] Solids.
aqueous_split (dict[str, float]) – Splits to [0] outlet stream.
solids_split (dict[str, float]) – Splits to [2] outlet stream.
moisture_content (float, optional) – Moisture content of solids. Defaults to 0.5.
Notes
Cost algorithm is based on a 3-phase decanter centrifuge from a conventional dry-grind corn ethanol plant that separates aqueous, oil, and solid fractions (i.e. DDGS) from the bottoms product of the beer column [2].
The unit operation first splits the feed to the light and heavy fractions, then fractionates the solids from the heavy phase.
Examples
>>> import biosteam as bst >>> bst.settings.set_thermo(['Water', 'Hexane', bst.Chemical('Solids', search_db=False, default=True, phase='s')], cache=True) >>> feed = bst.Stream('feed', Water=100, Hexane=100, Solids=10) >>> C1 = bst.SolidLiquidsSplitCentrifuge( ... 'C1', feed, ['oil', 'aqueous', 'solids'], ... solids_split={'Solids':1.0}, ... aqueous_split={'Water':0.99, 'Hexane':0.01, 'Solids': 0.9} ... ) >>> C1.simulate() >>> C1.show(flow='kg/hr') SolidLiquidsSplitCentrifuge: C1 ins... [0] feed phase: 'l', T: 298.15 K, P: 101325 Pa flow (kg/hr): Water 1.8e+03 Hexane 8.62e+03 Solids 10 outs... [0] oil phase: 'l', T: 298.15 K, P: 101325 Pa flow (kg/hr): Water 18 Hexane 8.53e+03 Solids 1 [1] aqueous phase: 'l', T: 298.15 K, P: 101325 Pa flow (kg/hr): Water 1.77e+03 Hexane 86.2 [2] solids phase: 'l', T: 298.15 K, P: 101325 Pa flow (kg/hr): Water 9 Solids 9
>>> C1.results() 3-Phase decanter centrifuge Units C1 Electricity Power kW 0.0101 Cost USD/hr 0.000792 Design Flow rate L/min 250 Purchase cost 3-Phase decanter centrifuge USD 2.88e+05 Total purchase cost USD 2.88e+05 Utility cost USD/hr 0.000792
Mixer-Settlers#
- class LiquidsMixingTank(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a LiquidsMixingTank for mixing two liquid phases.
- Parameters:
ins (
Stream
], optional) – Inlet fluids to be mixed.outs (
Stream
], optional) – Mixed outlet fluid.tau=0.022 (float) – Residence time [hr].
agitator_kW_per_m3=1.0 (float) – Electricity consumption in kW / m3 of volume.
steel' (vessel_material='Carbon) – Vessel construction material.
vessel_type='Horizontal' ('Horizontal' or 'Vertical', optional) – Vessel type.
length_to_diameter=1 (float) – Length to diameter ratio.
- class LLESettler(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a LLESettler object that rigorously simulates liquid-liquid extraction.
- Parameters:
ins (
Stream
], optional) – Inlet fluid with two liquid phases.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
steel' (vessel_material='Carbon) – Vessel construction material.
vessel_type='Horizontal' ('Horizontal' or 'Vertical', optional) – Vessel type.
length_to_diameter=4 (float, optional) – Length to diameter ratio.
area_to_feed=0.1 (float, optional) – Diameter * length per gpm of feed [ft2/gpm].
top_chemical=None (str, optional) – Identifier of chemical that will be favored in the low density phase.
efficiency=1.0 (float) – Fraction of feed in liquid-liquid equilibrium
cache_tolerance=1e-6 (float, optional) – Molar tolerance of cached partition coefficients.
- class LiquidsSplitSettler(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a LLESettler object that rigorously simulates liquid-liquid extraction.
- Parameters:
ins (
Stream
], optional) – Inlet fluid with two liquid phases.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
split (Should be one of the following) –
[float] The fraction of net feed in the 0th outlet stream
[array_like] Componentwise split of feed to 0th outlet stream
[dict] ID-split pairs of feed to 0th outlet stream
order=None (Iterable[str], defaults to biosteam.settings.chemicals.IDs) – Chemical order of split.
steel' (vessel_material='Carbon) – Vessel construction material.
vessel_type='Horizontal' ('Horizontal' or 'Vertical', optional) – Vessel type.
length_to_diameter=4 (float, optional) – Length to diameter ratio.
area_to_feed=0.1 (float, optional) – Diameter * length per gpm of feed [ft2/gpm].
- class LiquidsPartitionSettler(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a LiquidsPartitionSettler object that simulates liquid-liquid extraction by partition coefficients.
- Parameters:
ins (
Stream
], optional) – Inlet fluid with two liquid phases.outs (
Stream
], optional) –[0] Low density fluid.
[1] Heavy fluid.
steel' (vessel_material='Carbon) – Vessel construction material.
vessel_type='Horizontal' ('Horizontal' or 'Vertical', optional) – Vessel type.
length_to_diameter=4 (float, optional) – Length to diameter ratio.
area_to_feed=0.1 (float, optional) – Diameter * length per gpm of feed [ft2/gpm].
partition_coefficients (1d array, optional) – Partition coefficients of chemicals in equilibrium (molar composition ratio of the top fluid over the bottom fluid).
partition_IDs (tuple[str], optional) – IDs of chemicals in equilibrium.
- class MixerSettler(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a MixerSettler object that models liquid-liquid extraction using a mixing tank and a settler tank.
- Parameters:
ins (
Stream
], optional) –[0] feed.
[1] solvent.
outs (
Stream
], optional) –[0] extract.
[1] raffinate.
solvent_ID (str, optional) – Name of main chemical in the solvent. Defaults to chemical with highest molar fraction in the solvent.
mixer_data (dict, optional) – Arguments to initialize the “mixer” attribute, a
LiquidsMixingTank
object.settler_data (dict, optional) – Arguments to initialize the “settler” attribute, a
LiquidsSettler
object.
Examples
Simulate by rigorous LLE:
>>> import biosteam as bst >>> bst.settings.set_thermo(['Water', 'Methanol', 'Octanol'], cache=True) >>> feed = bst.Stream('feed', Water=500, Methanol=50) >>> solvent = bst.Stream('solvent', Octanol=500) >>> MS1 = bst.MixerSettler('MS1', ins=(feed, solvent), outs=('extract', 'raffinate')) >>> MS1.simulate() >>> MS1.extract.imol['Methanol'] / MS1.feed.imol['Methanol'] 0.66 >>> MS1.raffinate.imol['Water'] / MS1.feed.imol['Water'] 0.82 >>> MS1.extract.imol['Octanol'] / MS1.solvent.imol['Octanol'] 0.99 >>> MS1.results() Mixer settler Units MS1 Power Rate kW 1.98 Cost USD/hr 0.155 Design Mixer - Volume m^3 1.98 Mixer - Power hp 2.65 Mixer - Vessel type Vertical Mixer - Length ft 1.36 Mixer - Diameter ft 1.36 Mixer - Weight lb 91.2 Mixer - Wall thickness in 0.25 Settler - Vessel type Horizontal Settler - Length ft 12.6 Settler - Diameter ft 3.15 Settler - Weight lb 1.44e+03 Settler - Wall thickness in 0.25 Purchase cost Mixer - Turbine agitator USD 6.32e+03 Mixer - Vertical pressure vessel USD 4.59e+03 Mixer - Platform and ladders USD 641 Settler - Horizontal pressure ve... USD 9.99e+03 Settler - Platform and ladders USD 2.66e+03 Total purchase cost USD 2.42e+04 Utility cost USD/hr 0.155
Simulate with user defined partition coefficients:
>>> import biosteam as bst >>> import numpy as np >>> bst.settings.set_thermo(['Water', 'Methanol', 'Octanol']) >>> feed = bst.Stream('feed', Water=500, Methanol=50) >>> solvent = bst.Stream('solvent', Octanol=500) >>> MS1 = bst.MixerSettler('MS1', ... ins=(feed, solvent), outs=('extract', 'raffinate'), ... model='partition coefficients', ... settler_data={ ... 'partition_coefficients': np.array([1.451e-01, 1.380e+00, 2.958e+03]), ... 'partion_IDs': ('Water', 'Methanol', 'Octanol'), ... }, ... ) >>> MS1.simulate() >>> MS1.extract.imol['Methanol'] / MS1.feed.imol['Methanol'] 0.66 >>> MS1.raffinate.imol['Water'] / MS1.feed.imol['Water'] 0.82 >>> MS1.extract.imol['Octanol'] / MS1.solvent.imol['Octanol'] 0.99 >>> MS1.results() Mixer settler Units MS1 Electricity Power kW 1.98 Cost USD/hr 0.155 Design Mixer - Volume m^3 1.98 Mixer - Power hp 2.65 Mixer - Vessel type Vertical Mixer - Length ft 1.36 Mixer - Diameter ft 1.36 Mixer - Weight lb 91.2 Mixer - Wall thickness in 0.25 Settler - Vessel type Horizontal Settler - Length 12.6 Settler - Diameter 3.15 Settler - Weight 1.44e+03 Settler - Wall thickness 0.25 Purchase cost Mixer - Turbine agitator USD 6.32e+03 Mixer - Vertical pressure vessel USD 4.91e+03 Mixer - Platform and ladders USD 686 Settler - Horizontal pressure ve... USD 1.16e+04 Settler - Platform and ladders USD 3.08e+03 Total purchase cost USD 2.65e+04 Utility cost USD/hr 0.155
- class MultiStageMixerSettlers(ID='', ins=None, outs=(), thermo=None, **kwargs)[source]#
Create a MultiStageMixerSettlers object that models a counter-current system of mixer-settlers for liquid-liquid extraction.
- Parameters:
ins –
[0] feed.
[1] solvent.
outs –
[0] extract
[1] raffinate
N_stages (int) – Number of stages.
partition_data ({'IDs': tuple[str], 'K': 1d array}, optional) – IDs of chemicals in equilibrium and partition coefficients (molar composition ratio of the extract over the raffinate). If given, The mixer-settlers will be modeled with these constants. Otherwise, partition coefficients are computed based on temperature and composition.
solvent_ID (str) – Name of main chemical in the solvent.
mixer_data (dict) – Arguments to initialize the “mixer” attribute, a
LiquidsMixingTank
object.settler_data (dict) – Arguments to initialize the “settler” attribute, a
LiquidsSettler
object.
Notes
All mixer settlers are sized equally based on the assumption that the volumetric flow rate of each phase does not change significantly across stages.
Examples
Simulate by rigorous LLE:
>>> import biosteam as bst >>> bst.settings.set_thermo(['Water', 'Methanol', 'Octanol']) >>> feed = bst.Stream('feed', Water=500, Methanol=50) >>> solvent = bst.Stream('solvent', Octanol=500) >>> MSMS1 = bst.MultiStageMixerSettlers('MSMS1', ins=(feed, solvent), outs=('extract', 'raffinate'), N_stages=2) >>> MSMS1.simulate() >>> MSMS1.extract.imol['Methanol'] / MSMS1.feed.imol['Methanol'] 0.83 >>> MSMS1.raffinate.imol['Water'] / MSMS1.feed.imol['Water'] 0.82 >>> MSMS1.extract.imol['Octanol'] / MSMS1.solvent.imol['Octanol'] 0.99 >>> MSMS1.results() Multi stage mixer settlers Units MSMS1 Electricity Power kW 3.96 Cost USD/hr 0.309 Design Mixer - Volume m^3 1.98 Mixer - Power hp 2.65 Mixer - Vessel type Vertical Mixer - Length ft 1.36 Mixer - Diameter ft 1.36 Mixer - Weight lb 91.2 Mixer - Wall thickness in 0.25 Settler - Vessel type Horizontal Settler - Length 12.6 Settler - Diameter 3.15 Settler - Weight 1.44e+03 Settler - Wall thickness 0.25 Purchase cost Mixers and agitators USD 1.12e+04 Settlers USD 2.93e+04 Total purchase cost USD 4.05e+04 Utility cost USD/hr 0.309
Simulate with user defined partition coefficients:
>>> import biosteam as bst >>> import numpy as np >>> bst.settings.set_thermo(['Water', 'Methanol', 'Octanol']) >>> feed = bst.Stream('feed', Water=5000, Methanol=500) >>> solvent = bst.Stream('solvent', Octanol=5000) >>> MSMS1 = bst.MultiStageMixerSettlers('MSMS1', ins=(feed, solvent), outs=('extract', 'raffinate'), N_stages=10, ... partition_data={ ... 'K': np.array([0.1450, 1.380, 2957.]), ... 'IDs': ('Water', 'Methanol', 'Octanol'), ... 'phi': 0.590 # Initial phase fraction guess. This is optional. ... } ... ) >>> MSMS1.simulate() >>> MSMS1.extract.imol['Methanol'] / MSMS1.feed.imol['Methanol'] 0.99 >>> MSMS1.raffinate.imol['Water'] / MSMS1.feed.imol['Water'] 0.82 >>> MSMS1.extract.imol['Octanol'] / MSMS1.solvent.imol['Octanol'] 0.99 >>> MSMS1.results() Multi stage mixer settlers Units MSMS1 Electricity Power kW 198 Cost USD/hr 15.5 Design Mixer - Volume m^3 19.8 Mixer - Power hp 26.5 Mixer - Vessel type Vertical Mixer - Length ft 2.93 Mixer - Diameter ft 2.93 Mixer - Weight lb 423 Mixer - Wall thickness in 0.25 Settler - Vessel type Horizontal Settler - Length 39.8 Settler - Diameter 9.95 Settler - Weight 2.52e+04 Settler - Wall thickness 0.438 Purchase cost Mixers and agitators USD 1.15e+05 Settlers USD 6.15e+05 Total purchase cost USD 7.3e+05 Utility cost USD/hr 15.5
Because octanol and water do not mix well, it may be a good idea to assume that these solvents do not mix at all:
>>> MSMS1 = bst.MultiStageMixerSettlers('MSMS1', ins=(feed, solvent), outs=('extract', 'raffinate'), N_stages=20, ... partition_data={ ... 'K': np.array([1.38]), ... 'IDs': ('Methanol',), ... 'raffinate_chemicals': ('Water',), ... 'extract_chemicals': ('Octanol',), ... } ... ) >>> MSMS1.simulate() >>> MSMS1.extract.imol['Methanol'] / feed.imol['Methanol'] # Recovery 0.99 >>> MSMS1.extract.imol['Octanol'] / solvent.imol['Octanol'] # Solvent stays in extract 1.0 >>> MSMS1.raffinate.imol['Water'] / feed.imol['Water'] # Carrier remains in raffinate 1.0
Simulate with a feed at the 4th stage:
>>> dilute_feed = bst.Stream('dilute_feed', Water=100, Methanol=2) >>> MSMS1 = bst.MultiStageMixerSettlers('MSMS1', ins=(feed, dilute_feed, solvent), outs=('extract', 'raffinate'), N_stages=5, ... feed_stages=[0, 3, -1], # Stage at which each inlet enters, respectively ... partition_data={ ... 'K': np.array([1.38]), ... 'IDs': ('Methanol',), ... 'raffinate_chemicals': ('Water',), ... 'extract_chemicals': ('Octanol',), ... } ... ) >>> MSMS1.simulate() >>> MSMS1.extract.imol['Methanol'] / (feed.imol['Methanol'] + dilute_feed.imol['Methanol']) # Recovery 0.93
Simulate with a 60% extract side draw at the 2nd stage and 10% raffinate side draw at the 3rd stage:
>>> MSMS1 = bst.MultiStageMixerSettlers('MSMS1', ins=(feed, solvent), N_stages=4, ... # Extract side draws always come first, then raffinate side draws ... outs=('extract', 'raffinate', 'extract_side_draw', 'raffinate_side_draw'), ... extract_side_draws=[(1, 0.6)], # Stage number and split fraction pairs ... raffinate_side_draws=[(2, 0.10)], ... partition_data={ ... 'K': np.array([1.38]), ... 'IDs': ('Methanol',), ... 'raffinate_chemicals': ('Water',), ... 'extract_chemicals': ('Octanol',), ... } ... ) >>> MSMS1.simulate() >>> (MSMS1.extract.imol['Methanol'] + MSMS1.outs[2].imol['Methanol']) / feed.imol['Methanol'] # Recovery 1.0
References