示例#1
0
文件: input.py 项目: canh-thu/RMG-Py
def simpleReactor(temperature,
                  pressure,
                  initialMoleFractions,
                  terminationConversion=None,
                  terminationTime=None,
                  sensitivity=None,
                  sensitivityThreshold=1e-3):
    logging.debug('Found SimpleReactor reaction system')

    for value in initialMoleFractions.values():
        if value < 0:
            raise InputError('Initial mole fractions cannot be negative.')

    for spec in initialMoleFractions:
        initialMoleFractions[spec] = float(initialMoleFractions[spec])

    totalInitialMoles = sum(initialMoleFractions.values())
    if totalInitialMoles != 1:
        logging.warning(
            'Initial mole fractions do not sum to one; normalizing.')
        logging.info('')
        logging.info('Original composition:')
        for spec, molfrac in initialMoleFractions.iteritems():
            logging.info("{0} = {1}".format(spec, molfrac))
        for spec in initialMoleFractions:
            initialMoleFractions[spec] /= totalInitialMoles
        logging.info('')
        logging.info('Normalized mole fractions:')
        for spec, molfrac in initialMoleFractions.iteritems():
            logging.info("{0} = {1}".format(spec, molfrac))

    T = Quantity(temperature)
    P = Quantity(pressure)

    termination = []
    if terminationConversion is not None:
        for spec, conv in terminationConversion.iteritems():
            termination.append(TerminationConversion(speciesDict[spec], conv))
    if terminationTime is not None:
        termination.append(TerminationTime(Quantity(terminationTime)))
    if len(termination) == 0:
        raise InputError(
            'No termination conditions specified for reaction system #{0}.'.
            format(len(rmg.reactionSystems) + 2))

    sensitiveSpecies = []
    if sensitivity:
        if isinstance(sensitivity, str): sensitivity = [sensitivity]
        for spec in sensitivity:
            sensitiveSpecies.append(speciesDict[spec])
    system = SimpleReactor(T, P, initialMoleFractions, termination,
                           sensitiveSpecies, sensitivityThreshold)
    rmg.reactionSystems.append(system)
示例#2
0
文件: input.py 项目: thackray/RMG-Py
def simpleReactor(temperature,
                  pressure,
                  initialMoleFractions,
                  terminationConversion=None,
                  terminationTime=None,
                  sensitivity=None,
                  sensitivityThreshold=1e-3):
    logging.debug('Found SimpleReactor reaction system')

    for value in initialMoleFractions.values():
        if value < 0:
            raise InputError('Initial mole fractions cannot be negative.')
    if sum(initialMoleFractions.values()) != 1:
        logging.warning(
            'Initial mole fractions do not sum to one; renormalizing.')
        for spec in initialMoleFractions:
            initialMoleFractions[spec] /= sum(initialMoleFractions.values())

    T = Quantity(temperature)
    P = Quantity(pressure)

    termination = []
    if terminationConversion is not None:
        for spec, conv in terminationConversion.iteritems():
            termination.append(TerminationConversion(speciesDict[spec], conv))
    if terminationTime is not None:
        termination.append(TerminationTime(Quantity(terminationTime)))
    if len(termination) == 0:
        raise InputError(
            'No termination conditions specified for reaction system #{0}.'.
            format(len(rmg.reactionSystems) + 2))

    sensitiveSpecies = []
    if sensitivity:
        for spec in sensitivity:
            sensitiveSpecies.append(speciesDict[spec])
    system = SimpleReactor(T, P, initialMoleFractions, termination,
                           sensitiveSpecies, sensitivityThreshold)
    rmg.reactionSystems.append(system)
示例#3
0
    def saveForm(self, posted, form):
        """
        Save form data into input.py file specified by the path.
        """
        # Clean past history
        self.rmg = RMG()

        # Databases
        #self.rmg.databaseDirectory = settings['database.directory']
        self.rmg.thermoLibraries = []
        if posted.thermo_libraries.all():
            self.rmg.thermoLibraries = [
                item.thermolib.encode()
                for item in posted.thermo_libraries.all()
            ]
        self.rmg.reactionLibraries = []
        self.rmg.seedMechanisms = []
        if posted.reaction_libraries.all():
            for item in posted.reaction_libraries.all():
                if not item.seedmech and not item.edge:
                    self.rmg.reactionLibraries.append(
                        (item.reactionlib.encode(), False))
                elif not item.seedmech:
                    self.rmg.reactionLibraries.append(
                        (item.reactionlib.encode(), True))
                else:
                    self.rmg.seedMechanisms.append(item.reactionlib.encode())
        self.rmg.statmechLibraries = []
        self.rmg.kineticsDepositories = 'default'
        self.rmg.kineticsFamilies = 'default'
        self.rmg.kineticsEstimator = 'rate rules'

        # Species
        self.rmg.initialSpecies = []
        speciesDict = {}
        initialMoleFractions = {}
        self.rmg.reactionModel = CoreEdgeReactionModel()
        for item in posted.reactor_species.all():
            structure = Molecule().fromAdjacencyList(item.adjlist.encode())
            spec, isNew = self.rmg.reactionModel.makeNewSpecies(
                structure,
                label=item.name.encode(),
                reactive=False if item.inert else True)
            self.rmg.initialSpecies.append(spec)
            speciesDict[item.name.encode()] = spec
            initialMoleFractions[spec] = item.molefrac

        # Reactor systems
        self.rmg.reactionSystems = []
        for item in posted.reactor_systems.all():
            T = Quantity(item.temperature, item.temperature_units.encode())
            P = Quantity(item.pressure, item.pressure_units.encode())
            termination = []
            if item.conversion:
                termination.append(
                    TerminationConversion(speciesDict[item.species.encode()],
                                          item.conversion))
            termination.append(
                TerminationTime(
                    Quantity(item.terminationtime, item.time_units.encode())))
            # Sensitivity Analysis
            sensitiveSpecies = []
            if item.sensitivity:
                if isinstance(item.sensitivity.encode(), str):
                    sensitivity = item.sensitivity.encode().split(',')
                for spec in sensitivity:
                    sensitiveSpecies.append(speciesDict[spec.strip()])
            system = SimpleReactor(T, P, initialMoleFractions, termination,
                                   sensitiveSpecies, item.sensitivityThreshold)
            self.rmg.reactionSystems.append(system)

        # Simulator tolerances
        self.rmg.absoluteTolerance = form.cleaned_data['simulator_atol']
        self.rmg.relativeTolerance = form.cleaned_data['simulator_rtol']
        self.rmg.sensitivityAbsoluteTolerance = form.cleaned_data[
            'simulator_sens_atol']
        self.rmg.sensitivityRelativeTolerance = form.cleaned_data[
            'simulator_sens_rtol']
        self.rmg.fluxToleranceKeepInEdge = form.cleaned_data[
            'toleranceKeepInEdge']
        self.rmg.fluxToleranceMoveToCore = form.cleaned_data[
            'toleranceMoveToCore']
        self.rmg.fluxToleranceInterrupt = form.cleaned_data[
            'toleranceInterruptSimulation']
        self.rmg.maximumEdgeSpecies = form.cleaned_data['maximumEdgeSpecies']
        self.rmg.minCoreSizeForPrune = form.cleaned_data['minCoreSizeForPrune']
        self.rmg.minSpeciesExistIterationsForPrune = form.cleaned_data[
            'minSpeciesExistIterationsForPrune']
        self.rmg.filterReactions = form.cleaned_data['filterReactions']

        # Pressure Dependence
        pdep = form.cleaned_data['pdep'].encode()
        if pdep != 'off':
            self.rmg.pressureDependence = PressureDependenceJob(network=None)
            self.rmg.pressureDependence.method = pdep

            # Process interpolation model
            if form.cleaned_data['interpolation'].encode() == 'chebyshev':
                self.rmg.pressureDependence.interpolationModel = (
                    form.cleaned_data['interpolation'].encode(),
                    form.cleaned_data['temp_basis'],
                    form.cleaned_data['p_basis'])
            else:
                self.rmg.pressureDependence.interpolationModel = (
                    form.cleaned_data['interpolation'].encode(), )

            # Temperature and pressure range
            self.rmg.pressureDependence.Tmin = Quantity(
                form.cleaned_data['temp_low'],
                form.cleaned_data['temprange_units'].encode())
            self.rmg.pressureDependence.Tmax = Quantity(
                form.cleaned_data['temp_high'],
                form.cleaned_data['temprange_units'].encode())
            self.rmg.pressureDependence.Tcount = form.cleaned_data[
                'temp_interp']
            self.rmg.pressureDependence.generateTemperatureList()
            self.rmg.pressureDependence.Pmin = Quantity(
                form.cleaned_data['p_low'],
                form.cleaned_data['prange_units'].encode())
            self.rmg.pressureDependence.Pmax = Quantity(
                form.cleaned_data['p_high'],
                form.cleaned_data['prange_units'].encode())
            self.rmg.pressureDependence.Pcount = form.cleaned_data['p_interp']
            self.rmg.pressureDependence.generatePressureList()

            # Process grain size and count
            self.rmg.pressureDependence.grainSize = Quantity(
                form.cleaned_data['maximumGrainSize'],
                form.cleaned_data['grainsize_units'].encode())
            self.rmg.pressureDependence.grainCount = form.cleaned_data[
                'minimumNumberOfGrains']

            self.rmg.pressureDependence.maximumAtoms = form.cleaned_data[
                'maximumAtoms']
        # Additional Options
        self.rmg.units = 'si'
        self.rmg.saveRestartPeriod = Quantity(
            form.cleaned_data['saveRestartPeriod'],
            form.cleaned_data['saveRestartPeriodUnits'].encode(
            )) if form.cleaned_data['saveRestartPeriod'] else None
        self.rmg.generateOutputHTML = form.cleaned_data['generateOutputHTML']
        self.rmg.generatePlots = form.cleaned_data['generatePlots']
        self.rmg.saveSimulationProfiles = form.cleaned_data[
            'saveSimulationProfiles']
        self.rmg.saveEdgeSpecies = form.cleaned_data['saveEdgeSpecies']
        self.rmg.verboseComments = form.cleaned_data['verboseComments']

        # Species Constraints
        speciesConstraints = form.cleaned_data['speciesConstraints']
        if speciesConstraints == 'on':
            allowed = []
            if form.cleaned_data['allowed_inputSpecies']:
                allowed.append('input species')
            if form.cleaned_data['allowed_seedMechanisms']:
                allowed.append('seed mechanisms')
            if form.cleaned_data['allowed_reactionLibraries']:
                allowed.append('reaction libraries')
            self.rmg.speciesConstraints['allowed'] = allowed
            self.rmg.speciesConstraints[
                'maximumCarbonAtoms'] = form.cleaned_data['maximumCarbonAtoms']
            self.rmg.speciesConstraints[
                'maximumOxygenAtoms'] = form.cleaned_data['maximumOxygenAtoms']
            self.rmg.speciesConstraints[
                'maximumNitrogenAtoms'] = form.cleaned_data[
                    'maximumNitrogenAtoms']
            self.rmg.speciesConstraints[
                'maximumSiliconAtoms'] = form.cleaned_data[
                    'maximumSiliconAtoms']
            self.rmg.speciesConstraints[
                'maximumSulfurAtoms'] = form.cleaned_data['maximumSulfurAtoms']
            self.rmg.speciesConstraints[
                'maximumHeavyAtoms'] = form.cleaned_data['maximumHeavyAtoms']
            self.rmg.speciesConstraints[
                'maximumRadicalElectrons'] = form.cleaned_data[
                    'maximumRadicalElectrons']
            self.rmg.speciesConstraints['allowSingletO2'] = form.cleaned_data[
                'allowSingletO2']

        # Quantum Calculations
        quantumCalc = form.cleaned_data['quantumCalc']
        if quantumCalc == 'on':
            from rmgpy.qm.main import QMCalculator
            self.rmg.quantumMechanics = QMCalculator(
                software=form.cleaned_data['software'].encode(),
                method=form.cleaned_data['method'].encode(),
                fileStore=form.cleaned_data['fileStore'].encode(),
                scratchDirectory=form.cleaned_data['scratchDirectory'].encode(
                ),
                onlyCyclics=form.cleaned_data['onlyCyclics'],
                maxRadicalNumber=form.cleaned_data['maxRadicalNumber'],
            )

        # Save the input.py file
        self.rmg.saveInput(self.savepath)
