Exemplo n.º 1
0
class RegenerativeRankineCycle(RankineCycle):
	label = "Regenerative Rankine cycle"
	figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/RankineCycle_Recuperator.svg",  height = 300)
	description = F.ModelDescription("Rankine cycle with recuperator, \
		using the temperature of the hot steam before the condenser to pre-heat the fluid before entering the boiler", show = True)
	#================ Inputs ================#
	#---------------- Fields ----------------#
	# FieldGroup
	recuperator = F.SubModelGroup(TC.HeatExchangerTwoStreams, 'FG', label = 'Recuperator')
	inputs = F.SuperGroup(['workingFluidGroup', 'pump', recuperator, 'boiler', 'turbine', 'condenser'], label = 'Cycle defininition')
	#--------------- Model view ---------------#

	#================ Results ================#
	#---------------- Energy flows -----------#
	recuperatorHeat = F.Quantity('HeatFlowRate', default = (0, 'kW'), label = 'recuperator heat rate')
	flowFieldGroup = F.FieldGroup(['pumpPower', recuperatorHeat, 'boilerHeat', 'turbinePower', 'condenserHeat'], label = 'Energy flows')
	#---------------- Scheme -----------------#
	scheme_Rankine_recup = F.Image(default="static/ThermoFluids/img/ModuleImages/RankineCycle_Recuperator.png")
	SchemeVG = F.ViewGroup([scheme_Rankine_recup], label="Process Scheme")
	SchemeSG = F.SuperGroup([SchemeVG], label="Scheme")
	
	resultView = F.ModelView(ioType = "output", superGroups = ['resultDiagrams', SchemeSG, 'resultStates', 'resultEnergy', 'solverStats'])
	#================ Methods ================#
	def compute(self):
		self.initCompute(self.fluidName)
		# Connect components
		self.connectPorts(self.condenser.outlet, self.pump.inlet)
		self.connectPorts(self.pump.outlet, self.recuperator.inlet1)
		self.connectPorts(self.recuperator.outlet1, self.boiler.inlet)
		self.connectPorts(self.boiler.outlet, self.turbine.inlet)
		self.connectPorts(self.turbine.outlet, self.recuperator.inlet2)
		self.connectPorts(self.recuperator.outlet2, self.condenser.inlet)
		# Initial guess
		for fl in self.flows:
			fl.mDot = self.mDot
		self.condenser.outlet.state.update_pq(self.pLow, 0)
		self.boiler.outlet.state.update_pq(self.pHigh, 1)
		self.turbine.compute(self.pLow)
		# Cycle iterations
		self.solver.run()
		# Results
		self.postProcess()
		
	def computeCycle(self):
		self.pump.compute(self.pHigh)
		self.recuperator.compute()
		self.recuperator.computeStream1()
		self.boiler.compute()	
		self.turbine.compute(self.pLow)
		self.recuperator.computeStream2()
		self.condenser.compute()
		
	def postProcess(self):
		super(RegenerativeRankineCycle, self).postProcess()
		self.recuperatorHeat = self.recuperator.QDot 

	def SteamPlant(self):
		RankineCycle.SteamPlant(self)
		self.pLow = (2, 'bar')
		self.boiler.TOutlet = (600, 'degC')
Exemplo n.º 2
0
class ThermodynamicalProcess(ThermodynamicalCycle):
    ############# Inputs #############
    fluidSource = F.SubModelGroup(TC.FluidSource, 'FG', label='Initial State')
    fluidSink = F.SubModelGroup(TC.FluidSink, 'FG', label='Final State')
    inputs = F.SuperGroup([fluidSource, fluidSink])

    # Model View
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs],
                            autoFetch=True)

    ############# Results #############
    w = F.Quantity('SpecificEnergy',
                   default=(0, 'kJ/kg'),
                   label='specific work')
    qIn = F.Quantity('SpecificEnergy',
                     default=(0, 'kJ/kg'),
                     label='specific heat in')
    delta_h = F.Quantity('SpecificEnthalpy', label='enthalpy change (fluid)')
    WDot = F.Quantity('Power', default=(0, 'kW'), label='power')
    QDotIn = F.Quantity('HeatFlowRate',
                        default=(0, 'kW'),
                        label='heat flow rate in')
    deltaHDot = F.Quantity('Power', label='enthalpy change (fluid)')
    # Specific energy quantities
    specificEnergyResults = F.FieldGroup(
        [w, delta_h, qIn], label="Heat/work (specific quantities)")
    # Energy flow quantities
    energyFlowResults = F.FieldGroup([WDot, deltaHDot, QDotIn],
                                     label="Heat/work flows")
    energyBalanceResults = F.SuperGroup(
        [specificEnergyResults, energyFlowResults], label="Energy balance")

    # Model View
    resultView = F.ModelView(
        ioType="output",
        superGroups=['resultDiagrams', 'resultStates', energyBalanceResults])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    ############# Methods ###############
    def postProcess(self, component):
        super(ThermodynamicalProcess, self).postProcess(300)
        component.postProcess()
        self.w = component.w
        self.qIn = component.qIn
        self.delta_h = component.delta_h
        self.WDot = component.WDot
        self.QDotIn = component.QDotIn
        self.deltaHDot = component.deltaHDot
Exemplo n.º 3
0
class HeatExchangerTwoStreams(ThermodynamicalProcessTwoStreams):
    label = "Heat Exchanger (two streams)"
    description = F.ModelDescription(
        "Parameteric model for heat exchange between two streams", show=True)
    figure = F.ModelFigure(
        src="ThermoFluids/img/ModuleImages/HeatExchanger.svg")
    heatExchanger = F.SubModelGroup(TC.HeatExchangerTwoStreams,
                                    'FG',
                                    label='Heat exchanger')
    inputs = F.SuperGroup(['fluidSource1', 'fluidSource2', heatExchanger])

    def __init__(self):
        self.fluidSource2.T2 = (350, 'K')

    def compute(self):
        self.cycleDiagram.enable = False
        self.initCompute(self.fluidSource1.fluidName)
        # Connect components
        self.connectPorts(self.fluidSource1.outlet, self.heatExchanger.inlet1)
        self.connectPorts(self.heatExchanger.outlet1, self.fluidSink1.inlet)
        self.connectPorts(self.fluidSource2.outlet,
                          self.heatExchanger.inlet2,
                          fluid=self.fluidSource2.fluidName)
        self.connectPorts(self.heatExchanger.outlet2,
                          self.fluidSink2.inlet,
                          fluid=self.fluidSource2.fluidName)
        self.fluidSource1.compute()
        self.fluidSource2.compute()
        self.heatExchanger.compute()
        self.heatExchanger.computeStream1()
        self.heatExchanger.computeStream2()
        self.postProcess(self.heatExchanger)
Exemplo n.º 4
0
class SolverSettings(NumericalModel):
    tFinal = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(0, 'day'),
                        maxValue=(1000, 'day'),
                        label='simulation time')
    tPrint = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(1e-5, 'day'),
                        maxValue=(100, 'day'),
                        label='print interval')

    absTol = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-5, 'day'),
                        label='absolute tolerance')
    relTol = F.Quantity('Bio_Time',
                        default=(0.0, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-3, 'day'),
                        label='relative tolerance')

    FG = F.FieldGroup([tFinal, tPrint, absTol, relTol], label='Solver')
    SG = F.SuperGroup([FG], label='Settings')

    modelBlocks = []
Exemplo n.º 5
0
class CycleIterator(NumericalModel):
    hTolerance = F.Quantity('SpecificEnthalpy',
                            default=1.0,
                            label='enthalpy tolerance')
    maxNumIter = F.Quantity(default=500,
                            label='max iterations',
                            description='maximum number of iterations')
    convSettings = F.FieldGroup([hTolerance, maxNumIter],
                                label='Convergence settings')
    solverSettings = F.SuperGroup([convSettings], label='Solver')
    modelBlocks = []

    def run(self):
        self.converged = False
        self.ncp = len(self.cycle.fp)
        self.old_h = np.zeros((self.ncp))
        self.old_T = np.zeros((self.ncp))
        self.old_p = np.zeros((self.ncp))
        self.hHistory = []
        self.change_h = np.zeros((self.ncp))
        self.change_hHistory = []
        i = 0
        self.cycle.computeCycle()
        while (i < self.maxNumIter):
            self.saveOldValues()
            self.cycle.computeCycle()
            self.checkConvergence()
            if (self.converged):
                break
            i += 1

        if (not self.converged):
            raise E.ConvergenceError(
                'Solution did not converge, delta_h = {:e}'.format(
                    self.change_hHistory[-1]))

    def saveOldValues(self):
        for i in range(self.ncp):
            self.old_h[i] = self.cycle.fp[i].h
            self.old_T[i] = self.cycle.fp[i].T
            self.old_p[i] = self.cycle.fp[i].p
        #self.hHistory.append(self.old_h)

    def computeChange(self):
        for i in range(self.ncp):
            self.change_h[i] = self.cycle.fp[i].h - self.old_h[i]
        change = np.sqrt(np.sum(self.change_h**2))
        self.hHistory.append([x for x in self.change_h])
        self.change_hHistory.append(change)
        return change

    def checkConvergence(self):
        self.converged = self.computeChange() < self.hTolerance
        return self.converged

    def printValues(self):
        print[fp.T for fp in self.cycle.fp]
        print[fl.mDot for fl in self.cycle.flows]
Exemplo n.º 6
0
class Controller(NumericalModel):
    initialState = F.Choices(
        OrderedDict((
            (TC.FUELING, 'fueling'),
            (TC.EXTRACTION, 'extraction'),
        )),
        label='start with',
        description='start the simulation with fueling or extraction')
    tWaitBeforeExtraction = F.Quantity(
        'Time',
        default=(0., 's'),
        minValue=(0., 's'),
        maxValue=(1.e6, 's'),
        label='&#964 (extraction)',
        description='waiting time before each extraction')
    tWaitBeforeFueling = F.Quantity(
        'Time',
        default=(0., 's'),
        minValue=(0., 's'),
        maxValue=(1.e6, 's'),
        label='&#964 (fueling)',
        description='waiting time before each fueling')
    pMin = F.Quantity(
        'Pressure',
        default=(0., 'bar'),
        label='minimum pressure</sub>',
        description='minimum pressure in the gas storage for starting fueling')
    pMax = F.Quantity(
        'Pressure',
        default=(0., 'bar'),
        label='maximum pressure',
        description='maximum pressure in the gas storage for stopping fueling')
    mDotExtr = F.Quantity('MassFlowRate',
                          default=(0., 'kg/h'),
                          label='extraction mass flow rate',
                          description='extraction mass flow rate')
    nCompressor = F.Quantity('AngularVelocity',
                             default=(0., 'rev/s'),
                             minValue=(0, 'rev/s'),
                             maxValue=(1e4, 'rev/s'),
                             label='compressor speed',
                             description='compressor speed')

    FG = F.FieldGroup([
        initialState, pMin, pMax, mDotExtr, nCompressor, tWaitBeforeExtraction,
        tWaitBeforeFueling
    ],
                      label='Parameters')

    SG = F.SuperGroup([FG], label="Parameters")

    modelBlocks = []
Exemplo n.º 7
0
class ThermodynamicalProcessTwoStreams(ThermodynamicalCycle):
    ############# Inputs #############
    fluidSource1 = F.SubModelGroup(TC.FluidSource, 'FG', label='Inlet 1')
    fluidSource2 = F.SubModelGroup(TC.FluidSource, 'FG', label='Inlet 2')
    fluidSink1 = F.SubModelGroup(TC.FluidSink, 'FG', label='Outlet 1')
    fluidSink2 = F.SubModelGroup(TC.FluidSink, 'FG', label='Outlet 2')
    inputs = F.SuperGroup([fluidSource1, fluidSource2, fluidSink1, fluidSink2])

    # Model View
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs],
                            autoFetch=True)

    ############# Results #############
    QDot = F.Quantity('HeatFlowRate',
                      default=(0, 'kW'),
                      label='heat flow rate in')
    NTU = F.Quantity(label='NTU')
    Cr = F.Quantity(label='capacity ratio')
    energyResults = F.FieldGroup([QDot, NTU, Cr], label="Energy")
    energyBalanceResults = F.SuperGroup([energyResults],
                                        label="Energy balance")

    # Model View
    resultView = F.ModelView(
        ioType="output", superGroups=['resultStates', energyBalanceResults])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    ############# Methods ###############
    def postProcess(self, component):
        super(ThermodynamicalProcessTwoStreams, self).postProcess(300)
        self.QDot = component.QDot
        self.NTU = component.NTU
        self.Cr = component.Cr
Exemplo n.º 8
0
class Compression(ThermodynamicalProcess):
    label = "Compression"
    description = F.ModelDescription(
        "Parameteric model for compression process: isentropic and isothermal",
        show=True)
    figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/Compression.svg")
    compressor = F.SubModelGroup(TC.Compressor, 'FG', label='Compressor')
    inputs = F.SuperGroup(['fluidSource', 'fluidSink', compressor])

    def compute(self):
        self.initCompute(self.fluidSource.fluidName)
        # Connect components
        self.connectPorts(self.fluidSource.outlet, self.compressor.inlet)
        self.connectPorts(self.compressor.outlet, self.fluidSink.inlet)
        self.fluidSource.compute()
        self.compressor.compute(self.fluidSink.p)
        self.postProcess(self.compressor)
Exemplo n.º 9
0
class Cooling(ThermodynamicalProcess):
    label = "Cooling"
    description = F.ModelDescription("Cooling process at constant pressure",
                                     show=True)
    figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/Cooling.svg")
    condenser = F.SubModelGroup(TC.Condenser, 'FG', label='Condenser')
    inputs = F.SuperGroup(['fluidSource', condenser])

    ############# Methods ###############
    def compute(self):
        self.initCompute(self.fluidSource.fluidName)
        # Connect components
        self.connectPorts(self.fluidSource.outlet, self.condenser.inlet)
        self.connectPorts(self.condenser.outlet, self.fluidSink.inlet)
        self.fluidSource.compute()
        self.condenser.compute()
        self.postProcess(self.condenser)
Exemplo n.º 10
0
class ABC(NumericalModel):
    showOnHome = False
    label = 'ABC'
    compressor = F.SubModelGroup(TC.Compressor, ['etaS', 'fQ', 'modelType'],
                                 label='Compressor')  #fields = )
    inputs = F.SuperGroup([compressor])
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs],
                            autoFetch=True)
    resultView = F.ModelView(ioType="output", superGroups=[])

    testJs = JsBlock(srcType="file", src="TestPage.js")
    testHtml = HtmlBlock(srcType="file", src="TestPage.html")

    modelBlocks = [inputView, resultView, testJs, testHtml]

    def __init__(self):
        self.compressor.modelType = 'S'
        self.compressor.declared_fields['modelType'].show = 'false'

    def compute(self):
        pass
Exemplo n.º 11
0
class Expansion(ThermodynamicalProcess):
    label = "Expansion"
    description = F.ModelDescription(
        "Parameteric model for expansion process: isentropic and isenthalpic",
        show=True)
    figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/Expansion.svg")
    turbine = F.SubModelGroup(TC.Turbine,
                              'FG',
                              label='Turbine',
                              show="self.processType == 'S'")
    throttleValve = F.SubModelGroup(TC.ThrottleValve, 'FG', show="false")
    processType = F.Choices(options=OrderedDict((
        ('S', 'isentropic'),
        ('H', 'isenthalpic'),
    )),
                            default='S',
                            label="process type")
    processTypeFG = F.FieldGroup([processType], label="Process type")
    inputs = F.SuperGroup(
        ['fluidSource', 'fluidSink', processTypeFG, turbine, throttleValve])

    def __init__(self):
        self.fluidSource.p1 = (10, 'bar')
        self.fluidSource.p2 = (10, 'bar')
        self.fluidSink.p = (1, 'bar')

    def compute(self):
        if (self.processType == 'S'):
            component = self.turbine
        elif (self.processType == 'H'):
            component = self.throttleValve
        self.initCompute(self.fluidSource.fluidName)
        # Connect components
        self.connectPorts(self.fluidSource.outlet, component.inlet)
        self.connectPorts(component.outlet, self.fluidSink.inlet)
        self.fluidSource.compute()
        component.compute(self.fluidSink.p)
        self.postProcess(component)
Exemplo n.º 12
0
class Tank(NumericalModel):
    wallArea = F.Quantity('Area',
                          default=(0., 'm**2'),
                          label='wall area',
                          description='wall area')
    volume = F.Quantity('Volume',
                        default=(0., 'L'),
                        maxValue=(1e6, 'L'),
                        label='volume',
                        description='volume')
    TInit = F.Quantity('Temperature',
                       default=(0., 'degC'),
                       label='initial temperature',
                       description='initial temperature')
    pInit = F.Quantity('Pressure',
                       default=(0., 'bar'),
                       label='initial pressure',
                       description='initial pressure')

    linerMaterial = F.ObjectReference(Solids,
                                      default='StainlessSteel304',
                                      label='liner material',
                                      description='liner material')
    linerThickness = F.Quantity('Length',
                                default=(0., 'm'),
                                minValue=(0, 'm'),
                                label='liner thickness',
                                description='liner thickness')

    compositeMaterial = F.ObjectReference(Solids,
                                          default='StainlessSteel304',
                                          label='composite material',
                                          description='composite material')
    compositeThickness = F.Quantity('Length',
                                    default=(0., 'm'),
                                    minValue=(0, 'm'),
                                    label='composite thickness',
                                    description='composite thickness')

    hConvExternal = F.Quantity(
        'HeatTransferCoefficient',
        default=(0., 'W/m**2-K'),
        label='h<sub>conv</sub> (external)</sub>',
        description='external convection coefficient to ambient')
    hConvInternalWaiting = F.Quantity(
        'HeatTransferCoefficient',
        default=(0., 'W/m**2-K'),
        label='h<sub>conv</sub> (internal,waiting)</sub>',
        description='internal convection coefficient during waiting time')
    hConvInternalExtraction = F.Quantity(
        'HeatTransferCoefficient',
        default=(0., 'W/m**2-K'),
        label='h<sub>conv</sub> (internal, extraction)</sub>',
        description='internal convection coefficient during extraction')
    hConvInternalFueling = F.Quantity(
        'HeatTransferCoefficient',
        default=(0., 'W/m**2-K'),
        label='h<sub>conv</sub> (internal, fueling)',
        description='internal convection coefficient during refueling')

    initialValuesFG = F.FieldGroup([wallArea, volume, TInit, pInit],
                                   label='Initial values')
    convectionFG = F.FieldGroup([
        hConvExternal, hConvInternalWaiting, hConvInternalExtraction,
        hConvInternalFueling
    ],
                                label='Convection')
    linerFG = F.FieldGroup([linerMaterial, linerThickness], label='Liner')
    compositeFG = F.FieldGroup([compositeMaterial, compositeThickness],
                               label='Composite')

    SG = F.SuperGroup([initialValuesFG, convectionFG, linerFG, compositeFG],
                      label="Parameters")

    modelBlocks = []
