Beispiel #1
0
    def testTransportDataReadAndWrite(self):
        """
        Test that we can write to chemkin and recreate the same transport object
        """
        from rmgpy.species import Species
        from rmgpy.molecule import Molecule
        from rmgpy.transport import TransportData

        Ar = Species(label="Ar",
                     transportData=TransportData(shapeIndex=0,
                                                 epsilon=(1134.93, 'J/mol'),
                                                 sigma=(3.33, 'angstrom'),
                                                 dipoleMoment=(0, 'De'),
                                                 polarizability=(0,
                                                                 'angstrom^3'),
                                                 rotrelaxcollnum=0.0,
                                                 comment="""GRI-Mech"""))

        Ar_write = Species(label="Ar")
        folder = os.path.join(os.path.dirname(rmgpy.__file__), 'test_data')

        tempTransportPath = os.path.join(folder, 'tran_temp.dat')

        saveTransportFile(tempTransportPath, [Ar])
        speciesDict = {'Ar': Ar_write}
        loadTransportFile(tempTransportPath, speciesDict)
        self.assertEqual(repr(Ar), repr(Ar_write))

        os.remove(tempTransportPath)
Beispiel #2
0
 def test_toCantera(self):
     """
     Test that the Cantera GasTransportData creation is successful.
     """
     transport = TransportData(shapeIndex=0, epsilon=(1134.93,'J/mol'), sigma=(3.33,'angstrom'), dipoleMoment=(2,'De'), polarizability=(1,'angstrom^3'), rotrelaxcollnum=15.0, comment="""GRI-Mech""")
     rmg_ctTransport = transport.toCantera()
     import cantera as ct
     ctSpecies = ct.Species.fromCti("""species(name=u'Ar',
     atoms='Ar:1',
     transport=gas_transport(geom='atom',
                             diam=3.33,
                             well_depth=136.501,
                             dipole=2.0,
                             polar=1.0,
                             rot_relax=15.0))""")
     
     ctTransport = ctSpecies.transport
     
     self.assertAlmostEqual(rmg_ctTransport.geometry, ctTransport.geometry)
     self.assertAlmostEqual(rmg_ctTransport.acentric_factor, ctTransport.acentric_factor)
     self.assertAlmostEqual(rmg_ctTransport.diameter, ctTransport.diameter)
     self.assertAlmostEqual(rmg_ctTransport.dipole, ctTransport.dipole)
     self.assertAlmostEqual(rmg_ctTransport.polarizability, ctTransport.polarizability)
     self.assertAlmostEqual(rmg_ctTransport.rotational_relaxation, ctTransport.rotational_relaxation)
     self.assertAlmostEqual(rmg_ctTransport.well_depth, ctTransport.well_depth)
Beispiel #3
0
 def setUp(self):
     """
     A method that is run before each unit test in this class.
     """
     self.species = Species(
         index=1,
         label='C2H4',
         thermo=ThermoData(
             Tdata=([300.0,400.0,500.0,600.0,800.0,1000.0,1500.0],'K'),
             Cpdata=([3.0,4.0,5.0,6.0,8.0,10.0,15.0],'cal/(mol*K)'),
             H298=(-20.0,'kcal/mol'),
             S298=(50.0,'cal/(mol*K)'),
             Tmin=(300.0,'K'),
             Tmax=(2000.0,'K'),
         ),
         conformer=Conformer(
             E0=(0.0,'kJ/mol'),
             modes=[
                 IdealGasTranslation(mass=(28.03,'amu')),
                 NonlinearRotor(inertia=([5.6952e-47, 2.7758e-46, 3.3454e-46],'kg*m^2'), symmetry=1),
                 HarmonicOscillator(frequencies=([834.50, 973.31, 975.37, 1067.1, 1238.5, 1379.5, 1472.3, 1691.3, 3121.6, 3136.7, 3192.5, 3221.0],'cm^-1')),
             ],
             spinMultiplicity=1,
             opticalIsomers=1,
         ),
         molecule=[Molecule().fromSMILES('C=C')],
         transportData=TransportData(sigma=(1, 'angstrom'), epsilon=(100, 'K')),
         molecularWeight=(28.03,'amu'),
         reactive=True,
     )
