Ejemplo n.º 1
0
    def __init__(self,
                 reactorType,
                 reactionTime,
                 molFrac,
                 T0=None,
                 P0=None,
                 V0=None):
        self.reactorType = reactorType
        self.reactionTime = Quantity(reactionTime)

        # Normalize initialMolFrac if not already done:
        if sum(molFrac.values()) != 1.00:
            total = sum(molFrac.values())
            for species, value in molFrac.iteritems():
                molFrac[species] = value / total

        self.molFrac = molFrac

        # Check to see that one of the three attributes T0, P0, and V0 is less unspecified
        props = [T0, P0, V0]
        total = 0
        for prop in props:
            if prop is None: total += 1

        if not total == 1:
            raise Exception(
                "Cantera conditions must leave one of T0, P0, and V0 state variables unspecified"
            )

        self.T0 = Quantity(T0) if T0 else None
        self.P0 = Quantity(P0) if P0 else None
        self.V0 = Quantity(V0) if V0 else None
Ejemplo n.º 2
0
def liquidReactor(temperature,
                  initialConcentrations,
                  terminationConversion=None,
                  terminationTime=None,
                  sensitivity=None,
                  sensitivityThreshold=1e-3):

    logging.debug('Found LiquidReactor reaction system')
    T = Quantity(temperature)
    for spec, conc in initialConcentrations.iteritems():
        concentration = Quantity(conc)
        # check the dimensions are ok
        # convert to mol/m^3 (or something numerically nice? or must it be SI)
        initialConcentrations[spec] = concentration.value_si
    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 = LiquidReactor(T, initialConcentrations, termination,
                           sensitiveSpecies, sensitivityThreshold)
    rmg.reactionSystems.append(system)
Ejemplo n.º 3
0
def mlEstimator(thermo=True,
                name='main',
                minHeavyAtoms=1,
                maxHeavyAtoms=None,
                H298UncertaintyCutoff=(3.0, 'kcal/mol'),
                S298UncertaintyCutoff=(2.0, 'cal/(mol*K)'),
                CpUncertaintyCutoff=(2.0, 'cal/(mol*K)')):
    from rmgpy.ml.estimator import MLEstimator

    # Currently only support thermo
    if thermo:
        models_path = os.path.join(settings['database.directory'], 'thermo',
                                   'ml', name)
        if not os.path.exists(models_path):
            raise InputError(
                'Cannot find ML models folder {}'.format(models_path))
        H298_path = os.path.join(models_path, 'H298')
        S298_path = os.path.join(models_path, 'S298')
        Cp_path = os.path.join(models_path, 'Cp')
        rmg.ml_estimator = MLEstimator(H298_path, S298_path, Cp_path)

        uncertainty_cutoffs = dict(H298=Quantity(*H298UncertaintyCutoff),
                                   S298=Quantity(*S298UncertaintyCutoff),
                                   Cp=Quantity(*CpUncertaintyCutoff))
        rmg.ml_settings = dict(
            min_heavy_atoms=minHeavyAtoms,
            max_heavy_atoms=maxHeavyAtoms,
            uncertainty_cutoffs=uncertainty_cutoffs,
        )
Ejemplo n.º 4
0
def renderMW(MW):
    """
    Renders molecular weight from SI units to the regular g/mol units we are used to.
    """
    mass = Quantity(MW, 'kg/mol').value
    multfactor = Quantity(1, 'g/mol').getConversionFactorFromSI()
    return mark_safe("{0:.2f}".format(mass * multfactor))
Ejemplo n.º 5
0
def reactorSetups(reactorTypes, temperatures, pressures, initialMoleFractionsList, terminationTimes):
    global setups

    terminationTimes = Quantity(terminationTimes)
    temperatures = Quantity(temperatures)
    pressures = Quantity(pressures)

    setups = [reactorTypes, temperatures, pressures, initialMoleFractionsList, terminationTimes]
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
def energies(Emin=None, Emax=None, dE=None, count=None):
    global measure
    if dE is not None or count is not None:
        if dE is not None:
            measure.grainSize = Quantity(dE)
        if count is not None:
            measure.grainCount = count
        if Emin is not None and Emax is not None:
            measure.Emin = Quantity(Emin)
            measure.Emax = Quantity(Emax)
    else:
        raise InputError('Must specify either dE or count in energies() block.')
Ejemplo n.º 8
0
def pressureDependence(
    method,
    temperatures,
    pressures,
    maximumGrainSize=0.0,
    minimumNumberOfGrains=0,
    interpolation=None,
    maximumAtoms=None,
):

    from rmgpy.cantherm.pdep import PressureDependenceJob

    # Setting the pressureDependence attribute to non-None enables pressure dependence
    rmg.pressureDependence = PressureDependenceJob(network=None)

    # Process method
    rmg.pressureDependence.method = method

    # Process interpolation model
    if isinstance(interpolation, str):
        interpolation = (interpolation, )
    if interpolation[0].lower() not in ("chebyshev", "pdeparrhenius"):
        raise InputError(
            "Interpolation model must be set to either 'Chebyshev' or 'PDepArrhenius'."
        )
    rmg.pressureDependence.interpolationModel = interpolation

    # Process temperatures
    Tmin, Tmax, Tunits, Tcount = temperatures
    rmg.pressureDependence.Tmin = Quantity(Tmin, Tunits)
    rmg.pressureDependence.Tmax = Quantity(Tmax, Tunits)
    rmg.pressureDependence.Tcount = Tcount
    rmg.pressureDependence.generateTemperatureList()

    # Process pressures
    Pmin, Pmax, Punits, Pcount = pressures
    rmg.pressureDependence.Pmin = Quantity(Pmin, Punits)
    rmg.pressureDependence.Pmax = Quantity(Pmax, Punits)
    rmg.pressureDependence.Pcount = Pcount
    rmg.pressureDependence.generatePressureList()

    # Process grain size and count
    rmg.pressureDependence.maximumGrainSize = Quantity(maximumGrainSize)
    rmg.pressureDependence.minimumGrainCount = minimumNumberOfGrains

    # Process maximum atoms
    rmg.pressureDependence.maximumAtoms = maximumAtoms

    rmg.pressureDependence.activeJRotor = True
    rmg.pressureDependence.activeKRotor = True
    rmg.pressureDependence.rmgmode = True
Ejemplo n.º 9
0
def fitArrhenius(kineticsList, weights, Tlist, Tmin, Tmax):
    """
    Fit a modified Arrhenius expression to the set of loaded kinetics 
    `kineticsList` using the given array of temperatures `Tlist` in K. The
    `Tmin` and `Tmax` parameters specify the limits in K at which the fitted
    kinetics should be said to be valid. Returns the best-fit kinetics and the
    confidence interval (on a log scale).
    """
    import scipy.stats

    Tdata = []
    kdata = []
    wdata = []

    print 'Fitting modified Arrhenius kinetics...'

    for kinetics, weight in zip(kineticsList, weights):
        for n in range(len(Tlist)):
            if kinetics.isTemperatureValid(Tlist[n]):
                Tdata.append(Tlist[n])
                kdata.append(kinetics.getRateCoefficient(Tlist[n]))
                wdata.append(weight)

    Tdata = numpy.array(Tdata, numpy.float)
    kdata = numpy.array(kdata, numpy.float)
    wdata = numpy.array(wdata, numpy.float)
    arrhenius = Arrhenius().fitToData(Tdata,
                                      kdata,
                                      kunits='m^3/(mol*s)',
                                      T0=300,
                                      weights=wdata)

    # Compute RMS error and confidence interval
    count = len(kdata)
    rmsError = 0
    for T, k in zip(Tdata, kdata):
        rmsError += (math.log10(k) -
                     math.log10(arrhenius.getRateCoefficient(T)))**2
    rmsError = math.sqrt(rmsError / (count - 3))
    ci = scipy.stats.t.ppf(0.975, count - 3) * rmsError

    # Adjust units of best-fit Arrhenius expression
    arrhenius.A.units = 'cm^3/(mol*s)' if len(
        forwardReaction.reactants) == 2 else 's^-1'
    arrhenius.Ea.units = 'kJ/mol'

    # Set Tmin and Tmax of best-fit Arrhenius expression
    arrhenius.Tmin = Quantity(Tmin, "K")
    arrhenius.Tmax = Quantity(Tmax, "K")

    return arrhenius, ci