Exemplo n.º 13
0
class CycleDiagram(NumericalModel):
    #================ Inputs ================#
    enable = F.Boolean(label='create process diagram', default=True)
    isotherms = F.Boolean(label='isotherms')
    temperatureUnit = F.Choices(OrderedDict((('K', 'K'), ('degC', 'degC'))),
                                default='K',
                                label="temperature unit",
                                show="self.isotherms == true")
    isochores = F.Boolean(label='isochores')
    isentrops = F.Boolean(label='isentrops')
    qIsolines = F.Boolean(label='vapor quality isolines')
    diagramInputs = F.FieldGroup(
        [enable, isotherms, temperatureUnit, isochores, isentrops, qIsolines],
        label='Diagram')

    defaultMaxP = F.Boolean(label='default max pressure')
    defaultMaxT = F.Boolean(label='default max temperature')
    maxPressure = F.Quantity('Pressure',
                             default=(1, 'bar'),
                             label='max pressure',
                             show="self.defaultMaxP == false")
    maxTemperature = F.Quantity('Temperature',
                                default=(300, 'K'),
                                label='max temperature',
                                show="self.defaultMaxT == false")
    boundaryInputs = F.FieldGroup(
        [defaultMaxP, defaultMaxT, maxPressure, maxTemperature],
        label='Value Limits')

    inputs = F.SuperGroup([diagramInputs, boundaryInputs],
                          label='Diagram settings')
    modelBlocks = []

    def draw(self, fluid, fluidPoints, cycleLines):
        # Create diagram object
        diagram = PHDiagram(fluid.name, temperatureUnit=self.temperatureUnit)
        # Set limits
        pMax, TMax = None, None
        if not self.defaultMaxP:
            pMax = self.maxPressure
        if not self.defaultMaxT:
            TMax = self.maxTemperature
        diagram.setLimits(pMax=pMax, TMax=TMax)
        fig = diagram.draw(isotherms=self.isotherms,
                           isochores=self.isochores,
                           isentrops=self.isentrops,
                           qIsolines=self.qIsolines)
        ax = fig.get_axes()[0]
        # Draw points
        i = 1
        for fp in fluidPoints:
            ax.semilogy(fp.h / 1e3, fp.p / 1e5, 'ko')
            ax.annotate('{}'.format(i),
                        xy=(fp.h / 1e3, fp.p / 1e5),
                        xytext=(3, 2),
                        textcoords='offset points',
                        size='x-large')
            i += 1
        # Draw lines
        for (fp1, fp2) in cycleLines:
            ax.semilogy([fp1.h / 1e3, fp2.h / 1e3], [fp1.p / 1e5, fp2.p / 1e5],
                        'k',
                        linewidth=2)
        # Export diagram to file
        fHandle, resourcePath = diagram.export(fig)
        os.close(fHandle)
        return resourcePath
Exemplo n.º 14
0
class VaporCompressionCycleWithRecuperator(VaporCompressionCycle):
    label = "Vapor compression cycle (recuperator)"
    figure = F.ModelFigure(
        src=
        "ThermoFluids/img/ModuleImages/VaporCompressionCycle_Recuperator.svg")
    description = F.ModelDescription(
        "Vapor compression cycle with a recuperator. The stream \
	 before the throttle valve is precooled, using the cold stream at the evaporator outlet. \
	 This increases the compressor cooling/heating capacity of the cycle and improves slightly the COP",
        show=True)
    #================ Inputs ================#
    #---------------- Fields ----------------#
    recuperator = F.SubModelGroup(TC.HeatExchangerTwoStreams,
                                  'FG',
                                  label='Recuperator')
    inputs = F.SuperGroup([
        'workingFluidGroup', 'compressor', recuperator, 'condenser',
        'evaporator'
    ],
                          label='Cycle definition')
    #--------------- Model view ---------------#

    #================ Results ================#
    #---------------- Energy flows -----------#
    recuperatorHeat = F.Quantity('HeatFlowRate',
                                 default=(0, 'kW'),
                                 label='recuperator heat rate')
    flowFieldGroup = F.FieldGroup([
        'compressorPower', recuperatorHeat, 'condenserHeat', 'evaporatorHeat'
    ],
                                  label='Energy flows')

    #---------------- Scheme -----------------#
    scheme_VaporCompression_recup = F.Image(
        default=
        "static/ThermoFluids/img/ModuleImages/VaporCompressionCycle_Recuperator.png"
    )
    SchemeVG = F.ViewGroup([scheme_VaporCompression_recup],
                           label="Process Scheme")
    SchemeSG = F.SuperGroup([SchemeVG], label="Scheme")

    resultView = F.ModelView(ioType="output",
                             superGroups=[
                                 'resultDiagrams', SchemeSG, 'resultStates',
                                 'resultEnergy', 'solverStats'
                             ])

    #================ Methods ================#
    def compute(self):
        if (self.cycleTranscritical and self.condenser.computeMethod == 'dT'):
            raise ValueError(
                'In transcritical cycle, condenser sub-cooling cannot be used as input'
            )
        self.initCompute(fluid=self.fluidName)
        # Connect components
        self.connectPorts(self.evaporator.outlet, self.recuperator.inlet1)
        self.connectPorts(self.recuperator.outlet1, self.compressor.inlet)
        self.connectPorts(self.compressor.outlet, self.condenser.inlet)
        self.connectPorts(self.condenser.outlet, self.recuperator.inlet2)
        self.connectPorts(self.recuperator.outlet2, self.throttleValve.inlet)
        self.connectPorts(self.throttleValve.outlet, self.evaporator.inlet)
        # Initial guess
        for fl in self.flows:
            fl.mDot = self.mDot
        self.evaporator.outlet.state.update_pq(self.pLow, 1)
        if (self.cycleTranscritical):
            self.condenser.outlet.state.update_Tp(
                1.05 * self.fluid.critical['T'], self.pHigh)
        else:
            self.condenser.outlet.state.update_pq(self.pHigh, 0)
        # Cycle iterations
        self.solver.run()
        # Results
        self.postProcess()

    def computeCycle(self):
        self.recuperator.compute()
        self.recuperator.computeStream1()
        self.compressor.compute(self.pHigh)
        self.condenser.compute()
        self.recuperator.computeStream2()
        self.throttleValve.compute(self.pLow)
        self.evaporator.compute()

        if (self.cycleTranscritical and self.condenser.computeMethod == 'dT'):
            raise ValueError(
                'In transcritical cycle, condenser sub-cooling cannot be used as input'
            )

    def postProcess(self):
        super(VaporCompressionCycleWithRecuperator, self).postProcess()
        self.recuperatorHeat = self.recuperator.QDot

    def R134aCycle(self):
        super(VaporCompressionCycleWithRecuperator, self).R134aCycle()
        self.recuperator.eta = 0.7
Exemplo n.º 15
0
class VaporCompressionCycle(HeatPumpCycle):
    label = "Vapor compression cycle"
    figure = F.ModelFigure(
        src="ThermoFluids/img/ModuleImages/VaporCompressionCycle.svg")
    description = F.ModelDescription(
        "Basic vapor compression cycle used in refrigerators and air conditioners",
        show=True)

    #================ Inputs ================#
    #---------------- Fields ----------------#
    # FieldGroup
    compressor = F.SubModelGroup(TC.Compressor, 'FG', label='Compressor')
    condenser = F.SubModelGroup(TC.Condenser, 'FG', label='Condenser')
    throttleValve = F.SubModelGroup(TC.ThrottleValve, 'FG', label='JT valve')
    evaporator = F.SubModelGroup(TC.Evaporator, 'FG', label='Evaporator')
    inputs = F.SuperGroup(
        ['workingFluidGroup', compressor, condenser, evaporator],
        label='Cycle definition')

    #---------------- Actions ----------------#
    exampleAction = ServerAction(
        "loadEg",
        label="Examples",
        options=(
            ('R134aCycle', 'Typical fridge with R134a as a refrigerant'),
            ('CO2TranscriticalCycle', 'CO2 transcritial cycle'),
        ))
    #--------------- Model view ---------------#
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs, 'cycleDiagram', 'solver'],
                            actionBar=ActionBar([exampleAction]),
                            autoFetch=True)

    #================ Results ================#
    compressorPower = F.Quantity('Power',
                                 default=(1, 'kW'),
                                 label='compressor power')
    condenserHeat = F.Quantity('HeatFlowRate',
                               default=(1, 'kW'),
                               label='condenser heat out')
    evaporatorHeat = F.Quantity('HeatFlowRate',
                                default=(1, 'kW'),
                                label='evaporator heat in')
    flowFieldGroup = F.FieldGroup(
        [compressorPower, condenserHeat, evaporatorHeat], label='Energy flows')
    resultEnergy = F.SuperGroup([flowFieldGroup, 'efficiencyFieldGroup'],
                                label='Energy')
    resultView = F.ModelView(ioType="output",
                             superGroups=[
                                 'resultDiagrams', 'resultStates',
                                 resultEnergy, 'solverStats'
                             ])

    #============= Page structure =============#
    modelBlocks = [inputView, resultView]

    #================ Methods ================#
    def __init__(self):
        self.R134aCycle()

    def compute(self):
        if (self.cycleTranscritical and self.condenser.computeMethod == 'dT'):
            raise ValueError(
                'In transcritical cycle, condenser sub-cooling cannot be used as input'
            )
        if (self.cycleSupercritical and self.evaporator.computeMethod == 'dT'):
            raise ValueError(
                'In supercritical cycle, evaporator super-heating cannot be used as input'
            )
        self.initCompute(fluid=self.fluidName)
        # Connect components
        self.connectPorts(self.evaporator.outlet, self.compressor.inlet)
        self.connectPorts(self.compressor.outlet, self.condenser.inlet)
        self.connectPorts(self.condenser.outlet, self.throttleValve.inlet)
        self.connectPorts(self.throttleValve.outlet, self.evaporator.inlet)
        # Initial guess
        for fl in self.flows:
            fl.mDot = self.mDot
        self.evaporator.outlet.state.update_pq(self.pLow, 1)
        # Cycle iterations
        self.solver.run()
        # Results
        self.postProcess()

    def computeCycle(self):
        self.compressor.compute(self.pHigh)
        self.condenser.compute()
        self.throttleValve.compute(self.pLow)
        self.evaporator.compute()

    def postProcess(self):
        super(VaporCompressionCycle, self).postProcess(self.TAmbient)
        # Flows
        self.compressorPower = self.mDot * self.compressor.w
        self.compressorHeat = -self.mDot * self.compressor.qIn
        self.condenserHeat = -self.mDot * self.condenser.qIn
        self.evaporatorHeat = self.mDot * self.evaporator.qIn
        # Efficiencies
        self.COPCooling = self.evaporatorHeat / self.compressorPower
        self.COPHeating = self.condenserHeat / self.compressorPower

    def CO2TranscriticalCycle(self):
        self.fluidName = 'CarbonDioxide'
        self.pHighMethod = 'P'
        self.pHigh = (130, 'bar')
        self.pLowMethod = 'T'
        self.TEvaporation = (10, 'degC')
        self.compressor.modelType = 'S'
        self.compressor.etaS = 0.8
        self.compressor.fQ = 0.2
        self.condenser.computeMethod = 'T'
        self.condenser.TOutlet = (50, 'degC')
        self.evaporator.computeMethod = 'dT'
        self.evaporator.dTOutlet = (5, 'degC')

    def R134aCycle(self):
        self.fluidName = 'R134a'
        self.pHighMethod = 'P'
        self.pHigh = (10, 'bar')
        self.pLowMethod = 'T'
        self.TEvaporation = (-20, 'degC')
        self.compressor.modelType = 'S'
        self.compressor.etaS = 0.75
        self.compressor.fQ = 0.0
        self.condenser.computeMethod = 'T'
        self.condenser.TOutlet = (36, 'degC')
        self.evaporator.computeMethod = 'Q'
        self.evaporator.qOutlet = 1.0
Exemplo n.º 16
0
class ThermodynamicalCycle(NumericalModel):
    abstract = True
    #================ Inputs ================#
    # Cycle diagram
    cycleDiagram = F.SubModelGroup(TC.CycleDiagram,
                                   'inputs',
                                   label='Diagram settings')
    # Solver settings
    solver = F.SubModelGroup(CycleIterator, 'solverSettings', label='Solver')
    #================ Results ================#
    #---------------- Fields ----------------#
    cycleStatesTable = F.TableView(
        (('T', F.Quantity('Temperature', default=(1, 'degC'))),
         ('p', F.Quantity('Pressure', default=(1, 'bar'))),
         ('rho', F.Quantity('Density', default=(1, 'kg/m**3'))),
         ('h', F.Quantity('SpecificEnthalpy', default=(1, 'kJ/kg'))),
         ('s', F.Quantity('SpecificEntropy', default=(1, 'kJ/kg-K'))),
         ('q', F.Quantity()),
         ('dT', F.Quantity('TemperatureDifference', default=(1, 'degC'))),
         ('mDot', F.Quantity('MassFlowRate', default=(1, 'kg/min'))),
         ('b', F.Quantity('SpecificEnergy', default=(1, 'kJ/kg')))),
        label="Cycle states")

    cycleStates = F.ViewGroup([cycleStatesTable], label="States")
    resultStates = F.SuperGroup([cycleStates], label="States")
    #---------------- Cycle diagram -----------#
    phDiagram = F.Image(default='')
    cycleDiagramVG = F.ViewGroup([phDiagram], label="P-H Diagram")
    resultDiagrams = F.SuperGroup([cycleDiagramVG], label="Diagrams")
    #---------------- Convergence parameters -----------#
    residualPlot = F.PlotView((('iteration #', F.Quantity('Dimensionless')),
                               ('h change', F.Quantity('SpecificEnthalpy'))),
                              label='Residual (plot)',
                              ylog=True)
    iterationTable = F.TableView((
        ('h1', F.Quantity('SpecificEnthalpy')),
        ('h2', F.Quantity('SpecificEnthalpy')),
        ('h3', F.Quantity('SpecificEnthalpy')),
        ('h4', F.Quantity('SpecificEnthalpy')),
        ('h5', F.Quantity('SpecificEnthalpy')),
        ('h6', F.Quantity('SpecificEnthalpy')),
        ('h7', F.Quantity('SpecificEnthalpy')),
        ('h8', F.Quantity('SpecificEnthalpy')),
        ('h9', F.Quantity('SpecificEnthalpy')),
        ('h10', F.Quantity('SpecificEnthalpy')),
        ('h11', F.Quantity('SpecificEnthalpy')),
        ('h12', F.Quantity('SpecificEnthalpy')),
        ('h13', F.Quantity('SpecificEnthalpy')),
        ('h14', F.Quantity('SpecificEnthalpy')),
        ('h15', F.Quantity('SpecificEnthalpy')),
        ('h16', F.Quantity('SpecificEnthalpy')),
        ('h17', F.Quantity('SpecificEnthalpy')),
        ('h18', F.Quantity('SpecificEnthalpy')),
        ('h19', F.Quantity('SpecificEnthalpy')),
        ('h20', F.Quantity('SpecificEnthalpy')),
    ),
                                 label='Residual (table)',
                                 options={'formats': (['0.0000E0'] * 20)})
    residualGroup = F.ViewGroup([residualPlot, iterationTable],
                                label='Iterations')
    solverStats = F.SuperGroup([residualGroup], label='Convergence')

    # Info fields
    cycleTranscritical = F.Boolean(default=False)
    cycleSupercritical = F.Boolean(default=False)

    def initCompute(self, fluid):
        # Create fluid points
        self.fluid = Fluid(fluid)
        self.fp = []  #[FluidState(fluid) for _ in range(numPoints)]
        self.flows = []
        self.solver.cycle = self

    def connectPorts(self, port1, port2, fluid=None):
        if fluid == None:
            fluid = self.fluid
        fp = FluidState(fluid)
        flow = P.FluidFlow()
        self.fp.append(fp)
        self.flows.append(flow)
        port1.state = fp
        port2.state = fp
        port1.flow = flow
        port2.flow = flow

    def solve(self):
        self.solver.run()
        self.residualPlot.resize(len(self.solver.change_hHistory))
        for i in range(len(self.solver.change_hHistory)):
            self.residualPlot[i] = (i + 1, self.solver.change_hHistory[i])
        self.iterationTable.resize(len(self.solver.hHistory))
        v = self.iterationTable.view(dtype=np.float).reshape(
            -1, len(self.iterationTable.dtype))
        numCols = len(self.solver.hHistory[0])
        for i in range(len(self.solver.hHistory)):
            v[i, :numCols] = self.solver.hHistory[i]


# 		print self.iterationTable
# 		iterRecord = np.zeros(1, dtype = self.iterationTable.dtype)
# 		numCols = len(self.solver.hHistory[0])
# 		for i in range(len(self.solver.hHistory)):
# 			for j in range(numCols):
# 				iterRecord[j] = self.solver.hHistory[i][j]
# 			self.iterationTable[i] = iterRecord

    def postProcess(self, TAmbient):
        ## State diagram
        if (self.cycleDiagram.enable):
            self.createStateDiagram()
        ## Table of states
        self.cycleStatesTable.resize(len(self.fp))
        for i in range(len(self.fp)):
            fp = self.fp[i]
            self.cycleStatesTable[i] = (fp.T, fp.p, fp.rho, fp.h, fp.s, fp.q,
                                        fp.dT, self.flows[i].mDot,
                                        fp.b(TAmbient))
        # Select the zero for the exergy scale
        fp = FluidState(self.fluid)
        fp.update_Tp(TAmbient, 1e5)
        b0 = fp.b(TAmbient)
        self.cycleStatesTable['b'] -= b0

    def createStateDiagram(self):
        ncp = len(self.fp)
        fluidLines = []
        for i in range(ncp):
            fluidLines.append((self.fp[i], self.fp[(i + 1) % ncp]))
        self.phDiagram = self.cycleDiagram.draw(self.fluid, self.fp,
                                                fluidLines)

    def setPLow(self, p):
        if (self.fluid.tripple['p'] < p < self.fluid.critical['p']):
            self.pLow = p
            sat = self.fluid.saturation_p(p)
            self.TEvaporation = sat['TsatL']
        elif (p > self.fluid.critical['p']):
            self.pLow = p
            self.cycleSupercritical = True
        else:
            raise ValueError(
                'PLow  ({} bar) must be between {} bar and {} bar'.format(
                    p / 1e5, self.fluid.tripple['p'] / 1e5,
                    self.fluid.critical['p'] / 1e5))

    def setPHigh(self, p):
        if (self.fluid.tripple['p'] < p < self.fluid.critical['p']):
            self.pHigh = p
            sat = self.fluid.saturation_p(p)
            self.TCondensation = sat['TsatL']
        elif (p > self.fluid.critical['p']):
            self.pHigh = p
            self.cycleTranscritical = True
        else:
            raise ValueError(
                'PHigh  ({} bar) must be between {} bar and {} bar'.format(
                    p / 1e5, self.fluid.tripple['p'] / 1e5,
                    self.fluid.critical['p'] / 1e5))