Beispiel #4
0
    def testCantera(self):
        """
        Test that a Cantera Species object is created correctly.
        """
        from rmgpy.thermo import NASA, NASAPolynomial
        import cantera as ct
        rmgSpecies = Species(label="Ar", thermo=NASA(polynomials=[NASAPolynomial(coeffs=[2.5,0,0,0,0,-745.375,4.37967], Tmin=(200,'K'), Tmax=(1000,'K')), NASAPolynomial(coeffs=[2.5,0,0,0,0,-745.375,4.37967], Tmin=(1000,'K'), Tmax=(6000,'K'))], Tmin=(200,'K'), Tmax=(6000,'K'), comment="""
Thermo library: primaryThermoLibrary
"""), molecule=[Molecule(SMILES="[Ar]")], transportData=TransportData(shapeIndex=0, epsilon=(1134.93,'J/mol'), sigma=(3.33,'angstrom'), dipoleMoment=(2,'De'), polarizability=(1,'angstrom^3'), rotrelaxcollnum=15.0, comment="""GRI-Mech"""))
        
        rmg_ctSpecies = rmgSpecies.toCantera(useChemkinIdentifier = True)
        
        ctSpecies = ct.Species.fromCti("""species(name=u'Ar',
        atoms='Ar:1',
        thermo=(NASA([200.00, 1000.00],
                     [ 2.50000000E+00,  0.00000000E+00,  0.00000000E+00,
                       0.00000000E+00,  0.00000000E+00, -7.45375000E+02,
                       4.37967000E+00]),
                NASA([1000.00, 6000.00],
                     [ 2.50000000E+00,  0.00000000E+00,  0.00000000E+00,
                       0.00000000E+00,  0.00000000E+00, -7.45375000E+02,
                       4.37967000E+00])),
        transport=gas_transport(geom='atom',
                                diam=3.33,
                                well_depth=136.501,
                                dipole=2.0,
                                polar=1.0,
                                rot_relax=15.0))""")
        self.assertEqual(type(rmg_ctSpecies),type(ctSpecies))
        self.assertEqual(rmg_ctSpecies.name, ctSpecies.name)
        self.assertEqual(rmg_ctSpecies.composition, ctSpecies.composition)
        self.assertEqual(rmg_ctSpecies.size, ctSpecies.size)
        self.assertEqual(type(rmg_ctSpecies.thermo), type(ctSpecies.thermo))
        self.assertEqual(type(rmg_ctSpecies.transport), type(ctSpecies.transport))
Beispiel #5
0
    def testGetTransportData(self):
        """
        Test that transport data can be retrieved correctly via the getTransportData method.
        """

        spc = Species(label="Ar", molecule=[Molecule(SMILES="[Ar]")], transportData=TransportData(shapeIndex=0, epsilon=(1134.93,'J/mol'), sigma=(3.33,'angstrom'), dipoleMoment=(2,'De'), polarizability=(1,'angstrom^3'), rotrelaxcollnum=15.0, comment="""GRI-Mech"""))

        self.assertTrue(spc.getTransportData() is spc.transportData)
