Source code for biorefineries.corn.systems

# -*- coding: utf-8 -*-
# BioSTEAM: The Biorefinery Simulation and Techno-Economic Analysis Modules
# Copyright (C) 2020, Yoel Cortes-Pena <yoelcortes@gmail.com>
#                     Yalin Li <mailto.yalin.li@gmail.com>
# 
# This module is under the UIUC open-source license. See 
# github.com/BioSTEAMDevelopmentGroup/biosteam/blob/master/LICENSE.txt
# for license details.
"""
.. contents:: :local:

.. autofunction:: biorefineries.corn.systems.create_system

"""
import biosteam as bst
from biorefineries.ethanol import create_ethanol_purification_system
from .process_settings import BiorefinerySettings
from . import units

__all__ = ('create_system',)

import warnings
import numpy as np
warnings.filterwarnings("error", category=np.ComplexWarning)

[docs] def create_system(flowsheet=None, biorefinery_settings=None): settings = biorefinery_settings or BiorefinerySettings() system_ID = settings.system_ID feedstock_ID = 'corn' if 'corn' in system_ID else 'feedstock' parameters = settings.process_parameters prices = settings.stream_prices GWP_CFs = settings.stream_GWP_CFs get_stream_kwargs = lambda key: { 'price': prices.get(key, 0.), 'characterization_factors': {'GWP': GWP_CFs.get(key, 0.)}, 'units': 'kg/hr', } ### Streams ### chemicals = bst.settings.get_chemicals() z_mass_corn = chemicals.kwarray(settings.feedstock_composition) F_mass_corn = settings.feedstock_hourly_mass_flow mass_corn = F_mass_corn * z_mass_corn feedstock = bst.Stream(feedstock_ID, flow=mass_corn, **get_stream_kwargs(feedstock_ID.capitalize())) feedstock.register_alias('feedstock') crude_oil = bst.Stream('crude_oil', **get_stream_kwargs('Crude oil')) ammonia = bst.Stream('ammonia', NH3=89.723, **get_stream_kwargs('Ammonia')) lime = bst.Stream('lime', CaO=53.609, **get_stream_kwargs('Lime')) aa_price = prices.get('Alpha Amylase') or prices.get('Enzyme', 0.) aa_CF = GWP_CFs.get('Alpha Amylase') or prices.get('Enzyme', 0.) aa_kwargs = { 'price': aa_price, 'characterization_factors': {'GWP': aa_CF}, 'units': 'kg/hr', } alpha_amylase = bst.Stream('alpha_amylase', SolubleProtein=0.00082, Water=0.99918, **aa_kwargs) # F_mass for this (and other feedstock-related streams) # will be adjusted through specification alpha_amylase.F_mass = 32.467 recycled_process_water = bst.Stream('recycled_process_water', Water=1, units='kg/hr') ga_price = prices.get('Gluco Amylase') or prices.get('Enzyme', 0.) ga_CF = GWP_CFs.get('Gluco Amylase') or prices.get('Enzyme', 0.) ga_kwargs = { 'price': ga_price, 'characterization_factors': {'GWP': ga_CF}, 'units': 'kg/hr', } gluco_amylase = bst.Stream('gluco_amylase', SolubleProtein=0.0011, Water=0.9989, **ga_kwargs) gluco_amylase.F_mass = 46.895 sulfuric_acid = bst.Stream('sulfuric_acid', H2SO4=1., **get_stream_kwargs('Sulfuric acid')) sulfuric_acid.F_mass = 92.59300 backwater = bst.Stream('backwater', Water=22484., units='kg/hr') yeast = bst.Stream('yeast', Yeast=3.045, Water=63.335, **get_stream_kwargs('Yeast')) scrubber_water = bst.Stream('scrubber_water', Water=20139.4417, units='kg/hr') ethanol = bst.Stream('ethanol', **get_stream_kwargs('Ethanol')) denaturant = bst.Stream('denaturant', **get_stream_kwargs('Denaturant')) high_pressure_steam = bst.HeatUtility.get_agent('high_pressure_steam') DDGS = bst.Stream('DDGS', **get_stream_kwargs('DDGS')) steam = bst.Stream('steam', Water=1, phase='g', T=high_pressure_steam.T, P=high_pressure_steam.P, **get_stream_kwargs('Steam')) ### Process specifications ### def refresh_feed_specifications(): F_mass_dry_corn = feedstock.F_mass - feedstock.imass['Water'] lime.F_mass = F_mass_dry_corn * parameters['slurry_lime_loading'] ammonia.F_mass = F_mass_dry_corn * parameters['slurry_ammonia_loading'] alpha_amylase.F_mass = F_mass_dry_corn * parameters['liquefaction_alpha_amylase_loading'] sulfuric_acid.F_mass = F_mass_dry_corn * parameters['saccharification_sulfuric_acid_loading'] MH101._run() def update_scrubber_wash_water(): scrubber_water.F_mass = V409.ins[1].F_mass * parameters['scrubber_wash_water_over_vent'] V409._run() ### Units ### MH101 = units.GrainHandling('MH101', feedstock) MH101.add_specification(refresh_feed_specifications) V102 = units.CornStorage('V102', MH101-0) MH103 = units.CleaningSystem('MH103', V102-0, split=0.997) M104 = units.HammerMill('M104', MH103-0) V105 = units.MilledCornSurgeTank('V105', M104-0) W106 = units.MilledCornHopper('W106', V105-0) V107 = units.MilledCornWeighTank('V107', W106-0) V301 = units.AlphaAmylaseTank('V301', alpha_amylase) P302 = bst.Pump('P302', V301-0) V303 = units.AmmoniaTank('V303', ammonia) P304 = bst.Pump('P304', V303-0) V305 = units.LimeHopper('V305', lime) V307 = units.SlurryMixTank('V307', (V107-0, P302-0, P304-0, V305-0, recycled_process_water, backwater)) slurry_solids_content = parameters['slurry_solids_content'] @V307.add_specification(run=True) def correct_recycle_dilution_water(): F_mass_dry_corn = feedstock.F_mass - feedstock.imass['Water'] F_mass_others = lime.F_mass + ammonia.F_mass + alpha_amylase.F_mass + sulfuric_acid.F_mass + gluco_amylase.F_mass recycled_process_water.F_mass = F_mass_dry_corn * (1. - slurry_solids_content) / slurry_solids_content - F_mass_others P311 = bst.Pump('P311', V307-0, P=2e6) E312 = bst.HXprocess('E312', (P311-0, None), U=0.56783, ft=1.0) E313 = units.JetCooker('E313', (E312-0, steam)) V314 = units.CookedSlurrySurgeTank('V314', E313-0) P308 = bst.Pump('P308', V314-0) P308-0-1-E312 # E315 = bst.HXutility('E315', E312-1, U=0.9937, ft=1.0, T= + 273.15) HX101 = bst.HXutility('HX101', E312-1, U=1.5, T=87 + 273.15, ft=1.0) V310 = units.Liquefaction('V310', HX101-0) E316 = bst.HXprocess('E316', (V310-0, None), U=0.85174, ft=1.0, dT=5) V317 = units.GlucoAmylaseTank('V317', gluco_amylase) P318 = bst.Pump('P318', V317-0) V319 = units.SulfuricAcidTank('V319', sulfuric_acid) P320 = bst.Pump('P320', V319-0) V321 = units.Saccharification('V321', (P318-0, P320-0, E316-0)) P322 = bst.Pump('P322', V321-0) E401 = bst.HXprocess('E401', (P322-0, None), phase0='l', phase1='l', U=0.99370, ft=0.85) E402 = bst.HXutility('E402', E401-0, ft=0.95, U=0.9937, T=32.2 + 273.15) V403 = units.YeastTank('V403', yeast) P404 = bst.Pump('P404', V403-0) V405 = units.SSF('V405', (E402-0, P404-0), outs=('CO2', ''), V=1.9e3) @V405.add_specification(run=True) def correct_saccharification_feed_flows(): mash = V405.ins[0] mash_flow = mash.F_mass mash_dry_flow = mash_flow - mash.imass['Water'] yeast.F_mass = parameters['yeast_loading'] * mash_flow gluco_amylase.F_mass = parameters['saccharification_gluco_amylase_loading'] * mash_dry_flow P406 = bst.Pump('P406', V405-1) P407 = bst.Pump('P407', E401-1) P407-0-1-E316 V412 = bst.StorageTank('V412', E316-1, tau=4) PX = bst.Pump('PX', V412-0) V409 = bst.VentScrubber('V409', (scrubber_water, V405-0), gas=('CO2', 'O2')) V409.add_specification(update_scrubber_wash_water) P410 = bst.Pump('P410', V409-1) MX = bst.Mixer('MX', P406-0) MX-0-1-E401 ethanol_purification_sys = create_ethanol_purification_system( ins=[PX-0, denaturant], outs=ethanol, beer_column_heat_integration=True, mockup=True, IDs={ 'Beer column': 'T501', 'Beer column heat exchange': 'E413', 'Beer column bottoms product pump': 'P502', 'Recycle mixer': 'MX3', 'Distillation': 'T503_T507', 'Heat exchanger to superheat vapor to molecular sieves': 'HX500', 'Molecular sieves': 'X504', 'Ethanol condenser': 'HX501', 'Ethanol day tank': 'V511', 'Ethanol day tank pump': 'P512', 'Denaturant storage': 'V509', 'Denaturant pump': 'P510', 'Ethanol-denaturant mixer': 'MX4', 'Product tank': 'V513', 'Distillation bottoms product pump': 'P508', } ) f = flowsheet or bst.main_flowsheet u = f.unit u.X504.approx_duty = False u.T501.Rmin = 0.0001 u.T501.k = 1.05 u.T503_T507.k = 1.05 u.T501.P = 101325 u.T503_T507.P = 101325 u.E413.U = 0.79496 u.E413.ft = 1.0 u.MX4.denaturant_fraction = 0.04345 V601 = bst.MixTank('V601', u.E413-1) P602 = bst.Pump('P602', V601-0) C603 = units.DDGSCentrifuge('C603', P602-0, split=dict( Water=0.8285, Ethanol=0.8285, Yeast=0.2734, Lipid=0.5, # 0.331 originally H2SO4=0.8285, Starch=0.08, Fiber=0.5328, SolubleProtein=0.8285, InsolubleProtein=0.08) ) MH604 = units.WetDDGSConveyor('MH604', C603-1) S1 = bst.Splitter('S1', C603-0, (backwater, ''), split=0.208) V605 = bst.MixTank('V605', S1-1) P606 = bst.Pump('P606', V605-0) Ev607 = bst.MultiEffectEvaporator('Ev607', ins=P606-0, P=(101325, 69682, 47057, 30953, 19781), V=0.90 ) C603_2 = bst.LiquidsSplitCentrifuge('C603_2', Ev607-0, (crude_oil, ''), split={'Oil':0.99}) MX5 = bst.Mixer('MX5', (Ev607-1, P410-0, u.P508-0)) MX6 = bst.Mixer('MX6', (C603_2-1, MH604-0)) D610 = bst.DrumDryer('D610', (MX6-0, 'dryer_air', 'natural_gas'), moisture_content=0.10, split=dict(Ethanol=1.0)) X611 = bst.ThermalOxidizer('X611', (D610-1, 'oxidizer_air', '')) MH612 = units.DDGSHandling('MH612', D610-0, DDGS) T608 = bst.facilities.ProcessWaterCenter( 'T608', (MX5-0, 'makeup_water'), ('process_water', 'wastewater'), makeup_water_streams=(), process_water_streams=(recycled_process_water,) ) other_facilities = units.PlantAir_CIP_WasteWater_Facilities('other_facilities', feedstock) # HXN = bst.HeatExchangerNetwork('HXN', # units=lambda: [u.Ev607.evaporators[0], u.T503_T507.condenser] # ) other_unit_parameters = settings.other_unit_parameters for ID, params in other_unit_parameters.items(): attr, val = params.items() setattr(f.unit.search(ID), attr, val) globals().update(f.unit.data) return f.create_system(system_ID)
# System = bst.System # return System('corn_sys', # [MH101, # V102, # MH103, # M104, # V105, # W106, # V107, # V303, # P304, # V305, # V301, # P302, # V317, # P318, # V319, # P320, # V403, # P404, # System('SYS5', # [V307, # P311, # System('SYS1', # [E312, # E313, # V314, # P308], # recycle=P308-0), # HX101, # V310, # System('SYS3', # [E316, # V321, # P322, # System('SYS2', # [E401, # E402, # V405, # P406], # recycle=P406-0), # P407], # recycle=P407-0), # V412, # System('SYS4', # [E413, # MX2, # P411, # P301, # T501, # P502], # recycle=P502-0), # V601, # P602, # C603, # S1], # recycle=S1-0), # E408, # E408_2, # System('SYS6', # [MX3, # T503_T507, # HX500, # X504], # recycle=X504-0), # HX501, # V511, # P512, # V509, # P510, # MX4, # V513, # V605, # P606, # Ev607, # C603_2, # MX6, # D610, # X611, # MH612, # P508, # MX5, # MX1, # V409, # P410, # MH604], # facilities=[other_facilities, # T608, # HXN])