Exemplo n.º 17
0
class ClaudeCycle(LindeHampsonCycle):
    label = "Claude cycle"
    figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/ClaudeCycle.svg",
                           height=300)
    description = F.ModelDescription(
        "Liquefaction cycle using an expander and 3 recurperators for increased efficiency",
        show=True)

    #================ Inputs ================#
    #---------------- Fields ----------------#
    # FieldGroup
    recuperator2 = F.SubModelGroup(TC.HeatExchangerTwoStreams,
                                   'FG',
                                   label='Recuperator 2')
    recuperator3 = F.SubModelGroup(TC.HeatExchangerTwoStreams,
                                   'FG',
                                   label='Recuperator 3')
    expander = F.SubModelGroup(TC.Turbine, 'FG', label='Expander')
    expanderFlowFraction = F.Quantity('Fraction', label='flow fraction')
    expanderEta = F.Quantity('Efficiency', label='efficiency')
    expanderFG = F.FieldGroup([expanderFlowFraction, expanderEta],
                              label='Expander')
    expanderSplitter = F.SubModelGroup(TC.FlowSplitter, 'FG')
    expanderJunction = F.SubModelGroup(TC.FlowJunction, 'FG')
    inputs = F.SuperGroup([
        'workingFluidGroup', 'compressor', 'cooler', expanderFG, 'recuperator',
        recuperator2, recuperator3
    ],
                          label='Cycle definition')
    #---------------- Actions ----------------#
    exampleAction = ServerAction(
        "loadEg",
        label="Examples",
        options=(
            ('NitrogenMediumP',
             'Nitrogen medium pressure (30 bar) liquefaction cycle'),
            ('NitrogenLowP',
             'Nitrogen low pressure (8 bar) liquefacton cycle'),
        ))
    #--------------- Model view ---------------#
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs, 'cycleDiagram', 'solver'],
                            actionBar=ActionBar([exampleAction]),
                            autoFetch=True)

    #================ Results ================#
    #---------------- Scheme -----------------#
    scheme_Claude = F.Image(
        default="static/ThermoFluids/img/ModuleImages/ClaudeCycle.png")
    SchemeVG = F.ViewGroup([scheme_Claude], label="Process Scheme")
    SchemeSG = F.SuperGroup([SchemeVG], label="Scheme")

    resultView = F.ModelView(ioType="output",
                             superGroups=[
                                 'resultDiagrams', SchemeSG, 'resultStates',
                                 'resultEnergy', 'solverStats'
                             ])

    def __init__(self):
        self.cooler.computeMethod = 'eta'
        self.cooler.TExt = self.TAmbient
        self.NitrogenMediumP()

    def compute(self):
        self.initCompute(self.fluidName)
        self.expanderSplitter.frac1 = 1 - self.expanderFlowFraction
        self.expanderSplitter.frac2 = self.expanderFlowFraction
        self.expander.eta = self.expanderEta
        # Connect components
        self.connectPorts(self.gasSource.outlet, self.inletJunct.inletMain)
        self.connectPorts(self.inletJunct.outlet, self.compressor.inlet)
        self.connectPorts(self.compressor.outlet, self.cooler.inlet)
        self.connectPorts(self.cooler.outlet, self.recuperator.inlet1)
        self.connectPorts(self.recuperator.outlet1,
                          self.expanderSplitter.inlet)
        self.connectPorts(self.expanderSplitter.outlet1,
                          self.recuperator2.inlet1)
        self.connectPorts(self.recuperator2.outlet1, self.recuperator3.inlet1)
        self.connectPorts(self.recuperator3.outlet1, self.throttleValve.inlet)
        self.connectPorts(self.throttleValve.outlet, self.liqSeparator.inlet)
        self.connectPorts(self.liqSeparator.outletVapor,
                          self.secThrottleValve.inlet)
        self.connectPorts(self.secThrottleValve.outlet,
                          self.recuperator3.inlet2)
        self.connectPorts(self.recuperator3.outlet2,
                          self.expanderJunction.inletMain)
        self.connectPorts(self.expanderJunction.outlet,
                          self.recuperator2.inlet2)
        self.connectPorts(self.recuperator2.outlet2, self.recuperator.inlet2)
        self.connectPorts(self.recuperator.outlet2, self.inletJunct.inlet2)
        self.connectPorts(self.expanderSplitter.outlet2, self.expander.inlet)
        self.connectPorts(self.expander.outlet, self.expanderJunction.inlet2)
        self.connectPorts(self.liqSeparator.outletLiquid,
                          self.liquidSink.inlet)

        # Initial guess
        liqFractionGuess = 0.5
        for fl in self.flows:
            fl.mDot = 1.0 / liqFractionGuess * self.mDot
        for fp in self.fp:
            fp.update_Tp(self.TAmbient, self.pIn)

        # Initialize source
        self.gasSource.T = self.TIn
        self.gasSource.p = self.pIn
        self.gasSource.mDot = self.mDot
        self.gasSource.compute()
        # Run solver
        self.solve()
        # Results
        self.postProcess(self.TAmbient)

    def computeCycle(self):
        self.compressor.compute(self.pHigh)
        self.cooler.compute()
        self.recuperator.compute()
        self.recuperator.computeStream1()
        self.expanderSplitter.compute()
        self.recuperator2.compute()
        self.recuperator2.computeStream1()
        self.recuperator3.compute()
        self.recuperator3.computeStream1()
        self.throttleValve.compute(self.pLiquid)
        self.liqSeparator.compute()
        self.secThrottleValve.compute(self.pIn)
        self.recuperator3.computeStream2()
        self.expander.compute(self.pIn)
        self.expanderJunction.compute()
        self.recuperator2.computeStream2()
        self.recuperator.computeStream2()
        self.inletJunct.compute()

    def createStateDiagram(self):
        lineNumbers = [(2, 3), (3, 4), (4, 5), (6, 7), (7, 8), (8, 9), (9, 10),
                       (9, 18), (10, 11), (11, 12), (13, 14), (14, 15),
                       (16, 17)]
        fluidLines = []
        for i, j in lineNumbers:
            fluidLines.append((self.fp[i - 1], self.fp[j - 1]))
        self.phDiagram = self.cycleDiagram.draw(self.fluid, self.fp,
                                                fluidLines)

    def NitrogenLiquefaction(self):
        self.fluidName = "Nitrogen"
        self.pIn = (1, 'bar')
        self.TIn = self.TAmbient
        self.pHigh = (30, 'bar')
        self.pLiquid = (1.2, 'bar')
        self.compressor.modelType = 'T'
        self.compressor.etaT = 0.8
        self.compressor.dT = 50.
        self.cycleDiagram.defaultMaxP = False
        self.cycleDiagram.defaultMaxT = False
        self.cycleDiagram.maxPressure = (500, 'bar')
        self.cycleDiagram.maxTemperature = 350

    def NitrogenMediumP(self):
        self.fluidName = "Nitrogen"
        self.pIn = (1, 'bar')
        self.TIn = self.TAmbient
        self.mDot = (0.188, 'kg/s')
        self.pHigh = (30, 'bar')
        self.pLiquid = (1.2, 'bar')
        self.compressor.modelType = 'T'
        self.compressor.etaT = 0.8
        self.compressor.dT = 50
        self.cooler.computeMethod = 'eta'
        self.cooler.etaThermal = 1.
        self.cooler.TExt = (30, 'degC')
        self.expanderEta = 0.8
        self.expanderFlowFraction = 0.66
        self.recuperator.computeMethod = 'EG'
        self.recuperator.epsGiven = 0.99
        self.recuperator2.computeMethod = 'EN'
        self.recuperator2.UA = (1950, 'W/K')
        self.recuperator3.computeMethod = 'EG'
        self.recuperator3.epsGiven = 0
        self.cycleDiagram.defaultMaxT = False
        self.cycleDiagram.maxTemperature = 400

    def NitrogenLowP(self):
        self.fluidName = "Nitrogen"
        self.pIn = (1.1, 'bar')
        self.TIn = (300, 'K')
        self.mDot = (12.8, 'kg/h')
        self.pHigh = (8, 'bar')
        self.pLiquid = (1.2, 'bar')
        self.TAmbient = (300, 'K')
        self.compressor.modelType = 'S'
        self.compressor.etaS = 0.8
        self.compressor.fQ = 0.3
        self.cooler.computeMethod = 'eta'
        self.cooler.etaThermal = 1.
        self.cooler.TExt = (310, 'K')
        self.expanderEta = 0.5
        self.expanderFlowFraction = 0.94
        self.recuperator.computeMethod = 'EN'
        self.recuperator.UA = (1280, 'W/K')
        self.recuperator2.computeMethod = 'EN'
        self.recuperator2.UA = (90, 'W/K')
        self.recuperator3.computeMethod = 'EG'
        self.recuperator3.epsGiven = 0
        self.cycleDiagram.defaultMaxT = False
        self.cycleDiagram.maxTemperature = 550
Exemplo n.º 18
0
class ChemostatDDE2_ESA(NumericalModel):
    label = "DDE Chemostat (Example 2 - ESA)"
    description = F.ModelDescription(
        "Chemostat model with delay differential equations (DDE) and extremum seeking algorithm (ESA) - Example 2",
        show=True)
    figure = F.ModelFigure(
        src="BioReactors/img/ModuleImages/SimpleChemostat.png", show=False)

    #1. ############ Inputs ###############
    #1.1 Fields - Input values
    # Parameters
    k1 = F.Quantity(
        default=0,
        minValue=0,
        maxValue=1e6,
        label='k<sub>1</sub>',
        description=
        'yield coefficient related to substrate-1 consumption from bacteria-1')
    k2 = F.Quantity(
        default=0,
        minValue=0,
        maxValue=1e6,
        label='k<sub>2</sub>',
        description=
        'yield coefficient related to substrate-2 production from bacteria-1')
    k3 = F.Quantity(
        default=0,
        minValue=0,
        maxValue=1e6,
        label='k<sub>3</sub>',
        description=
        'yield coefficient related to substrate-2 consumption from bacteria-2')
    k4 = F.Quantity(
        default=0,
        minValue=0,
        maxValue=1e6,
        label='k<sub>4</sub>',
        description=
        'yield coefficient of methane (biogas) on bacteria-2 and substrate-2')
    s1_in = F.Quantity('Bio_MassConcentration',
                       default=(0, 'g/L'),
                       label='s<sub>1</sub><sup>in</sub>',
                       description='input substrate-1 concentration')
    s2_in = F.Quantity('Bio_MassConcentration',
                       default=(0, 'g/L'),
                       label='s<sub>2</sub><sup>in</sub>',
                       description='input substrate-2 concentration')
    a = F.Quantity(
        'Fraction',
        default=(0, '-'),
        label='&#945',
        description=
        'proportion of organisms that are affected by the dilution rate D')
    D = F.Quantity('Bio_TimeRate',
                   default=(0, '1/day'),
                   minValue=(0, '1/day'),
                   label='D',
                   description='dilution rate')
    parametersFG = F.FieldGroup([s1_in, s2_in, k1, k2, k3, k4, a, D],
                                label='Parameters')

    # Parameters - specific growth rates
    m1 = F.Quantity('Bio_TimeRate',
                    default=(0, '1/day'),
                    minValue=(0, '1/day'),
                    label='m<sub>1</sub>',
                    description='maximum specific growth rate of bacteria-1')
    m2 = F.Quantity('Bio_TimeRate',
                    default=(0, '1/day'),
                    minValue=(0, '1/day'),
                    label='m<sub>2</sub>',
                    description='maximum specific growth rate of bacteria-2')
    k_s1 = F.Quantity('Bio_MassConcentration',
                      default=(0, 'g/L'),
                      label='k<sub>s1</sub>',
                      description='half saturation constant of bacteria-1')
    k_s2 = F.Quantity('Bio_MassConcentration',
                      default=(0, 'g/L'),
                      label='k<sub>s2</sub>',
                      description='half saturation constant of bacteria-2')
    k_I = F.Quantity('Dimensionless',
                     default=(0, '-'),
                     label='k<sub>I</sub>',
                     description='constant in unit: [ sqrt( g/L ) ]')
    parametersMuFG = F.FieldGroup([m1, m2, k_s1, k_s2, k_I],
                                  label='Parameters - specific growth rates')

    # Parameters - time delays
    tau1 = F.Quantity(
        'Bio_Time',
        default=(0, 'day'),
        minValue=(0, 'day'),
        label='&#964<sub>1</sub>',
        description=
        'time delay in conversion of the substrate-1 to viable biomass for bacteria-1'
    )
    tau2 = F.Quantity(
        'Bio_Time',
        default=(0, 'day'),
        minValue=(0, 'day'),
        label='&#964<sub>2</sub>',
        description=
        'time delay in conversion of the substrate-2 to viable biomass for bacteria-2'
    )
    parametersTauFG = F.FieldGroup([tau1, tau2],
                                   label='Parameters - time delay')

    # historical initial conditions
    s1_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(0, 'g/L'),
        label='s<sub>1</sub><sup>&#91-&#964<sub>1</sub>, 0&#93</sup>',
        description='historical initial condition for substrate-1 concentration'
    )
    x1_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(0, 'g/L'),
        label='x<sub>1</sub><sup>&#91-&#964<sub>1</sub>, 0&#93</sup>',
        description='historical initial condition for bacteria-1 concentration'
    )
    s2_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(0, 'g/L'),
        label='s<sub>2</sub><sup>&#91-&#964<sub>2</sub>, 0&#93</sup>',
        description='historical initial condition for substrate-2 concentration'
    )
    x2_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(0, 'g/L'),
        label='x<sub>2</sub><sup>&#91-&#964<sub>2</sub>, 0&#93</sup>',
        description='historical initial condition for bacteria-2 concentration'
    )
    parametersHistFG = F.FieldGroup(
        [s1_hist_vals, x1_hist_vals, s2_hist_vals, x2_hist_vals],
        label='Historical initial conditions')

    inputValuesSG = F.SuperGroup(
        [parametersMuFG, parametersFG, parametersTauFG, parametersHistFG],
        label="Input values")

    #1.2 Fields - Settings
    ESA_enable = F.Boolean(
        default=False,
        label='enable',
        description=
        'find the the maximum methane flow rate (i.e. run extremum seeking algorithm)'
    )
    ESA_DMin = F.Quantity('Bio_TimeRate',
                          default=(0, '1/day'),
                          minValue=(0.0, '1/day'),
                          label='D<sub>min</sub>',
                          description='minimum dilution rate',
                          show='self.ESA_enable')
    ESA_DMax = F.Quantity('Bio_TimeRate',
                          default=(0, '1/day'),
                          minValue=(0.0, '1/day'),
                          label='D<sub>max</sub>',
                          description='maximum dilution rate',
                          show='self.ESA_enable')
    ESA_eps = F.Quantity('Bio_TimeRate',
                         default=(0, '1/day'),
                         minValue=(1e-9, '1/day'),
                         maxValue=(1.0, '1/day'),
                         label='&#949*',
                         description='D max tolerance',
                         show='self.ESA_enable')
    ESA_h = F.Quantity('Bio_TimeRate',
                       default=(0, '1/day'),
                       minValue=(1e-8, '1/day'),
                       maxValue=(1.0, '1/day'),
                       label='h*',
                       description='seeking step of D max',
                       show='self.ESA_enable')
    ESA_eps_z = F.Quantity('Bio_MassConcentration',
                           default=(0, 'g/L'),
                           minValue=(1e-9, 'g/L'),
                           maxValue=(1.0, 'g/L'),
                           label='&#949<sub>z</sub>*',
                           description='equilibrium point tolerance',
                           show='self.ESA_enable')
    ESA_FG = F.FieldGroup(
        [ESA_enable, ESA_DMin, ESA_DMax, ESA_eps, ESA_h, ESA_eps_z],
        label='Extremum Seeking Algorithm (ESA)')

    DsQs_DMin = F.Quantity('Bio_TimeRate',
                           default=(0, '1/day'),
                           minValue=(0, '1/day'),
                           label='D<sub>min</sub>',
                           description='minimum dilution rate')
    DsQs_DMax = F.Quantity('Bio_TimeRate',
                           default=(0, '1/day'),
                           minValue=(0, '1/day'),
                           label='D<sub>max</sub>',
                           description='maximum dilution rate')
    DsQs_Step = F.Quantity('Bio_TimeRate',
                           default=(0, '1/day'),
                           minValue=(1e-4, '1/day'),
                           maxValue=(1.0, '1/day'),
                           label='D<sub>step</sub>',
                           description='step of dilution rate')
    DsQs_FG = F.FieldGroup([DsQs_DMin, DsQs_DMax, DsQs_Step],
                           label='Chart (Ds, Qs)')

    tFinal = F.Quantity('Bio_Time',
                        default=(100, 'day'),
                        minValue=(0, 'day'),
                        maxValue=(5000, 'day'),
                        label='simulation time')
    tPrint = F.Quantity('Bio_Time',
                        default=(0.1, 'day'),
                        minValue=(1e-5, 'day'),
                        maxValue=(100, 'day'),
                        label='print interval*')
    mainSimStep = F.Quantity('Bio_Time',
                             default=(10., 'day'),
                             minValue=(0.25, 'day'),
                             maxValue=(1e3, 'day'),
                             label='main simulation step*')
    absTol = F.Quantity('Bio_Time',
                        default=(1e-12, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-5, 'day'),
                        label='absolute tolerance*')
    relTol = F.Quantity('Bio_Time',
                        default=(1e-12, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-3, 'day'),
                        label='relative tolerance*')
    solverFG = F.FieldGroup([tFinal, tPrint, mainSimStep, absTol, relTol],
                            label='Solver')

    settingsSG = F.SuperGroup([solverFG, DsQs_FG, ESA_FG], label='Settings')

    #1.4 Model view
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputValuesSG, settingsSG],
                            autoFetch=True)

    #2. ############ Results ###############
    # 2.1. Results
    dataSeries = (
        ('time', F.Quantity('Bio_Time', default=(1, 'day'))),
        ('s1', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
        ('x1', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
        ('s2', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
        ('x2', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
        ('D', F.Quantity('Bio_TimeRate', default=(1, '1/day'))),
        ('Q',
         F.Quantity('Bio_MassConcentrationFlowRate', default=(1, 'g/L/day'))),
    )

    plot = F.PlotView(
        dataSeries,
        label='Plot',
        options={
            'ylabel': None,
            'title': 'Chemostat (DDE)'
        },
    )
    table = F.TableView(dataSeries,
                        label='Table',
                        options={
                            'title':
                            'Title',
                            'formats': [
                                '0.0000', '0.0000', '0.0000', '0.0000',
                                '0.0000', '0.0000', '0.0000'
                            ]
                        })

    chartS1S2 = F.MPLPlot(label='Chart (s<sub>1</sub>, s<sub>2</sub>)')
    chartX1X2 = F.MPLPlot(label='Chart (x<sub>1</sub>, x<sub>2</sub>)')
    chartS1X1 = F.MPLPlot(label='Chart (s<sub>1</sub>, x<sub>1</sub>)')
    chartS2X2 = F.MPLPlot(label='Chart (s<sub>2</sub>, x<sub>2</sub>)')
    chartS2X2 = F.MPLPlot(label='Chart (s<sub>2</sub>, x<sub>2</sub>)')
    chartDQ = F.MPLPlot(label='Chart (D, Q)')
    chartDsQs = F.MPLPlot(label='Chart (Ds, Qs)')

    resultsVG = F.ViewGroup([
        plot, table, chartS1S2, chartX1X2, chartS1X1, chartS2X2, chartDQ,
        chartDsQs
    ],
                            label='Results')
    resultsSG = F.SuperGroup([resultsVG], label="Results")

    # 2.2 Equilibrium point
    s1_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='s<sub>1</sub><sup>*</sup>',
        description='substrate-1 concentration at the equilibrium point')
    x1_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='x<sub>1</sub><sup>*</sup>',
        description='bacteria-1 concentration at the equilibrium point')
    s2_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='s<sub>2</sub><sup>*</sup>',
        description='substrate-2 concentration at the equilibrium point')
    x2_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='x<sub>2</sub><sup>*</sup>',
        description='bacteria-1 concentration at the equilibrium point')

    equilibriumPointFG = F.FieldGroup([s1_eqpnt, x1_eqpnt, s2_eqpnt, x2_eqpnt],
                                      label='Equilibrium point')
    equilibriumPointSG = F.SuperGroup([equilibriumPointFG],
                                      label='Equilibrium point')

    # 2.3 ESA Results
    resESA_QMaxIsFound = F.Boolean(label='Q<sub>max</sub> is found')
    resESA_DMax = F.Quantity('Bio_TimeRate',
                             default=(0, '1/day'),
                             label='D<sub>max</sub>',
                             description='maximum dilution rate')
    resESA_QMax = F.Quantity('Bio_MassConcentrationFlowRate',
                             default=(0, 'g/L/day'),
                             label='Q<sub>max</sub>',
                             description='maximum methane (biogas) flow rate')
    resESA_FG = F.FieldGroup([resESA_QMaxIsFound, resESA_DMax, resESA_QMax],
                             label='Results (ESA)')
    resESA_SG = F.SuperGroup([resESA_FG], label='Results (ESA)')

    #2.1 Model view
    resultView = F.ModelView(
        ioType="output",
        superGroups=[resultsSG, resESA_SG, equilibriumPointSG])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    def __init__(self):
        self.k1 = (10.53, '-')
        self.k2 = (28.6, '-')
        self.k3 = (1074, '-')
        self.k4 = (100, '-')
        self.s1_in = (7.5, 'g/L')
        self.s2_in = (75, 'g/L')
        self.a = (0.5, '-')
        self.m1 = (1.2, '1/day')
        self.m2 = (0.74, '1/day')
        self.k_s1 = (7.1, 'g/L')
        self.k_s2 = (9.28, 'g/L')
        self.k_I = (16, '-')
        self.D = (0.25, '1/day')
        self.tau1 = (2, 'day')
        self.tau2 = (7, 'day')
        self.s1_hist_vals = (2, 'g/L')
        self.x1_hist_vals = (0.1, 'g/L')
        self.s2_hist_vals = (10, 'g/L')
        self.x2_hist_vals = (0.05, 'g/L')

        self.DsQs_DMin = (0.0, '1/day')
        self.DsQs_DMax = (1.0, '1/day')
        self.DsQs_Step = (0.01, '1/day')

        self.tFinal = (2000, 'day')
        self.tPrint = (1.0, 'day')
        self.mainSimStep = (10., 'day')
        self.absTol = (1e-12, 'day')
        self.relTol = (1e-12, 'day')

        self.ESA_enable = True
        self.ESA_DMin = (0.01, '1/day')
        self.ESA_DMax = (0.33, '1/day')
        self.ESA_eps = (0.01, '1/day')
        self.ESA_h = (0.025, '1/day')
        self.ESA_eps_z = (0.01, 'g/L')

    def compute(self):
        chemostatDDE = DM.ChemostatDDE2_ESA(self)
        if self.ESA_enable:
            chemostatDDE.runESA(self)
        else:
            chemostatDDE.run(self)

        resESA = chemostatDDE.getResultsESA()
        self.resESA_QMaxIsFound = resESA['QMaxIsFound']
        self.resESA_DMax = (resESA['DMax'], '1/day')
        self.resESA_QMax = (resESA['QMax'], 'kg/m**3/day')

        res = chemostatDDE.getResults()
        results = np.array([
            res['t'], res['s1'], res['x1'], res['s2'], res['x2'], res['D'],
            res['Q']
        ]).transpose()
        self.plot = results
        self.table = results

        chemostatDDE.plotS1S2(self.chartS1S2)
        chemostatDDE.plotX1X2(self.chartX1X2)
        chemostatDDE.plotS1X1(self.chartS1X1)
        chemostatDDE.plotS2X2(self.chartS2X2)
        chemostatDDE.plotDQ(self.chartDQ)
        chemostatDDE.plotDsQs(self.chartDsQs)

        self.s1_eqpnt = (chemostatDDE.equilibriumPoint[0], 'kg/m**3')
        self.x1_eqpnt = (chemostatDDE.equilibriumPoint[1], 'kg/m**3')
        self.s2_eqpnt = (chemostatDDE.equilibriumPoint[2], 'kg/m**3')
        self.x2_eqpnt = (chemostatDDE.equilibriumPoint[3], 'kg/m**3')