Beispiel #6
0
    def setUp(self):
        """
        A function run before each unit test in this class.
        """
        self.nC4H10O = Species(
            label = 'n-C4H10O',
            conformer = Conformer(
                E0 = (-317.807,'kJ/mol'),
                modes = [
                    IdealGasTranslation(mass=(74.07,"g/mol")),
                    NonlinearRotor(inertia=([41.5091,215.751,233.258],"amu*angstrom^2"), symmetry=1),
                    HarmonicOscillator(frequencies=([240.915,341.933,500.066,728.41,809.987,833.93,926.308,948.571,1009.3,1031.46,1076,1118.4,1184.66,1251.36,1314.36,1321.42,1381.17,1396.5,1400.54,1448.08,1480.18,1485.34,1492.24,1494.99,1586.16,2949.01,2963.03,2986.19,2988.1,2995.27,3026.03,3049.05,3053.47,3054.83,3778.88],"cm^-1")),
                    HinderedRotor(inertia=(0.854054,"amu*angstrom^2"), symmetry=1, fourier=([[0.25183,-1.37378,-2.8379,0.0305112,0.0028088], [0.458307,0.542121,-0.599366,-0.00283925,0.0398529]],"kJ/mol")),
                    HinderedRotor(inertia=(8.79408,"amu*angstrom^2"), symmetry=1, fourier=([[0.26871,-0.59533,-8.15002,-0.294325,-0.145357], [1.1884,0.99479,-0.940416,-0.186538,0.0309834]],"kJ/mol")),
                    HinderedRotor(inertia=(7.88153,"amu*angstrom^2"), symmetry=1, fourier=([[-4.67373,2.03735,-6.25993,-0.27325,-0.048748], [-0.982845,1.76637,-1.57619,0.474364,-0.000681718]],"kJ/mol")),
                    HinderedRotor(inertia=(2.81525,"amu*angstrom^2"), symmetry=3, barrier=(2.96807,"kcal/mol")),
                ],
                spinMultiplicity = 1,
                opticalIsomers = 1,
            ),
            molecularWeight = (74.07,"g/mol"),
            transportData=TransportData(sigma=(5.94, 'angstrom'), epsilon=(559, 'K')),
            energyTransferModel = SingleExponentialDown(alpha0=(447.5*0.011962,"kJ/mol"), T0=(300,"K"), n=0.85),
        )
        
        self.nC4H8 = Species(
            label = 'n-C4H8',
            conformer = Conformer(
                E0 = (-17.8832,'kJ/mol'),
                modes = [
                    IdealGasTranslation(mass=(56.06,"g/mol")),
                    NonlinearRotor(inertia=([22.2748,122.4,125.198],"amu*angstrom^2"), symmetry=1),
                    HarmonicOscillator(frequencies=([308.537,418.67,636.246,788.665,848.906,936.762,979.97,1009.48,1024.22,1082.96,1186.38,1277.55,1307.65,1332.87,1396.67,1439.09,1469.71,1484.45,1493.19,1691.49,2972.12,2994.31,3018.48,3056.87,3062.76,3079.38,3093.54,3174.52],"cm^-1")),
                    HinderedRotor(inertia=(5.28338,"amu*angstrom^2"), symmetry=1, fourier=([[-0.579364,-0.28241,-4.46469,0.143368,0.126756], [1.01804,-0.494628,-0.00318651,-0.245289,0.193728]],"kJ/mol")),
                    HinderedRotor(inertia=(2.60818,"amu*angstrom^2"), symmetry=3, fourier=([[0.0400372,0.0301986,-6.4787,-0.0248675,-0.0324753], [0.0312541,0.0538,-0.493785,0.0965968,0.125292]],"kJ/mol")),
                ],
                spinMultiplicity = 1,
                opticalIsomers = 1,
            ),
        )
        
        self.H2O = Species(
            label = 'H2O',
            conformer = Conformer(
                E0 = (-269.598,'kJ/mol'),
                modes = [
                    IdealGasTranslation(mass=(18.01,"g/mol")),
                    NonlinearRotor(inertia=([0.630578,1.15529,1.78586],"amu*angstrom^2"), symmetry=2),
                    HarmonicOscillator(frequencies=([1622.09,3771.85,3867.85],"cm^-1")),
                ],
                spinMultiplicity = 1,
                opticalIsomers = 1,
            ),
        )

        self.configuration = Configuration(self.nC4H8, self.H2O)
Beispiel #7
0
    def setUp(self):
        """
        A method that is run before each unit test in this class.
        """
        self.species = Species(
            index=1,
            label='C2H4',
            thermo=ThermoData(
                Tdata=([300.0, 400.0, 500.0, 600.0, 800.0, 1000.0,
                        1500.0], 'K'),
                Cpdata=([3.0, 4.0, 5.0, 6.0, 8.0, 10.0, 15.0], 'cal/(mol*K)'),
                H298=(-20.0, 'kcal/mol'),
                S298=(50.0, 'cal/(mol*K)'),
                Tmin=(300.0, 'K'),
                Tmax=(2000.0, 'K'),
            ),
            conformer=Conformer(
                E0=(0.0, 'kJ/mol'),
                modes=[
                    IdealGasTranslation(mass=(28.03, 'amu')),
                    NonlinearRotor(
                        inertia=([5.6952e-47, 2.7758e-46,
                                  3.3454e-46], 'kg*m^2'),
                        symmetry=1),
                    HarmonicOscillator(frequencies=([
                        834.50, 973.31, 975.37, 1067.1, 1238.5, 1379.5, 1472.3,
                        1691.3, 3121.6, 3136.7, 3192.5, 3221.0
                    ], 'cm^-1')),
                ],
                spin_multiplicity=1,
                optical_isomers=1,
            ),
            molecule=[Molecule().from_smiles('C=C')],
            transport_data=TransportData(sigma=(1, 'angstrom'),
                                         epsilon=(100, 'K')),
            molecular_weight=(28.03, 'amu'),
            reactive=True,
        )

        self.species2 = Species().from_adjacency_list("""
            1  C u0 p0 c0 {2,D} {6,S} {7,S}
            2  C u0 p0 c0 {1,D} {3,S} {8,S}
            3  C u0 p0 c0 {2,S} {4,D} {9,S}
            4  C u0 p0 c0 {3,D} {5,S} {10,S}
            5  C u0 p0 c0 {4,S} {6,D} {11,S}
            6  C u0 p0 c0 {1,S} {5,D} {12,S}
            7  H u0 p0 c0 {1,S}
            8  H u0 p0 c0 {2,S}
            9  H u0 p0 c0 {3,S}
            10 H u0 p0 c0 {4,S}
            11 H u0 p0 c0 {5,S}
            12 H u0 p0 c0 {6,S}
            """)
