Пример #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
Пример #2
0
def options(units='si',
            saveRestartPeriod=None,
            generateOutputHTML=False,
            generatePlots=False,
            saveSimulationProfiles=False,
            verboseComments=False,
            saveEdgeSpecies=False):
    rmg.units = units
    rmg.saveRestartPeriod = Quantity(
        saveRestartPeriod) if saveRestartPeriod else None
    rmg.generateOutputHTML = generateOutputHTML
    rmg.generatePlots = generatePlots
    rmg.saveSimulationProfiles = saveSimulationProfiles
    rmg.verboseComments = verboseComments
    rmg.saveEdgeSpecies = saveEdgeSpecies
Пример #3
0
def simpleReactor(temperature,
                  pressure,
                  initialMoleFractions,
                  terminationConversion=None,
                  terminationTime=None,
                  sensitivity=None,
                  sensitivityThreshold=1e-3):
    logging.debug('Found SimpleReactor reaction system')

    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))

    sensitivitySpecies = []
    if sensitivity:
        for spec in sensitivity:
            sensitivitySpecies.append(speciesDict[spec])
    system = SimpleReactor(T, P, initialMoleFractions, termination,
                           sensitivitySpecies, sensitivityThreshold)
    rmg.reactionSystems.append(system)
Пример #4
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, filterThreshold=1e8, ignoreOverallFluxCriterion=False,
          maxNumSpecies=None,maxNumObjsPerIter=1,terminateAtMaxObjects=False,toleranceThermoKeepSpeciesInEdge=numpy.inf,dynamicsTimeScale=(0.0,'sec'),
          toleranceBranchReactionToCore=0.0, branchingIndex=0.5, branchingRatioMax=1.0):
    """
    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=toleranceMoveToCore,
            toleranceMoveEdgeReactionToCore=toleranceMoveEdgeReactionToCore,
            toleranceKeepInEdge=toleranceKeepInEdge,
            toleranceInterruptSimulation=toleranceInterruptSimulation,
            toleranceMoveEdgeReactionToSurface=toleranceMoveEdgeReactionToSurface,
            toleranceMoveSurfaceSpeciesToCore=toleranceMoveSurfaceSpeciesToCore,
            toleranceMoveSurfaceReactionToCore=toleranceMoveSurfaceReactionToCore,
            toleranceMoveEdgeReactionToSurfaceInterrupt=toleranceMoveEdgeReactionToSurfaceInterrupt,
            toleranceMoveEdgeReactionToCoreInterrupt=toleranceMoveEdgeReactionToCoreInterrupt,
            maximumEdgeSpecies=maximumEdgeSpecies,
            minCoreSizeForPrune=minCoreSizeForPrune,
            minSpeciesExistIterationsForPrune=minSpeciesExistIterationsForPrune,
            filterReactions=filterReactions,
            filterThreshold=filterThreshold,
            ignoreOverallFluxCriterion=ignoreOverallFluxCriterion,
            maxNumSpecies=maxNumSpecies,
            maxNumObjsPerIter=maxNumObjsPerIter,
            terminateAtMaxObjects=terminateAtMaxObjects,
            toleranceThermoKeepSpeciesInEdge=toleranceThermoKeepSpeciesInEdge,
            dynamicsTimeScale=Quantity(dynamicsTimeScale),
            toleranceBranchReactionToCore=toleranceBranchReactionToCore,
            branchingIndex=branchingIndex,
            branchingRatioMax=branchingRatioMax,
        )
    )
Пример #5
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, ArrheniusBM,
                             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.rate_coefficient_units
    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).get_conversion_factor_from_si()

        return kunits, kunits_low, kfactor
Пример #6
0
def options(name='Seed', generateSeedEachIteration=False, 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
Пример #7
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]'])
    
    logging.info('Running thermo sensitivity analysis using finite differences...')
    for index, species in enumerate(speciesList):
        species_index = index + 1
        species_string = getSpeciesIdentifier(species)
        logging.info('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])
Пример #8
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)
Пример #9
0
    def __init__(self, reactor_type, reaction_time, mol_frac, T0=None, P0=None, V0=None):
        self.reactor_type = reactor_type
        self.reaction_time = Quantity(reaction_time)

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

        self.mol_frac = mol_frac

        # 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
Пример #10
0
class CanteraCondition:
    """
    This class organizes the inputs needed for a cantera simulation

    ======================= ====================================================
    Attribute               Description
    ======================= ====================================================
    `reactorType`           A string 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)

    `reactionTime`          A tuple object giving the (reaction time, units)
    `molFrac`               A dictionary giving the initial mol Fractions. Keys are species objects and the values are floats

    To specify the system for an ideal gas, you must define 2 of the following 3 parameters:
    `T0`                    A tuple giving the (initial temperature, units) which reconstructs a Quantity object
    'P0'                    A tuple giving the (initial pressure, units) which reconstructs a Quantity object
    'V0'                    A tuple giving the (initial specific volume, units) which reconstructs a Quantity object
    ======================= ====================================================


    """
    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


    def __repr__(self):
        """
        Return a string representation that can be used to reconstruct the
        object.
        """
        string="CanteraCondition("
        string += 'reactorType="{0}", '.format(self.reactorType)
        string += 'reactionTime={}, '.format(self.reactionTime.__repr__())
        string += 'molFrac={0}, '.format(self.molFrac.__repr__())
        if self.T0: string += 'T0={}, '.format(self.T0.__repr__())
        if self.P0: string += 'P0={}, '.format(self.P0.__repr__())
        if self.V0: string += 'V0={}, '.format(self.V0__repr__())
        string = string[:-2] + ')'
        return string

    def __str__(self):
        """
        Return a string representation of the condition.
        """
        string=""
        string += 'Reactor Type: {0}\n'.format(self.reactorType)
        string += 'Reaction Time: {}\n'.format(self.reactionTime)
        if self.T0: string += 'T0: {}\n'.format(self.T0)
        if self.P0: string += 'P0: {}\n'.format(self.P0)
        if self.V0: string += 'V0: {}\n'.format(self.V0)
        #ConvertMolFrac to SMILES for keys for display
        prettyMolFrac={}
        for key, value in self.molFrac.iteritems():
            prettyMolFrac[key.molecule[0].toSMILES()]=value
        string += 'Initial Mole Fractions: {0}'.format(prettyMolFrac.__repr__())
        return string
Пример #11
0
def loadChemkinOutput(outputFile, reactionModel):
    """
    Load the species concentrations from a Chemkin Output file in a simulation
    and generate the reaction rates at each time point.
    """
    import rmgpy.constants as constants
    from rmgpy.quantity import Quantity

    coreReactions = reactionModel.core.reactions
    edgeReactions = reactionModel.edge.reactions
    speciesList = reactionModel.core.species

    time = []
    coreSpeciesConcentrations = []
    coreReactionRates = []
    edgeReactionRates = []

    with open(outputFile, 'r') as f:

        line = f.readline()
        while line != '' and 'SPECIFIED END' not in line:
            line.strip()
            tokens = line.split()
            if ' TIME ' in line:
                # Time is in seconds
                time.append(float(tokens[-2]))
            elif ' PRESSURE ' in line:
                # Pressure from Chemkin is in atm
                P = Quantity(float(tokens[-2]), 'atm')
            elif ' TEMPERATURE ' in line:
                # Temperature from Chemkin in in K
                T = Quantity(float(tokens[-2]), 'K')
            elif ' MOLE FRACTIONS ' in line:
                # Species always come in the same order as listed in chem.inp
                molefractions = []
                line = f.readline(
                )  # This one reads the blank line which follows
                line = f.readline()
                while line.strip() != '':
                    tokens = line.split()
                    for value in tokens[2::3]:

                        # Make all concentrations positive
                        if value.find('-') == 0:
                            value = value.replace('-', '', 1)
                        # Sometimes chemkin removes the `E` in scientific notation due to lack of space,
                        # rendering invalid float values.  If this is the case, add it in.
                        if value.find('-') != -1:
                            if value.find('E') == -1:
                                value = value.replace('-', 'E-')

                        molefractions.append(float(value))

                    line = f.readline()

                totalConcentration = P.value_si / constants.R / T.value_si
                coreSpeciesConcentrations.append([
                    molefrac * totalConcentration for molefrac in molefractions
                ])
                coreRates = []
                edgeRates = []
                for reaction in coreReactions:
                    rate = reaction.getRateCoefficient(T.value_si, P.value_si)
                    for reactant in reaction.reactants:
                        rate *= molefractions[speciesList.index(
                            reactant)] * totalConcentration
                    coreRates.append(rate)
                for reaction in edgeReactions:
                    edgeRates.append(
                        reaction.getRateCoefficient(T.value_si, P.value_si))

                if coreRates:
                    coreReactionRates.append(coreRates)
                if edgeRates:
                    edgeReactionRates.append(edgeRates)

            line = f.readline()

    time = numpy.array(time)
    coreSpeciesConcentrations = numpy.array(coreSpeciesConcentrations)
    coreReactionRates = numpy.array(coreReactionRates)
    edgeReactionRates = numpy.array(edgeReactionRates)

    return time, coreSpeciesConcentrations, coreReactionRates, edgeReactionRates
Пример #12
0
    def sensitivity_analysis(self,
                             initial_mole_fractions,
                             sensitive_species,
                             T,
                             P,
                             termination_time,
                             sensitivity_threshold=1e-3,
                             number=10,
                             fileformat='.png'):
        """
        Run sensitivity analysis using the RMG solver in a single ReactionSystem object
        
        initial_mole_fractions is a dictionary with Species objects as keys and mole fraction initial conditions
        sensitive_species 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.rmg.listener import SimulationProfileWriter, SimulationProfilePlotter
        from rmgpy.rmg.settings import ModelSettings, SimulatorSettings
        T = Quantity(T)
        P = Quantity(P)
        termination = [TerminationTime(Quantity(termination_time))]

        reaction_system = SimpleReactor(
            T=T,
            P=P,
            initial_mole_fractions=initial_mole_fractions,
            termination=termination,
            sensitive_species=sensitive_species,
            sensitivity_threshold=sensitivity_threshold)

        # Create the csv worksheets for logging sensitivity
        util.make_output_subdirectory(self.output_directory, 'solver')
        sens_worksheet = []
        reaction_system_index = 0
        for spec in reaction_system.sensitive_species:
            csvfile_path = os.path.join(
                self.output_directory, 'solver',
                'sensitivity_{0}_SPC_{1}.csv'.format(reaction_system_index + 1,
                                                     spec.index))
            sens_worksheet.append(csvfile_path)

        reaction_system.attach(
            SimulationProfileWriter(self.output_directory,
                                    reaction_system_index, self.species_list))
        reaction_system.attach(
            SimulationProfilePlotter(self.output_directory,
                                     reaction_system_index, self.species_list))

        simulator_settings = SimulatorSettings()  # defaults

        model_settings = ModelSettings()  # defaults
        model_settings.tol_move_to_core = 0.1
        model_settings.tol_interrupt_simulation = 1.0
        model_settings.tol_keep_in_edge = 0.0

        reaction_system.simulate(
            core_species=self.species_list,
            core_reactions=self.reaction_list,
            edge_species=[],
            edge_reactions=[],
            surface_species=[],
            surface_reactions=[],
            model_settings=model_settings,
            simulator_settings=simulator_settings,
            sensitivity=True,
            sens_worksheet=sens_worksheet,
        )

        plot_sensitivity(self.output_directory,
                         reaction_system_index,
                         reaction_system.sensitive_species,
                         number=number,
                         fileformat=fileformat)