Ejemplo n.º 10
0
    def sensitivityAnalysis(self, initialMoleFractions, sensitiveSpecies, T, P, terminationTime, sensitivityThreshold=1e-3, number=10, fileformat='.png'):
        """
        Run sensitivity analysis using the RMG solver in a single ReactionSystem object
        
        initialMoleFractions is a dictionary with Species objects as keys and mole fraction initial conditions
        sensitiveSpecies is a list of sensitive Species objects
        number is the number of top species thermo or reaction kinetics desired to be plotted
        """
        
        
        from rmgpy.solver import SimpleReactor, TerminationTime
        from rmgpy.quantity import Quantity
        from rmgpy.tools.sensitivity import plotSensitivity
        from rmgpy.rmg.listener import SimulationProfileWriter, SimulationProfilePlotter

        T = Quantity(T)
        P = Quantity(P)
        termination=[TerminationTime(Quantity(terminationTime))]
                                     
        reactionSystem = SimpleReactor(T, P, initialMoleFractions, termination, sensitiveSpecies, sensitivityThreshold)
        
        # Create the csv worksheets for logging sensitivity
        util.makeOutputSubdirectory(self.outputDirectory, 'solver')
        sensWorksheet = []
        reactionSystemIndex = 0
        for spec in reactionSystem.sensitiveSpecies:
            csvfilePath = os.path.join(self.outputDirectory, 'solver', 'sensitivity_{0}_SPC_{1}.csv'.format(reactionSystemIndex+1, spec.index))
            sensWorksheet.append(csvfilePath)

        reactionSystem.attach(SimulationProfileWriter(
            self.outputDirectory, reactionSystemIndex, self.speciesList))  
        reactionSystem.attach(SimulationProfilePlotter(
            self.outputDirectory, reactionSystemIndex, self.speciesList))
        
        reactionSystem.simulate(
            coreSpecies = self.speciesList,
            coreReactions = self.reactionList,
            edgeSpecies = [],
            edgeReactions = [],
            toleranceKeepInEdge = 0,
            toleranceMoveToCore = 1,
            toleranceInterruptSimulation = 1,
            sensitivity = True,
            sensWorksheet = sensWorksheet,
        )
        
        
        plotSensitivity(self.outputDirectory, reactionSystemIndex, reactionSystem.sensitiveSpecies, number=number, fileformat=fileformat)
Ejemplo n.º 11
0
def temperatures(Tlist=None, Tmin=None, Tmax=None, count=None):
    global measure
    if Tlist is not None:
        # We've been provided a list of specific temperatures to use
        measure.Tlist = Quantity(Tlist)
        measure.Tmin = Quantity(numpy.min(measure.Tlist.value_si),"K")
        measure.Tmax = Quantity(numpy.max(measure.Tlist.value_si),"K")
    elif Tmin is not None and Tmax is not None and count is not None:
        # We've been provided a temperature range and number of temperatures to use
        # We defer choosing the actual temperatures because they depend on the
        # choice of interpolation model
        measure.Tmin = Quantity(Tmin)
        measure.Tmax = Quantity(Tmax)
        measure.Tcount = count
    else:
        raise SyntaxError('Must specify either a list of temperatures or Tmin, Tmax, and count.')
Ejemplo n.º 12
0
def options(name='Seed',
            generateSeedEachIteration=True,
            saveSeedToDatabase=False,
            units='si',
            saveRestartPeriod=None,
            generateOutputHTML=False,
            generatePlots=False,
            saveSimulationProfiles=False,
            verboseComments=False,
            saveEdgeSpecies=False,
            keepIrreversible=False,
            wallTime='00:00:00:00'):
    rmg.name = name
    rmg.generateSeedEachIteration = generateSeedEachIteration
    rmg.saveSeedToDatabase = saveSeedToDatabase
    rmg.units = units
    rmg.saveRestartPeriod = Quantity(
        saveRestartPeriod) if saveRestartPeriod else None
    if generateOutputHTML:
        logging.warning(
            'Generate Output HTML option was turned on. Note that this will slow down model generation.'
        )
    rmg.generateOutputHTML = generateOutputHTML
    rmg.generatePlots = generatePlots
    rmg.saveSimulationProfiles = saveSimulationProfiles
    rmg.verboseComments = verboseComments
    if saveEdgeSpecies:
        logging.warning(
            'Edge species saving was turned on. This will slow down model generation for large simulations.'
        )
    rmg.saveEdgeSpecies = saveEdgeSpecies
    rmg.keepIrreversible = keepIrreversible
    rmg.wallTime = wallTime
Ejemplo n.º 13
0
def pressures(Plist=None, Pmin=None, Pmax=None, count=None):
    global measure
    if Plist is not None:
        # We've been provided a list of specific pressures to use
        measure.Plist = Quantity(Plist)
        measure.Pmin = Quantity(numpy.min(measure.Plist.value_si),"Pa")
        measure.Pmax = Quantity(numpy.max(measure.Plist.value_si),"Pa")
    elif Pmin is not None and Pmax is not None and count is not None:
        # We've been provided a pressures range and number of pressures to use
        # We defer choosing the actual pressures because they depend on the
        # choice of interpolation model
        measure.Pmin = Quantity(Pmin)
        measure.Pmax = Quantity(Pmax)
        measure.Pcount = count
    else:
        raise SyntaxError('Must specify either a list of pressures or Pmin, Pmax, and count.')
Ejemplo n.º 14
0
def explorer(source,
             explore_tol=(0.01, 's^-1'),
             energy_tol=np.inf,
             flux_tol=0.0,
             bathGas=None,
             maximumRadicalElectrons=np.inf):
    global jobList, speciesDict
    for job in jobList:
        if isinstance(job, PressureDependenceJob):
            pdepjob = job
            break
    else:
        raise InputError(
            'the explorer block must occur after the pressureDependence block')

    source = [speciesDict[name] for name in source]

    explore_tol = Quantity(explore_tol)

    if bathGas:
        bathGas0 = bathGas or {}
        bathGas = {}
        for spec, fraction in bathGas0.items():
            bathGas[speciesDict[spec]] = fraction

    job = ExplorerJob(source=source,
                      pdepjob=pdepjob,
                      explore_tol=explore_tol.value_si,
                      energy_tol=energy_tol,
                      flux_tol=flux_tol,
                      bathGas=bathGas,
                      maximumRadicalElectrons=maximumRadicalElectrons)
    jobList.append(job)