Beispiel #8
0
    def get_transport_properties_via_group_estimates(self, species):
        """
        Return the set of transport parameters corresponding to a given
        :class:`Species` object `species` by estimation using the group
        additivity values. If no group additivity values are loaded, a
        :class:`DatabaseError` is raised.
        """

        # assume that the stablest resonance isomer has already been put as the first
        # and that we want the transport properties of this isomer
        molecule = species.molecule[0]
        if molecule.is_aromatic(
        ):  #don't use aromatic resonance structures as there are no groups for them currently
            molecule = molecule.copy(deep=True)
            molecule.kekulize()

        molecule.clear_labeled_atoms()
        molecule.update_atomtypes()
        critical_point = self.estimate_critical_properties_via_group_additivity(
            molecule)
        Tc = critical_point.Tc
        Pc = critical_point.Pc
        Vc = critical_point.Vc
        Tb = critical_point.Tb
        if critical_point.linear != molecule.is_linear():
            logging.warning(
                "Group-based structure index and is_linear() function disagree about "
                "linearity of {mol!r}".format(mol=molecule))

        if len(molecule.atoms) == 1:
            shape_index = 0
        elif molecule.is_linear():
            shape_index = 1
        else:
            shape_index = 2

        # Acetone values from Joback thesis: Tc = 511.455  (based on experimental Tb)  Pc = 47.808    Vc = 209.000    Tb = 322.082
        # print "Tc={Tc:.2f} K, Pc={Pc:.4g} bar, Vc={Vc:.4g} cm3/mol, Tb={Tb:.4g} K, average of {isomers} isomers".format(Tc=Tc,Pc=Pc,Vc=Vc,Tb=Tb,isomers=counter)
        # print 'Estimated with Tc={Tc:.2f} K, Pc={Pc:.4g} bar (from Joback method)'.format(Tc=Tc,Pc=Pc)
        transport = TransportData(
            shapeIndex=shape_index,
            epsilon=(.77 * Tc * constants.R, 'J/mol'),
            sigma=(2.44 * (Tc / Pc)**(1. / 3), 'angstroms'),
            dipoleMoment=(0, 'C*m'),
            polarizability=(0, 'angstroms^3'),
            rotrelaxcollnum=0,  # rotational relaxation collision number at 298 K
            comment=
            'Epsilon & sigma estimated with Tc={Tc:.2f} K, Pc={Pc:.4g} bar (from Joback method)'
            .format(Tc=Tc, Pc=Pc),
        )
        return transport, None, None
Beispiel #9
0
    def get_transport_properties_via_lennard_jones_parameters(self, species):
        """
        Serves as last resort if every other method to estimate Transport Properties fails.
        
        Generate the Lennard-Jones parameters for the species.
        """
        count = sum([
            1 for atom in species.molecule[0].vertices
            if atom.is_non_hydrogen()
        ])

        if count == 1:
            sigma = (3.758e-10, "m")
            epsilon = (148.6, "K")
        elif count == 2:
            sigma = (4.443e-10, "m")
            epsilon = (110.7, "K")
        elif count == 3:
            sigma = (5.118e-10, "m")
            epsilon = (237.1, "K")
        elif count == 4:
            sigma = (4.687e-10, "m")
            epsilon = (531.4, "K")
        elif count == 5:
            sigma = (5.784e-10, "m")
            epsilon = (341.1, "K")
        else:
            sigma = (5.949e-10, "m")
            epsilon = (399.3, "K")

        if len(species.molecule[0].atoms) == 1:
            shape_index = 0
        elif species.molecule[0].is_linear():
            shape_index = 1
        else:
            shape_index = 2

        transport = TransportData(
            shapeIndex=shape_index,
            epsilon=epsilon,
            sigma=sigma,
            dipoleMoment=(0, 'C*m'),
            polarizability=(0, 'angstroms^3'),
            rotrelaxcollnum=0,  # rotational relaxation collision number at 298 K
            comment=
            'Epsilon & sigma estimated with fixed Lennard Jones Parameters. This is the fallback method! Try improving transport databases!'
        )

        return transport, None, None
