Example #1
0
    def __init__(self, initScript=None):
        """Init the flash

        Init Info:
        nuLiqphases = 2
        nuStreamsIn = 2

        """
        super(LLStage, self).__init__(initScript)

        # Create a separator
        self.innerFlash = innerFlash = Flash.SimpleFlash()
        self.AddUnitOperation(innerFlash, FLASH)

        # Create a balance
        self.innerMixer = innerMixer = Balance.BalanceOp()
        self.AddUnitOperation(innerMixer, MIX)

        # Initialize params
        self.InitializeParameters()

        # Share the ports directly
        self.ports_mat_OUT = innerFlash.ports_mat_OUT
        self.ports_mat_IN = innerMixer.ports_mat_IN

        # Connect the balance to the separator
        self.ConnectPorts(MIX, OUT_PORT + str(0), FLASH, IN_PORT)
Example #2
0
def TestMoleBalance():
    print("""Init TestMoleBalance ++++++++++++++++++++++++++++++""")
    pkgName = "Peng-Robinson"
    cmpNames = ("PROPANE", "n-BUTANE")
    thAdmin = ThermoAdmin.ThermoAdmin()
    providers = thAdmin.GetAvThermoProviderNames()
    provider = providers[0]  # Should be Virt Mat
    thCase = 'myTh'
    thermo = thAdmin.AddPkgFromName(provider, thCase, pkgName)

    flowSh = Flowsheet.Flowsheet()
    flowSh.SetThermoAdmin(thAdmin)
    flowSh.SetThermo(thermo)
    for i in cmpNames:
        thAdmin.AddCompound(provider, thCase, i)

    pIn1 = flowSh.CreatePort(IN | MAT, 'pIn1')
    pIn2 = flowSh.CreatePort(IN | MAT, 'pIn2')
    pOut1 = flowSh.CreatePort(OUT | MAT, 'pOut1')
    pOut2 = flowSh.CreatePort(OUT | MAT, 'pOut2')

    pIn1.SetCompositionValue("PROPANE", .3, FIXED_V)
    pIn1.SetCompositionValue("n-BUTANE", .7, FIXED_V)

    pIn2.SetCompositionValue("PROPANE", .4, FIXED_V)
    pIn2.SetCompositionValue("n-BUTANE", .6, FIXED_V)

    pOut1.SetCompositionValue("PROPANE", .6, FIXED_V)
    pOut1.SetCompositionValue("n-BUTANE", .4, FIXED_V)

    pOut2.SetCompositionValue("PROPANE", .8, FIXED_V)
    pOut2.SetCompositionValue("n-BUTANE", .2, FIXED_V)

    pIn1.SetPropValue(MOLEFLOW_VAR, 1000, FIXED_V)
    pOut1.SetPropValue(MOLEFLOW_VAR, 1500, FIXED_V)

    myBalance = Balance.Balance(Balance.MOLE_BALANCE)
    myBalance.AddInput(pIn1)
    myBalance.AddInput(pIn2)
    myBalance.AddOutput(pOut1)
    myBalance.AddOutput(pOut2)

    myBalance.DoBalance()

    print('moleFlowIn1', pIn1.GetPropValue(MOLEFLOW_VAR))
    print('moleFlowIn2', pIn2.GetPropValue(MOLEFLOW_VAR))
    print('moleFlowOut1', pOut1.GetPropValue(MOLEFLOW_VAR))
    print('moleFlowOut2', pOut2.GetPropValue(MOLEFLOW_VAR))
    temp1 = (pOut1.GetPropValue(MOLEFLOW_VAR) + pOut2.GetPropValue(MOLEFLOW_VAR))
    print('moleBalance', (pIn1.GetPropValue(MOLEFLOW_VAR) + pIn2.GetPropValue(MOLEFLOW_VAR)) - temp1)

    print("""Finished TestMoleBalance ++++++++++++++++++++++++++++++""")
    flowSh.CleanUp()
    thAdmin.CleanUp()