Ejemplo n.º 15
0
def plotKinetics(request):
    """
    Allows user to upload chemkin files to generate a plot of reaction kinetics.
    """
    from rmgpy.quantity import Quantity
    from rmgweb.database.forms import RateEvaluationForm

    if request.method == 'POST':
        chemkin = Chemkin()
        chemkin.createDir()
        form = UploadChemkinForm(request.POST, request.FILES, instance=chemkin)
        rateForm = RateEvaluationForm(request.POST)
        eval = []

        if rateForm.is_valid():
            temperature = Quantity(
                rateForm.cleaned_data['temperature'],
                str(rateForm.cleaned_data['temperature_units'])).value_si
            pressure = Quantity(
                rateForm.cleaned_data['pressure'],
                str(rateForm.cleaned_data['pressure_units'])).value_si
            eval = [temperature, pressure]
            kineticsDataList = chemkin.getKinetics()

        if form.is_valid():
            form.save()
            kineticsDataList = chemkin.getKinetics()

        return render_to_response(
            'plotKineticsData.html', {
                'kineticsDataList': kineticsDataList,
                'plotWidth': 500,
                'plotHeight': 400 + 15 * len(kineticsDataList),
                'form': rateForm,
                'eval': eval
            },
            context_instance=RequestContext(request))

    # Otherwise create the form
    else:

        chemkin = Chemkin()
        chemkin.deleteDir()
        form = UploadChemkinForm(instance=chemkin)

    return render_to_response('plotKinetics.html', {'form': form},
                              context_instance=RequestContext(request))
Ejemplo n.º 16
0
def pressureDependence(
    method,
    temperatures,
    pressures,
    maximumGrainSize=0.0,
    minimumNumberOfGrains=0,
    interpolation=None,
    maximumAtoms=None,
):

    from rmgpy.cantherm.pdep import PressureDependenceJob

    # Setting the pressureDependence attribute to non-None enables pressure dependence
    rmg.pressureDependence = PressureDependenceJob(network=None)

    # Process method
    rmg.pressureDependence.method = method

    # Process interpolation model
    rmg.pressureDependence.interpolationModel = interpolation

    # Process temperatures
    Tmin, Tmax, Tunits, Tcount = temperatures
    rmg.pressureDependence.Tmin = Quantity(Tmin, Tunits)
    rmg.pressureDependence.Tmax = Quantity(Tmax, Tunits)
    rmg.pressureDependence.Tcount = Tcount
    rmg.pressureDependence.generateTemperatureList()

    # Process pressures
    Pmin, Pmax, Punits, Pcount = pressures
    rmg.pressureDependence.Pmin = Quantity(Pmin, Punits)
    rmg.pressureDependence.Pmax = Quantity(Pmax, Punits)
    rmg.pressureDependence.Pcount = Pcount
    rmg.pressureDependence.generatePressureList()

    # Process grain size and count
    rmg.pressureDependence.maximumGrainSize = Quantity(maximumGrainSize)
    rmg.pressureDependence.minimumGrainCount = minimumNumberOfGrains

    # Process maximum atoms
    rmg.pressureDependence.maximumAtoms = maximumAtoms

    rmg.pressureDependence.activeJRotor = True
    rmg.pressureDependence.activeKRotor = True
    rmg.pressureDependence.rmgmode = True
Ejemplo n.º 17
0
 def copy(self):
     """
     Return a copy of the current MEASURE job.
     """
     measure = MEASURE()
     
     measure.inputFile = self.inputFile
     measure.logFile = self.logFile
     measure.outputFile = self.outputFile
     measure.drawFile = self.drawFile
     
     if self.Tmin is not None: measure.Tmin = Quantity(self.Tmin)
     if self.Tmax is not None: measure.Tmax = Quantity(self.Tmax)
     measure.Tcount = self.Tcount
     if self.Pmin is not None: measure.Pmin = Quantity(self.Pmin)
     if self.Pmax is not None: measure.Pmax = Quantity(self.Pmax)
     measure.Pcount = self.Pcount
     if self.Emin is not None: measure.Emin = Quantity(self.Emin)
     if self.Emax is not None: measure.Emax = Quantity(self.Emax)
     if self.grainSize is not None: measure.grainSize = Quantity(self.grainSize)
     measure.grainCount = self.grainCount
     
     measure.method = self.method
     measure.model = self.model
     
     measure.network = self.network
     measure.Tlist = self.Tlist
     measure.Plist = self.Plist
     measure.Elist = self.Elist
     
     return measure
Ejemplo n.º 18
0
 def test_repr(self):
     """
     Test that the repr function for a CanteraCondition object can reconstitute
     the same object
     """
     reactor_type = 'IdealGasReactor'
     mol_frac = {'CC': 0.05, '[Ar]': 0.95}
     P = (3, 'atm')
     T = (1500, 'K')
     termination_time = (5e-5, 's')
     condition = CanteraCondition(reactor_type,
                                  termination_time,
                                  mol_frac,
                                  T0=T,
                                  P0=P)
     repr_condition = eval(condition.__repr__())
     self.assertEqual(repr_condition.T0.value_si, Quantity(T).value_si)
     self.assertEqual(repr_condition.P0.value_si, Quantity(P).value_si)
     self.assertEqual(repr_condition.V0, None)
     self.assertEqual(repr_condition.mol_frac, mol_frac)
