Skip to content

Navigation Menu

Sign in
Sign up

Recycled stream issue #185

Open
Open

Description

Hi Yoel! Hope the codes below can reproduce the error.

When only simulating the MeOH_SynthesisReactor, it works well.

But when simulating system with more units and recycled streams (including complex heat exchange process as the attached figure), it gives:
*** RuntimeError: Failed to extrapolate gas heat capacity method 'HEOS_FIT' at T=nan K for component with CASRN '1333-74-0'.

I think some recycled stream caused this issue and maybe you have more quicker way to figure it out. Could you please help me check which stream causes this issue? Thanks!!

[_chemicals.py]

import thermosteam as tmo
#%% 
# Constants
_cal2joule=4.184
#%% 
chems=tmo.Chemicals([])
database_chemicals_dict={}
copied_chemicals_dict={}
defined_chemicals_dict={}
def chemical_database(ID, search_ID=None, phase=None, **kwargs):
 chemical = tmo.Chemical(ID,search_ID=search_ID, **kwargs)
 if phase:
 chemical.at_state(phase)
 chemical.phase_ref = phase
 chems.append(chemical)
 database_chemicals_dict[ID] = f'{ID}: {chemical.formula}/{chemical.MW}'
 return chemical
def chemical_copied(ID,ref_chemical,**data):
 chemical=ref_chemical.copy(ID)
 chems.append(chemical)
 for i,j in data.items():setattr(chemical,i,j)
 copied_chemicals_dict[ID]=f'{ID}:{chemical.formula}/{chemical.MW}'
 return chemical
def chemical_defined(ID,**kwargs):
 chemical=tmo.Chemical.blank(ID,**kwargs)
 chems.append(chemical)
 defined_chemicals_dict[ID]=f'{ID}:{chemical.formula}/{chemical.MW}'
 return chemical
# %% 
# =============================================================================
# Create chemical objects available in database
# =============================================================================
H2O = chemical_database('H2O')
O2 = chemical_database('O2', phase='g', Hf=0)
N2 = chemical_database('N2', phase='g', Hf=0)
H2 = chemical_database('H2', Hf=0)
CH4 = chemical_database('Methane')
CO = chemical_database('CarbonMonoxide', Hf=-26400*_cal2joule)
CO2 = chemical_database('CO2')
CH3OH = chemical_database('Methanol')
HCOOH = chemical_database('HCOOH')
C18H39N = chemical_database('C18H39N') # amine
C19H41NO2 = chemical_database('C19H41NO2')
Triphenylphosphine = chemical_database('Triphenylphosphine', search_ID='603-35-0', phase='s') # surrogate model for DCPE
DCPE = chemical_database('DCPE', search_ID='23743-26-2', phase='s') # FA catalyst; second component
for i in DCPE.get_missing_properties():
 if i == 'V':
 try:
 DCPE.copy_models_from(Triphenylphosphine, [i])
 except:
 pass
phase_change_chemicals = ['H2O', 'H2', 'CH4', 'CO', 'CO2', 'CH3OH', 'HCOOH'
 'C18H39N', 'C19H41NO2']
for chem in chems:
 if chem.ID in phase_change_chemicals: pass
 elif chem.locked_state: pass
 else: 
 # Set phase_ref to avoid missing model errors
 if chem.phase_ref == 'g':
 chem.at_state('g')
 if chem.phase_ref == 'l':
 chem.at_state('l')
chems.compile()
tmo.settings.set_thermo(chems, cache=True)
chems.set_synonym('H2O', 'Water')
chems.set_synonym('CO2', 'CarbonDioxide')
chems.set_synonym('CO', 'CarbonMonoxide')
chems.set_synonym('Methanol', 'CH3OH')

[_units.py]

