BioSTEAMDevelopmentGroup / biosteam

The Biorefinery Simulation and Techno-Economic Analysis Modules; Life Cycle Assessment; Chemical Process Simulation Under Uncertainty
Other
180 stars 35 forks source link

Problem with adding Psat to proceed with the distillation #77

Closed DmitryBachin closed 2 years ago

DmitryBachin commented 2 years ago

Describe the bug Idea is to split glycerol and eicosapentaenoic acid (EPA) with distillation. Though Psat is missing and it is not clear how to add it there. The basic model (Psat.add_model(0)) doesn't work either.

To Reproduce

import biosteam as bst
from biosteam.units import BinaryDistillation, Distillation

chemicals = bst.Chemicals([bst.Chemical('Glycerol'),
                           bst.Chemical('EPA', default=True, search_ID="10417-94-4", phase='l', Tb=423)])

chemicals.compile()
bst.settings.set_thermo(chemicals)

input_stream = bst.Stream("input", EPA=8.8e-05, Glycerol=2.17e-05)

D1 = BinaryDistillation('D1', LHK=('EPA', 'Glycerol'),
                        Lr=0.999, Hr=0.999, k=1.05)

D1.simulate()

Expected behavior Separation of glycerol and EPA

Actual behavior

Traceback (most recent call last):
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/Celebi/temp.py", line 16, in <module>
    D1.simulate()
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/biosteam/_unit.py", line 839, in simulate
    self.run()
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/biosteam/_unit.py", line 753, in run
    self._run()
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/biosteam/units/distillation.py", line 1076, in _run
    self._update_distillate_and_bottoms_temperature()
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/biosteam/units/distillation.py", line 590, in _update_distillate_and_bottoms_temperature
    self._boilup_bubble_point = bp = reboiler_bottoms_product.bubble_point_at_P()
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/thermosteam/_stream.py", line 1796, in bubble_point_at_P
    bp = self.get_bubble_point(IDs)
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/thermosteam/_stream.py", line 1731, in get_bubble_point
    bp = self._bubble_point_cache(chemicals, self._thermo)
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/thermosteam/utils/cache.py", line 36, in __call__
    self.value = value = self.load(*self.args)
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/thermosteam/equilibrium/bubble_point.py", line 102, in __init__
    Tmin, Tmax = vle_domain(chemicals)
  File "/Users/dmitrybachin/PycharmProjects/bioprocess_modelling/venv/lib/python3.9/site-packages/thermosteam/equilibrium/domain.py", line 37, in vle_domain
    Tmax_Psat = min([i.Tmax for i in Psats])
ValueError: min() arg is an empty sequence

Version

Additional question If I have NaOH in the mix before the distillation, what should I do?

yoelcortes commented 2 years ago

Hi Dmitry, sorry for the late reply!

By setting phase='l' when EPA is created, then EPA will only exist in the liquid phase. To use EPA as a light (or heavy) key in distillation, the phase cannot be locked. I wrote some code here that works for distillation for EPA and Glycerol, but you'll need to add the missing chemical properties:

mport biosteam as bst
from biosteam.units import BinaryDistillation, Distillation

# Change conditions  of heating agent to satisfy distillation boiler temperature
Water = bst.Chemical('Water')
hps = bst.HeatUtility.get_heating_agent('high_pressure_steam')
hps.T = 620
hps.P = Water.Psat(620)

chemicals = Glycerol, EPA = bst.Chemicals([
    bst.Chemical('Glycerol'),
    bst.Chemical('EPA', default=True, search_ID="10417-94-4", Tb=423)
])
EPA.V.l.add_method(0.001) # Arbitrary
EPA.Psat.add_method(lambda T: 101325 * (T / 423), Tmax=1e6, Tmin=0) # Arbitrary
EPA.Hvap.add_method(lambda T: 1e-5) # # Arbitrary; cannot be zero
EPA.reset_free_energies() # Necessary after setting Hvap
chemicals.compile()
bst.settings.set_thermo(chemicals)

input_stream = bst.Stream("input", EPA=8.8e-05, Glycerol=2.17e-05)

D1 = BinaryDistillation('D1', ins=input_stream, LHK=('EPA', 'Glycerol'),
                        Lr=0.6, Hr=0.6, k=1.05) # Low Lr and Hr because of azeotrope

D1.simulate()

Please let me know if you have any questions, Hope this helps!

SonjaMGS commented 2 years ago

Hi Yoel,

Thank you very much for your reply. It is really helpful with great insights. However, there is an issue with the BinaryDistillation command of Lr and Hr. We want to have an almost 100% separation (99%) between these two compounds. Even if we change the BinaryDistillation to a normal distillation it does not work. Even if we choose Flash. The boiling temp of EPA is 423 Kelvin, whereas the glycerol is 563 Kelvin.

yoelcortes commented 2 years ago

@SonjaMGS, could you share the code to reproduce the issue along with the traceback?

SonjaMGS commented 2 years ago

