def system():
    bst.main_flowsheet.clear()
    MockChemical = bst.Chemical('MockChemical', phase='l', search_db=False, default=True)
    bst.settings.set_thermo([MockChemical])
    with bst.System('MockSystem') as system:
        feed = bst.Stream('feed', MockChemical=1e6, units='kg/hr', price=0.150)
        product = bst.Stream('product', price=0.151)
        M1 = bst.MixTank('M1', feed, 's1')
        H1 = bst.HXutility('H1', M1-0, product, T=325, V=0.)
    system.simulate()
    return system
Example #2
0
def get_grouped_species(stream, units='kmol/hr'):
    s = bst.Stream(species=species)
    s.setflow(flow=stream.mol, species=stream.species.IDs)
    return pd.Series({
        i: s.getflow(*j, units=units).sum()
        for i, j in species_groups.items()
    })
Example #3
0
def test_kolmogorov_smirnov_d(model):
    # Test made by Yalin.
    import numpy as np
    import biosteam as bst
    from chaospy import distributions as shape

    bst.settings.set_thermo(['H2O', 'Ethanol'], cache=True)

    s1 = bst.Stream('s1', H2O=100)
    M1 = bst.MixTank(ins=s1)
    M2 = bst.MixTank(ins=M1 - 0)
    sys = bst.System('sys', path=(M1, M2))

    model = bst.Model(sys)

    baseline = 1
    distribution = shape.Uniform(lower=0.5, upper=1.5)

    @model.parameter(name='M1 tau',
                     element=M1,
                     kind='coupled',
                     distribution=distribution,
                     units='hr',
                     baseline=baseline)
    def set_M1_tau(i):
        M1.tau = i

    baseline = 1.75
    distribution = shape.Uniform(lower=1, upper=2)

    @model.parameter(name='M2 tau',
                     element=M2,
                     kind='coupled',
                     distribution=distribution,
                     units='hr',
                     baseline=baseline)
    def set_M2_tau(i):
        M2.tau = i

    model.metrics = [
        bst.Metric(name='tau1', getter=lambda: M1.tau, units='hr', element=M1),
        bst.Metric(name='tau2', getter=lambda: M2.tau, units='hr', element=M2),
    ]

    np.random.seed(3221)
    samples = model.sample(100, rule='L')
    model.load_samples(samples)
    model.evaluate()

    D, p = model.kolmogorov_smirnov_d(
        thresholds=[1, 1.5])  # Just make sure it works for now
Example #4
0
def create_streams(num):
    bst.settings.set_thermo(chems)
    bst_s = []
    for n in range(num):
        s = bst.Stream(Methanol=100 * (n + 1),
                       Ethanol=100 * (n + 1),
                       units='kg/hr')
        bst_s.append(s)

    qs.set_thermo(cmps)
    qs_ws = []
    for n in range(num):
        ws = qs.WasteStream(Methanol=100 * (n + 1),
                            Ethanol=100 * (n + 1),
                            units='kg/hr')
        qs_ws.append(ws)

    return bst_s, qs_ws
Example #5
0
    def __init__(self, ID='', ins=None, outs=(), P=101325):
        Unit.__init__(self, ID, ins, outs)
        self.P = P
        #: [ParallelReaction] Enzymatic hydrolysis reactions including from downstream batch tank in co-fermentation.
        self.saccharification = ParallelRxn([
            #   Reaction definition                   Reactant    Conversion
            Rxn('Glucan -> GlucoseOligomer', 'Glucan', 0.0400),
            Rxn('Glucan + 0.5 H2O -> 0.5 Cellobiose', 'Glucan', 0.0120),
            Rxn('Glucan + H2O -> Glucose', 'Glucan', 0.9000),
            Rxn('Cellobiose + H2O -> Glucose', 'Cellobiose', 1.0000)
        ])

        self.cofermentation = ParallelRxn([
            #   Reaction definition                             Reactant    Conversion
            Rxn('Glucose -> 2 Ethanol + 2 CO2', 'Glucose', 0.9500),
            Rxn('Glucose + 0.047 CSL + 0.018 DAP -> 6 Z_mobilis + 2.4 H2O',
                'Glucose', 0.0200),
            Rxn('Glucose + 2 H2O -> 2 Glycerol + O2', 'Glucose', 0.0040),
            Rxn('Glucose + 2 CO2 -> 2 SuccinicAcid + O2', 'Glucose', 0.0060),
            Rxn('3 Xylose -> 5 Ethanol + 5 CO2', 'Xylose', 0.8500),
            Rxn('Xylose + 0.039 CSL + 0.015 DAP -> 5 Z_mobilis + 2 H2O',
                'Xylose', 0.0190),
            Rxn('3 Xylose + 5 H2O -> 5 Glycerol + 2.5 O2', 'Xylose', 0.0030),
            Rxn('Xylose + H2O -> Xylitol + 0.5 O2', 'Xylose', 0.0460),
            Rxn('3 Xylose + 5 CO2 -> 5 SuccinicAcid + 2.5 O2', 'Xylose',
                0.0090),
            # Losses
            Rxn('Glucose -> 2 LacticAcid', 'Glucose', 0.0300),
            Rxn('3 Xylose -> 5 LacticAcid', 'Xylose', 0.0300),
            Rxn('3 Arabinose -> 5 LacticAcid', 'Arabinose', 0.0300),
            Rxn('Galactose -> 2 LacticAcid', 'Galactose', 0.0300),
            Rxn('Mannose -> 2 LacticAcid', 'Mannose', 0.0300),
        ])

        self.CSL2constituents = Rxn(
            'CSL -> 0.5 H2O + 0.25 LacticAcid + 0.25 Protein', 'CSL', 1.0000)

        self.saccharified_stream = bst.Stream(None)
def update_stripping_water():
    stripping_water.mol[:] = stripping_water_over_vent * vent_stream.massnet


puresys = System('purification',
                 network=(M304, update_stripping_water, D401, M401, T302, H401,
                          D402, H401, P401, H401, ethanol_recycle_sys, P402,
                          H403, T701, P701, adjust_denaturant, T702, P702,
                          M701, JX))

# %% Lignin Separation
bst.Stream.species = species

recycled_water = bst.Stream(Water=1,
                            T=47 + 273.15,
                            P=3.9 * 101325,
                            units='kg/hr')

splits = [('Glucose', 19, 502), ('Xylose', 40, 1022),
          ('OtherSugars', 81, 2175), ('SugarOligomers', 60, 1552),
          ('OrganicSolubleSolids', 612, 15808),
          ('InorganicSolubleSolids', 97, 2513), ('Furfurals', 19, 513),
          ('OtherOrganics', 52, 1348), ('Glucan', 1230, 25), ('Xylan', 415, 8),
          ('OtherStructuralCarbohydrates', 94, 2), ('Lignin', 12226, 250),
          ('Protein', 3376, 69), ('CellMass', 925, 19),
          ('OtherInsolubleSolids', 4489, 92)]

# bst.Stream.default_ID_number = IDnum_400

