Skip to content

Commit

Permalink
Dump and parse YAML files in Cantherm
Browse files Browse the repository at this point in the history
  • Loading branch information
alongd committed Jul 4, 2018
1 parent 3441954 commit f100c03
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 27 deletions.
71 changes: 54 additions & 17 deletions rmgpy/cantherm/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
from rmgpy.kinetics.chebyshev import Chebyshev
from rmgpy.kinetics.falloff import ThirdBody, Lindemann, Troe
from rmgpy.kinetics.kineticsdata import KineticsData, PDepKineticsData
from rmgpy.kinetics.model import TunnelingModel
from rmgpy.kinetics.tunneling import Wigner, Eckart

from rmgpy.pdep.configuration import Configuration
Expand All @@ -65,6 +66,7 @@
from rmgpy.cantherm.statmech import StatMechJob, assign_frequency_scale_factor
from rmgpy.cantherm.thermo import ThermoJob
from rmgpy.cantherm.pdep import PressureDependenceJob
from rmgpy.cantherm.common import is_pdep

################################################################################

Expand All @@ -76,6 +78,7 @@

################################################################################


def species(label, *args, **kwargs):
global speciesDict, jobList
if label in speciesDict:
Expand Down Expand Up @@ -124,15 +127,26 @@ def species(label, *args, **kwargs):
else:
raise TypeError('species() got an unexpected keyword argument {0!r}.'.format(key))

if structure: spec.molecule = [structure]
if structure:
spec.molecule = [structure]
spec.conformer = Conformer(E0=E0, modes=modes, spinMultiplicity=spinMultiplicity, opticalIsomers=opticalIsomers)
spec.molecularWeight = molecularWeight
if molecularWeight is not None:
spec.molecularWeight = molecularWeight
else:
if structure:
# If a structure was given, simply calling spec.molecularWeight will calculate the molecular weight
spec.molecularWeight = spec.molecularWeight
elif is_pdep(jobList):
# 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 cannot be reconstructed.".format(spec.label))
spec.transportData = collisionModel
spec.energyTransferModel = energyTransferModel
spec.thermo = thermo

return spec


def transitionState(label, *args, **kwargs):
global transitionStateDict
if label in transitionStateDict:
Expand Down Expand Up @@ -173,9 +187,9 @@ def transitionState(label, *args, **kwargs):

return ts