Пример #13
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.
        """
        # 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
Пример #14
0
    def __init__(self,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 = Quantity((0.0,'sec'))):

        
        self.fluxToleranceKeepInEdge = toleranceKeepInEdge
        self.fluxToleranceMoveToCore = toleranceMoveToCore
        self.toleranceMoveEdgeReactionToCore = toleranceMoveEdgeReactionToCore
        self.fluxToleranceInterrupt = toleranceInterruptSimulation
        self.maximumEdgeSpecies = maximumEdgeSpecies
        self.minCoreSizeForPrune = minCoreSizeForPrune
        self.minSpeciesExistIterationsForPrune = minSpeciesExistIterationsForPrune
        self.filterReactions = filterReactions
        self.ignoreOverallFluxCriterion=ignoreOverallFluxCriterion
        self.toleranceMoveEdgeReactionToSurface = toleranceMoveEdgeReactionToSurface
        self.toleranceMoveSurfaceSpeciesToCore = toleranceMoveSurfaceSpeciesToCore
        self.toleranceMoveSurfaceReactionToCore = toleranceMoveSurfaceReactionToCore
        self.toleranceThermoKeepSpeciesInEdge = toleranceThermoKeepSpeciesInEdge
        self.terminateAtMaxObjects = terminateAtMaxObjects
        self.dynamicsTimeScale = dynamicsTimeScale.value_si
        
        if toleranceInterruptSimulation:
            self.fluxToleranceInterrupt = toleranceInterruptSimulation
        else:
            self.fluxToleranceInterrupt = toleranceMoveToCore
            
        if toleranceMoveEdgeReactionToSurfaceInterrupt:
            self.toleranceMoveEdgeReactionToSurfaceInterrupt = toleranceMoveEdgeReactionToSurfaceInterrupt
        else:
            self.toleranceMoveEdgeReactionToSurfaceInterrupt = toleranceMoveEdgeReactionToSurface
        
        if toleranceMoveEdgeReactionToCoreInterrupt:
            self.toleranceMoveEdgeReactionToCoreInterrupt = toleranceMoveEdgeReactionToCoreInterrupt
        else:
            self.toleranceMoveEdgeReactionToCoreInterrupt = toleranceMoveEdgeReactionToCore
            
        if maxNumSpecies:
            self.maxNumSpecies = maxNumSpecies
        else:
            self.maxNumSpecies = numpy.inf
        
        if maxNumObjsPerIter <= 0:
            self.maxNumObjsPerIter = numpy.inf
        else:
            self.maxNumObjsPerIter = maxNumObjsPerIter
Пример #15
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)
Пример #16
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()}
Пример #17
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
Пример #18
0
    def __init__(self,
                 tol_move_to_core=None,
                 tol_move_edge_rxn_to_core=np.inf,
                 tol_keep_in_edge=0.0,
                 tol_interrupt_simulation=1.0,
                 tol_move_edge_rxn_to_surface=np.inf,
                 tol_move_surface_spc_to_core=np.inf,
                 tol_move_surface_rxn_to_core=np.inf,
                 tol_move_edge_rxn_to_surface_interrupt=None,
                 tol_move_edge_rxn_to_core_interrupt=None,
                 maximum_edge_species=1000000,
                 min_core_size_for_prune=50,
                 min_species_exist_iterations_for_prune=2,
                 filter_reactions=False,
                 filter_threshold=1e8,
                 ignore_overall_flux_criterion=False,
                 max_num_species=None,
                 max_num_objects_per_iter=1,
                 terminate_at_max_objects=False,
                 thermo_tol_keep_spc_in_edge=np.inf,
                 dynamics_time_scale=Quantity((0.0, 'sec')),
                 tol_branch_rxn_to_core=0.0,
                 branching_index=0.5,
                 branching_ratio_max=1.0):

        self.tol_keep_in_edge = tol_keep_in_edge
        self.tol_move_to_core = tol_move_to_core
        self.tol_move_edge_rxn_to_core = tol_move_edge_rxn_to_core
        self.tol_interrupt_simulation = tol_interrupt_simulation
        self.maximum_edge_species = maximum_edge_species
        self.min_core_size_for_prune = min_core_size_for_prune
        self.min_species_exist_iterations_for_prune = min_species_exist_iterations_for_prune
        self.filter_reactions = filter_reactions
        self.filter_threshold = filter_threshold
        self.ignore_overall_flux_criterion = ignore_overall_flux_criterion
        self.tol_move_edge_rxn_to_surface = tol_move_edge_rxn_to_surface
        self.tol_move_surface_spc_to_core = tol_move_surface_spc_to_core
        self.tol_move_surface_rxn_to_core = tol_move_surface_rxn_to_core
        self.thermo_tol_keep_spc_in_edge = thermo_tol_keep_spc_in_edge
        self.terminate_at_max_objects = terminate_at_max_objects
        self.dynamics_time_scale = dynamics_time_scale.value_si
        self.tol_branch_rxn_to_core = tol_branch_rxn_to_core
        self.branching_index = branching_index
        self.branching_ratio_max = branching_ratio_max

        if tol_interrupt_simulation:
            self.tol_interrupt_simulation = tol_interrupt_simulation
        else:
            self.tol_interrupt_simulation = tol_move_to_core

        if tol_move_edge_rxn_to_surface_interrupt:
            self.tol_move_edge_rxn_to_surface_interrupt = tol_move_edge_rxn_to_surface_interrupt
        else:
            self.tol_move_edge_rxn_to_surface_interrupt = tol_move_edge_rxn_to_surface

        if tol_move_edge_rxn_to_core_interrupt:
            self.tol_move_edge_rxn_to_core_interrupt = tol_move_edge_rxn_to_core_interrupt
        else:
            self.tol_move_edge_rxn_to_core_interrupt = tol_move_edge_rxn_to_core

        if max_num_species:
            self.max_num_species = max_num_species
        else:
            self.max_num_species = np.inf

        if max_num_objects_per_iter <= 0:
            self.max_num_objects_per_iter = np.inf
        else:
            self.max_num_objects_per_iter = max_num_objects_per_iter
Пример #19
0
def render_states_math(states, user=None):
    """
    Return a math representation of the given `states` 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)
        Eunits = str(user_profile.energyUnits)
    else:
        Tunits = 'K'
        Eunits = 'kcal/mol'
    Tfactor = Quantity(1, Tunits).getConversionFactorFromSI()
    Efactor = Quantity(1, Eunits).getConversionFactorFromSI()

    # The string that will be returned to the template
    result = ''

    result += '<table class="reference">\n'

    hindIndex = 0
    for mode in states.modes:
        if isinstance(mode, Translation):
            result += '<tr>'
            result += r'    <td colspan="2" class="section">External translation</td>'
            result += '</tr>\n'
            result += '<tr>'
            result += r'    <td class="label">Mass (g/mol):</td>'
            result += r'    <td>{0:g}</td>'.format(mode.mass.value * 1000.)
            result += '</tr>\n'

        elif isinstance(mode, RigidRotor):
            result += '<tr>'
            result += r'    <td colspan="2" class="section">External rotation</td>'
            result += '</tr>\n'
            result += '<tr>'
            result += r'    <td class="label">Linearity:</td>'
            result += r'    <td>{0}</td>'.format(mode.linear)
            result += '</tr>\n'
            result += '<tr>'
            result += r'    <td class="label">Moments of inertia (amu&times;&Aring;^2):</td>'
            if mode.inertia.isArray():
                inertia = ', '.join([
                    '{0:.1f}'.format(I * constants.Na * 1e23)
                    for I in mode.inertia.values
                ])
            else:
                inertia = '{0:.1f}'.format(mode.inertia.value * constants.Na *
                                           1e23)
            result += r'    <td>{0!s}</td>'.format(inertia)
            result += '</tr>\n'
            result += '<tr>'
            result += r'    <td class="label">Symmetry number:</td>'
            result += r'    <td>{0:d}</td>'.format(mode.symmetry)
            result += '</tr>\n'

        elif isinstance(mode, HarmonicOscillator):
            result += '<tr>'
            result += r'    <td colspan="2" class="section">Vibrations</td>'
            result += '</tr>\n'
            result += '<tr>'
            frequencies = ', '.join(
                ['{0:.1f}'.format(freq) for freq in mode.frequencies.values])
            result += r'    <td class="label" class="section">Frequencies (cm^-1):</td>'
            result += r'    <td>{0!s}</td>'.format(frequencies)
            result += '</tr>\n'

        elif isinstance(mode, HinderedRotor):
            hindIndex += 1
            result += '<tr>'
            result += r'    <td colspan="2" class="section">Hindered rotor #{0:d}:</td>'.format(
                hindIndex)
            result += '</tr>\n'
            if mode.fourier:
                fourierA = ', '.join(
                    ['{0:g}'.format(a_k) for a_k in mode.fourier.values[0, :]])
                fourierB = ', '.join(
                    ['{0:g}'.format(b_k) for b_k in mode.fourier.values[1, :]])
                result += '<tr>'
                result += r'    <td colspan="2"><span class="math">V(\phi) = A + \sum_k \left( a_k \cos k \phi + b_k \sin k \phi \right)</span></td>'
                result += '</tr>\n'
                result += '<tr>'
                result += r'    <td class="label"><span class="math">a_k</span></td>'
                result += r'    <td>{0}</td>'.format(fourierA)
                result += '</tr>\n'
                result += '<tr>'
                result += r'    <td class="label"><span class="math">b_k</span></td>'
                result += r'    <td>{0}</td>'.format(fourierB)
                result += '</tr>\n'
            else:
                result += '<tr>'
                result += r'    <td colspan="2"><span class="math">V(\phi) = \frac{1}{2} V_0 \left[1 - \cos \left( \sigma \phi \right) \right]</span></td>'
                result += '</tr>\n'
                result += '<tr>'
                result += r'    <td class="label">Barrier height ({0!s}):</td>'.format(
                    Eunits)
                result += r'    <td>{0:.2f}</td>'.format(mode.barrier.value *
                                                         Efactor)
                result += '</tr>\n'
            result += '<tr>'
            result += r'    <td class="label">Moment of inertia (amu&times;&Aring;^2):</td>'
            result += r'    <td>{0:.1f}</td>'.format(mode.inertia.value *
                                                     constants.Na * 1e23)
            result += '</tr>\n'
            result += '<tr>'
            result += r'    <td class="label">Symmetry number:</td>'
            result += r'    <td>{0:d}</td>'.format(mode.symmetry)
            result += '</tr>\n'

    result += '<tr>'
    result += r'    <td colspan="2" class="section">Electronic</td>'
    result += '</tr>\n'
    result += '<tr>'
    result += r'    <td class="label">Spin multiplicity:</td>'
    result += r'    <td>{0:d}</td>'.format(states.spinMultiplicity)
    result += '</tr>\n'

    result += '</table>\n'

    return mark_safe(result)