Example #3
0
 def __init__(self, initScript=None):
     """
     create the ports and init the balance
     """
     UnitOperations.UnitOperation.__init__(self, initScript)
     self.portOut0 = self.CreatePort(OUT | MAT, OUT_PORT + str(0))
     self.portOut1 = self.CreatePort(OUT | MAT, OUT_PORT + str(1))
     self.portIn = self.CreatePort(IN | MAT, IN_PORT)
     self._balance = Balance.Balance(Balance.MOLE_BALANCE | Balance.ENERGY_BALANCE)
     self._balance.AddInput(self.portIn)
     self._balance.AddOutput(self.portOut0)
     self._balance.AddOutput(self.portOut1)
     self.splits = SplitList(self)  # list to hold split fraction signal ports
     self.borrowedSplits = None  # used by containing op to be notified of split list changes
Example #4
0
    def UpdatePortsIn(self):
        """Update the amount and names of the ports in"""
        nuPorts = self.GetNumberPorts(MAT | IN)
        nuStIn = self.parameters[NUSTIN_PAR]

        for i in range(nuPorts, nuStIn, -1):
            self.DeletePortNamed(IN_PORT + str(i - 1))
        for i in range(nuPorts, nuStIn):
            self.CreatePort(MAT | IN, IN_PORT + str(i))

        self._balance = Balance.Balance(Balance.MOLE_BALANCE
                                        | Balance.ENERGY_BALANCE)
        self._balance.AddOutput(self.GetPort(OUT_PORT))
        for i in range(nuStIn):
            self._balance.AddInput(self.GetPort(IN_PORT + str(i)))
Example #5
0
    def __init__(self, initScript=None):
        super(ConvReactor, self).__init__(initScript)
        self.isoRxn = IsothermalConvReactor()
        self.AddUnitOperation(self.isoRxn, 'IsoRxn')
        self.isoRxn.containerUnitOp = self

        self.heater = Heater.Heater()
        self.AddUnitOperation(self.heater, 'RxnHeater')

        self.baln = Balance.BalanceOp()
        self.AddUnitOperation(self.baln, 'EneBalance')

        # Initialize with one energy In and Out as a default
        # The parameter QEXOTHERMIC_ISPOS_PAR will set the missing energy port
        self.baln.SetParameterValue(NUSTIN_PAR + Balance.S_ENE, 1)
        self.baln.SetParameterValue(NUSTOUT_PAR + Balance.S_ENE, 1)
        self.baln.SetParameterValue(Balance.BALANCETYPE_PAR, Balance.ENERGY_BALANCE)

        # to create an Energy Out port for export
        self.balEneSensor = Sensor.EnergySensor()
        self.AddUnitOperation(self.balEneSensor, 'BalEneSensor')
        self.eneSensor = Sensor.EnergySensor()
        self.AddUnitOperation(self.eneSensor, 'EneSensor')
        self.eneStream = Stream.Stream_Energy()
        self.AddUnitOperation(self.eneStream, 'EneStream')

        # connect the child unit ops
        self.ConnectPorts('IsoRxn', OUT_PORT + 'Q', 'EneBalance', IN_PORT + 'Q0')
        self.ConnectPorts('RxnHeater', IN_PORT + 'Q', 'EneBalance', OUT_PORT + 'Q0')
        self.ConnectPorts('IsoRxn', OUT_PORT, 'RxnHeater', IN_PORT)

        self.ConnectPorts('EneSensor', OUT_PORT, 'EneStream', IN_PORT)
        #
        self.ConnectPorts('BalEneSensor', SIG_PORT, 'EneSensor', SIG_PORT)

        # borrow child ports
        self.BorrowChildPort(self.eneStream.GetPort(OUT_PORT), OUT_PORT + 'Q')
        self.BorrowChildPort(self.isoRxn.GetPort(IN_PORT), IN_PORT)
        self.BorrowChildPort(self.heater.GetPort(OUT_PORT), OUT_PORT)
        self.BorrowChildPort(self.heater.GetPort(DELTAP_PORT), DELTAP_PORT)

        self.SetParameterValue(NURXN_PAR, 0)
        self.SetParameterValue(SIMULTANEOUSRXN_PAR, 1)
        self.SetParameterValue(QEXOTHERMIC_ISPOS_PAR, 1)
