Example #1
0
    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)
Example #2
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
Example #3
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))
Example #4
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')
Example #5
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')
Example #6
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)
Example #7
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
Example #8
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