Пример #20
0
def get_states_data(states, user=None):
    """
    Generate and return a set of :math:`k(T,P)` 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.
    """

    # 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)
        Eunits = str(user_profile.energyUnits)
    else:
        Tunits = 'K'
        Eunits = 'kcal/mol'
    Tfactor = Quantity(1, Tunits).getConversionFactorFromSI()
    Efactor = Quantity(1, Eunits).getConversionFactorFromSI()
    Qunits = ''
    Qfactor = 1.0
    rhounits = 'per cm^-1'
    rhofactor = constants.h * constants.c * 100 * constants.Na
    phiunits = 'rad'
    phifactor = 1.0
    Vunits = Eunits
    Vfactor = Efactor

    # Generate data to use for plots
    Tdata = []
    Qdata = []
    for T in numpy.arange(10, 2001, 10):
        Tdata.append(T * Tfactor)
        Qdata.append(states.getPartitionFunction(T) * Qfactor)

    Edata = numpy.arange(0, 400001, 1000, numpy.float)
    rhodata = states.getDensityOfStates(Edata)
    Edata = list(Edata * Efactor)
    rhodata = list(rhodata * rhofactor)

    phidata = numpy.arange(0, 2 * math.pi, math.pi / 200)
    Vdata = []
    for mode in states.modes:
        if isinstance(mode, HinderedRotor):
            Vdata.append(list(mode.getPotential(phidata) * Vfactor))
    phidata = list(phidata * phifactor)

    return mark_safe("""
Tlist = {0};
Qlist = {1};
Elist = {2};
rholist = {3};
philist = {4};
Vlist = {5};
Tunits = "{6}";
Qunits = "{7}";
Eunits = "{8}";
rhounits = "{9}";
phiunits = "{10}";
Vunits = "{11}";
    """.format(
        Tdata,
        Qdata,
        Edata,
        rhodata,
        phidata,
        Vdata,
        Tunits,
        Qunits,
        Eunits,
        rhounits,
        phiunits,
        Vunits,
    ))