Example #6
0
    def __init__(self, initScript=None):
        super(EquilibriumReactor, self).__init__(initScript)
        self.itnRxn = InternalEqmReactor()
        self.AddUnitOperation(self.itnRxn, 'itnRxn')
        self.itnRxn.containerUnitOp = self

        self.baln = Balance.BalanceOp()
        self.AddUnitOperation(self.baln, 'EneBalance')

        self.baln.SetParameterValue(NUSTIN_PAR + Balance.S_ENE, 1)
        self.baln.SetParameterValue(Balance.BALANCETYPE_PAR,
                                    Balance.ENERGY_BALANCE)

        # to create an Energy Out port for export
        self.balEneSensor = Sensor.EnergySensor()
        self.AddUnitOperation(self.balEneSensor, 'BalEneSensor')
        self.eneSensor = Sensor.EnergySensor()
        self.AddUnitOperation(self.eneSensor, 'EneSensor')
        self.eneStream = Stream.Stream_Energy()
        self.AddUnitOperation(self.eneStream, 'EneStream')

        # connect the child unit ops
        self.ConnectPorts('itnRxn', OUT_PORT + 'Q', 'EneBalance',
                          IN_PORT + 'Q0')
        self.ConnectPorts('EneSensor', OUT_PORT, 'EneStream', IN_PORT)
        self.ConnectPorts('BalEneSensor', SIG_PORT, 'EneSensor', SIG_PORT)

        # borrow child ports
        self.BorrowChildPort(self.eneStream.GetPort(OUT_PORT), OUT_PORT + 'Q')
        self.BorrowChildPort(self.itnRxn.GetPort(IN_PORT), IN_PORT)
        self.BorrowChildPort(self.itnRxn.GetPort(OUT_PORT), OUT_PORT)
        self.BorrowChildPort(self.itnRxn.GetPort(DELTAP_PORT), DELTAP_PORT)

        self.SetParameterValue(NURXN_PAR, 0)
        self.SetParameterValue(CALCOPTION_PAR,
                               1)  # use table to correlate constant
        self.SetParameterValue(CONSTBASIS_PAR,
                               1)  # use partial pressure to calculate constant
        self.SetParameterValue(
            BASISPUNIT_PAR,
            'atm')  # VMG pressure unit when partial pressure as basis
        self.SetParameterValue(QEXOTHERMIC_ISPOS_PAR, 1)
Example #7
0
    def __init__(self, initScript=None):
        """
        create the ports and init the balance
        """
        super(Valve, self).__init__(initScript)

        self.outPort = self.CreatePort(OUT | MAT, OUT_PORT)
        self.outPort.SetLocked(True)

        self.inPort = self.CreatePort(IN | MAT, IN_PORT)
        self.inPort.SetLocked(True)

        self.dpPort = self.CreatePort(SIG, DELTAP_PORT)
        self.dpPort.SetSignalType(DELTAP_VAR)
        self.dpPort.SetLocked(True)

        self._balance = Balance.Balance(Balance.MOLE_BALANCE
                                        | Balance.ENERGY_BALANCE)
        self._balance.AddInput(self.inPort)
        self._balance.AddOutput(self.outPort)
Example #8
0
    def UpdatePortsOut(self):
        """Update the amount and names of the ports out"""
        portNames = self.GetPortNames(MAT | OUT)
        nuLPorts = self.nuLPorts
        nuSPorts = self.nuSPorts

        # Get how many phases of each we actually have
        nuLPh = self.NumberLiqPhases()
        nuSPh = self.NumberSolidPhases()

        # Create or delete the liquid ports
        for i in range(nuLPorts, nuLPh, -1):
            p = self.GetPort(L_PORT + str(i - 1))
            p.SetLocked(False)
            self.DeletePort(p)
        for i in range(nuLPorts, nuLPh):
            p = self.CreatePort(MAT | OUT, L_PORT + str(i))
            p.SetLocked(True)

        # Create or delete the solid ports
        for i in range(nuSPorts, nuSPh, -1):
            p = self.GetPort(S_PORT + str(i - 1))
            p.SetLocked(False)
            self.DeletePort(p)
        for i in range(nuSPorts, nuSPh):
            p = self.CreatePort(MAT | OUT, S_PORT + str(i))
            p.SetLocked(True)

        # Update the port counts
        self.nuLPorts = nuLPh
        self.nuSPorts = nuSPh

        # Update the balance
        self.balance = Balance.Balance(Balance.MOLE_BALANCE
                                       | Balance.ENERGY_BALANCE)
        self.balance.AddInput(self.ports_mat_IN[IN_PORT])
        for port in self.GetPorts(MAT | OUT):
            self.balance.AddOutput(port)