import numpy as np
import biosteam as bst
import thermosteam as tmo
from biosteam import Stream, Unit, BinaryDistillation
from biosteam.units import HXutility, Mixer, SolidsSeparator, Compressor
from biosteam.units.decorators import cost
from biosteam.units.design_tools import size_batch
from thermosteam import MultiStream
from biosteam.units.design_tools.geometry import cylinder_diameter_from_volume
from qsdsan._sanunit import SanUnit
Rxn = tmo.reaction.Reaction
ParallelRxn = tmo.reaction.ParallelReaction
#%% 
# =============================================================================
# H2 production through Liquid Alkaline (LA) electrolysis 
# =============================================================================
# Model H2 production by H2O => H2 + 0.5O2
class Electrolyzer(SanUnit): 
 _N_ins = 1
 _N_outs = 2
 
 def __init__(self, ID="", ins=None, outs=(),
 stack_lifetime=10,
 renewable_electricity_price=0.03, # currently possible in U.S. markets with plentiful wind
 **kwargs):
 bst.Unit.__init__(self, ID, ins, outs)
 self.stack_lifetime = stack_lifetime
 self.renewable_electricity_price = renewable_electricity_price
 
 def _run(self):
 water, = self.ins
 hydrogen, oxygen = self.outs
 hydrogen.phase = 'g'
 hydrogen.P = 30 * 101325 # Model H2 purification so that output is 99.99% purity and 30 bar
 oxygen.phase = 'g'
 hydrogen.imol['H2'] = water.F_mol
 oxygen.imol['O2'] = water.F_mol / 2
 
 def _cost(self): # based on https://www.osti.gov/biblio/2203367 P17
 self.power_utility.rate = self.outs[0].imass['H2'] * 122000 * 24 / 50000 # base case 50 MTD / 122 MW
 # self.power_utility.cost = self.renewable_electricity_price * self.power_utility.rate
 self.baseline_purchase_costs['Stack'] = self.power_utility.rate * 292 # process equipment, piping, valves, and instrumentation including temperature, pressure, flow, and level indicators
 self.baseline_purchase_costs['Mechanical BOP'] = self.power_utility.rate * 280
 self.baseline_purchase_costs['Electrical BOP'] = self.power_utility.rate * 155 # for AC-> DC, transformer, power substation
 self.add_OPEX = self._calculate_replacement_cost()
 
 def _calculate_replacement_cost(self):
 stack_replacement_cost = self.baseline_purchase_costs['Stack'] / self.stack_lifetime / (365*24) # convert from USD/year to USD/hour
 return stack_replacement_cost
 
 
# =============================================================================
# MeOH synthesis
# =============================================================================
# Reactor is modelled as an adiabatic ideal plug flow reactor (PFR)
class MeOH_SynthesisReactor(bst.units.design_tools.PressureVessel, bst.Unit):
 _N_ins = _N_outs = 1
 _N_heat_utilities = 0
 
 _units = {**bst.design_tools.PressureVessel._units,
 'Volume': 'm^3',
 'Catalyst weight': 'kg'}
 
 _F_BM_default = {**bst.design_tools.PressureVessel._F_BM_default,
 'Catalyst': 1.0} # Cu/ZnO/Al2O3
 
 def __init__(self, ID="", ins=None, outs=(), thermo=None, *,
 P=7600000,
 tau=6/3600, # tau=5-7s to h; from 10.1016/j.jcou.201501006
 vessel_material='Stainless steel 304',
 vessel_type='Vertical',
 length_to_diameter=0.15/0.016, # 10.1016/j.jclepro.201306008
 catalyst_density=1775, # In kg/m^3; 10.1016/j.jclepro.201306008
 catalyst_price=13,
 porosity=0.5,):
 
 super().__init__(ID, ins, outs, thermo)
 self.P = P
 self.tau = tau
 self.WHSV = 1/self.tau
 self.vessel_material = vessel_material # Vessel material
 self.vessel_type = vessel_type # 'Horizontal' or 'Vertical'
 self.length_to_diameter = length_to_diameter #: Length to diameter ratio
 self.catalyst_density = catalyst_density
 self.catalyst_price = catalyst_price # In USD/kg
 self.porosity = porosity # fraction of the bed volume occupied by void space
 self.reactions = ParallelRxn([
 # Reaction definition Reactant Conversion
 Rxn('CO2 + 3H2 -> CH3OH + H2O', 'CO2', 0.210),
 Rxn('CO2 + H2 -> CO + H2O', 'CO2', 0.004),])
 
 def _default_vessel_type(self):
 return 'Vertical'
 
 def _run(self):
 feed, = self.ins
 assert feed.phase == 'g', 'feed phase must be a gas'
 effluent, = self.outs
 effluent.copy_like(feed)
 self.reactions.adiabatic_reaction(effluent)
 
 def _design(self):
 feed, = self.ins
 effluent, = self.outs
 length_to_diameter = self.length_to_diameter
 P = effluent.get_property('P', 'psi')
 results = self.design_results
 catalyst = feed.F_mass / self.WHSV
 results['Catalyst weight'] = catalyst
 results['Volume'] = volume = feed.F_vol * self.tau / self.porosity
 D = cylinder_diameter_from_volume(volume, length_to_diameter)
 L = length_to_diameter * D
 results.update(self._vessel_design(P, D, L))
 
 def _cost(self):
 D = self.design_results
 self.purchase_costs.update(
 self._vessel_purchase_cost(D['Weight'], D['Diameter'], D['Length'])
 )
 self.purchase_costs['Catalyst'] = self.catalyst_price * D['Catalyst weight']

[system.py]