Пример #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.
    """

    # Determine the number of reactants based on the units of one of the
    # kinetic parameters (which to use depends on the model)
    numReactants = 0
    if isinstance(kinetics, Arrhenius):
        numReactants = getNumberOfReactantsFromUnits(kinetics.A.units)
    elif isinstance(kinetics, ArrheniusEP):
        numReactants = getNumberOfReactantsFromUnits(kinetics.A.units)
    elif isinstance(kinetics, KineticsData):
        numReactants = getNumberOfReactantsFromUnits(kinetics.kdata.units)
    elif isinstance(kinetics, PDepArrhenius):
        numReactants = getNumberOfReactantsFromUnits(
            kinetics.arrhenius[0].A.units)
    elif isinstance(kinetics, Chebyshev):
        numReactants = getNumberOfReactantsFromUnits(kinetics.kunits)
    elif isinstance(kinetics, Troe):
        numReactants = getNumberOfReactantsFromUnits(
            kinetics.arrheniusHigh.A.units)
    elif isinstance(kinetics, Lindemann):
        numReactants = getNumberOfReactantsFromUnits(
            kinetics.arrheniusHigh.A.units)
    elif isinstance(kinetics, ThirdBody):
        numReactants = getNumberOfReactantsFromUnits(
            kinetics.arrheniusLow.A.units)
    elif isinstance(kinetics, MultiArrhenius):
        return getRateCoefficientUnits(kinetics.arrhenius[0])
    elif isinstance(kinetics, MultiPDepArrhenius):
        return getRateCoefficientUnits(kinetics.arrhenius[0])

    # Use the number of reactants to get the rate coefficient units and conversion factor
    kunitsDict = {
        1: 's^-1',
        2: 'm^3/(mol*s)',
        3: 'm^6/(mol^2*s)',
        4: 'm^9/(mol^3*s)',
    }
    if user and user.is_authenticated():
        user_profile = UserProfile.objects.get(user=user)
        if user_profile.rateCoefficientUnits == 'm^3,mol,s':
            kunitsDict = {
                1: 's^-1',
                2: 'm^3/(mol*s)',
                3: 'm^6/(mol^2*s)',
                4: 'm^9/(mol^3*s)',
            }
        elif user_profile.rateCoefficientUnits == 'cm^3,mol,s':
            kunitsDict = {
                1: 's^-1',
                2: 'cm^3/(mol*s)',
                3: 'cm^6/(mol^2*s)',
                4: 'cm^9/(mol^3*s)',
            }
        elif user_profile.rateCoefficientUnits == 'm^3,molecule,s':
            kunitsDict = {
                1: 's^-1',
                2: 'm^3/(molecule*s)',
                3: 'm^6/(molecule^2*s)',
                4: 'm^9/(molecule^3*s)',
            }
        elif user_profile.rateCoefficientUnits == 'cm^3,molecule,s':
            kunitsDict = {
                1: 's^-1',
                2: 'cm^3/(molecule*s)',
                3: 'cm^6/(molecule^2*s)',
                4: 'cm^9/(molecule^3*s)',
            }

    kunits = kunitsDict[numReactants]
    kunits_low = kunitsDict[numReactants + 1]
    kfactor = Quantity(1, kunits).getConversionFactorFromSI()

    return kunits, kunits_low, kfactor, numReactants
Пример #22
0
        if network is None: return

        # Set title and description of network
        network.title = local_context['title']
        network.description = local_context['description'].strip()
        # Log title and description
        logging.info('')
        logging.info('Network title: {0}'.format(network.title))
        logging.info('Network description: ')
        logging.info(network.description)
        
        measure.network = network
        
        # Determine temperature grid if not yet known
        if measure.Tlist is None and measure.Tmin is not None and measure.Tmax is not None and measure.Tcount is not None:
            measure.Tlist = Quantity(getTemperaturesForModel(measure.model, measure.Tmin.value_si, measure.Tmax.value_si, measure.Tcount),"K")
        elif measure.Tmin is not None and measure.Tmax is not None and measure.Tcount is not None:
            pass
        else:
            raise InputError('No temperature() block found.')
        
        # Determine pressure grid if not yet known
        if measure.Plist is None and measure.Pmin is not None and measure.Pmax is not None and measure.Pcount is not None:
            measure.Plist = Quantity(getPressuresForModel(measure.model, measure.Pmin.value_si, measure.Pmax.value_si, measure.Pcount),"Pa")
        elif measure.Pmin is not None and measure.Pmax is not None and measure.Pcount is not None:
            pass
        else:
            raise InputError('No pressure() block found.')
        
        # Check that we have energy grain information
        if measure.grainSize is None and measure.grainCount is None:
Пример #23
0
            ('C', 'O', 2): (799.0, 'kJ/mol'), ('C', 'O', 3): (1072.0, 'kJ/mol'),
            ('C', 'P', 1): (264.0, 'kJ/mol'), ('C', 'S', 1): (272.0, 'kJ/mol'),
            ('C', 'S', 2): (573.0, 'kJ/mol'), ('C', 'F', 1): (485.0, 'kJ/mol'),
            ('C', 'Cl', 1): (327.0, 'kJ/mol'), ('C', 'Br', 1): (285.0, 'kJ/mol'),
            ('C', 'I', 1): (213.0, 'kJ/mol'),
            ('Si', 'Si', 1): (222.0, 'kJ/mol'), ('Si', 'N', 1): (355.0, 'kJ/mol'),
            ('Si', 'O', 1): (452.0, 'kJ/mol'), ('Si', 'S', 1): (293.0, 'kJ/mol'),
            ('Si', 'F', 1): (565.0, 'kJ/mol'), ('Si', 'Cl', 1): (381.0, 'kJ/mol'),
            ('Si', 'Br', 1): (310.0, 'kJ/mol'), ('Si', 'I', 1): (234.0, 'kJ/mol'),
            ('N', 'N', 1): (167.0, 'kJ/mol'), ('N', 'N', 2): (418.0, 'kJ/mol'),
            ('N', 'N', 3): (942.0, 'kJ/mol'), ('N', 'O', 1): (201.0, 'kJ/mol'),
            ('N', 'O', 2): (607.0, 'kJ/mol'), ('N', 'F', 1): (283.0, 'kJ/mol'),
            ('N', 'Cl', 1): (313.0, 'kJ/mol'),
            ('O', 'O', 1): (142.0, 'kJ/mol'), ('O', 'O', 2): (494.0, 'kJ/mol'),
            ('O', 'P', 1): (335.0, 'kJ/mol'), ('O', 'P', 2): (544.0, 'kJ/mol'),
            ('O', 'S', 1): (265.0, 'kJ/mol'), ('O', 'S', 2): (522.0, 'kJ/mol'),
            ('P', 'P', 1): (201.0, 'kJ/mol'), ('P', 'P', 2): (351.0, 'kJ/mol'),
            ('P', 'P', 3): (489.0, 'kJ/mol'), ('P', 'S', 2): (335.0, 'kJ/mol'),
            ('P', 'F', 1): (490.0, 'kJ/mol'), ('P', 'Cl', 1): (326.0, 'kJ/mol'),
            ('P', 'Br', 1): (264.0, 'kJ/mol'), ('P', 'I', 2): (184.0, 'kJ/mol'),
            ('S', 'S', 1): (226.0, 'kJ/mol'), ('S', 'S', 2): (425.0, 'kJ/mol'),
            ('S', 'Cl', 1): (255.0, 'kJ/mol'),
            ('F', 'F', 1): (155.0, 'kJ/mol'), ('Cl', 'Cl', 1): (240.0, 'kJ/mol'),
            ('Br', 'Br', 1): (190.0, 'kJ/mol'), ('I', 'I', 1): (148.0, 'kJ/mol')}

bdes = {}
for key, value in bde_dict.items():
    q = Quantity(value).value_si
    bdes[(key[0], key[1], key[2])] = q
    bdes[(key[1], key[0], key[2])] = q
Пример #24
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
Пример #25
0
class CanteraCondition:
    """
    This class organizes the inputs needed for a cantera simulation

    ======================= ====================================================
    Attribute               Description
    ======================= ====================================================
    `reactorType`           A string 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)

    `reactionTime`          A tuple object giving the (reaction time, units)
    `molFrac`               A dictionary giving the initial mol Fractions. Keys are species objects and the values are floats

    To specify the system for an ideal gas, you must define 2 of the following 3 parameters:
    `T0`                    A tuple giving the (initial temperature, units) which reconstructs a Quantity object
    'P0'                    A tuple giving the (initial pressure, units) which reconstructs a Quantity object
    'V0'                    A tuple giving the (initial specific volume, units) which reconstructs a Quantity object
    ======================= ====================================================


    """
    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

    def __repr__(self):
        """
        Return a string representation that can be used to reconstruct the
        object.
        """
        string = "CanteraCondition("
        string += 'reactorType="{0}", '.format(self.reactorType)
        string += 'reactionTime={}, '.format(self.reactionTime.__repr__())
        string += 'molFrac={0}, '.format(self.molFrac.__repr__())
        if self.T0: string += 'T0={}, '.format(self.T0.__repr__())
        if self.P0: string += 'P0={}, '.format(self.P0.__repr__())
        if self.V0: string += 'V0={}, '.format(self.V0__repr__())
        string = string[:-2] + ')'
        return string

    def __str__(self):
        """
        Return a string representation of the condition.
        """
        string = ""
        string += 'Reactor Type: {0}\n'.format(self.reactorType)
        string += 'Reaction Time: {}\n'.format(self.reactionTime)
        if self.T0: string += 'T0: {}\n'.format(self.T0)
        if self.P0: string += 'P0: {}\n'.format(self.P0)
        if self.V0: string += 'V0: {}\n'.format(self.V0)
        #ConvertMolFrac to SMILES for keys for display
        prettyMolFrac = {}
        for key, value in self.molFrac.iteritems():
            prettyMolFrac[key.molecule[0].toSMILES()] = value
        string += 'Initial Mole Fractions: {0}'.format(
            prettyMolFrac.__repr__())
        return string
Пример #26
0
def render_kinetics_math(kinetics, user=None):
    """
    Return a math representation of the given `kinetics` using MathJax. If a
    `user` is specified, the user's preferred units will be used; otherwise
    default units will be used.
    """
    if kinetics is None:
        return mark_safe("<p>There are no kinetics for this entry.</p>")
    # Define other units and conversion factors to use
    if user and user.is_authenticated:
        user_profile = UserProfile.objects.get(user=user)
        Tunits = user_profile.temperature_units
        Punits = user_profile.pressure_units
        Eunits = user_profile.energy_units
    else:
        Tunits = 'K'
        Punits = 'Pa'
        Eunits = 'J/mol'
    kunits, kunits_low, kfactor = getRateCoefficientUnits(kinetics, user=user)
    Tfactor = Quantity(1, Tunits).get_conversion_factor_from_si()
    Pfactor = Quantity(1, Punits).get_conversion_factor_from_si()
    Efactor = Quantity(1, Eunits).get_conversion_factor_from_si()
    if kunits == 's^-1':
        kunits = 's^{-1}'

    # The string that will be returned to the template
    result = ''

    if isinstance(kinetics, (Arrhenius, SurfaceArrhenius, StickingCoefficient)):
        # The kinetics is in Arrhenius format
        result += r'<script type="math/tex; mode=display">k(T) = {0!s}</script>'.format(getArrheniusJSMath(
            kinetics.A.value_si * kfactor, kunits,
            kinetics.n.value_si, '',
            kinetics.Ea.value_si * Efactor, Eunits,
            kinetics.T0.value_si * Tfactor, Tunits,
        ))

    elif isinstance(kinetics, (ArrheniusEP, SurfaceArrheniusBEP, StickingCoefficientBEP)):
        # The kinetics is in ArrheniusEP format
        result += r'<script type="math/tex; mode=display">k(T) = {0!s}'.format(getLaTeXScientificNotation(kinetics.A.value_si * kfactor))
        if kinetics.n.value_si != 0:
            result += r' T^{{ {0:.2f} }}'.format(kinetics.n.value_si)
        result += r' \exp \left( - \, \frac{{ {0:.2f} \ \mathrm{{ {1!s} }} + {2:.2f} \Delta H_\mathrm{{rxn}}^\circ }}{{ R T }} \right)'.format(kinetics.E0.value_si * Efactor, Eunits, kinetics.alpha.value_si)
        result += r' \ \mathrm{{ {0!s} }}</script>'.format(kunits)

    elif isinstance(kinetics, ArrheniusBM):
        # The kinetics is in ArrheniusBM format
        result += r'<script type="math/tex; mode=display">\begin{{split}}k(T) &= {0!s}'.format(getLaTeXScientificNotation(kinetics.A.value_si * kfactor))
        if kinetics.n.value_si != 0:
            result += r' T^{{ {0:.2f} }}' .format(kinetics.n.value_si)
        result += r' \exp \left(- \, \frac{{ E_\mathrm{{a}} }}{{RT}} \right) \ \mathrm{{ {0!s} }} \\'.format(kunits)
        result += r'''
E_\mathrm{{a}} &= \frac{{ \left( w_{{0}} + 0.5 \Delta H_\mathrm{{rxn}} \right)
\left( V_\mathrm{{p}} - 2 w_{{0}} + \Delta H_\mathrm{{rxn}} \right) ^ {{2}} }}
{{ V_\mathrm{{p}} ^ {{2}} - \left( 2 w_{{0}} \right) ^ {{2}} + \Delta H_\mathrm{{rxn}} ^ {{2}} }} \\
V_\mathrm{{p}} &= 2 w_{{0}} \left( \frac{{ w_{{0}} + E_{{0}} }} {{ w_{{0}} - E_{{0}} }} \right) \\
w_{{0}} &= {0:.2f}\ \mathrm{{ {1!s} }} \\
E_{{0}} &= {2:.2f}\ \mathrm{{ {1!s} }} \end{{split}}</script>
'''.format(kinetics.w0.value_si * Efactor, Eunits, kinetics.E0.value_si * Efactor)
        
    elif isinstance(kinetics, KineticsData):
        # The kinetics is in KineticsData format
        result += r'<table class="KineticsData">'
        result += r'<tr><th>Temperature</th><th>Rate coefficient</th></tr>'
        for T, k in zip(kinetics.Tdata.value_si, kinetics.kdata.value_si):
            result += r'<tr><td><script type="math/tex">{0:g} \ \mathrm{{ {1!s} }}</script></td><td><script type="math/tex">{2!s} \ \mathrm{{ {3!s} }}</script></td></tr>'.format(T * Tfactor, Tunits, getLaTeXScientificNotation(k * kfactor), kunits)
        result += r'</table>'
        # fit to an arrhenius
        arr = kinetics.to_arrhenius()
        result += "Fitted to an Arrhenius:"
        result += r'<script type="math/tex; mode=display">k(T) = {0!s}</script>'.format(getArrheniusJSMath(
            arr.A.value_si * kfactor, kunits,
            arr.n.value_si, '',
            arr.Ea.value_si * Efactor, Eunits,
            arr.T0.value_si * Tfactor, Tunits,
        ))

    elif isinstance(kinetics, PDepArrhenius):
        # The kinetics is in PDepArrhenius format
        for P, arrh in zip(kinetics.pressures.value_si, kinetics.arrhenius):
            if isinstance(arrh, Arrhenius):
                result += r'<script type="math/tex; mode=display">k(T, {0} \mathrm{{ {1!s} }}) = {2}</script>'.format(
                    getLaTeXScientificNotation(P * Pfactor), Punits,
                    getArrheniusJSMath(
                        arrh.A.value_si * kfactor, kunits,
                        arrh.n.value_si, '',
                        arrh.Ea.value_si * Efactor, Eunits,
                        arrh.T0.value_si * Tfactor, Tunits,
                    ),
                )
            elif isinstance(arrh, MultiArrhenius):
                start = (r'<script type="math/tex; mode=display">'
                         r'k(T, {0} \mathrm{{ {1!s} }}) = '.format(getLaTeXScientificNotation(P * Pfactor), Punits))
                res = ''
                for i, k in enumerate(arrh.arrhenius):
                    start += 'k_{{ {0:d} }}(T, {1} \mathrm{{ {2!s} }}) + '.format(i + 1, getLaTeXScientificNotation(P * Pfactor), Punits)
                    res += r'<script type="math/tex; mode=display">k_{{ {0:d} }}(T, {1} \mathrm{{ {2!s} }}) = {3}</script>'.format(
                        i + 1, getLaTeXScientificNotation(P * Pfactor), Punits,
                        getArrheniusJSMath(
                            k.A.value_si * kfactor, kunits,
                            k.n.value_si, '',
                            k.Ea.value_si * Efactor, Eunits,
                            k.T0.value_si * Tfactor, Tunits,
                        ),
                    )
                result += start[:-3] + '</script>\n' + res + '<br/>'

    elif isinstance(kinetics, Chebyshev):
        # The kinetics is in Chebyshev format
        result += r"""<script type="math/tex; mode=display">