Example #9
0
File: Pump.py Project: kpatvt/sim21
    def __init__(self, initScript=None):
        """
        Just do balance and conserve entropy
        isCompressor determines energy flow direction
        """
        super(IdealPump, self).__init__(initScript)

        self.balance = Balance.Balance(Balance.MOLE_BALANCE
                                       | Balance.ENERGY_BALANCE)
        self.lastPIn = None
        self.lastPOut = None

        inPort = self.CreatePort(MAT | IN, IN_PORT)
        outPort = self.CreatePort(MAT | OUT, OUT_PORT)

        dpPort = self.CreatePort(SIG, DELTAP_PORT)
        dpPort.SetSignalType(DELTAP_VAR)

        qPort = self.CreatePort(ENE | IN, IN_PORT + 'Q')
        self.balance.AddInput((inPort, qPort))
        self.balance.AddOutput(outPort)

        self.SetParameterValue(ISENTROPIC_PAR, 1)
Example #10
0
    def UpdatePortsOut(self):
        """Update the amount and names of the ports in"""
        nuPorts = self.GetNumberPorts(MAT | OUT)
        nuStOut = self.parameters[NUSTOUT_PAR]

        for i in range(nuPorts, nuStOut, -1):
            self.DeletePortNamed(OUT_PORT + str(i - 1))
            self.DeletePortNamed(FLOWFRAC_PAR + str(i - 1))
        for i in range(nuPorts, nuStOut):
            self.CreatePort(MAT | OUT, OUT_PORT + str(i))
            port = self.CreatePort(SIG, FLOWFRAC_PAR + str(i))
            port.SetSignalType(FRAC_VAR)

        self._balance = Balance.Balance(Balance.MOLE_BALANCE
                                        | Balance.ENERGY_BALANCE)
        self._balance.AddInput(self.GetPort(IN_PORT))
        self.fracPortList = []
        self.matPortList = []
        for i in range(nuStOut):
            port = self.GetPort(OUT_PORT + str(i))
            self._balance.AddOutput(port)
            self.matPortList.append(port)

            self.fracPortList.append(self.GetPort(FLOWFRAC_PAR + str(i)))
Example #11
0
    def __init__(self, initScript=None):
        """
        set up the basic flowsheet
        """
        UnitOperations.UnitOperation.__init__(self, initScript)

        self.feedBalance = Balance.BalanceOp()
        self.AddUnitOperation(self.feedBalance, 'FeedBalance')

        self.feedBalance.SetParameterValue(NUSTOUT_PAR + Balance.S_MAT, 1)
        self.feedBalance.SetParameterValue(Balance.BALANCETYPE_PAR,
                                           Balance.MOLE_BALANCE | Balance.ENERGY_BALANCE)

        self.SetParameterValue(NUSTIN_PAR + Balance.S_MAT, 1)
        self.SetParameterValue(NUSTIN_PAR + Balance.S_ENE, 1)

        self.splitter = SimpleComponentSplitter()
        self.splitter.borrowedSplits = self
        self.AddUnitOperation(self.splitter, 'Splitter')

        for port in self.splitter.GetPorts(MAT | OUT):
            self.BorrowChildPort(port, port.GetName())

        self.ConnectPorts('FeedBalance', OUT_PORT + '0', 'Splitter', IN_PORT)