import numpy as np
import thermosteam as tmo
import biosteam as bst
from biosteam import Flowsheet as F 
from biosteam import main_flowsheet
from biosteam import units, Stream, SystemFactory
from biosteam.process_tools import UnitGroup
from biorefineries.ccu._chemicals import chems
from biorefineries.ccu import _units
F = bst.Flowsheet('CO2_methane')
bst.main_flowsheet.set_flowsheet(F)
tmo.settings.set_thermo(chems, cache=True)
#%%
# =============================================================================
# 1. MeOH production; based on 
# Design and simulation of a methanol production plant from CO2 hydrogenation
# =============================================================================
#add catalyst
water_stream_1 = Stream('water_stream_1',
 Water=1,
 phase='l',
 total_flow=10000,
 units='kg/hr')
CO2_stream_1 = Stream('CO2_stream_1',
 CO2=1,
 phase='g',
 total_flow=88000,
 units='kg/hr')
# h2 = Stream('h2',
# H2=1,
# phase='g',
# T=25+273.15,
# P=30*101325,
# total_flow=12100,
# units='kg/hr')
 
# CO2 compressing
ks = [bst.units.IsentropicCompressor(P=3*101325), 
 bst.units.IsentropicCompressor(P=8*101325),
 bst.units.IsentropicCompressor(P=26.3*101325)]
hxs = [bst.units.HXutility(T=T) for T in [38+273.15, 38+273.15, 38+273.15]]
C1101 = units.MultistageCompressor('C1101', ins=CO2_stream_1, outs='', compressors=ks, hxs=hxs)
C1102 = units.IsentropicCompressor('C1102', ins=C1101-0, outs='', P=78*101325)
# Water electrolysis
R1101 = _units.Electrolyzer('R1101', ins=water_stream_1, outs=('hydrogen','oxygen'))
@R1101.add_specification(run=True)
def adjust_water_flow():
 C1101.run()
 R1101.ins[0].F_mol = C1101.ins[0].F_mol * 3 # H2:CO2 = 3:1
# H2 compressing to same pressure
ks_2 = [bst.units.IsentropicCompressor(P=78*101325)]
hxs_2 = [bst.units.HXutility(T=164+273.15)]
C1103 = units.MultistageCompressor('C1103', ins=R1101-0, outs='', compressors=ks_2, hxs=hxs_2)
M1101 = units.Mixer('M1101', ins=(C1102-0, C1103-0), outs='', rigorous=True)
M1102 = units.Mixer('M1102', ins=(M1101-0, ''), outs='')
H1101 = units.HXprocess('H1101', ins=(M1102-0, ''), outs=('', ''))
# H1101_1 = units.HXutility('H1101_1', ins=H1101-0, outs='', T=210+273.15)
R1102 = _units.MeOH_SynthesisReactor('R1102', ins=H1101-0, outs='product')
S1101 = units.Splitter('S1101', ins=R1102-0, outs=(1-H1101, ''), split=0.65)
V1101 = units.IsenthalpicValve('V1101', ins=H1101-1, outs='', P=73.6*101325)
M1103 = units.Mixer('M1103', ins=(V1101-0, ''), outs='')
H1102 = units.HXutility('H1102', ins=M1103-0, outs='', T=35+273.15, rigorous=True)
S1102 = units.PhaseSplitter('S1102', ins=H1102-0, outs=('gas', 'condensed_water_and_methanol'))
S1103 = units.Splitter('S1103', ins=S1102-0, outs=('purge', 'recycled'), split=0.01)
C1104 = units.IsentropicCompressor('C1104', ins=S1103-1, outs=1-M1102, P=78*101325)
# For condensed water and methanol in S1102 (composed of methanol, water and residual dissolved gases)
V1102 = units.IsenthalpicValve('V1102', ins=S1102-1, outs='', P=10*101325)
V1103 = units.IsenthalpicValve('V1103', ins=V1102-0, outs='', P=1.2*101325)
F1101 = units.SplitFlash('F1101', ins=V1103-0, outs=('gas', ''), T=22+273.15, P=1.2*101325,
 split=dict(CO2=0.999, H2=0.999))
 
H1103 = units.HXprocess('H1103', ins=(S1101-1, F1101-1), outs=(1-M1103, ''))
D1101 = units.BinaryDistillation('D1101', ins=H1103-1, outs=('gas_MEOH', 'bottom_water'),
 LHK=('Methanol', 'Water'),
 Lr=0.9999, Hr=0.9999, k=2,
 is_divided=True)
sys = bst.main_flowsheet.create_system('MeOH_sys')
sys.set_tolerance(method='fixedpoint')
sys.maxiter = 600 # 200 will not lead to convergence
sys.empty_recycles()
sys.simulate()
sys.diagram()

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      AltStyle によって変換されたページ (->オリジナル) /