Exemplo n.º 19
0
class LindeHampsonCycle(LiquefactionCycle):
    label = "Linde-Hampson cycle"
    figure = F.ModelFigure(
        src="ThermoFluids/img/ModuleImages/LindeHampson.svg", height=300)
    description = F.ModelDescription(
        "Basic liquefaction cycle used e.g. for air liquefaction", show=True)

    #================ Inputs ================#
    #---------------- Fields ----------------#
    # FieldGroup
    gasSource = F.SubModelGroup(TC.FluidSource_TP, 'FG')
    inletJunct = F.SubModelGroup(TC.FlowJunction, 'FG')
    compressor = F.SubModelGroup(TC.Compressor, 'FG', label='Compressor')
    cooler = F.SubModelGroup(TC.Condenser, 'FG', label='Cooler')
    recuperator = F.SubModelGroup(TC.HeatExchangerTwoStreams,
                                  'FG',
                                  label='Recuperator')
    throttleValve = F.SubModelGroup(TC.ThrottleValve, 'FG', label='JT valve')
    liqSeparator = F.SubModelGroup(TC.PhaseSeparator,
                                   'FG',
                                   label='Liquid separator')
    secThrottleValve = F.SubModelGroup(TC.ThrottleValve,
                                       'FG',
                                       label='JT valve')
    liquidSink = F.SubModelGroup(TC.FluidSink, 'FG')
    inputs = F.SuperGroup(
        ['workingFluidGroup', compressor, cooler, recuperator],
        label='Cycle definition')

    #---------------- Actions ----------------#
    exampleAction = ServerAction("loadEg",
                                 label="Examples",
                                 options=(
                                     ('ArgonLiquefaction',
                                      'Argon liquefaction cycle'),
                                     ('NitrogenLiquefaction',
                                      'Nitrogen liquefacton cycle'),
                                 ))
    #--------------- Model view ---------------#
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputs, 'cycleDiagram', 'solver'],
                            actionBar=ActionBar([exampleAction]),
                            autoFetch=True)

    #================ Results ================#
    compressorPower = F.Quantity('Power',
                                 default=(1, 'kW'),
                                 label='compressor power')
    compressorHeat = F.Quantity('HeatFlowRate',
                                default=(1, 'kW'),
                                label='compressor heat')
    coolerHeat = F.Quantity('HeatFlowRate',
                            default=(1, 'kW'),
                            label='cooler heat out')
    flowFieldGroup = F.FieldGroup(
        [compressorPower, compressorHeat, coolerHeat], label='Flows')
    resultEnergy = F.SuperGroup([flowFieldGroup, 'efficiencyFieldGroup'],
                                label='Energy')
    #---------------- Scheme -----------------#
    scheme_LindeHampson = F.Image(
        default="static/ThermoFluids/img/ModuleImages/LindeHampson.png")
    SchemeVG = F.ViewGroup([scheme_LindeHampson], label="Process Scheme")
    SchemeSG = F.SuperGroup([SchemeVG], label="Scheme")

    resultView = F.ModelView(ioType="output",
                             superGroups=[
                                 'resultDiagrams', SchemeSG, 'resultStates',
                                 resultEnergy, 'solverStats'
                             ])

    #============= Page structure =============#
    modelBlocks = [inputView, resultView]

    #================ Methods ================#
    def __init__(self):
        self.cooler.computeMethod = 'eta'
        self.cooler.TExt = self.TAmbient
        self.ArgonLiquefaction()

    def compute(self):
        self.initCompute(self.fluidName)
        # Connect components
        self.connectPorts(self.gasSource.outlet, self.inletJunct.inletMain)
        self.connectPorts(self.inletJunct.outlet, self.compressor.inlet)
        self.connectPorts(self.compressor.outlet, self.cooler.inlet)
        self.connectPorts(self.cooler.outlet, self.recuperator.inlet1)
        self.connectPorts(self.recuperator.outlet1, self.throttleValve.inlet)
        self.connectPorts(self.throttleValve.outlet, self.liqSeparator.inlet)
        self.connectPorts(self.liqSeparator.outletVapor,
                          self.secThrottleValve.inlet)
        self.connectPorts(self.secThrottleValve.outlet,
                          self.recuperator.inlet2)
        self.connectPorts(self.recuperator.outlet2, self.inletJunct.inlet2)
        self.connectPorts(self.liqSeparator.outletLiquid,
                          self.liquidSink.inlet)
        # Initialize source
        self.gasSource.T = self.TIn
        self.gasSource.p = self.pIn
        self.gasSource.mDot = self.mDot
        self.gasSource.compute()
        # Initial guess
        liqFractionGuess = 0.5
        for fl in self.flows:
            fl.mDot = 1.0 / liqFractionGuess * self.mDot
        for fp in self.fp:
            fp.update_Tp(self.TAmbient, self.pIn)