Example #12
0
    def __init__(self, initScript=None):
        """Init the ejector

        Init Info:
        Efficiency = 1.0

        """

        super(EjectorOp, self).__init__(initScript)
        self.SetParameterValue(EquationSolver.SOLVE_METH_PAR,
                               EquationSolver.NR)

        # Init Efficiency as 1.0
        self.SetParameterValue(EFFIC_PAR, 1.0)

        # Material ports
        p = self.CreatePort(IN | MAT, PROCESS_PORT)
        m = self.CreatePort(IN | MAT, MOTIVE_PORT)
        d = self.CreatePort(OUT | MAT, DISCHARGE_PORT)

        # Signal ports
        nozzDiam = self.CreatePort(SIG, NOZZLE_DIAM_PORT)
        thrDiam = self.CreatePort(SIG, THROAT_DIAM_PORT)
        nozzDiam.SetSignalType(LENGTH_VAR)
        thrDiam.SetSignalType(LENGTH_VAR)

        p.SetLocked(True)
        m.SetLocked(True)
        d.SetLocked(True)
        nozzDiam.SetLocked(True)
        thrDiam.SetLocked(True)

        # Load a balance
        self._balance = Balance.Balance(Balance.MOLE_BALANCE)
        self._balance.AddInput(self.GetPorts(IN | MAT))
        self._balance.AddOutput(self.GetPorts(OUT | MAT))

        # Setting for simoultaneous solution
        self._nuUnk = 18
        self._lowBoundLst = self._nuUnk * [None]
        self._unkName = self._nuUnk * ['']
        self._canBeSpec = self._nuUnk * [False]
        self._nuEqns = 10

        # Member variables that are used during solution
        self._matProcess = None
        self._matMotive = None
        self._matDischarge = None
        self._unkFracs = None  # Any value for now
        self._pFracs = None
        self._mFracs = None
        self._dFracs = None
        self._pureCmpMW = None
        self._thCaseObj = None
        self._eff = None

        # Lower bounds are wrong, should support negatives
        self._lowBoundLst[w1Idx] = -1E+30
        self._lowBoundLst[w2Idx] = -1E+30
        self._lowBoundLst[w3Idx] = -1E+30
        self._lowBoundLst[p1Idx] = 0.000001
        self._lowBoundLst[p2Idx] = 0.000001
        self._lowBoundLst[p3Idx] = 0.000001
        self._lowBoundLst[S1Idx] = 0.00001
        self._lowBoundLst[S2Idx] = 0.00001
        self._lowBoundLst[S3Idx] = 0.00001
        self._lowBoundLst[v1Idx] = -1E+30
        self._lowBoundLst[v2Idx] = -1E+30
        self._lowBoundLst[v3Idx] = -1E+30
        self._lowBoundLst[H1Idx] = -1E+30
        self._lowBoundLst[H2Idx] = -1E+30
        self._lowBoundLst[H3Idx] = -1E+30
        self._lowBoundLst[d1Idx] = 0.0000000001
        self._lowBoundLst[d2Idx] = 0.0000000001
        self._lowBoundLst[d3Idx] = 0.0000000001

        # Indicate if a variable can be used as a spec when deciding if there is enough known info to solve
        self._canBeSpec[w1Idx] = True
        self._canBeSpec[w2Idx] = True
        self._canBeSpec[w3Idx] = True
        self._canBeSpec[p1Idx] = True
        self._canBeSpec[p2Idx] = True
        self._canBeSpec[p3Idx] = True
        self._canBeSpec[S1Idx] = True
        self._canBeSpec[S2Idx] = True
        self._canBeSpec[S3Idx] = True
        self._canBeSpec[v1Idx] = False
        self._canBeSpec[v2Idx] = False
        self._canBeSpec[v3Idx] = False
        self._canBeSpec[H1Idx] = True
        self._canBeSpec[H2Idx] = True
        self._canBeSpec[H3Idx] = True
        self._canBeSpec[d1Idx] = False
        self._canBeSpec[d2Idx] = False
        self._canBeSpec[d3Idx] = False

        self._unkName[w1Idx] = 'W1'
        self._unkName[w2Idx] = 'W2'
        self._unkName[w3Idx] = 'W3'
        self._unkName[p1Idx] = 'P1'
        self._unkName[p2Idx] = 'P2'
        self._unkName[p3Idx] = 'P3'
        self._unkName[S1Idx] = 'S1'
        self._unkName[S2Idx] = 'S2'
        self._unkName[S3Idx] = 'S3'
        self._unkName[v1Idx] = 'v1'
        self._unkName[v2Idx] = 'v2'
        self._unkName[v3Idx] = 'v3'
        self._unkName[H1Idx] = 'H1'
        self._unkName[H2Idx] = 'H2'
        self._unkName[H3Idx] = 'H3'
        self._unkName[d1Idx] = 'Den1'
        self._unkName[d2Idx] = 'Den2'
        self._unkName[d3Idx] = 'Den3'

        self.UpdateStructure()