示例#4
0
    def testColliderModel(self):
        """
        Test the solver's ability to simulate a model with collision efficiencies.
        """
        chemFile = os.path.join(os.path.dirname(__file__), 'files',
                                'collider_model', 'chem.inp')
        dictionaryFile = os.path.join(os.path.dirname(__file__), 'files',
                                      'collider_model',
                                      'species_dictionary.txt')
        speciesList, reactionList = loadChemkinFile(chemFile, dictionaryFile)

        smilesDict = {
            'H': '[H]',
            'HO2': '[O]O',
            'O2': '[O][O]',
            'Ar': '[Ar]',
            'N2': 'N#N',
            'CO2': 'O=C=O',
            'CH3': '[CH3]',
            'CH4': 'C'
        }
        speciesDict = {}
        for name, smiles in smilesDict.iteritems():
            mol = Molecule(SMILES=smiles)
            for species in speciesList:
                if species.isIsomorphic(mol):
                    speciesDict[name] = species
                    break

        T = 1000  # K
        P = 10  # Pa
        initialMoleFractions = {
            speciesDict['O2']: 0.5,
            speciesDict['H']: 0.5,
            speciesDict['CO2']: 1.0,
            speciesDict['Ar']: 4.0
        }

        # Initialize the model
        rxnSystem = SimpleReactor(T,
                                  P,
                                  initialMoleFractions=initialMoleFractions,
                                  termination=None)
        rxnSystem.initializeModel(speciesList, reactionList, [], [])

        # Advance to time = 0.1 s
        rxnSystem.advance(0.1)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulatedMoleFracs = rxnSystem.y / numpy.sum(rxnSystem.y)
        expectedMoleFracs = numpy.array([
            0.6666667, 0, 0, 0, 0.1666667, 0, 0.08333333, 0.08333333,
            2.466066000000000E-10, 0, 0, 0, 0, 0
        ])
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i], expectedMoleFracs[i])

        # Advance to time = 5 s
        rxnSystem.advance(5)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulatedMoleFracs = rxnSystem.y / numpy.sum(rxnSystem.y)
        expectedMoleFracs = numpy.array([
            0.6666667, 0, 0, 0, 0.1666667, 0, 0.08333332, 0.08333332,
            1.233033000000000E-08, 0, 0, 0, 0, 0
        ])
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i], expectedMoleFracs[i])

        # Try a new set of conditions

        T = 850  # K
        P = 200  # Pa
        initialMoleFractions = {
            speciesDict['O2']: 0.5,
            speciesDict['H']: 1,
            speciesDict['CO2']: 1,
            speciesDict['N2']: 4,
            speciesDict['CH3']: 1
        }

        # Initialize the model
        rxnSystem = SimpleReactor(T,
                                  P,
                                  initialMoleFractions=initialMoleFractions,
                                  termination=None)
        rxnSystem.initializeModel(speciesList, reactionList, [], [])

        # Advance to time = 5 s
        rxnSystem.advance(5)

        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulatedMoleFracs = rxnSystem.y / numpy.sum(rxnSystem.y)
        expectedMoleFracs = numpy.array([
            0, 0, 0, 0.5487241, 0.137181, 0, 0.1083234, 0.0685777,
            1.280687000000000E-05, 0, 0, 0, 0.1083362, 0.02884481
        ])
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i], expectedMoleFracs[i])
示例#5
0
    def testSolve(self):
        """
        Test the simple batch reactor with a simple kinetic model. Here we
        choose a kinetic model consisting of the hydrogen abstraction reaction
        CH4 + C2H5 <=> CH3 + C2H6.
        """
        CH4 = Species(
            molecule=[Molecule().fromSMILES("C")],
            thermo=ThermoData(
                Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"),
                Cpdata=([8.615, 9.687, 10.963, 12.301, 14.841, 16.976,
                         20.528], "cal/(mol*K)"),
                H298=(-17.714, "kcal/mol"),
                S298=(44.472, "cal/(mol*K)")))
        CH3 = Species(molecule=[Molecule().fromSMILES("[CH3]")],
                      thermo=ThermoData(
                          Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"),
                          Cpdata=([
                              9.397, 10.123, 10.856, 11.571, 12.899, 14.055,
                              16.195
                          ], "cal/(mol*K)"),
                          H298=(9.357, "kcal/mol"),
                          S298=(45.174, "cal/(mol*K)")))
        C2H6 = Species(molecule=[Molecule().fromSMILES("CC")],
                       thermo=ThermoData(
                           Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"),
                           Cpdata=([
                               12.684, 15.506, 18.326, 20.971, 25.500, 29.016,
                               34.595
                           ], "cal/(mol*K)"),
                           H298=(-19.521, "kcal/mol"),
                           S298=(54.799, "cal/(mol*K)")))
        C2H5 = Species(molecule=[Molecule().fromSMILES("C[CH2]")],
                       thermo=ThermoData(
                           Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"),
                           Cpdata=([
                               11.635, 13.744, 16.085, 18.246, 21.885, 24.676,
                               29.107
                           ], "cal/(mol*K)"),
                           H298=(29.496, "kcal/mol"),
                           S298=(56.687, "cal/(mol*K)")))

        rxn1 = Reaction(reactants=[C2H6, CH3],
                        products=[C2H5, CH4],
                        kinetics=Arrhenius(A=(686.375 * 6, 'm^3/(mol*s)'),
                                           n=4.40721,
                                           Ea=(7.82799, 'kcal/mol'),
                                           T0=(298.15, 'K')))

        coreSpecies = [CH4, CH3, C2H6, C2H5]
        edgeSpecies = []
        coreReactions = [rxn1]
        edgeReactions = []

        T = 1000
        P = 1.0e5
        rxnSystem = SimpleReactor(T,
                                  P,
                                  initialMoleFractions={
                                      C2H5: 0.1,
                                      CH3: 0.1,
                                      CH4: 0.4,
                                      C2H6: 0.4
                                  },
                                  termination=[])

        rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies,
                                  edgeReactions)

        tlist = numpy.array([10**(i / 10.0) for i in range(-130, -49)],
                            numpy.float64)

        # Integrate to get the solution at each time point
        t = []
        y = []
        reactionRates = []
        speciesRates = []
        for t1 in tlist:
            rxnSystem.advance(t1)
            t.append(rxnSystem.t)
            # You must make a copy of y because it is overwritten by DASSL at
            # each call to advance()
            y.append(rxnSystem.y.copy())
            reactionRates.append(rxnSystem.coreReactionRates.copy())
            speciesRates.append(rxnSystem.coreSpeciesRates.copy())

        # Convert the solution vectors to numpy arrays
        t = numpy.array(t, numpy.float64)
        y = numpy.array(y, numpy.float64)
        reactionRates = numpy.array(reactionRates, numpy.float64)
        speciesRates = numpy.array(speciesRates, numpy.float64)
        V = constants.R * rxnSystem.T.value_si * numpy.sum(
            y) / rxnSystem.P.value_si

        # Check that we're computing the species fluxes correctly
        for i in range(t.shape[0]):
            self.assertAlmostEqual(reactionRates[i, 0],
                                   speciesRates[i, 0],
                                   delta=1e-6 * reactionRates[i, 0])
            self.assertAlmostEqual(reactionRates[i, 0],
                                   -speciesRates[i, 1],
                                   delta=1e-6 * reactionRates[i, 0])
            self.assertAlmostEqual(reactionRates[i, 0],
                                   -speciesRates[i, 2],
                                   delta=1e-6 * reactionRates[i, 0])
            self.assertAlmostEqual(reactionRates[i, 0],
                                   speciesRates[i, 3],
                                   delta=1e-6 * reactionRates[i, 0])

        # Check that we've reached equilibrium
        self.assertAlmostEqual(reactionRates[-1, 0], 0.0, delta=1e-2)

        #######
        # Unit test for the jacobian function:
        # Solve a reaction system and check if the analytical jacobian matches the finite difference jacobian

        H2 = Species(molecule=[Molecule().fromSMILES("[H][H]")],
                     thermo=ThermoData(
                         Tdata=([300, 400, 500, 600, 800, 1000, 1500], "K"),
                         Cpdata=([6.89, 6.97, 6.99, 7.01, 7.08, 7.22,
                                  7.72], "cal/(mol*K)"),
                         H298=(0, "kcal/mol"),
                         S298=(31.23, "cal/(mol*K)")))

        rxnList = []
        rxnList.append(
            Reaction(reactants=[C2H6],
                     products=[CH3, CH3],
                     kinetics=Arrhenius(A=(686.375 * 6, '1/s'),
                                        n=4.40721,
                                        Ea=(7.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))
        rxnList.append(
            Reaction(reactants=[CH3, CH3],
                     products=[C2H6],
                     kinetics=Arrhenius(A=(686.375 * 6, 'm^3/(mol*s)'),
                                        n=4.40721,
                                        Ea=(7.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))

        rxnList.append(
            Reaction(reactants=[C2H6, CH3],
                     products=[C2H5, CH4],
                     kinetics=Arrhenius(A=(46.375 * 6, 'm^3/(mol*s)'),
                                        n=3.40721,
                                        Ea=(6.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))
        rxnList.append(
            Reaction(reactants=[C2H5, CH4],
                     products=[C2H6, CH3],
                     kinetics=Arrhenius(A=(46.375 * 6, 'm^3/(mol*s)'),
                                        n=3.40721,
                                        Ea=(6.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))

        rxnList.append(
            Reaction(reactants=[C2H5, CH4],
                     products=[CH3, CH3, CH3],
                     kinetics=Arrhenius(A=(246.375 * 6, 'm^3/(mol*s)'),
                                        n=1.40721,
                                        Ea=(3.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))
        rxnList.append(
            Reaction(reactants=[CH3, CH3, CH3],
                     products=[C2H5, CH4],
                     kinetics=Arrhenius(A=(246.375 * 6, 'm^6/(mol^2*s)'),
                                        n=1.40721,
                                        Ea=(3.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))  #

        rxnList.append(
            Reaction(reactants=[C2H6, CH3, CH3],
                     products=[C2H5, C2H5, H2],
                     kinetics=Arrhenius(A=(146.375 * 6, 'm^6/(mol^2*s)'),
                                        n=2.40721,
                                        Ea=(8.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))
        rxnList.append(
            Reaction(reactants=[C2H5, C2H5, H2],
                     products=[C2H6, CH3, CH3],
                     kinetics=Arrhenius(A=(146.375 * 6, 'm^6/(mol^2*s)'),
                                        n=2.40721,
                                        Ea=(8.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))

        rxnList.append(
            Reaction(reactants=[C2H6, C2H6],
                     products=[CH3, CH4, C2H5],
                     kinetics=Arrhenius(A=(1246.375 * 6, 'm^3/(mol*s)'),
                                        n=0.40721,
                                        Ea=(8.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))
        rxnList.append(
            Reaction(reactants=[CH3, CH4, C2H5],
                     products=[C2H6, C2H6],
                     kinetics=Arrhenius(A=(46.375 * 6, 'm^6/(mol^2*s)'),
                                        n=0.10721,
                                        Ea=(8.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))

        for rxn in rxnList:
            coreSpecies = [CH4, CH3, C2H6, C2H5, H2]
            edgeSpecies = []
            coreReactions = [rxn]

            rxnSystem0 = SimpleReactor(T,
                                       P,
                                       initialMoleFractions={
                                           CH4: 0.2,
                                           CH3: 0.1,
                                           C2H6: 0.35,
                                           C2H5: 0.15,
                                           H2: 0.2
                                       },
                                       termination=[])
            rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies,
                                       edgeReactions)
            dydt0 = rxnSystem0.residual(0.0, rxnSystem0.y,
                                        numpy.zeros(rxnSystem0.y.shape))[0]
            numCoreSpecies = len(coreSpecies)
            dN = .000001 * sum(rxnSystem0.y)
            dN_array = dN * numpy.eye(numCoreSpecies)

            dydt = []
            for i in range(numCoreSpecies):
                rxnSystem0.y[i] += dN
                dydt.append(
                    rxnSystem0.residual(0.0, rxnSystem0.y,
                                        numpy.zeros(rxnSystem0.y.shape))[0])
                rxnSystem0.y[i] -= dN  # reset y to original y0

            # Let the solver compute the jacobian
            solverJacobian = rxnSystem0.jacobian(0.0, rxnSystem0.y, dydt0, 0.0)
            # Compute the jacobian using finite differences
            jacobian = numpy.zeros((numCoreSpecies, numCoreSpecies))
            for i in range(numCoreSpecies):
                for j in range(numCoreSpecies):
                    jacobian[i, j] = (dydt[j][i] - dydt0[i]) / dN
                    self.assertAlmostEqual(jacobian[i, j],
                                           solverJacobian[i, j],
                                           delta=abs(1e-4 * jacobian[i, j]))

        #print 'Solver jacobian'
        #print solverJacobian
        #print 'Numerical jacobian'
        #print jacobian

        ###
        # Unit test for the compute rate derivative
        rxnList = []
        rxnList.append(
            Reaction(reactants=[C2H6],
                     products=[CH3, CH3],
                     kinetics=Arrhenius(A=(686.375e6, '1/s'),
                                        n=4.40721,
                                        Ea=(7.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))
        rxnList.append(
            Reaction(reactants=[C2H6, CH3],
                     products=[C2H5, CH4],
                     kinetics=Arrhenius(A=(46.375 * 6, 'm^3/(mol*s)'),
                                        n=3.40721,
                                        Ea=(6.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))
        rxnList.append(
            Reaction(reactants=[C2H6, CH3, CH3],
                     products=[C2H5, C2H5, H2],
                     kinetics=Arrhenius(A=(146.375 * 6, 'm^6/(mol^2*s)'),
                                        n=2.40721,
                                        Ea=(8.82799, 'kcal/mol'),
                                        T0=(298.15, 'K'))))

        coreSpecies = [CH4, CH3, C2H6, C2H5, H2]
        edgeSpecies = []
        coreReactions = rxnList

        rxnSystem0 = SimpleReactor(T,
                                   P,
                                   initialMoleFractions={
                                       CH4: 0.2,
                                       CH3: 0.1,
                                       C2H6: 0.35,
                                       C2H5: 0.15,
                                       H2: 0.2
                                   },
                                   termination=[])
        rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies,
                                   edgeReactions)
        dfdt0 = rxnSystem0.residual(0.0, rxnSystem0.y,
                                    numpy.zeros(rxnSystem0.y.shape))[0]
        solver_dfdk = rxnSystem0.computeRateDerivative()
        #print 'Solver d(dy/dt)/dk'
        #print solver_dfdk

        integrationTime = 1e-8
        rxnSystem0.termination.append(TerminationTime((integrationTime, 's')))
        rxnSystem0.simulate(coreSpecies, coreReactions, [], [], 0, 1, 0)

        y0 = rxnSystem0.y

        dfdk = numpy.zeros((numCoreSpecies, len(rxnList)))  # d(dy/dt)/dk

        for i in range(len(rxnList)):
            k0 = rxnList[i].getRateCoefficient(T, P)
            rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si * (
                1 + 1e-3)
            dk = rxnList[i].getRateCoefficient(T, P) - k0

            rxnSystem = SimpleReactor(T,
                                      P,
                                      initialMoleFractions={
                                          CH4: 0.2,
                                          CH3: 0.1,
                                          C2H6: 0.35,
                                          C2H5: 0.15,
                                          H2: 0.2
                                      },
                                      termination=[])
            rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies,
                                      edgeReactions)

            dfdt = rxnSystem.residual(0.0, rxnSystem.y,
                                      numpy.zeros(rxnSystem.y.shape))[0]
            dfdk[:, i] = (dfdt - dfdt0) / dk

            rxnSystem.termination.append(
                TerminationTime((integrationTime, 's')))
            rxnSystem.simulate(coreSpecies, coreReactions, [], [], 0, 1, 0)

            rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si / (
                1 + 1e-3)  # reset A factor

        for i in range(numCoreSpecies):
            for j in range(len(rxnList)):
                self.assertAlmostEqual(dfdk[i, j],
                                       solver_dfdk[i, j],
                                       delta=abs(1e-3 * dfdk[i, j]))
示例#6
0
    def testSolve(self):
        """
        Test the simple batch reactor with a simple kinetic model. Here we
        choose a kinetic model consisting of the hydrogen abstraction reaction
        CH4 + C2H5 <=> CH3 + C2H6.
        """
        CH4 = Species(
            molecule=[Molecule().fromSMILES("C")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 8.615, 9.687,10.963,12.301,14.841,16.976,20.528],"cal/(mol*K)"), H298=(-17.714,"kcal/mol"), S298=(44.472,"cal/(mol*K)"))
            )
        CH3 = Species(
            molecule=[Molecule().fromSMILES("[CH3]")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 9.397,10.123,10.856,11.571,12.899,14.055,16.195],"cal/(mol*K)"), H298=(  9.357,"kcal/mol"), S298=(45.174,"cal/(mol*K)"))
            )
        C2H6 = Species(
            molecule=[Molecule().fromSMILES("CC")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([12.684,15.506,18.326,20.971,25.500,29.016,34.595],"cal/(mol*K)"), H298=(-19.521,"kcal/mol"), S298=(54.799,"cal/(mol*K)"))
            )
        C2H5 = Species(
            molecule=[Molecule().fromSMILES("C[CH2]")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([11.635,13.744,16.085,18.246,21.885,24.676,29.107],"cal/(mol*K)"), H298=( 29.496,"kcal/mol"), S298=(56.687,"cal/(mol*K)"))
            )
        

        rxn1 = Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(686.375*6,'m^3/(mol*s)'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K')))

        coreSpecies = [CH4,CH3,C2H6,C2H5]
        edgeSpecies = []
        coreReactions = [rxn1]
        edgeReactions = []

        T = 1000; P = 1.0e5
        rxnSystem = SimpleReactor(T, P, initialMoleFractions={C2H5: 0.1, CH3: 0.1, CH4: 0.4, C2H6: 0.4}, termination=[])

        rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions)

        tlist = numpy.array([10**(i/10.0) for i in range(-130, -49)], numpy.float64)

        # Integrate to get the solution at each time point
        t = []; y = []; reactionRates = []; speciesRates = []
        for t1 in tlist:
            rxnSystem.advance(t1)
            t.append(rxnSystem.t)
            # You must make a copy of y because it is overwritten by DASSL at
            # each call to advance()
            y.append(rxnSystem.y.copy())
            reactionRates.append(rxnSystem.coreReactionRates.copy())
            speciesRates.append(rxnSystem.coreSpeciesRates.copy())

        # Convert the solution vectors to numpy arrays
        t = numpy.array(t, numpy.float64)
        y = numpy.array(y, numpy.float64)
        reactionRates = numpy.array(reactionRates, numpy.float64)
        speciesRates = numpy.array(speciesRates, numpy.float64)
        V = constants.R * rxnSystem.T.value_si * numpy.sum(y) / rxnSystem.P.value_si       

        # Check that we're computing the species fluxes correctly
        for i in range(t.shape[0]):
            self.assertAlmostEqual(reactionRates[i,0], speciesRates[i,0], delta=1e-6*reactionRates[i,0])
            self.assertAlmostEqual(reactionRates[i,0], -speciesRates[i,1], delta=1e-6*reactionRates[i,0])
            self.assertAlmostEqual(reactionRates[i,0], -speciesRates[i,2], delta=1e-6*reactionRates[i,0])
            self.assertAlmostEqual(reactionRates[i,0], speciesRates[i,3], delta=1e-6*reactionRates[i,0])
        
        # Check that we've reached equilibrium 
        self.assertAlmostEqual(reactionRates[-1,0], 0.0, delta=1e-2)
        
        #######        
        # Unit test for the jacobian function:
        # Solve a reaction system and check if the analytical jacobian matches the finite difference jacobian
        
        H2 = Species(
            molecule=[Molecule().fromSMILES("[H][H]")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([6.89,6.97,6.99,7.01,7.08,7.22,7.72],"cal/(mol*K)"), H298=( 0,"kcal/mol"), S298=(31.23,"cal/(mol*K)"))
            )
        
        rxnList = []
        rxnList.append(Reaction(reactants=[C2H6], products=[CH3,CH3], kinetics=Arrhenius(A=(686.375*6,'1/s'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K'))))
        rxnList.append(Reaction(reactants=[CH3,CH3], products=[C2H6], kinetics=Arrhenius(A=(686.375*6,'m^3/(mol*s)'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K'))))
        
        rxnList.append(Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(46.375*6,'m^3/(mol*s)'), n=3.40721, Ea=(6.82799,'kcal/mol'), T0=(298.15,'K'))))        
        rxnList.append(Reaction(reactants=[C2H5,CH4], products=[C2H6,CH3], kinetics=Arrhenius(A=(46.375*6,'m^3/(mol*s)'), n=3.40721, Ea=(6.82799,'kcal/mol'), T0=(298.15,'K'))))        
        
        rxnList.append(Reaction(reactants=[C2H5,CH4], products=[CH3,CH3,CH3], kinetics=Arrhenius(A=(246.375*6,'m^3/(mol*s)'), n=1.40721, Ea=(3.82799,'kcal/mol'), T0=(298.15,'K'))))       
        rxnList.append(Reaction(reactants=[CH3,CH3,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(246.375*6,'m^6/(mol^2*s)'), n=1.40721, Ea=(3.82799,'kcal/mol'), T0=(298.15,'K'))))#        
        
        rxnList.append(Reaction(reactants=[C2H6,CH3,CH3], products=[C2H5,C2H5,H2], kinetics=Arrhenius(A=(146.375*6,'m^6/(mol^2*s)'), n=2.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K'))))
        rxnList.append(Reaction(reactants=[C2H5,C2H5,H2], products=[C2H6,CH3,CH3], kinetics=Arrhenius(A=(146.375*6,'m^6/(mol^2*s)'), n=2.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K'))))
        
        rxnList.append(Reaction(reactants=[C2H6,C2H6], products=[CH3,CH4,C2H5], kinetics=Arrhenius(A=(1246.375*6,'m^3/(mol*s)'), n=0.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K'))))
        rxnList.append(Reaction(reactants=[CH3,CH4,C2H5], products=[C2H6,C2H6], kinetics=Arrhenius(A=(46.375*6,'m^6/(mol^2*s)'), n=0.10721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K'))))
        

        for rxn in rxnList:
            coreSpecies = [CH4,CH3,C2H6,C2H5,H2]
            edgeSpecies = []
            coreReactions = [rxn]
            
            rxnSystem0 = SimpleReactor(T,P,initialMoleFractions={CH4:0.2,CH3:0.1,C2H6:0.35,C2H5:0.15, H2:0.2},termination=[])
            rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions)
            dydt0 = rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0]
            numCoreSpecies = len(coreSpecies)
            dN = .000001*sum(rxnSystem0.y)
            dN_array = dN*numpy.eye(numCoreSpecies)
            
            dydt = []
            for i in range(numCoreSpecies):
                rxnSystem0.y[i] += dN 
                dydt.append(rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0])
                rxnSystem0.y[i] -= dN  # reset y to original y0
            
            # Let the solver compute the jacobian       
            solverJacobian = rxnSystem0.jacobian(0.0, rxnSystem0.y, dydt0, 0.0)     
            # Compute the jacobian using finite differences
            jacobian = numpy.zeros((numCoreSpecies, numCoreSpecies))
            for i in range(numCoreSpecies):
                for j in range(numCoreSpecies):
                    jacobian[i,j] = (dydt[j][i]-dydt0[i])/dN
                    self.assertAlmostEqual(jacobian[i,j], solverJacobian[i,j], delta=abs(1e-4*jacobian[i,j]))
        
        #print 'Solver jacobian'
        #print solverJacobian
        #print 'Numerical jacobian'
        #print jacobian
        
        ###
        # Unit test for the compute rate derivative
        rxnList = []
        rxnList.append(Reaction(reactants=[C2H6], products=[CH3,CH3], kinetics=Arrhenius(A=(686.375e6,'1/s'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K')))) 
        rxnList.append(Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(46.375*6,'m^3/(mol*s)'), n=3.40721, Ea=(6.82799,'kcal/mol'), T0=(298.15,'K'))))        
        rxnList.append(Reaction(reactants=[C2H6,CH3,CH3], products=[C2H5,C2H5,H2], kinetics=Arrhenius(A=(146.375*6,'m^6/(mol^2*s)'), n=2.40721, Ea=(8.82799,'kcal/mol'), T0=(298.15,'K'))))
        
        
        coreSpecies = [CH4,CH3,C2H6,C2H5,H2]
        edgeSpecies = []
        coreReactions = rxnList
        
        rxnSystem0 = SimpleReactor(T,P,initialMoleFractions={CH4:0.2,CH3:0.1,C2H6:0.35,C2H5:0.15, H2:0.2},termination=[])
        rxnSystem0.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions)
        dfdt0 = rxnSystem0.residual(0.0, rxnSystem0.y, numpy.zeros(rxnSystem0.y.shape))[0]
        solver_dfdk = rxnSystem0.computeRateDerivative()
        #print 'Solver d(dy/dt)/dk'
        #print solver_dfdk
        
        integrationTime = 1e-8
        rxnSystem0.termination.append(TerminationTime((integrationTime,'s')))
        modelSettings = ModelSettings(toleranceKeepInEdge = 0,toleranceMoveToCore=1,toleranceInterruptSimulation=0)
        simulatorSettings = SimulatorSettings()
        rxnSystem0.simulate(coreSpecies, coreReactions, [], [], [],[], modelSettings = modelSettings, simulatorSettings=simulatorSettings)

        y0 = rxnSystem0.y
        
        dfdk = numpy.zeros((numCoreSpecies,len(rxnList)))   # d(dy/dt)/dk
        
        for i in range(len(rxnList)):
            k0 = rxnList[i].getRateCoefficient(T,P)
            rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si*(1+1e-3)               
            dk = rxnList[i].getRateCoefficient(T,P) - k0

            rxnSystem = SimpleReactor(T,P,initialMoleFractions={CH4:0.2,CH3:0.1,C2H6:0.35,C2H5:0.15, H2:0.2},termination=[])
            rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions)

            dfdt = rxnSystem.residual(0.0, rxnSystem.y, numpy.zeros(rxnSystem.y.shape))[0]  
            dfdk[:,i]=(dfdt-dfdt0)/dk          
            
            
            rxnSystem.termination.append(TerminationTime((integrationTime,'s')))
            modelSettings = ModelSettings(toleranceKeepInEdge=0,toleranceMoveToCore=1,toleranceInterruptSimulation=0)
            simulatorSettings = SimulatorSettings()
            
            rxnSystem.simulate(coreSpecies, coreReactions, [], [], [], [], modelSettings=modelSettings, simulatorSettings=simulatorSettings)
            
            rxnList[i].kinetics.A.value_si = rxnList[i].kinetics.A.value_si/(1+1e-3)  # reset A factor
            
        for i in range(numCoreSpecies):
            for j in range(len(rxnList)):
                self.assertAlmostEqual(dfdk[i,j], solver_dfdk[i,j], delta=abs(1e-3*dfdk[i,j]))
    def testSpecificColliderModel(self):
        """
        Test the solver's ability to simulate a model with specific third body species collision efficiencies.
        """
        chemFile = os.path.join(os.path.dirname(__file__),'files','specific_collider_model','chem.inp')
        dictionaryFile = os.path.join(os.path.dirname(__file__),'files','specific_collider_model','species_dictionary.txt')
        speciesList, reactionList = loadChemkinFile(chemFile, dictionaryFile)

        smilesDict = {'Ar':'[Ar]','N2(1)':'N#N','O2':'[O][O]','H':'[H]','CH3':'[CH3]','CH4':'C'}
        speciesDict = {}
        for name, smiles in smilesDict.iteritems():
            mol = Molecule(SMILES=smiles)
            for species in speciesList:
                if species.isIsomorphic(mol):
                    speciesDict[name] = species
                    break

        T = 1000 # K
        P = 10 # Pa
        initialMoleFractions = {speciesDict['Ar']:2.0,
                        speciesDict['N2(1)']:1.0,
                        speciesDict['O2']:0.5,
                        speciesDict['H']:0.1,
                        speciesDict['CH3']:0.1,
                        speciesDict['CH4']:0.001}

        # Initialize the model
        rxnSystem = SimpleReactor(T,P,initialMoleFractions=initialMoleFractions,termination=None)
        rxnSystem.initializeModel(speciesList, reactionList, [], [])

        # Advance to time = 0.1 s
        rxnSystem.advance(0.1)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulatedMoleFracs = rxnSystem.y/numpy.sum(rxnSystem.y)
        expectedMoleFracs = numpy.array([0.540394532, 0.270197216, 0.135098608, 0.027019722, 0.027019722, 0.000270202]) # order: Ar, N2, O2, H, CH3, CH4
        for i in xrange(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i],expectedMoleFracs[i],6)

        # Advance to time = 5 s
        rxnSystem.advance(5)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        expectedMoleFracs = numpy.array([0.540394573, 0.270197287, 0.135098693, 0.027019519, 0.027019519, 0.00027041]) # order: Ar, N2, O2, H, CH3, CH4
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i],expectedMoleFracs[i],6)

        # Try a new set of conditions
        T = 850 # K
        P = 200 # Pa
        initialMoleFractions = {speciesDict['Ar']:1.0,
                        speciesDict['N2(1)']:0.5,
                        speciesDict['O2']:0.5,
                        speciesDict['H']:0.001,
                        speciesDict['CH3']:0.01,
                        speciesDict['CH4']:0.5}

        # Initialize the model
        rxnSystem = SimpleReactor(T,P,initialMoleFractions=initialMoleFractions,termination=None)
        rxnSystem.initializeModel(speciesList, reactionList, [], [])

        # Advance to time = 5 s
        rxnSystem.advance(5)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulatedMoleFracs = rxnSystem.y/numpy.sum(rxnSystem.y)
        expectedMoleFracs = numpy.array([0.398247713, 0.199123907, 0.199123907, 0.000398169, 0.003982398, 0.199123907]) # order: Ar, N2, O2, H, CH3, CH4
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i],expectedMoleFracs[i],6)
示例#8
0
    def testColliderModel(self):
        """
        Test the solver's ability to simulate a model with collision efficiencies.
        """
        chemFile = os.path.join(os.path.dirname(__file__),'files','collider_model','chem.inp')
        dictionaryFile = os.path.join(os.path.dirname(__file__),'files','collider_model','species_dictionary.txt')
        speciesList, reactionList = loadChemkinFile(chemFile, dictionaryFile)

        
        smilesDict = {'H':'[H]','HO2':'[O]O','O2':'[O][O]','Ar':'[Ar]','N2':'N#N','CO2':'O=C=O','CH3':'[CH3]','CH4':'C'}
        speciesDict = {}
        for name, smiles in smilesDict.iteritems():
            mol = Molecule(SMILES=smiles)
            for species in speciesList:
                if species.isIsomorphic(mol):
                    speciesDict[name] = species
                    break
                
                
        T = 1000 # K
        P = 10 # Pa            
        initialMoleFractions = {speciesDict['O2']:0.5,
                        speciesDict['H']:0.5,
                        speciesDict['CO2']:1.0, 
                        speciesDict['Ar']:4.0}
        
        # Initialize the model
        rxnSystem = SimpleReactor(T,P,initialMoleFractions=initialMoleFractions,termination=None)
        rxnSystem.initializeModel(speciesList, reactionList, [], [])
        
        # Advance to time = 0.1 s
        rxnSystem.advance(0.1)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulatedMoleFracs = rxnSystem.y/numpy.sum(rxnSystem.y)
        expectedMoleFracs = numpy.array([0.6666667,0,0,0,0.1666667,0, 0.08333333,0.08333333,2.466066000000000E-10,0,0,0,0,0])
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i],expectedMoleFracs[i])
            
        # Advance to time = 5 s
        rxnSystem.advance(5)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        expectedMoleFracs = numpy.array([0.6666667,0,0,0, 0.1666667,0,0.08333332,0.08333332,1.233033000000000E-08,0,0,0,0,0])
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i],expectedMoleFracs[i])
        
        # Try a new set of conditions
        
        T = 850 # K
        P = 200 # Pa        
        initialMoleFractions = {speciesDict['O2']:0.5,
                        speciesDict['H']:1,
                        speciesDict['CO2']:1, 
                        speciesDict['N2']:4,
                        speciesDict['CH3']:1}
        
        # Initialize the model
        rxnSystem = SimpleReactor(T,P,initialMoleFractions=initialMoleFractions,termination=None)
        rxnSystem.initializeModel(speciesList, reactionList, [], [])
        
        # Advance to time = 5 s
        rxnSystem.advance(5)  

        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulatedMoleFracs = rxnSystem.y/numpy.sum(rxnSystem.y)
        expectedMoleFracs = numpy.array([0,0,0,0.5487241, 0.137181,0, 0.1083234, 0.0685777, 1.280687000000000E-05,  0,0,0,   0.1083362, 0.02884481])
        for i in range(len(simulatedMoleFracs)):
            self.assertAlmostEqual(simulatedMoleFracs[i],expectedMoleFracs[i])
示例#9
0
文件: input.py 项目: nsm120/RMG-Py
def simpleReactor(temperature,
                  pressure,
                  initialMoleFractions,
                  nSimsTerm=6,
                  terminationConversion=None,
                  terminationTime=None,
                  terminationRateRatio=None,
                  balanceSpecies=None,
                  sensitivity=None,
                  sensitivityThreshold=1e-3,
                  sensitivityTemperature=None,
                  sensitivityPressure=None,
                  sensitivityMoleFractions=None,
                  ):
    logging.debug('Found SimpleReactor reaction system')
    
    for key,value in initialMoleFractions.iteritems():
        if not isinstance(value,list):
            initialMoleFractions[key] = float(value)
            if value < 0:
                raise InputError('Initial mole fractions cannot be negative.')
        else:
            if len(value) != 2:
                raise InputError("Initial mole fraction values must either be a number or a list with 2 entries")
            initialMoleFractions[key] = [float(value[0]),float(value[1])]
            if value[0] < 0 or value[1] < 0:
                raise InputError('Initial mole fractions cannot be negative.')
            elif value[1] < value[0]:
                raise InputError('Initial mole fraction range out of order: {0}'.format(key))
    
    if not isinstance(temperature,list):
        T = Quantity(temperature)
    else:
        if len(temperature) != 2:
            raise InputError('Temperature and pressure ranges can either be in the form of (number,units) or a list with 2 entries of the same format')
        T = [Quantity(t) for t in temperature]
        
    if not isinstance(pressure,list):
        P = Quantity(pressure)
    else:
        if len(pressure) != 2:
            raise InputError('Temperature and pressure ranges can either be in the form of (number,units) or a list with 2 entries of the same format')
        P = [Quantity(p) for p in pressure]
        
        
    if not isinstance(temperature,list) and not isinstance(pressure,list) and all([not isinstance(x,list) for x in initialMoleFractions.values()]):
        nSimsTerm=1
    
    termination = []
    if terminationConversion is not None:
        for spec, conv in terminationConversion.iteritems():
            termination.append(TerminationConversion(speciesDict[spec], conv))
    if terminationTime is not None:
        termination.append(TerminationTime(Quantity(terminationTime)))
    if terminationRateRatio is not None:
        termination.append(TerminationRateRatio(terminationRateRatio))
    if len(termination) == 0:
        raise InputError('No termination conditions specified for reaction system #{0}.'.format(len(rmg.reactionSystems)+2))
    
    sensitiveSpecies = []
    if sensitivity:
        if isinstance(sensitivity, str): sensitivity = [sensitivity]
        for spec in sensitivity:
            sensitiveSpecies.append(speciesDict[spec])
    
    if not isinstance(T,list):
        sensitivityTemperature = T
    if not isinstance(P,list):
        sensitivityPressure = P
    if not any([isinstance(x,list) for x in initialMoleFractions.itervalues()]):
        sensitivityMoleFractions = deepcopy(initialMoleFractions)
    if sensitivityMoleFractions is None or sensitivityTemperature is None or sensitivityPressure is None:
        sensConditions = None
    else:
        sensConditions = sensitivityMoleFractions
        sensConditions['T'] = Quantity(sensitivityTemperature).value_si
        sensConditions['P'] = Quantity(sensitivityPressure).value_si

    
    system = SimpleReactor(T, P, initialMoleFractions, nSimsTerm, termination, sensitiveSpecies, sensitivityThreshold,sensConditions)
    rmg.reactionSystems.append(system)
    
    assert balanceSpecies is None or isinstance(balanceSpecies,str), 'balanceSpecies should be the string corresponding to a single species'
    rmg.balanceSpecies = balanceSpecies
    if balanceSpecies: #check that the balanceSpecies can't be taken to zero
        total = 0.0
        for key,item in initialMoleFractions.iteritems():
            if key == balanceSpecies:
                assert not isinstance(item,list), 'balanceSpecies must not have a defined range'
                xbspcs = item
            if isinstance(item,list):
                total += item[1]-item[0]

        if total > xbspcs:
            raise ValueError('The sum of the differences in the ranged mole fractions is greater than the mole fraction of the balance species, this would require the balanceSpecies mole fraction to be negative in some cases which is not allowed, either reduce the maximum mole fractions or dont use balanceSpecies')
示例#10
0
    def saveForm(self, posted, form):
        """
        Save form data into input.py file specified by the path.
        """
        # Clean past history
        self.rmg = RMG()

        # Databases
        #self.rmg.databaseDirectory = settings['database.directory']
        self.rmg.thermoLibraries = []
        if posted.thermo_libraries.all():
            self.rmg.thermoLibraries = [
                item.thermolib.encode()
                for item in posted.thermo_libraries.all()
            ]
        self.rmg.reactionLibraries = []
        self.rmg.seedMechanisms = []
        if posted.reaction_libraries.all():
            for item in posted.reaction_libraries.all():
                if not item.seedmech and not item.edge:
                    self.rmg.reactionLibraries.append(
                        (item.reactionlib.encode(), False))
                elif not item.seedmech:
                    self.rmg.reactionLibraries.append(
                        (item.reactionlib.encode(), True))
                else:
                    self.rmg.seedMechanisms.append(item.reactionlib.encode())
        self.rmg.statmechLibraries = []
        self.rmg.kineticsDepositories = ['training']
        self.rmg.kineticsFamilies = ['!Intra_Disproportionation']
        self.rmg.kineticsEstimator = 'rate rules'

        # Species
        self.rmg.initialSpecies = []
        speciesDict = {}
        initialMoleFractions = {}
        self.rmg.reactionModel = CoreEdgeReactionModel()
        for item in posted.reactor_species.all():
            structure = Molecule().fromAdjacencyList(item.adjlist.encode())
            spec, isNew = self.rmg.reactionModel.makeNewSpecies(
                structure,
                label=item.name.encode(),
                reactive=False if item.inert else True)
            self.rmg.initialSpecies.append(spec)
            speciesDict[item.name.encode()] = spec
            initialMoleFractions[spec] = item.molefrac

        # Reactor systems
        self.rmg.reactionSystems = []
        for item in posted.reactor_systems.all():
            T = Quantity(item.temperature, item.temperature_units.encode())
            P = Quantity(item.pressure, item.pressure_units.encode())
            termination = []
            if item.conversion:
                termination.append(
                    TerminationConversion(speciesDict[item.species.encode()],
                                          item.conversion))
            termination.append(
                TerminationTime(
                    Quantity(item.terminationtime, item.time_units.encode())))
            system = SimpleReactor(T, P, initialMoleFractions, termination)
            self.rmg.reactionSystems.append(system)

        # Simulator tolerances
        self.rmg.absoluteTolerance = form.cleaned_data['simulator_atol']
        self.rmg.relativeTolerance = form.cleaned_data['simulator_rtol']
        self.rmg.fluxToleranceKeepInEdge = form.cleaned_data[
            'toleranceKeepInEdge']
        self.rmg.fluxToleranceMoveToCore = form.cleaned_data[
            'toleranceMoveToCore']
        self.rmg.fluxToleranceInterrupt = form.cleaned_data[
            'toleranceInterruptSimulation']
        self.rmg.maximumEdgeSpecies = form.cleaned_data['maximumEdgeSpecies']

        # Pressure Dependence
        pdep = form.cleaned_data['pdep'].encode()
        if pdep != 'off':
            self.rmg.pressureDependence = MEASURE()
            self.rmg.pressureDependence.method = pdep
            # Temperature and pressure range
            interpolation = (form.cleaned_data['interpolation'].encode(),
                             form.cleaned_data['temp_basis'],
                             form.cleaned_data['p_basis'])
            self.rmg.pressureDependence.Tmin = Quantity(
                form.cleaned_data['temp_low'],
                form.cleaned_data['temprange_units'].encode())
            self.rmg.pressureDependence.Tmax = Quantity(
                form.cleaned_data['temp_high'],
                form.cleaned_data['temprange_units'].encode())
            self.rmg.pressureDependence.Tcount = form.cleaned_data[
                'temp_interp']
            Tlist = getTemperaturesForModel(
                interpolation, self.rmg.pressureDependence.Tmin.value,
                self.rmg.pressureDependence.Tmax.value,
                self.rmg.pressureDependence.Tcount)
            self.rmg.pressureDependence.Tlist = Quantity(Tlist, "K")

            self.rmg.pressureDependence.Pmin = Quantity(
                form.cleaned_data['p_low'],
                form.cleaned_data['prange_units'].encode())
            self.rmg.pressureDependence.Pmax = Quantity(
                form.cleaned_data['p_high'],
                form.cleaned_data['prange_units'].encode())
            self.rmg.pressureDependence.Pcount = form.cleaned_data['p_interp']
            Plist = getPressuresForModel(
                interpolation, self.rmg.pressureDependence.Pmin.value,
                self.rmg.pressureDependence.Pmax.value,
                self.rmg.pressureDependence.Pcount)
            self.rmg.pressureDependence.Plist = Quantity(Plist, "Pa")

            # Process grain size and count
            self.rmg.pressureDependence.grainSize = Quantity(
                form.cleaned_data['maximumGrainSize'],
                form.cleaned_data['grainsize_units'].encode())
            self.rmg.pressureDependence.grainCount = form.cleaned_data[
                'minimumNumberOfGrains']

            # Process interpolation model
            self.rmg.pressureDependence.model = interpolation

        # Additional Options
        self.rmg.units = 'si'
        self.rmg.saveRestartPeriod = Quantity(
            form.cleaned_data['saveRestartPeriod'],
            form.cleaned_data['saveRestartPeriodUnits'].encode(
            )) if form.cleaned_data['saveRestartPeriod'] else None
        self.rmg.drawMolecules = form.cleaned_data['drawMolecules']
        self.rmg.generatePlots = form.cleaned_data['generatePlots']
        self.rmg.saveConcentrationProfiles = form.cleaned_data[
            'saveConcentrationProfiles']

        # Save the input.py file
        self.rmg.saveInput(self.savepath)
示例#11
0
    def test_specific_collider_model(self):
        """
        Test the solver's ability to simulate a model with specific third body species collision efficiencies.
        """
        chem_file = os.path.join(os.path.dirname(__file__), 'files', 'specific_collider_model', 'chem.inp')
        dictionary_file = os.path.join(os.path.dirname(__file__), 'files', 'specific_collider_model',
                                       'species_dictionary.txt')
        species_list, reaction_list = load_chemkin_file(chem_file, dictionary_file)

        # Note that H2O is in the corresponding Chemkin file, but intentionally not defined here to check the solver.
        smiles_dict = {'Ar': '[Ar]', 'N2(1)': 'N#N', 'O2': '[O][O]', 'H': '[H]', 'CH3': '[CH3]', 'CH4': 'C'}
        species_dict = {}
        for name, smiles in smiles_dict.items():
            mol = Molecule(smiles=smiles)
            for species in species_list:
                if species.is_isomorphic(mol):
                    species_dict[name] = species
                    break

        T = 1000  # K
        P = 10  # Pa
        initial_mole_fractions = {species_dict['Ar']: 2.0,
                                  species_dict['N2(1)']: 1.0,
                                  species_dict['O2']: 0.5,
                                  species_dict['H']: 0.1,
                                  species_dict['CH3']: 0.1,
                                  species_dict['CH4']: 0.001}

        # Initialize the model
        rxn_system = SimpleReactor(T, P, initial_mole_fractions=initial_mole_fractions, n_sims=1, termination=None)
        rxn_system.initialize_model(species_list, reaction_list, [], [])

        # Advance to time = 0.1 s
        rxn_system.advance(0.1)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulated_mole_fracs = rxn_system.y / np.sum(rxn_system.y)
        expected_mole_fracs = np.array([0.540394532, 0.270197216, 0.135098608, 0.027019722, 0.027019722, 0.000270202, 0.0])
        # order: Ar, N2, O2, H, CH3, CH4
        for i in range(len(simulated_mole_fracs)):
            self.assertAlmostEqual(simulated_mole_fracs[i], expected_mole_fracs[i], 6)

        # Advance to time = 5 s
        rxn_system.advance(5)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        expected_mole_fracs = np.array([0.540394573, 0.270197287, 0.135098693, 0.027019519, 0.027019519, 0.00027041, 0.0])
        # order: Ar, N2, O2, H, CH3, CH4
        for i in range(len(simulated_mole_fracs)):
            self.assertAlmostEqual(simulated_mole_fracs[i], expected_mole_fracs[i], 6)

        # Try a new set of conditions
        T = 850  # K
        P = 200  # Pa
        initial_mole_fractions = {species_dict['Ar']: 1.0,
                                  species_dict['N2(1)']: 0.5,
                                  species_dict['O2']: 0.5,
                                  species_dict['H']: 0.001,
                                  species_dict['CH3']: 0.01,
                                  species_dict['CH4']: 0.5}

        # Initialize the model
        rxn_system = SimpleReactor(T, P, initial_mole_fractions=initial_mole_fractions, n_sims=1, termination=None)
        rxn_system.initialize_model(species_list, reaction_list, [], [])

        # Advance to time = 5 s
        rxn_system.advance(5)
        # Compare simulated mole fractions with expected mole fractions from CHEMKIN
        simulated_mole_fracs = rxn_system.y / np.sum(rxn_system.y)
        expected_mole_fracs = np.array([0.398247713, 0.199123907, 0.199123907, 0.000398169, 0.003982398, 0.199123907, 0.0])
        # order: Ar, N2, O2, H, CH3, CH4
        for i in range(len(simulated_mole_fracs)):
            self.assertAlmostEqual(simulated_mole_fracs[i], expected_mole_fracs[i], 6)
示例#12
0
    def testSolve(self):
        """
        Test the simple batch reactor with a simple kinetic model. Here we
        choose a kinetic model consisting of the hydrogen abstraction reaction
        CH4 + C2H5 <=> CH3 + C2H6.
        """
        CH4 = Species(
            molecule=[Molecule().fromSMILES("C")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 8.615, 9.687,10.963,12.301,14.841,16.976,20.528],"cal/(mol*K)"), H298=(-17.714,"kcal/mol"), S298=(44.472,"cal/(mol*K)"))
            )
        CH3 = Species(
            molecule=[Molecule().fromSMILES("[CH3]")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 9.397,10.123,10.856,11.571,12.899,14.055,16.195],"cal/(mol*K)"), H298=(  9.357,"kcal/mol"), S298=(45.174,"cal/(mol*K)"))
            )
        C2H6 = Species(
            molecule=[Molecule().fromSMILES("CC")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([12.684,15.506,18.326,20.971,25.500,29.016,34.595],"cal/(mol*K)"), H298=(-19.521,"kcal/mol"), S298=(54.799,"cal/(mol*K)"))
            )
        C2H5 = Species(
            molecule=[Molecule().fromSMILES("C[CH2]")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([11.635,13.744,16.085,18.246,21.885,24.676,29.107],"cal/(mol*K)"), H298=( 29.496,"kcal/mol"), S298=(56.687,"cal/(mol*K)"))
            )

        rxn1 = Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=(686.375*6,'m^3/(mol*s)'), n=4.40721, Ea=(7.82799,'kcal/mol'), T0=(298.15,'K')))

        coreSpecies = [CH4,CH3,C2H6,C2H5]
        edgeSpecies = []
        coreReactions = [rxn1]
        edgeReactions = []

        T = 1000; P = 1.0e5
        rxnSystem = SimpleReactor(T, P, initialMoleFractions={C2H5: 0.1, CH3: 0.1, CH4: 0.4, C2H6: 0.4}, termination=[])
        rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions)

        tlist = numpy.array([10**(i/10.0) for i in range(-130, -49)], numpy.float64)

        # Integrate to get the solution at each time point
        t = []; y = []; reactionRates = []; speciesRates = []
        for t1 in tlist:
            rxnSystem.advance(t1)
            t.append(rxnSystem.t)
            # You must make a copy of y because it is overwritten by DASSL at
            # each call to advance()
            y.append(rxnSystem.y.copy())
            reactionRates.append(rxnSystem.coreReactionRates.copy())
            speciesRates.append(rxnSystem.coreSpeciesRates.copy())

        # Convert the solution vectors to numpy arrays
        t = numpy.array(t, numpy.float64)
        y = numpy.array(y, numpy.float64)
        reactionRates = numpy.array(reactionRates, numpy.float64)
        speciesRates = numpy.array(speciesRates, numpy.float64)

        # Check that we're computing the species fluxes correctly
        for i in range(t.shape[0]):
            self.assertAlmostEqual(reactionRates[i,0], speciesRates[i,0], delta=1e-6*reactionRates[i,0])
            self.assertAlmostEqual(reactionRates[i,0], -speciesRates[i,1], delta=1e-6*reactionRates[i,0])
            self.assertAlmostEqual(reactionRates[i,0], -speciesRates[i,2], delta=1e-6*reactionRates[i,0])
            self.assertAlmostEqual(reactionRates[i,0], speciesRates[i,3], delta=1e-6*reactionRates[i,0])
        
        # Check that we've reached equilibrium 
        self.assertAlmostEqual(reactionRates[-1,0], 0.0, delta=1e-2)
示例#13
0
    def testSolve(self):
        """
        Test the simple batch reactor with a simple kinetic model. Here we
        choose a kinetic model consisting of the hydrogen abstraction reaction
        CH4 + C2H5 <=> CH3 + C2H6.
        """
        CH4 = Species(
            molecule=[Molecule().fromSMILES("C")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 8.615, 9.687,10.963,12.301,14.841,16.976,20.528],"cal/mol*K"), H298=(-17.714,"kcal/mol"), S298=(44.472,"cal/mol*K"))
            )
        CH3 = Species(
            molecule=[Molecule().fromSMILES("[CH3]")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([ 9.397,10.123,10.856,11.571,12.899,14.055,16.195],"cal/mol*K"), H298=(  9.357,"kcal/mol"), S298=(45.174,"cal/mol*K"))
            )
        C2H6 = Species(
            molecule=[Molecule().fromSMILES("CC")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([12.684,15.506,18.326,20.971,25.500,29.016,34.595],"cal/mol*K"), H298=(-19.521,"kcal/mol"), S298=(54.799,"cal/mol*K"))
            )
        C2H5 = Species(
            molecule=[Molecule().fromSMILES("C[CH2]")],
            thermo=ThermoData(Tdata=([300,400,500,600,800,1000,1500],"K"), Cpdata=([11.635,13.744,16.085,18.246,21.885,24.676,29.107],"cal/mol*K"), H298=( 29.496,"kcal/mol"), S298=(56.687,"cal/mol*K"))
            )

        rxn1 = Reaction(reactants=[C2H6,CH3], products=[C2H5,CH4], kinetics=Arrhenius(A=686.375*6, n=4.40721, Ea=7.82799*4184., T0=298.15))

        coreSpecies = [CH4,CH3,C2H6,C2H5]
        edgeSpecies = []
        coreReactions = [rxn1]
        edgeReactions = []

        T = 1000; P = 1.0e5
        rxnSystem = SimpleReactor(T, P, initialMoleFractions={C2H5: 0.1, CH3: 0.1, CH4: 0.4, C2H6: 0.4})
        rxnSystem.initializeModel(coreSpecies, coreReactions, edgeSpecies, edgeReactions)

        tlist = numpy.array([10**(i/10.0) for i in range(-130, -49)], numpy.float64)

        # Integrate to get the solution at each time point
        t = []; y = []; reactionRates = []; speciesRates = []
        for t1 in tlist:
            rxnSystem.advance(t1)
            t.append(rxnSystem.t)
            # You must make a copy of y because it is overwritten by DASSL at
            # each call to advance()
            y.append(rxnSystem.y.copy())
            reactionRates.append(rxnSystem.coreReactionRates.copy())
            speciesRates.append(rxnSystem.coreSpeciesRates.copy())

        # Convert the solution vectors to numpy arrays
        t = numpy.array(t, numpy.float64)
        y = numpy.array(y, numpy.float64)
        reactionRates = numpy.array(reactionRates, numpy.float64)
        speciesRates = numpy.array(speciesRates, numpy.float64)

        import pylab
        fig = pylab.figure(figsize=(6,6))
        pylab.subplot(2,1,1)
        pylab.semilogx(t, y)
        pylab.ylabel('Concentration (mol/m$^\\mathdefault{3}$)')
        pylab.legend(['CH4', 'CH3', 'C2H6', 'C2H5'], loc=4)
        pylab.subplot(2,1,2)
        pylab.semilogx(t, speciesRates)
        pylab.legend(['CH4', 'CH3', 'C2H6', 'C2H5'], loc=4)
        pylab.xlabel('Time (s)')
        pylab.ylabel('Rate (mol/m$^\\mathdefault{3}$*s)')
        fig.subplots_adjust(left=0.12, bottom=0.10, right=0.95, top=0.95, wspace=0.20, hspace=0.35)
        pylab.show()