Beispiel #10
0
    def getTransportPropertiesViaGroupEstimates(self, species):
        """
        Return the set of transport parameters corresponding to a given
        :class:`Species` object `species` by estimation using the group
        additivity values. If no group additivity values are loaded, a
        :class:`DatabaseError` is raised.
        """

        Tc = 0
        Pc = 0
        Tb = 0
        Vc = 0
        counter = 0

        # assume that the stablest resonance isomer has already been put as the first
        # and that we want the transport properties of this isomer
        molecule = species.molecule[0]
        molecule.clearLabeledAtoms()
        molecule.updateAtomTypes()
        criticalPoint = self.estimateCriticalPropertiesViaGroupAdditivity(
            molecule)
        Tc = criticalPoint.Tc
        Pc = criticalPoint.Pc
        Vc = criticalPoint.Vc
        Tb = criticalPoint.Tb
        if criticalPoint.linear != molecule.isLinear():
            logging.warning(
                "Group-based structure index and isLinear() function disagree about linearity of {mol!r}"
                .format(mol=molecule))
        shapeIndex = 1 if molecule.isLinear() else 2

        # Acetone values from Joback thesis: Tc = 511.455  (based on experimental Tb)  Pc = 47.808    Vc = 209.000    Tb = 322.082
        #print "Tc={Tc:.2f} K, Pc={Pc:.4g} bar, Vc={Vc:.4g} cm3/mol, Tb={Tb:.4g} K, average of {isomers} isomers".format(Tc=Tc,Pc=Pc,Vc=Vc,Tb=Tb,isomers=counter)
        #print 'Estimated with Tc={Tc:.2f} K, Pc={Pc:.4g} bar (from Joback method)'.format(Tc=Tc,Pc=Pc)
        transport = TransportData(
            shapeIndex=shapeIndex,  # 1 if linear, else 2
            epsilon=(.77 * Tc * constants.R, 'J/mol'),
            sigma=(2.44 * (Tc / Pc)**(1. / 3), 'angstroms'),
            dipoleMoment=(0, 'C*m'),
            polarizability=(0, 'angstroms^3'),
            rotrelaxcollnum=0,  # rotational relaxation collision number at 298 K
            comment=
            'Epsilon & sigma estimated with Tc={Tc:.2f} K, Pc={Pc:.4g} bar (from Joback method)'
            .format(Tc=Tc, Pc=Pc),
        )
        return (transport, None, None)
Beispiel #11
0
    def test_species(self):
        """
        Test loading a species from input file-like kew word arguments
        """
        label0 = 'CH2O'
        kwargs = {
            'E0': (28.69, 'kcal/mol'),
            'structure':
            SMILES('C=O'),
            'collisionModel':
            TransportData(sigma=(3.69e-10, 'm'), epsilon=(4.0, 'kJ/mol')),
            'energyTransferModel':
            SingleExponentialDown(alpha0=(0.956, 'kJ/mol'),
                                  T0=(300, 'K'),
                                  n=0.95),
            'spinMultiplicity':
            1,
            'opticalIsomers':
            1,
            'modes': [
                HarmonicOscillator(
                    frequencies=([1180, 1261, 1529, 1764, 2931, 2999],
                                 'cm^-1')),
                NonlinearRotor(rotationalConstant=([
                    1.15498821005263, 1.3156969584727, 9.45570474524524
                ], "cm^-1"),
                               symmetry=2,
                               quantum=False),
                IdealGasTranslation(mass=(30.0106, "g/mol")),
            ]
        }

        spc0 = species(label0, **kwargs)
        self.assertEqual(spc0.label, 'CH2O')
        self.assertEqual(spc0.smiles, 'C=O')
        self.assertAlmostEqual(spc0.conformer.E0.value_si, 120038.96)
        self.assertEqual(spc0.conformer.spin_multiplicity, 1)
        self.assertEqual(spc0.conformer.optical_isomers, 1)
        self.assertEqual(len(spc0.conformer.modes), 3)
        self.assertIsInstance(spc0.transport_data, TransportData)
        self.assertIsInstance(spc0.energy_transfer_model,
                              SingleExponentialDown)