Example #13
0
File: Pump.py Project: kpatvt/sim21
    def __init__(self, initScript=None):
        """Init pump - build it from Idealpump,
        Heater and Set operations
        """
        super(Pump, self).__init__(initScript)

        # the isentropic compressor
        self.ideal = IdealPump()
        self.AddUnitOperation(self.ideal, 'Ideal')

        # a heater to add the waste heat to the outlet
        self.waste = Heater.Heater()
        self.AddUnitOperation(self.waste, 'Waste')
        self.waste.GetPort(DELTAP_PORT).SetValue(0.0, FIXED_V)

        # connect them
        self.ConnectPorts('Ideal', OUT_PORT, 'Waste', IN_PORT)

        # energy sensors (needed for signals)
        self.idealQ = Sensor.EnergySensor()
        self.AddUnitOperation(self.idealQ, 'IdealQ')
        self.ConnectPorts('Ideal', IN_PORT + 'Q', 'IdealQ', OUT_PORT)

        self.wasteQ = Sensor.EnergySensor()
        self.AddUnitOperation(self.wasteQ, 'WasteQ')
        self.ConnectPorts('Waste', IN_PORT + 'Q', 'WasteQ', OUT_PORT)

        self.totalQ = Sensor.EnergySensor()
        self.AddUnitOperation(self.totalQ, 'TotalQ')

        # create a signal stream for the efficiency
        self.effStream = Stream.Stream_Signal()
        self.effStream.SetParameterValue(SIGTYPE_PAR, GENERIC_VAR)
        self.AddUnitOperation(self.effStream, 'EfficiencySig')

        # set relation between ideal and total Q
        self.set = Set.Set()
        self.AddUnitOperation(self.set, 'Set')
        self.set.SetParameterValue(SIGTYPE_PAR, ENERGY_VAR)
        self.set.GetPort(Set.ADD_PORT).SetValue(0.0, FIXED_V)
        self.ConnectPorts('TotalQ', SIG_PORT, 'Set', SIG_PORT + '0')
        self.ConnectPorts('IdealQ', SIG_PORT, 'Set', SIG_PORT + '1')
        self.ConnectPorts('EfficiencySig', OUT_PORT, 'Set', Set.MULT_PORT)

        # energy stream balance
        self.mix = Balance.BalanceOp()
        self.AddUnitOperation(self.mix, 'Mix')
        self.mix.SetParameterValue(NUSTIN_PAR + Balance.S_ENE, 1)
        self.mix.SetParameterValue(NUSTOUT_PAR + Balance.S_ENE, 2)
        self.mix.SetParameterValue(Balance.BALANCETYPE_PAR,
                                   Balance.ENERGY_BALANCE)

        # connect the mixer ports
        self.ConnectPorts('IdealQ', IN_PORT, 'Mix', OUT_PORT + 'Q0')
        self.ConnectPorts('WasteQ', IN_PORT, 'Mix', OUT_PORT + 'Q1')
        self.ConnectPorts('TotalQ', OUT_PORT, 'Mix', IN_PORT + 'Q0')

        # export the flow ports
        self.BorrowChildPort(self.ideal.GetPort(IN_PORT), IN_PORT)
        self.BorrowChildPort(self.waste.GetPort(OUT_PORT), OUT_PORT)
        self.BorrowChildPort(self.totalQ.GetPort(IN_PORT), IN_PORT + 'Q')
        self.BorrowChildPort(self.effStream.GetPort(IN_PORT), EFFICIENCY_PORT)
        self.BorrowChildPort(self.ideal.GetPort(DELTAP_PORT), DELTAP_PORT)

        # Change the type of the energy port such that it is in Work units and scaling
        self.totalQ.GetPort(IN_PORT).GetProperty().SetTypeByName(WORK_VAR)