\begin{split}
\log k(T,P) &= \sum_{t=1}^{N_T} \sum_{p=1}^{N_P} C_{tp} \phi_t(\tilde{T}) \phi_p(\tilde{P}) [\mathrm{""" + kinetics.kunits + r""" }] \\
\tilde{T} &\equiv \frac{2T^{-1} - T_\mathrm{min}^{-1} - T_\mathrm{max}^{-1}}{T_\mathrm{max}^{-1} - T_\mathrm{min}^{-1}} \\
\tilde{P} &\equiv \frac{2 \log P - \log P_\mathrm{min} - \log P_\mathrm{max}}{\log P_\mathrm{max} - \log P_\mathrm{min}}
\end{split}</script><br/>
<script type="math/tex; mode=display">\mathbf{C} = \begin{bmatrix}
        """
        for t in range(kinetics.degreeT):
            for p in range(kinetics.degreeP):
                if p > 0:
                    result += ' & '
                result += '{0:g}'.format(kinetics.coeffs.value_si[t, p])
            result += '\\\\ \n'
        result += '\end{bmatrix}</script>'

    elif isinstance(kinetics, Troe):
        # The kinetics is in Troe format
        Fcent = r'(1 - \alpha) \exp \left( -T/T_3 \right) + \alpha \exp \left( -T/T_1 \right) + \exp \left( -T_2/T \right)'
        if kinetics.T2 is not None:
            Fcent += r' + \exp \left( -T_2/T \right)'
        result += r"""<script type="math/tex; mode=display">