S401 = units.PressureFilter('S401',
                            ins=('', recycled_water),
def create_ethanol_production_system(ID='ethanol_production_sys',
                                     sugar_solution=None):
    ### Streams ###
    
    # Fresh water
    stripping_water = bst.Stream('stripping_water', Water=5000, units='kg/hr')
    
    # Gasoline
    denaturant = bst.Stream('denaturant', Octane=230.69,
                            units='kg/hr', price=price['Gasoline'])
    
    if not sugar_solution: # Feedstock
        sugar_solution = bst.Stream('sugar_solution',
            Glucose = 3802,
            Sucrose = 4.309e+04,
            Water   = 2.59e+05,
            H3PO4   = 83.33,
            units = 'kg/hr',
            T = 372,
        )
    
    # Yeast
    yeast = bst.Stream('yeast', Water=24700, DryYeast=10300, units='kg/hr')
    
    # Ethanol product
    ethanol = bst.Stream('ethanol', price=price['Ethanol'])
    
    ### Units ###
    
    # Split sugar solution
    S301 = units.Splitter('S301',
                        split=0.265)
    
    # Concentrate sugars
    F301 = units.MultiEffectEvaporator('F301',
                                       P=(101325, 73581, 50892, 32777),
                                       V=0.95) # fraction evaporated
    F301.components['condenser'].U = 1.85
    # Note: value of steam ~ 6.86 for the following 
    # (101325, 73580.467, 50891.17, 32777.406, 19999.925, 11331.5),
    
    # Mix sugar solutions
    M301 = units.Mixer('M301')
    
    # Cool for fermentation
    H301 = units.HXutility('H301', T=295.15)
    
    # Ethanol Production
    R301 = units.Fermentation('R301', outs=('CO2', ''), tau=9, efficiency=0.90, N=4) 
    T301 = units.StorageTank('T301', tau=4, vessel_material='Carbon steel')
    T301.line = 'Beer tank'
    
    D301 = units.VentScrubber('D301', ins=(stripping_water, R301-0), 
                              outs=('vent', ''),
                              gas=('CO2',))
    
    # Separate 99% of yeast
    C301 = units.SolidsCentrifuge('C301', outs=('', 'recycle_yeast'),
                                split=(1, 0.99999, 1, 0.96, 0.01),
                                order=('Ethanol', 'Glucose', 'H3PO4', 
                                       'Water', 'DryYeast'),
                                solids=('DryYeast',))
    
    # Mix in Water
    M302 = units.Mixer('M302')
    P301 = units.Pump('P301')
    
    # Heat up before beer column
    # Exchange heat with stillage
    H302 = units.HXprocess('H302', phase0='l', phase1='l', U=1.28)
    
    # Beer column
    xbot = mass2molar_ethanol_fraction(0.00001)
    ytop = mass2molar_ethanol_fraction(0.574)
    D302 = units.BinaryDistillation('D302', P=101325,
                                y_top=ytop, x_bot=xbot, k=1.25,
                                LHK=('Ethanol', 'Water'))
    D302.tray_material = 'Stainless steel 304'
    D302.vessel_material = 'Stainless steel 304'
    D302.boiler.U = 1.85
    P302 = units.Pump('P302')
    
    # Mix ethanol Recycle (Set-up)
    M303 = units.Mixer('M303')
    
    ytop = mass2molar_ethanol_fraction(0.9061726)
    D303 = units.BinaryDistillation('D303', P=101325,
                                y_top=ytop, x_bot=xbot, k=1.25,
                                LHK=('Ethanol', 'Water'),
                                tray_material='Stainless steel 304',
                                vessel_material='Stainless steel 304',
                                is_divided=True)
    D303.boiler.U = 1.85
    P303 = units.Pump('P303')
    
    # Superheat vapor for mol sieve
    H303 = units.HXutility('H303', T=115+273.15, V=1)
    
    # Molecular sieve
    U301 = units.MolecularSieve('U301',
                                split=(2165.14/13356.04, 1280.06/1383.85),
                                order=('Ethanol', 'Water'))
    
    # Condense ethanol product
    H304 = units.HXutility('H304', 'S149', V=0, T=340.)
    T302 = units.StorageTank('T302', tau=7*24,
                             vessel_type='Floating roof',
                             vessel_material='Carbon steel')
    P304 = units.Pump('P304')
    
    # Storage for gasoline
    T303 = units.StorageTank('T303', tau=7*24,
                             vessel_type='Floating roof',
                             vessel_material='Carbon steel')
    P305 = units.Pump('P305')
    
    # Denatured ethanol product
    T304 = units.MixTank('T304', outs=ethanol)
    T304.tau = 0.10
    
    # Waste water
    M305 = units.Mixer('M305', outs='wastewater')
    
    # Yeast mixing
    T305 = units.MixTank('T305')
    T305.tau = 0.1
    yeast-T305
    
    # Multi-effect evaporator pumps
    P306 = units.Pump('P306')
    
    
    ### Ethanol system set-up ###
    
    sugar_solution-S301-1-F301-0-P306
    (S301-0, P306-0)-M301-H301
    (H301-0, yeast-T305-0)-R301-1-T301-0-C301
    (C301-0, D301-1)-M302-P301
    (P301-0, P302-0)-H302-0-D302-1-P302
    (D302-0, U301-0)-M303-0-D303-0-H303-U301
    D303-1-P303
    
    def adjust_denaturant():
        P304._run()
        pure_ethanol = P304.outs[0]
        denaturant.imol['Octane'] = 0.021*pure_ethanol.F_mass/114.232
        
    P304.specification = adjust_denaturant
    U301-1-H304-0-T302-0-P304
    denaturant-T303-P305
    (P305-0, P304-0)-T304
    (P303-0, F301-1, H302-1)-M305
    
    ### System ###
    
    return bst.System(ID, 
                [S301, 
                 F301, 
                 P306, 
                 M301, 
                 H301, 
                 T305,
                 R301,
                 T301, 
                 C301, 
                 M302, 
                 P301,
                 bst.System('beer_column_heat_integration',
                     [H302,
                      D302,
                      P302],
                     recycle=P302-0),
                 bst.System('ethanol_recycle_from_molecular_sieves',
                     [M303,
                      D303,
                      H303,
                      U301],
                     recycle=U301-0),
                 H304,
                 T302, 
                 P304,
                 T303, 
                 P305, 
                 T304, 
                 D301,
                 P303, 
                 M305])
def create_wastewater_treatment_units(ins, outs, NaOH_price=0.15):
    """
    Create units for wastewater treatment, including anaerobic and aerobic 
    digestion reactors, a membrane bioreactor, a sludge centrifuge, 
    and a reverse osmosis unit.
    
    Parameters
    ----------
    ins : streams
        Wastewater streams (without solids).
    outs : stream sequence
        * [0] methane
        * [1] sludge
        * [2] treated_water
        * [3] waste_brine 
    NaOH_price : float, optional
        Price of NaOH in USD/kg. The default is 0.15.
    
    """
    methane, sludge, treated_water, waste_brine = outs
    well_water = bst.Stream('well_water', Water=1, T=15 + 273.15)
    air = bst.Stream('air_lagoon',
                     O2=51061,
                     N2=168162,
                     phase='g',
                     units='kg/hr')
    caustic = bst.Stream('caustic',
                         Water=2252,
                         NaOH=2252,
                         units='kg/hr',
                         price=NaOH_price)

    wastewater_mixer = bst.Mixer('M601', ins)
    WWTC = WastewaterSystemCost('WWTC', wastewater_mixer - 0)
    anaerobic_digestion = AnaerobicDigestion('R601', (WWTC - 0, well_water),
                                             (methane, '', '', ''))
    recycled_sludge_mixer = bst.Mixer('M602', (anaerobic_digestion - 1, None))

    caustic_over_waste = 2 * caustic.imol['Water', 'NaOH'] / 2544301
    air_over_waste = air.imol['O2', 'N2'] / 2544301
    air.mol[:] = 0.
    waste = recycled_sludge_mixer - 0

    def update_aerobic_input_streams():
        waste, air, caustic = aerobic_digestion.ins
        F_mass_waste = waste.F_mass
        caustic.imol['Water', 'NaOH'] = F_mass_waste * caustic_over_waste
        air.imol['O2', 'N2'] = F_mass_waste * air_over_waste
        aerobic_digestion._run()

    aerobic_digestion = AerobicDigestion('R602', (waste, air, caustic),
                                         outs=('evaporated_water', ''))
    aerobic_digestion.specification = update_aerobic_input_streams
    membrane_bioreactor = MembraneBioreactor('S601', aerobic_digestion - 1)
    sludge_splitter = bst.Splitter('S602', membrane_bioreactor - 1, split=0.96)
    fresh_sludge_mixer = bst.Mixer(
        'M603', (anaerobic_digestion - 2, sludge_splitter - 1))
    sludge_centrifuge = SludgeCentrifuge('S603',
                                         fresh_sludge_mixer - 0,
                                         outs=('', sludge))
    sludge_centrifuge - 0 - 1 - recycled_sludge_mixer
    reverse_osmosis = ReverseOsmosis('S604',
                                     membrane_bioreactor - 0,
                                     outs=(treated_water, waste_brine))
Example #9
0
def create_wastewater_treatment_system(
        wastewater_streams=(),
        wastewater_treatment_area=600,
        NaOH_price=0.15,
):
    """
    Create a system for wastewater treatment.

    Parameters
    ----------
    wastewater_streams : Iterable[:class:`~thermosteam.Stream`], optional
        Wastewater streams (without solids).
    wastewater_treatment_area : int, optional
        Area number to label unit operations. The default is 600.
    NaOH_price : float, optional
        Price of NaOH in USD/kg. The default is 0.15.
    
    Returns
    -------
    wastewater_treatment : :class:`~biosteam.System`
        Wastewater treatment system. The system includes anaerobic and aerobic 
        digestion, a membrane bioreactor, a sludge centrifuge, and reverse osmosis.
        

    """
    n = wastewater_treatment_area
    well_water = bst.Stream('well_water', Water=1, T=15 + 273.15)
    air = bst.Stream('air_lagoon',
                     O2=51061,
                     N2=168162,
                     phase='g',
                     units='kg/hr')
    caustic = bst.Stream('caustic',
                         Water=2252,
                         NaOH=2252,
                         units='kg/hr',
                         price=NaOH_price * 0.5)

    wastewater_mixer = bst.Mixer(f'M{n+1}', wastewater_streams)
    WWTC = WastewaterSystemCost('WWTC', wastewater_mixer - 0)
    anaerobic_digestion = AnaerobicDigestion(f'R{n+1}', (WWTC - 0, well_water))
    recycled_sludge_mixer = bst.Mixer(f'M{n+2}',
                                      (anaerobic_digestion - 1, None))

    caustic_over_waste = caustic.mol / 2544300.6261793654
    air_over_waste = air.mol / 2544300.6261793654
    waste = recycled_sludge_mixer - 0

    def update_aerobic_input_streams():
        F_mass_waste = waste.F_mass
        caustic.mol[:] = F_mass_waste * caustic_over_waste
        air.mol[:] = F_mass_waste * air_over_waste

    aerobic_digestion = AerobicDigestion(f'R{n+2}', (waste, air, caustic),
                                         outs=('evaporated_water', ''))
    membrane_bioreactor = MembraneBioreactor(f'S{n+1}', aerobic_digestion - 1)
    sludge_splitter = bst.Splitter(f'S{n+2}',
                                   membrane_bioreactor - 1,
                                   split=0.96)
    fresh_sludge_mixer = bst.Mixer(
        f'M{n+3}', (anaerobic_digestion - 2, sludge_splitter - 1))
    sludge_centrifuge = SludgeCentrifuge(f'S{n+3}',
                                         fresh_sludge_mixer - 0,
                                         outs=('', 'sludge'))
    sludge_centrifuge - 0 - 1 - recycled_sludge_mixer
    reverse_osmosis = ReverseOsmosis(f'S{n+4}',
                                     membrane_bioreactor - 0,
                                     outs=('treated_water', 'waste_brine'))

    aerobic_digestion_sys = bst.System(
        'aerobic_digestion_sys',
        path=(recycled_sludge_mixer, update_aerobic_input_streams,
              aerobic_digestion, membrane_bioreactor, sludge_splitter,
              fresh_sludge_mixer, sludge_centrifuge),
        recycle=recycled_sludge_mixer - 0)

    wastewater_treatment = bst.System('wastewater_treatment',
                                      path=[
                                          wastewater_mixer, WWTC,
                                          anaerobic_digestion,
                                          aerobic_digestion_sys,
                                          reverse_osmosis
                                      ])
    return wastewater_treatment
Example #10
0
bst.main_flowsheet.set_flowsheet('sugarcane_pretreatment_section')

F_mass_sugarcane = 333334
z_mass_sugarcane = chemicals.kwarray(
    dict(Glucose=0.0120811,
         Lignin=0.0327653,
         Solids=0.015,
         Sucrose=0.136919,
         Ash=0.006,
         Cellulose=0.0611531,
         Hemicellulose=0.036082,
         Water=0.7))

sugarcane = sugar_cane = bst.Stream('sugar_cane',
                                    flow=F_mass_sugarcane * z_mass_sugarcane,
                                    units='kg/hr',
                                    price=price['Sugar cane'])

enzyme = bst.Stream('enzyme',
                    Cellulose=100,
                    Water=900,
                    units='kg/hr',
                    price=price['Protease'])

imbibition_water = bst.Stream('imbibition_water',
                              Water=87023.35,
                              units='kg/hr',
                              T=338.15)

H3PO4 = bst.Stream('H3PO4',
                   H3PO4=74.23,
Example #11
0
def create_system(ID='sugarcane_sys'):
    ### Streams ###
    chemicals = bst.settings.get_chemicals()

    z_mass_sugarcane = chemicals.kwarray(
        dict(Glucose=0.0120811,
             Lignin=0.0327653,
             Solids=0.015,
             Sucrose=0.136919,
             Ash=0.006,
             Cellulose=0.0611531,
             Hemicellulose=0.036082,
             Water=0.7))

    sugarcane = bst.Stream('sugarcane',
                           flow=333334 * z_mass_sugarcane,
                           units='kg/hr',
                           price=price['Sugar cane'])

    enzyme = bst.Stream('enzyme',
                        Cellulose=100,
                        Water=900,
                        units='kg/hr',
                        price=price['Protease'])

    imbibition_water = bst.Stream('imbibition_water',
                                  Water=87023.35,
                                  units='kg/hr',
                                  T=338.15)

    H3PO4 = bst.Stream('H3PO4',
                       H3PO4=74.23,
                       Water=13.10,
                       units='kg/hr',
                       price=price['H3PO4'])  # to T203

    lime = bst.Stream('lime',
                      CaO=333.00,
                      Water=2200.00,
                      units='kg/hr',
                      price=price['Lime'])  # to P5

    polymer = bst.Stream('polymer',
                         Flocculant=0.83,
                         units='kg/hr',
                         price=price['Polymer'])  # to T205

    rvf_wash_water = bst.Stream('rvf_wash_water',
                                Water=16770,
                                units='kg/hr',
                                T=363.15)  # to C202

    ### Unit operations ###

    # Feed the shredder
    U101 = units.ConveyingBelt('U101', ins=sugarcane)

    # Separate metals
    U102 = units.MagneticSeparator('U102', ins=U101 - 0)

    # Shredded cane
    U103 = units.Shredder('U103', ins=U102 - 0)

    # Hydrolyze starch
    T201 = units.EnzymeTreatment('T201', T=323.15)  # T=50

    # Finely crush lipid cane
    U201 = units.CrushingMill('U201',
                              split=dict(Ash=0.92,
                                         Cellulose=0.92,
                                         Glucose=0.04,
                                         Hemicellulose=0.92,
                                         Lignin=0.92,
                                         Sucrose=0.04,
                                         Solids=1),
                              moisture_content=0.5)

    # Convey out bagasse
    U202 = units.ConveyingBelt('U202', ins=U201.outs[0], outs='Bagasse')

    # Mix in water
    M201 = units.Mixer('M201')
    # crushing_mill_recycle_sys = bst.System('crushing_mill_recycle_sys',
    #                                path=(U201, S201, M201),
    #                                recycle=M201-0)

    # Screen out fibers
    S201 = units.VibratingScreen('S201',
                                 split=dict(Ash=0.35,
                                            Cellulose=0.35,
                                            Glucose=0.88,
                                            Hemicellulose=0.35,
                                            Lignin=0.35,
                                            Solids=0,
                                            Sucrose=0.88,
                                            Water=0.88))

    # Store juice before treatment
    T202 = units.StorageTank('T202', tau=4, vessel_material='Carbon steel')

    # Heat up before adding acid
    H201 = units.HXutility('H201', T=343.15)

    # Mix in acid
    T203 = units.MixTank('T203')

    # Pump acid solution
    P201 = units.Pump('P201')

    # Mix lime solution
    T204 = units.MixTank('T204', tau=0.10)
    P202 = units.Pump('P202')

    # Blend acid lipid solution with lime
    T205 = units.MixTank('T205', tau=0.10)

    # Mix recycle
    M202 = units.Mixer('M202')

    # Heat before adding flocculant
    H202 = units.HXutility('H202', T=372.15)

    # Mix in flocculant
    T206 = units.MixTank('T206')
    T206.tau = 0.10

    # Separate residual solids
    C201 = units.Clarifier('C201',
                           split=dict(Ash=0,
                                      CaO=0,
                                      Cellulose=0,
                                      Flocculant=0.522,
                                      Glucose=0.522,
                                      Hemicellulose=0,
                                      Lignin=0,
                                      H3PO4=0.522,
                                      Sucrose=0.522,
                                      Water=0.522))

    # Remove solids as filter cake
    C202 = units.RVF('C202',
                     outs=('filter_cake', ''),
                     moisture_content=0.80,
                     split=dict(Ash=0.85,
                                CaO=0.85,
                                Cellulose=0.85,
                                Glucose=0.01,
                                Hemicellulose=0.85,
                                Lignin=0.85,
                                Sucrose=0.01))
    P203 = units.Pump('P203')

    # Screen out small fibers from sugar stream
    S202 = units.VibratingScreen('S202',
                                 outs=('', 'fiber_fines'),
                                 split=dict(Ash=1.0,
                                            CaO=1.0,
                                            Cellulose=1.0,
                                            Flocculant=0.0,
                                            Glucose=0.998,
                                            Hemicellulose=1.0,
                                            Lignin=1.0,
                                            H3PO4=1.0,
                                            Sucrose=0.998,
                                            Water=0.998))
    S202.mesh_opening = 2

    ### Process specifications ###

    # Specifications dependent on lipid cane flow rate
    def correct_flows():
        U103._run()
        F_mass = sugarcane.F_mass
        # correct enzyme, lime, phosphoric acid, and imbibition water
        enzyme.imass['Cellulose',
                     'Water'] = 0.003 * F_mass * np.array([0.1, 0.9])
        lime.imass['CaO', 'Water'] = 0.001 * F_mass * np.array([0.046, 0.954])
        H3PO4.imass['H3PO4', 'Water'] = 0.00025 * F_mass
        imbibition_water.imass['Water'] = 0.25 * F_mass

    U103.specification = correct_flows

    # Specifications within a system
    def correct_wash_water():
        P202._run()
        solids = P202.outs[0].imol['Ash', 'CaO', 'Cellulose', 'Hemicellulose',
                                   'Lignin'].sum()
        rvf_wash_water.imol['Water'] = 0.0574 * solids

    P202.specification = correct_wash_water

    ### System set-up ###

    (U103 - 0, enzyme) - T201
    (T201 - 0, M201 - 0) - U201 - 1 - S201 - 0 - T202
    (S201 - 1, imbibition_water) - M201

    T202 - 0 - H201
    (H201 - 0, H3PO4) - T203 - P201
    (P201 - 0, lime - T204 - 0) - T205 - P202
    (P202 - 0, P203 - 0) - M202 - H202
    (H202 - 0, polymer) - T206 - C201
    (C201 - 1, rvf_wash_water) - C202 - 1 - P203
    C201 - 0 - S202

    ### Ethanol section ###

    ethanol_production_sys = create_ethanol_production_system(
        sugar_solution=S202 - 0)

    ### Facilities ###

    s = F.stream
    BT = units.BoilerTurbogenerator(
        'BT', (U202 - 0, '', 'boiler_makeup_water', 'natural_gas', '', ''),
        boiler_efficiency=0.80,
        turbogenerator_efficiency=0.85)

    CT = units.CoolingTower('CT')
    makeup_water_streams = (s.cooling_tower_makeup_water,
                            s.boiler_makeup_water)
    process_water_streams = (s.imbibition_water, rvf_wash_water,
                             s.stripping_water, *makeup_water_streams)
    makeup_water = bst.Stream('makeup_water', price=0.000254)

    CWP = units.ChilledWaterPackage('CWP')
    PWC = units.ProcessWaterCenter('PWC', (bst.Stream(), makeup_water), (),
                                   None, makeup_water_streams,
                                   process_water_streams)

    ### System ###

    return bst.System(
        ID,
        [
            U101, U102, U103, T201,
            bst.System("juice_extraction_sys", [U201, S201, M201],
                       recycle=M201 - 0), T202, H201, T203, P201, T204, T205,
            P202,
            bst.System('juice_separation_sys',
                       [M202, H202, T206, C201, C202, P203],
                       recycle=P203 - 0), S202, ethanol_production_sys, U202
        ],
        facilities=(CWP, BT, CT, PWC),
    )
Example #12
0
from biorefineries.lipidcane.process_settings import price

__all__ = ('lipidcane_sys', 'lipidcane_tea', 'lipidcane', 'lipid_cane')

# %% Pretreatment section

bst.settings.set_thermo(pretreatment_chemicals)

### Streams ###

lipidcane = lipid_cane = bst.Stream('lipid_cane',
                                    Ash=2000.042,
                                    Cellulose=26986.69,
                                    Glucose=2007.067,
                                    Hemicellulose=15922.734,
                                    Lignin=14459.241,
                                    Lipid=10035.334,
                                    Solids=5017.667,
                                    Sucrose=22746.761,
                                    Water=234157.798,
                                    units='kg/hr',
                                    price=price['Lipid cane'])

enzyme = bst.Stream('enzyme',
                    Cellulose=100,
                    Water=900,
                    units='kg/hr',
                    price=price['Protease'])

imbibition_water = bst.Stream('imbibition_water',
                              Water=87023.35,
                              units='kg/hr',
Example #13
0
def test_equipment_lifetimes():
    from biorefineries.sugarcane import create_tea
    bst.settings.set_thermo(['Water'], cache=True)
    
    class A(bst.Unit):
        _BM = {
            'Equipment A': 2,
            'Equipment B': 3,
        }
        _equipment_lifetime = {
            'Equipment A': 10,
            'Equipment B': 5,
        }
        def _cost(self):
            purchase_costs = self.purchase_costs
            purchase_costs['Equipment A'] = 1e6
            purchase_costs['Equipment B'] = 1e5
            
    class B(bst.Unit):
        _BM = {
            'Equipment A': 2,
        }
        _equipment_lifetime = 15
        def _cost(self):
            self.purchase_costs['Equipment A'] = 1e6

    class C(bst.Unit):
        _BM = {
            'Equipment A': 4,
        }
        def _cost(self):
            self.purchase_costs['Equipment A'] = 1e6
            
    @bst.decorators.cost('Flow rate', units='kmol/hr', S=1, BM=3,
                         cost=1e6, n=0.6, CE=bst.CE, lifetime=8)
    class D(bst.Unit): pass
    
    @bst.decorators.cost('Flow rate', units='kmol/hr', S=1, BM=4,
                         cost=1e6, n=0.6, CE=bst.CE, lifetime=20)
    class E(bst.Unit): pass
    
    D_feed = bst.Stream('D_feed', Water=1)
    E_feed = D_feed.copy('E_feed')
    units = [A(None, 'A_feed'), B(None, 'B_feed'), C(None, 'C_feed'), D(None, D_feed), E(None, E_feed)]
    test_sys = bst.System('test_sys', units)
    test_sys.simulate()
    tea = create_tea(test_sys)
    table = tea.get_cashflow_table()
    C_FCI = table['Fixed capital investment [MM$]']
    # Test with lang factor = 3 (default for sugarcane biorefinery)
    cashflows_FCI = [6.12, 9.18, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 3.0, 
                     0.0, 3.3, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0]
    assert_allclose(C_FCI, cashflows_FCI)
    # Cashflows include maintainance and others, so all entries are not zero
    cashflows = [-6120000.0, -9945000.0, -4321300.0, -4321300.0, -4321300.0, 
                 -4321300.0, -4321300.0, -4621300.0, -4321300.0, -4321300.0, 
                 -7321300.0, -4321300.0, -7621300.0, -4321300.0, -4321300.0, 
                 -4321300.0, -4321300.0, -4621300.0, -4321300.0, -4321300.0, 
                 -4321300.0, -3556300.0]
    assert_allclose(tea.cashflow_array, cashflows)
    
    # Test with bare module costs
    tea.lang_factor = None
    table = tea.get_cashflow_table()
    C_FCI = table['Fixed capital investment [MM$]']
    cashflows_FCI = [6.12, 9.18, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 3.0, 
                     0.0, 2.3, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 0.0, 0.0, 0.0]
    assert_allclose(C_FCI, cashflows_FCI)
    cashflows = [-6120000.0, -9945000.0, -4321300.0, -4321300.0, -4321300.0, 
                 -4321300.0, -4321300.0, -4621300.0, -4321300.0, -4321300.0, 
                 -7321300.0, -4321300.0, -6621300.0, -4321300.0, -4321300.0, 
                 -4321300.0, -4321300.0, -4621300.0, -4321300.0, -4321300.0, 
                 -4321300.0, -3556300.0]
    assert_allclose(tea.cashflow_array, cashflows)
Example #14
0
def synthesize_network(hus, T_min_app=5., Qmin=1e-3, force_ideal_thermo=False):
    pinch_T_arr, hot_util_load, cold_util_load, T_in_arr, T_out_arr,\
        hxs, hot_indices, cold_indices, indices, streams_inlet, hx_utils_rearranged, \
        streams_quenched = temperature_interval_pinch_analysis(hus, T_min_app, force_ideal_thermo)
    H_out_arr = [i.H for i in streams_quenched]
    duties = np.array([abs(hx.Q) for hx in hxs])
    dTs = np.abs(T_in_arr - T_out_arr)
    dTs[dTs == 0.] = 1e-12
    C_flow_vector = duties / dTs
    Q_hot_side = {}
    Q_cold_side = {}
    stream_HXs_dict = {i: [] for i in indices}
    is_cold = lambda x: x in cold_indices
    load_duties(streams_inlet, streams_quenched, pinch_T_arr, T_out_arr,
                indices, is_cold, Q_hot_side, Q_cold_side)
    matches_hs = {i: [] for i in cold_indices}
    matches_cs = {i: [] for i in hot_indices}
    candidate_hot_streams = hot_indices.copy()
    candidate_cold_streams = cold_indices.copy()
    HXs_hot_side = []
    HXs_cold_side = []
    streams_transient_cold_side = [i.copy() for i in streams_inlet]
    streams_transient_hot_side = [i.copy() for i in streams_inlet]
    for i in hot_indices:
        s = streams_transient_cold_side[i]
        if s.T != pinch_T_arr[i]:
            s.vle(T=pinch_T_arr[i], P=s.P)
    for i in cold_indices:
        s = streams_transient_hot_side[i]
        if s.T != pinch_T_arr[i]:
            s.vle(T=pinch_T_arr[i], P=s.P)

    def get_stream_at_H_max(cold):
        s_cs = streams_transient_cold_side[cold]
        s_hs = streams_transient_hot_side[cold]
        return s_cs if s_cs.H > s_hs.H else s_hs

    def get_stream_at_H_min(hot):
        s_cs = streams_transient_cold_side[hot]
        s_hs = streams_transient_hot_side[hot]
        return s_cs if s_cs.H < s_hs.H else s_hs

    def get_T_transient_cold_side(index):
        return streams_transient_cold_side[index].T

    def get_T_transient_hot_side(index):
        return streams_transient_hot_side[index].T

    attempts = set()
    # ------------- Cold side design ------------- #
    unavailables = set(
        [i for i in hot_indices if T_out_arr[i] >= pinch_T_arr[i]])
    unavailables.update(
        [i for i in cold_indices if T_in_arr[i] >= pinch_T_arr[i]])
    for hot in hot_indices:
        stream_quenched = False
        potential_matches = []
        for cold in cold_indices:
            if (C_flow_vector[hot] >= C_flow_vector[cold]
                    and get_T_transient_cold_side(hot) >
                    get_T_transient_cold_side(cold) + T_min_app
                    and (hot not in unavailables)
                    and (cold not in unavailables)
                    and (cold not in matches_cs[hot])
                    and (cold in candidate_cold_streams)):
                potential_matches.append(cold)
        potential_matches = sorted(
            potential_matches,
            key=lambda pot_cold: min(C_flow_vector[hot], C_flow_vector[
                pot_cold]) * (get_T_transient_cold_side(hot) -
                              get_T_transient_cold_side(pot_cold) - T_min_app),
            reverse=True)
        for cold in potential_matches:
            ID = 'HX_%s_%s_cs' % (hot, cold)
            if ID in attempts: continue
            attempts.add(ID)
            Q_hstr = Q_cold_side[hot][1]
            Q_cstr = Q_cold_side[cold][1]
            Q_res = Q_cstr - Q_hstr
            # if abs(get_T_transient_cold_side(cold) - pinch_T_arr[cold])<= 0.01:
            #     continue
            hot_stream = streams_transient_cold_side[hot].copy()
            cold_stream = streams_transient_cold_side[cold].copy()

            hot_stream.ID = 's_%s__%s' % (hot, ID)
            cold_stream.ID = 's_%s__%s' % (cold, ID)
            hot_out = bst.Stream('%s__s_%s' % (ID, hot),
                                 thermo=hot_stream.thermo)
            cold_out = bst.Stream('%s__s_%s' % (ID, cold),
                                  thermo=cold_stream.thermo)
            H_lim = H_out_arr[hot]
            new_HX = bst.units.HXprocess(ID=ID,
                                         ins=(hot_stream, cold_stream),
                                         outs=(hot_out, cold_out),
                                         H_lim0=H_lim,
                                         T_lim1=pinch_T_arr[cold],
                                         dT=T_min_app,
                                         thermo=hot_stream.thermo)
            new_HX._run()
            if abs(new_HX.Q) < Qmin: continue
            HXs_cold_side.append(new_HX)
            stream_HXs_dict[hot].append(new_HX)
            stream_HXs_dict[cold].append(new_HX)
            Q_cold_side[hot][1] -= new_HX.Q
            Q_cold_side[cold][1] -= new_HX.Q
            streams_transient_cold_side[hot] = new_HX.outs[0]
            streams_transient_cold_side[cold] = new_HX.outs[1]
            H_out = new_HX.outs[0].H
            assert H_out - new_HX.ins[0].H <= 0.
            stream_quenched = H_out < H_lim or np.allclose(H_out, H_lim)
            matches_cs[hot].append(cold)
            if stream_quenched:
                break

    # ------------- Hot side design ------------- #
    unavailables = set(
        [i for i in hot_indices if T_in_arr[i] <= pinch_T_arr[i]])
    unavailables.update(
        [i for i in cold_indices if T_out_arr[i] <= pinch_T_arr[i]])

    for cold in cold_indices:
        # streams_transient_hot_side[cold] = streams_transient_cold_side[cold].copy()
        # T_transient_hot_side[cold] = min(T_transient_hot_side[cold], get_T_transient_cold_side(cold))
        potential_matches = []
        for hot in candidate_hot_streams:
            if ((cold in matches_cs and hot in matches_cs[cold])
                    or (cold in matches_hs and hot in matches_hs[cold])):
                break
            if (C_flow_vector[cold] >= C_flow_vector[hot]
                    and get_T_transient_hot_side(hot) >
                    get_T_transient_hot_side(cold) + T_min_app
                    and (hot not in unavailables)
                    and (cold not in unavailables)
                    and (hot not in matches_hs[cold])
                    and (hot in candidate_hot_streams)):
                potential_matches.append(hot)

        potential_matches = sorted(
            potential_matches,
            key=lambda x: (min(C_flow_vector[cold], C_flow_vector[x]) *
                           (get_T_transient_hot_side(x) -
                            get_T_transient_hot_side(cold) - T_min_app)),
            reverse=True)
        stream_quenched = False
        for hot in potential_matches:
            ID = 'HX_%s_%s_hs' % (cold, hot)
            if ID in attempts: continue
            attempts.add(ID)
            Q_hstr = Q_hot_side[hot][1]
            Q_cstr = Q_hot_side[cold][1]
            Q_res = Q_cstr - Q_hstr
            # if abs(get_T_transient_hot_side(hot) - pinch_T_arr[hot])< 1e-6:
            #     continue
            hot_stream = streams_transient_hot_side[hot].copy()
            cold_stream = streams_transient_hot_side[cold].copy()
            cold_stream.ID = 's_%s__%s' % (cold, ID)
            hot_stream.ID = 's_%s__%s' % (hot, ID)
            hot_out = bst.Stream('%s__s_%s' % (ID, hot),
                                 thermo=hot_stream.thermo)
            cold_out = bst.Stream('%s__s_%s' % (ID, cold),
                                  thermo=cold_stream.thermo)
            H_lim = H_out_arr[cold]
            new_HX = bst.units.HXprocess(ID=ID,
                                         ins=(cold_stream, hot_stream),
                                         outs=(cold_out, hot_out),
                                         H_lim0=H_lim,
                                         T_lim1=pinch_T_arr[hot],
                                         dT=T_min_app,
                                         thermo=hot_stream.thermo)
            try:
                new_HX._run()
            except:
                continue
            if abs(new_HX.Q) < Qmin: continue
            HXs_hot_side.append(new_HX)
            stream_HXs_dict[hot].append(new_HX)
            stream_HXs_dict[cold].append(new_HX)
            Q_hot_side[hot][1] -= new_HX.Q
            Q_hot_side[cold][1] -= new_HX.Q
            streams_transient_hot_side[cold] = new_HX.outs[0]
            streams_transient_hot_side[hot] = new_HX.outs[1]
            H_out = new_HX.outs[0].H
            assert H_out - new_HX.ins[0].H >= 0.
            stream_quenched = H_out > H_lim or np.allclose(H_out, H_lim)
            matches_hs[cold].append(hot)
            if stream_quenched:
                break

    # Offset heating requirement on cold side
    for cold in cold_indices:
        if Q_cold_side[cold][0] == 'heat' and Q_cold_side[cold][1] > 0:
            for hot in hot_indices:
                ID = 'HX_%s_%s_cs' % (hot, cold)
                if ID in attempts: continue
                attempts.add(ID)
                T_cold_in = get_T_transient_cold_side(cold)
                T_hot_in = get_T_transient_cold_side(hot)
                # if ((cold in matches_cs and hot in matches_cs[cold])
                #     or (cold in matches_hs and hot in matches_hs[cold])):
                #     continue
                if (Q_cold_side[hot][0] == 'cool' and Q_cold_side[hot][1] > 0
                        and T_hot_in - T_cold_in >= T_min_app):
                    # if abs(T_cold_in - pinch_T_arr[cold])<= 0.01:
                    #     continue
                    hot_stream = streams_transient_cold_side[hot].copy()
                    cold_stream = streams_transient_cold_side[cold].copy()
                    hot_stream.ID = 's_%s__%s' % (hot, ID)
                    cold_stream.ID = 's_%s__%s' % (cold, ID)
                    hot_out = bst.Stream('%s__s_%s' % (ID, hot),
                                         thermo=hot_stream.thermo)
                    cold_out = bst.Stream('%s__s_%s' % (ID, cold),
                                          thermo=cold_stream.thermo)
                    new_HX = bst.units.HXprocess(ID=ID,
                                                 ins=(hot_stream, cold_stream),
                                                 outs=(hot_out, cold_out),
                                                 H_lim0=H_out_arr[hot],
                                                 T_lim1=T_out_arr[cold],
                                                 dT=T_min_app,
                                                 thermo=hot_stream.thermo)
                    try:
                        new_HX._run()
                    except:
                        continue
                    if abs(new_HX.Q) < Qmin: continue
                    HXs_cold_side.append(new_HX)
                    stream_HXs_dict[hot].append(new_HX)
                    stream_HXs_dict[cold].append(new_HX)
                    Q_cold_side[hot][1] -= new_HX.Q
                    Q_cold_side[cold][1] -= new_HX.Q
                    streams_transient_cold_side[hot] = new_HX.outs[0]
                    streams_transient_cold_side[cold] = new_HX.outs[1]
                    matches_cs[hot].append(cold)

    # Offset cooling requirement on hot side
    for hot in hot_indices:
        stream_quenched = False
        if Q_hot_side[hot][0] == 'cool' and Q_hot_side[hot][1] > 0:
            for cold in cold_indices:
                ID = 'HX_%s_%s_hs' % (cold, hot)
                if ID in attempts: continue
                attempts.add(ID)
                # if ((hot in matches_cs and cold in matches_cs[hot])
                #     or (hot in matches_hs and cold in matches_hs[hot])):
                #     continue
                original_cold_stream = get_stream_at_H_max(cold)
                T_cold_in = original_cold_stream.T
                T_hot_in = get_T_transient_hot_side(hot)
                if (Q_hot_side[cold][0] == 'heat' and Q_hot_side[cold][1] > 0
                        and T_hot_in - T_cold_in >= T_min_app):
                    # if abs(T_hot_in - pinch_T_arr[hot])<= 0.01:
                    #     continue
                    cold_stream = original_cold_stream.copy()
                    hot_stream = streams_transient_hot_side[hot].copy()
                    cold_stream.ID = 's_%s__%s' % (cold, ID)
                    hot_stream.ID = 's_%s__%s' % (hot, ID)
                    hot_out = bst.Stream('%s__s_%s' % (ID, hot),
                                         thermo=hot_stream.thermo)
                    cold_out = bst.Stream('%s__s_%s' % (ID, cold),
                                          thermo=cold_stream.thermo)
                    H_lim = H_out_arr[cold]
                    new_HX = bst.units.HXprocess(ID=ID,
                                                 ins=(cold_stream, hot_stream),
                                                 outs=(cold_out, hot_out),
                                                 H_lim0=H_lim,
                                                 T_lim1=T_out_arr[hot],
                                                 dT=T_min_app,
                                                 thermo=hot_stream.thermo)
                    try:
                        new_HX._run()
                    except:
                        continue
                    if abs(new_HX.Q) < Qmin: continue
                    HXs_hot_side.append(new_HX)
                    stream_HXs_dict[hot].append(new_HX)
                    stream_HXs_dict[cold].append(new_HX)
                    Q_hot_side[hot][1] -= new_HX.Q
                    Q_hot_side[cold][1] -= new_HX.Q
                    streams_transient_hot_side[cold] = new_HX.outs[0]
                    streams_transient_hot_side[hot] = new_HX.outs[1]
                    H_out = new_HX.outs[0].H
                    assert H_out - new_HX.ins[0].H >= 0.
                    stream_quenched = H_out > H_lim or np.allclose(
                        H_out, H_lim)
                    matches_hs[cold].append(hot)
                    if stream_quenched:
                        break

    def get_hottest_stream_from_life_cycle(cold):
        s_hottest = get_stream_at_H_max(cold)
        H_max = s_hottest.H
        chemicals = s_hottest.chemicals
        for u in HXs_cold_side + HXs_hot_side:
            for s in u.outs:
                if '_%s_' % (cold) in s.ID and '__s_%s' % (
                        cold
                ) in s.ID and s.chemicals is chemicals and np.allclose(
                        s.mol, s_hottest.mol):
                    if s.H > H_max:
                        H_max = s.H
                        s_hottest = s
        return s_hottest

    def get_coldest_stream_from_life_cycle(hot):
        s_coldest = get_stream_at_H_min(hot)
        H_min = s_coldest.H
        chemicals = s_coldest.chemicals
        for u in HXs_cold_side + HXs_hot_side:
            for s in u.outs:
                if '_%s_' % (hot) in s.ID and '__s_%s' % (
                        hot
                ) in s.ID and s.chemicals is chemicals and np.allclose(
                        s.mol, s_coldest.mol):
                    if s.H < H_min:
                        H_min = s.H
                        s_coldest = s
        return s_coldest

    # Add final utility HXs
    new_HX_utils = []
    for hot in hot_indices:
        hot_stream = get_coldest_stream_from_life_cycle(hot).copy()
        ID = 'Util_%s_cs' % (hot)
        hot_stream.ID = 's_%s__%s' % (hot, ID)
        outsID = '%s__s_%s' % (ID, hot)
        new_HX_util = bst.units.HXutility(ID=ID,
                                          ins=hot_stream,
                                          outs=outsID,
                                          H=H_out_arr[hot],
                                          rigorous=True,
                                          thermo=hot_stream.thermo)
        new_HX_util._run()
        s_out = new_HX_util - 0
        np.testing.assert_allclose(s_out.H, H_out_arr[hot], rtol=5e-3, atol=1.)
        atol_T = 2. if 's' in hxs[hot].outs[0].phases else 0.001
        np.testing.assert_allclose(s_out.T,
                                   T_out_arr[hot],
                                   rtol=5e-3,
                                   atol=atol_T)
        new_HX_utils.append(new_HX_util)
        stream_HXs_dict[hot].append(new_HX_util)

    for cold in cold_indices:
        cold_stream = get_hottest_stream_from_life_cycle(cold).copy()
        ID = 'Util_%s_hs' % (cold)
        cold_stream.ID = 's_%s__%s' % (cold, ID)
        outsID = '%s__s_%s' % (ID, cold)
        new_HX_util = bst.units.HXutility(ID=ID,
                                          ins=cold_stream,
                                          outs=outsID,
                                          H=H_out_arr[cold],
                                          rigorous=True,
                                          thermo=cold_stream.thermo)
        new_HX_util._run()
        s_out = new_HX_util - 0
        np.testing.assert_allclose(s_out.H,
                                   H_out_arr[cold],
                                   rtol=1e-2,
                                   atol=1.)
        atol_T = 2. if 's' in hxs[cold].outs[0].phases else 0.001
        np.testing.assert_allclose(s_out.T,
                                   T_out_arr[cold],
                                   rtol=5e-2,
                                   atol=atol_T)
        new_HX_utils.append(new_HX_util)
        stream_HXs_dict[cold].append(new_HX_util)

    return HXs_hot_side, HXs_cold_side, new_HX_utils, hxs, T_in_arr,\
           T_out_arr, pinch_T_arr, C_flow_vector, hx_utils_rearranged, streams_inlet, stream_HXs_dict,\
           hot_indices, cold_indices
Example #15
0
def create_system(ID='lipidcane_sys'):
    chemicals = bst.settings.get_chemicals()
    s = bst.main_flowsheet.stream
    u = bst.main_flowsheet.unit

    ### Streams ###

    lipidcane = lipidcane = bst.Stream('lipidcane',
                                       Ash=2000.042,
                                       Cellulose=26986.69,
                                       Glucose=2007.067,
                                       Hemicellulose=15922.734,
                                       Lignin=14459.241,
                                       Lipid=10035.334,
                                       Solids=5017.667,
                                       Sucrose=22746.761,
                                       Water=234157.798,
                                       units='kg/hr',
                                       price=price['Lipid cane'])

    enzyme = bst.Stream('enzyme',
                        Cellulose=100,
                        Water=900,
                        units='kg/hr',
                        price=price['Protease'])

    imbibition_water = bst.Stream('imbibition_water',
                                  Water=87023.35,
                                  units='kg/hr',
                                  T=338.15)

    H3PO4 = bst.Stream('H3PO4',
                       H3PO4=74.23,
                       Water=13.10,
                       units='kg/hr',
                       price=price['H3PO4'])  # to T203

    lime = bst.Stream('lime',
                      CaO=333.00,
                      Water=2200.00,
                      units='kg/hr',
                      price=price['Lime'])  # to P5

    polymer = bst.Stream('polymer',
                         Flocculant=0.83,
                         units='kg/hr',
                         price=price['Polymer'])  # to T205

    rvf_wash_water = bst.Stream('rvf_wash_water',
                                Water=16770,
                                units='kg/hr',
                                T=363.15)  # to C202

    oil_wash_water = bst.Stream('oil_wash_water',
                                Water=1350,
                                units='kg/hr',
                                T=358.15)  # to T207

    ### Unit operations ###

    bst.Stream.ticket_name = 'd'
    bst.Stream.ticket_number = 100

    # Feed the shredder
    U101 = units.ConveyingBelt('U101', ins=lipidcane)
    U101.cost_items['Conveying belt'].ub = 5000

    # Separate metals
    U102 = units.MagneticSeparator('U102', ins=U101 - 0)

    # Shredded cane
    U103 = units.Shredder('U103', ins=U102 - 0)

    bst.Stream.ticket_number = 200

    # Hydrolyze starch
    T201 = units.EnzymeTreatment('T201', T=323.15)  # T=50

    # Finely crush lipid cane
    U201 = units.CrushingMill('U201',
                              split=dict(Ash=0.92,
                                         Cellulose=0.92,
                                         Glucose=0.04,
                                         Hemicellulose=0.92,
                                         Lignin=0.92,
                                         Sucrose=0.04,
                                         Lipid=0.1,
                                         Solids=1),
                              moisture_content=0.5)

    # Convey out bagasse
    U202 = units.ConveyingBelt('U202', ins=U201.outs[0], outs='Bagasse')

    # Mix in water
    M201 = units.Mixer('M201')

    # Screen out fibers
    S201 = units.VibratingScreen('S201',
                                 split=dict(Ash=0.35,
                                            Cellulose=0.35,
                                            Glucose=0.88,
                                            Hemicellulose=0.35,
                                            Lignin=0.35,
                                            Lipid=0.88,
                                            Solids=0,
                                            Sucrose=0.88,
                                            Water=0.88))

    # Store juice before treatment
    T202 = units.StorageTank('T202', tau=4, vessel_material='Carbon steel')

    # Heat up before adding acid
    H201 = units.HXutility('H201', T=343.15, V=0)

    # Mix in acid
    T203 = units.MixTank('T203')
    T203.tau = 0.10

    # Pump acid solution
    P201 = units.Pump('P201')

    # Mix lime solution
    T204 = units.MixTank('T204')
    T204.tau = 0.10
    P202 = units.Pump('P202')

    # Blend acid lipid solution with lime
    T205 = units.MixTank('T205')

    # Mix recycle
    M202 = units.Mixer('M202')

    # Heat before adding flocculant
    H202 = units.HXutility('H202', T=372.15, V=0)

    # Mix in flocculant
    T206 = units.MixTank('T206')
    T206.tau = 0.10

    # Separate residual solids
    C201 = units.Clarifier('C201',
                           split=dict(Ash=0,
                                      CaO=0,
                                      Cellulose=0,
                                      Flocculant=0.522,
                                      Glucose=0.522,
                                      Hemicellulose=0,
                                      Lignin=0,
                                      Lipid=0.98,
                                      H3PO4=0.522,
                                      Sucrose=0.522,
                                      Water=0.522))

    # Remove solids as filter cake
    C202 = units.RVF('C202',
                     outs=('filter_cake', ''),
                     moisture_content=0.80,
                     split=dict(Ash=0.85,
                                CaO=0.85,
                                Cellulose=0.85,
                                Glucose=0.01,
                                Hemicellulose=0.85,
                                Lignin=0.85,
                                Sucrose=0.01))
    P203 = units.Pump('P203')

    # Separate oil and sugar
    T207 = units.MixTank('T207')
    T207_2 = units.Splitter('T207_2', split=dict(Lipid=1, Water=1e-4))

    # Cool the oil
    H203 = units.HXutility('H203', T=343.15, V=0)

    # Screen out small fibers from sugar stream
    S202 = units.VibratingScreen('S202',
                                 outs=('', 'fiber_fines'),
                                 split=dict(Ash=1.0,
                                            CaO=1.0,
                                            Cellulose=1.0,
                                            Flocculant=0.0,
                                            Glucose=0.998,
                                            Hemicellulose=1.0,
                                            Lignin=1.0,
                                            Lipid=1.0,
                                            H3PO4=1.0,
                                            Sucrose=0.998,
                                            Water=0.998))
    sugar = S202 - 0
    S202.mesh_opening = 2

    # Add distilled water to wash lipid
    T208 = units.MixTank('T208')
    T208.tau = 0.10

    # Centrifuge out water
    C203 = units.LiquidsSplitCentrifuge('C203',
                                        split=dict(Lipid=0.99, Water=0.01))

    # Vacume out water
    F201 = units.SplitFlash('F201',
                            T=357.15,
                            P=2026.5,
                            outs=('water_vapor', ''),
                            split=dict(Lipid=0.0001, Water=0.999))

    ### Process specifications ###
    def correct_flows():
        F_mass = lipidcane.F_mass
        # correct enzyme, lime, phosphoric acid, and imbibition water
        enzyme.imass['Cellulose',
                     'Water'] = 0.003 * F_mass * np.array([0.1, 0.9])
        lime.imass['CaO', 'Water'] = 0.001 * F_mass * np.array([0.046, 0.954])
        H3PO4.imass['H3PO4', 'Water'] = 0.00025 * F_mass
        imbibition_water.imass['Water'] = 0.25 * F_mass
        T201._run()

    T201.specification = correct_flows

    # Specifications within a system
    def correct_lipid_wash_water():
        oil_wash_water.imol['Water'] = 100 / 11 * H202.outs[0].imol['Lipid']
        T208._run()

    T208.specification = correct_lipid_wash_water

    def correct_wash_water():
        P202._run()
        solids = P202.outs[0].imol['Ash', 'CaO', 'Cellulose', 'Hemicellulose',
                                   'Lignin'].sum()
        rvf_wash_water.imol['Water'] = 0.0574 * solids

    P202.specification = correct_wash_water

    ### System set-up ###

    (U103 - 0, enzyme) - T201
    (T201 - 0, M201 - 0) - U201 - 1 - S201 - 0 - T202
    (S201 - 1, imbibition_water) - M201

    T202 - 0 - H201
    (H201 - 0, H3PO4) - T203 - P201
    (P201 - 0, lime - T204 - 0) - T205 - P202
    (P202 - 0, P203 - 0) - M202 - H202
    (H202 - 0, polymer) - T206 - C201
    (C201 - 1, rvf_wash_water) - C202 - 1 - P203

    C201 - 0 - T207 - T207_2 - 0 - H203
    (H203 - 0, oil_wash_water) - T208 - C203 - 0 - F201
    T207 - T207_2 - 1 - S202

    lipid = F201 - 1

    ### Ethanol section ###

    ### Utilities ###

    MW_etoh = chemicals.Ethanol.MW
    MW_water = chemicals.Water.MW

    def mass2molar_ethanol_fraction(ethanol_mass_fraction):
        """Return ethanol mol fraction in a ethanol water mixture"""
        x = ethanol_mass_fraction
        return x / MW_etoh / (x / MW_etoh + (1 - x) / MW_water)

    ### Input streams ###

    ethanol_production_sys = create_ethanol_production_system(
        sugar_solution=S202 - 0)
    u.M305.ins.append(C203 - 1)

    ### Biodiesel section ###

    ### Streams ###

    # Fresh degummed oil
    oil = lipid

    # Fresh methanol
    methanol = bst.Stream('methanol', Methanol=1, price=price['Methanol'])

    # Catalyst
    catalyst = bst.Stream('catalyst',
                          NaOCH3=0.25,
                          Methanol=0.75,
                          units='kg/hr',
                          price=price['NaOCH3'])
    # price=0.25*price['NaOCH3'] + 0.75*Methanol.price)

    # Water to remove glycerol
    biodiesel_wash_water = bst.Stream('biodiesel_wash_water',
                                      Water=13.6,
                                      T=273.15 + 60,
                                      price=price['Water'])

    # Acid to neutralize catalyst after second centrifuge
    HCl1 = bst.Stream('HCl1', HCl=0.21, Water=0.79, price=price['HCl'])
    # price=0.21*price['HCl'] + 0.79*Water.price) # 35% HCl by mass

    # Acid to remove soaps after first centrifuge
    HCl2 = bst.Stream('HCl2', HCl=0.21, Water=0.79, price=HCl1.price)

    # Base to neutralize acid before distillation
    NaOH = bst.Stream('NaOH', NaOH=1, price=price['NaOH'])

    # Products
    crude_glycerol = bst.Stream('crude_glycerol',
                                price=price['Crude glycerol'])
    biodiesel = bst.Stream('biodiesel', price=price['Biodiesel'])

    # Waste
    waste = bst.Stream('waste', price=price['Waste'])

    ### Units ###

    ### Biodiesel Transesterification Section ###

    # Aparently reactors are adiabatic, meoh coming in at 40C, lipid at 60C

    # From USDA Biodiesel model
    x_cat = 1.05e-05  # Catalyst molar fraction in methanol feed

    # Mix Recycle Methanol and Fresh Methanol
    T401 = units.StorageTank('T401')
    P401 = units.Pump('P401')

    # Storage Tank for Catalyst
    T402 = units.StorageTank('T402')
    P402 = units.Pump('P402')

    # Tank for oil
    T403 = units.StorageTank('T403')
    T403.tau = 4
    P403 = units.Pump('P403')

    # Mix Methanol and Catalyst stream
    T404 = units.MixTank('T404')
    P404 = units.Pump('P404')

    # Split Methanol/Catalyst to reactors (this is done through a process specification, so use a fake splitter)
    S401 = bst.FakeSplitter('S401')

    # First Reactor
    R401 = units.Transesterification('R401',
                                     efficiency=0.90,
                                     methanol2lipid=6,
                                     T=333.15,
                                     catalyst_molfrac=x_cat)

    # Centrifuge to remove glycerol
    C401 = units.LiquidsSplitCentrifuge('C401',
                                        split=dict(Lipid=0.99,
                                                   Methanol=0.40,
                                                   Glycerol=0.06,
                                                   Biodiesel=0.999,
                                                   Water=0.40,
                                                   NaOH=0,
                                                   HCl=0,
                                                   NaOCH3=0.40))

    P405 = units.Pump('P405')

    # Second Reactor
    R402 = units.Transesterification('R402',
                                     efficiency=0.90,
                                     methanol2lipid=6,
                                     T=333.15,
                                     catalyst_molfrac=x_cat)

    def adjust_feed_to_reactors():
        R402._run()
        S401.ins[0].sum(S401.outs)

    R402.specification = adjust_feed_to_reactors

    # Centrifuge to remove glycerol
    C402 = units.LiquidsSplitCentrifuge('C402',
                                        split=dict(Lipid=0.90,
                                                   Methanol=0.10,
                                                   Glycerol=0.05,
                                                   Biodiesel=0.999,
                                                   Water=0.10,
                                                   NaOH=0,
                                                   HCl=0,
                                                   NaOCH3=0.10))

    # Acids and bases per catalyst by mol
    k1 = 0.323 / 1.5
    k2 = 1.060 / 1.5
    k3 = 0.04505 / 1.5

    def adjust_acid_and_base():
        T404._run()
        # Adjust according to USDA biodiesel model
        catalyst_mol = T404.outs[0].imol['NaOCH3']
        NaOH.imol['NaOH'] = k1 * catalyst_mol
        HCl1.imol['HCl'] = k2 * catalyst_mol
        HCl2.imol['HCl'] = k3 * catalyst_mol

    T404.specification = adjust_acid_and_base

    ### Biodiesel Purification Section ###

    # Water wash
    T405 = units.MixTank('T405')
    P406 = units.Pump('P406')

    # Centrifuge out water
    C403 = units.LiquidsRatioCentrifuge('C403',
                                        K_chemicals=('Methanol', 'Glycerol'),
                                        Ks=np.array([0.382, 0.183]),
                                        top_solvents=('Biodiesel', ),
                                        top_split=(0.999, ),
                                        bot_solvents=('Water', 'Lipid', 'NaOH',
                                                      'HCl'),
                                        bot_split=(0.999, 1, 1, 1))

    # Vacuum dry biodiesel
    # Consider doing this by split, and keeping this unit constant
    # 290 Pa, 324 K according to USDA Biodiesel Model
    F401 = units.SplitFlash('F401',
                            order=('Water', 'Methanol', 'Biodiesel'),
                            split=(0.9999, 0.9999, 0.00001),
                            P=2026.5,
                            T=331.5,
                            Q=0)
    F401.line = 'Vacuum dryer'
    F401.material = 'Stainless steel 304'
    P407 = units.Pump('P407')

    ### Glycerol Purification Section ###

    # Condense vacuumed methanol to recycle
    H401 = units.HXutility('H401', V=0, T=295)
    P408 = units.Pump('P408')

    # Mix recycled streams and HCl
    T406 = units.MixTank('T406')
    P409 = units.Pump('P409')

    # Centrifuge out waste fat
    # assume all the lipid, free_lipid and biodiesel is washed out
    C404 = units.LiquidsSplitCentrifuge('C404',
                                        outs=('', waste),
                                        order=('Methanol', 'Glycerol',
                                               'Water'),
                                        split=(0.999, 0.999, 0.999))

    # Add and mix NaOH
    T407 = units.MixTank('T407')
    P410 = units.Pump('P410')

    # Methanol/Water distillation column
    D401 = units.BinaryDistillation('D401',
                                    LHK=('Methanol', 'Water'),
                                    P=101325,
                                    y_top=0.99999,
                                    x_bot=0.0001,
                                    k=2.5,
                                    is_divided=True,
                                    vessel_material='Stainless steel 304',
                                    tray_material='Stainless steel 304')

    # Condense water to recycle
    H402 = units.HXutility('H402', T=353, V=0)

    # Glycerol/Water flash (not a distillation column)
    w = 0.20 / chemicals.Water.MW
    g = 0.80 / chemicals.Glycerol.MW
    x_water = w / (w + g)

    D402 = units.BinaryDistillation('D402',
                                    LHK=('Water', 'Glycerol'),
                                    k=1.25,
                                    P=101325,
                                    y_top=0.999,
                                    x_bot=x_water,
                                    tray_material='Stainless steel 304',
                                    vessel_material='Stainless steel 304')

    def startup_water():
        imol = D402.ins[0].imol
        water, glycerol = imol['Water', 'Glycerol']
        minimum_water = 5 * (w / (w + g)) * glycerol
        if water < minimum_water:
            imol['Water'] = minimum_water
        D402._run()
        # Remove accumulation
        D402.outs[0].imol['Water'] = 1100 * C402.outs[0].imol['Glycerol']

    D402.specification = startup_water

    # Condense recycle methanol
    H403 = units.HXutility('H403', V=0, T=315)
    P411 = units.Pump('P411')

    # Condense recycle water
    H404 = units.HXutility('H404', V=0, T=315)
    P412 = units.Pump('P412')

    # Storage tank for glycerol
    T408 = units.StorageTank('T408', outs=crude_glycerol)

    # Storage tank for biodiesel
    T409 = units.StorageTank('T409', outs=biodiesel)
    F401 - 1 - P407 - 0 - T409

    ### Biodiesel system set-up ###

    # Biodiesel Transesterification Section
    oil - T403 - P403
    (P403 - 0, S401 - 0) - R401 - 0 - C401
    (C401 - 0, S401 - 1) - R402 - 0 - C402 - 1

    # Specs for product https://www.afdc.energy.gov/fuels/biodiesel_specifications.html
    # minimum spec requirements:
    #  0.050 wt % water (lower to 0.045)
    #  0.2 wt % meoh (lower to 0.15)
    #  0.02 wt % glycerol (lower to 0.015)
    #  0.4 wt % free lipids (lower to 0.35)

    # Find Water Flow
    def adjust_biodiesel_wash_water():
        total_glycerol = (C401.outs[1].imol['Glycerol'] +
                          R402.outs[0].imol['Glycerol'])
        wash_water = (x_water / (1 - x_water) * total_glycerol -
                      HCl1.imol['Water'] - NaOH.imol['Water'] -
                      oil.imol['Water'] - HCl2.imol['Water'])
        biodiesel_wash_water.imol[
            'Water'] = wash_water if wash_water > 0 else 0.
        T405._run()

    T405.specification = adjust_biodiesel_wash_water
    D402 - 0 - H404 - 0 - P412

    # Biodiesel wash
    (C402 - 0, P412 - 0, biodiesel_wash_water, HCl1) - T405 - P406 - C403

    # Glycerol recycle and purification section
    C403 - 0 - F401
    F401 - 0 - H401 - P408
    C401 - 1 - P405
    (P405 - 0, C402 - 1, C403 - 1, P408 - 0, HCl2) - T406 - P409 - C404
    (C404 - 0, NaOH) - T407 - P410
    H402 - 0 - D401 - 1 - D402 - 1 - T408
    P410 - 0 - H402

    # Mass Balance for Methanol, Recycle Methanol, and Catalyst stream
    B401 = bst.MassBalance(
        'B401',
        description='Adjust catalyst and methanol feed to reactors',
        variable_inlets=[catalyst, methanol],
        constant_inlets=[D401 - 0],
        constant_outlets=[1**R401, 1**R402],
        chemical_IDs=('Methanol', 'NaOCH3'))

    # Find Fresh Methanol Flow
    D401 - 0 - B401 - H403 - P411  # Recycle methanol
    methanol - T401 - P401  # Mix fresh and recycled methanol
    catalyst - T402 - P402  # Fresh catalyst
    (P411 - 0, P401 - 0,
     P402 - 0) - T404 - P404 - S401  # Mix Catalyst with Methanol

    # Initial guess
    D402.outs[0].imol['Methanol', 'Glycerol',
                      'Water'] = [0.00127, 3.59e-05, 0.0244]

    ### Facilities ###

    # Burn bagasse from conveyor belt
    BT = units.BoilerTurbogenerator(
        'BT', (U202 - 0, '', 'boiler_makeup_water', 'natural_gas', '', ''),
        boiler_efficiency=0.80,
        turbogenerator_efficiency=0.85)

    CT = units.CoolingTower('CT')
    makeup_water_streams = (s.cooling_tower_makeup_water,
                            s.boiler_makeup_water)

    process_water_streams = (s.imbibition_water, s.biodiesel_wash_water,
                             oil_wash_water, rvf_wash_water, s.stripping_water,
                             *makeup_water_streams)

    makeup_water = bst.Stream('makeup_water', price=0.000254)

    CWP = units.ChilledWaterPackage('CWP')
    PWC = units.ProcessWaterCenter('PWC', (bst.Stream(), makeup_water), (),
                                   None, makeup_water_streams,
                                   process_water_streams)

    return bst.System(
        ID,
        [
            U101, U102, U103, T201,
            bst.System('juice_extraction_sys', [U201, S201, M201],
                       recycle=M201 - 0), T202, H201, T203, P201, T204, T205,
            P202,
            bst.System(
                'juice_separation_sys', [M202, H202, T206, C201, C202, P203],
                recycle=P203 - 0), T207, T207_2, H203, T208, C203, F201, T403,
            P403, R401, C401, R402, C402,
            bst.System('methanol_recycle_sys', [
                T406, P409, C404, T407, P410, H402, D401, D402, H404, P412,
                T405, P406, C403
            ],
                       recycle=C403 - 1), F401, P407, T409, H401, P408, P405,
            B401, H403, P411, T401, P401, T402, P402, T404, P404, S401, S202,
            ethanol_production_sys, T408, U202
        ],
        facilities=(CWP, BT, CT, PWC),
    )
Example #16
0
def create_ethanol_subsystem_example():
    """
    Test BioSTEAM by creating a conventional sugarcane fermentation and ethanol
    purification process.
    
    Examples
    --------
    >>> ethanol_sys = create_ethanol_subsystem_example()
    >>> # The sugarcane_example_subsystem flowsheet may help for accessing units
    >>> from biosteam import main_flowsheet as F
    >>> fs = F.flowsheet['ethanol_subsystem_example']
    >>> fs.unit # Check unit operation registry
    Register:
     <Fermentation: R301>
     <StorageTank: T301>
     <VentScrubber: D301>
     <SolidsCentrifuge: C301>
     <Mixer: M302>
     <Pump: P301>
     <HXprocess: H302>
     <BinaryDistillation: D302>
     <Pump: P302>
     <Mixer: M303>
     <BinaryDistillation: D303>
     <Pump: P303>
     <HXutility: H303>
     <MolecularSieve: U301>
    >>> R301 = fs.unit.R301 # Get unit operation

    """
    original_flowsheet = main_flowsheet.get_flowsheet()
    main_flowsheet.set_flowsheet('ethanol_subsystem_example')
    
    ### Create property package ###
    
    chemicals = tmo.Chemicals(
        ['Water', 'Ethanol', 'Glucose',
         'Sucrose', 'H3PO4', 'P4O10',
         'CO2', 'Octane', 'O2']
    )
    
    Water, Ethanol, Glucose, Sucrose, H3PO4, P4O10, CO2, Octane, O2 = chemicals
    
    CO2.at_state(phase='g')
    H3PO4.at_state(phase='s')
    P4O10.at_state(phase='s')
    Glucose.at_state(phase='s')
    Sucrose.at_state(phase='s')
    
    DryYeast = tmo.Chemical('DryYeast', MW=1., phase='s',
                            search_db=False, default=True, CAS='Yeast')
    chemicals.append(DryYeast)
    
    Ash = tmo.Chemical('Ash', MW=1., search_db=False, phase='s', default=True)
    chemicals.append(Ash)
    
    # Insolubles occupy a significant volume
    insoluble_solids = (Ash, DryYeast)
    
    # Solubles don't occupy much volume
    soluble_solids = (H3PO4, Glucose, Sucrose) 
    
    for chemical in insoluble_solids:
        V = fn.rho_to_V(rho=1540, MW=chemical.MW)
        chemical.V.add_model(V, top_priority=True)
    
    for chemical in soluble_solids:
        V = fn.rho_to_V(rho=1e5, MW=chemical.MW)
        chemical.V.add_model(V, top_priority=True)
    
    # Add constant models for molar heat capacity of solids
    Ash.Cn.add_model(0.09 * 4.184 * Ash.MW) 
    for chemical in chemicals: chemical.default()
    bst.settings.set_thermo(chemicals)
    chemicals.set_synonym('Water', 'H2O')
    
    ### Create fresh streams ###
    
    # Fresh water
    stripping_water = bst.Stream('stripping_water', Water=5000, units='kg/hr')
    fermentation_feed = bst.Stream('fermentation_feed', phase='l',
                                Glucose=21.11,
                                Sucrose=125.9,
                                Water=1370 + 4409,
                                H3PO4=0.7575,
                                DryYeast=1.03e+04)
    
    # Ethanol Production
    R301 = units.Fermentation('R301', outs=('CO2', ''), tau=9, efficiency=0.90, N=4) 
    T301 = units.StorageTank('T301', tau=4, vessel_material='Carbon steel')
    T301.line = 'Beer tank'
    
    D301 = units.VentScrubber('D301', ins=(stripping_water, R301-0), gas=('CO2',))
    
    # Separate 99% of yeast
    C301 = units.SolidsCentrifuge('C301', outs=('recycle_yeast', ''),
                                split=(1, 0.99999, 1, 0.96, 0.01),
                                order=('Ethanol', 'Glucose', 'H3PO4', 
                                       'Water', 'DryYeast'),
                                solids=('DryYeast',))
    C301.split[:] = 1. - C301.split
    # Mix in Water
    M302 = units.Mixer('M302')
    P301 = units.Pump('P301')
    
    # Heat up before beer column
    # Exchange heat with stillage
    H302 = units.HXprocess('H302', outs=('', 'stillage'),
                          phase0='l', phase1='l', U=1.28)
    
    # Beer column
    x_bot = 3.910570816782338e-06
    y_top = 0.34508430224337167
    D302 = units.BinaryDistillation('D302', P=101325,
                                y_top=y_top, x_bot=x_bot, k=1.25,
                                LHK=('Ethanol', 'Water'))
    D302.tray_material = 'Stainless steel 304'
    D302.vessel_material = 'Stainless steel 304'
    D302.boiler.U = 1.85
    P302 = units.Pump('P302')
    
    # Mix ethanol Recycle (Set-up)
    M303 = units.Mixer('M303')
    x_bot = 3.910570816782338e-06
    y_top = 0.7906528373264998
    D303 = units.BinaryDistillation('D303', P=101325,
                                y_top=y_top, x_bot=x_bot, k=1.25,
                                LHK=('Ethanol', 'Water'),
                                tray_material='Stainless steel 304',
                                vessel_material='Stainless steel 304',
                                is_divided=True)
    D303.boiler.U = 1.85
    P303 = units.Pump('P303')
    
    # Superheat vapor for mol sieve
    H303 = units.HXutility('H303', T=115+273.15, V=1)
    
    # Molecular sieve
    U301 = units.MolecularSieve('U301',
                                split=(2165.14/13356.04, 1280.06/1383.85),
                                order=('Ethanol', 'Water'))
    
    fermentation_feed-R301-1-T301-0-C301
    (C301-1, D301-1)-M302-P301
    (P301-0, P302-0)-H302-0-D302-1-P302
    (D302-0, U301-0)-M303-0-D303-0-H303-U301
    D303-1-P303
    
    ethanol_subsystem_example = main_flowsheet.create_system('ethanol_subsystem_example')
    ethanol_subsystem_example.simulate()
    main_flowsheet.set_flowsheet(original_flowsheet) 
    return ethanol_subsystem_example