Ejemplo n.º 19
0
def runIgnitionThermoSensitivity(runChemkinJob, inputFile, dictionaryFile):
    """
    Supply a runChemkinJob python function which returns the ignition delay with a 
    chemkin file input.  This will run finite difference sensitivities to enthalpies and 
    save them to a csv file.
    """

    from rmgpy.chemkin import loadChemkinFile, saveChemkinFile, getSpeciesIdentifier
    from rmgpy.quantity import Quantity

    speciesList, reactionList = loadChemkinFile(inputFile,
                                                dictionaryPath=dictionaryFile,
                                                readComments=False)

    num_species = len(speciesList)

    deltaH = Quantity(0.5, 'kcal/mol').value_si

    worksheet = csv.writer(file('ignition_thermo_sensitivity.csv', 'w'))
    worksheet.writerow([
        'Species', 'd[del H] (kcal/mol)', 'tau_high', 'tau_low',
        'd[ln tau]/d[del H]'
    ])

    print 'Running thermo sensitivity analysis using finite differences...'
    for index, species in enumerate(speciesList):
        species_index = index + 1
        species_string = getSpeciesIdentifier(species)
        print 'At species {0} of {1}. {2}'.format(species_index, num_species,
                                                  species_string)

        species.thermo.changeBaseEnthalpy(deltaH)
        saveChemkinFile('chem_temp.inp',
                        speciesList,
                        reactionList,
                        verbose=False)
        tau_high = runChemkinJob('chem_temp.inp')
        species.thermo.changeBaseEnthalpy(-deltaH)  # reset the thermo

        species.thermo.changeBaseEnthalpy(-deltaH)
        saveChemkinFile('chem_temp.inp',
                        speciesList,
                        reactionList,
                        verbose=False)
        tau_low = runChemkinJob('chem_temp.inp')
        species.thermo.changeBaseEnthalpy(deltaH)  # reset the kinetics

        if tau_high != 0 and tau_low != 0:
            sens = numpy.log(tau_high / tau_low) / (2 * deltaH)
        else:
            sens = 0

        worksheet.writerow([species_string, '1', tau_high, tau_low, sens])
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
def getRateCoefficientUnits(kinetics, user=None):
    """
    For a given `kinetics` model, return the desired rate coefficient units
    at high and low pressures, the conversion factor from SI to those units
    (high pressure), and the number of reactant species. If a `user` is 
    specified, the user's preferred units will be used; otherwise default units
    will be used.
    """
    # Get units from based on the kinetics type
    if isinstance(
            kinetics,
        (Arrhenius, ArrheniusEP, SurfaceArrhenius, SurfaceArrheniusBEP,
         StickingCoefficient, StickingCoefficientBEP)):
        units = kinetics.A.units
    elif isinstance(kinetics, KineticsData):
        units = kinetics.kdata.units
    elif isinstance(kinetics,
                    (PDepArrhenius, MultiArrhenius, MultiPDepArrhenius)):
        return getRateCoefficientUnits(kinetics.arrhenius[0])
    elif isinstance(kinetics, Chebyshev):
        units = kinetics.kunits
    elif isinstance(kinetics, Troe):
        units = kinetics.arrheniusHigh.A.units
    elif isinstance(kinetics, Lindemann):
        units = kinetics.arrheniusHigh.A.units
    elif isinstance(kinetics, ThirdBody):
        units = kinetics.arrheniusLow.A.units
    else:
        raise NotImplementedError('Cannot get units for {0} class.'.format(
            kinetics.__class__.__name__))

    if user and user.is_authenticated():
        # If user is logged in, get their desired units
        user_profile = UserProfile.objects.get(user=user)
        desired_units = user_profile.rateCoefficientUnits
    else:
        # Default base units
        desired_units = 'm^3,mol,s'

    if units == '':
        # Dimensionless
        return '', '', 1
    else:
        # Reconstruct the rate units using the desired base units
        kunits = reconstruct_rate_units(units, desired_units)
        kunits_low = reconstruct_rate_units(units,
                                            desired_units,
                                            add_conc_dim=True)
        kfactor = Quantity(1, kunits).getConversionFactorFromSI()

        return kunits, kunits_low, kfactor
Ejemplo n.º 22
0
def model(toleranceMoveToCore=None,
          toleranceMoveEdgeReactionToCore=numpy.inf,
          toleranceKeepInEdge=0.0,
          toleranceInterruptSimulation=1.0,
          toleranceMoveEdgeReactionToSurface=numpy.inf,
          toleranceMoveSurfaceSpeciesToCore=numpy.inf,
          toleranceMoveSurfaceReactionToCore=numpy.inf,
          toleranceMoveEdgeReactionToSurfaceInterrupt=None,
          toleranceMoveEdgeReactionToCoreInterrupt=None,
          maximumEdgeSpecies=1000000,
          minCoreSizeForPrune=50,
          minSpeciesExistIterationsForPrune=2,
          filterReactions=False,
          ignoreOverallFluxCriterion=False,
          maxNumSpecies=None,
          maxNumObjsPerIter=1,
          terminateAtMaxObjects=False,
          toleranceThermoKeepSpeciesInEdge=numpy.inf,
          dynamicsTimeScale=(0.0, 'sec')):
    """
    How to generate the model. `toleranceMoveToCore` must be specified. 
    toleranceMoveReactionToCore and toleranceReactionInterruptSimulation refers to an additional criterion for forcing an edge reaction to be included in the core
    by default this criterion is turned off
    Other parameters are optional and control the pruning.
    ignoreOverallFluxCriterion=True will cause the toleranceMoveToCore to be only applied
    to the pressure dependent network expansion and not movement of species from edge to core
    """
    if toleranceMoveToCore is None:
        raise InputError(
            "You must provide a toleranceMoveToCore value. It should be less than or equal to toleranceInterruptSimulation which is currently {0}"
            .format(toleranceInterruptSimulation))
    if toleranceMoveToCore > toleranceInterruptSimulation:
        raise InputError(
            "toleranceMoveToCore must be less than or equal to toleranceInterruptSimulation, which is currently {0}"
            .format(toleranceInterruptSimulation))

    rmg.modelSettingsList.append(
        ModelSettings(toleranceMoveToCore, toleranceMoveEdgeReactionToCore,
                      toleranceKeepInEdge, toleranceInterruptSimulation,
                      toleranceMoveEdgeReactionToSurface,
                      toleranceMoveSurfaceSpeciesToCore,
                      toleranceMoveSurfaceReactionToCore,
                      toleranceMoveEdgeReactionToSurfaceInterrupt,
                      toleranceMoveEdgeReactionToCoreInterrupt,
                      maximumEdgeSpecies, minCoreSizeForPrune,
                      minSpeciesExistIterationsForPrune, filterReactions,
                      ignoreOverallFluxCriterion, maxNumSpecies,
                      maxNumObjsPerIter, terminateAtMaxObjects,
                      toleranceThermoKeepSpeciesInEdge,
                      Quantity(dynamicsTimeScale)))
Ejemplo n.º 23
0
def species(label='', E0=None, states=None, thermo=None, transportData=None, molecularWeight=0.0, collisionModel=None, SMILES='', InChI=''):
    global speciesDict
    if label == '': raise InputError('Missing "label" attribute in species() block.')
    spec = Species(label=label, states=states, thermo=thermo, E0=E0, molecularWeight=molecularWeight, transportData=transportData, collisionModel=collisionModel)
    if InChI != '':
        spec.molecule = [Molecule(InChI=InChI)]
    elif SMILES != '':
        spec.molecule = [Molecule(SMILES=SMILES)]
    speciesDict[label] = spec
    logging.debug('Found species "{0}"'.format(spec))
    # If the molecular weight was not specified but the structure was, then
    # get the molecular weight from the structure
    if spec.molecularWeight.value_si == 0.0 and spec.molecule is not None and len(spec.molecule) > 0:
        spec.molecularWeight = Quantity(spec.molecule[0].getMolecularWeight(),"kg/mol")
Ejemplo n.º 24
0
def options(units='si',
            saveRestartPeriod=None,
            drawMolecules=False,
            generatePlots=False,
            saveSimulationProfiles=False,
            verboseComments=False,
            saveEdgeSpecies=False):
    rmg.units = units
    rmg.saveRestartPeriod = Quantity(
        saveRestartPeriod) if saveRestartPeriod else None
    rmg.drawMolecules = drawMolecules
    rmg.generatePlots = generatePlots
    rmg.saveSimulationProfiles = saveSimulationProfiles
    rmg.verboseComments = verboseComments
    rmg.saveEdgeSpecies = saveEdgeSpecies