\begin{{split}}
k(T,P) &= k_\infty(T) \left[ \frac{{P_\mathrm{{r}}}}{{1 + P_\mathrm{{r}}}} \right] F \\
P_\mathrm{{r}} &= \frac{{k_0(T)}}{{k_\infty(T)}} [\mathrm{{M}}] \\
\log F &= \left\{{1 + \left[ \frac{{\log P_\mathrm{{r}} + c}}{{n - d (\log P_\mathrm{{r}} + c)}} \right]^2 \right\}}^{{-1}} \log F_\mathrm{{cent}} \\
c &= -0.4 - 0.67 \log F_\mathrm{{cent}} \\
n &= 0.75 - 1.27 \log F_\mathrm{{cent}} \\
d &= 0.14 \\
F_\mathrm{{cent}} &= {0}
\end{{split}}
</script><script type="math/tex; mode=display">\begin{{split}}
        """.format(Fcent)
        result += r'k_\infty(T) &= {0!s} \\'.format(getArrheniusJSMath(
            kinetics.arrheniusHigh.A.value_si * kfactor, kunits,
            kinetics.arrheniusHigh.n.value_si, '',
            kinetics.arrheniusHigh.Ea.value_si * Efactor, Eunits,
            kinetics.arrheniusHigh.T0.value_si * Tfactor, Tunits,
        ))
        result += r'k_0(T) &= {0!s} \\'.format(getArrheniusJSMath(
            kinetics.arrheniusLow.A.value_si * kfactor * kfactor, kunits_low,
            kinetics.arrheniusLow.n.value_si, '',
            kinetics.arrheniusLow.Ea.value_si * Efactor, Eunits,
            kinetics.arrheniusLow.T0.value_si * Tfactor, Tunits,
        ))
        result += r'\alpha &= {0:g} \\'.format(kinetics.alpha)
        result += r'T_3 &= {0:g} \ \mathrm{{ {1!s} }} \\'.format(kinetics.T3.value_si * Tfactor, Tunits)
        result += r'T_1 &= {0:g} \ \mathrm{{ {1!s} }} \\'.format(kinetics.T1.value_si * Tfactor, Tunits)
        if kinetics.T2 is not None:
            result += r'T_2 &= {0:g} \ \mathrm{{ {1!s} }} \\'.format(kinetics.T2.value_si * Tfactor, Tunits)
        result += r'\end{split}</script>'

    elif isinstance(kinetics, Lindemann):
        # The kinetics is in Lindemann format
        result += r"""<script type="math/tex; mode=display">