# 		liqFractionGuess = 0.2
# 		self.compressor.inlet.flow.mDot = 1.0 / liqFractionGuess * self.gasSource.outlet.flow.mDot
# 		self.liqSeparator.outletVapor.flow.mDot = liqFractionGuess * self.mDot
#
# 		self.compressor.inlet.state.update_Tp(
# 			self.gasSource.outlet.state.T, self.gasSource.outlet.state.p)
# 		self.secThrottleValve.outlet.state.update_pq(self.pIn, 1)
# Run solver
        self.solve()
        # Results
        self.postProcess(self.TAmbient)

    def computeCycle(self):
        self.compressor.compute(self.pHigh)
        self.cooler.compute()
        self.recuperator.compute()
        self.recuperator.computeStream1()
        self.throttleValve.compute(self.pLiquid)
        self.liqSeparator.compute()
        self.secThrottleValve.compute(self.pIn)
        self.recuperator.computeStream2()
        self.inletJunct.compute()

    def postProcess(self, TAmbient):
        LiquefactionCycle.postProcess(self, TAmbient)
        self.compressor.postProcess()
        self.cooler.postProcess()
        # Flows
        self.compressorPower = self.compressor.WDot
        self.compressorHeat = -self.compressor.QDotIn
        self.coolerHeat = -self.cooler.QDotIn
        # Efficiencies
        self.liqEnergy = self.compressor.WDot / self.liqSeparator.outletLiquid.flow.mDot
        self.minLiqEnergy = self.liqSeparator.outletLiquid.state.b(self.TAmbient) \
         - self.gasSource.outlet.state.b(self.TAmbient)
        self.etaSecondLaw = self.minLiqEnergy / self.liqEnergy

    def createStateDiagram(self):
        lineNumbers = [(2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (6, 10), (7, 8),
                       (8, 9)]
        fluidLines = []
        for i, j in lineNumbers:
            fluidLines.append((self.fp[i - 1], self.fp[j - 1]))
        self.phDiagram = self.cycleDiagram.draw(self.fluid, self.fp,
                                                fluidLines)

    def ArgonLiquefaction(self):
        self.fluidName = "Argon"
        self.pIn = (1, 'bar')
        self.TIn = self.TAmbient
        self.pHigh = (200, 'bar')
        self.pLiquid = (1.2, 'bar')
        self.compressor.modelType = 'T'
        self.compressor.etaT = 0.8
        self.compressor.dT = 50.
        self.recuperator.eta = 0.99
        self.cycleDiagram.defaultMaxP = False
        self.cycleDiagram.maxPressure = (300, 'bar')

    def NitrogenLiquefaction(self):
        self.fluidName = "Nitrogen"
        self.pIn = (1, 'bar')
        self.TIn = self.TAmbient
        self.pHigh = (300, 'bar')
        self.pLiquid = (1.2, 'bar')
        self.compressor.modelType = 'T'
        self.compressor.etaT = 0.8
        self.compressor.dT = 50.
        self.recuperator.eta = 0.99
        self.cycleDiagram.defaultMaxP = False
        self.cycleDiagram.defaultMaxT = False
        self.cycleDiagram.maxPressure = (500, 'bar')
        self.cycleDiagram.maxTemperature = 350
Exemplo n.º 20
0
class CylindricalBlockHeatExchanger(NumericalModel):
    label = "Cylindrical heat exchanger"
    figure = F.ModelFigure(
        src="ThermoFluids/img/ModuleImages/HeatExchangerDesign.png",
        show=False)
    description = F.ModelDescription(
        """Model of heat exchanger made out of a solid cylindrical block, with
	central channels for one of the fluids and a spiraling
	channel around the block for the other fluid
	""")

    async = True
    progressOptions = {'suffix': '%', 'fractionOutput': False}

    #================ Inputs ================#
    #---------------- Fields ----------------#
    # Fields: geometry
    blockGeom = F.SubModelGroup(BlockGeometry, 'FG', 'Geometry')
    blockProps = F.SubModelGroup(BlockProperties, 'FG', 'Properties')
    blockSG = F.SuperGroup([blockGeom, blockProps], label='Block')

    # Fields: internal channels
    primaryChannelsGeom = F.SubModelGroup(ChannelGroupGeometry,
                                          'FG',
                                          label='Primary channels')
    secondaryChannelsGeom = F.SubModelGroup(ChannelGroupGeometry,
                                            'FG',
                                            label='Secondary channels')
    primaryFlowIn = F.SubModelGroup(FluidFlowInput,
                                    'FG',
                                    label='Primary flow inlet')
    secondaryFlowIn = F.SubModelGroup(FluidFlowInput,
                                      'FG',
                                      label='Secondary flow inlet')
    internalChannelSG = F.SuperGroup([
        primaryChannelsGeom, secondaryChannelsGeom, primaryFlowIn,
        secondaryFlowIn
    ],
                                     label='Channels')

    # Fields: external channel
    externalChannelGeom = F.SubModelGroup(ExternalChannelGeometry,
                                          'FG',
                                          label='Geometry')
    externalFlowIn = F.SubModelGroup(IncompressibleSolutionFlowInput,
                                     'incomSolFG',
                                     label='Inlet flow')
    externalChannelSG = F.SuperGroup([externalChannelGeom, externalFlowIn],
                                     label='External channel')

    # Fields: settings
    fvSolverSettings = F.SubModelGroup(FiniteVolumeSolverSettings,
                                       'FG',
                                       label='Finite volume solver')
    sectionResultsSettings = F.SubModelGroup(SectionResultsSettings,
                                             'FG',
                                             label='Section results plots')
    settingsSG = F.SuperGroup([fvSolverSettings, sectionResultsSettings],
                              label='Settings')

    #--------------- Model view ---------------#
    inputView = F.ModelView(ioType="input",
                            superGroups=[
                                blockSG, internalChannelSG, externalChannelSG,
                                settingsSG
                            ],
                            autoFetch=True)

    #================ Results ================#
    meshView = F.MPLPlot(label='Cross-section mesh')
    crossSectionProfileView = F.MPLPlot(label='Cross-section profile')
    longitudinalProfileView = F.MPLPlot(label='Longitudinal profile')
    primaryChannelProfileView = F.MPLPlot(label='Primary channel profile')
    secondaryChannelProfileView = F.MPLPlot(label='Secondary channel profile')
    geometryVG = F.ViewGroup([
        meshView, crossSectionProfileView, longitudinalProfileView,
        primaryChannelProfileView, secondaryChannelProfileView
    ],
                             label='Geometry/Mesh')
    geometrySG = F.SuperGroup([geometryVG], label='Geometry/mesh')

    primaryFlowOut = F.SubModelGroup(FluidFlowOutput,
                                     'FG',
                                     label='Primary flow outlet')
    secondaryFlowOut = F.SubModelGroup(FluidFlowOutput,
                                       'FG',
                                       label='Secondary flow outlet')
    externalFlowOut = F.SubModelGroup(FluidFlowOutput,
                                      'FG',
                                      label='External flow outlet')
    QDotChannels = F.SubModelGroup(HeatFlowChannels, 'FG', label='Heat flow')
    resultSG = F.SuperGroup(
        [primaryFlowOut, secondaryFlowOut, externalFlowOut, QDotChannels],
        label='Results')

    resultTable = F.TableView((
        ('xStart', F.Quantity('Length', default=(1, 'm'))),
        ('xEnd', F.Quantity('Length', default=(1, 'm'))),
        ('TPrimFluid', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TPrimWall', F.Quantity('Temperature', default=(1, 'degC'))),
        ('RePrim', F.Quantity()),
        ('hConvPrim',
         F.Quantity('HeatTransferCoefficient', default=(1, 'W/m**2-K'))),
        ('QDotPrim', F.Quantity('HeatFlowRate', default=(1, 'W'))),
        ('TSecFluid', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TSecWall', F.Quantity('Temperature', default=(1, 'degC'))),
        ('ReSec', F.Quantity()),
        ('hConvSec',
         F.Quantity('HeatTransferCoefficient', default=(1, 'W/m**2-K'))),
        ('QDotSec', F.Quantity('HeatFlowRate', default=(1, 'W'))),
        ('TExtFluid', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TExtWall', F.Quantity('Temperature', default=(1, 'degC'))),
        ('ReExt', F.Quantity()),
        ('hConvExt',
         F.Quantity('HeatTransferCoefficient', default=(1, 'W/m**2-K'))),
        ('QDotExt', F.Quantity('HeatFlowRate', default=(1, 'W'))),
    ),
                              label='Detailed results')
    resultTPlot = F.PlotView((
        ('x', F.Quantity('Length', default=(1, 'm'))),
        ('TPrimFluid', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TPrimWall', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TSecFluid', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TSecWall', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TExtFluid', F.Quantity('Temperature', default=(1, 'degC'))),
        ('TExtWall', F.Quantity('Temperature', default=(1, 'degC'))),
    ),
                             label='Temperature plots')

    resultQPlot = F.PlotView((
        ('x', F.Quantity('Length', default=(1, 'm'))),
        ('QDotPrim', F.Quantity('HeatFlowRate', default=(1, 'W'))),
        ('QDotSec', F.Quantity('HeatFlowRate', default=(1, 'W'))),
        ('QDotExt', F.Quantity('HeatFlowRate', default=(1, 'W'))),
    ),
                             label='Heat flow plots')
    detailedResultVG = F.ViewGroup([resultTable, resultTPlot, resultQPlot],
                                   label='Detailed results')
    detailedResultSG = F.SuperGroup([detailedResultVG],
                                    label='Detailed results')

    sectionPlot1 = F.MPLPlot(label='Section 1')
    sectionPlot2 = F.MPLPlot(label='Section 2')
    sectionPlot3 = F.MPLPlot(label='Section 3')
    sectionPlot4 = F.MPLPlot(label='Section 4')
    sectionPlot5 = F.MPLPlot(label='Section 5')
    sectionResultsVG = F.ViewGroup(
        [sectionPlot1, sectionPlot2, sectionPlot3, sectionPlot4, sectionPlot5],
        label='Section temperatures')
    sectionResultsSG = F.SuperGroup([sectionResultsVG],
                                    label='Section results')

    resultView = F.ModelView(
        ioType="output",
        superGroups=[geometrySG, resultSG, detailedResultSG, sectionResultsSG])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    ############# Methods ###############
    def __init__Internal(self):
        self.blockGeom.diameter = (58.0, 'mm')
        self.blockGeom.length = (0.8, 'm')
        self.blockProps.divisionStep = (0.1, 'm')
        self.blockProps.material = 'Aluminium6061'

        self.primaryChannelsGeom.number = 3
        self.primaryChannelsGeom.radialPosition = (7, 'mm')
        self.primaryChannelsGeom.startingAngle = (0, 'deg')
        self.primaryChannelsGeom.meshFineness = 4
        self.primaryChannelsGeom.channelName = "PrimaryChannel"

        self.primaryChannelsGeom.externalDiameter = (7.5, 'mm')
        self.primaryChannelsGeom.sections[0] = (0.002, 0.2)
        self.primaryChannelsGeom.sections[1] = (0.004, 0.1)
        self.primaryChannelsGeom.sections[2] = (0.006, 0.1)
        self.primaryChannelsGeom.sections[3] = (0.0065, 0.1)
        self.primaryChannelsGeom.sections[4] = (0.007, 0.3)

        self.secondaryChannelsGeom.number = 3
        self.secondaryChannelsGeom.radialPosition = (17.5, 'mm')
        self.secondaryChannelsGeom.startingAngle = (60, 'deg')
        self.secondaryChannelsGeom.meshFineness = 4
        self.secondaryChannelsGeom.channelName = "SecondaryChannel"

        self.secondaryChannelsGeom.externalDiameter = (7.5, 'mm')
        self.secondaryChannelsGeom.sections[0] = (0.002, 0.2)
        self.secondaryChannelsGeom.sections[1] = (0.004, 0.1)
        self.secondaryChannelsGeom.sections[2] = (0.006, 0.1)
        self.secondaryChannelsGeom.sections[3] = (0.0065, 0.1)
        self.secondaryChannelsGeom.sections[4] = (0.007, 0.3)

        self.primaryFlowIn.fluidName = 'ParaHydrogen'
        self.primaryFlowIn.flowRateChoice = 'm'
        self.primaryFlowIn.mDot = (1, 'kg/h')
        self.primaryFlowIn.T = (100, 'K')
        self.primaryFlowIn.p = (1, 'bar')

        self.secondaryFlowIn.fluidName = 'ParaHydrogen'
        self.secondaryFlowIn.flowRateChoice = 'm'
        self.secondaryFlowIn.mDot = (1, 'kg/h')
        self.secondaryFlowIn.T = (100, 'K')
        self.secondaryFlowIn.p = (1, 'bar')

        self.externalFlowIn.solName = 'MEG'
        self.externalFlowIn.solMassFraction = (50, '%')
        self.externalFlowIn.flowRateChoice = 'V'
        self.externalFlowIn.VDot = (3, 'm**3/h')
        self.externalFlowIn.T = (80, 'degC')
        self.externalFlowIn.p = (1, 'bar')

        self.externalChannelGeom.widthAxial = (30, 'mm')
        self.externalChannelGeom.heightRadial = (12, 'mm')
        self.externalChannelGeom.coilPitch = (32, 'mm')
        self.externalChannelGeom.meshFineness = 4

        self.sectionResultsSettings.setTRange = False
        self.sectionResultsSettings.Tmin = (100, 'K')
        self.sectionResultsSettings.Tmax = (380, 'K')

    def __init__(self):
        self.blockGeom.diameter = (60.0, 'mm')
        self.blockGeom.length = (1.0, 'm')
        self.blockProps.divisionStep = (0.1, 'm')
        self.blockProps.material = 'Aluminium6061'

        self.primaryChannelsGeom.number = 4
        self.primaryChannelsGeom.radialPosition = (10, 'mm')
        self.primaryChannelsGeom.startingAngle = (0, 'deg')
        self.primaryChannelsGeom.meshFineness = 3
        self.primaryChannelsGeom.channelName = "PrimaryChannel"

        self.primaryChannelsGeom.externalDiameter = (10, 'mm')
        self.primaryChannelsGeom.sections[0] = (0.000, 0.2)
        self.primaryChannelsGeom.sections[1] = (0.002, 0.2)
        self.primaryChannelsGeom.sections[2] = (0.004, 0.2)
        self.primaryChannelsGeom.sections[3] = (0.006, 0.2)
        self.primaryChannelsGeom.sections[4] = (0.008, 0.2)

        self.secondaryChannelsGeom.number = 6
        self.secondaryChannelsGeom.radialPosition = (22.5, 'mm')
        self.secondaryChannelsGeom.startingAngle = (60, 'deg')
        self.secondaryChannelsGeom.meshFineness = 3
        self.secondaryChannelsGeom.channelName = "SecondaryChannel"

        self.secondaryChannelsGeom.externalDiameter = (7, 'mm')
        self.secondaryChannelsGeom.sections[0] = (0.002, 0.2)
        self.secondaryChannelsGeom.sections[1] = (0.003, 0.2)
        self.secondaryChannelsGeom.sections[2] = (0.004, 0.2)
        self.secondaryChannelsGeom.sections[3] = (0.005, 0.2)
        self.secondaryChannelsGeom.sections[4] = (0.006, 0.2)

        self.primaryFlowIn.fluidName = 'Ammonia'
        self.primaryFlowIn.flowRateChoice = 'm'
        self.primaryFlowIn.mDot = (50, 'kg/h')
        self.primaryFlowIn.T = (400, 'K')
        self.primaryFlowIn.p = (20, 'bar')

        self.secondaryFlowIn.fluidName = 'Ammonia'
        self.secondaryFlowIn.flowRateChoice = 'm'
        self.secondaryFlowIn.mDot = (50, 'kg/h')
        self.secondaryFlowIn.T = (400, 'K')
        self.secondaryFlowIn.p = (20, 'bar')

        self.externalFlowIn.solName = 'MPG'
        self.externalFlowIn.solMassFraction = (50, '%')
        self.externalFlowIn.flowRateChoice = 'V'
        self.externalFlowIn.VDot = (0.5, 'm**3/h')
        self.externalFlowIn.T = (20, 'degC')
        self.externalFlowIn.p = (1, 'bar')

        self.externalChannelGeom.widthAxial = (40, 'mm')
        self.externalChannelGeom.heightRadial = (10, 'mm')
        self.externalChannelGeom.coilPitch = (43, 'mm')
        self.externalChannelGeom.meshFineness = 3

        self.sectionResultsSettings.setTRange = False
        self.sectionResultsSettings.Tmin = (200, 'K')
        self.sectionResultsSettings.Tmax = (350, 'K')

    def computeAsync(self):
        # PreComputation
        self.externalChannelGeom.compute(self.blockGeom.diameter)
        self.primaryChannelsGeom.compute()
        self.secondaryChannelsGeom.compute()

        self.primaryFlowIn.compute()
        self.secondaryFlowIn.compute()
        self.externalFlowIn.compute()

        # Validation
        self.validateInputs()

        # Create the mesh
        mesher = HeatExchangerMesher()
        mesher.create(self)

        # Create channel calculator objects
        solver = HeatExchangerSolver(self, mesher)
        solver.createChannelCalculators(self)

        # Produce geometry/mesh drawings
        self.drawGeometry(mesher, solver)

        solver.solve(self)

        # Produce results
        self.postProcess(mesher, solver)

    def drawGeometry(self, mesher, solver):
        # Draw the mesh
        vertexCoords = mesher.mesh.vertexCoords
        vertexIDs = mesher.mesh._orderedCellVertexIDs
        triPlotMesh = tri.Triangulation(vertexCoords[0], vertexCoords[1],
                                        np.transpose(vertexIDs))
        self.meshView.triplot(triPlotMesh)
        self.meshView.set_aspect('equal')
        self.meshView.set_title('%d elements' %
                                len(mesher.mesh.cellCenters[0]))

        # Draw the channels profiles
        ticks = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x * 1e3))

        solver.primChannelCalc.plotGeometry(self.primaryChannelProfileView)
        self.primaryChannelProfileView.set_xlabel('[m]')
        self.primaryChannelProfileView.set_ylabel('[mm]')
        self.primaryChannelProfileView.yaxis.set_major_formatter(ticks)

        solver.secChannelCalc.plotGeometry(self.secondaryChannelProfileView)
        self.secondaryChannelProfileView.set_xlabel('[m]')
        self.secondaryChannelProfileView.set_ylabel('[mm]')
        self.secondaryChannelProfileView.yaxis.set_major_formatter(ticks)

        #Draw the cross-section profile
        crossSectionProfile = HeatExchangerCrossSectionProfile()
        crossSectionProfile.addBlock(self.blockGeom)
        crossSectionProfile.addChannels(self.primaryChannelsGeom)
        crossSectionProfile.addChannels(self.secondaryChannelsGeom)
        crossSectionProfile.plotGeometry(self.crossSectionProfileView)

        self.crossSectionProfileView.set_xlabel('[mm]')
        self.crossSectionProfileView.set_ylabel('[mm]')
        self.crossSectionProfileView.xaxis.set_major_formatter(ticks)
        self.crossSectionProfileView.yaxis.set_major_formatter(ticks)

        #Draw the longitudinal profile
        longitudinalProfile = HeatExchangerLongitudinalProfile()
        longitudinalProfile.addBlock(self.blockGeom)
        longitudinalProfile.addExternalChannel(self.externalChannelGeom)
        longitudinalProfile.plotGeometry(self.longitudinalProfileView)

        self.longitudinalProfileView.set_xlabel('[mm]')
        self.longitudinalProfileView.set_ylabel('[mm]')
        self.longitudinalProfileView.xaxis.set_major_formatter(ticks)
        self.longitudinalProfileView.yaxis.set_major_formatter(ticks)

    def postProcess(self, mesher, solver):
        # Get the value for the outlet conditions
        self.primaryFlowOut.compute(fState=solver.primChannelStateOut,
                                    mDot=self.primaryFlowIn.mDot)
        self.secondaryFlowOut.compute(fState=solver.secChannelStateOut,
                                      mDot=self.secondaryFlowIn.mDot)
        self.externalFlowOut.compute(fState=solver.extChannelStateOut,
                                     mDot=self.externalFlowIn.mDot)

        self.QDotChannels.QDotPrimaryChannels = self.primaryFlowIn.mDot * \
         abs(self.primaryFlowOut.fState.h - self.primaryFlowIn.fState.h)
        self.QDotChannels.QDotSecondaryChannels = self.secondaryFlowIn.mDot * \
         abs(self.secondaryFlowOut.fState.h - self.secondaryFlowIn.fState.h)
        self.QDotChannels.QDotExternalChannel = self.externalFlowIn.mDot * \
         abs(self.externalFlowOut.fState.h - self.externalFlowIn.fState.h)
        # Fill the table with values
        self.resultTable.resize(solver.numSectionSteps)
        self.resultTPlot.resize(solver.numSectionSteps)
        self.resultQPlot.resize(solver.numSectionSteps)

        for i in range(solver.numSectionSteps):
            self.resultTable[i] = (
                solver.primChannelCalc.sections[i].xStart,
                solver.primChannelCalc.sections[i].xEnd,
                solver.primChannelCalc.sections[i].fState.T,
                solver.primChannelCalc.sections[i].TWall,
                solver.primChannelCalc.sections[i].Re,
                solver.primChannelCalc.sections[i].hConv,
                abs(solver.primChannelCalc.sections[i].QDotWall),
                solver.secChannelCalc.sections[i].fState.T,
                solver.secChannelCalc.sections[i].TWall,
                solver.secChannelCalc.sections[i].Re,
                solver.secChannelCalc.sections[i].hConv,
                abs(solver.secChannelCalc.sections[i].QDotWall),
                solver.extChannelCalc.sections[i].fState.T,
                solver.extChannelCalc.sections[i].TWall,
                solver.extChannelCalc.sections[i].Re,
                solver.extChannelCalc.sections[i].hConv,
                abs(solver.extChannelCalc.sections[i].QDotWall),
            )

            self.resultTPlot[i] = (
                (solver.primChannelCalc.sections[i].xStart +
                 solver.primChannelCalc.sections[i].xEnd) / 2,
                solver.primChannelCalc.sections[i].fState.T,
                solver.primChannelCalc.sections[i].TWall,
                solver.secChannelCalc.sections[i].fState.T,
                solver.secChannelCalc.sections[i].TWall,
                solver.extChannelCalc.sections[i].fState.T,
                solver.extChannelCalc.sections[i].TWall,
            )

            self.resultQPlot[i] = (
                (solver.primChannelCalc.sections[i].xStart +
                 solver.primChannelCalc.sections[i].xEnd) / 2,
                abs(solver.primChannelCalc.sections[i].QDotWall),
                abs(solver.secChannelCalc.sections[i].QDotWall),
                abs(solver.extChannelCalc.sections[i].QDotWall),
            )

    def validateInputs(self):
        self.validateChannels(self.primaryChannelsGeom, "primary")
        self.validateChannels(self.secondaryChannelsGeom, "secondary")

        if self.externalChannelGeom.widthAxial > self.externalChannelGeom.coilPitch:
            raise ValueError(
                'The coil pitch of the external channel is less than the axial width.'
            )

    def validateChannels(self, channelsGeom, channelsName):
        if self.blockGeom.diameter <= channelsGeom.externalDiameter:
            raise ValueError(
                'The block diameter is less than the external diameter of the {0} channels.'
                .format(channelsName))

        if self.blockGeom.diameter / 2. <= (
                channelsGeom.radialPosition +
                channelsGeom.externalDiameter / 2.):
            raise ValueError(
                'The radial position of the {0} channels is too big (the channels are outside of the block).'
                .format(channelsName))

        if self.blockGeom.length != channelsGeom.length:
            raise ValueError(
                'The length of the block is different from the length of the {0} channels.'
                .format(channelsName))

        i = 0
        for section in channelsGeom.sections:
            if (section['length'] < self.blockProps.divisionStep):
                raise ValueError(
                    'The axial division step of the block is greater than the {0}-th section of the {1} channels'
                    .format(i, channelsName))

            if self.isDividedExactly(section['length'],
                                     self.blockProps.divisionStep) == False:
                raise ValueError(
                    'The axial division step of the block does not divide the {0}-th section of the {1} channels in equal parts.'
                    .format(i, channelsName))
            i += 1

    def isDividedExactly(self, a, b):
        bigE = 1e6
        return int(a * bigE) % int(b * bigE) == 0
Exemplo n.º 21
0
class CH4Bioreactor(NumericalModel):
    # Stoichiometric parameter values
    Y_ac = F.Quantity(default=0.0,
                      minValue=0.0,
                      label='Y<sub>ac</sub>',
                      description='yield of acetate degraders on acetate')

    stoichiometricParametersFG = F.FieldGroup(
        [
            Y_ac,
        ], label='Stoichiometric parameters (R-CH4)')

    # Biochemical parameter values
    k_m_ac = F.Quantity(
        'Bio_TimeRate',
        default=(0.0, '1/day'),
        minValue=(0, '1/day'),
        label='k<sub>m,ac</sub>',
        description='specific Monod maximum uptake rate of acetate degraders')
    K_S_ac = F.Quantity(
        'Bio_MassConcentration',
        default=(0.0, 'g/L'),
        minValue=(0, 'g/L'),
        label='K<sub>S,ac</sub>',
        description='Monod half saturation constant of acetate degraders')

    biochemicalParametersFG = F.FieldGroup(
        [
            k_m_ac,
            K_S_ac,
        ], label='Biochemical parameters (R-CH4)')

    # Physiochemical parameters
    Y_ch4_ac = F.Quantity(
        default=0.0,
        minValue=0.0,
        label='Y<sub>ch4,ac</sub>',
        description='yield coefficient of methane on acetate')

    physiochemicalParametersFG = F.FieldGroup(
        [Y_ch4_ac], label='Physiochemical parameters (R-CH4)')

    # Physical parameters
    V_liq_RCH4_del_V_liq_RH2 = F.Quantity(
        default=(0.0, '-'),
        label='V<sub>liq,RCH4</sub>/V<sub>liq,RH2</sub>',
        description=
        'fraction between the volume of the liquid part of the H2 and CH4 bioreactors'
    )

    physicalParametersFG = F.FieldGroup([V_liq_RCH4_del_V_liq_RH2],
                                        label='Physical parameters (R-CH4)')

    # Input concentrations of components
    X_ac_in = F.Quantity(
        'Bio_MassConcentration',
        default=(0.0, 'g/L'),
        minValue=(0, 'g/L'),
        label='X<sub>ac</sub><sup> (in)</sup>',
        description='input concentration of acetate degraders')

    inputConcentrationsFG = F.FieldGroup([
        X_ac_in,
    ],
                                         label='Input concentrations (R-CH4)')

    # Initial concentrations of components
    S_ac_0 = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='S<sub>ac</sub><sup> (0)</sup>',
                        description='initial concentration of acetate')

    X_ac_0 = F.Quantity(
        'Bio_MassConcentration',
        default=(0.0, 'g/L'),
        minValue=(0, 'g/L'),
        label='X<sub>ac</sub><sup> (0)</sup>',
        description='initial concentration of acetate degraders')

    initialConcentrationsFG = F.FieldGroup(
        [
            S_ac_0,
            X_ac_0,
        ], label='Initial concentrations (R-CH4)')

    #1.2 Super groups - parameters & concentrations
    parametersSG = F.SuperGroup([
        stoichiometricParametersFG,
        biochemicalParametersFG,
        physiochemicalParametersFG,
        physicalParametersFG,
    ],
                                label="Parameters (R-CH4)")

    concentrationsSG = F.SuperGroup([
        initialConcentrationsFG,
        inputConcentrationsFG,
    ],
                                    label="Concentrations (R-CH4)")

    modelBlocks = []
Exemplo n.º 22
0
class BiochemicalReactions(NumericalModel):
    label = "Biochemical reactions"
    description = F.ModelDescription(
        "Solver for elementary biochemical reactions", show=True)
    figure = F.ModelFigure(
        src="BioReactors/img/ModuleImages/BiochemicalReactions.png",
        show=False)

    async = True
    progressOptions = {'suffix': 's', 'fractionOutput': True}

    #1. ############ Inputs ###############
    #1.1 Fields - Input values
    reactions = F.RecordArray(
        (
            ('reactionEquation',
             F.String('E + S <-> ES', label='Equation', inputBoxWidth=160)),
            ('rateConstnats',
             F.String('0.0, 0.0', label='Rate constants', inputBoxWidth=100)),
            ('reactionName',
             F.String('enzyme binding to a substrate',
                      label='Name',
                      inputBoxWidth=400,
                      showTooltip=True)),
        ),
        toggle=False,
        label='Reactions',
        numRows=2,
        description='Biochemical reactions',
    )
    reactionsFG = F.FieldGroup([reactions],
                               hideContainer=True,
                               label="Reactions")
    reactionsSG = F.SuperGroup([reactionsFG], label="Reactions")

    species = F.RecordArray(
        (
            ('speciesVariable',
             F.String('E', label='Variable', inputBoxWidth=70)),
            ('initialValue',
             F.Quantity('Bio_MolarConcentration',
                        default=(1, 'M'),
                        minValue=(0, 'M'),
                        label='Initial value',
                        inputBoxWidth=75)),
            ('speciesName', F.String('enzyme', label='Name',
                                     inputBoxWidth=270)),
        ),
        toggle=False,
        label='species',
        numRows=4,
        description='Species of the reactions',
    )
    speciesFG = F.FieldGroup([species], hideContainer=True, label="Species")
    speciesSG = F.SuperGroup([speciesFG], label="Species")

    #1.2 Fields - Settings
    tFinal = F.Quantity('Time',
                        default=(0.0, 's'),
                        minValue=(0, 's'),
                        maxValue=(1000, 's'),
                        label='simulation time')
    tPrint = F.Quantity('Time',
                        default=(0.0, 's'),
                        minValue=(1e-3, 's'),
                        maxValue=(100, 's'),
                        label='print interval')
    solverFG = F.FieldGroup([tFinal, tPrint], label='Solver')

    settingsSG = F.SuperGroup([solverFG], label='Settings')

    #1.4 Model view
    exampleAction = A.ServerAction(
        "loadEg",
        label="Examples",
        options=(
            ('exampleMMK', 'Michaelis-Menten kinetics'),
            ('exampleMMKI', 'Michaelis-Menten kinetics with inhibition'),
        ))

    inputView = F.ModelView(
        ioType="input",
        superGroups=[reactionsSG, speciesSG, settingsSG],
        autoFetch=True,
        actionBar=A.ActionBar([exampleAction]),
    )

    #2. ############ Results ###############
    storage = F.HdfStorage(hdfFile=DM.dataStorageFilePath,
                           hdfGroup=DM.dataStorageDatasetPath)

    dataSeries = (
        ('time', F.Quantity('Time', default=(1, 's'))),
        ('E', F.Quantity('Bio_MolarConcentration', default=(1, 'M'))),
    )

    plot = F.PlotView(dataSeries,
                      label='Plot',
                      useHdfStorage=True,
                      storage='storage')

    table = F.TableView(
        dataSeries,
        label='Table',
        options={'formats': ['0.000', '0.000', '0.000', '0.000']},
        useHdfStorage=True,
        storage='storage')

    storageVG = F.ViewGroup([storage], show="false")
    resultsVG = F.ViewGroup([plot, table], label='Results')
    resultsSG = F.SuperGroup([resultsVG, storageVG], label='Results')

    # 2.2 ODEs plot
    odesPlot = F.MPLPlot(label='ODEs')
    odesVG = F.ViewGroup([odesPlot], label='Ordinary differential equations')
    odesSG = F.SuperGroup([odesVG], label='ODEs')

    # 2.3 Results plot
    chartPlot = F.MPLPlot(label='Chart')
    chartPlotVG = F.ViewGroup([chartPlot], label='Chart')
    chartPlotSG = F.SuperGroup([chartPlotVG], label='Chart')

    #2.1 Model view
    resultView = F.ModelView(ioType="output",
                             superGroups=[resultsSG, odesSG, chartPlotSG],
                             keepDefaultDefs=True)

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    def __init__(self):
        self.exampleMMK()

    def exampleMMK(self):
        self.species[0] = ('E', 4.0, 'enzyme')
        self.species[1] = ('S', 8.0, 'substrate')
        self.species[2] = ('ES', 0.0, 'complex')
        self.species[3] = ('P', 0.0, 'product')

        self.reactions[0] = (
            'E + S <=> ES', '2.0, 1.0',
            'an enzyme binding to a substrate form an enzyme-substrate complex (reversible process)'
        )
        self.reactions[1] = (
            'ES -> E + P', '1.5',
            'an enzyme-substrate complex decomposition to a product and the enzyme'
        )

        self.tFinal = 20.0
        self.tPrint = 0.01

    def exampleMMKI(self):
        self.species.resize(6)
        self.species[0] = ('E', 4.0, 'enzyme')
        self.species[1] = ('S', 8.0, 'substrate')
        self.species[2] = ('ES', 0.0, 'enzyme-substrate complex')
        self.species[3] = ('P', 0.0, 'product')
        self.species[4] = ('I', 5.0, 'inhibitor')
        self.species[5] = ('EI', 0.0, 'inactive enzyme-inhibitor complex')

        self.reactions.resize(3)
        self.reactions[0] = (
            'E + S <=> ES', '2.0, 1.0',
            'an enzyme binding to a substrate form an enzyme-substrate complex (reversible process)'
        )
        self.reactions[1] = (
            'ES -> E + P', '1.5',
            'an enzyme-substrate complex decomposition to a product and an enzyme'
        )
        self.reactions[2] = (
            'E + I <=> EI', '2.0, 0.5',
            'an inhibitor binding to the active site of an enzyme form an inactive enzyme-inhibitor complex (reversible processes)'
        )

        self.tFinal = 20.0
        self.tPrint = 0.01

    def computeAsync(self):
        # Redefine some fields
        self.redefineFileds()

        # Create the model
        model = DM.BiochemicalReactions(self)

        # Tun simulation
        model.prepareSimulation()
        model.run(self)

        # Show results
        self.storage = model.resultStorage.simulationName

        # Plot results
        model.plotODEsTxt(self.odesPlot)
        model.plotHDFResults(self.chartPlot)

    def redefineFileds(self):
        # Create tuples for species
        speciesTuples = (('time', F.Quantity('Time', default=(1, 's'))), )
        datasetColumns = ['t']
        for itSpecies in self.species:
            X = itSpecies[0]  #species variable
            speciesTuple = (('%s' % X,
                             F.Quantity('Bio_MolarConcentration',
                                        default=(1, 'M'))), )
            speciesTuples += speciesTuple
            datasetColumns.append('%s' % X)

        # Redefine Fields
        redefinedStorage = F.HdfStorage(
            hdfFile='BioReactors_SimulationResults.h5',
            hdfGroup='/BiochemicalReactions',
            datasetColumns=datasetColumns)
        self.redefineField('storage', 'storageVG', redefinedStorage)

        redefinedPlot = F.PlotView(speciesTuples,
                                   label='Plot',
                                   options={
                                       'ylabel': 'concentration',
                                       'title': ''
                                   },
                                   useHdfStorage=True,
                                   storage='storage')
        self.redefineField('plot', 'resultsVG', redefinedPlot)

        redefinedTable = F.TableView(
            speciesTuples,
            label='Table',
            options={'formats': ['0.000', '0.000', '0.000', '0.000']},
            useHdfStorage=True,
            storage='storage')
        self.redefineField('table', 'resultsVG', redefinedTable)
Exemplo n.º 23
0
class RankineCycle(HeatEngineCycle):
	label = "Rankine cycle"
	figure = F.ModelFigure(src="ThermoFluids/img/ModuleImages/RankineCycle.png",  height = 300)
	description = F.ModelDescription("Basic Rankine cycle used in power generation", show = True)
	
	#================ Inputs ================#
	#---------------- Fields ----------------#
	# FieldGroup
	pump = F.SubModelGroup(TC.Compressor, 'FG', label  = 'Pump')
	boiler = F.SubModelGroup(TC.Evaporator, 'FG', label = 'Boiler')
	turbine = F.SubModelGroup(TC.Turbine, 'FG', label = 'Turbine')
	condenser = F.SubModelGroup(TC.Condenser, 'FG', label = 'Condenser')
	inputs = F.SuperGroup(['workingFluidGroup', pump, boiler, turbine, condenser], label = 'Cycle definition')	
	#---------------- Actions ----------------#
	exampleAction = ServerAction("loadEg", label = "Examples", options = (
			('SteamPlant', 'Typical steam power plant'),
			('ORC1', 'Geothermal Organic Rankine Cycle with R134a'),
	))
	#--------------- Model view ---------------#
	inputView = F.ModelView(ioType = "input", superGroups = [inputs, 'cycleDiagram', 'solver'], 
		actionBar = ActionBar([exampleAction]), autoFetch = True)
	#================ Results ================#
	#---------------- Energy flows -----------#
	pumpPower = F.Quantity('Power', default = (1, 'kW'), label = 'pump power')
	boilerHeat = F.Quantity('HeatFlowRate', default = (1, 'kW'), label = 'boiler heat in')
	turbinePower = F.Quantity('HeatFlowRate', default = (1, 'kW'), label = 'turbine power')
	condenserHeat = F.Quantity('HeatFlowRate', default = (1, 'kW'), label = 'condenser heat out')
	flowFieldGroup = F.FieldGroup([pumpPower, boilerHeat, turbinePower, condenserHeat], label = 'Energy flows')
	resultEnergy = F.SuperGroup([flowFieldGroup, 'efficiencyFieldGroup'], label = 'Energy')
	resultView = F.ModelView(ioType = "output", superGroups = ['resultDiagrams', 'resultStates', resultEnergy, 'solverStats'])

	#============= Page structure =============#
	modelBlocks = [inputView, resultView]

	#================ Methods ================#
	def __init__(self):
		self.SteamPlant()
		
	def compute(self):
		if (self.cycleTranscritical and 
				(self.boiler.computeMethod == 'dT' or self.boiler.computeMethod == 'Q')):
			raise ValueError('In transcritical cycle, boiler super-heating cannot be used as input')
		if (self.cycleSupercritical and 
				(self.condenser.computeMethod == 'dT' or self.condenser.computeMethod == 'Q')):
			raise ValueError('In supercritical cycle condenser sub-cooling cannot be used as input')
		# Connect components to points
		self.initCompute(self.fluidName)
		self.connectPorts(self.condenser.outlet, self.pump.inlet)
		self.connectPorts(self.pump.outlet, self.boiler.inlet)
		self.connectPorts(self.boiler.outlet, self.turbine.inlet)
		self.connectPorts(self.turbine.outlet, self.condenser.inlet)
		# Initial guess
		for fl in self.flows:
			fl.mDot = self.mDot
		self.condenser.outlet.state.update_pq(self.pLow, 0)
		# Cycle iterations
		self.solver.run()
		# Results
		self.postProcess()
		
	def computeCycle(self):
		self.pump.compute(self.pHigh)
		self.boiler.compute()	
		self.turbine.compute(self.pLow)
		self.condenser.compute()
		
	def postProcess(self):
		super(RankineCycle, self).postProcess(self.TAmbient)
		# Flows
		self.pumpPower = self.mDot * self.pump.w 
		self.boilerHeat = self.mDot * self.boiler.qIn
		self.turbinePower = - self.mDot * self.turbine.w
		self.condenserHeat = - self.mDot * self.condenser.qIn 
		# Efficiencies
		self.eta = (self.turbinePower - self.pumpPower) / self.boilerHeat
		self.etaCarnot = 1 - self.condenser.outlet.state.T / self.boiler.outlet.state.T
		self.etaSecondLaw = self.eta / self.etaCarnot
	
	def SteamPlant(self):
		self.fluidName = 'Water'
		self.mDot = 25.
		self.pHighMethod = 'P'
		self.pHigh = (35, 'bar')
		self.pLowMethod = 'P'
		self.pLow = (0.5, 'bar')
		self.boiler.computeMethod = 'T'
		self.boiler.TOutlet = (400, 'degC')
		self.turbine.eta = 0.85
		self.condenser.computeMethod = 'Q'
		self.condenser.qOutlet = 0
	
	def ORC1(self):
		self.fluidName = 'R134a'
		self.mDot = (10, 'kg/min')
		self.pHighMethod = 'T'
		self.TEvaporation = (85, 'degC')
		self.pLowMethod = 'T'
		self.TCondensation = (40, 'degC')
		self.boiler.computeMethod = 'Q'
		self.boiler.qOutlet = 1
		self.turbine.eta = 0.8
		self.condenser.computeMethod = 'Q'
		self.condenser.qOutlet = 0
Exemplo n.º 24
0
class H2Bioreactor(NumericalModel):
    # Stoichiometric parameter values
    f_ch_xc = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='f<sub>ch,xc</sub>',
                         description='yield of carbohydrates on composites')
    f_pr_xc = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='f<sub>pr,xc</sub>',
                         description='yield of proteins on composites')
    f_li_xc = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='f<sub>li,xc</sub>',
                         description='yield of lipids on composites')

    f_su_li = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='f<sub>su,li</sub>',
                         description='yield of sugar on lipids')
    f_fa_li = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='f<sub>fa,li</sub>',
                         description='yield of LCFA on lipids')

    f_ac_su = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='f<sub>ac,su</sub>',
                         description='yield of acetate on sugars')

    f_ac_aa = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='f<sub>ac,aa</sub>',
                         description='yield of acetate on amino acids')

    Y_suaa = F.Quantity(
        default=0.0,
        minValue=0.0,
        label='Y<sub>su-aa</sub>',
        description=
        'yield of sugar and amino acid degraders on sugars and amino acids')
    Y_fa = F.Quantity(default=0.0,
                      minValue=0.0,
                      label='Y<sub>fa</sub>',
                      description='yield of LCFA degraders on LCFA')

    stoichiometricParametersFG = F.FieldGroup(
        [
            f_ch_xc, f_pr_xc, f_li_xc, f_su_li, f_fa_li, f_ac_su, f_ac_aa,
            Y_suaa, Y_fa
        ],
        label='Stoichiometric parameters (R-H2)')

    # Biochemical parameter values
    k_dis = F.Quantity(
        'Bio_TimeRate',
        default=(0.0, '1/day'),
        minValue=(0, '1/day'),
        label='k<sub>dis</sub>',
        description='rate coefficient for disintegration of composites')

    k_hyd_ch = F.Quantity(
        'Bio_TimeRate',
        default=(0.0, '1/day'),
        minValue=(0, '1/day'),
        label='k<sub>hyd,ch</sub>',
        description='rate coefficient for hydrolysis of carbohydrates')
    k_hyd_pr = F.Quantity(
        'Bio_TimeRate',
        default=(0.0, '1/day'),
        minValue=(0, '1/day'),
        label='k<sub>hyd,pr</sub>',
        description='rate coefficient for hydrolysis of proteins')
    k_hyd_li = F.Quantity(
        'Bio_TimeRate',
        default=(0.0, '1/day'),
        minValue=(0, '1/day'),
        label='k<sub>hyd,li</sub>',
        description='rate coefficient for hydrolysis of lipids')

    k_m_suaa = F.Quantity(
        'Bio_TimeRate',
        default=(0.0, '1/day'),
        minValue=(0, '1/day'),
        label='k<sub>m,su-aa</sub>',
        description=
        'specific Monod maximum uptake rate of sugar and amino acids degraders'
    )
    K_S_suaa = F.Quantity(
        'Bio_MassConcentration',
        default=(0.0, 'g/L'),
        minValue=(0, 'g/L'),
        label='K<sub>S,su-aa</sub>',
        description=
        'Monod half saturation constant of sugar and amino acids degraders')

    k_m_fa = F.Quantity(
        'Bio_TimeRate',
        default=(0.0, '1/day'),
        minValue=(0, '1/day'),
        label='k<sub>m,fa</sub>',
        description='specific Monod maximum uptake rate of LCFA degraders')
    K_S_fa = F.Quantity(
        'Bio_MassConcentration',
        default=(0.0, 'g/L'),
        minValue=(0, 'g/L'),
        label='K<sub>S,fa</sub>',
        description='Monod half saturation constant of LCFA degraders')

    biochemicalParametersFG = F.FieldGroup(
        [
            k_dis,
            k_hyd_ch,
            k_hyd_pr,
            k_hyd_li,
            k_m_suaa,
            K_S_suaa,
            k_m_fa,
            K_S_fa,
        ],
        label='Biochemical parameters (R-H2)')

    # Physiochemical parameters
    Y_h2_su = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='Y<sub>h2,su</sub>',
                         description='yield coefficient of hydrogen on sugar')

    Y_h2_aa = F.Quantity(
        default=0.0,
        minValue=0.0,
        label='Y<sub>h2,aa</sub>',
        description='yield coefficient of hydrogen on amino acids')

    Y_h2_fa = F.Quantity(default=0.0,
                         minValue=0.0,
                         label='Y<sub>h2,fa</sub>',
                         description='yield coefficient of hydrogen on LCFA')

    physiochemicalParametersFG = F.FieldGroup(
        [Y_h2_su, Y_h2_aa, Y_h2_fa], label='Physiochemical parameters (R-H2)')

    # Dilution rates
    D_liq_arr = F.RecordArray(
        (
            ('time',
             F.Quantity('Bio_Time',
                        default=(10.0, 'day'),
                        minValue=(0, 'day'),
                        label='Duration')),
            ('D',
             F.Quantity('Bio_TimeRate',
                        default=(1.0, '1/day'),
                        minValue=(0, '1/day'),
                        label='dilution rate')),
        ),
        label='D<sub> liq</sub>',
        description='liquid dilution (or washout) rate',
        numRows=4,
        toggle=True,
    )

    dilutionRatesFG = F.FieldGroup([
        D_liq_arr,
    ],
                                   label='Dilution rates (R-H2)')

    # Input concentrations of components
    S_su_in = F.Quantity('Bio_CODConcentration',
                         default=(0.0, 'gCOD/L'),
                         minValue=(0, 'gCOD/L'),
                         label='S<sub>su</sub><sup> (in)</sup>',
                         description='input concentration of sugars')

    S_aa_in = F.Quantity('Bio_CODConcentration',
                         default=(0.0, 'gCOD/L'),
                         minValue=(0, 'gCOD/L'),
                         label='S<sub>aa</sub><sup> (in)</sup>',
                         description='input concentration of amino acids')

    S_fa_in = F.Quantity(
        'Bio_CODConcentration',
        default=(0.0, 'gCOD/L'),
        minValue=(0, 'gCOD/L'),
        label='S<sub>fa</sub><sup> (in)</sup>',
        description='input concentration of fatty acids (LCFA)')

    S_ac_in = F.Quantity('Bio_CODConcentration',
                         default=(0.0, 'gCOD/L'),
                         minValue=(0, 'gCOD/L'),
                         label='S<sub>ac</sub><sup> (in)</sup>',
                         description='input concentration of acetate')

    X_c_in = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='X<sub>c</sub><sup> (in)</sup>',
                        description='input concentration of composites')

    X_ch_in = F.Quantity('Bio_CODConcentration',
                         default=(0.0, 'gCOD/L'),
                         minValue=(0, 'gCOD/L'),
                         label='X<sub>ch</sub><sup> (in)</sup>',
                         description='input concentration of carbohydrates')

    X_pr_in = F.Quantity('Bio_CODConcentration',
                         default=(0.0, 'gCOD/L'),
                         minValue=(0, 'gCOD/L'),
                         label='X<sub>pr</sub><sup> (in)</sup>',
                         description='input concentration of proteins')

    X_li_in = F.Quantity('Bio_CODConcentration',
                         default=(0.0, 'gCOD/L'),
                         minValue=(0, 'gCOD/L'),
                         label='X<sub>li</sub><sup> (in)</sup>',
                         description='input concentration of lipids')

    X_suaa_in = F.Quantity(
        'Bio_MassConcentration',
        default=(0.0, 'g/L'),
        minValue=(0, 'g/L'),
        label='X<sub>su-aa</sub><sup> (in)</sup>',
        description='input concentration of sugar and amino acids degraders')

    X_fa_in = F.Quantity('Bio_MassConcentration',
                         default=(0.0, 'g/L'),
                         minValue=(0, 'g/L'),
                         label='X<sub>fa</sub><sup> (in)</sup>',
                         description='input concentration of LCFA degraders')

    inputConcentrationsFG = F.FieldGroup([
        S_su_in,
        S_aa_in,
        S_fa_in,
        S_ac_in,
        X_c_in,
        X_ch_in,
        X_pr_in,
        X_li_in,
        X_suaa_in,
        X_fa_in,
    ],
                                         label='Input concentrations (R-H2)')

    # Initial concentrations of components
    S_su_0 = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='S<sub>su</sub><sup> (0)</sup>',
                        description='initial concentration of sugars')

    S_aa_0 = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='S<sub>aa</sub><sup> (0)</sup>',
                        description='initial concentration of amino acids')

    S_fa_0 = F.Quantity(
        'Bio_CODConcentration',
        default=(0.0, 'gCOD/L'),
        minValue=(0, 'gCOD/L'),
        label='S<sub>fa</sub><sup> (0)</sup>',
        description='initial concentration of fatty acids (LCFA)')

    S_ac_0 = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='S<sub>ac</sub><sup> (0)</sup>',
                        description='initial concentration of acetate')

    X_c_0 = F.Quantity('Bio_CODConcentration',
                       default=(0.0, 'gCOD/L'),
                       minValue=(0, 'gCOD/L'),
                       label='X<sub>c</sub><sup> (0)</sup>',
                       description='initial concentration of composites')

    X_ch_0 = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='X<sub>ch</sub><sup> (0)</sup>',
                        description='initial concentration of carbohydrates')

    X_pr_0 = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='X<sub>pr</sub><sup> (0)</sup>',
                        description='initial concentration of proteins')

    X_li_0 = F.Quantity('Bio_CODConcentration',
                        default=(0.0, 'gCOD/L'),
                        minValue=(0, 'gCOD/L'),
                        label='X<sub>li</sub><sup> (0)</sup>',
                        description='initial concentration of lipids')

    X_suaa_0 = F.Quantity(
        'Bio_MassConcentration',
        default=(0.0, 'g/L'),
        minValue=(0, 'g/L'),
        label='X<sub>su-aa</sub><sup> (0)</sup>',
        description='initial concentration of sugar and amino acids degraders')

    X_fa_0 = F.Quantity('Bio_MassConcentration',
                        default=(0.0, 'g/L'),
                        minValue=(0, 'g/L'),
                        label='X<sub>fa</sub><sup> (0)</sup>',
                        description='initial concentration of LCFA degraders')

    initialConcentrationsFG = F.FieldGroup(
        [
            S_su_0,
            S_aa_0,
            S_fa_0,
            S_ac_0,
            X_c_0,
            X_ch_0,
            X_pr_0,
            X_li_0,
            X_suaa_0,
            X_fa_0,
        ],
        label='Initial concentrations (R-H2)')

    #1.2 Super groups - parameters & concentrations
    parametersSG = F.SuperGroup([
        stoichiometricParametersFG,
        biochemicalParametersFG,
        physiochemicalParametersFG,
        dilutionRatesFG,
    ],
                                label="Parameters (R-H2)")

    concentrationsSG = F.SuperGroup([
        initialConcentrationsFG,
        inputConcentrationsFG,
    ],
                                    label="Concentrations (R-H2)")

    modelBlocks = []