Hi, Yes of course. The goal aimed with this unit is 'replication' of a fractional distillator. Since there is no fractional distillator, a BinaryDistillator or a normal distillator was tried out.

The code with the BinaryDistillator is shown here below

import biosteam as bst
from biosteam.units import BinaryDistillation, Distillation, Flash

Water = bst.Chemical('Water')
hps = bst.HeatUtility.get_heating_agent('high_pressure_steam')
hps.T = 620
hps.P = Water.Psat(620)

EPA = bst.Chemical('EPA', default=True, search_ID="10417-94-4", Tb=423)
EPA.V.l.add_method(0.001) # Arbitrary
EPA.Psat.add_method(lambda T: 101325 * (T / 423), Tmax=1e6, Tmin=0) # Arbitrary
EPA.Hvap.add_method(lambda T: 1e-5) # # Arbitrary; cannot be zero
EPA.reset_free_energies() # Necessary after setting Hvap

chemicals = bst.Chemicals([
            bst.Chemical('Glycerol'), Water, EPA
])

chemicals.compile()
bst.settings.set_thermo(chemicals)

input_stream = bst.Stream("input", EPA=8.8e-05, Glycerol=2.17e-05)

D1 = BinaryDistillation('D1', ins=input_stream, LHK=('EPA', 'Glycerol'),
                        Lr=0.99, Hr=0.99, k=1.05) 

D1.simulate()

However, the code gives this output

Backend TkAgg is interactive backend. Turning interactive mode on.
Traceback (most recent call last):
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\IPython\core\interactiveshell.py", line 3444, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-f9cb96e070b8>", line 1, in <module>
    runfile('C:/Users/Sonja/Desktop/celebi/Celebi/Test_Binary_Distillation.py', wdir='C:/Users/Sonja/Desktop/celebi/Celebi')
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/Users/Sonja/Desktop/celebi/Celebi/Test_Binary_Distillation.py", line 28, in <module>
    D1.simulate()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\_unit.py", line 840, in simulate
    self._summary()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\_unit.py", line 768, in _summary
    self._design()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\units\distillation.py", line 1180, in _design
    self._run_McCabeThiele()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\units\distillation.py", line 1145, in _run_McCabeThiele
    compute_stages_McCabeThiele(P, ss, x_stages, y_stages, T_stages, x_m, solve_Ty)
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\units\distillation.py", line 897, in compute_stages_McCabeThiele
    raise RuntimeError('cannot meet specifications! stages > 100')
RuntimeError: cannot meet specifications! stages > 100

So a normal distillation was tried out later on, same inputs as in the BinaryDstillator

D1 = Distillation('D1', ins=input_stream, LHK=('EPA', 'Glycerol'),
                        Lr=0.99, Hr=0.99, k=1.05) 
D1.simulate()

And the error I get is :

Traceback (most recent call last):
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\IPython\core\interactiveshell.py", line 3444, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-f9cb96e070b8>", line 1, in <module>
    runfile('C:/Users/Sonja/Desktop/celebi/Celebi/Test_Binary_Distillation.py', wdir='C:/Users/Sonja/Desktop/celebi/Celebi')
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/Users/Sonja/Desktop/celebi/Celebi/Test_Binary_Distillation.py", line 28, in <module>
    D1.simulate()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\_unit.py", line 840, in simulate
    self._summary()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\_unit.py", line 769, in _summary
    self._cost()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\units\distillation.py", line 843, in _cost
    N_T = Design['Actual stages'] - 1.
KeyError: 'Actual stages'

Looking forward to your reply!

Thank you in advance!

internEVbiotech commented 2 years ago

Hello,

There is another issue except the not full separation of the distillation of glycerol and EPA. There is a unit.Flash before the distillator, where the separation of hexane and EPA occurs. Before the changes it worked but now it does not run anymore.

The code is `import biosteam as bst from biosteam.units import BinaryDistillation, Distillation, Flash

Water = bst.Chemical('Water') hps = bst.HeatUtility.get_heating_agent('high_pressure_steam') hps.T = 620 hps.P = Water.Psat(620)

EPA = bst.Chemical('EPA', default=True, search_ID="10417-94-4", Tb=423) EPA.V.l.add_method(0.001) EPA.Psat.add_method(lambda T: 101325 * (T / 423), Tmax=1e6, Tmin=0) EPA.Hvap.add_method(lambda T: 1e-5) EPA.reset_free_energies()

chemicals = bst.Chemicals([ bst.Chemical('Hexane'), Water, EPA ])

chemicals.compile() bst.settings.set_thermo(chemicals)

feed = bst.Stream("feed", EPA=8.5, Hexane=2.17)

F1 = Flash('F1', ins=feed, outs=(), P=101325, T=345)

F1.simulate()`

The output is this :