\begin{{split}}
k(T,P) &= k_\infty(T) \left[ \frac{{P_\mathrm{{r}}}}{{1 + P_\mathrm{{r}}}} \right] \\
P_\mathrm{{r}} &= \frac{{k_0(T)}}{{k_\infty(T)}} [\mathrm{{M}}] \\
\end{{split}}
</script><script type="math/tex; mode=display">\begin{{split}}
        """.format()
        result += r'k_\infty(T) &= {0!s} \\'.format(getArrheniusJSMath(
            kinetics.arrheniusHigh.A.value_si * kfactor, kunits,
            kinetics.arrheniusHigh.n.value_si, '',
            kinetics.arrheniusHigh.Ea.value_si * Efactor, Eunits,
            kinetics.arrheniusHigh.T0.value_si * Tfactor, Tunits,
        ))
        result += r'k_0(T) &= {0!s} \\'.format(getArrheniusJSMath(
            kinetics.arrheniusLow.A.value_si * kfactor * kfactor, kunits_low,
            kinetics.arrheniusLow.n.value_si, '',
            kinetics.arrheniusLow.Ea.value_si * Efactor, Eunits,
            kinetics.arrheniusLow.T0.value_si * Tfactor, Tunits,
        ))
        result += r'\end{split}</script>'

    elif isinstance(kinetics, ThirdBody):
        # The kinetics is in ThirdBody format
        result += r"""<script type="math/tex; mode=display">