Ejemplo n.º 25
0
def loadFAMEInput(path, moleculeDict=None):
    """
    Load the contents of a FAME input file into the MEASURE object. FAME
    is an early version of MEASURE written in Fortran and used by RMG-Java.
    This script enables importing FAME input files into MEASURE so we can
    use the additional functionality that MEASURE provides. Note that it
    is mostly designed to load the FAME input files generated automatically
    by RMG-Java, and may not load hand-crafted FAME input files. If you
    specify a `moleculeDict`, then this script will use it to associate
    the species with their structures.
    """
    
    def readMeaningfulLine(f):
        line = f.readline()
        while line != '':
            line = line.strip()
            if len(line) > 0 and line[0] != '#':
                return line
            else:
                line = f.readline()
        return ''

    moleculeDict = moleculeDict or {}

    logging.info('Loading file "{0}"...'.format(path))
    f = open(path)

    job = PressureDependenceJob(network=None)
    
    # Read method
    method = readMeaningfulLine(f).lower()
    if method == 'modifiedstrongcollision': 
        job.method = 'modified strong collision'
    elif method == 'reservoirstate': 
        job.method = 'reservoir state'

    # Read temperatures
    Tcount, Tunits, Tmin, Tmax = readMeaningfulLine(f).split()
    job.Tmin = Quantity(float(Tmin), Tunits) 
    job.Tmax = Quantity(float(Tmax), Tunits)
    job.Tcount = int(Tcount)
    Tlist = []
    for i in range(int(Tcount)):
        Tlist.append(float(readMeaningfulLine(f)))
    job.Tlist = Quantity(Tlist, Tunits)
    
    # Read pressures
    Pcount, Punits, Pmin, Pmax = readMeaningfulLine(f).split()
    job.Pmin = Quantity(float(Pmin), Punits) 
    job.Pmax = Quantity(float(Pmax), Punits)
    job.Pcount = int(Pcount)
    Plist = []
    for i in range(int(Pcount)):
        Plist.append(float(readMeaningfulLine(f)))
    job.Plist = Quantity(Plist, Punits)
    
    # Read interpolation model
    model = readMeaningfulLine(f).split()
    if model[0].lower() == 'chebyshev':
        job.interpolationModel = ('chebyshev', int(model[1]), int(model[2]))
    elif model[0].lower() == 'pdeparrhenius':
        job.interpolationModel = ('pdeparrhenius',)
    
    # Read grain size or number of grains
    job.minimumGrainCount = 0
    job.maximumGrainSize = None
    for i in range(2):
        data = readMeaningfulLine(f).split()
        if data[0].lower() == 'numgrains':
            job.minimumGrainCount = int(data[1])
        elif data[0].lower() == 'grainsize':
            job.maximumGrainSize = (float(data[2]), data[1])

    # A FAME file is almost certainly created during an RMG job, so use RMG mode
    job.rmgmode = True

    # Create the Network
    job.network = Network()

    # Read collision model
    data = readMeaningfulLine(f)
    assert data.lower() == 'singleexpdown'
    alpha0units, alpha0 = readMeaningfulLine(f).split()
    T0units, T0 = readMeaningfulLine(f).split()
    n = readMeaningfulLine(f)
    energyTransferModel = SingleExponentialDown(
        alpha0 = Quantity(float(alpha0), alpha0units),
        T0 = Quantity(float(T0), T0units),
        n = float(n),
    )
    
    speciesDict = {}

    # Read bath gas parameters
    bathGas = Species(label='bath_gas', energyTransferModel=energyTransferModel)
    molWtunits, molWt = readMeaningfulLine(f).split()
    if molWtunits == 'u': molWtunits = 'amu'
    bathGas.molecularWeight = Quantity(float(molWt), molWtunits)
    sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split()
    epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split()
    assert epsilonLJunits == 'J'
    bathGas.transportData = TransportData(
        sigma = Quantity(float(sigmaLJ), sigmaLJunits),
        epsilon = Quantity(float(epsilonLJ) / constants.kB, 'K'),
    )
    job.network.bathGas = {bathGas: 1.0}
    
    # Read species data
    Nspec = int(readMeaningfulLine(f))
    for i in range(Nspec):
        species = Species()
        species.conformer = Conformer()
        species.energyTransferModel = energyTransferModel
        
        # Read species label
        species.label = readMeaningfulLine(f)
        speciesDict[species.label] = species
        if species.label in moleculeDict:
            species.molecule = [moleculeDict[species.label]]
        
        # Read species E0
        E0units, E0 = readMeaningfulLine(f).split()
        species.conformer.E0 = Quantity(float(E0), E0units)
        species.conformer.E0.units = 'kJ/mol'
        
        # Read species thermo data
        H298units, H298 = readMeaningfulLine(f).split()
        S298units, S298 = readMeaningfulLine(f).split()
        Cpcount, Cpunits = readMeaningfulLine(f).split()
        Cpdata = []
        for i in range(int(Cpcount)):
            Cpdata.append(float(readMeaningfulLine(f)))
        if S298units == 'J/mol*K': S298units = 'J/(mol*K)'
        if Cpunits == 'J/mol*K': Cpunits = 'J/(mol*K)'
        species.thermo = ThermoData(
            H298 = Quantity(float(H298), H298units),
            S298 = Quantity(float(S298), S298units),
            Tdata = Quantity([300,400,500,600,800,1000,1500], "K"),
            Cpdata = Quantity(Cpdata, Cpunits),
            Cp0 = (Cpdata[0], Cpunits),
            CpInf = (Cpdata[-1], Cpunits),
        )
        
        # Read species collision parameters
        molWtunits, molWt = readMeaningfulLine(f).split()
        if molWtunits == 'u': molWtunits = 'amu'
        species.molecularWeight = Quantity(float(molWt), molWtunits)
        sigmaLJunits, sigmaLJ = readMeaningfulLine(f).split()
        epsilonLJunits, epsilonLJ = readMeaningfulLine(f).split()
        assert epsilonLJunits == 'J'
        species.transportData = TransportData(
            sigma = Quantity(float(sigmaLJ), sigmaLJunits),
            epsilon = Quantity(float(epsilonLJ) / constants.kB, 'K'),
        )
        
        # Read species vibrational frequencies
        freqCount, freqUnits = readMeaningfulLine(f).split()
        frequencies = []
        for j in range(int(freqCount)):
            frequencies.append(float(readMeaningfulLine(f)))
        species.conformer.modes.append(HarmonicOscillator(
            frequencies = Quantity(frequencies, freqUnits),
        ))
        
        # Read species external rotors
        rotCount, rotUnits = readMeaningfulLine(f).split()
        if int(rotCount) > 0:
            raise NotImplementedError('Cannot handle external rotational modes in FAME input.')
        
        # Read species internal rotors
        freqCount, freqUnits = readMeaningfulLine(f).split()
        frequencies = []
        for j in range(int(freqCount)):
            frequencies.append(float(readMeaningfulLine(f)))
        barrCount, barrUnits = readMeaningfulLine(f).split()
        barriers = []
        for j in range(int(barrCount)):
            barriers.append(float(readMeaningfulLine(f)))
        if barrUnits == 'cm^-1':
            barrUnits = 'J/mol'
            barriers = [barr * constants.h * constants.c * constants.Na * 100. for barr in barriers]
        elif barrUnits in ['Hz', 's^-1']:
            barrUnits = 'J/mol'
            barriers = [barr * constants.h * constants.Na for barr in barriers]
        elif barrUnits != 'J/mol':
            raise Exception('Unexpected units "{0}" for hindered rotor barrier height.'.format(barrUnits))
        inertia = [V0 / 2.0 / (nu * constants.c * 100.)**2 / constants.Na for nu, V0 in zip(frequencies, barriers)]
        for I, V0 in zip(inertia, barriers):
            species.conformer.modes.append(HinderedRotor(
                inertia = Quantity(I,"kg*m^2"), 
                barrier = Quantity(V0,barrUnits), 
                symmetry = 1,
                semiclassical = False,
            ))
            
        # Read overall symmetry number
        species.conformer.spinMultiplicity = int(readMeaningfulLine(f))
        
    # Read isomer, reactant channel, and product channel data
    Nisom = int(readMeaningfulLine(f))
    Nreac = int(readMeaningfulLine(f))
    Nprod = int(readMeaningfulLine(f))
    for i in range(Nisom):
        data = readMeaningfulLine(f).split()
        assert data[0] == '1'
        job.network.isomers.append(speciesDict[data[1]])
    for i in range(Nreac):
        data = readMeaningfulLine(f).split()
        assert data[0] == '2'
        job.network.reactants.append([speciesDict[data[1]], speciesDict[data[2]]])
    for i in range(Nprod):
        data = readMeaningfulLine(f).split()
        if data[0] == '1':
            job.network.products.append([speciesDict[data[1]]])
        elif data[0] == '2':
            job.network.products.append([speciesDict[data[1]], speciesDict[data[2]]])

    # Read path reactions
    Nrxn = int(readMeaningfulLine(f))
    for i in range(Nrxn):
        
        # Read and ignore reaction equation
        equation = readMeaningfulLine(f)
        reaction = Reaction(transitionState=TransitionState(), reversible=True)
        job.network.pathReactions.append(reaction)
        reaction.transitionState.conformer = Conformer()
        
        # Read reactant and product indices
        data = readMeaningfulLine(f).split()
        reac = int(data[0]) - 1
        prod = int(data[1]) - 1
        if reac < Nisom:
            reaction.reactants = [job.network.isomers[reac]]
        elif reac < Nisom+Nreac:
            reaction.reactants = job.network.reactants[reac-Nisom]
        else:
            reaction.reactants = job.network.products[reac-Nisom-Nreac]
        if prod < Nisom:
            reaction.products = [job.network.isomers[prod]]
        elif prod < Nisom+Nreac:
            reaction.products = job.network.reactants[prod-Nisom]
        else:
            reaction.products = job.network.products[prod-Nisom-Nreac]
        
        # Read reaction E0
        E0units, E0 = readMeaningfulLine(f).split()
        reaction.transitionState.conformer.E0 = Quantity(float(E0), E0units)
        reaction.transitionState.conformer.E0.units = 'kJ/mol'
        
        # Read high-pressure limit kinetics
        data = readMeaningfulLine(f)
        assert data.lower() == 'arrhenius'
        Aunits, A = readMeaningfulLine(f).split()
        if '/' in Aunits:
            index = Aunits.find('/')
            Aunits = '{0}/({1})'.format(Aunits[0:index], Aunits[index+1:])
        Eaunits, Ea = readMeaningfulLine(f).split()
        n = readMeaningfulLine(f)
        reaction.kinetics = Arrhenius(
            A = Quantity(float(A), Aunits),
            Ea = Quantity(float(Ea), Eaunits),
            n = Quantity(float(n)),
        )
        reaction.kinetics.Ea.units = 'kJ/mol'

    f.close()
    
    job.network.isomers = [Configuration(isomer) for isomer in job.network.isomers]
    job.network.reactants = [Configuration(*reactants) for reactants in job.network.reactants]
    job.network.products = [Configuration(*products) for products in job.network.products]

    return job