Beispiel #12
0
    def setUp(self):
        """
        A function run before each unit test in this class.
        """
        self.shapeIndex = 1
        self.epsilon = Energy(2.104, 'kJ/mol')
        self.sigma = Length(3.402, 'angstroms')
        self.dipoleMoment = DipoleMoment(1.000, 'C*m')
        self.polarizability = Volume(0.134, 'angstroms^3')
        self.rotrelaxcollnum = 0.000
        self.comment = 'test'

        self.transport = TransportData(
            shapeIndex=self.shapeIndex,
            epsilon=self.epsilon,
            sigma=self.sigma,
            dipoleMoment=self.dipoleMoment,
            polarizability=self.polarizability,
            rotrelaxcollnum=self.rotrelaxcollnum,
            comment=self.comment,
        )
Beispiel #13
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
Beispiel #14
0
    def setUp(self):
        """
        A function run before each unit test in this class.
        """
        self.nC4H10O = Species(
            label='n-C4H10O',
            conformer=Conformer(
                E0=(-317.807, 'kJ/mol'),
                modes=[
                    IdealGasTranslation(mass=(74.07, "g/mol")),
                    NonlinearRotor(inertia=([41.5091, 215.751,
                                             233.258], "amu*angstrom^2"),
                                   symmetry=1),
                    HarmonicOscillator(frequencies=([
                        240.915, 341.933, 500.066, 728.41, 809.987, 833.93,
                        926.308, 948.571, 1009.3, 1031.46, 1076, 1118.4,
                        1184.66, 1251.36, 1314.36, 1321.42, 1381.17, 1396.5,
                        1400.54, 1448.08, 1480.18, 1485.34, 1492.24, 1494.99,
                        1586.16, 2949.01, 2963.03, 2986.19, 2988.1, 2995.27,
                        3026.03, 3049.05, 3053.47, 3054.83, 3778.88
                    ], "cm^-1")),
                    HinderedRotor(inertia=(0.854054, "amu*angstrom^2"),
                                  symmetry=1,
                                  fourier=([[
                                      0.25183, -1.37378, -2.8379, 0.0305112,
                                      0.0028088
                                  ],
                                            [
                                                0.458307, 0.542121, -0.599366,
                                                -0.00283925, 0.0398529
                                            ]], "kJ/mol")),
                    HinderedRotor(
                        inertia=(8.79408, "amu*angstrom^2"),
                        symmetry=1,
                        fourier=([[
                            0.26871, -0.59533, -8.15002, -0.294325, -0.145357
                        ], [1.1884, 0.99479, -0.940416, -0.186538,
                            0.0309834]], "kJ/mol")),
                    HinderedRotor(inertia=(7.88153, "amu*angstrom^2"),
                                  symmetry=1,
                                  fourier=([[
                                      -4.67373, 2.03735, -6.25993, -0.27325,
                                      -0.048748
                                  ],
                                            [
                                                -0.982845, 1.76637, -1.57619,
                                                0.474364, -0.000681718
                                            ]], "kJ/mol")),
                    HinderedRotor(inertia=(2.81525, "amu*angstrom^2"),
                                  symmetry=3,
                                  barrier=(2.96807, "kcal/mol")),
                ],
                spin_multiplicity=1,
                optical_isomers=1,
            ),
            molecular_weight=(74.07, "g/mol"),
            transport_data=TransportData(sigma=(5.94, 'angstrom'),
                                         epsilon=(559, 'K')),
            energy_transfer_model=SingleExponentialDown(
                alpha0=(447.5 * 0.011962, "kJ/mol"), T0=(300, "K"), n=0.85),
        )

        self.nC4H8 = Species(
            label='n-C4H8',
            conformer=Conformer(
                E0=(-17.8832, 'kJ/mol'),
                modes=[
                    IdealGasTranslation(mass=(56.06, "g/mol")),
                    NonlinearRotor(inertia=([22.2748, 122.4,
                                             125.198], "amu*angstrom^2"),
                                   symmetry=1),
                    HarmonicOscillator(frequencies=([
                        308.537, 418.67, 636.246, 788.665, 848.906, 936.762,
                        979.97, 1009.48, 1024.22, 1082.96, 1186.38, 1277.55,
                        1307.65, 1332.87, 1396.67, 1439.09, 1469.71, 1484.45,
                        1493.19, 1691.49, 2972.12, 2994.31, 3018.48, 3056.87,
                        3062.76, 3079.38, 3093.54, 3174.52
                    ], "cm^-1")),
                    HinderedRotor(inertia=(5.28338, "amu*angstrom^2"),
                                  symmetry=1,
                                  fourier=([[
                                      -0.579364, -0.28241, -4.46469, 0.143368,
                                      0.126756
                                  ],
                                            [
                                                1.01804, -0.494628,
                                                -0.00318651, -0.245289,
                                                0.193728
                                            ]], "kJ/mol")),
                    HinderedRotor(
                        inertia=(2.60818, "amu*angstrom^2"),
                        symmetry=3,
                        fourier=([[
                            0.0400372, 0.0301986, -6.4787, -0.0248675,
                            -0.0324753
                        ], [0.0312541, 0.0538, -0.493785, 0.0965968,
                            0.125292]], "kJ/mol")),
                ],
                spin_multiplicity=1,
                optical_isomers=1,
            ),
        )

        self.H2O = Species(
            label='H2O',
            conformer=Conformer(
                E0=(-269.598, 'kJ/mol'),
                modes=[
                    IdealGasTranslation(mass=(18.01, "g/mol")),
                    NonlinearRotor(inertia=([0.630578, 1.15529,
                                             1.78586], "amu*angstrom^2"),
                                   symmetry=2),
                    HarmonicOscillator(
                        frequencies=([1622.09, 3771.85, 3867.85], "cm^-1")),
                ],
                spin_multiplicity=1,
                optical_isomers=1,
            ),
        )

        self.N2 = Species(
            label='N2',
            molecular_weight=(28.04, "g/mol"),
            transport_data=TransportData(sigma=(3.41, "angstrom"),
                                         epsilon=(124, "K")),
            energy_transfer_model=None,
        )

        self.TS = TransitionState(
            label='TS',
            conformer=Conformer(
                E0=(-42.4373, "kJ/mol"),
                modes=[
                    IdealGasTranslation(mass=(74.07, "g/mol")),
                    NonlinearRotor(inertia=([40.518, 232.666,
                                             246.092], "u*angstrom**2"),
                                   symmetry=1,
                                   quantum=False),
                    HarmonicOscillator(frequencies=([
                        134.289, 302.326, 351.792, 407.986, 443.419, 583.988,
                        699.001, 766.1, 777.969, 829.671, 949.753, 994.731,
                        1013.59, 1073.98, 1103.79, 1171.89, 1225.91, 1280.67,
                        1335.08, 1373.9, 1392.32, 1417.43, 1469.51, 1481.61,
                        1490.16, 1503.73, 1573.16, 2972.85, 2984.3, 3003.67,
                        3045.78, 3051.77, 3082.37, 3090.44, 3190.73, 3708.52
                    ], "kayser")),
                    HinderedRotor(inertia=(2.68206, "amu*angstrom^2"),
                                  symmetry=3,
                                  barrier=(3.35244, "kcal/mol")),
                    HinderedRotor(inertia=(9.77669, "amu*angstrom^2"),
                                  symmetry=1,
                                  fourier=([[
                                      0.208938, -1.55291, -4.05398, -0.105798,
                                      -0.104752
                                  ],
                                            [
                                                2.00518, -0.020767, -0.333595,
                                                0.137791, -0.274578
                                            ]], "kJ/mol")),
                ],
                spin_multiplicity=1,
                optical_isomers=1,
            ),
            frequency=(-2038.34, 'cm^-1'),
        )

        self.reaction = Reaction(
            label='dehydration',
            reactants=[self.nC4H10O],
            products=[self.nC4H8, self.H2O],
            transition_state=self.TS,
        )

        self.network = Network(
            label='n-butanol',
            isomers=[Configuration(self.nC4H10O)],
            reactants=[],
            products=[Configuration(self.nC4H8, self.H2O)],
            path_reactions=[self.reaction],
            bath_gas={self.N2: 1.0},
        )