k(T,P) = k_0(T) [\mathrm{{M}}]
</script><script type="math/tex; mode=display">
        """.format()
        result += r'k_0(T) = {0!s}'.format(getArrheniusJSMath(
            kinetics.arrheniusLow.A.value_si * kfactor * kfactor, kunits_low,
            kinetics.arrheniusLow.n.value_si, '',
            kinetics.arrheniusLow.Ea.value_si * Efactor, Eunits,
            kinetics.arrheniusLow.T0.value_si * Tfactor, Tunits,
        ))
        result += '</script>'

    elif isinstance(kinetics, (MultiArrhenius, MultiPDepArrhenius)):
        # The kinetics is in MultiArrhenius or MultiPDepArrhenius format
        result = ''
        start = r'<script type="math/tex; mode=display">k(T, P) = '
        for i, k in enumerate(kinetics.arrhenius):
            res = render_kinetics_math(k, user=user)
            start += 'k_{{ {0:d} }}(T, P) + '.format(i+1)
            result += res.replace('k(T', 'k_{{ {0:d} }}(T'.format(i+1)) + '<br/>'

        result = start[:-3] + '</script><br/>' + result

    # Collision efficiencies
    if hasattr(kinetics, 'efficiencies') and kinetics.efficiencies:
        result += '<table>\n'
        result += '<tr><th colspan="2">Collision efficiencies</th></tr>'
        for smiles, eff in kinetics.efficiencies.items():
            result += '<tr><td>{0}</td><td>{1:g}</td></tr>\n'.format(getStructureMarkup(smiles), eff)
        result += '</table><br/>\n'

    # Temperature and pressure ranges
    result += '<table class="kineticsEntryData">'
    if kinetics.Tmin is not None and kinetics.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(kinetics.Tmin.value_si * Tfactor, kinetics.Tmax.value_si * Tfactor, Tunits)
    if kinetics.Pmin is not None and kinetics.Pmax is not None:
        result += '<tr><td class="key">Pressure range</td><td class="equals">=</td><td class="value">{0:g} to {1:g} {2!s}</td></tr>'.format(kinetics.Pmin.value_si * Pfactor, kinetics.Pmax.value_si * Pfactor, Punits)
    result += '</table>'

    return mark_safe(result)
Пример #27
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 ''
Пример #28
0
def get_rate_coefficients(kinetics, user=None):
    """
    Generate and return a set of :math:`k(T,P)` 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 `user=='A_n_Ea'` then it fits an Arrhenius expression and returns
    the parameters (and their units).
    """
    if kinetics is None:
        return "// There are no kinetics for this entry."

    if user == "A_n_Ea":
        # Not a user, but a request to just return the Arrhenius coefficients
        return_A_n_Ea = True
        user = None
    else:
        return_A_n_Ea = False

    # Define other units and conversion factors to use
    if user and user.is_authenticated:
        user_profile = UserProfile.objects.get(user=user)
        Tunits = user_profile.temperature_units
        Punits = user_profile.pressure_units
        Eunits = user_profile.energy_units
    else:
        Tunits = 'K'
        Punits = 'Pa'
        Eunits = 'J/mol'
    kunits, kunits_low, kfactor = getRateCoefficientUnits(kinetics, user=user)
    Tfactor = Quantity(1, Tunits).get_conversion_factor_from_si()
    Pfactor = Quantity(1, Punits).get_conversion_factor_from_si()
    Efactor = Quantity(1, Eunits).get_conversion_factor_from_si()

    # Generate data to use for plots
    Tdata = []
    Pdata = []
    kdata = []
    if kinetics.Tmin is not None and kinetics.Tmax is not None:
        if kinetics.Tmin.value_si == kinetics.Tmax.value_si:
            Tmin = kinetics.Tmin.value_si - 5
            Tmax = kinetics.Tmax.value_si + 5
        else:
            Tmin = kinetics.Tmin.value_si
            Tmax = kinetics.Tmax.value_si
    else:
        Tmin = 300
        Tmax = 2000
    if kinetics.Pmin is not None and kinetics.Pmax is not None:
        Pmin = kinetics.Pmin.value_si
        Pmax = kinetics.Pmax.value_si
    else:
        Pmin = 1e3
        Pmax = 1e7

    # Number of points in Tlist (ten times that in Pdep's Tlist2)
    points = 50

    for Tinv in np.linspace(1.0 / Tmax, 1.0 / Tmin, points):
        Tdata.append(1.0 / Tinv)
    if kinetics.is_pressure_dependent():
        for logP in np.arange(math.log10(Pmin), math.log10(Pmax)+0.001, 1):
            Pdata.append(10**logP)
        for P in Pdata:
            klist = []
            for T in Tdata:
                klist.append(kinetics.get_rate_coefficient(T, P) * kfactor)
            kdata.append(klist)
    elif isinstance(kinetics, (ArrheniusEP, ArrheniusBM)):
        for T in Tdata:
            kdata.append(kinetics.get_rate_coefficient(T, dHrxn=0) * kfactor)
    elif isinstance(kinetics, (StickingCoefficient, StickingCoefficientBEP)):
        for T in Tdata:
            kdata.append(kinetics.get_sticking_coefficient(T) * kfactor)
    else:
        for T in Tdata:
            kdata.append(kinetics.get_rate_coefficient(T) * kfactor)

    Tdata2 = []
    Pdata2 = []
    kdata2 = []
    for Tinv in np.linspace(1.0 / Tmax, 1.0 / Tmin, points // 10):
        Tdata2.append(1.0 / Tinv)
    if kinetics.is_pressure_dependent():
        for logP in np.arange(math.log10(Pmin), math.log10(Pmax)+0.001, 0.1):
            Pdata2.append(10**logP)
        for P in Pdata2:
            klist = []
            for T in Tdata2:
                klist.append(kinetics.get_rate_coefficient(T, P) * kfactor)
            kdata2.append(klist)
    elif isinstance(kinetics, (ArrheniusEP, ArrheniusBM)):
        for T in Tdata2:
            kdata2.append(kinetics.get_rate_coefficient(T, dHrxn=0) * kfactor)
    elif isinstance(kinetics, (StickingCoefficient, StickingCoefficientBEP)):
        for T in Tdata:
            kdata2.append(kinetics.get_sticking_coefficient(T) * kfactor)
    else:
        for T in Tdata2:
            kdata2.append(kinetics.get_rate_coefficient(T) * kfactor)

    if return_A_n_Ea:
        "We are only interested in the (fitted) Arrhenius parameters (and their units)"
        Tlist = np.array([T * Tfactor for T in Tdata], np.float64)

        if kinetics.is_pressure_dependent():
            # Use the highest pressure we have available
            klist = np.array(kdata[-1], np.float64)
            pressure_note = " (At {0} {1})".format(Pdata[-1], Punits)
            k_model = Arrhenius().fit_to_data(Tlist, klist, kunits)
        elif isinstance(kinetics, (StickingCoefficient, StickingCoefficientBEP)):
            klist = np.array(kdata, np.float64)
            pressure_note = ""
            k_model = StickingCoefficient().fit_to_data(Tlist, klist, kunits)
        elif isinstance(kinetics, (SurfaceArrhenius, SurfaceArrheniusBEP)):
            klist = np.array(kdata, np.float64)
            pressure_note = ""
            k_model = SurfaceArrhenius().fit_to_data(Tlist, klist, kunits)
        else:
            klist = np.array(kdata, np.float64)
            pressure_note = ""
            k_model = Arrhenius().fit_to_data(Tlist, klist, kunits)

        return mark_safe("""A = {0}; n = {1}; Ea = {2}; Aunits = "{3}"; Eunits = "{4}"; Pnote = "{5}";""".format(
                            k_model.A.value_si * kfactor,
                            k_model.n.value_si,
                            k_model.Ea.value_si * Efactor,
                            kunits,
                            Eunits,
                            pressure_note
                        ))

    return mark_safe("""Tlist = {0};Plist = {1};klist = {2};
                        Tlist2 = {3};Plist2 = {4}; klist2 = {5};
                        Tunits = "{6}";Punits = "{7}";kunits = "{8}";""".format(
                             [T * Tfactor for T in Tdata],
                             [P * Pfactor for P in Pdata],
                             kdata,
                             [T * Tfactor for T in Tdata2],
                             [P * Pfactor for P in Pdata2],
                             kdata2,
                             Tunits,
                             Punits,
                             kunits,
                         ))
Пример #29
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.simulate import plot_sensitivity
        from rmgpy.rmg.listener import SimulationProfileWriter, SimulationProfilePlotter
        from rmgpy.rmg.settings import ModelSettings, SimulatorSettings
        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))

        simulatorSettings = SimulatorSettings()  #defaults

        modelSettings = ModelSettings()  #defaults
        modelSettings.fluxToleranceMoveToCore = 0.1
        modelSettings.fluxToleranceInterrupt = 1.0
        modelSettings.fluxToleranceKeepInEdge = 0.0

        reactionSystem.simulate(
            coreSpecies=self.speciesList,
            coreReactions=self.reactionList,
            edgeSpecies=[],
            edgeReactions=[],
            surfaceSpecies=[],
            surfaceReactions=[],
            modelSettings=modelSettings,
            simulatorSettings=simulatorSettings,
            sensitivity=True,
            sensWorksheet=sensWorksheet,
        )

        plot_sensitivity(self.outputDirectory,
                         reactionSystemIndex,
                         reactionSystem.sensitiveSpecies,
                         number=number,
                         fileformat=fileformat)
Пример #30
0
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')
Пример #31
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
Пример #32
0
def liquidReactor(temperature,
                  initialConcentrations,
                  terminationConversion=None,
                  nSimsTerm = 4,
                  terminationTime=None,
                  terminationRateRatio=None,
                  sensitivity=None,
                  sensitivityThreshold=1e-3,
                  sensitivityTemperature=None,
                  sensitivityConcentrations=None,
                  constantSpecies=None):
    
    logging.debug('Found LiquidReactor reaction system')
    
    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]
    
    for spec,conc in initialConcentrations.iteritems():
        if not isinstance(conc,list):
            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
        else:
            if len(conc) != 2:
                raise InputError("Concentration values must either be in the form of (number,units) or a list with 2 entries of the same format")
            initialConcentrations[spec] = [Quantity(conc[0]),Quantity(conc[1])]
            
    if not isinstance(temperature,list) and all([not isinstance(x,list) for x in initialConcentrations.itervalues()]):
        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:
        for spec in sensitivity:
            sensitiveSpecies.append(speciesDict[spec])
    
    ##chatelak: check the constant species exist
    if constantSpecies is not None:
        logging.debug('  Generation with constant species:')
        for constantSpecie in constantSpecies:
            logging.debug("  {0}".format(constantSpecie))
            if not speciesDict.has_key(constantSpecie):
                raise InputError('Species {0} not found in the input file'.format(constantSpecie))
    
    if not isinstance(T,list):
        sensitivityTemperature = T
    if not any([isinstance(x,list) for x in initialConcentrations.itervalues()]):
        sensitivityConcentrations = initialConcentrations
    if sensitivityConcentrations is None or sensitivityTemperature is None:
        sensConditions = None
    else:
        sensConditions = sensitivityConcentrations
        sensConditions['T'] = Quantity(sensitivityTemperature).value_si
        
    system = LiquidReactor(T, initialConcentrations, nSimsTerm, termination, sensitiveSpecies, sensitivityThreshold, sensConditions, constantSpecies)
    rmg.reactionSystems.append(system)