def reaction(label, reactants, products, transitionState, kinetics=None, tunneling=''):
global reactionDict, speciesDict, transitionStateDict
#label = 'reaction'+transitionState
if label in reactionDict:
label = label+transitionState
if label in reactionDict:
Expand All @@ -194,9 +208,9 @@ def reaction(label, reactants, products, transitionState, kinetics=None, tunneli
raise ValueError('Unknown tunneling model {0!r}.'.format(tunneling))
rxn = Reaction(label=label, reactants=reactants, products=products, transitionState=transitionState, kinetics=kinetics)
reactionDict[label] = rxn

return rxn


def network(label, isomers=None, reactants=None, products=None, pathReactions=None, bathGas=None):
global networkDict, speciesDict, reactionDict
logging.info('Loading network {0}...'.format(label))
Expand Down Expand Up @@ -266,6 +280,7 @@ def network(label, isomers=None, reactants=None, products=None, pathReactions=No
)
networkDict[label] = network


def kinetics(label, Tmin=None, Tmax=None, Tlist=None, Tcount=0, sensitivity_conditions=None):
global jobList, reactionDict
try:
Expand All @@ -276,6 +291,7 @@ def kinetics(label, Tmin=None, Tmax=None, Tlist=None, Tcount=0, sensitivity_cond
sensitivity_conditions=sensitivity_conditions)
jobList.append(job)


def statmech(label):
global jobList, speciesDict, transitionStateDict
if label in speciesDict or label in transitionStateDict:
Expand All @@ -287,6 +303,7 @@ def statmech(label):
else:
raise ValueError('Unknown species or transition state label {0!r} for statmech() job.'.format(label))


def thermo(label, thermoClass):
global jobList, speciesDict
try:
Expand All @@ -296,6 +313,7 @@ def thermo(label, thermoClass):
job = ThermoJob(species=spec, thermoClass=thermoClass)
jobList.append(job)


def pressureDependence(label,
Tmin=None, Tmax=None, Tcount=0, Tlist=None,
Pmin=None, Pmax=None, Pcount=0, Plist=None,
Expand All @@ -315,17 +333,22 @@ def pressureDependence(label,
rmgmode=rmgmode, sensitivity_conditions=sensitivity_conditions)
jobList.append(job)


def SMILES(smiles):
return Molecule().fromSMILES(smiles)


def adjacencyList(adj):
return Molecule().fromAdjacencyList(adj)


def InChI(inchi):
return Molecule().fromInChI(inchi)


################################################################################


def loadInputFile(path):
"""
Load the CanTherm input file located at `path` on disk, and return a list of
Expand Down Expand Up @@ -388,27 +411,41 @@ def loadInputFile(path):
logging.error('The input file {0!r} was invalid:'.format(path))
raise

modelChemistry = local_context.get('modelChemistry', '')
model_chemistry = local_context.get('modelChemistry', '')
level_of_theory = local_context.get('levelOfTheory', '')
author = local_context.get('author', '')
if 'frequencyScaleFactor' not in local_context:
logging.debug('Assigning a frequencyScaleFactor according to the modelChemistry...')
frequencyScaleFactor = assign_frequency_scale_factor(modelChemistry)
frequency_scale_factor = assign_frequency_scale_factor(model_chemistry)
else:
frequencyScaleFactor = local_context.get('frequencyScaleFactor')
useHinderedRotors = local_context.get('useHinderedRotors', True)
useAtomCorrections = local_context.get('useAtomCorrections', True)
useBondCorrections = local_context.get('useBondCorrections', False)
atomEnergies = local_context.get('atomEnergies', None)
frequency_scale_factor = local_context.get('frequencyScaleFactor')
use_hindered_rotors = local_context.get('useHinderedRotors', True)
use_atom_corrections = local_context.get('useAtomCorrections', True)
use_bond_corrections = local_context.get('useBondCorrections', False)
atom_energies = local_context.get('atomEnergies', None)

directory = os.path.dirname(path)

for job in jobList:
if isinstance(job, StatMechJob):
job.path = os.path.join(directory, job.path)
job.modelChemistry = modelChemistry.lower()
job.frequencyScaleFactor = frequencyScaleFactor
job.includeHinderedRotors = useHinderedRotors
job.applyAtomEnergyCorrections = useAtomCorrections
job.applyBondEnergyCorrections = useBondCorrections
job.atomEnergies = atomEnergies
job.modelChemistry = model_chemistry.lower()
job.frequencyScaleFactor = frequency_scale_factor
job.includeHinderedRotors = use_hindered_rotors
job.applyAtomEnergyCorrections = use_atom_corrections
job.applyBondEnergyCorrections = use_bond_corrections
job.atomEnergies = atom_energies
if isinstance(job, ThermoJob):
job.cantherm_species.author = author
job.cantherm_species.level_of_theory = level_of_theory
level_of_theory_energy = level_of_theory.split('//')[0]
if level_of_theory_energy != model_chemistry:
# Only log the model chemistry if it isn't identical to the first part of level_of_theory
job.cantherm_species.model_chemistry = model_chemistry
job.cantherm_species.frequency_scale_factor = frequency_scale_factor
job.cantherm_species.use_hindered_rotors = use_hindered_rotors
job.cantherm_species.use_bond_corrections = use_bond_corrections
if atom_energies is not None:
job.cantherm_species.atom_energies = atom_energies

return jobList
6 changes: 5 additions & 1 deletion rmgpy/cantherm/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@
from rmgpy.cantherm.statmech import StatMechJob
from rmgpy.cantherm.thermo import ThermoJob
from rmgpy.cantherm.pdep import PressureDependenceJob
from rmgpy.cantherm.common import is_pdep

################################################################################


class CanTherm:
"""
The :class:`CanTherm` class represents an instance of CanTherm, a tool for
Expand Down Expand Up @@ -253,8 +255,10 @@ def execute(self):

# run thermo jobs (printing out thermo stuff)
for job in self.jobList:
if isinstance(job,ThermoJob) or isinstance(job, StatMechJob):
if isinstance(job, ThermoJob):
job.execute(outputFile=outputFile, plot=self.plot)
if isinstance(job, StatMechJob):
job.execute(outputFile=outputFile, plot=self.plot, pdep=is_pdep(self.jobList))

with open(chemkinFile, 'a') as f:
f.write('\n')
Expand Down
30 changes: 24 additions & 6 deletions rmgpy/cantherm/statmech.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
from rmgpy.statmech.torsion import Torsion, HinderedRotor, FreeRotor
from rmgpy.statmech.conformer import Conformer
from rmgpy.exceptions import InputError
from rmgpy.cantherm.common import CanthermSpecies

################################################################################

Expand All @@ -66,6 +67,7 @@

################################################################################


class ScanLog(object):
"""
Represent a text file containing a table of angles and corresponding
Expand Down Expand Up @@ -180,29 +182,43 @@ def __init__(self, species, path):
self.applyAtomEnergyCorrections = True
self.applyBondEnergyCorrections = True
self.atomEnergies = None
if isinstance(species, Species):
# Currently we do not dump and load transition states in YAML form
self.cantherm_species = CanthermSpecies(species=species)

def execute(self, outputFile=None, plot=False):
def execute(self, outputFile=None, plot=False, pdep=False):
"""
Execute the statistical mechanics job, saving the results to the
given `outputFile` on disk.
`pdep` passed to load() and is used to distinguish between necessary and unnecessary
species attributes when loading a YAML file.
"""
self.load()
self.load(pdep)
if outputFile is not None:
self.save(outputFile=outputFile)
logging.debug('Finished statmech job for species {0}.'.format(self.species))
logging.debug(repr(self.species))

def load(self):
def load(self, pdep):
"""
Load the statistical mechanics parameters for each conformer from
the associated files on disk. Creates :class:`Conformer` objects for
each conformer and appends them to the list of conformers on the
species object.
"""
logging.info('Loading statistical mechanics parameters for {0}...'.format(self.species.label))

path = self.path
TS = isinstance(self.species, TransitionState)
filename, file_extension = os.path.splitext(path)
if file_extension in ['.yml', '.yaml']:
if TS:
raise ValueError('Loading transition states from a YAML file is still unsupported.')
self.cantherm_species.load_yaml(path=path, species=self.species, pdep=pdep)
self.species.conformer = self.cantherm_species.conformer
self.species.transportData = self.cantherm_species.transport_data
self.species.energyTransferModel = self.cantherm_species.energy_transfer_model
return

logging.info('Loading statistical mechanics parameters for {0}...'.format(self.species.label))

global_context = {
'__builtins__': None,
Expand Down Expand Up @@ -489,7 +505,6 @@ def load(self):

self.species.conformer = conformer


def save(self, outputFile):
"""
Save the results of the statistical mechanics job to the file located
Expand Down Expand Up @@ -567,6 +582,7 @@ def plotHinderedRotor(self, angle, Vlist, cosineRotor, fourierRotor, rotor, roto

################################################################################


def applyEnergyCorrections(E0, modelChemistry, atoms, bonds,
atomEnergies=None, applyAtomEnergyCorrections=True, applyBondEnergyCorrections=False):
"""
Expand Down Expand Up @@ -790,6 +806,7 @@ def applyEnergyCorrections(E0, modelChemistry, atoms, bonds,

return E0


class Log(object):
"""
Represent a general log file.
Expand Down Expand Up @@ -1046,6 +1063,7 @@ def projectRotors(conformer, F, rotors, linear, TS):

return numpy.sqrt(eig[-Nvib:]) / (2 * math.pi * constants.c * 100)


def assign_frequency_scale_factor(model_chemistry):
"""
Assign the frequency scaling factor according to the model chemistry.
Expand Down
16 changes: 13 additions & 3 deletions rmgpy/cantherm/thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,11 @@
from rmgpy.species import Species
from rmgpy.molecule import Molecule
from rmgpy.molecule.util import retrieveElementCount
from rmgpy.cantherm.common import CanthermSpecies

################################################################################


class ThermoJob(object):
"""
A representation of a CanTherm thermodynamics job. This job is used to
Expand All @@ -65,6 +67,7 @@ class ThermoJob(object):
def __init__(self, species, thermoClass):
self.species = species
self.thermoClass = thermoClass
self.cantherm_species = CanthermSpecies(species=species)

def execute(self, outputFile=None, plot=False):
"""
Expand All @@ -73,7 +76,13 @@ def execute(self, outputFile=None, plot=False):
"""
self.generateThermo()
if outputFile is not None:
self.save(outputFile)
self.cantherm_species.chemkin_thermo_string = self.save(outputFile)
if self.species.molecule is None or len(self.species.molecule) == 0:
logging.debug("Not generating database file for species {0}, since its structure wasn't"
" specified".format(self.species.label))
else:
self.cantherm_species.update_species_attributes(self.species)
self.cantherm_species.save_yaml(path=os.path.dirname(outputFile))
if plot:
self.plot(os.path.dirname(outputFile))

Expand All @@ -88,8 +97,8 @@ def generateThermo(self):

species = self.species

logging.info('Generating {0} thermo model for {1}...'.format(self.thermoClass, species))
logging.debug('Generating {0} thermo model for {1}...'.format(self.thermoClass, species))

Tlist = np.arange(10.0, 3001.0, 10.0, np.float64)
Cplist = np.zeros_like(Tlist)
H298 = 0.0
Expand Down Expand Up @@ -186,6 +195,7 @@ def save(self, outputFile):
f.write(species.molecule[0].toAdjacencyList(removeH=False,label=species.label))
f.write('\n')
f.close()
return chemkin_thermo_string

def plot(self, outputDirectory):
"""
Expand Down

0 comments on commit f100c03

Please sign in to comment.