Ejemplo n.º 26
0
    def processOldLibraryEntry(self, data):
        """
        Process a list of parameters `data` as read from an old-style RMG
        thermo database, returning the corresponding kinetics object.
        """

        # The names of all of the RMG reaction families that are bimolecular
        BIMOLECULAR_KINETICS_FAMILIES = [
            'H_Abstraction',
            'R_Addition_MultipleBond',
            'R_Recombination',
            'Disproportionation',
            '1+2_Cycloaddition',
            '2+2_cycloaddition_Cd',
            '2+2_cycloaddition_CO',
            '2+2_cycloaddition_CCO',
            'Diels_alder_addition',
            '1,2_Insertion',
            '1,3_Insertion_CO2',
            '1,3_Insertion_ROR',
            'R_Addition_COm',
            'Oa_R_Recombination',
            'Substitution_O',
            'SubstitutionS',
            'R_Addition_CSm',
            '1,3_Insertion_RSR',
            'lone_electron_pair_bond',
        ]

        # The names of all of the RMG reaction families that are unimolecular
        UNIMOLECULAR_KINETICS_FAMILIES = [
            'intra_H_migration', 'Birad_recombination', 'intra_OH_migration',
            'HO2_Elimination_from_PeroxyRadical', 'H_shift_cyclopentadiene',
            'Cyclic_Ether_Formation', 'Intra_R_Add_Exocyclic',
            'Intra_R_Add_Endocyclic', '1,2-Birad_to_alkene',
            'Intra_Disproportionation', 'Korcek_step1', 'Korcek_step2',
            '1,2_shiftS', 'intra_substitutionCS_cyclization',
            'intra_substitutionCS_isomerization',
            'intra_substitutionS_cyclization',
            'intra_substitutionS_isomerization', 'intra_NO2_ONO_conversion',
            '1,4_Cyclic_birad_scission', '1,4_Linear_birad_scission',
            'Intra_Diels_alder', 'ketoenol', 'Retroen'
        ]
        # This is hardcoding of reaction families!
        label = os.path.split(self.label)[-2]
        if label in BIMOLECULAR_KINETICS_FAMILIES:
            Aunits = 'cm^3/(mol*s)'
        elif label in UNIMOLECULAR_KINETICS_FAMILIES:
            Aunits = 's^-1'
        else:
            raise Exception(
                'Unable to determine preexponential units for old reaction family "{0}".'
                .format(self.label))

        try:
            Tmin, Tmax = data[0].split('-')
            Tmin = (float(Tmin), "K")
            Tmax = (float(Tmax), "K")
        except ValueError:
            Tmin = (float(data[0]), "K")
            Tmax = None

        A, n, alpha, E0, dA, dn, dalpha, dE0 = data[1:9]

        A = float(A)
        if dA[0] == '*':
            A = Quantity(A, Aunits, '*|/', float(dA[1:]))
        else:
            dA = float(dA)
            if dA != 0:
                A = Quantity(A, Aunits, '+|-', dA)
            else:
                A = Quantity(A, Aunits)

        n = float(n)
        dn = float(dn)
        if dn != 0:
            n = Quantity(n, '', '+|-', dn)
        else:
            n = Quantity(n, '')

        alpha = float(alpha)
        dalpha = float(dalpha)
        if dalpha != 0:
            alpha = Quantity(alpha, '', '+|-', dalpha)
        else:
            alpha = Quantity(alpha, '')

        E0 = float(E0)
        dE0 = float(dE0)
        if dE0 != 0:
            E0 = Quantity(E0, 'kcal/mol', '+|-', dE0)
        else:
            E0 = Quantity(E0, 'kcal/mol')

        rank = int(data[9])

        return ArrheniusEP(A=A, n=n, alpha=alpha, E0=E0, Tmin=Tmin,
                           Tmax=Tmax), rank