Exemplo n.º 25
0
class ChemostatDDE1(NumericalModel):
    label = "DDE Chemostat (Example 1)"
    description = F.ModelDescription(
        "Chemostat model with delay differential equations (DDE) - Example 1",
        show=True)
    figure = F.ModelFigure(
        src="BioReactors/img/ModuleImages/SimpleChemostat.png", show=False)

    #1. ############ Inputs ###############
    #1.1 Fields - Input values
    # Parameters
    k1 = F.Quantity(
        default=10.53,
        minValue=0,
        maxValue=1e6,
        label='k<sub>1</sub>',
        description=
        'yield coefficient related to substrate-1 consumption from bacteria-1')
    k2 = F.Quantity(
        default=28.6,
        minValue=0,
        maxValue=1e6,
        label='k<sub>2</sub>',
        description=
        'yield coefficient related to substrate-2 production from bacteria-1')
    k3 = F.Quantity(
        default=1074.,
        minValue=0,
        maxValue=1e6,
        label='k<sub>3</sub>',
        description=
        'yield coefficient related to substrate-2 consumption from bacteria-2')
    s1_in = F.Quantity('Bio_MassConcentration',
                       default=(7.5, 'g/L'),
                       label='s<sub>1</sub><sup>in</sub>',
                       description='input substrate-1 concentration')
    s2_in = F.Quantity('Bio_MassConcentration',
                       default=(75., 'g/L'),
                       label='s<sub>2</sub><sup>in</sub>',
                       description='input substrate-2 concentration')
    a = F.Quantity(
        'Fraction',
        default=(0.5, '-'),
        label='&#945',
        description=
        'proportion of organisms that are affected by the dilution rate D')
    D = F.Quantity('Bio_TimeRate',
                   default=(0.89, '1/day'),
                   minValue=(0, '1/day'),
                   label='D',
                   description='dilution rate')
    parametersFG = F.FieldGroup([s1_in, s2_in, k1, k2, k3, a, D],
                                label='Parameters')

    # Parameters - specific growth rates
    m1 = F.Quantity('Bio_TimeRate',
                    default=(1.20, '1/day'),
                    minValue=(0, '1/day'),
                    label='m<sub>1</sub>',
                    description='maximum specific growth rate of bacteria-1')
    m2 = F.Quantity('Bio_TimeRate',
                    default=(0.74, '1/day'),
                    minValue=(0, '1/day'),
                    label='m<sub>2</sub>',
                    description='maximum specific growth rate of bacteria-2')
    k_s1 = F.Quantity('Bio_MassConcentration',
                      default=(7.1, 'g/L'),
                      label='k<sub>s1</sub>',
                      description='half saturation constant of bacteria-1')
    k_s2 = F.Quantity('Bio_MassConcentration',
                      default=(9.28, 'g/L'),
                      label='k<sub>s2</sub>',
                      description='half saturation constant of bacteria-2')
    k_I = F.Quantity('Dimensionless',
                     default=(16., '-'),
                     label='k<sub>I</sub>',
                     description='constant in unit: [ sqrt( g/L ) ]')
    parametersMuFG = F.FieldGroup([m1, m2, k_s1, k_s2, k_I],
                                  label='Parameters - specific growth rates')

    # Parameters - time delays
    tau1 = F.Quantity(
        'Bio_Time',
        default=(10.1, 'day'),
        minValue=(0, 'day'),
        label='&#964<sub>1</sub>',
        description=
        'time delay in conversion of the substrate-1 to viable biomass for bacteria-1'
    )
    tau2 = F.Quantity(
        'Bio_Time',
        default=(5.7, 'day'),
        minValue=(0, 'day'),
        label='&#964<sub>2</sub>',
        description=
        'time delay in conversion of the substrate-2 to viable biomass for bacteria-2'
    )
    parametersTauFG = F.FieldGroup([tau1, tau2],
                                   label='Parameters - time delay')

    # historical initial conditions
    s1_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(3., 'g/L'),
        label='s<sub>1</sub><sup>&#91-&#964<sub>1</sub>, 0&#93</sup>',
        description='historical initial condition for substrate-1 concentration'
    )
    x1_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(0.5, 'g/L'),
        label='x<sub>1</sub><sup>&#91-&#964<sub>1</sub>, 0&#93</sup>',
        description='historical initial condition for bacteria-1 concentration'
    )
    s2_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(15., 'g/L'),
        label='s<sub>2</sub><sup>&#91-&#964<sub>2</sub>, 0&#93</sup>',
        description='historical initial condition for substrate-2 concentration'
    )
    x2_hist_vals = F.Quantity(
        'Bio_MassConcentration',
        default=(0.1, 'g/L'),
        label='x<sub>2</sub><sup>&#91-&#964<sub>2</sub>, 0&#93</sup>',
        description='historical initial condition for bacteria-2 concentration'
    )
    parametersHistFG = F.FieldGroup(
        [s1_hist_vals, x1_hist_vals, s2_hist_vals, x2_hist_vals],
        label='Historical initial conditions')

    inputValuesSG = F.SuperGroup(
        [parametersMuFG, parametersFG, parametersTauFG, parametersHistFG],
        label="Input values")

    #1.2 Fields - Settings
    tFinal = F.Quantity('Bio_Time',
                        default=(100, 'day'),
                        minValue=(0, 'day'),
                        maxValue=(1000, 'day'),
                        label='simulation time')
    tPrint = F.Quantity('Bio_Time',
                        default=(0.1, 'day'),
                        minValue=(1e-5, 'day'),
                        maxValue=(100, 'day'),
                        label='print interval')
    absTol = F.Quantity('Bio_Time',
                        default=(1e-12, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-5, 'day'),
                        label='absolute tolerance')
    relTol = F.Quantity('Bio_Time',
                        default=(1e-12, 'day'),
                        minValue=(1e-16, 'day'),
                        maxValue=(1e-3, 'day'),
                        label='relative tolerance')
    solverFG = F.FieldGroup([tFinal, tPrint, absTol, relTol], label='Solver')

    settingsSG = F.SuperGroup([solverFG], label='Settings')

    #1.4 Model view
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputValuesSG, settingsSG],
                            autoFetch=True)

    #2. ############ Results ###############
    dataSeries = (
        ('time', F.Quantity('Bio_Time', default=(1, 'day'))),
        ('s1', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
        ('x1', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
        ('s2', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
        ('x2', F.Quantity('Bio_MassConcentration', default=(1, 'g/L'))),
    )

    plot = F.PlotView(
        dataSeries,
        label='Plot',
        options={
            'ylabel': None,
            'title': 'Chemostat (DDE)'
        },
    )
    table = F.TableView(dataSeries,
                        label='Table',
                        options={
                            'title':
                            'Title',
                            'formats':
                            ['0.0000', '0.0000', '0.0000', '0.0000', '0.0000']
                        })

    chartS1S2 = F.MPLPlot(label='Chart (s<sub>1</sub>, s<sub>2</sub>)')
    chartX1X2 = F.MPLPlot(label='Chart (x<sub>1</sub>, x<sub>2</sub>)')
    chartS1X1 = F.MPLPlot(label='Chart (s<sub>1</sub>, x<sub>1</sub>)')
    chartS2X2 = F.MPLPlot(label='Chart (s<sub>2</sub>, x<sub>2</sub>)')

    resultsVG = F.ViewGroup(
        [plot, table, chartS1S2, chartX1X2, chartS1X1, chartS2X2],
        label='Results')
    resultsSG = F.SuperGroup([resultsVG], label="Results")

    # 2.2 Equilibrium point
    s1_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='s<sub>1</sub><sup>*</sup>',
        description='substrate-1 concentration at the equilibrium point')
    x1_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='x<sub>1</sub><sup>*</sup>',
        description='bacteria-1 concentration at the equilibrium point')
    s2_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='s<sub>2</sub><sup>*</sup>',
        description='substrate-2 concentration at the equilibrium point')
    x2_eqpnt = F.Quantity(
        'Bio_MassConcentration',
        default=(0., 'g/L'),
        label='x<sub>2</sub><sup>*</sup>',
        description='bacteria-1 concentration at the equilibrium point')

    equilibriumPointFG = F.FieldGroup([s1_eqpnt, x1_eqpnt, s2_eqpnt, x2_eqpnt],
                                      label='Equilibrium point')
    equilibriumPointSG = F.SuperGroup([equilibriumPointFG],
                                      label='Equilibrium point')

    #2.1 Model view
    resultView = F.ModelView(ioType="output",
                             superGroups=[resultsSG, equilibriumPointSG])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    def __init__(self):
        self.k1 = 10.53
        self.k2 = 28.6
        self.k3 = 1074
        self.s1_in = 7.5
        self.s2_in = 75
        self.a = 0.5
        self.m1 = 1.2
        self.m2 = 0.74
        self.k_s1 = 7.1
        self.k_s2 = 9.28
        self.k_I = 16
        self.D = 0.85
        self.tau1 = 2
        self.tau2 = 7
        self.s1_hist_vals = 2
        self.x1_hist_vals = 0.1
        self.s2_hist_vals = 10
        self.x2_hist_vals = 0.05

    def compute(self):
        chemostatDDE = DM.ChemostatDDE1(self)
        chemostatDDE.run(self)

        res = chemostatDDE.getResults()
        results = np.array(
            [res['t'], res['s1'], res['x1'], res['s2'],
             res['x2']]).transpose()
        self.plot = results
        self.table = results

        chemostatDDE.plotS1S2(self.chartS1S2)
        chemostatDDE.plotX1X2(self.chartX1X2)
        chemostatDDE.plotS1X1(self.chartS1X1)
        chemostatDDE.plotS2X2(self.chartS2X2)

        self.s1_eqpnt = (chemostatDDE.equilibriumPoint[0], 'kg/m**3')
        self.x1_eqpnt = (chemostatDDE.equilibriumPoint[1], 'kg/m**3')
        self.s2_eqpnt = (chemostatDDE.equilibriumPoint[2], 'kg/m**3')
        self.x2_eqpnt = (chemostatDDE.equilibriumPoint[3], 'kg/m**3')