Backend TkAgg is interactive backend. Turning interactive mode on.
Traceback (most recent call last):
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\IPython\core\interactiveshell.py", line 3444, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-e197cea51401>", line 1, in <module>
    runfile('C:/Users/Sonja/Desktop/celebi/Celebi/Control_assign.py', wdir='C:/Users/Sonja/Desktop/celebi/Celebi')
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "C:/Users/Sonja/Desktop/celebi/Celebi/Control_assign.py", line 27, in <module>
    F1.simulate()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\_unit.py", line 840, in simulate
    self._summary()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\_unit.py", line 768, in _summary
    self._design()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\units\_flash.py", line 259, in _design
    args = self._horizontal_vessel_pressure_diameter_and_length()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\units\_flash.py", line 405, in _horizontal_vessel_pressure_diameter_and_length
    rhov, rhol, P, Th, Ts, has_mist_eliminator, Qv, Qll, Ut, Uv, Vh, Vs = self._design_parameters()
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\biosteam\units\_flash.py", line 323, in _design_parameters
    rhov = vap.get_property('rho', 'lb/ft3')
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\thermosteam\_stream.py", line 702, in get_property
    value = getattr(self, name)
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\thermosteam\_stream.py", line 1047, in rho
    return fn.V_to_rho(self.V, self.MW)
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\thermosteam\_stream.py", line 979, in V
    *self._imol.get_phase_and_composition(),
  File "C:\Users\Sonja\Desktop\Test\venv\lib\site-packages\thermosteam\indexer.py", line 425, in get_phase_and_composition
    return self.phase, data / data.sum()
FloatingPointError: invalid value encountered in true_divide

The code that works is shown here below.

`import biosteam as bst from biosteam.units import BinaryDistillation, Distillation, Flash

Water = bst.Chemical('Water') hps = bst.HeatUtility.get_heating_agent('high_pressure_steam') hps.T = 620 hps.P = Water.Psat(620)

chemicals = bst.Chemicals(['Hexane', bst.Chemical('EPA', Cp=0.55, default=True, search_db=False, MW=328, phase='l', formula='C20H30O2'), Water ]) chemicals.compile() bst.settings.set_thermo(chemicals)

feed = bst.Stream("feed", EPA=8.5, Hexane=2.17)

F1 = Flash('F1', ins=feed, outs=(), P=101325, T=345)

F1.simulate()`

The Flash works. Can this be solved?

yoelcortes commented 2 years ago

Hello!

Before going over the issues, I think these key points will help clarify some confusions:

The arbitrary model I provided for the vapor pressure should be replaced with a realistic model. If you can find the critical pressure and temperature and the acentric factor (Tc, Pc, omega), you can set these when you initialize the chemical and you will have a good vapor pressure model. For example:

import biosteam as bst
>>> EPA = bst.Chemical('EPA', default=True, search_ID="10417-94-4",
                   Tb=423, Tc=647, Pc=22048320, omega=0.344) # Tc, Pc, omega are arbitrary here
>>> EPA.Psat.method
'AMBROSE_WALTON'

If you have data, you can fit it to standard vapor pressure models: https://thermo.readthedocs.io/property_objects.html#fitting-correlation-coefficients

Note that the random model I used in the example (101325 * (T / 423)) leads to an azeotrope, making it impossible to separate the two components:

# First run the code in my first reply
D1.plot_stages()

bad_distillation_azeotrope

The flash vessel ran into an error when trying to size it because there is no vapor phase at that temperature and pressure. You can fix this up by specifying pressure (or temperature) and vapor fraction:

import biosteam as bst
from biosteam.units import BinaryDistillation, Distillation, Flash

Water = bst.Chemical('Water')
hps = bst.HeatUtility.get_heating_agent('high_pressure_steam')
hps.T = 620
hps.P = Water.Psat(620)

EPA = bst.Chemical('EPA', default=True, search_ID="10417-94-4", Tb=423)
EPA.V.l.add_method(0.001) 
EPA.Psat.add_method(lambda T: 101325 * (T / 423), Tmax=1e6, Tmin=0)
EPA.Hvap.add_method(lambda T: 1e-5) 
EPA.reset_free_energies() 

chemicals = bst.Chemicals([
            bst.Chemical('Hexane'), Water, EPA
])

chemicals.compile()
bst.settings.set_thermo(chemicals)

feed = bst.Stream("feed", EPA=8.5, Hexane=2.17)

F1 = Flash('F1', ins=feed, outs=(), P=101325, V=0.999)

F1.simulate()
F1.show()

Output:

Flash: F1
ins...
[0] feed
    phase: 'l', T: 298.15 K, P: 101325 Pa
    flow (kmol/hr): Hexane  2.17
                    EPA     8.5
outs...
[0] s7
    phase: 'g', T: 363.91 K, P: 101325 Pa
    flow (kmol/hr): Hexane  2.17
                    EPA     8.49
[1] s8
    phase: 'l', T: 363.91 K, P: 101325 Pa
    flow (kmol/hr): Hexane  0.000793
                    EPA     0.00988

Hope this helps! THanks,