Ejemplo n.º 27
0
def render_thermo_math(thermo, user=None):
    """
    Return a math representation of the given `thermo` using jsMath. If a 
    `user` is specified, the user's preferred units will be used; otherwise 
    default units will be used.
    """
    # Define other units and conversion factors to use
    if user and user.is_authenticated():
        user_profile = UserProfile.objects.get(user=user)
        Tunits = str(user_profile.temperatureUnits)
        Punits = str(user_profile.pressureUnits)
        Cpunits = str(user_profile.heatCapacityUnits)
        Hunits = str(user_profile.energyUnits)
        Sunits = str(user_profile.heatCapacityUnits)
        Gunits = str(user_profile.energyUnits)
    else:
        Tunits = 'K'
        Punits = 'bar'
        Cpunits = 'cal/(mol*K)'
        Hunits = 'kcal/mol'
        Sunits = 'cal/(mol*K)'
        Gunits = 'kcal/mol'
    Tfactor = Quantity(1, Tunits).getConversionFactorFromSI()
    Pfactor = Quantity(1, Punits).getConversionFactorFromSI()
    Cpfactor = Quantity(1, Cpunits).getConversionFactorFromSI()
    Hfactor = Quantity(1, Hunits).getConversionFactorFromSI()
    Sfactor = Quantity(1, Sunits).getConversionFactorFromSI()
    Gfactor = Quantity(1, Gunits).getConversionFactorFromSI()
    
    # The string that will be returned to the template
    result = ''
    
    if isinstance(thermo, ThermoData):
        # The thermo is in ThermoData format
        result += '<table class="thermoEntryData">\n'
        
        if thermo.H298 is not None:
            result += '<tr>'
            result += r'    <td class="key"><span class="math">\Delta H_\mathrm{f}^\circ(298 \ \mathrm{K})</span></td>'
            result += r'    <td class="equals">=</td>'
            result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s} }}</span></td>'.format(thermo.H298.value_si * Hfactor, Hunits)
            result += '</tr>\n'
        
        if thermo.S298 is not None:
            result += '<tr>'
            result += r'    <td class="key"><span class="math">\Delta S_\mathrm{f}^\circ(298 \ \mathrm{K})</span></td>'
            result += r'    <td class="equals">=</td>'
            result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s} }}</span></td>'.format(thermo.S298.value_si * Sfactor, Sunits)
            result += '</tr>\n'
        if thermo.Tdata is not None and thermo.Cpdata is not None:
            for T, Cp in zip(thermo.Tdata.value_si, thermo.Cpdata.value_si):
                result += '<tr>'
                result += r'    <td class="key"><span class="math">C_\mathrm{{p}}^\circ({0:g} \ \mathrm{{ {1!s} }})</span></td>'.format(T * Tfactor, Tunits)
                result += r'    <td class="equals">=</td>'
                result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s} }}</span></td>'.format(Cp * Cpfactor, Cpunits)
                result += '</tr>\n'
        result += '</table>\n'
    
    elif isinstance(thermo, Wilhoit):
        # The thermo is in Wilhoit format
        result += '<div class="math">\n'
        result += r'\begin{split}'
        result += r'C_\mathrm{p}(T) &= C_\mathrm{p}(0) + \left[ C_\mathrm{p}(\infty) -'
        result += r'    C_\mathrm{p}(0) \right] y^2 \left[ 1 + (y - 1) \sum_{i=0}^3 a_i y^i \right] \\'
        result += r'H^\circ(T) &= H_0 + \int_0^\infty C_\mathrm{p}(T) \ dT \\'
        result += r'S^\circ(T) &= S_0 + \int_0^\infty \frac{C_\mathrm{p}(T)}{T} \ dT\\'
        result += r'y &\equiv \frac{T}{T + B}'
        result += r'\end{split}'
        result += '</div>\n'

        result += '<table class="thermoEntryData">\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">C_\mathrm{p}(0)</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s}  }}</span></td>'.format(thermo.cp0.value_si * Cpfactor, Cpunits)
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">C_\mathrm{p}(\infty)</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s} }}</span></td>'.format(thermo.cpInf.value_si * Cpfactor, Cpunits)
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_0</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(thermo.a0))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_1</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(thermo.a1))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_2</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(thermo.a2))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_3</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(thermo.a3))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">H_0</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s} }}</span></td>'.format(thermo.H0.value_si * Hfactor, Hunits)
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">S_0</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s} }}</span></td>'.format(thermo.S0.value_si * Sfactor, Sunits)
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">B</span></td>'
        result += r'    <td class="equals">=</td>'
        result += r'    <td class="value"><span class="math">{0:.2f} \ \mathrm{{ {1!s} }}</span></td>'.format(thermo.B.value_si * Tfactor, Tunits)
        result += '</tr>\n'
        result += '</table>\n'
    
    elif isinstance(thermo, NASA):
        # The thermo is in NASA format
        result += '<div class="math">\n'
        result += r'\frac{C_\mathrm{p}^\circ(T)}{R} = a_{-2} T^{-2} + a_{-1} T^{-1} + a_0 + a_1 T + a_2 T^2 + a_3 T^3 + a_4 T^4'
        result += '</div>\n'
        result += '<div class="math">\n'
        result += r'\frac{H^\circ(T)}{RT} = -a_{-2} T^{-2} + a_{-1} \frac{\ln T}{T} + a_0 + \frac{1}{2} a_1 T + \frac{1}{3} a_2 T^2 + \frac{1}{4} a_3 T^3 + \frac{1}{5} a_4 T^4 + \frac{a_5}{T}'
        result += '</div>\n'
        result += '<div class="math">\n'
        result += r'\frac{S^\circ(T)}{R} = -\frac{1}{2} a_{-2} T^{-2} - a_{-1} T^{-1} + a_0 \ln T + a_1 T + \frac{1}{2} a_2 T^2 + \frac{1}{3} a_3 T^3 + \frac{1}{4} a_4 T^4 + a_6'
        result += '</div>\n'

        result += '<table class="thermoEntryData">\n'
        result += '<tr>'
        result += r'    <td class="key">Temperature range</td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value">{0:g} to {1:g} {2!s}</td>'.format(polynomial.Tmin.value_si * Tfactor, polynomial.Tmax.value_si * Tfactor, Tunits)
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_{-2}</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.cm2))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_{-1}</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.cm1))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_0</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.c0))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_1</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.c1))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_2</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.c2))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_3</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.c3))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_4</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.c4))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_5</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.c5))
        result += '</tr>\n'
        result += '<tr>'
        result += r'    <td class="key"><span class="math">a_6</span></td>'
        result += r'    <td class="equals">=</td>'
        for polynomial in thermo.polynomials:
            result += r'    <td class="value"><span class="math">{0!s}</span></td>'.format(getLaTeXScientificNotation(polynomial.c6))
        result += '</tr>\n'
        result += '</table>\n'
    
    elif isinstance(thermo, list):
        # The thermo is a link
        index = thermo[1]
        url = reverse('database.views.thermoEntry', {'section': section, 'subsection': subsection, 'index': index})
        result += '<table class="thermoEntryData">\n'
        result += '<tr>'
        result += r'    <td class="key">Link:</td>'
        result += r'    <td class="value"><a href="{0!s}">{1}</a></td>'.format(url, index)
        result += '</tr>\n'
        result += '<\table>\n'
    
    # Temperature range
    if isinstance(thermo, (ThermoData, Wilhoit, NASA)):
        result += '<table class="thermoEntryData">'
        if thermo.Tmin is not None and thermo.Tmax is not None:
            result += '<tr><td class="key">Temperature range</td><td class="equals">=</td><td class="value">{0:g} to {1:g} {2!s}</td></tr>'.format(thermo.Tmin.value_si, thermo.Tmax.value_si, Tunits)
        result += '</table>'

    return mark_safe(result)
