def species(label, *args, **kwargs): global speciesDict, jobList if label in speciesDict: raise ValueError('Multiple occurrences of species with label {0!r}.'.format(label)) logging.info('Loading species {0}...'.format(label)) spec = Species(label=label) speciesDict[label] = spec if len(args) == 1: # The argument is a path to a conformer input file path = args[0] job = StatMechJob(species=spec, path=path) jobList.append(job) if len(kwargs) > 0: # The species parameters are given explicitly structure = None E0 = None modes = [] spinMultiplicity = 1 opticalIsomers = 1 molecularWeight = None collisionModel = None energyTransferModel = None thermo = None for key, value in kwargs.items(): if key == 'structure': structure = value elif key == 'E0': E0 = value elif key == 'modes': modes = value elif key == 'spinMultiplicity': spinMultiplicity = value elif key == 'opticalIsomers': opticalIsomers = value elif key == 'molecularWeight': molecularWeight = value elif key == 'collisionModel': collisionModel = value elif key == 'energyTransferModel': energyTransferModel = value elif key == 'thermo': thermo = value else: raise TypeError('species() got an unexpected keyword argument {0!r}.'.format(key)) if structure: spec.molecule = [structure] spec.conformer = Conformer(E0=E0, modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) spec.molecularWeight = molecularWeight spec.transportData = collisionModel spec.energyTransferModel = energyTransferModel spec.thermo = thermo return spec
def setUp(cls): """A method that is run before each unit test in this class""" spc = Species().fromSMILES('CCO') log = GaussianLog(os.path.join(os.path.dirname(__file__), 'data', 'ethylene.log')) spc.conformer = log.loadConformer()[0] coords, numbers, masses = log.loadGeometry() spc.conformer.coordinates = coords, 'angstroms' spc.conformer.number = numbers spc.conformer.mass = masses, 'amu' cls.thermo_job = ThermoJob(species=spc, thermoClass='NASA')
def test_get_str_xyz(self): """Test generating an xyz string from the species.conformer object""" log = GaussianLog(os.path.join(self.data_path, 'gaussian', 'ethylene_G3.log')) conformer = log.load_conformer()[0] coords, number, mass = log.load_geometry() conformer.coordinates, conformer.number, conformer.mass = (coords, "angstroms"), number, (mass, "amu") spc1 = Species(smiles='C=C') spc1.conformer = conformer xyz_str = get_str_xyz(spc1) expected_xyz_str = """C 0.00545100 0.00000000 0.00339700 H 0.00118700 0.00000000 1.08823200 H 0.97742900 0.00000000 -0.47841600 C -1.12745800 0.00000000 -0.70256500 H -1.12319800 0.00000000 -1.78740100 H -2.09943900 0.00000000 -0.22075700""" self.assertEqual(xyz_str, expected_xyz_str)
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
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.model = ['chebyshev', int(model[1]), int(model[2])] elif model[0].lower() == 'pdeparrhenius': job.model = ['pdeparrhenius'] # Read grain size or number of grains job.grainCount = 0 job.grainSize = Quantity(0.0, "J/mol") for i in range(2): data = readMeaningfulLine(f).split() if data[0].lower() == 'numgrains': job.grainCount = int(data[1]) elif data[0].lower() == 'grainsize': job.grainSize = Quantity(float(data[2]), data[1]) # 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.lennardJones = LennardJones( 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() # 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), ) # 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.lennardJones = LennardJones( 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, )) # 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
def species(label, *args, **kwargs): """Load a species from an input file""" global species_dict, job_list if label in species_dict: raise ValueError( 'Multiple occurrences of species with label {0!r}.'.format(label)) logging.info('Loading species {0}...'.format(label)) spec = Species(label=label) species_dict[label] = spec path = None if len(args) == 1: # The argument is a path to a conformer input file path = args[0] job = StatMechJob(species=spec, path=path) logging.debug('Added species {0} to a stat mech job.'.format(label)) job_list.append(job) elif len(args) > 1: raise InputError('species {0} can only have two non-keyword argument ' 'which should be the species label and the ' 'path to a quantum file.'.format(spec.label)) if len(kwargs) > 0: # The species parameters are given explicitly structure = None E0 = None modes = [] spin_multiplicity = 0 optical_isomers = 1 molecular_weight = None collision_model = None energy_transfer_model = None thermo = None reactive = True for key, value in kwargs.items(): if key == 'structure': structure = value elif key == 'E0': E0 = value elif key == 'modes': modes = value elif key == 'spinMultiplicity': spin_multiplicity = value elif key == 'opticalIsomers': optical_isomers = value elif key == 'molecularWeight': molecular_weight = value elif key == 'collisionModel': collision_model = value elif key == 'energyTransferModel': energy_transfer_model = value elif key == 'thermo': thermo = value elif key == 'reactive': reactive = value else: raise TypeError( 'species() got an unexpected keyword argument {0!r}.'. format(key)) if structure: spec.molecule = [structure] spec.conformer = Conformer(E0=E0, modes=modes, spin_multiplicity=spin_multiplicity, optical_isomers=optical_isomers) if molecular_weight is not None: spec.molecular_weight = molecular_weight elif spec.molecular_weight is None and is_pdep(job_list): # If a structure was given, simply calling spec.molecular_weight will calculate the molecular weight # If one of the jobs is pdep and no molecular weight is given or calculated, raise an error raise ValueError( "No molecularWeight was entered for species {0}. Since a structure wasn't given" " as well, the molecularWeight, which is important for pressure dependent jobs," " cannot be reconstructed.".format(spec.label)) spec.transport_data = collision_model spec.energy_transfer_model = energy_transfer_model spec.thermo = thermo spec.reactive = reactive if spec.reactive and path is None and spec.thermo is None and spec.conformer.E0 is None: if not spec.molecule: raise InputError( 'Neither thermo, E0, species file path, nor structure specified, cannot estimate' ' thermo properties of species {0}'.format(spec.label)) try: db = get_db('thermo') if db is None: raise DatabaseError('Thermo database is None.') except DatabaseError: logging.warning( "The database isn't loaded, cannot estimate thermo for {0}. " "If it is a bath gas, set reactive = False to avoid generating " "thermo.".format(spec.label)) else: logging.info( 'No E0 or thermo found, estimating thermo and E0 of species {0} using' ' RMG-Database...'.format(spec.label)) spec.thermo = db.get_thermo_data(spec) if spec.thermo.E0 is None: th = spec.thermo.to_wilhoit() spec.conformer.E0 = th.E0 spec.thermo.E0 = th.E0 else: spec.conformer.E0 = spec.thermo.E0 if spec.reactive and spec.thermo and not spec.has_statmech( ) and structure is not None: # generate stat mech info if it wasn't provided before spec.generate_statmech() if not energy_transfer_model: # default to RMG's method of generating energy_transfer_model spec.generate_energy_transfer_model() return spec
def species(label, *args, **kwargs): global speciesDict, jobList if label in speciesDict: raise ValueError( 'Multiple occurrences of species with label {0!r}.'.format(label)) logging.info('Loading species {0}...'.format(label)) spec = Species(label=label) speciesDict[label] = spec if len(args) == 1: # The argument is a path to a conformer input file path = args[0] job = StatMechJob(species=spec, path=path) jobList.append(job) if len(kwargs) > 0: # The species parameters are given explicitly structure = None E0 = None modes = [] spinMultiplicity = 1 opticalIsomers = 1 molecularWeight = None collisionModel = None energyTransferModel = None thermo = None for key, value in kwargs.items(): if key == 'structure': structure = value elif key == 'E0': E0 = value elif key == 'modes': modes = value elif key == 'spinMultiplicity': spinMultiplicity = value elif key == 'opticalIsomers': opticalIsomers = value elif key == 'molecularWeight': molecularWeight = value elif key == 'collisionModel': collisionModel = value elif key == 'energyTransferModel': energyTransferModel = value elif key == 'thermo': thermo = value else: raise TypeError( 'species() got an unexpected keyword argument {0!r}.'. format(key)) if structure: spec.molecule = [structure] spec.conformer = Conformer(E0=E0, modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) spec.molecularWeight = molecularWeight spec.transportData = collisionModel spec.energyTransferModel = energyTransferModel spec.thermo = thermo return spec
def species(label, *args, **kwargs): global speciesDict, jobList if label in speciesDict: raise ValueError('Multiple occurrences of species with label {0!r}.'.format(label)) logging.info('Loading species {0}...'.format(label)) spec = Species(label=label) speciesDict[label] = spec path = None if len(args) == 1: # The argument is a path to a conformer input file path = args[0] job = StatMechJob(species=spec, path=path) logging.debug('Added species {0} to a stat mech job.'.format(label)) jobList.append(job) elif len(args) > 1: raise InputError('species {0} can only have two non-keyword argument ' 'which should be the species label and the ' 'path to a quantum file.'.format(spec.label)) if len(kwargs) > 0: # The species parameters are given explicitly structure = None E0 = None modes = [] spinMultiplicity = 0 opticalIsomers = 1 molecularWeight = None collisionModel = None energyTransferModel = None thermo = None reactive = True for key, value in kwargs.items(): if key == 'structure': structure = value elif key == 'E0': E0 = value elif key == 'modes': modes = value elif key == 'spinMultiplicity': spinMultiplicity = value elif key == 'opticalIsomers': opticalIsomers = value elif key == 'molecularWeight': molecularWeight = value elif key == 'collisionModel': collisionModel = value elif key == 'energyTransferModel': energyTransferModel = value elif key == 'thermo': thermo = value elif key == 'reactive': reactive = value else: raise TypeError('species() got an unexpected keyword argument {0!r}.'.format(key)) if structure: spec.molecule = [structure] spec.conformer = Conformer(E0=E0, modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers) if molecularWeight is not None: spec.molecularWeight = molecularWeight elif spec.molecularWeight is None and is_pdep(jobList): # If a structure was given, simply calling spec.molecularWeight will calculate the molecular weight # If one of the jobs is pdep and no molecular weight is given or calculated, raise an error raise ValueError("No molecularWeight was entered for species {0}. Since a structure wasn't given" " as well, the molecularWeight, which is important for pressure dependent jobs," " cannot be reconstructed.".format(spec.label)) spec.transportData = collisionModel spec.energyTransferModel = energyTransferModel spec.thermo = thermo spec.reactive = reactive if spec.reactive and path is None and spec.thermo is None and spec.conformer.E0 is None: if not spec.molecule: raise InputError('Neither thermo, E0, species file path, nor structure specified, cannot estimate' ' thermo properties of species {0}'.format(spec.label)) try: db = getDB('thermo') if db is None: raise DatabaseError('Thermo database is None.') except DatabaseError: logging.warn("The database isn't loaded, cannot estimate thermo for {0}. " "If it is a bath gas, set reactive = False to avoid generating thermo.".format(spec.label)) else: logging.info('No E0 or thermo found, estimating thermo and E0 of species {0} using' ' RMG-Database...'.format(spec.label)) spec.thermo = db.getThermoData(spec) if spec.thermo.E0 is None: th = spec.thermo.toWilhoit() spec.conformer.E0 = th.E0 spec.thermo.E0 = th.E0 else: spec.conformer.E0 = spec.thermo.E0 if spec.reactive and spec.thermo and not spec.hasStatMech() and structure is not None: # generate stat mech info if it wasn't provided before spec.generateStatMech() if not energyTransferModel: # default to RMG's method of generating energyTransferModel spec.generateEnergyTransferModel() return spec