Example #14
0
def TestRecycle2():
    print("""Init TestRecycle2 ++++++++++++++++++++++++++++++""")
    # Set Thermo
    pkgName = "Peng-Robinson"
    #     cmpNames = ("n-HEPTANE", "BENZENE", "TRIETHYLENE GLYCOL")
    cmpNames = ("PROPANE", "n-BUTANE", "ISOBUTANE", "n-NONANE")
    thAdmin = ThermoAdmin.ThermoAdmin()
    providers = thAdmin.GetAvThermoProviderNames()
    provider = providers[0]  # Should be Virt Mat
    thCase = 'myTh'
    thermo = thAdmin.AddPkgFromName(provider, thCase, pkgName)
    for i in cmpNames:
        thAdmin.AddCompound(provider, thCase, i)

    # Create a flowsheet to contain all the units
    flsheet = Flowsheet.Flowsheet()
    flsheet.SetThermoAdmin(thAdmin)
    flsheet.SetThermo(thermo)
    flsheet.SetParameterValue(NULIQPH_PAR, 1)

    # SetStream
    stream = Stream.Stream_Material()
    flsheet.AddUnitOperation(stream, 'Feed')

    portsIn = stream.GetPortNames(MAT | IN)
    # I know in advance there's only one port in
    stream.SetCompositionValue(portsIn[0], "PROPANE", 0.25)
    stream.SetCompositionValue(portsIn[0], "n-BUTANE", 0.25)
    stream.SetCompositionValue(portsIn[0], "ISOBUTANE", 0.25)
    stream.SetCompositionValue(portsIn[0], "n-NONANE", 0.25)
    stream.GetPort(portsIn[0]).SetPropValue(T_VAR, 360.15, FIXED_V)
    stream.GetPort(portsIn[0]).SetPropValue(P_VAR, 715.0, FIXED_V)

    recycle = Stream.Stream_Material()
    flsheet.AddUnitOperation(recycle, 'Recycle')

    portsIn = recycle.GetPortNames(MAT | IN)
    # I know in advance there's only one port in

    # Set a mixer
    mixer = Mixer.Mixer()
    flsheet.AddUnitOperation(mixer, 'Mixer')
    mixer.SetParameterValue(NUSTIN_PAR, 2)

    flsheet.ConnectPorts('Feed', 'Out', 'Mixer', 'In0')
    flsheet.ConnectPorts('Recycle', 'Out', 'Mixer', 'In1')

    # Set mixed Stream
    mixed = Stream.Stream_Material()
    flsheet.AddUnitOperation(mixed, 'Mixed')

    fixedGuess = FIXED_V | ESTIMATED_V
    portsIn = mixed.GetPortNames(MAT | IN)

    # Set Flash UO
    flash = Flash.SimpleFlash()
    flsheet.AddUnitOperation(flash, 'Flash')

    # to start, just guess same as feed
    flash.SetCompositionValue(portsIn[0], "PROPANE", 0.25, fixedGuess)
    flash.SetCompositionValue(portsIn[0], "n-BUTANE", 0.25, fixedGuess)
    flash.SetCompositionValue(portsIn[0], "ISOBUTANE", 0.25, fixedGuess)
    flash.SetCompositionValue(portsIn[0], "n-NONANE", 0.25, fixedGuess)
    flash.GetPort(portsIn[0]).SetPropValue(T_VAR, 360.15, fixedGuess)

    flsheet.ConnectPorts('Mixer', 'Out', 'Mixed', 'In')

    flsheet.ConnectPorts('Mixed', 'Out', 'Flash', 'In')

    # Set a splitter
    splitter = Split.Splitter()
    flsheet.AddUnitOperation(splitter, 'Splitter')
    splitter.SetParameterValue(NUSTOUT_PAR, 2)

    flsheet.ConnectPorts('Flash', 'Liq0', 'Splitter', 'In')

    splitter.GetPort('Out1').SetPropValue(MOLEFLOW_VAR, 200.0, FIXED_V)
    splitter.GetPort('Out1').SetPropValue(P_VAR, 715.0, FIXED_V)
    flash.GetPort('Vap').SetPropValue(MOLEFLOW_VAR, 1652.682, FIXED_V)

    # close recycle
    flsheet.ConnectPorts('Splitter', 'Out1', 'Recycle', 'In')

    # add balance to back calculate flow
    bal = Balance.BalanceOp()
    flsheet.AddUnitOperation(bal, 'Balance')
    bal.SetParameterValue(NUSTIN_PAR + Balance.S_MAT, 2)
    bal.SetParameterValue(NUSTOUT_PAR + Balance.S_MAT, 1)
    bal.SetParameterValue('BalanceType', Balance.MOLE_BALANCE)
    flsheet.ConnectPorts('Balance', 'In1', 'Flash', 'Vap')
    flsheet.ConnectPorts('Balance', 'In0', 'Splitter', 'Out0')
    flsheet.ConnectPorts('Balance', 'Out0', 'Feed', 'In')

    flsheet.Solve()
    print('***************')
    cmps = splitter.GetCompositionValues('Out0')
    for j in range(len(cmps)):
        print('fraction of ', cmpNames[j], ': ', cmps[j])
    print('***************')
    print('Some properties of splitter Out0')
    print(T_VAR, ': ', splitter.GetPropValue('Out0', T_VAR))
    print(P_VAR, ': ', splitter.GetPropValue('Out0', P_VAR))
    print(H_VAR, ': ', splitter.GetPropValue('Out0', H_VAR))
    print(MOLEFLOW_VAR, ': ', splitter.GetPropValue('Out0', MOLEFLOW_VAR))

    print('Some properties of mixed Out')
    print(T_VAR, ': ', mixed.GetPropValue('Out', T_VAR))
    print(P_VAR, ': ', mixed.GetPropValue('Out', P_VAR))
    print(H_VAR, ': ', mixed.GetPropValue('Out', H_VAR))
    print(MOLEFLOW_VAR, ': ', mixed.GetPropValue('Out', MOLEFLOW_VAR))

    print('Some properties of stream Out')
    print(T_VAR, ': ', stream.GetPropValue('Out', T_VAR))
    print(P_VAR, ': ', stream.GetPropValue('Out', P_VAR))
    print(H_VAR, ': ', stream.GetPropValue('Out', H_VAR))
    print(MOLEFLOW_VAR, ': ', stream.GetPropValue('Out', MOLEFLOW_VAR))

    print('****reset pressure***')
    # stream.GetPort(portsIn[0]).SetPropValue(P_VAR, 800.0, FIXED_V)
    stream.GetPort(portsIn[0]).SetPropValue(T_VAR, 400.0, FIXED_V)

    flsheet.Solve()
    print('*************** splitter out1')
    cmps = splitter.GetCompositionValues('Out0')
    for j in range(len(cmps)):
        print('fraction of ', cmpNames[j], ': ', cmps[j])
    print('***************')
    print('Some properties of splitter Out0')
    print(T_VAR, ': ', splitter.GetPropValue('Out0', T_VAR))
    print(P_VAR, ': ', splitter.GetPropValue('Out0', P_VAR))
    print(H_VAR, ': ', splitter.GetPropValue('Out0', H_VAR))
    print(MOLEFLOW_VAR, ': ', splitter.GetPropValue('Out0', MOLEFLOW_VAR))

    print("""Finished TestRecycle2 ++++++++++++++++++++++++++++++""")
    flsheet.CleanUp()
    thAdmin.CleanUp()