Ejemplo n.º 28
0
def get_thermo_data(thermo, user=None):
    """
    Generate and return a set of thermodynamics data suitable for plotting
    using Highcharts. If a `user` is specified, the user's preferred units
    will be used; otherwise default units will be used.
    """
    
    if not isinstance(thermo, (ThermoData, Wilhoit, NASA)):
        return ''
    
    # Define other units and conversion factors to use
    if user and user.is_authenticated():
        user_profile = UserProfile.objects.get(user=user)
        Tunits = str(user_profile.temperatureUnits)
        Punits = str(user_profile.pressureUnits)
        Cpunits = str(user_profile.heatCapacityUnits)
        Hunits = str(user_profile.energyUnits)
        Sunits = str(user_profile.heatCapacityUnits)
        Gunits = str(user_profile.energyUnits)
    else:
        Tunits = 'K'
        Punits = 'bar'
        Cpunits = 'cal/(mol*K)'
        Hunits = 'kcal/mol'
        Sunits = 'cal/(mol*K)'
        Gunits = 'kcal/mol'
    Tfactor = Quantity(1, Tunits).getConversionFactorFromSI()
    Pfactor = Quantity(1, Punits).getConversionFactorFromSI()
    Cpfactor = Quantity(1, Cpunits).getConversionFactorFromSI()
    Hfactor = Quantity(1, Hunits).getConversionFactorFromSI()
    Sfactor = Quantity(1, Sunits).getConversionFactorFromSI()
    Gfactor = Quantity(1, Gunits).getConversionFactorFromSI()
        
    if thermo.Tmin is not None and thermo.Tmax is not None:
        Tmin = thermo.Tmin.value_si
        Tmax = thermo.Tmax.value_si
    elif isinstance(thermo, ThermoData) and (thermo.Cp0 is None or thermo.CpInf is None):
        Tmin = 300
        Tmax = 1500
    else:
        Tmin = 300
        Tmax = 2000
    Tdata = []; Cpdata = []; Hdata = []; Sdata = []; Gdata = []
    
    try:
        for T in numpy.arange(Tmin, Tmax+1, 10):
            Tdata.append(T * Tfactor)
            Cpdata.append(thermo.getHeatCapacity(T) * Cpfactor)
            Hdata.append(thermo.getEnthalpy(T) * Hfactor)
            Sdata.append(thermo.getEntropy(T) * Sfactor)
            Gdata.append(thermo.getFreeEnergy(T) * Gfactor)
    
        return mark_safe("""
    Tlist = {0};
    Cplist = {1};
    Hlist = {2};
    Slist = {3};
    Glist = {4};
    Tunits = "{5!s}";
    Cpunits = "{6!s}";
    Hunits = "{7!s}";
    Sunits = "{8!s}";
    Gunits = "{9!s}";
        """.format(
            Tdata,
            Cpdata, 
            Hdata,
            Sdata, 
            Gdata, 
            Tunits, 
            Cpunits, 
            Hunits,
            Sunits,
            Gunits,
    ))
    except:
        # don't fail completely if thermo data is incomplete
        return ''
Ejemplo n.º 29
0
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    #
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     #
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         #
# DEALINGS IN THE SOFTWARE.                                                   #
#                                                                             #
###############################################################################

"""
This module contains information related to kinetic uncertainties
"""

from rmgpy.quantity import Quantity

rank_accuracy_map ={1:(0.0,'kcal/mol'),
                  2:(0.5,'kcal/mol'),
                  3:(1.0,'kcal/mol'),
                  4:(1.5,'kcal/mol'),
                  5:(2.5,'kcal/mol'),
                  6:(3.5,'kcal/mol'),
                  7:(4.0,'kcal/mol'),
                  8:(5.0,'kcal/mol'),
                  9:(14.0,'kcal/mol'),
                  10:(14.0,'kcal/mol'),
                  None:(14.0,'kcal/mol'),
                  0:(14.0,'kcal/mol'),
                  11:(14.0,'kcal/mol'),
                  }
rank_accuracy_map = {key:Quantity(value) for key,value in rank_accuracy_map.iteritems()}
Ejemplo n.º 30
0
def generateCanteraConditions(reactorTypeList,
                              reactionTimeList,
                              molFracList,
                              Tlist=None,
                              Plist=None,
                              Vlist=None):
    """
        Creates a list of cantera conditions from from the arguments provided. 
        
        ======================= ====================================================
        Argument                Description
        ======================= ====================================================
        `reactorTypeList`        A list of strings of the cantera reactor type. List of supported types below:
            IdealGasReactor: A constant volume, zero-dimensional reactor for ideal gas mixtures
            IdealGasConstPressureReactor: A homogeneous, constant pressure, zero-dimensional reactor for ideal gas mixtures
            IdealGasConstPressureTemperatureReactor: A homogenous, constant pressure and constant temperature, zero-dimensional reactor 
                                for ideal gas mixtures (the same as RMG's SimpleReactor)

        `reactionTimeList`      A tuple object giving the ([list of reaction times], units)
        `molFracList`           A list of molfrac dictionaries with species object keys
                               and mole fraction values
        To specify the system for an ideal gas, you must define 2 of the following 3 parameters:
        `T0List`                A tuple giving the ([list of initial temperatures], units)
        'P0List'                A tuple giving the ([list of initial pressures], units)
        'V0List'                A tuple giving the ([list of initial specific volumes], units)
    
        
        This saves all the reaction conditions into the Cantera class.
        """

    # Create individual ScalarQuantity objects for Tlist, Plist, Vlist, and reactionTimeList
    if Tlist:
        Tlist = Quantity(
            Tlist)  # Be able to create a Quantity object from it first
        Tlist = [(Tlist.value[i], Tlist.units)
                 for i in range(len(Tlist.value))]
    if Plist:
        Plist = Quantity(Plist)
        Plist = [(Plist.value[i], Plist.units)
                 for i in range(len(Plist.value))]
    if Vlist:
        Vlist = Quantity(Vlist)
        Vlist = [(Vlist.value[i], Vlist.units)
                 for i in range(len(Vlist.value))]
    if reactionTimeList:
        reactionTimeList = Quantity(reactionTimeList)
        reactionTimeList = [(reactionTimeList.value[i], reactionTimeList.units)
                            for i in range(len(reactionTimeList.value))]

    conditions = []

    if Tlist is None:
        for reactorType in reactorTypeList:
            for reactionTime in reactionTimeList:
                for molFrac in molFracList:
                    for P in Plist:
                        for V in Vlist:
                            conditions.append(
                                CanteraCondition(reactorType,
                                                 reactionTime,
                                                 molFrac,
                                                 P0=P,
                                                 V0=V))

    elif Plist is None:
        for reactorType in reactorTypeList:
            for reactionTime in reactionTimeList:
                for molFrac in molFracList:
                    for T in Tlist:
                        for V in Vlist:
                            conditions.append(
                                CanteraCondition(reactorType,
                                                 reactionTime,
                                                 molFrac,
                                                 T0=T,
                                                 V0=V))

    elif Vlist is None:
        for reactorType in reactorTypeList:
            for reactionTime in reactionTimeList:
                for molFrac in molFracList:
                    for T in Tlist:
                        for P in Plist:
                            conditions.append(
                                CanteraCondition(reactorType,
                                                 reactionTime,
                                                 molFrac,
                                                 T0=T,
                                                 P0=P))

    else:
        raise Exception(
            "Cantera conditions must leave one of T0, P0, and V0 state variables unspecified"
        )
    return conditions