Exemplo n.º 26
0
class ADM1H2CH4Bioreactors(NumericalModel):
    label = "(H2,CH4) Bioreactors"
    description = F.ModelDescription(
        "A model of the process of hydrogen and methane production by anaerobic digestion of organic wastes in a cascade of two continuously stirred bioreactors.",
        show=True)
    figure = F.ModelFigure(
        src="BioReactors/img/ModuleImages/ADM1H2CH4Bioreactors.png", show=True)

    async = True
    progressOptions = {'suffix': 'day', 'fractionOutput': True}

    #1. ############ Inputs ###############
    #1.1 Fields - Input values
    parametersRH2 = F.SubModelGroup(H2Bioreactor,
                                    'parametersSG',
                                    label='Parameters (R-H2)')
    concentrationsRH2 = F.SubModelGroup(H2Bioreactor,
                                        'concentrationsSG',
                                        label='Concentrations (R-H2)')

    parametersRCH4 = F.SubModelGroup(CH4Bioreactor,
                                     'parametersSG',
                                     label='Parameters (R-CH4)')
    concentrationsRCH4 = F.SubModelGroup(CH4Bioreactor,
                                         'concentrationsSG',
                                         label='Concentrations (R-CH4)')

    #1.3 Fields - Settings
    solverSettings = F.SubModelGroup(SolverSettings,
                                     'FG',
                                     label='H2 & CH4 - Bioreactors')
    settingsSG = F.SuperGroup([solverSettings], label='Solver settings')

    #1.4 Model view
    exampleAction = A.ServerAction(
        "loadEg",
        label="Examples",
        options=(
            #('exampleDef', 'Reset to default values'),
            ('exampleADM1', 'Reset to ADM1 values'), ))

    inputView = F.ModelView(
        ioType="input",
        superGroups=[
            parametersRH2, concentrationsRH2, parametersRCH4,
            concentrationsRCH4, settingsSG
        ],
        autoFetch=True,
        actionBar=A.ActionBar([exampleAction]),
    )

    #2. ############ Results ###############
    storage = F.HdfStorage(hdfFile=DM.dataStorageFilePath,
                           hdfGroup=DM.dataStorageDatasetPath)

    varTuples = (
        ('time', F.Quantity('Bio_Time', default=(1, 'day'))),  #0
        ('S_su_RH2', F.Quantity('Bio_CODConcentration',
                                default=(1, 'gCOD/L'))),  #1
        ('S_aa_RH2', F.Quantity('Bio_CODConcentration',
                                default=(1, 'gCOD/L'))),  #2
        ('S_fa_RH2', F.Quantity('Bio_CODConcentration',
                                default=(1, 'gCOD/L'))),  #3
        ('S_ac_RH2', F.Quantity('Bio_CODConcentration',
                                default=(1, 'gCOD/L'))),  #4
        ('X_c_RH2', F.Quantity('Bio_CODConcentration',
                               default=(1, 'gCOD/L'))),  #5
        ('X_ch_RH2', F.Quantity('Bio_CODConcentration',
                                default=(1, 'gCOD/L'))),  #6
        ('X_pr_RH2', F.Quantity('Bio_CODConcentration',
                                default=(1, 'gCOD/L'))),  #7
        ('X_li_RH2', F.Quantity('Bio_CODConcentration',
                                default=(1, 'gCOD/L'))),  #8
        ('X_suaa_RH2', F.Quantity('Bio_MassConcentration',
                                  default=(1, 'g/L'))),  #9
        ('X_fa_RH2', F.Quantity('Bio_MassConcentration',
                                default=(1, 'g/L'))),  #10
        ('intQ_h2_RH2',
         F.Quantity('Bio_CODConcentration', default=(1, 'gCOD/L'))),  #11
        ('S_ac_RCH4', F.Quantity('Bio_CODConcentration',
                                 default=(1, 'gCOD/L'))),  #12   
        ('X_ac_RCH4', F.Quantity('Bio_MassConcentration',
                                 default=(1, 'g/L'))),  #13
        ('intQ_ch4_RCH4',
         F.Quantity('Bio_CODConcentration', default=(1, 'gCOD/L'))),  #14
        ('Q_h2_RH2',
         F.Quantity('Bio_CODConcentrationFlowRate',
                    default=(1, 'gCOD/L/day'))),  #15
        ('Q_ch4_RCH4',
         F.Quantity('Bio_CODConcentrationFlowRate',
                    default=(1, 'gCOD/L/day'))),  #16
        ('D_RH2', F.Quantity('Bio_TimeRate', default=(1, '1/day'))),  #17
        ('D_RCH4', F.Quantity('Bio_TimeRate', default=(1, '1/day'))),  #18
    )

    plot1RH2 = F.PlotView(
        varTuples,
        label='R-H2 (S<sub>su</sub>, S<sub>aa</sub>, S<sub>fa</sub>)',
        options={'ylabel': None},
        visibleColumns=[0, 1, 2, 3],
        useHdfStorage=True,
        storage='storage',
    )

    plot2RH2 = F.PlotView(
        varTuples,
        label='R-H2 (X<sub>ch</sub>, X<sub>pr</sub>, X<sub>li</sub>)',
        options={'ylabel': None},
        visibleColumns=[0, 6, 7, 8],
        useHdfStorage=True,
        storage='storage',
    )

    plot3RH2 = F.PlotView(
        varTuples,
        label='R-H2 (X<sub>su-aa</sub>,X<sub>fa</sub>)',
        options={'ylabel': None},
        visibleColumns=[0, 9, 10],
        useHdfStorage=True,
        storage='storage',
    )

    plot4RH2 = F.PlotView(
        varTuples,
        label='R-H2 (H<sub>2</sub>)',
        options={'ylabel': None},
        visibleColumns=[0, 11, 15],
        useHdfStorage=True,
        storage='storage',
    )

    plot1RCH4 = F.PlotView(
        varTuples,
        label='R-CH4 (S<sub>ac</sub>, X<sub>ac</sub>)',
        options={'ylabel': None},
        visibleColumns=[0, 12, 13],
        useHdfStorage=True,
        storage='storage',
    )

    plot2RCH4 = F.PlotView(
        varTuples,
        label='R-CH4 (CH<sub>4</sub>)',
        options={'ylabel': None},
        visibleColumns=[0, 14, 16],
        useHdfStorage=True,
        storage='storage',
    )

    plotD = F.PlotView(
        varTuples,
        label='(D<sub>RH2</sub>, D<sub>RCH4</sub>)',
        options={'ylabel': None},
        visibleColumns=[0, 17, 18],
        useHdfStorage=True,
        storage='storage',
    )

    table = F.TableView(
        varTuples,
        label='Table',
        options={
            'title': 'Bioreactors',
            'formats': ['0.000']
        },
        useHdfStorage=True,
        storage='storage',
    )

    storageVG = F.ViewGroup([storage], show="false")
    resultsVG = F.ViewGroup([
        plot1RH2, plot2RH2, plot3RH2, plot4RH2, plot1RCH4, plot2RCH4, plotD,
        table
    ])
    resultsSG = F.SuperGroup([resultsVG, storageVG], label='Results')

    #2.1 Model view
    resultView = F.ModelView(ioType="output", superGroups=[resultsSG])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    ############# Methods ###############
    def __init__(self):
        self.exampleADM1()

    def exampleDef(self):
        ############# H2 Bioreactor ###############
        #Stoichiometric parameter values
        self.parametersRH2.f_ch_xc = 0.5  #-
        self.parametersRH2.f_pr_xc = 0.15  #-
        self.parametersRH2.f_li_xc = 0.15  #-

        self.parametersRH2.f_su_li = 0.05  #-
        self.parametersRH2.f_fa_li = 0.9  #-

        self.parametersRH2.f_ac_su = 0.41  #-

        self.parametersRH2.f_ac_aa = 0.4  #-

        self.parametersRH2.Y_suaa = 0.1  #-
        self.parametersRH2.Y_fa = 0.06  #-

        #Biochemical parameter values
        self.parametersRH2.k_dis = (0.5, '1/day')

        self.parametersRH2.k_hyd_ch = (10.0, '1/day')
        self.parametersRH2.k_hyd_pr = (10.0, '1/day')
        self.parametersRH2.k_hyd_li = (10.0, '1/day')

        self.parametersRH2.k_m_suaa = (30.0, '1/day')
        self.parametersRH2.K_S_suaa = (0.5, 'g/L')

        self.parametersRH2.k_m_fa = (6.0, '1/day')
        self.parametersRH2.K_S_fa = (0.4, 'g/L')

        # Physiochemical parameter values
        self.parametersRH2.Y_h2_su = 1.0  #-
        self.parametersRH2.Y_h2_aa = 1.0  #-
        self.parametersRH2.Y_h2_fa = 1.0  #-

        # Volumetric flow rate values
        self.parametersRH2.D_liq_arr[0] = (10.0, 0.0)  #(day, 1/day)
        self.parametersRH2.D_liq_arr[1] = (10.0, 0.1)  #(day, 1/day)
        self.parametersRH2.D_liq_arr[2] = (10.0, 0.05)  #(day, 1/day)
        self.parametersRH2.D_liq_arr[3] = (10.0, 0.15)  #(day, 1/day)

        # Input concentrations
        self.concentrationsRH2.S_su_in = (0.0, 'gCOD/L')
        self.concentrationsRH2.S_aa_in = (0.0, 'gCOD/L')
        self.concentrationsRH2.S_fa_in = (0.0, 'gCOD/L')
        self.concentrationsRH2.S_ac_in = (0.0, 'gCOD/L')
        self.concentrationsRH2.X_c_in = (2.0, 'gCOD/L')
        self.concentrationsRH2.X_ch_in = (0.0, 'gCOD/L')
        self.concentrationsRH2.X_pr_in = (0.0, 'gCOD/L')
        self.concentrationsRH2.X_li_in = (0.0, 'gCOD/L')
        self.concentrationsRH2.X_suaa_in = (0.0, 'g/L')
        self.concentrationsRH2.X_fa_in = (0.0, 'g/L')

        # Initial values of state variables
        self.concentrationsRH2.S_su_0 = (0.012, 'gCOD/L')
        self.concentrationsRH2.S_aa_0 = (0.005, 'gCOD/L')
        self.concentrationsRH2.S_fa_0 = (0.099, 'gCOD/L')
        self.concentrationsRH2.S_ac_0 = (0.20, 'gCOD/L')
        self.concentrationsRH2.X_c_0 = (30.0, 'gCOD/L')
        self.concentrationsRH2.X_ch_0 = (0.028, 'gCOD/L')
        self.concentrationsRH2.X_pr_0 = (0.10, 'gCOD/L')
        self.concentrationsRH2.X_li_0 = (0.03, 'gCOD/L')
        self.concentrationsRH2.X_suaa_0 = (0.42, 'g/L')
        self.concentrationsRH2.X_fa_0 = (0.24, 'g/L')

        ############# CH4 Bioreactor ###############
        #Stoichiometric parameter values
        self.parametersRCH4.Y_ac = 0.5  #-

        #Biochemical parameter values
        self.parametersRCH4.k_m_ac = (8.0, '1/day')
        self.parametersRCH4.K_S_ac = (0.15, 'g/L')

        # Physiochemical parameter values
        self.parametersRCH4.Y_ch4_ac = 1.0  #-

        # Physical parameter values
        self.parametersRCH4.V_liq_RCH4_del_V_liq_RH2 = (50.0, '-')  #L/L

        # Input concentrations
        self.concentrationsRCH4.X_ac_in = (0.0, 'g/L')

        # Initial values of state variables
        self.concentrationsRCH4.S_ac_0 = (0.0, 'gCOD/L')
        self.concentrationsRCH4.X_ac_0 = (2.0, 'g/L')

        ############# Solver settings ###############
        self.solverSettings.tFinal = (50.0, 'day')
        self.solverSettings.tPrint = (0.1, 'day')
        self.solverSettings.absTol = (1e-9, 'day')
        self.solverSettings.relTol = (1e-7, 'day')

    def exampleADM1(self):
        ############# H2 Bioreactor ###############
        #Stoichiometric parameter values
        self.parametersRH2.f_ch_xc = 0.2  #-
        self.parametersRH2.f_pr_xc = 0.2  #-
        self.parametersRH2.f_li_xc = 0.3  #-

        self.parametersRH2.f_su_li = 0.05  #-
        self.parametersRH2.f_fa_li = 0.95  #-

        self.parametersRH2.f_ac_su = 0.41  #-

        self.parametersRH2.f_ac_aa = 0.4  #-

        self.parametersRH2.Y_suaa = 0.1  #-
        self.parametersRH2.Y_fa = 0.06  #-

        #Biochemical parameter values
        self.parametersRH2.k_dis = (0.5, '1/day')

        self.parametersRH2.k_hyd_ch = (10.0, '1/day')
        self.parametersRH2.k_hyd_pr = (10.0, '1/day')
        self.parametersRH2.k_hyd_li = (10.0, '1/day')

        self.parametersRH2.k_m_suaa = (30.0, '1/day')
        self.parametersRH2.K_S_suaa = (0.5, 'g/L')

        self.parametersRH2.k_m_fa = (6.0, '1/day')
        self.parametersRH2.K_S_fa = (0.4, 'g/L')

        # Physiochemical parameter values
        self.parametersRH2.Y_h2_su = 1.0  #-
        self.parametersRH2.Y_h2_aa = 1.0  #-
        self.parametersRH2.Y_h2_fa = 1.0  #-

        # Volumetric flow rate values
        self.parametersRH2.D_liq_arr[0] = (10.0, 0.0)  #(day, 1/day)
        self.parametersRH2.D_liq_arr[1] = (10.0, 0.1)  #(day, 1/day)
        self.parametersRH2.D_liq_arr[2] = (10.0, 0.05)  #(day, 1/day)
        self.parametersRH2.D_liq_arr[3] = (10.0, 0.15)  #(day, 1/day)

        # Input concentrations
        self.concentrationsRH2.S_su_in = (0.01, 'gCOD/L')
        self.concentrationsRH2.S_aa_in = (0.001, 'gCOD/L')
        self.concentrationsRH2.S_fa_in = (0.001, 'gCOD/L')
        self.concentrationsRH2.S_ac_in = (0.001, 'gCOD/L')
        self.concentrationsRH2.X_c_in = (2.0, 'gCOD/L')
        self.concentrationsRH2.X_ch_in = (5.0, 'gCOD/L')
        self.concentrationsRH2.X_pr_in = (20.0, 'gCOD/L')
        self.concentrationsRH2.X_li_in = (5.0, 'gCOD/L')
        self.concentrationsRH2.X_suaa_in = (0.0, 'g/L')
        self.concentrationsRH2.X_fa_in = (0.01, 'g/L')

        # Initial values of state variables
        self.concentrationsRH2.S_su_0 = (0.012, 'gCOD/L')
        self.concentrationsRH2.S_aa_0 = (0.005, 'gCOD/L')
        self.concentrationsRH2.S_fa_0 = (0.099, 'gCOD/L')
        self.concentrationsRH2.S_ac_0 = (0.20, 'gCOD/L')
        self.concentrationsRH2.X_c_0 = (0.31, 'gCOD/L')
        self.concentrationsRH2.X_ch_0 = (0.028, 'gCOD/L')
        self.concentrationsRH2.X_pr_0 = (0.10, 'gCOD/L')
        self.concentrationsRH2.X_li_0 = (0.03, 'gCOD/L')
        self.concentrationsRH2.X_suaa_0 = (0.42, 'g/L')
        self.concentrationsRH2.X_fa_0 = (0.24, 'g/L')

        ############# CH4 Bioreactor ###############
        #Stoichiometric parameter values
        self.parametersRCH4.Y_ac = 0.05  #-

        #Biochemical parameter values
        self.parametersRCH4.k_m_ac = (8.0, '1/day')
        self.parametersRCH4.K_S_ac = (0.15, 'g/L')

        # Physiochemical parameter values
        self.parametersRCH4.Y_ch4_ac = 1.0  #-

        # Physical parameter values
        self.parametersRCH4.V_liq_RCH4_del_V_liq_RH2 = (50.0, '-')  #L/L

        # Input concentrations
        self.concentrationsRCH4.X_ac_in = (0.0, 'g/L')

        # Initial values of state variables
        self.concentrationsRCH4.S_ac_0 = (0.0, 'gCOD/L')
        self.concentrationsRCH4.X_ac_0 = (0.76, 'g/L')

        ############# Solver settings ###############
        self.solverSettings.tFinal = (50.0, 'day')
        self.solverSettings.tPrint = (0.1, 'day')
        self.solverSettings.absTol = (1e-12, 'day')
        self.solverSettings.relTol = (1e-10, 'day')

    def computeAsync(self):
        # Simulate RH2 and RCH4 Bioreactors
        bioreactor = DM.ADM1H2CH4Bioreactors(self, self.parametersRH2,
                                             self.concentrationsRH2,
                                             self.parametersRCH4,
                                             self.concentrationsRCH4)

        bioreactor.prepareSimulation(self.solverSettings)
        bioreactor.run(self.solverSettings)

        # Show results
        self.storage = bioreactor.resultStorage.simulationName