Beispiel #15
0
    def test_reaction(self):
        """
        Test loading a reaction from input file-like kew word arguments
        """

        species(label='methoxy',
                structure=SMILES('C[O]'),
                E0=(9.44, 'kcal/mol'),
                modes=[
                    HarmonicOscillator(frequencies=(
                        [758, 960, 1106, 1393, 1403, 1518, 2940, 3019, 3065],
                        'cm^-1')),
                    NonlinearRotor(rotationalConstant=([0.916, 0.921,
                                                        5.251], "cm^-1"),
                                   symmetry=3,
                                   quantum=False),
                    IdealGasTranslation(mass=(31.01843, "g/mol"))
                ],
                spinMultiplicity=2,
                opticalIsomers=1,
                molecularWeight=(31.01843, 'amu'),
                collisionModel=TransportData(sigma=(3.69e-10, 'm'),
                                             epsilon=(4.0, 'kJ/mol')),
                energyTransferModel=SingleExponentialDown(alpha0=(0.956,
                                                                  'kJ/mol'),
                                                          T0=(300, 'K'),
                                                          n=0.95))

        species(label='formaldehyde',
                E0=(28.69, 'kcal/mol'),
                molecularWeight=(30.0106, "g/mol"),
                collisionModel=TransportData(sigma=(3.69e-10, 'm'),
                                             epsilon=(4.0, 'kJ/mol')),
                energyTransferModel=SingleExponentialDown(alpha0=(0.956,
                                                                  'kJ/mol'),
                                                          T0=(300, 'K'),
                                                          n=0.95),
                spinMultiplicity=1,
                opticalIsomers=1,
                modes=[
                    HarmonicOscillator(
                        frequencies=([1180, 1261, 1529, 1764, 2931, 2999],
                                     'cm^-1')),
                    NonlinearRotor(rotationalConstant=([
                        1.15498821005263, 1.3156969584727, 9.45570474524524
                    ], "cm^-1"),
                                   symmetry=2,
                                   quantum=False),
                    IdealGasTranslation(mass=(30.0106, "g/mol"))
                ])

        species(label='H',
                E0=(0.000, 'kcal/mol'),
                molecularWeight=(1.00783, "g/mol"),
                collisionModel=TransportData(sigma=(3.69e-10, 'm'),
                                             epsilon=(4.0, 'kJ/mol')),
                energyTransferModel=SingleExponentialDown(alpha0=(0.956,
                                                                  'kJ/mol'),
                                                          T0=(300, 'K'),
                                                          n=0.95),
                modes=[IdealGasTranslation(mass=(1.00783, "g/mol"))],
                spinMultiplicity=2,
                opticalIsomers=1)

        transitionState(
            label='TS3',
            E0=(34.1, 'kcal/mol'),
            spinMultiplicity=2,
            opticalIsomers=1,
            frequency=(-967, 'cm^-1'),
            modes=[
                HarmonicOscillator(frequencies=(
                    [466, 581, 1169, 1242, 1499, 1659, 2933, 3000], 'cm^-1')),
                NonlinearRotor(rotationalConstant=([0.970, 1.029,
                                                    3.717], "cm^-1"),
                               symmetry=1,
                               quantum=False),
                IdealGasTranslation(mass=(31.01843, "g/mol"))
            ])

        reactants = ['formaldehyde', 'H']
        products = ['methoxy']
        tunneling = 'Eckart'

        rxn = reaction('CH2O+H=Methoxy',
                       reactants,
                       products,
                       'TS3',
                       tunneling=tunneling)
        self.assertEqual(rxn.label, 'CH2O+H=Methoxy')
        self.assertEqual(len(rxn.reactants), 2)
        self.assertEqual(len(rxn.products), 1)
        self.assertAlmostEqual(rxn.reactants[0].conformer.E0.value_si, 0)
        self.assertAlmostEqual(rxn.reactants[1].conformer.E0.value_si,
                               120038.96)
        self.assertAlmostEqual(rxn.products[0].conformer.E0.value_si, 39496.96)
        self.assertAlmostEqual(rxn.transition_state.conformer.E0.value_si,
                               142674.4)
        self.assertAlmostEqual(rxn.transition_state.frequency.value_si, -967.0)
        self.assertIsInstance(rxn.transition_state.tunneling, Eckart)