Exemplo n.º 27
0
class ChemostatSimple(NumericalModel):
    label = "Simple Chemostat"
    description = F.ModelDescription(
        "Simple chemostat model with ordinary differential equations (ODE)",
        show=True)
    figure = F.ModelFigure(
        src="BioReactors/img/ModuleImages/SimpleChemostat.png", show=False)

    async = True
    progressOptions = {'suffix': 'day', 'fractionOutput': True}

    #1. ############ Inputs ###############
    #1.1 Fields - Input values
    S_in = F.Quantity('Bio_MassConcentration',
                      default=(5, 'g/L'),
                      minValue=(0, 'g/L'),
                      label='S<sub>in</sub>',
                      description='input substrate concentration')
    X_in = F.Quantity('Bio_MassConcentration',
                      default=(0.0, 'g/L'),
                      minValue=(0, 'g/L'),
                      label='X<sub>in</sub>',
                      description='input microorganisms concentration')
    m = F.Quantity(
        'Bio_TimeRate',
        default=(3, '1/day'),
        minValue=(0, '1/day'),
        label='m',
        description='maximum specific growth rate of the microorganisms')
    K = F.Quantity('Bio_MassConcentration',
                   default=(3.7, 'g/L'),
                   minValue=(0, 'g/L'),
                   label='K',
                   description='half saturation constant')
    gamma = F.Quantity(default=0.6,
                       minValue=0,
                       maxValue=1.0,
                       label='&#947',
                       description='yield coefficient of microorganisms')
    D_vals = F.RecordArray((
        ('time',
         F.Quantity('Bio_Time',
                    default=(20, 'day'),
                    minValue=(0, 'day'),
                    label='Duration')),
        ('D',
         F.Quantity('Bio_TimeRate',
                    default=(1, '1/day'),
                    minValue=(0, '1/day'),
                    label='D')),
    ),
                           label='D',
                           description='dilution (or washout) rate')
    parametersFG = F.FieldGroup([S_in, X_in, m, K, gamma, D_vals],
                                label="Parameters")

    S0 = F.Quantity('Bio_MassConcentration',
                    default=(0, 'g/L'),
                    minValue=0,
                    label='S<sub>0</sub>',
                    description='initial substrate concentration')
    X0 = F.Quantity('Bio_MassConcentration',
                    default=(0.5, 'g/L'),
                    minValue=0,
                    label='X<sub>0</sub>',
                    description='initial microorganisms concentration')
    initialValuesFG = F.FieldGroup([S0, X0], label="Initial values")

    inputValuesSG = F.SuperGroup([parametersFG, initialValuesFG],
                                 label="Input values")

    #1.2 Fields - Settings
    tFinal = F.Quantity('Bio_Time',
                        default=(100, 'day'),
                        minValue=(0, 'day'),
                        maxValue=(1000, 'day'),
                        label='simulation time')
    tPrint = F.Quantity('Bio_Time',
                        default=(0.1, 'day'),
                        minValue=(1e-5, 'day'),
                        maxValue=(100, 'day'),
                        label='print interval')
    solverFG = F.FieldGroup([tFinal, tPrint], label='Solver')

    settingsSG = F.SuperGroup([solverFG], label='Settings')

    #1.4 Model view
    inputView = F.ModelView(ioType="input",
                            superGroups=[inputValuesSG, settingsSG],
                            autoFetch=True)

    #2. ############ Results ###############
    storage = F.HdfStorage(hdfFile=DM.dataStorageFilePath,
                           hdfGroup=DM.dataStorageDatasetPath)

    dataSeries = (('time', F.Quantity('Bio_Time', default=(1, 'day'))),
                  ('S', F.Quantity('Bio_MassConcentration',
                                   default=(1, 'g/L'))),
                  ('X', F.Quantity('Bio_MassConcentration',
                                   default=(1, 'g/L'))),
                  ('D', F.Quantity('Bio_TimeRate', default=(1, '1/day'))))

    plot = F.PlotView(dataSeries,
                      label='Plot',
                      options={'ylabel': None},
                      useHdfStorage=True,
                      storage='storage')

    table = F.TableView(dataSeries,
                        label='Table',
                        options={
                            'title': 'Simple Chemostat',
                            'formats': ['0.000', '0.000', '0.000', '0.000']
                        },
                        useHdfStorage=True,
                        storage='storage')

    resultsVG = F.ViewGroup([plot, table], label='Results')
    storageVG = F.ViewGroup([storage], show="false")
    resultsSG = F.SuperGroup([resultsVG, storageVG])

    #2.1 Model view
    resultView = F.ModelView(ioType="output", superGroups=[resultsSG])

    ############# Page structure ########
    modelBlocks = [inputView, resultView]

    def computeAsync(self):
        # Create the model
        chemostat = DM.ChemostatSimple(self)

        # Run simulation
        chemostat.prepareSimulation()
        chemostat.run(self)

        # Show results
        self.storage = chemostat.resultStorage.simulationName