From 59d8060aee0908dd592dc221ab60c1e8173c7ca2 Mon Sep 17 00:00:00 2001 From: Alon Grinberg Dana Date: Mon, 23 Sep 2019 13:15:37 -0400 Subject: [PATCH] Make Arkane PEP8 compliant --- Arkane.py | 2 +- arkane/common.py | 20 +- arkane/commonTest.py | 28 +-- arkane/data/methoxy.py | 2 +- arkane/data/methoxy_explore.py | 2 +- arkane/encorr/corr.py | 2 - arkane/encorr/mbac.py | 2 +- arkane/explorer.py | 118 +++++---- arkane/explorerTest.py | 29 ++- arkane/gaussian.py | 43 ++-- arkane/gaussianTest.py | 14 +- arkane/input.py | 242 +++++++++---------- arkane/inputTest.py | 4 +- arkane/kinetics.py | 125 +++++----- arkane/log.py | 34 +-- arkane/main.py | 96 ++++---- arkane/mainTest.py | 2 +- arkane/molpro.py | 55 +++-- arkane/molproTest.py | 18 +- arkane/output.py | 17 +- arkane/pdep.py | 209 ++++++++-------- arkane/pdepTest.py | 22 +- arkane/qchem.py | 36 +-- arkane/qchemTest.py | 24 +- arkane/sensitivity.py | 16 +- arkane/statmech.py | 153 ++++++------ arkane/statmechTest.py | 8 +- arkane/thermo.py | 23 +- arkane/thermoTest.py | 6 +- examples/arkane/explorer/methoxy/input.py | 8 +- examples/arkane/reactions/CH3OH+HCO/ch3oh.py | 2 +- examples/arkane/reactions/CH3OH+HCO/ts.py | 2 +- 32 files changed, 662 insertions(+), 702 deletions(-) diff --git a/Arkane.py b/Arkane.py index fb4b8f3f05..6c8636ebee 100755 --- a/Arkane.py +++ b/Arkane.py @@ -54,7 +54,7 @@ arkane = Arkane() # Parse and validate the command-line arguments -arkane.parseCommandLineArguments() +arkane.parse_command_line_arguments() # Execute the job arkane.execute() diff --git a/arkane/common.py b/arkane/common.py index 5313ad462b..fa7fe87730 100644 --- a/arkane/common.py +++ b/arkane/common.py @@ -42,7 +42,7 @@ import rmgpy.constants as constants from rmgpy import __version__ -from rmgpy.molecule.element import element_list, get_element +from rmgpy.molecule.element import get_element from rmgpy.molecule.translator import to_inchi, to_inchi_key from rmgpy.pdep.collision import SingleExponentialDown from rmgpy.quantity import ScalarQuantity, ArrayQuantity @@ -58,8 +58,6 @@ from arkane.pdep import PressureDependenceJob -################################################################################ - # Add a custom string representer to use block literals for multiline strings def str_repr(dumper, data): @@ -229,7 +227,7 @@ def save_yaml(self, path): def load_yaml(self, path, label=None, pdep=False): """ Load the all statMech data from the .yml file in `path` into `species` - `pdep` is a boolean specifying whether or not jobList includes a pressureDependentJob. + `pdep` is a boolean specifying whether or not job_list includes a pressureDependentJob. """ yml_file = os.path.basename(path) if label: @@ -312,26 +310,26 @@ def load_yaml(self, path, label=None, pdep=False): ################################################################################ -def is_pdep(jobList): +def is_pdep(job_list): """A helper function to determine whether a job is PressureDependenceJob or not""" - for job in jobList: + for job in job_list: if isinstance(job, PressureDependenceJob): return True return False -def check_conformer_energy(Vlist, path): +def check_conformer_energy(energies, path): """ Check to see that the starting energy of the species in the potential energy scan calculation is not 0.5 kcal/mol (or more) higher than any other energies in the scan. If so, print and log a warning message. """ - v_list = np.array(Vlist, np.float64) - v_diff = (v_list[0] - np.min(v_list)) * constants.E_h * constants.Na / 1000 - if v_diff >= 2: # we choose 2 kJ/mol to be the critical energy + energies = np.array(energies, np.float64) + e_diff = (energies[0] - np.min(energies)) * constants.E_h * constants.Na / 1000 + if e_diff >= 2: # we choose 2 kJ/mol to be the critical energy logging.warning('the species corresponding to {path} is different in energy from the lowest energy conformer ' 'by {diff} kJ/mol. This can cause significant errors in your computed rate constants.' - .format(path=os.path.basename(path), diff=v_diff)) + .format(path=os.path.basename(path), diff=e_diff)) def get_element_mass(input_element, isotope=None): diff --git a/arkane/commonTest.py b/arkane/commonTest.py index 608bde8ea3..8c2949c12d 100644 --- a/arkane/commonTest.py +++ b/arkane/commonTest.py @@ -48,7 +48,7 @@ from arkane import Arkane, input from arkane.common import ArkaneSpecies, get_element_mass -from arkane.input import jobList +from arkane.input import job_list from arkane.statmech import InputError, StatMechJob ################################################################################ @@ -81,11 +81,11 @@ class TestArkaneJob(unittest.TestCase): def setUp(cls): """A method that is run before each unit test in this class""" arkane = Arkane() - job_list = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'data', 'methoxy.py')) + job_list = arkane.load_input_file(os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'data', 'methoxy.py')) pdepjob = job_list[-1] cls.kineticsjob = job_list[0] - pdepjob.activeJRotor = True + pdepjob.active_j_rotor = True network = pdepjob.network cls.Nisom = len(network.isomers) cls.Nreac = len(network.reactants) @@ -99,9 +99,9 @@ def setUp(cls): cls.PminValue = pdepjob.Pmin.value cls.Pcount = pdepjob.Pcount cls.Tcount = pdepjob.Tcount - cls.GenTlist = pdepjob.generateTemperatureList() + cls.GenTlist = pdepjob.generate_T_list() cls.PlistValue = pdepjob.Plist.value - cls.maximumGrainSizeValue = pdepjob.maximumGrainSize.value + cls.maximum_grain_size_value = pdepjob.maximum_grain_size.value cls.method = pdepjob.method cls.rmgmode = pdepjob.rmgmode @@ -189,7 +189,7 @@ def test_maximum_grain_size_value(self): """ Test the max grain size value. """ - self.assertEqual(self.maximumGrainSizeValue, 0.5) + self.assertEqual(self.maximum_grain_size_value, 0.5) def test_method(self): """ @@ -242,7 +242,7 @@ def test_species(self): def test_species_statmech(self): """Test loading of statmech job from species input file.""" - job = jobList[-1] + job = job_list[-1] self.assertTrue(isinstance(job, StatMechJob)) job.modelChemistry = self.modelChemistry job.frequencyScaleFactor = self.frequencyScaleFactor @@ -256,7 +256,7 @@ def test_species_statmech(self): def test_species_thermo(self): """Test thermo job execution for species from separate input file.""" input.thermo('C2H4', 'NASA') - job = jobList[-1] + job = job_list[-1] filepath = os.path.join(self.directory, 'reactions', 'H+C2H4=C2H5') job.execute(output_directory=filepath) self.assertTrue(os.path.isfile(os.path.join(filepath, 'output.py'))) @@ -271,7 +271,7 @@ def test_transition_state(self): def test_transition_state_statmech(self): """Test loading of statmech job from transition state input file.""" - job = jobList[-1] + job = job_list[-1] self.assertTrue(isinstance(job, StatMechJob)) job.modelChemistry = self.modelChemistry job.frequencyScaleFactor = self.frequencyScaleFactor @@ -289,8 +289,8 @@ class TestStatmech(unittest.TestCase): def setUp(cls): """A method that is run before each unit test in this class""" arkane = Arkane() - cls.job_list = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'data', 'Benzyl', 'input.py')) + cls.job_list = arkane.load_input_file(os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'data', 'Benzyl', 'input.py')) def test_gaussian_log_file_error(self): """Test that the proper error is raised if gaussian geometry and frequency file paths are the same""" @@ -330,7 +330,7 @@ def test_dump_yaml(self): """ Test properly dumping the ArkaneSpecies object and respective sub-objects """ - job_list = self.arkane.loadInputFile(self.dump_input_path) + job_list = self.arkane.load_input_file(self.dump_input_path) for job in job_list: job.execute(output_directory=self.dump_path) self.assertTrue(os.path.isfile(self.dump_output_file)) @@ -340,7 +340,7 @@ def test_create_and_load_yaml(self): Test properly loading the ArkaneSpecies object and respective sub-objects """ # Create YAML file by running Arkane - job_list = self.arkane.loadInputFile(self.dump_input_path) + job_list = self.arkane.load_input_file(self.dump_input_path) for job in job_list: job.execute(output_directory=self.dump_path) diff --git a/arkane/data/methoxy.py b/arkane/data/methoxy.py index 12e844704f..3c8d39681d 100644 --- a/arkane/data/methoxy.py +++ b/arkane/data/methoxy.py @@ -224,7 +224,7 @@ minimumGrainCount=500, method='modified strong collision', # Other methods include: 'reservoir state', 'chemically-significant eigenvalues', - interpolationModel=('pdeparrhenius'), + interpolationModel='pdeparrhenius', activeKRotor=True, # active_j_rotor = False, # causes Arkane to crash rmgmode=False, diff --git a/arkane/data/methoxy_explore.py b/arkane/data/methoxy_explore.py index b3ccc3be90..e36471bf8f 100644 --- a/arkane/data/methoxy_explore.py +++ b/arkane/data/methoxy_explore.py @@ -231,7 +231,7 @@ maximumGrainSize=(0.5, 'kcal/mol'), minimumGrainCount=500, method='modified strong collision', - interpolationModel=('pdeparrhenius'), + interpolationModel='pdeparrhenius', activeKRotor=True, rmgmode=False, ) diff --git a/arkane/encorr/corr.py b/arkane/encorr/corr.py index a0a8d5a943..0c58156bb7 100644 --- a/arkane/encorr/corr.py +++ b/arkane/encorr/corr.py @@ -42,8 +42,6 @@ import arkane.encorr.pbac as pbac from arkane.exceptions import AtomEnergyCorrectionError, BondAdditivityCorrectionError -################################################################################ - def get_energy_correction(model_chemistry, atoms, bonds, coords, nums, multiplicity=1, atom_energies=None, apply_atom_corrections=True, diff --git a/arkane/encorr/mbac.py b/arkane/encorr/mbac.py index 7e956ebcc3..963792b5bb 100644 --- a/arkane/encorr/mbac.py +++ b/arkane/encorr/mbac.py @@ -85,7 +85,7 @@ def get_bac(model_chemistry, coords, nums, multiplicity=1, mol_corr=0.0): # Bond correction bac_bond = 0.0 - for bond in mol.getAllEdges(): + for bond in mol.get_all_edges(): atom1 = bond.atom1 atom2 = bond.atom2 symbol1 = atom1.element.symbol diff --git a/arkane/explorer.py b/arkane/explorer.py index 240bb07089..656ae4cd34 100644 --- a/arkane/explorer.py +++ b/arkane/explorer.py @@ -54,24 +54,24 @@ class ExplorerJob(object): """ def __init__(self, source, pdepjob, explore_tol, energy_tol=np.inf, flux_tol=0.0, - bathGas=None, maximumRadicalElectrons=np.inf): + bath_gas=None, maximum_radical_electrons=np.inf): self.source = source self.explore_tol = explore_tol self.energy_tol = energy_tol self.flux_tol = flux_tol - self.maximumRadicalElectrons = maximumRadicalElectrons - self.jobRxns = None + self.maximum_radical_electrons = maximum_radical_electrons + self.job_rxns = None self.networks = None self.pdepjob = pdepjob - if not hasattr(self.pdepjob, 'outputFile'): - self.pdepjob.outputFile = None + if not hasattr(self.pdepjob, 'output_file'): + self.pdepjob.output_file = None - if bathGas: - self.bathGas = bathGas - elif self.pdepjob.network and self.pdepjob.network.bathGas: - self.bathGas = self.pdepjob.network.bathGas + if bath_gas: + self.bath_gas = bath_gas + elif self.pdepjob.network and self.pdepjob.network.bath_gas: + self.bath_gas = self.pdepjob.network.bath_gas else: raise InputError('bathGas not specified in explorer block') @@ -87,47 +87,45 @@ def copy(self): flux_tol=self.flux_tol ) - def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesList=None, thermoLibrary=None, - kineticsLibrary=None): + def execute(self, output_file, plot, file_format='pdf', print_summary=True, species_list=None, + thermo_library=None, kinetics_library=None): """Execute an ExplorerJob""" logging.info('Exploring network...') rmg = RMG() rmg.species_constraints = {'allowed': ['input species', 'seed mechanisms', 'reaction libraries'], - 'maximumRadicalElectrons': self.maximumRadicalElectrons, + 'maximumRadicalElectrons': self.maximum_radical_electrons, 'explicitlyAllowedMolecules': []} rmgpy.rmg.input.rmg = rmg reaction_model = CoreEdgeReactionModel() - reaction_model.pressureDependence = self.pdepjob + reaction_model.pressure_dependence = self.pdepjob - reaction_model.pressureDependence.rmgmode = True + reaction_model.pressure_dependence.rmgmode = True - if outputFile: - reaction_model.pressureDependence.outputFile = os.path.dirname(outputFile) + if output_file: + reaction_model.pressure_dependence.output_file = os.path.dirname(output_file) kinetics_database = get_db('kinetics') thermo_database = get_db('thermo') - thermo_database.libraries['thermojobs'] = thermoLibrary - thermo_database.libraryOrder.insert(0, 'thermojobs') + thermo_database.libraries['thermojobs'] = thermo_library + thermo_database.library_order.insert(0, 'thermojobs') - kinetics_database.libraries['kineticsjobs'] = kineticsLibrary - kinetics_database.libraryOrder.insert(0, ('kineticsjobs', 'Reaction Library')) + kinetics_database.libraries['kineticsjobs'] = kinetics_library + kinetics_database.library_order.insert(0, ('kineticsjobs', 'Reaction Library')) - job_rxns = [rxn for rxn in reaction_model.core.reactions] + self.job_rxns = [rxn for rxn in reaction_model.core.reactions] - self.jobRxns = job_rxns - - if outputFile is not None: - if not os.path.exists(os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')): - os.mkdir(os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')) + if output_file is not None: + if not os.path.exists(os.path.join(reaction_model.pressure_dependence.output_file, 'pdep')): + os.mkdir(os.path.join(reaction_model.pressure_dependence.output_file, 'pdep')) else: - shutil.rmtree(os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')) - os.mkdir(os.path.join(reaction_model.pressureDependence.outputFile, 'pdep')) + shutil.rmtree(os.path.join(reaction_model.pressure_dependence.output_file, 'pdep')) + os.mkdir(os.path.join(reaction_model.pressure_dependence.output_file, 'pdep')) # get the molecular formula for the network mmol = None @@ -137,18 +135,18 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesLis else: mmol = spc.molecule[0].copy(deep=True) - form = mmol.getFormula() + form = mmol.get_formula() - for spec in list(self.bathGas.keys()) + self.source: + for spec in list(self.bath_gas.keys()) + self.source: nspec, is_new = reaction_model.make_new_species(spec, reactive=False) flags = np.array([s.molecule[0].get_formula() == form for s in reaction_model.core.species]) - reaction_model.enlarge(nspec, reactEdge=False, unimolecularReact=flags, - bimolecularReact=np.zeros((len(reaction_model.core.species), + reaction_model.enlarge(nspec, react_edge=False, unimolecular_react=flags, + bimolecular_react=np.zeros((len(reaction_model.core.species), len(reaction_model.core.species)))) reaction_model.add_seed_mechanism_to_core('kineticsjobs') - for lib in kinetics_database.libraryOrder: + for lib in kinetics_database.library_order: if lib[0] != 'kineticsjobs': reaction_model.add_reaction_library_to_edge(lib[0]) @@ -170,23 +168,23 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesLis else: raise ValueError("Reactant channels with greater than 2 reactants not supported") - reaction_model.enlarge(reactEdge=True, unimolecularReact=flags, - bimolecularReact=biflags) + reaction_model.enlarge(react_edge=True, unimolecular_react=flags, + bimolecular_react=biflags) # find the networks we're interested in networks = [] - for nwk in reaction_model.networkList: + for nwk in reaction_model.network_list: if set(nwk.source) == set(self.source): self.source = nwk.source networks.append(nwk) if len(networks) == 0: - raise ValueError('Did not generate a network with the requested source. This usually means no unimolecular' - 'reactions were generated for the source. Note that library reactions that are not' - ' properly flagged as elementary_high_p can replace RMG generated reactions that would' - ' otherwise be part of networks.') + raise ValueError('Did not generate a network with the requested source. This usually means no unimolecular ' + 'reactions were generated for the source. Note that library reactions that are not ' + 'properly flagged as elementary_high_p can replace RMG generated reactions that would ' + 'otherwise be part of networks.') for network in networks: - network.bathGas = self.bathGas + network.bath_gas = self.bath_gas self.networks = networks @@ -219,48 +217,48 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesLis if spc in checked_species: continue if forbidden_structures.is_molecule_forbidden(spc.molecule[0]): - reaction_model.remove_species_from_edge(reaction_model.reactionSystems, spc) + reaction_model.remove_species_from_edge(reaction_model.reaction_systems, spc) reaction_model.remove_empty_pdep_networks() else: checked_species.append(spc) kchar = 0.0 - for rxn in network.netReactions: # reaction_model.core.reactions+reaction_model.edge.reactions: + for rxn in network.net_reactions: # reaction_model.core.reactions+reaction_model.edge.reactions if (set(rxn.reactants) == set(self.source) and rxn.products[0].molecule[0].get_formula() == form): kchar += rxn.kinetics.get_rate_coefficient(T=temperature, P=pressure) elif (set(rxn.products) == set(self.source) and rxn.reactants[0].molecule[0].get_formula() == form): - kchar += rxn.generate_reverse_rate_coefficient(network_kinetics=True).get_rate_coefficient( - T=temperature, P=pressure) + kchar += rxn.generate_reverse_rate_coefficient( + network_kinetics=True).get_rate_coefficient(T=temperature, P=pressure) if network.get_leak_coefficient(T=temperature, P=pressure) > self.explore_tol * kchar: incomplete = True spc = network.get_maximum_leak_species(T=temperature, P=pressure) logging.info('adding new isomer {0} to network'.format(spc)) flags = np.array([s.molecule[0].get_formula() == form for s in reaction_model.core.species]) - reaction_model.enlarge((network, spc), reactEdge=False, unimolecularReact=flags, - bimolecularReact=np.zeros((len(reaction_model.core.species), + reaction_model.enlarge((network, spc), react_edge=False, unimolecular_react=flags, + bimolecular_react=np.zeros((len(reaction_model.core.species), len(reaction_model.core.species)))) flags = np.array([s.molecule[0].get_formula() == form for s in reaction_model.core.species]) - reaction_model.enlarge(reactEdge=True, unimolecularReact=flags, - bimolecularReact=np.zeros((len(reaction_model.core.species), + reaction_model.enlarge(react_edge=True, unimolecular_react=flags, + bimolecular_react=np.zeros((len(reaction_model.core.species), len(reaction_model.core.species)))) for network in self.networks: rm_rxns = [] - for rxn in network.pathReactions: # remove reactions with forbidden species + for rxn in network.path_reactions: # remove reactions with forbidden species for r in rxn.reactants + rxn.products: if forbidden_structures.is_molecule_forbidden(r.molecule[0]): rm_rxns.append(rxn) for rxn in rm_rxns: logging.info('Removing forbidden reaction: {0}'.format(rxn)) - network.pathReactions.remove(rxn) + network.path_reactions.remove(rxn) # clean up output files - if outputFile is not None: - path = os.path.join(reaction_model.pressureDependence.outputFile, 'pdep') + if output_file is not None: + path = os.path.join(reaction_model.pressure_dependence.output_file, 'pdep') for name in os.listdir(path): if name.endswith('.py') and '_' in name: if name.split('_')[-1].split('.')[0] != str(len(network.isomers)): @@ -271,8 +269,8 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesLis warns = [] - for rxn in job_rxns: - if rxn not in network.pathReactions: + for rxn in self.job_rxns: + if rxn not in network.path_reactions: warns.append('Reaction {0} in the input file was not explored during network expansion and was ' 'not included in the full network. This is likely because your explore_tol value is ' 'too high.'.format(rxn)) @@ -314,8 +312,8 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesLis network.remove_reactions(reaction_model, rxns=rxn_set, prods=product_set) - for rxn in job_rxns: - if rxn not in network.pathReactions: + for rxn in self.job_rxns: + if rxn not in network.path_reactions: warns.append( 'Reaction {0} in the input file was not included in the reduced model.'.format(rxn)) @@ -324,13 +322,13 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True, speciesLis self.pdepjob.network = network if len(self.networks) > 1: - s1, s2 = outputFile.split(".") + s1, s2 = output_file.split(".") ind = str(self.networks.index(network)) stot = s1 + "{}.".format(ind) + s2 else: - stot = outputFile + stot = output_file - self.pdepjob.execute(stot, plot, format='pdf', print_summary=True) + self.pdepjob.execute(stot, plot, file_format='pdf', print_summary=True) if os.path.isfile('network.pdf'): os.rename('network.pdf', 'network' + str(p) + '.pdf') diff --git a/arkane/explorerTest.py b/arkane/explorerTest.py index 962687e79e..ba709b3dde 100644 --- a/arkane/explorerTest.py +++ b/arkane/explorerTest.py @@ -54,20 +54,19 @@ def setUpClass(cls): """A method that is run before each unit test in this class""" arkane = Arkane() - cls.jobList = arkane.loadInputFile( + cls.job_list = arkane.load_input_file( os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'methoxy_explore.py')) - for job in cls.jobList: + for job in cls.job_list: if not isinstance(job, ExplorerJob): - job.execute(outputFile=None, plot=None) + job.execute(output_file=None, plot=None) else: - thermo_library, kinetics_library, species_list = arkane.getLibraries() - job.execute(outputFile=None, plot=None, speciesList=species_list, thermoLibrary=thermo_library, - kineticsLibrary=kinetics_library) - - cls.thermoLibrary = thermo_library - cls.kineticsLibrary = kinetics_library - cls.explorerjob = cls.jobList[-1] - cls.pdepjob = cls.jobList[-2] + thermo_library, kinetics_library, species_list = arkane.get_libraries() + job.execute(output_file=None, plot=None, thermo_library=thermo_library, + kinetics_library=kinetics_library) + cls.thermo_library = thermo_library + cls.kinetics_library = kinetics_library + cls.explorer_job = cls.job_list[-1] + cls.pdep_job = cls.job_list[-2] @classmethod def tearDownClass(cls): @@ -80,21 +79,21 @@ def test_reactions(self): """ test that the right number of reactions are in output network """ - self.assertEqual(len(self.explorerjob.networks[0].pathReactions), 6) + self.assertEqual(len(self.explorer_job.networks[0].path_reactions), 6) def test_isomers(self): """ test that the right number of isomers are in the output network """ - self.assertEqual(len(self.explorerjob.networks[0].isomers), 2) + self.assertEqual(len(self.explorer_job.networks[0].isomers), 2) def test_job_rxns(self): """ test that in this case all the reactions in the job ended up in the final network """ - for rxn in self.explorerjob.jobRxns: - self.assertIn(rxn, self.explorerjob.networks[0].pathReactions) + for rxn in self.explorer_job.job_rxns: + self.assertIn(rxn, self.explorer_job.networks[0].path_reactions) if __name__ == '__main__': diff --git a/arkane/gaussian.py b/arkane/gaussian.py index c6cfdad750..4643336b95 100644 --- a/arkane/gaussian.py +++ b/arkane/gaussian.py @@ -60,7 +60,7 @@ class GaussianLog(Log): def __init__(self, path): super(GaussianLog, self).__init__(path) - def getNumberOfAtoms(self): + def get_number_of_atoms(self): """ Return the number of atoms in the molecular configuration used in the Gaussian log file. @@ -81,7 +81,7 @@ def getNumberOfAtoms(self): return n_atoms - def loadForceConstantMatrix(self): + def load_force_constant_matrix(self): """ Return the force constant matrix from the Gaussian log file. The job that generated the log file must have the option ``iop(7/33=1)`` in @@ -93,7 +93,7 @@ def loadForceConstantMatrix(self): """ force = None - n_atoms = self.getNumberOfAtoms() + n_atoms = self.get_number_of_atoms() n_rows = n_atoms * 3 with open(self.path, 'r') as f: @@ -117,7 +117,7 @@ def loadForceConstantMatrix(self): return force - def loadGeometry(self): + def load_geometry(self): """ Return the optimum geometry of the molecular configuration from the Gaussian log file. If multiple such geometries are identified, only the @@ -156,7 +156,7 @@ def loadGeometry(self): return coord, number, mass - def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, label=''): + def load_conformer(self, symmetry=None, spin_multiplicity=0, optical_isomers=None, label=''): """ Load the molecular degree of freedom data from a log file created as the result of a Gaussian "Freq" quantum chemistry calculation. As @@ -169,10 +169,10 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, modes = [] unscaled_frequencies = [] e0 = 0.0 - if opticalIsomers is None or symmetry is None: - _opticalIsomers, _symmetry, _ = self.get_symmetry_properties() - if opticalIsomers is None: - opticalIsomers = _opticalIsomers + if optical_isomers is None or symmetry is None: + _optical_isomers, _symmetry, _ = self.get_symmetry_properties() + if optical_isomers is None: + optical_isomers = _optical_isomers if symmetry is None: symmetry = _symmetry with open(self.path, 'r') as f: @@ -180,10 +180,10 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, while line != '': # Read the spin multiplicity if not explicitly given - if spinMultiplicity == 0 and 'Multiplicity =' in line: - spinMultiplicity = int(line.split()[-1]) + if spin_multiplicity == 0 and 'Multiplicity =' in line: + spin_multiplicity = int(line.split()[-1]) logging.debug('Conformer {0} is assigned a spin multiplicity of {1}' - .format(label, spinMultiplicity)) + .format(label, spin_multiplicity)) # The data we want is in the Thermochemistry section of the output if '- Thermochemistry -' in line: @@ -239,8 +239,8 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, e0 = float(line.split()[6]) * 4.35974394e-18 * constants.Na # Read spin multiplicity if above method was unsuccessful - elif 'Electronic' in line and in_partition_functions and spinMultiplicity == 0: - spinMultiplicity = int(float(line.split()[1].replace('D', 'E'))) + elif 'Electronic' in line and in_partition_functions and spin_multiplicity == 0: + spin_multiplicity = int(float(line.split()[1].replace('D', 'E'))) elif 'Log10(Q)' in line: in_partition_functions = True @@ -251,10 +251,10 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, # Read the next line in the file line = f.readline() - return Conformer(E0=(e0 * 0.001, "kJ/mol"), modes=modes, spin_multiplicity=spinMultiplicity, - optical_isomers=opticalIsomers), unscaled_frequencies + return Conformer(E0=(e0 * 0.001, "kJ/mol"), modes=modes, spin_multiplicity=spin_multiplicity, + optical_isomers=optical_isomers), unscaled_frequencies - def loadEnergy(self, zpe_scale_factor=1.): + def load_energy(self, zpe_scale_factor=1.): """ Load the energy in J/mol from a Gaussian log file. The file is checked for a complete basis set extrapolation; if found, that value is @@ -300,7 +300,7 @@ def loadEnergy(self, zpe_scale_factor=1.): else: raise LogError('Unable to find energy in Gaussian log file.') - def loadZeroPointEnergy(self): + def load_zero_point_energy(self): """ Load the unscaled zero-point energy in J/mol from a Gaussian log file. """ @@ -326,7 +326,7 @@ def loadZeroPointEnergy(self): else: raise LogError('Unable to find zero-point energy in Gaussian log file.') - def loadScanEnergies(self): + def load_scan_energies(self): """ Extract the optimized energies in J/mol from a log file, e.g. the result of a Gaussian "Scan" quantum chemistry calculation. @@ -448,7 +448,7 @@ def load_scan_frozen_atoms(self): """ return self._load_scan_specs('F') - def loadNegativeFrequency(self): + def load_negative_frequency(self): """ Return the negative frequency from a transition state frequency calculation in cm^-1. @@ -467,8 +467,7 @@ def loadNegativeFrequency(self): frequencies.sort() frequency = [freq for freq in frequencies if freq < 0][0] if frequency is None: - raise LogError('Unable to find imaginary frequency of {1} ' - 'in Gaussian output file {0}'.format(self.path, self.species.label)) + raise LogError('Unable to find imaginary frequency in Gaussian output file {0}'.format(self.path)) return frequency def get_D1_diagnostic(self): diff --git a/arkane/gaussianTest.py b/arkane/gaussianTest.py index fad0cfb1a9..faea728e14 100644 --- a/arkane/gaussianTest.py +++ b/arkane/gaussianTest.py @@ -61,8 +61,8 @@ def test_load_ethylene_from_gaussian_log_cbsqb3(self): """ log = GaussianLog(os.path.join(os.path.dirname(__file__), 'data', 'ethylene.log')) - conformer, unscaled_frequencies = log.loadConformer() - e0 = log.loadEnergy() + conformer, unscaled_frequencies = log.load_conformer() + e0 = log.load_energy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, IdealGasTranslation)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, NonlinearRotor)]) == 1) @@ -88,8 +88,8 @@ def test_load_oxygen_from_gaussian_log(self): """ log = GaussianLog(os.path.join(os.path.dirname(__file__), 'data', 'oxygen.log')) - conformer, unscaled_frequencies = log.loadConformer() - e0 = log.loadEnergy() + conformer, unscaled_frequencies = log.load_conformer() + e0 = log.load_energy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, IdealGasTranslation)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, LinearRotor)]) == 1) @@ -116,8 +116,8 @@ def test_load_ethylene_from_gaussian_log_g3(self): """ log = GaussianLog(os.path.join(os.path.dirname(__file__), 'data', 'ethylene_G3.log')) - conformer, unscaled_frequencies = log.loadConformer() - e0 = log.loadEnergy() + conformer, unscaled_frequencies = log.load_conformer() + e0 = log.load_energy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, IdealGasTranslation)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, NonlinearRotor)]) == 1) @@ -148,7 +148,7 @@ def test_load_symmetry_and_optics(self): self.assertEqual(optical, 1) self.assertEqual(symmetry, 2) - conf = log.loadConformer()[0] + conf = log.load_conformer()[0] self.assertEqual(conf.optical_isomers, 1) found_rotor = False for mode in conf.modes: diff --git a/arkane/input.py b/arkane/input.py index c9f10af091..ef77cb89ff 100644 --- a/arkane/input.py +++ b/arkane/input.py @@ -68,64 +68,49 @@ from arkane.statmech import StatMechJob, assign_frequency_scale_factor from arkane.thermo import ThermoJob -################################################################################ - -speciesDict = {} -transitionStateDict = {} -reactionDict = {} -networkDict = {} -jobList = [] -################################################################################ +species_dict, transition_state_dict, reaction_dict, network_dict = dict(), dict(), dict(), dict() +job_list = list() def database(thermoLibraries=None, transportLibraries=None, reactionLibraries=None, frequenciesLibraries=None, kineticsFamilies='default', kineticsDepositories='default', kineticsEstimator='rate rules'): """Load the RMG database""" - if isinstance(thermoLibraries, str): - thermoLibraries = [thermoLibraries] - if isinstance(transportLibraries, str): - transportLibraries = [transportLibraries] - if isinstance(reactionLibraries, str): - reactionLibraries = [reactionLibraries] - if isinstance(frequenciesLibraries, str): - frequenciesLibraries = [frequenciesLibraries] - - databaseDirectory = settings['database.directory'] - thermoLibraries = thermoLibraries or [] - transportLibraries = transportLibraries - reactionLibraries = reactionLibraries or [] - kineticsEstimator = kineticsEstimator + thermo_libraries = [thermoLibraries] if isinstance(thermoLibraries, str) else list() + reaction_libraries = [reactionLibraries] if isinstance(reactionLibraries, str) else list() + transport_libraries = [transportLibraries] if isinstance(thermoLibraries, str) else None + + database_directory = settings['database.directory'] if kineticsDepositories == 'default': - kineticsDepositories = ['training'] + kinetics_depositories = ['training'] elif kineticsDepositories == 'all': - kineticsDepositories = None + kinetics_depositories = None else: if not isinstance(kineticsDepositories, list): raise InputError( "kineticsDepositories should be either 'default', 'all', or a list of names eg. ['training','PrIMe'].") - kineticsDepositories = kineticsDepositories + kinetics_depositories = kineticsDepositories if kineticsFamilies in ('default', 'all', 'none'): - kineticsFamilies = kineticsFamilies + kinetics_families = kineticsFamilies else: if not isinstance(kineticsFamilies, list): raise InputError( "kineticsFamilies should be either 'default', 'all', 'none', or a list of names eg. " "['H_Abstraction','R_Recombination'] or ['!Intra_Disproportionation'].") - kineticsFamilies = kineticsFamilies + kinetics_families = kineticsFamilies rmg_database = get_db() or RMGDatabase() rmg_database.load( - path=databaseDirectory, - thermoLibraries=thermoLibraries, - transportLibraries=transportLibraries, - reactionLibraries=reactionLibraries, + path=database_directory, + thermoLibraries=thermo_libraries, + transportLibraries=transport_libraries, + reactionLibraries=reaction_libraries, seedMechanisms=[], - kineticsFamilies=kineticsFamilies, - kineticsDepositories=kineticsDepositories, + kineticsFamilies=kinetics_families, + kineticsDepositories=kinetics_depositories, depository=False, # Don't bother loading the depository information, as we don't use it ) @@ -138,13 +123,13 @@ def database(thermoLibraries=None, transportLibraries=None, reactionLibraries=No def species(label, *args, **kwargs): """Load a species from an input file""" - global speciesDict, jobList - if label in speciesDict: + 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) - speciesDict[label] = spec + species_dict[label] = spec path = None if len(args) == 1: @@ -152,7 +137,7 @@ def species(label, *args, **kwargs): path = args[0] job = StatMechJob(species=spec, path=path) logging.debug('Added species {0} to a stat mech job.'.format(label)) - jobList.append(job) + 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 ' @@ -163,11 +148,11 @@ def species(label, *args, **kwargs): structure = None E0 = None modes = [] - spinMultiplicity = 0 - opticalIsomers = 1 - molecularWeight = None - collisionModel = None - energyTransferModel = None + 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(): @@ -178,15 +163,15 @@ def species(label, *args, **kwargs): elif key == 'modes': modes = value elif key == 'spinMultiplicity': - spinMultiplicity = value + spin_multiplicity = value elif key == 'opticalIsomers': - opticalIsomers = value + optical_isomers = value elif key == 'molecularWeight': - molecularWeight = value + molecular_weight = value elif key == 'collisionModel': - collisionModel = value + collision_model = value elif key == 'energyTransferModel': - energyTransferModel = value + energy_transfer_model = value elif key == 'thermo': thermo = value elif key == 'reactive': @@ -196,17 +181,18 @@ def species(label, *args, **kwargs): if structure: spec.molecule = [structure] - spec.conformer = Conformer(E0=E0, modes=modes, spin_multiplicity=spinMultiplicity, optical_isomers=opticalIsomers) - if molecularWeight is not None: - spec.molecularWeight = molecularWeight - elif spec.molecularWeight is None and is_pdep(jobList): + spec.conformer = Conformer(E0=E0, modes=modes, spin_multiplicity=spin_multiplicity, + optical_isomers=optical_isomers) + if molecular_weight is not None: + spec.molecularWeight = molecular_weight + elif spec.molecularWeight is None and is_pdep(job_list): # 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.transportData = collision_model + spec.energyTransferModel = energy_transfer_model spec.thermo = thermo spec.reactive = reactive @@ -237,7 +223,7 @@ def species(label, *args, **kwargs): # generate stat mech info if it wasn't provided before spec.generate_statmech() - if not energyTransferModel: + if not energy_transfer_model: # default to RMG's method of generating energyTransferModel spec.generate_energy_transfer_model() @@ -246,25 +232,25 @@ def species(label, *args, **kwargs): def transitionState(label, *args, **kwargs): """Load a transition state from an input file""" - global transitionStateDict - if label in transitionStateDict: + global transition_state_dict + if label in transition_state_dict: raise ValueError('Multiple occurrences of transition state with label {0!r}.'.format(label)) logging.info('Loading transition state {0}...'.format(label)) ts = TransitionState(label=label) - transitionStateDict[label] = ts + transition_state_dict[label] = ts if len(args) == 1 and len(kwargs) == 0: # The argument is a path to a conformer input file path = args[0] job = StatMechJob(species=ts, path=path) - jobList.append(job) + job_list.append(job) elif len(args) == 0: # The species parameters are given explicitly E0 = None modes = [] - spinMultiplicity = 1 - opticalIsomers = 1 + spin_multiplicity = 1 + optical_isomers = 1 frequency = None for key, value in kwargs.items(): if key == 'E0': @@ -272,15 +258,16 @@ def transitionState(label, *args, **kwargs): elif key == 'modes': modes = value elif key == 'spinMultiplicity': - spinMultiplicity = value + spin_multiplicity = value elif key == 'opticalIsomers': - opticalIsomers = value + optical_isomers = value elif key == 'frequency': frequency = value else: raise TypeError('transition_state() got an unexpected keyword argument {0!r}.'.format(key)) - ts.conformer = Conformer(E0=E0, modes=modes, spin_multiplicity=spinMultiplicity, optical_isomers=opticalIsomers) + ts.conformer = Conformer(E0=E0, modes=modes, spin_multiplicity=spin_multiplicity, + optical_isomers=optical_isomers) ts.frequency = frequency else: if len(args) == 0 and len(kwargs) == 0: @@ -293,16 +280,16 @@ def transitionState(label, *args, **kwargs): def reaction(label, reactants, products, transitionState=None, kinetics=None, tunneling=''): """Load a reaction from an input file""" - global reactionDict, speciesDict, transitionStateDict - if label in reactionDict: + global reaction_dict, species_dict, transition_state_dict + if label in reaction_dict: label = label + transitionState - if label in reactionDict: + if label in reaction_dict: raise ValueError('Multiple occurrences of reaction with label {0!r}.'.format(label)) logging.info('Loading reaction {0}...'.format(label)) - reactants = sorted([speciesDict[spec] for spec in reactants]) - products = sorted([speciesDict[spec] for spec in products]) + reactants = sorted([species_dict[spec] for spec in reactants]) + products = sorted([species_dict[spec] for spec in products]) if transitionState: - transitionState = transitionStateDict[transitionState] + transitionState = transition_state_dict[transitionState] if tunneling.lower() == 'wigner': transitionState.tunneling = Wigner(frequency=None) elif tunneling.lower() == 'eckart': @@ -341,36 +328,36 @@ def reaction(label, reactants, products, transitionState=None, kinetics=None, tu model.apply_kinetics_to_reaction(r) if isinstance(rxn, Reaction): - reactionDict[label] = rxn + reaction_dict[label] = rxn else: for i in range(len(rxn)): - reactionDict[label + str(i)] = rxn[i] + reaction_dict[label + str(i)] = rxn[i] return rxn def network(label, isomers=None, reactants=None, products=None, pathReactions=None, bathGas=None): """Load a network from an input file""" - global networkDict, speciesDict, reactionDict + global network_dict, species_dict, reaction_dict logging.info('Loading network {0}...'.format(label)) isomers0 = isomers or [] isomers = [] for isomer in isomers0: if isinstance(isomer, (list, tuple)): raise ValueError('Only one species can be present in a unimolecular isomer.') - isomers.append(speciesDict[isomer]) + isomers.append(species_dict[isomer]) reactants0 = reactants or [] reactants = [] for reactant in reactants0: if not isinstance(reactant, (list, tuple)): reactant = [reactant] - reactants.append(sorted([speciesDict[spec] for spec in reactant])) + reactants.append(sorted([species_dict[spec] for spec in reactant])) if pathReactions is None: # Only add reactions that match reactants and/or isomers - pathReactions = [] - for rxn in reactionDict.values(): + path_reactions = [] + for rxn in reaction_dict.values(): if not rxn.is_unimolecular(): # this reaction is not pressure dependent continue @@ -381,20 +368,20 @@ def network(label, isomers=None, reactants=None, products=None, pathReactions=No product_is_reactant = any( [frozenset(rxn.products) == frozenset(reactant_pair) for reactant_pair in reactants]) if reactant_is_isomer or reactant_is_reactant or product_is_isomer or product_is_reactant: - pathReactions.append(rxn) - logging.debug('Path reactions {} were found for network {}'.format([rxn.label for rxn in pathReactions], label)) + path_reactions.append(rxn) + logging.debug('Path reactions {} were found for network {}'.format( + [rxn.label for rxn in path_reactions], label)) else: - pathReactions0 = pathReactions - pathReactions = [] - for rxn in pathReactions0: - pathReactions.append(reactionDict[rxn]) + path_reactions_0 = pathReactions + path_reactions = [] + for rxn in path_reactions_0: + path_reactions.append(reaction_dict[rxn]) if products is None: # Figure out which configurations are isomers, reactant channels, and product channels products = [] - for rxn in pathReactions: - # Sort bimolecular configurations so that we always encounter them in the - # same order + for rxn in path_reactions: + # Sort bimolecular configurations so that we always encounter them in the same order # The actual order doesn't matter, as long as it is consistent rxn.reactants.sort() rxn.products.sort() @@ -416,45 +403,45 @@ def network(label, isomers=None, reactants=None, products=None, pathReactions=No for product in products0: if not isinstance(product, (list, tuple)): product = [product] - products.append(sorted([speciesDict[spec] for spec in product])) + products.append(sorted([species_dict[spec] for spec in product])) isomers = [Configuration(species) for species in isomers] reactants = [Configuration(*species) for species in reactants] products = [Configuration(*species) for species in products] - bathGas0 = bathGas or {} - bathGas = {} - for spec, fraction in bathGas0.items(): - bathGas[speciesDict[spec]] = fraction + bath_gas_0 = bathGas or {} + bath_gas = {} + for spec, fraction in bath_gas_0.items(): + bath_gas[species_dict[spec]] = fraction network = Network( label=label, isomers=isomers, reactants=reactants, products=products, - path_reactions=pathReactions, - bath_gas=bathGas, + path_reactions=path_reactions, + bath_gas=bath_gas, ) - networkDict[label] = network + network_dict[label] = network def kinetics(label, Tmin=None, Tmax=None, Tlist=None, Tcount=0, sensitivity_conditions=None): """Generate a kinetics job""" - global jobList, reactionDict + global job_list, reaction_dict try: - rxn = reactionDict[label] + rxn = reaction_dict[label] except KeyError: raise ValueError('Unknown reaction label {0!r} for kinetics() job.'.format(label)) job = KineticsJob(reaction=rxn, Tmin=Tmin, Tmax=Tmax, Tcount=Tcount, Tlist=Tlist, sensitivity_conditions=sensitivity_conditions) - jobList.append(job) + job_list.append(job) def statmech(label): """Generate a statmech job""" - global jobList, speciesDict, transitionStateDict - if label in speciesDict or label in transitionStateDict: - for job in jobList: + global job_list, species_dict, transition_state_dict + if label in species_dict or label in transition_state_dict: + for job in job_list: if job.species.label == label: break else: @@ -465,27 +452,27 @@ def statmech(label): def thermo(label, thermoClass): """Generate a thermo job""" - global jobList, speciesDict + global job_list, species_dict try: - spec = speciesDict[label] + spec = species_dict[label] except KeyError: raise ValueError('Unknown species label {0!r} for thermo() job.'.format(label)) - job = ThermoJob(species=spec, thermoClass=thermoClass) - jobList.append(job) + job = ThermoJob(species=spec, thermo_class=thermoClass) + job_list.append(job) def pressureDependence(label, Tmin=None, Tmax=None, Tcount=0, Tlist=None, Pmin=None, Pmax=None, Pcount=0, Plist=None, maximumGrainSize=None, minimumGrainCount=0, method=None, interpolationModel=None, activeKRotor=True, activeJRotor=True, rmgmode=False, sensitivity_conditions=None): """Generate a pressure dependent job""" - global jobList, networkDict + global job_list, network_dict if isinstance(interpolationModel, str): interpolationModel = (interpolationModel,) nwk = None - if label in list(networkDict.keys()): - nwk = networkDict[label] + if label in list(network_dict.keys()): + nwk = network_dict[label] job = PressureDependenceJob(network=nwk, Tmin=Tmin, Tmax=Tmax, Tcount=Tcount, Tlist=Tlist, Pmin=Pmin, Pmax=Pmax, Pcount=Pcount, Plist=Plist, @@ -493,31 +480,31 @@ def pressureDependence(label, Tmin=None, Tmax=None, Tcount=0, Tlist=None, Pmin=N method=method, interpolationModel=interpolationModel, activeKRotor=activeKRotor, activeJRotor=activeJRotor, rmgmode=rmgmode, sensitivity_conditions=sensitivity_conditions) - jobList.append(job) + job_list.append(job) def explorer(source, explore_tol=0.01, energy_tol=np.inf, flux_tol=0.0, bathGas=None, maximumRadicalElectrons=np.inf): """Generate an explorer job""" - global jobList, speciesDict - for job in jobList: + global job_list, species_dict + for job in job_list: 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] + source = [species_dict[name] for name in source] if bathGas: - bathGas0 = bathGas or {} - bathGas = {} - for spec, fraction in bathGas0.items(): - bathGas[speciesDict[spec]] = fraction + bath_gas_0 = bathGas or {} + bath_gas = {} + for spec, fraction in bath_gas_0.items(): + bath_gas[species_dict[spec]] = fraction job = ExplorerJob(source=source, pdepjob=pdepjob, explore_tol=explore_tol, - energy_tol=energy_tol, flux_tol=flux_tol, bathGas=bathGas, - maximumRadicalElectrons=maximumRadicalElectrons) - jobList.append(job) + energy_tol=energy_tol, flux_tol=flux_tol, bath_gas=bathGas, + maximum_radical_electrons=maximumRadicalElectrons) + job_list.append(job) def SMILES(smiles): @@ -535,7 +522,7 @@ def InChI(inchi): return Molecule().from_inchi(inchi) -def loadNecessaryDatabases(): +def load_necessary_databases(): """ loads transport and statmech databases """ @@ -559,19 +546,16 @@ def loadNecessaryDatabases(): ################################################################################ -def loadInputFile(path): +def load_input_file(path): """ Load the Arkane input file located at `path` on disk, and return a list of the jobs defined in that file. """ - global speciesDict, transitionStateDict, reactionDict, networkDict, jobList + global species_dict, transition_state_dict, reaction_dict, network_dict, job_list # Clear module-level variables - speciesDict = {} - transitionStateDict = {} - reactionDict = {} - networkDict = {} - jobList = [] + species_dict, transition_state_dict, reaction_dict, network_dict = dict(), dict(), dict(), dict() + job_list = [] global_context = {'__builtins__': None} local_context = { @@ -616,7 +600,7 @@ def loadInputFile(path): 'InChI': InChI, } - loadNecessaryDatabases() + load_necessary_databases() with open(path, 'r') as f: try: @@ -643,10 +627,10 @@ def loadInputFile(path): directory = os.path.dirname(path) - for rxn in reactionDict.values(): + for rxn in reaction_dict.values(): rxn.elementary_high_p = True - for job in jobList: + for job in job_list: if isinstance(job, StatMechJob): job.path = os.path.join(directory, job.path) job.modelChemistry = sp_level @@ -665,7 +649,7 @@ def loadInputFile(path): if atom_energies is not None: job.arkane_species.atom_energies = atom_energies - return jobList, reactionDict, speciesDict, transitionStateDict, networkDict + return job_list, reaction_dict, species_dict, transition_state_dict, network_dict def process_model_chemistry(model_chemistry): diff --git a/arkane/inputTest.py b/arkane/inputTest.py index 4d5ba2bea8..adae7590b0 100644 --- a/arkane/inputTest.py +++ b/arkane/inputTest.py @@ -45,7 +45,7 @@ from rmgpy.thermo.nasa import NASAPolynomial, NASA from rmgpy.transport import TransportData -from arkane.input import species, transitionState, reaction, SMILES, loadInputFile, process_model_chemistry +from arkane.input import species, transitionState, reaction, SMILES, load_input_file, process_model_chemistry ################################################################################ @@ -212,7 +212,7 @@ def test_load_input_file(self): """Test loading an Arkane input file""" path = os.path.join(os.path.dirname(os.path.dirname(rmgpy.__file__)), 'examples', 'arkane', 'networks', 'acetyl+O2', 'input.py') - job_list, reaction_dict, species_dict, transition_state_dict, network_dict = loadInputFile(path) + job_list, reaction_dict, species_dict, transition_state_dict, network_dict = load_input_file(path) self.assertEqual(len(job_list), 1) diff --git a/arkane/kinetics.py b/arkane/kinetics.py index 9407626d8c..5cce536149 100644 --- a/arkane/kinetics.py +++ b/arkane/kinetics.py @@ -75,7 +75,7 @@ def __init__(self, reaction, Tmin=None, Tmax=None, Tlist=None, Tcount=0, sensiti self.Tlist = (1 / np.linspace(1 / self.Tmax.value_si, 1 / self.Tmin.value_si, self.Tcount), 'K') self.reaction = reaction - self.kunits = None + self.k_units = None if sensitivity_conditions is not None: self.sensitivity_conditions = [quantity.Quantity(condition) for condition in sensitivity_conditions] @@ -119,7 +119,7 @@ def execute(self, output_directory=None, plot=True): If `plot` is True, then plots of the raw and fitted values for the kinetics will be saved. """ - self.generateKinetics() + self.generate_kinetics() if output_directory is not None: try: self.write_output(output_directory) @@ -147,7 +147,7 @@ def execute(self, output_directory=None, plot=True): logging.debug('Finished kinetics job for reaction {0}.'.format(self.reaction)) logging.debug(repr(self.reaction)) - def generateKinetics(self): + def generate_kinetics(self): """ Generate the kinetics data for the reaction and fit it to a modified Arrhenius model. """ @@ -179,11 +179,11 @@ def generateKinetics(self): klist[i] = self.reaction.calculate_tst_rate_coefficient(t) order = len(self.reaction.reactants) klist *= 1e6 ** (order - 1) - self.kunits = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] - self.Kequnits = {2: 'mol^2/cm^6', 1: 'mol/cm^3', 0: ' ', -1: 'cm^3/mol', -2: 'cm^6/mol^2'}[ + self.k_units = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] + self.K_eq_units = {2: 'mol^2/cm^6', 1: 'mol/cm^3', 0: ' ', -1: 'cm^3/mol', -2: 'cm^6/mol^2'}[ len(self.reaction.products) - len(self.reaction.reactants)] - self.krunits = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[len(self.reaction.products)] - self.reaction.kinetics = Arrhenius().fit_to_data(self.Tlist.value_si, klist, kunits=self.kunits) + self.k_r_units = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[len(self.reaction.products)] + self.reaction.kinetics = Arrhenius().fit_to_data(self.Tlist.value_si, klist, kunits=self.k_units) self.reaction.elementary_high_p = True def write_output(self, output_directory): @@ -193,10 +193,7 @@ def write_output(self, output_directory): """ reaction = self.reaction - ks = [] - k0s = [] - k0revs = [] - krevs = [] + ks, k0s, k0_revs, k_revs = [], [], [], [] logging.info('Saving kinetics for {0}...'.format(reaction)) @@ -237,39 +234,39 @@ def write_output(self, output_directory): ks.append(k) k0s.append(k0) - f.write('# {0:4g} K {1:11.3e} {2:11g} {3:11.3e} {4}\n'.format(T, k0, kappa, k, self.kunits)) + f.write('# {0:4g} K {1:11.3e} {2:11g} {3:11.3e} {4}\n'.format(T, k0, kappa, k, self.k_units)) f.write('# ======= =========== =========== =========== ===============\n') f.write('\n\n') f.write('# ======= ============ =========== ============ ============= =========\n') - f.write('# Temp. Kc (eq) Units krev (TST) krev (TST+T) Units\n') + f.write('# Temp. Kc (eq) Units k_rev (TST) k_rev (TST+T) Units\n') f.write('# ======= ============ =========== ============ ============= =========\n') # Initialize Object for Converting Units - if self.Kequnits != ' ': - keq_unit_converter = quantity.Units(self.Kequnits).getConversionFactorFromSI() + if self.K_eq_units != ' ': + keq_unit_converter = quantity.Units(self.K_eq_units).get_conversion_factor_from_si() else: keq_unit_converter = 1 for n, T in enumerate(t_list): k = ks[n] k0 = k0s[n] - Keq = keq_unit_converter * reaction.get_equilibrium_constant(T) # returns SI units - k0rev = k0 / Keq - krev = k / Keq - k0revs.append(k0rev) - krevs.append(krev) + K_eq = keq_unit_converter * reaction.get_equilibrium_constant(T) # returns SI units + k0_rev = k0 / K_eq + k_rev = k / K_eq + k0_revs.append(k0_rev) + k_revs.append(k_rev) f.write('# {0:4g} K {1:11.3e} {2} {3:11.3e} {4:11.3e} {5}\n'.format( - T, Keq, self.Kequnits, k0rev, krev, self.krunits)) + T, K_eq, self.K_eq_units, k0_rev, k_rev, self.k_r_units)) f.write('# ======= ============ =========== ============ ============= =========\n') f.write('\n\n') - kinetics0rev = Arrhenius().fit_to_data(t_list, np.array(k0revs), kunits=self.krunits) - kineticsrev = Arrhenius().fit_to_data(t_list, np.array(krevs), kunits=self.krunits) + kinetics_0_rev = Arrhenius().fit_to_data(t_list, np.array(k0_revs), kunits=self.k_r_units) + kinetics_rev = Arrhenius().fit_to_data(t_list, np.array(k_revs), kunits=self.k_r_units) - f.write('# krev (TST) = {0} \n'.format(kinetics0rev)) - f.write('# krev (TST+T) = {0} \n\n'.format(kineticsrev)) + f.write('# k_rev (TST) = {0} \n'.format(kinetics_0_rev)) + f.write('# k_rev (TST+T) = {0} \n\n'.format(kinetics_rev)) # Reaction path degeneracy is INCLUDED in the kinetics itself! rxn_str = 'kinetics(label={0!r}, kinetics={1!r})'.format(reaction.label, reaction.kinetics) f.write('{0}\n\n'.format(prettify(rxn_str))) @@ -347,7 +344,7 @@ def plot(self, output_directory): '<=>', ' + '.join([product.label for product in self.reaction.products])) plt.title(reaction_str) plt.xlabel('1000 / Temperature (K^-1)') - plt.ylabel('Rate coefficient ({0})'.format(self.kunits)) + plt.ylabel('Rate coefficient ({0})'.format(self.k_units)) plot_path = os.path.join(output_directory, 'plots') @@ -358,7 +355,7 @@ def plot(self, output_directory): plt.savefig(os.path.join(plot_path, filename)) plt.close() - def draw(self, output_directory, format='pdf'): + def draw(self, output_directory, file_format='pdf'): """ Generate a PDF drawing of the reaction. This requires that Cairo and its Python wrapper be available; if not, @@ -379,7 +376,7 @@ def draw(self, output_directory, format='pdf'): filename = ''.join(c for c in reaction_str if c in valid_chars) + '.pdf' path = os.path.join(drawing_path, filename) - KineticsDrawer().draw(self.reaction, format=format, path=path) + KineticsDrawer().draw(self.reaction, file_format=file_format, path=path) class KineticsDrawer(object): @@ -388,7 +385,7 @@ class KineticsDrawer(object): for a high pressure limit reaction using the Cairo 2D graphics engine. The most common use case is simply:: - KineticsDrawer().draw(reaction, format='png', path='network.png') + KineticsDrawer().draw(reaction, file_format='png', path='network.png') where ``reaction`` is the :class:`Reaction` object to draw. You can also pass a dict of options to the constructor to affect how the reaction is drawn. @@ -422,7 +419,7 @@ def clear(self): self.surface = None self.cr = None - def __getEnergyRange(self): + def _get_energy_range(self): """ Return the minimum and maximum energy in J/mol on the potential energy surface. """ @@ -437,7 +434,7 @@ def __getEnergyRange(self): self.reaction.transition_state.conformer.E0.value_si / 1000.)) return e0_min, e0_max - def __useStructureForLabel(self, configuration): + def _use_structure_for_label(self, configuration): """ Return ``True`` if the configuration should use molecular structures for its labels or ``False`` otherwise. @@ -455,14 +452,14 @@ def __useStructureForLabel(self, configuration): return use_structures - def __getTextSize(self, text, padding=2, format='pdf'): + def _get_text_size(self, text, padding=2, file_format='pdf'): try: import cairocffi as cairo except ImportError: import cairo # Use dummy surface to determine text extents - surface = create_new_surface(format) + surface = create_new_surface(file_format) cr = cairo.Context(surface) cr.set_font_size(self.options['fontSizeNormal']) extents = cr.text_extents(text) @@ -470,7 +467,7 @@ def __getTextSize(self, text, padding=2, format='pdf'): height = extents[3] + 2 * padding return [0, 0, width, height] - def __drawText(self, text, cr, x0, y0, padding=2): + def _draw_text(self, text, cr, x0, y0, padding=2): cr.save() cr.set_font_size(self.options['fontSizeNormal']) extents = cr.text_extents(text) @@ -482,19 +479,19 @@ def __drawText(self, text, cr, x0, y0, padding=2): height = extents[3] + 2 * padding return [0, 0, width, height] - def __getLabelSize(self, configuration, format='pdf'): + def _get_label_size(self, configuration, file_format='pdf'): width = 0 height = 0 bounding_rects = [] - if self.__useStructureForLabel(configuration): + if self._use_structure_for_label(configuration): for spec in configuration.species_list: - rect = MoleculeDrawer().draw(spec.molecule[0], format=format)[2] + rect = MoleculeDrawer().draw(spec.molecule[0], file_format=file_format)[2] bounding_rects.append(list(rect)) else: for spec in configuration.species_list: - bounding_rects.append(self.__getTextSize(spec.label, format=format)) + bounding_rects.append(self._get_text_size(spec.label, file_format=file_format)) - plus_rect = self.__getTextSize('+', format=format) + plus_rect = self._get_text_size('+', file_format=file_format) for rect in bounding_rects: if width < rect[2]: @@ -504,24 +501,24 @@ def __getLabelSize(self, configuration, format='pdf'): return [0, 0, width, height] - def __drawLabel(self, configuration, cr, x0, y0, format='pdf'): + def _draw_label(self, configuration, cr, x0, y0, file_format='pdf'): - bounding_rect = self.__getLabelSize(configuration, format=format) + bounding_rect = self._get_label_size(configuration, file_format=file_format) padding = 2 - use_structures = self.__useStructureForLabel(configuration) + use_structures = self._use_structure_for_label(configuration) y = y0 for i, spec in enumerate(configuration.species_list): if i > 0: - rect = self.__getTextSize('+', padding=padding, format=format) + rect = self._get_text_size('+', padding=padding, file_format=file_format) x = x0 - 0.5 * (rect[2] - bounding_rect[2]) + 2 * padding - self.__drawText('+', cr, x, y) + self._draw_text('+', cr, x, y) y += rect[3] if use_structures: molecule_drawer = MoleculeDrawer() cr.save() - rect = molecule_drawer.draw(spec.molecule[0], format=format)[2] + rect = molecule_drawer.draw(spec.molecule[0], file_format=file_format)[2] cr.restore() x = x0 - 0.5 * (rect[2] - bounding_rect[2]) cr.save() @@ -529,17 +526,17 @@ def __drawLabel(self, configuration, cr, x0, y0, format='pdf'): cr.restore() y += rect[3] else: - rect = self.__getTextSize(spec.label, padding=padding, format=format) + rect = self._get_text_size(spec.label, padding=padding, file_format=file_format) x = x0 - 0.5 * (rect[2] - bounding_rect[2]) + 2 * padding - self.__drawText(spec.label, cr, x, y) + self._draw_text(spec.label, cr, x, y) y += rect[3] return bounding_rect - def draw(self, reaction, format, path=None): + def draw(self, reaction, file_format, path=None): """ Draw the potential energy surface for the given `network` as a Cairo - surface of the given `format`. If `path` is given, the surface is + surface of the given `file_format`. If `path` is given, the surface is saved to that location on disk. """ try: @@ -557,10 +554,10 @@ def draw(self, reaction, format, path=None): # Generate the bounding rectangles for each configuration label label_rects = [] for well in self.wells: - label_rects.append(self.__getLabelSize(well, format=format)) + label_rects.append(self._get_label_size(well, file_format=file_format)) # Get energy range (use kJ/mol internally) - e0_min, e0_max = self.__getEnergyRange() + e0_min, e0_max = self._get_energy_range() e0_min *= 0.001 e0_max *= 0.001 @@ -582,9 +579,9 @@ def draw(self, reaction, format, path=None): raise InputError('Invalid value "{0}" for Eunits parameter.'.format(e_units)) # Determine height required for drawing - Eheight = self.__getTextSize('0.0', format=format)[3] + 6 - y_e0 = (e0_max - 0.0) * e_slope + padding + Eheight - height = (e0_max - e0_min) * e_slope + 2 * padding + Eheight + 6 + e_height = self._get_text_size('0.0', file_format=file_format)[3] + 6 + y_e0 = (e0_max - 0.0) * e_slope + padding + e_height + height = (e0_max - e0_min) * e_slope + 2 * padding + e_height + 6 for i in range(len(self.wells)): if 0.001 * self.wells[i].E0 == e0_min: height += label_rects[i][3] @@ -611,15 +608,15 @@ def draw(self, reaction, format, path=None): x, y = coordinates[i, :] if w < well_width: w = well_width - t -= 6 + Eheight - h += 6 + Eheight + t -= 6 + e_height + h += 6 + e_height well_rects.append([l + x - 0.5 * w, t + y + 6, w, h]) # Squish columns together from the left where possible until an isomer is encountered - oldLeft = np.min(coordinates[:, 0]) - Nleft = - 1 + old_left = np.min(coordinates[:, 0]) + n_left = - 1 columns = [] - for i in range(Nleft, -1, -1): + for i in range(n_left, -1, -1): top = well_rects[i][1] bottom = top + well_rects[i][3] for column in columns: @@ -644,7 +641,7 @@ def draw(self, reaction, format, path=None): well_rects[c][0] += delta coordinates[c, 0] += delta new_left = np.min(coordinates[:, 0]) - coordinates[:, 0] -= new_left - oldLeft + coordinates[:, 0] -= new_left - old_left # Squish columns together from the right where possible until an isomer is encountered n_right = 3 @@ -677,7 +674,7 @@ def draw(self, reaction, format, path=None): width = max([rect[2] + rect[0] for rect in well_rects]) - min([rect[0] for rect in well_rects]) + 2 * padding # Draw to the final surface - surface = create_new_surface(format=format, target=path, width=width, height=height) + surface = create_new_surface(file_format=file_format, target=path, width=width, height=height) cr = cairo.Context(surface) # Some global settings @@ -687,7 +684,7 @@ def draw(self, reaction, format, path=None): # Fill the background with white cr.set_source_rgba(1.0, 1.0, 1.0, 1.0) cr.paint() - self.__drawText('E0 ({0})'.format(e_units), cr, 15, 10, padding=2) # write units + self._draw_text('E0 ({0})'.format(e_units), cr, 15, 10, padding=2) # write units # Draw reactions e0_reac = self.wells[0].E0 * 0.001 - e0_offset @@ -774,10 +771,10 @@ def draw(self, reaction, format, path=None): cr.rectangle(x, y, label_rects[i][2], label_rects[i][3]) cr.set_source_rgba(1.0, 1.0, 1.0, 0.75) cr.fill() - self.__drawLabel(well, cr, x, y, format=format) + self._draw_label(well, cr, x, y, file_format=file_format) # Finish Cairo drawing - if format == 'png': + if file_format == 'png': surface.write_to_png(path) else: surface.finish() diff --git a/arkane/log.py b/arkane/log.py index 73e3ebfe41..e5b0a958b8 100644 --- a/arkane/log.py +++ b/arkane/log.py @@ -51,15 +51,15 @@ class Log(object): def __init__(self, path): self.path = path - def getNumberOfAtoms(self): + def get_number_of_atoms(self): """ Return the number of atoms in the molecular configuration used in the MolPro log file. """ - raise NotImplementedError("getNumberOfAtoms is not implemented for the Log class. " + raise NotImplementedError("get_number_of_atoms is not implemented for the Log class. " "This method should be implemented by a subclass.") - def loadForceConstantMatrix(self): + def load_force_constant_matrix(self): """ Return the force constant matrix (in Cartesian coordinates) from the QChem log file. If multiple such matrices are identified, @@ -67,50 +67,50 @@ def loadForceConstantMatrix(self): are J/m^2. If no force constant matrix can be found in the log file, ``None`` is returned. """ - raise NotImplementedError("loadForceConstantMatrix is not implemented for the Log class. " + raise NotImplementedError("load_force_constant_matrix is not implemented for the Log class. " "This method should be implemented by a subclass.") - def loadGeometry(self): + def load_geometry(self): """ Return the optimum geometry of the molecular configuration from the log file. If multiple such geometries are identified, only the last is returned. """ - raise NotImplementedError("loadGeometry is not implemented for the Log class. " + raise NotImplementedError("load_geometry is not implemented for the Log class. " "This method should be implemented by a subclass.") - def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, label=''): + def load_conformer(self, symmetry=None, spin_multiplicity=0, optical_isomers=None, label=''): """ Load the molecular degree of freedom data from an output file created as the result of a QChem "Freq" calculation. As QChem's guess of the external symmetry number is not always correct, you can use the `symmetry` parameter to substitute your own value; if not provided, the value in the QChem output file will be adopted. """ - raise NotImplementedError("loadConformer is not implemented for the Log class. " + raise NotImplementedError("load_conformer is not implemented for the Log class. " "This method should be implemented by a subclass.") - def loadEnergy(self, zpe_scale_factor=1.): + def load_energy(self, zpe_scale_factor=1.): """ Load the energy in J/mol from a QChem log file. Only the last energy in the file is returned. The zero-point energy is *not* included in the returned value. """ - raise NotImplementedError("loadEnergy is not implemented for the Log class. " + raise NotImplementedError("load_energy is not implemented for the Log class. " "This method should be implemented by a subclass.") - def loadZeroPointEnergy(self): + def load_zero_point_energy(self): """ Load the unscaled zero-point energy in J/mol from a QChem output file. """ - raise NotImplementedError("loadZeroPointEnergy is not implemented for the Log class. " + raise NotImplementedError("load_zero_point_energy is not implemented for the Log class. " "This method should be implemented by a subclass.") - def loadScanEnergies(self): + def load_scan_energies(self): """ Extract the optimized energies in J/mol from a QChem log file, e.g. the result of a QChem "PES Scan" quantum chemistry calculation. """ - raise NotImplementedError("loadScanEnergies is not implemented for the Log class. " + raise NotImplementedError("load_scan_energies is not implemented for the Log class. " "This method should be implemented by a subclass.") def load_scan_pivot_atoms(self): @@ -131,12 +131,12 @@ def load_scan_frozen_atoms(self): """ raise NotImplementedError("load_scan_frozen_atoms is not implemented for the Log class") - def loadNegativeFrequency(self): + def load_negative_frequency(self): """ Return the imaginary frequency from a transition state frequency calculation in cm^-1. """ - raise NotImplementedError("loadNegativeFrequency is not implemented for the Log class. " + raise NotImplementedError("load_negative_frequency is not implemented for the Log class. " "This method should be implemented by a subclass.") def get_symmetry_properties(self): @@ -146,7 +146,7 @@ def get_symmetry_properties(self): of optical isomers, the second element is the symmetry number, and the third element is the point group identified. """ - coordinates, atom_numbers, _ = self.loadGeometry() + coordinates, atom_numbers, _ = self.load_geometry() unique_id = '0' # Just some name that the SYMMETRY code gives to one of its jobs # Scratch directory that the SYMMETRY code writes its files in: scr_dir = os.path.join(os.path.abspath('.'), str('scratch')) diff --git a/arkane/main.py b/arkane/main.py index e3f9284361..90f7ced29c 100644 --- a/arkane/main.py +++ b/arkane/main.py @@ -56,7 +56,7 @@ from arkane.common import is_pdep from arkane.explorer import ExplorerJob -from arkane.input import loadInputFile +from arkane.input import load_input_file from arkane.kinetics import KineticsJob from arkane.pdep import PressureDependenceJob from arkane.statmech import StatMechJob @@ -73,9 +73,9 @@ class Arkane(object): =================== ======================================================== Attribute Description =================== ======================================================== - `jobList` A list of the jobs to execute - `inputFile` The path of the input file defining the jobs to execute - `outputDirectory` The directory in which to write the output files + `job_list` A list of the jobs to execute + `input_file` The path of the input file defining the jobs to execute + `output_directory` The directory in which to write the output files `verbose` The level of detail in the generated logging messages =================== ======================================================== @@ -86,16 +86,16 @@ class Arkane(object): attributes using either the :meth:`__init__()` method or by directly accessing the attributes, and then invoke the :meth:`execute()` method. You can also populate the attributes from the command line using the - :meth:`parseCommandLineArguments()` method before running :meth:`execute()`. + :meth:`parse_command_line_arguments()` method before running :meth:`execute()`. """ - def __init__(self, inputFile=None, outputDirectory=None, verbose=logging.INFO): - self.jobList = [] - self.inputFile = inputFile - self.outputDirectory = outputDirectory + def __init__(self, input_file=None, output_directory=None, verbose=logging.INFO): + self.job_list = [] + self.input_file = input_file + self.output_directory = output_directory self.verbose = verbose - def parseCommandLineArguments(self): + def parse_command_line_arguments(self): """ Parse the command-line arguments being passed to Arkane. This uses the :mod:`argparse` module, which ensures that the command-line arguments are @@ -131,7 +131,7 @@ def parseCommandLineArguments(self): args = parser.parse_args() # Extract the input file - self.inputFile = args.file[0] + self.input_file = args.file[0] # Extract the log verbosity self.verbose = args.verbose @@ -143,45 +143,45 @@ def parseCommandLineArguments(self): # By default the directory containing the input file is used, unless an # alternate directory is specified using the -o flag if args.output_directory and os.path.isdir(args.output_directory[0]): - self.outputDirectory = os.path.abspath(args.output_directory[0]) + self.output_directory = os.path.abspath(args.output_directory[0]) else: - self.outputDirectory = os.path.dirname(os.path.abspath(args.file[0])) + self.output_directory = os.path.dirname(os.path.abspath(args.file[0])) - def loadInputFile(self, inputFile): + def load_input_file(self, input_file): """ - Load a set of jobs from the given `inputFile` on disk. Returns the + Load a set of jobs from the given `input_file` on disk. Returns the loaded set of jobs as a list. """ - self.inputFile = inputFile - self.jobList, self.reactionDict, self.speciesDict, self.transitionStateDict, self.networkDict = loadInputFile( - self.inputFile) + self.input_file = input_file + self.job_list, self.reaction_dict, self.species_dict, self.transition_state_dict, self.network_dict = \ + load_input_file(self.input_file) logging.info('') - return self.jobList + return self.job_list def execute(self): """ Execute, in order, the jobs found in input file specified by the - `inputFile` attribute. + `input_file` attribute. """ # Initialize the logging system (both to the console and to a file in the # output directory) - initialize_log(self.verbose, os.path.join(self.outputDirectory, 'arkane.log')) + initialize_log(self.verbose, os.path.join(self.output_directory, 'arkane.log')) # Print some information to the beginning of the log log_header() # Load the input file for the job - self.jobList = self.loadInputFile(self.inputFile) + self.job_list = self.load_input_file(self.input_file) logging.info('') # Initialize (and clear!) the output files for the job - if self.outputDirectory is None: - self.outputDirectory = os.path.dirname(os.path.abspath(self.inputFile)) - output_file = os.path.join(self.outputDirectory, 'output.py') - with open(output_file, 'w') as f: + if self.output_directory is None: + self.output_directory = os.path.dirname(os.path.abspath(self.input_file)) + output_file = os.path.join(self.output_directory, 'output.py') + with open(output_file, 'w'): pass - chemkin_file = os.path.join(self.outputDirectory, 'chem.inp') + chemkin_file = os.path.join(self.output_directory, 'chem.inp') # write the chemkin files and run the thermo and then kinetics jobs with open(chemkin_file, 'w') as f: @@ -190,7 +190,7 @@ def execute(self): f.write('SPECIES\n\n') # write each species in species block - for job in self.jobList: + for job in self.job_list: if isinstance(job, ThermoJob): f.write(job.species.to_chemkin()) f.write('\n') @@ -202,11 +202,11 @@ def execute(self): # run thermo and statmech jobs (also writes thermo blocks to Chemkin file) supporting_info = [] hindered_rotor_info = [] - for job in self.jobList: + for job in self.job_list: if isinstance(job, ThermoJob): - job.execute(output_directory=self.outputDirectory, plot=self.plot) + job.execute(output_directory=self.output_directory, plot=self.plot) if isinstance(job, StatMechJob): - job.execute(output_directory=self.outputDirectory, plot=self.plot, pdep=is_pdep(self.jobList)) + job.execute(output_directory=self.output_directory, plot=self.plot, pdep=is_pdep(self.job_list)) if hasattr(job, 'supporting_info'): supporting_info.append(job.supporting_info) if hasattr(job, 'raw_hindered_rotor_data'): @@ -220,7 +220,7 @@ def execute(self): if supporting_info: # write supporting_info.csv for statmech jobs - supporting_info_file = os.path.join(self.outputDirectory, 'supporting_information.csv') + supporting_info_file = os.path.join(self.output_directory, 'supporting_information.csv') with open(supporting_info_file, 'w') as csvfile: writer = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) writer.writerow(['Label', 'Symmetry Number', 'Number of optical isomers', 'Symmetry Group', @@ -248,7 +248,7 @@ def execute(self): writer.writerow([label, row[1], row[2], row[3], rot, freq, row[7], row[8], row[9], atoms, row[12], row[13]]) if hindered_rotor_info: - hr_file = os.path.join(self.outputDirectory, 'hindered_rotor_scan_data.csv') + hr_file = os.path.join(self.output_directory, 'hindered_rotor_scan_data.csv') # find longest length to set column number for energies max_energy_length = max([len(hr[4]) for hr in hindered_rotor_info]) with open(hr_file, 'w') as csvfile: @@ -260,21 +260,21 @@ def execute(self): writer.writerow([row[0], row[1], row[2], row[3][1] * 180 / np.pi, row[5], row[6]] + [a for a in row[4]]) # run kinetics and pdep jobs (also writes reaction blocks to Chemkin file) - for job in self.jobList: + for job in self.job_list: if isinstance(job, KineticsJob): - job.execute(output_directory=self.outputDirectory, plot=self.plot) + job.execute(output_directory=self.output_directory, plot=self.plot) elif isinstance(job, PressureDependenceJob) and not any([isinstance(job, ExplorerJob) for job in - self.jobList]): + self.job_list]): # if there is an explorer job the pdep job will be run in the explorer job if job.network is None: raise InputError( 'No network matched the label of the pressureDependence block and there is no explorer block ' 'to generate a network') - job.execute(outputFile=output_file, plot=self.plot) + job.execute(output_file=output_file, plot=self.plot) elif isinstance(job, ExplorerJob): - thermo_library, kinetics_library, species_list = self.getLibraries() - job.execute(outputFile=output_file, plot=self.plot, speciesList=species_list, - thermoLibrary=thermo_library, kineticsLibrary=kinetics_library) + thermo_library, kinetics_library, species_list = self.get_libraries() + job.execute(output_file=output_file, plot=self.plot, species_list=species_list, + thermo_library=thermo_library, kinetics_library=kinetics_library) with open(chemkin_file, 'a') as f: f.write('END\n\n') @@ -282,12 +282,12 @@ def execute(self): # Print some information to the end of the log log_footer() - def getLibraries(self): + def get_libraries(self): """Get RMG kinetics and thermo libraries""" name = 'kineticsjobs' - species_list = list(self.speciesDict.values()) - reaction_list = list(self.reactionDict.values()) + species_list = list(self.species_dict.values()) + reaction_list = list(self.reaction_dict.values()) # remove duplicate species for rxn in reaction_list: @@ -313,11 +313,11 @@ def getLibraries(self): thermo_library = ThermoLibrary(name=name) for i, species in enumerate(species_list): if species.thermo: - thermo_library.loadEntry(index=i + 1, - label=species.label, - molecule=species.molecule[0].to_adjacency_list(), - thermo=species.thermo, - shortDesc=species.thermo.comment) + thermo_library.load_entry(index=i + 1, + label=species.label, + molecule=species.molecule[0].to_adjacency_list(), + thermo=species.thermo, + shortDesc=species.thermo.comment) else: logging.warning( 'Species {0} did not contain any thermo data and was omitted from the thermo library.'.format( diff --git a/arkane/mainTest.py b/arkane/mainTest.py index 0ace057527..ba525fb319 100644 --- a/arkane/mainTest.py +++ b/arkane/mainTest.py @@ -70,7 +70,7 @@ def test_arkane_examples(self): example_type_path = os.path.join(self.base_path, example_type) for example in sorted(os.listdir(example_type_path)): path = os.path.join(example_type_path, example) - arkane = Arkane(inputFile=os.path.join(path, 'input.py'), outputDirectory=path) + arkane = Arkane(input_file=os.path.join(path, 'input.py'), output_directory=path) arkane.plot = True logging.info("running {}".format(example)) arkane.execute() diff --git a/arkane/molpro.py b/arkane/molpro.py index 5372a62dfb..63d23fb423 100644 --- a/arkane/molpro.py +++ b/arkane/molpro.py @@ -44,7 +44,6 @@ from arkane.common import get_element_mass from arkane.exceptions import LogError from arkane.log import Log -from arkane.exceptions import LogError ################################################################################ @@ -59,7 +58,7 @@ class MolproLog(Log): def __init__(self, path): super(MolproLog, self).__init__(path) - def getNumberOfAtoms(self): + def get_number_of_atoms(self): """ Return the number of atoms in the molecular configuration used in the MolPro log file. @@ -80,13 +79,13 @@ def getNumberOfAtoms(self): return n_atoms - 1 - def loadForceConstantMatrix(self): + def load_force_constant_matrix(self): """ Print the force constant matrix by including the print, hessian command in the input file """ fc = None - n_atoms = self.getNumberOfAtoms() + n_atoms = self.get_number_of_atoms() n_rows = n_atoms * 3 with open(self.path, 'r') as f: @@ -110,7 +109,7 @@ def loadForceConstantMatrix(self): return fc - def loadGeometry(self): + def load_geometry(self): """ Return the optimum geometry of the molecular configuration from the Molpro .out file. If multiple such geometries are identified, only the @@ -166,7 +165,7 @@ def loadGeometry(self): return coord, number, mass - def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, label=''): + def load_conformer(self, symmetry=None, spin_multiplicity=0, optical_isomers=None, label=''): """ Load the molecular degree of freedom data from a log file created as the result of a MolPro "Freq" quantum chemistry calculation with the thermo printed. @@ -175,10 +174,10 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, modes = [] unscaled_frequencies = [] e0 = 0.0 - if opticalIsomers is None or symmetry is None: - _opticalIsomers, _symmetry, _ = self.get_symmetry_properties() - if opticalIsomers is None: - opticalIsomers = _opticalIsomers + if optical_isomers is None or symmetry is None: + _optical_isomers, _symmetry, _ = self.get_symmetry_properties() + if optical_isomers is None: + optical_isomers = _optical_isomers if symmetry is None: symmetry = _symmetry with open(self.path, 'r') as f: @@ -186,31 +185,31 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, while line != '': # Read the spin multiplicity if not explicitly given - if spinMultiplicity == 0 and 'spin' in line: + if spin_multiplicity == 0 and 'spin' in line: splits = line.replace('=', ' ').replace(',', ' ').split(' ') for i, s in enumerate(splits): if 'spin' in s: - spinMultiplicity = int(splits[i + 1]) + 1 + spin_multiplicity = int(splits[i + 1]) + 1 logging.debug( - 'Conformer {0} is assigned a spin multiplicity of {1}'.format(label, spinMultiplicity)) + 'Conformer {0} is assigned a spin multiplicity of {1}'.format(label, spin_multiplicity)) break - if spinMultiplicity == 0 and 'SPIN SYMMETRY' in line: + if spin_multiplicity == 0 and 'SPIN SYMMETRY' in line: spin_symmetry = line.split()[-1] if spin_symmetry == 'Singlet': - spinMultiplicity = 1 + spin_multiplicity = 1 elif spin_symmetry == 'Doublet': - spinMultiplicity = 2 + spin_multiplicity = 2 elif spin_symmetry == 'Triplet': - spinMultiplicity = 3 + spin_multiplicity = 3 elif spin_symmetry == 'Quartet': - spinMultiplicity = 4 + spin_multiplicity = 4 elif spin_symmetry == 'Quintet': - spinMultiplicity = 5 + spin_multiplicity = 5 elif spin_symmetry == 'Sextet': - spinMultiplicity = 6 - if spinMultiplicity: + spin_multiplicity = 6 + if spin_multiplicity: logging.debug( - 'Conformer {0} is assigned a spin multiplicity of {1}'.format(label, spinMultiplicity)) + 'Conformer {0} is assigned a spin multiplicity of {1}'.format(label, spin_multiplicity)) break # The data we want is in the Thermochemistry section of the output @@ -266,10 +265,10 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, # Read the next line in the file line = f.readline() - return Conformer(E0=(e0 * 0.001, "kJ/mol"), modes=modes, spin_multiplicity=spinMultiplicity, - optical_isomers=opticalIsomers), unscaled_frequencies + return Conformer(E0=(e0 * 0.001, "kJ/mol"), modes=modes, spin_multiplicity=spin_multiplicity, + optical_isomers=optical_isomers), unscaled_frequencies - def loadEnergy(self, zpe_scale_factor=1.): + def load_energy(self, zpe_scale_factor=1.): """ Return either the f12 or MRCI energy in J/mol from a Molpro Logfile. If the MRCI job outputted the MRCI+Davidson energy, the latter is returned. @@ -347,7 +346,7 @@ def loadEnergy(self, zpe_scale_factor=1.): else: raise LogError('Unable to find energy in Molpro log file {0}.'.format(self.path)) - def loadZeroPointEnergy(self): + def load_zero_point_energy(self): """ Load the unscaled zero-point energy in J/mol from a MolPro log file. """ @@ -373,7 +372,7 @@ def loadZeroPointEnergy(self): raise LogError('Unable to find zero-point energy in Molpro log file. Make sure that the ' 'keyword {frequencies, thermo, print,thermo} is included in the input file.') - def loadNegativeFrequency(self): + def load_negative_frequency(self): """ Return the negative frequency from a transition state frequency calculation in cm^-1. """ @@ -393,7 +392,7 @@ def loadNegativeFrequency(self): negativefrequency = -float(frequency) return negativefrequency - def loadScanEnergies(self): + def load_scan_energies(self): """ Rotor scans are not implemented in Molpro """ diff --git a/arkane/molproTest.py b/arkane/molproTest.py index 22579032a7..de18c27f8b 100644 --- a/arkane/molproTest.py +++ b/arkane/molproTest.py @@ -59,7 +59,7 @@ def test_load_dz_from_molpro_log_f12(self): """ log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'ethylene_f12_dz.out')) - e0 = log.loadEnergy() + e0 = log.load_energy() self.assertAlmostEqual(e0 / constants.Na / constants.E_h, -78.474353559604, 5) @@ -70,7 +70,7 @@ def test_load_qz_from_molpro_log_f12(self): """ log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'ethylene_f12_qz.out')) - e0 = log.loadEnergy() + e0 = log.load_energy() self.assertAlmostEqual(e0 / constants.Na / constants.E_h, -78.472682755635, 5) @@ -81,7 +81,7 @@ def test_load_rad_from_molpro_log_f12(self): """ log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'OH_f12.out')) - e0 = log.loadEnergy() + e0 = log.load_energy() self.assertAlmostEqual(e0 / constants.Na / constants.E_h, -75.663696424380, 5) @@ -92,8 +92,8 @@ def test_load_hosi_from_molpro_log(self): """ log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'HOSI_ccsd_t1.out')) - conformer, unscaled_frequencies = log.loadConformer(spinMultiplicity=1) - e0 = log.loadEnergy() + conformer, unscaled_frequencies = log.load_conformer(spin_multiplicity=1) + e0 = log.load_energy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, IdealGasTranslation)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, NonlinearRotor)]) == 1) @@ -118,7 +118,7 @@ def test_load_non_f12_e0(self): Load E0 for CCSD(T) (without F12) from a molpro output file """ molpro_log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'TS_CCSD(T)_no_F12_sp_molpro.out')) - e0 = molpro_log.loadEnergy() + e0 = molpro_log.load_energy() self.assertAlmostEqual(e0, -301585968.58196217, places=7) def test_load_mrci_e0(self): @@ -127,8 +127,8 @@ def test_load_mrci_e0(self): """ mrci_log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'molpro_mrci.out')) mrciq_log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'molpro_mrci+q.out')) - mrci_e0 = mrci_log.loadEnergy() - mrciq_e0 = mrciq_log.loadEnergy() + mrci_e0 = mrci_log.load_energy() + mrciq_e0 = mrciq_log.load_energy() self.assertAlmostEqual(mrci_e0, -293217091.0381712, places=7) self.assertAlmostEqual(mrciq_e0, -293284017.3925107, places=7) @@ -137,7 +137,7 @@ def test_load_negative_frequency(self): Load an imaginary frequency from a molpro output file """ freq_log = MolproLog(os.path.join(os.path.dirname(__file__), 'data', 'molpro_TS.out')) - imaginary_freq = freq_log.loadNegativeFrequency() + imaginary_freq = freq_log.load_negative_frequency() self.assertEqual(imaginary_freq, -1997.98) def test_get_d1_diagnostic(self): diff --git a/arkane/output.py b/arkane/output.py index 345bdd4c66..b1002196fd 100644 --- a/arkane/output.py +++ b/arkane/output.py @@ -49,17 +49,16 @@ def __init__(self, level=0, indent=4): self.level = level self.indent = indent - def visit_Call(self, node): + def visit_call(self, node): """ - Return a pretty representation of the class or function call - represented by `node`. + Return a pretty representation of the class or function call represented by `node`. """ result = node.func.id + '(\n' keywords = [] for keyword in node.keywords: keywords.append('{0}={1}'.format(keyword.arg, self.visit(keyword.value))) - result = '{0}({1})'.format(node.func.id, ', '.join(keywords)) + result += '{0}({1})'.format(node.func.id, ', '.join(keywords)) if len(result) > 80: result = node.func.id + '(\n' @@ -76,7 +75,7 @@ def visit_Call(self, node): return result - def visit_List(self, node): + def visit_list(self, node): """ Return a pretty representation of the list represented by `node`. """ @@ -95,7 +94,7 @@ def visit_List(self, node): self.string = result return result - def visit_Tuple(self, node): + def visit_tuple(self, node): """ Return a pretty representation of the tuple represented by `node`. """ @@ -122,7 +121,7 @@ def visit_Tuple(self, node): self.string = result return result - def visit_Dict(self, node): + def visit_dict(self, node): """ Return a pretty representation of the dict represented by `node`. """ @@ -144,7 +143,7 @@ def visit_Dict(self, node): self.string = result return result - def visit_Str(self, node): + def visit_str(self, node): """ Return a pretty representation of the string represented by `node`. """ @@ -152,7 +151,7 @@ def visit_Str(self, node): self.string = result return result - def visit_Num(self, node): + def visit_num(self, node): """ Return a pretty representation of the number represented by `node`. """ diff --git a/arkane/pdep.py b/arkane/pdep.py index fb3766cfa9..703e9de4fa 100644 --- a/arkane/pdep.py +++ b/arkane/pdep.py @@ -132,18 +132,18 @@ def __init__(self, network, else: self.Plist = None - self.maximumGrainSize = maximumGrainSize - self.minimumGrainCount = minimumGrainCount + self.maximum_grain_size = maximumGrainSize + self.minimum_grain_count = minimumGrainCount self.Emin = None self.Emax = None self.Elist = None self.method = method - self.interpolationModel = interpolationModel - self.maximumAtoms = maximumAtoms + self.interpolation_model = interpolationModel + self.maximum_atoms = maximumAtoms - self.activeKRotor = activeKRotor - self.activeJRotor = activeJRotor + self.active_k_rotor = activeKRotor + self.active_j_rotor = activeJRotor self.rmgmode = rmgmode if sensitivity_conditions is not None: @@ -155,9 +155,9 @@ def __init__(self, network, self.sensitivity_conditions = None if self.Tlist is None and self.Tmin is not None and self.Tmax is not None and self.Tcount is not None: - self.generateTemperatureList() + self.generate_T_list() if self.Plist is None and self.Pmin is not None and self.Pmax is not None and self.Pcount is not None: - self.generatePressureList() + self.generate_P_list() @property def Tmin(self): @@ -214,13 +214,13 @@ def Plist(self, value): self._Plist = quantity.Pressure(value) @property - def maximumGrainSize(self): + def maximum_grain_size(self): """The maximum allowed energy grain size, or ``None`` if not defined.""" - return self._maximumGrainSize + return self._maximum_grain_size - @maximumGrainSize.setter - def maximumGrainSize(self, value): - self._maximumGrainSize = quantity.Energy(value) + @maximum_grain_size.setter + def maximum_grain_size(self, value): + self._maximum_grain_size = quantity.Energy(value) def copy(self): """ @@ -236,16 +236,16 @@ def copy(self): Pmax=self.Pmax, Pcount=self.Pcount, Plist=self.Plist, - maximumGrainSize=self.maximumGrainSize, - minimumGrainCount=self.minimumGrainCount, + maximumGrainSize=self.maximum_grain_size, + minimumGrainCount=self.minimum_grain_count, method=self.method, - interpolationModel=self.interpolationModel, - activeKRotor=self.activeKRotor, - activeJRotor=self.activeJRotor, + interpolationModel=self.interpolation_model, + activeKRotor=self.active_k_rotor, + activeJRotor=self.active_j_rotor, rmgmode=self.rmgmode, ) - def execute(self, outputFile, plot, format='pdf', print_summary=True): + def execute(self, output_file, plot, file_format='pdf', print_summary=True): """Execute a PressureDependenceJob""" for config in self.network.isomers + self.network.reactants + self.network.products: for spec in config.species: @@ -253,7 +253,7 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True): raise AttributeError('species {0} is missing energy for its conformer'.format(spec.label)) # set transition state Energy if not set previously using same method as RMG pdep - for reaction in self.network.pathReactions: + for reaction in self.network.path_reactions: transition_state = reaction.transition_state if transition_state.conformer and transition_state.conformer.E0 is None: transition_state.conformer.E0 = (sum([spec.conformer.E0.value_si for spec in reaction.reactants]) @@ -265,25 +265,25 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True): if print_summary: self.network.log_summary() - if outputFile is not None: - self.draw(os.path.dirname(outputFile), format) + if output_file is not None: + self.draw(os.path.dirname(output_file), file_format) self.initialize() self.K = self.network.calculate_rate_coefficients(self.Tlist.value_si, self.Plist.value_si, self.method) - self.fitInterpolationModels() + self.fit_interpolation_models() - if outputFile is not None: - self.save(outputFile) + if output_file is not None: + self.save(output_file) if plot: - self.plot(os.path.dirname(outputFile)) + self.plot(os.path.dirname(output_file)) if self.sensitivity_conditions is not None: perturbation = 0.1 # kcal/mol logging.info('\n\nRunning sensitivity analysis...') for i in range(3): try: - SensAnalysis(self, os.path.dirname(outputFile), perturbation=perturbation) + SensAnalysis(self, os.path.dirname(output_file), perturbation=perturbation) except (InvalidMicrocanonicalRateError, ModifiedStrongCollisionError) as e: logging.warning('Could not complete the sensitivity analysis with a perturbation of {0} ' 'kcal/mol, trying {1} kcal/mol instead.'.format( @@ -300,7 +300,7 @@ def execute(self, outputFile, plot, format='pdf', print_summary=True): logging.debug('Finished pdep job for reaction {0}.'.format(self.network.label)) logging.debug(repr(self.network)) - def generateTemperatureList(self): + def generate_T_list(self): """ Returns an array of temperatures based on the interpolation `model`, minimum and maximum temperatures `Tmin` and `Tmax` in K, and the number of @@ -313,25 +313,24 @@ def generateTemperatureList(self): Tmin = self.Tmin.value_si Tmax = self.Tmax.value_si Tcount = self.Tcount - if self.Tlist is not None: - pass - elif self.interpolationModel[0].lower() == 'chebyshev': - # Distribute temperatures on a Gauss-Chebyshev grid - Tlist = np.zeros(Tcount, np.float64) - for i in range(Tcount): - T = -math.cos((2 * i + 1) * math.pi / (2 * self.Tcount)) - T = 2.0 / ((1.0 / Tmax - 1.0 / Tmin) * T + 1.0 / Tmax + 1.0 / Tmin) - Tlist[i] = T - self.Tlist = (Tlist, "K") - else: - # Distribute temperatures evenly on a T^-1 domain - Tlist = 1.0 / np.linspace(1.0 / Tmax, 1.0 / Tmin, Tcount) - self.Tlist = (Tlist, "K") + if self.Tlist is None: + if self.interpolation_model[0].lower() == 'chebyshev': + # Distribute temperatures on a Gauss-Chebyshev grid + Tlist = np.zeros(Tcount, np.float64) + for i in range(Tcount): + T = -math.cos((2 * i + 1) * math.pi / (2 * self.Tcount)) + T = 2.0 / ((1.0 / Tmax - 1.0 / Tmin) * T + 1.0 / Tmax + 1.0 / Tmin) + Tlist[i] = T + self.Tlist = (Tlist, "K") + else: + # Distribute temperatures evenly on a T^-1 domain + Tlist = 1.0 / np.linspace(1.0 / Tmax, 1.0 / Tmin, Tcount) + self.Tlist = (Tlist, "K") return self.Tlist.value_si def initialize(self): """Initialize a PressureDependenceJob""" - for reaction in self.network.pathReactions: + for reaction in self.network.path_reactions: tunneling = reaction.transition_state.tunneling # throw descriptive error if tunneling not allowed if tunneling and reaction.transition_state.frequency is None and reaction.kinetics is not None: @@ -355,7 +354,7 @@ def initialize(self): else: raise ValueError('Unknown tunneling model {0!r} for path reaction {1}.'.format(tunneling, reaction)) - maximum_grain_size = self.maximumGrainSize.value_si if self.maximumGrainSize is not None else 0.0 + maximum_grain_size = self.maximum_grain_size.value_si if self.maximum_grain_size is not None else 0.0 self.network.initialize( Tmin=self.Tmin.value_si, @@ -363,16 +362,16 @@ def initialize(self): Pmin=self.Pmin.value_si, Pmax=self.Pmax.value_si, maximum_grain_size=maximum_grain_size, - minimum_grain_count=self.minimumGrainCount, - activeJRotor=self.activeJRotor, - activeKRotor=self.activeKRotor, + minimum_grain_count=self.minimum_grain_count, + active_j_rotor=self.active_j_rotor, + active_k_rotor=self.active_k_rotor, rmgmode=self.rmgmode, ) - self.generateTemperatureList() - self.generatePressureList() + self.generate_T_list() + self.generate_P_list() - def generatePressureList(self): + def generate_P_list(self): """ Returns an array of pressures based on the interpolation `model`, minimum and maximum pressures `Pmin` and `Pmax` in Pa, and the number of @@ -387,7 +386,7 @@ def generatePressureList(self): Pcount = self.Pcount if self.Plist is not None: pass - elif self.interpolationModel[0].lower() == 'chebyshev': + elif self.interpolation_model[0].lower() == 'chebyshev': # Distribute pressures on a Gauss-Chebyshev grid Plist = np.zeros(Pcount, np.float64) for i in range(Pcount): @@ -401,24 +400,19 @@ def generatePressureList(self): self.Plist = (Plist * 1e-5, "bar") return self.Plist.value_si - def fitInterpolationModels(self): + def fit_interpolation_models(self): """Fit all pressure dependent rates with interpolation models""" configurations = [] configurations.extend(self.network.isomers) configurations.extend(self.network.reactants) configurations.extend(self.network.products) - self.network.netReactions = [] + self.network.net_reactions = [] - n_reac = self.network.Nisom + self.network.Nreac - n_prod = n_reac + self.network.Nprod + n_reac = self.network.n_isom + self.network.n_reac + n_prod = n_reac + self.network.n_prod - Tmin = self.Tmin.value_si - Tmax = self.Tmax.value_si - Tdata = self.Tlist.value_si - Pmin = self.Pmin.value_si - Pmax = self.Pmax.value_si - Pdata = self.Plist.value_si + Tdata, Pdata = self.Tlist.value_si, self.Plist.value_si for prod in range(n_prod): for reac in range(n_reac): @@ -430,40 +424,39 @@ def fitInterpolationModels(self): kdata = self.K[:, :, prod, reac].copy() order = len(reaction.reactants) kdata *= 1e6 ** (order - 1) - kunits = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] + k_units = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] logging.debug('Fitting master eqn data to kinetics for reaction {}.'.format(reaction)) - reaction.kinetics = self.fitInterpolationModel(Tdata, Pdata, kdata, kunits) + reaction.kinetics = self.fit_interpolation_model(Tdata, Pdata, kdata, k_units) - self.network.netReactions.append(reaction) + self.network.net_reactions.append(reaction) - def fitInterpolationModel(self, Tdata, Pdata, kdata, kunits): + def fit_interpolation_model(self, Tdata, Pdata, kdata, k_units): """Fit an interpolation model to a pressure dependent rate""" Tmin = self.Tmin.value_si Tmax = self.Tmax.value_si Pmin = self.Pmin.value_si Pmax = self.Pmax.value_si - model = self.interpolationModel[0].lower() + model = self.interpolation_model[0].lower() if model == 'chebyshev': - kinetics = Chebyshev().fitToData(Tdata, Pdata, kdata, kunits, - self.interpolationModel[1], self.interpolationModel[2], - Tmin, Tmax, Pmin, Pmax, - ) + kinetics = Chebyshev().fit_to_data(Tdata, Pdata, kdata, k_units, + self.interpolation_model[1], self.interpolation_model[2], + Tmin, Tmax, Pmin, Pmax) elif model == 'pdeparrhenius': - kinetics = PDepArrhenius().fitToData(Tdata, Pdata, kdata, kunits) + kinetics = PDepArrhenius().fit_to_data(Tdata, Pdata, kdata, k_units) else: - raise PressureDependenceError('Invalid interpolation model {0!r}.'.format(self.interpolationModel[0])) + raise PressureDependenceError('Invalid interpolation model {0!r}.'.format(self.interpolation_model[0])) return kinetics - def save(self, outputFile): + def save(self, output_file): """Save the output of a pressure dependent job""" logging.info('Saving pressure dependence results for network {0}...'.format(self.network.label)) - f = open(outputFile, 'a') - f_chemkin = open(os.path.join(os.path.dirname(outputFile), 'chem.inp'), 'a') + f = open(output_file, 'a') + f_chemkin = open(os.path.join(os.path.dirname(output_file), 'chem.inp'), 'a') - n_reac = self.network.Nisom + self.network.Nreac - n_prod = n_reac + self.network.Nprod + n_reac = self.network.n_isom + self.network.n_reac + n_prod = n_reac + self.network.n_prod Tlist = self.Tlist.value_si Plist = self.Plist.value_si Tcount = Tlist.shape[0] @@ -471,7 +464,7 @@ def save(self, outputFile): f.write("#Thermo used: \n") spcs = [] - for rxn in self.network.pathReactions: + for rxn in self.network.path_reactions: spcs.extend(rxn.reactants) spcs.extend(rxn.products) for spc in spcs: @@ -479,7 +472,7 @@ def save(self, outputFile): f.write("#" + spc.label + " SMILES: " + spc.molecule[0].to_smiles() + "\n") f.write("#" + spc.thermo.comment + "\n") f.write("\n#Path Reactions used: \n") - for rxn in self.network.pathReactions: + for rxn in self.network.path_reactions: if rxn.kinetics: f.write("#" + str(rxn) + "\n") for s in rxn.kinetics.comment.split("\n"): @@ -492,7 +485,7 @@ def save(self, outputFile): for reac in range(n_reac): if reac == prod: continue - reaction = self.network.netReactions[count] + reaction = self.network.net_reactions[count] count += 1 # make sure we aren't double counting any reactions if not any([reaction.is_isomorphic(other_rxn, check_only_label=True) @@ -512,7 +505,7 @@ def save(self, outputFile): kdata = self.K[:, :, prod, reac].copy() order = len(reaction.reactants) kdata *= 1e6 ** (order - 1) - kunits = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] + k_units = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] f.write('# =========== ') f.write('=========== ' * Pcount) @@ -548,7 +541,7 @@ def save(self, outputFile): f.close() f_chemkin.close() - def plot(self, outputDirectory): + def plot(self, output_directory): """Plot pressure dependent rates""" # Skip this step if matplotlib is not installed try: @@ -573,7 +566,7 @@ def plot(self, outputDirectory): for reac in range(n_reac): if reac == prod: continue - reaction = self.network.netReactions[count] + reaction = self.network.net_reactions[count] count += 1 reaction_str = '{0} {1} {2}'.format( @@ -594,7 +587,7 @@ def plot(self, outputDirectory): order = len(reaction.reactants) K *= 1e6 ** (order - 1) K2 *= 1e6 ** (order - 1) - kunits = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] + k_units = {1: 's^-1', 2: 'cm^3/(mol*s)', 3: 'cm^6/(mol^2*s)'}[order] plt.subplot(1, 2, 1) for p in range(Pcount): @@ -604,7 +597,7 @@ def plot(self, outputDirectory): plt.semilogy(1000.0 / Tlist, K2[:, p], color=cm(1. * p / (Pcount - 1)), marker='', linestyle='-') plt.xlabel('1000 / Temperature (K^-1)') - plt.ylabel('Rate coefficient ({0})'.format(kunits)) + plt.ylabel('Rate coefficient ({0})'.format(k_units)) plt.title(reaction_str) plt.legend() @@ -614,17 +607,17 @@ def plot(self, outputDirectory): label=str('%.0d' % Tlist[t]) + ' K') plt.loglog(Plist * 1e-5, K2[t, :], color=cm(1. * t / (Tcount - 1)), marker='', linestyle='-') plt.xlabel('Pressure (bar)') - plt.ylabel('Rate coefficient ({0})'.format(kunits)) + plt.ylabel('Rate coefficient ({0})'.format(k_units)) plt.title(reaction_str) plt.legend() fig.subplots_adjust(left=0.10, bottom=0.13, right=0.95, top=0.92, wspace=0.3, hspace=0.3) - if not os.path.exists(os.path.join(outputDirectory, 'plots', '')): - os.mkdir(os.path.join(outputDirectory, 'plots', '')) - plt.savefig(os.path.join(outputDirectory, 'plots', 'kinetics_{0:d}.pdf'.format(count))) + if not os.path.exists(os.path.join(output_directory, 'plots', '')): + os.mkdir(os.path.join(output_directory, 'plots', '')) + plt.savefig(os.path.join(output_directory, 'plots', 'kinetics_{0:d}.pdf'.format(count))) plt.close() - def draw(self, outputDirectory, format='pdf'): + def draw(self, output_directory, file_format='pdf'): """ Generate a PDF drawing of the pressure-dependent reaction network. This requires that Cairo and its Python wrapper be available; if not, @@ -645,21 +638,21 @@ def draw(self, outputDirectory, format='pdf'): from rmgpy.pdep.draw import NetworkDrawer - path = os.path.join(outputDirectory, 'network.' + format) + path = os.path.join(output_directory, 'network.' + file_format) - NetworkDrawer().draw(self.network, format=format, path=path) + NetworkDrawer().draw(self.network, file_format=file_format, path=path) - def saveInputFile(self, path): + def save_input_file(self, path): """ Save an Arkane input file for the pressure dependence job to `path` on disk. """ - speciesList = self.network.get_all_species() + species_list = self.network.get_all_species() # Add labels for species, reactions, transition states that don't have them - for i, spec in enumerate(speciesList): + for i, spec in enumerate(species_list): if not spec.label: spec.label = 'species{0:d}'.format(i + 1) - for i, rxn in enumerate(self.network.pathReactions): + for i, rxn in enumerate(self.network.path_reactions): if not rxn.label: rxn.label = 'reaction{0:d}'.format(i + 1) if not rxn.transition_state.label: @@ -669,7 +662,7 @@ def saveInputFile(self, path): with open(path, 'w') as f: # Write species - for spec in speciesList: + for spec in species_list: f.write('species(\n') f.write(' label = {0!r},\n'.format(str(spec))) if len(spec.molecule) > 0: @@ -695,7 +688,7 @@ def saveInputFile(self, path): f.write(')\n\n') # Write transition states - for rxn in self.network.pathReactions: + for rxn in self.network.path_reactions: ts = rxn.transition_state f.write('transitionState(\n') f.write(' label = {0!r},\n'.format(ts.label)) @@ -714,7 +707,7 @@ def saveInputFile(self, path): f.write(')\n\n') # Write reactions - for rxn in self.network.pathReactions: + for rxn in self.network.path_reactions: ts = rxn.transition_state f.write('reaction(\n') f.write(' label = {0!r},\n'.format(rxn.label)) @@ -744,7 +737,7 @@ def saveInputFile(self, path): f.write(' ({0}),\n'.format(', '.join([repr(str(spec)) for spec in reactants.species]))) f.write(' ],\n') f.write(' bathGas = {\n') - for spec, frac in self.network.bathGas.items(): + for spec, frac in self.network.bath_gas.items(): f.write(' {0!r}: {1:g},\n'.format(str(spec), frac)) f.write(' },\n') f.write(')\n\n') @@ -760,15 +753,15 @@ def saveInputFile(self, path): f.write(' Pmax = {0!r},\n'.format(self.Pmax)) f.write(' Pcount = {0:d},\n'.format(self.Pcount)) f.write(' Plist = {0!r},\n'.format(self.Plist)) - if self.maximumGrainSize is not None: - f.write(' maximumGrainSize = {0!r},\n'.format(self.maximumGrainSize)) - if self.minimumGrainCount != 0: - f.write(' minimumGrainCount = {0:d},\n'.format(self.minimumGrainCount)) + if self.maximum_grain_size is not None: + f.write(' maximumGrainSize = {0!r},\n'.format(self.maximum_grain_size)) + if self.minimum_grain_count != 0: + f.write(' minimumGrainCount = {0:d},\n'.format(self.minimum_grain_count)) f.write(' method = {0!r},\n'.format(self.method)) - if self.interpolationModel is not None: - f.write(' interpolationModel = {0!r},\n'.format(self.interpolationModel)) - f.write(' activeKRotor = {0!r},\n'.format(self.activeKRotor)) - f.write(' activeJRotor = {0!r},\n'.format(self.activeJRotor)) + if self.interpolation_model is not None: + f.write(' interpolationModel = {0!r},\n'.format(self.interpolation_model)) + f.write(' activeKRotor = {0!r},\n'.format(self.active_k_rotor)) + f.write(' activeJRotor = {0!r},\n'.format(self.active_j_rotor)) if self.rmgmode: f.write(' rmgmode = {0!r},\n'.format(self.rmgmode)) f.write(')\n\n') diff --git a/arkane/pdepTest.py b/arkane/pdepTest.py index 0fd42236aa..e8fead1d34 100644 --- a/arkane/pdepTest.py +++ b/arkane/pdepTest.py @@ -75,23 +75,23 @@ def test_pdep_job(self): A general test for a PDep job in Arkane """ self.tst1 = Arkane() - self.tst1.inputFile = self.input_file - self.tst1.outputDirectory = self.directory + self.tst1.input_file = self.input_file + self.tst1.output_directory = self.directory self.tst1.verbose = logging.WARN self.tst1.plot = False - self.tst1.jobList = [] - self.tst1.jobList = self.tst1.loadInputFile(self.tst1.inputFile) + self.tst1.job_list = [] + self.tst1.job_list = self.tst1.load_input_file(self.tst1.input_file) self.tst1.execute() - job = self.tst1.jobList[0] + job = self.tst1.job_list[0] self.assertEquals(job.Tmin.value_si, 300.0) - self.assertEquals(job.minimumGrainCount, 100) + self.assertEquals(job.minimum_grain_count, 100) self.assertFalse(job.rmgmode) - self.assertTrue(job.activeJRotor) - self.assertEquals(job.network.pathReactions[0].label, 'acetylperoxy <=> hydroperoxylvinoxy') - self.assertAlmostEquals(job.network.pathReactions[0].transition_state.tunneling.E0_TS.value_si, -24267.2) - self.assertAlmostEquals(job.network.pathReactions[0].transition_state.tunneling.frequency.value_si, -1679.04) - self.assertEquals(len(job.network.netReactions[0].reactants[0].conformer.modes), 6) + self.assertTrue(job.active_j_rotor) + self.assertEquals(job.network.path_reactions[0].label, 'acetylperoxy <=> hydroperoxylvinoxy') + self.assertAlmostEquals(job.network.path_reactions[0].transition_state.tunneling.E0_TS.value_si, -24267.2) + self.assertAlmostEquals(job.network.path_reactions[0].transition_state.tunneling.frequency.value_si, -1679.04) + self.assertEquals(len(job.network.net_reactions[0].reactants[0].conformer.modes), 6) # self.assertEquals(self.tst1.frequencyScaleFactor, 0.947) # test that a network pdf was generated diff --git a/arkane/qchem.py b/arkane/qchem.py index 5cce877297..a28150939f 100644 --- a/arkane/qchem.py +++ b/arkane/qchem.py @@ -60,7 +60,7 @@ class QChemLog(Log): def __init__(self, path): super(QChemLog, self).__init__(path) - def getNumberOfAtoms(self): + def get_number_of_atoms(self): """ Return the number of atoms in the molecular configuration used in the QChem output file. @@ -81,7 +81,7 @@ def getNumberOfAtoms(self): return n_atoms - def loadForceConstantMatrix(self): + def load_force_constant_matrix(self): """ Return the force constant matrix (in Cartesian coordinates) from the QChem log file. If multiple such matrices are identified, @@ -91,7 +91,7 @@ def loadForceConstantMatrix(self): """ force = None - n_atoms = self.getNumberOfAtoms() + n_atoms = self.get_number_of_atoms() n_rows = n_atoms * 3 with open(self.path, 'r') as f: line = f.readline() @@ -114,7 +114,7 @@ def loadForceConstantMatrix(self): return force - def loadGeometry(self): + def load_geometry(self): """ Return the optimum geometry of the molecular configuration from the @@ -169,7 +169,7 @@ def loadGeometry(self): return coord, number, mass - def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, label=''): + def load_conformer(self, symmetry=None, spin_multiplicity=0, optical_isomers=None, label=''): """ Load the molecular degree of freedom data from an output file created as the result of a QChem "Freq" calculation. As QChem's guess of the external symmetry number is not always correct, @@ -183,22 +183,22 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, inertia = [] unscaled_frequencies = [] e0 = 0.0 - if opticalIsomers is None or symmetry is None: - _opticalIsomers, _symmetry, _ = self.get_symmetry_properties() - if opticalIsomers is None: - opticalIsomers = _opticalIsomers + if optical_isomers is None or symmetry is None: + _optical_isomers, _symmetry, _ = self.get_symmetry_properties() + if optical_isomers is None: + optical_isomers = _optical_isomers if symmetry is None: symmetry = _symmetry with open(self.path, 'r') as f: line = f.readline() while line != '': # Read spin multiplicity if not explicitly given - if '$molecule' in line and spinMultiplicity == 0: + if '$molecule' in line and spin_multiplicity == 0: line = f.readline() if len(line.split()) == 2: - spinMultiplicity = int(float(line.split()[1])) + spin_multiplicity = int(float(line.split()[1])) logging.debug( - 'Conformer {0} is assigned a spin multiplicity of {1}'.format(label, spinMultiplicity)) + 'Conformer {0} is assigned a spin multiplicity of {1}'.format(label, spin_multiplicity)) # The rest of the data we want is in the Thermochemistry section of the output elif 'VIBRATIONAL ANALYSIS' in line: modes = [] @@ -267,10 +267,10 @@ def loadConformer(self, symmetry=None, spinMultiplicity=0, opticalIsomers=None, inertia = [] modes = mmass + rot + freq - return Conformer(E0=(e0 * 0.001, "kJ/mol"), modes=modes, spin_multiplicity=spinMultiplicity, - optical_isomers=opticalIsomers), unscaled_frequencies + return Conformer(E0=(e0 * 0.001, "kJ/mol"), modes=modes, spin_multiplicity=spin_multiplicity, + optical_isomers=optical_isomers), unscaled_frequencies - def loadEnergy(self, zpe_scale_factor=1.): + def load_energy(self, zpe_scale_factor=1.): """ Load the energy in J/mol from a QChem log file. Only the last energy in the file is returned. The zero-point energy is *not* included in @@ -289,7 +289,7 @@ def loadEnergy(self, zpe_scale_factor=1.): raise LogError('Unable to find energy in QChem output file {0}.'.format(self.path)) return e_elect - def loadZeroPointEnergy(self): + def load_zero_point_energy(self): """ Load the unscaled zero-point energy in J/mol from a QChem output file. """ @@ -304,7 +304,7 @@ def loadZeroPointEnergy(self): else: raise LogError('Unable to find zero-point energy in QChem output file {0}.'.format(self.path)) - def loadScanEnergies(self): + def load_scan_energies(self): """ Extract the optimized energies in J/mol from a QChem log file, e.g. the result of a QChem "PES Scan" quantum chemistry calculation. @@ -339,7 +339,7 @@ def loadScanEnergies(self): angle = np.arange(0.0, 2 * math.pi + 0.00001, 2 * math.pi / (len(v_list) - 1), np.float64) return v_list, angle - def loadNegativeFrequency(self): + def load_negative_frequency(self): """ Return the imaginary frequency from a transition state frequency calculation in cm^-1. diff --git a/arkane/qchemTest.py b/arkane/qchemTest.py index 2a6bd5a8dd..7b936d12b7 100644 --- a/arkane/qchemTest.py +++ b/arkane/qchemTest.py @@ -54,9 +54,9 @@ def test_number_of_atoms_from_qchem_log(self): number of atoms can be properly read. """ log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'npropyl.out')) - self.assertEqual(log.getNumberOfAtoms(), 10) + self.assertEqual(log.get_number_of_atoms(), 10) log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'co.out')) - self.assertEqual(log.getNumberOfAtoms(), 2) + self.assertEqual(log.get_number_of_atoms(), 2) def test_energy_from_qchem_log(self): """ @@ -64,11 +64,11 @@ def test_energy_from_qchem_log(self): molecular energies can be properly read. """ log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'npropyl.out')) - self.assertAlmostEqual(log.loadEnergy(), -310896203.5432524, delta=1e-5) + self.assertAlmostEqual(log.load_energy(), -310896203.5432524, delta=1e-5) log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'co.out')) - self.assertAlmostEqual(log.loadEnergy(), -297402545.0217114, delta=1e-5) + self.assertAlmostEqual(log.load_energy(), -297402545.0217114, delta=1e-5) log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'CH4_sp_qchem.out')) - self.assertAlmostEqual(log.loadEnergy(), -106356735.53661588, delta=1e-5) + self.assertAlmostEqual(log.load_energy(), -106356735.53661588, delta=1e-5) def test_load_vibrations_from_qchem_log(self): """ @@ -76,11 +76,11 @@ def test_load_vibrations_from_qchem_log(self): molecular energies can be properly read. """ log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'npropyl.out')) - conformer, unscaled_frequencies = log.loadConformer() + conformer, unscaled_frequencies = log.load_conformer() self.assertEqual(len(conformer.modes[2]._frequencies.getValue()), 24) self.assertEqual(conformer.modes[2]._frequencies.getValue()[5], 881.79) log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'co.out')) - conformer, unscaled_frequencies = log.loadConformer() + conformer, unscaled_frequencies = log.load_conformer() self.assertEqual(len(conformer.modes[2]._frequencies.getValue()), 1) self.assertEqual(conformer.modes[2]._frequencies.getValue(), 2253.16) @@ -90,7 +90,7 @@ def test_load_npropyl_modes_from_qchem_log(self): molecular modes can be properly read. """ log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'npropyl.out')) - conformer, unscaled_frequencies = log.loadConformer() + conformer, unscaled_frequencies = log.load_conformer() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, IdealGasTranslation)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, NonlinearRotor)]) == 1) @@ -103,10 +103,10 @@ def test_spin_multiplicity_from_qchem_log(self): molecular degrees of freedom can be properly read. """ log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'npropyl.out')) - conformer, unscaled_frequencies = log.loadConformer() + conformer, unscaled_frequencies = log.load_conformer() self.assertEqual(conformer.spin_multiplicity, 2) log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'co.out')) - conformer, unscaled_frequencies = log.loadConformer() + conformer, unscaled_frequencies = log.load_conformer() self.assertEqual(conformer.spin_multiplicity, 1) def test_load_co_modes_from_qchem_log(self): @@ -115,8 +115,8 @@ def test_load_co_modes_from_qchem_log(self): molecular degrees of freedom can be properly read. """ log = QChemLog(os.path.join(os.path.dirname(__file__), 'data', 'co.out')) - conformer, unscaled_frequencies = log.loadConformer() - E0 = log.loadEnergy() + conformer, unscaled_frequencies = log.load_conformer() + E0 = log.load_energy() self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, IdealGasTranslation)]) == 1) self.assertTrue(len([mode for mode in conformer.modes if isinstance(mode, LinearRotor)]) == 1) diff --git a/arkane/sensitivity.py b/arkane/sensitivity.py index d2587bd57a..d01e62d26f 100644 --- a/arkane/sensitivity.py +++ b/arkane/sensitivity.py @@ -89,7 +89,7 @@ def execute(self): for species in [self.job.reaction.reactants[0], self.job.reaction.products[0], self.job.reaction.transition_state]: self.perturb(species) - self.job.execute(outputFile=None, plot=False) # run the perturbed job + self.job.execute(output_file=None, plot=False) # run the perturbed job self.f_sa_rates[species] = [self.job.reaction.kinetics.get_rate_coefficient(condition.value_si) for condition in self.conditions] kr = self.job.reaction.generate_reverse_rate_coefficient() @@ -245,14 +245,14 @@ def __init__(self, job, output_directory, perturbation): self.sensitivity_path = os.path.join(output_directory, 'sensitivity') self.conditions = self.job.sensitivity_conditions self.rates = {} - for rxn in self.job.network.netReactions: + for rxn in self.job.network.net_reactions: self.rates[str(rxn)] = [] for condition in self.conditions: self.rates[str(rxn)].append(rxn.kinetics.get_rate_coefficient(condition[0].value_si, condition[1].value_si)) self.sa_rates = {} self.sa_coefficients = {} - for rxn in self.job.network.netReactions: + for rxn in self.job.network.net_reactions: self.sa_rates[str(rxn)] = {} self.sa_coefficients[str(rxn)] = {} self.perturbation = quantity.Quantity(perturbation, 'kcal/mol') @@ -267,7 +267,7 @@ def execute(self): wells.extend(self.job.network.isomers) wells.extend(self.job.network.products) transition_states = [] - for rxn in self.job.network.pathReactions: + for rxn in self.job.network.path_reactions: # if rxn.transition_state is not None: transition_states.append(rxn.transition_state) @@ -277,9 +277,9 @@ def execute(self): else: logging.info("\n\nPerturbing TS '{0}' by {1}:".format(entry.label, self.perturbation)) self.perturb(entry) - self.job.execute(outputFile=None, plot=False, print_summary=False) # run the perturbed job + self.job.execute(output_file=None, plot=False, print_summary=False) # run the perturbed job self.unperturb(entry) - for rxn in self.job.network.netReactions: + for rxn in self.job.network.net_reactions: self.sa_rates[str(rxn)][entry] = [rxn.kinetics.get_rate_coefficient( condition[0].value_si, condition[1].value_si) for condition in self.conditions] self.sa_coefficients[str(rxn)][entry] = [((self.sa_rates[str(rxn)][entry][i] @@ -323,7 +323,7 @@ def save(self, wells, transition_states): "The semi-normalized sensitivity coefficients are calculated as dln(r)/dE0\n" "by perturbing E0 of each well or TS by {1},\n and are given in " "`mol/J` units.\n\n\n".format(network_str, self.perturbation)) - for rxn in self.job.network.netReactions: + for rxn in self.job.network.net_reactions: reactants_label = ' + '.join([reactant.label for reactant in rxn.reactants]) products_label = ' + '.join([reactant.label for reactant in rxn.products]) reaction_str = '{0} {1} {2}'.format(reactants_label, '<=>', products_label) @@ -353,7 +353,7 @@ def plot(self, wells, transition_states): except ImportError: return - for rxn in self.job.network.netReactions: + for rxn in self.job.network.net_reactions: plt.rcdefaults() ax = plt.subplots(nrows=len(self.conditions), ncols=1, tight_layout=True)[1] labels = [str(entry) for entry in wells] diff --git a/arkane/statmech.py b/arkane/statmech.py index 13b6681dfe..defd41956b 100644 --- a/arkane/statmech.py +++ b/arkane/statmech.py @@ -127,27 +127,27 @@ def load(self): return angles, energies - def save(self, angles, energies, angleUnits='radians', energyUnits='kJ/mol'): + def save(self, angles, energies, angle_units='radians', energy_units='kJ/mol'): """ Save the scan energies to the file using the given `angles` in radians and corresponding energies `energies` in J/mol. The file is created to - use the given `angleUnits` for angles and `energyUnits` for energies. + use the given `angle_units` for angles and `energy_units` for energies. """ assert len(angles) == len(energies) try: - angle_factor = ScanLog.angleFactors[angleUnits] + angle_factor = ScanLog.angleFactors[angle_units] except KeyError: - raise ValueError('Invalid angle units {0!r}.'.format(angleUnits)) + raise ValueError('Invalid angle units {0!r}.'.format(angle_units)) try: - energy_factor = ScanLog.energyFactors[energyUnits] + energy_factor = ScanLog.energyFactors[energy_units] except KeyError: - raise ValueError('Invalid energy units {0!r}.'.format(energyUnits)) + raise ValueError('Invalid energy units {0!r}.'.format(energy_units)) with open(self.path, 'w') as stream: stream.write('{0:>24} {1:>24}\n'.format( - 'Angle ({0})'.format(angleUnits), - 'Energy ({0})'.format(energyUnits), + 'Angle ({0})'.format(angle_units), + 'Energy ({0})'.format(energy_units), )) for angle, energy in zip(angles, energies): stream.write('{0:23.10f} {1:23.10f}\n'.format(angle * angle_factor, energy * energy_factor)) @@ -392,10 +392,10 @@ def load(self, pdep=False, plot=False): self.species.label)) logging.debug(' Reading molecular degrees of freedom...') - conformer, unscaled_frequencies = statmech_log.loadConformer(symmetry=external_symmetry, - spinMultiplicity=spin_multiplicity, - opticalIsomers=optical_isomers, - label=self.species.label) + conformer, unscaled_frequencies = statmech_log.load_conformer(symmetry=external_symmetry, + spin_multiplicity=spin_multiplicity, + optical_isomers=optical_isomers, + label=self.species.label) for mode in conformer.modes: if isinstance(mode, (Translation, IdealGasTranslation)): @@ -409,7 +409,7 @@ def load(self, pdep=False, plot=False): "please specify the multiplicity in the input file.".format(self.path)) logging.debug(' Reading optimized geometry...') - coordinates, number, mass = geom_log.loadGeometry() + coordinates, number, mass = geom_log.load_geometry() # Infer atoms from geometry atoms = {} @@ -436,7 +436,7 @@ def load(self, pdep=False, plot=False): if e0 is None: if e_electronic is None: # The energy read from the log file is without the ZPE - e_electronic = energy_log.loadEnergy(zpe_scale_factor) # in J/mol + e_electronic = energy_log.load_energy(zpe_scale_factor) # in J/mol else: e_electronic *= constants.E_h * constants.Na # convert Hartree/particle into J/mol if self.applyAtomEnergyCorrections: @@ -456,7 +456,7 @@ def load(self, pdep=False, plot=False): bond_corrections = 0 e_electronic_with_corrections = e_electronic + atom_corrections + bond_corrections # Get ZPE only for polyatomic species (monoatomic species don't have frequencies, so ZPE = 0) - zpe = statmech_log.loadZeroPointEnergy() * zpe_scale_factor if len(number) > 1 else 0 + zpe = statmech_log.load_zero_point_energy() * zpe_scale_factor if len(number) > 1 else 0 logging.debug('Scaled zero point energy (ZPE) is {0} J/mol'.format(zpe)) e0 = e_electronic_with_corrections + zpe @@ -470,16 +470,16 @@ def load(self, pdep=False, plot=False): # If loading a transition state, also read the imaginary frequency if is_ts: - neg_freq = statmech_log.loadNegativeFrequency() + neg_freq = statmech_log.load_negative_frequency() self.species.frequency = (neg_freq * self.frequencyScaleFactor, "cm^-1") # Read and fit the 1D hindered rotors if applicable # If rotors are found, the vibrational frequencies are also # recomputed with the torsional modes removed - F = statmech_log.loadForceConstantMatrix() + hessian = statmech_log.load_force_constant_matrix() - if F is not None and len(mass) > 1 and len(rotors) > 0: + if hessian is not None and len(mass) > 1 and len(rotors) > 0: logging.debug(' Fitting {0} hindered rotors...'.format(len(rotors))) rotor_count = 0 @@ -493,19 +493,18 @@ def load(self, pdep=False, plot=False): conformer.modes.append(rotor) rotor_count += 1 elif len(q) == 8: - scandir, pivots1, top1, symmetry1, pivots2, top2, symmetry2, symmetry = q + scan_dir, pivots1, top1, symmetry1, pivots2, top2, symmetry2, symmetry = q logging.info("Calculating energy levels for 2D-HR, may take a while...") rotor = HinderedRotor2D(name='r' + str(j), torsigma1=symmetry1, torsigma2=symmetry2, - symmetry=symmetry, - calc_path=os.path.join(directory, scandir), pivots1=pivots1, pivots2=pivots2, - top1=top1, top2=top2) + symmetry=symmetry, calc_path=os.path.join(directory, scan_dir), + pivots1=pivots1, pivots2=pivots2, top1=top1, top2=top2) rotor.run() conformer.modes.append(rotor) rotor_count += 2 elif len(q) == 5 and isinstance(q[1][0], list): - scandir, pivots, tops, sigmas, semiclassical = q - rotor = HinderedRotorClassicalND(pivots, tops, sigmas, calc_path=os.path.join(directory, scandir), - conformer=conformer, F=F, + scan_dir, pivots, tops, sigmas, semiclassical = q + rotor = HinderedRotorClassicalND(pivots, tops, sigmas, calc_path=os.path.join(directory, scan_dir), + conformer=conformer, F=hessian, semiclassical=semiclassical, is_linear=linear, is_ts=is_ts) rotor.run() conformer.modes.append(rotor) @@ -522,7 +521,7 @@ def load(self, pdep=False, plot=False): scan_log = determine_qm_software(os.path.join(directory, scan_log.path)) scan_log.path = os.path.join(directory, scan_log.path) if isinstance(scan_log, (GaussianLog, QChemLog)): - v_list, angle = scan_log.loadScanEnergies() + v_list, angle = scan_log.load_scan_energies() try: pivot_atoms = scan_log.load_scan_pivot_atoms() except Exception as e: @@ -592,7 +591,7 @@ def load(self, pdep=False, plot=False): rotor_count += 1 logging.debug(' Determining frequencies from reduced force constant matrix...') - frequencies = np.array(projectRotors(conformer, F, rotors, linear, is_ts, label=self.species.label)) + frequencies = np.array(project_rotors(conformer, hessian, rotors, linear, is_ts, label=self.species.label)) elif len(conformer.modes) > 2: if len(rotors) > 0: @@ -689,7 +688,7 @@ def write_output(self, output_directory): f.write('{0}\n\n'.format(prettify(result))) f.close() - def create_hindered_rotor_figure(self, angle, v_list, cosineRotor, fourierRotor, rotor, rotorIndex): + def create_hindered_rotor_figure(self, angle, v_list, cosine_rotor, fourier_rotor, rotor, rotor_index): """ Plot the potential for the rotor, along with its cosine and Fourier series potential fits, and save it in the `hindered_rotor_plots` attribute. @@ -698,20 +697,20 @@ def create_hindered_rotor_figure(self, angle, v_list, cosineRotor, fourierRotor, Vlist_cosine = np.zeros_like(phi) Vlist_fourier = np.zeros_like(phi) for i in range(phi.shape[0]): - Vlist_cosine[i] = cosineRotor.get_potential(phi[i]) - Vlist_fourier[i] = fourierRotor.get_potential(phi[i]) + Vlist_cosine[i] = cosine_rotor.get_potential(phi[i]) + Vlist_fourier[i] = fourier_rotor.get_potential(phi[i]) fig = plt.figure(figsize=(6, 5)) plt.plot(angle, v_list / 4184., 'ok') - linespec = '-r' if rotor is cosineRotor else '--r' + linespec = '-r' if rotor is cosine_rotor else '--r' plt.plot(phi, Vlist_cosine / 4184., linespec) - linespec = '-b' if rotor is fourierRotor else '--b' + linespec = '-b' if rotor is fourier_rotor else '--b' plt.plot(phi, Vlist_fourier / 4184., linespec) plt.legend(['scan', 'cosine', 'fourier'], loc=1) plt.xlim(0, 2 * constants.pi) plt.xlabel('Angle') plt.ylabel('Potential (kcal/mol)') - plt.title('{0} hindered rotor #{1:d}'.format(self.species.label, rotorIndex + 1)) + plt.title('{0} hindered rotor #{1:d}'.format(self.species.label, rotor_index + 1)) axes = fig.get_axes()[0] axes.set_xticks([float(j * constants.pi / 4) for j in range(0, 9)]) @@ -719,7 +718,7 @@ def create_hindered_rotor_figure(self, angle, v_list, cosineRotor, fourierRotor, axes.set_xticklabels( ['$0$', '$\pi/4$', '$\pi/2$', '$3\pi/4$', '$\pi$', '$5\pi/4$', '$3\pi/2$', '$7\pi/4$', '$2\pi$']) - self.hindered_rotor_plots.append((fig, rotorIndex)) + self.hindered_rotor_plots.append((fig, rotor_index)) fig.close() def save_hindered_rotor_figures(self, directory): @@ -762,9 +761,9 @@ def is_linear(coordinates): return True -def projectRotors(conformer, F, rotors, linear, is_ts, getProjectedOutFreqs=False, label=None): +def project_rotors(conformer, hessian, rotors, linear, is_ts, get_projected_out_freqs=False, label=None): """ - For a given `conformer` with associated force constant matrix `F`, lists of + For a given `conformer` with associated force constant matrix `hessian`, lists of rotor information `rotors`, `pivots`, and `top1`, and the linearity of the molecule `linear`, project out the nonvibrational modes from the force constant matrix and use this to determine the vibrational frequencies. The @@ -815,93 +814,91 @@ def projectRotors(conformer, F, rotors, linear, is_ts, getProjectedOutFreqs=Fals # Rotation matrix inertia = conformer.get_moment_of_inertia_tensor() - PMoI, Ixyz = np.linalg.eigh(inertia) + inertia_xyz = np.linalg.eigh(inertia)[1] external = 6 if linear: external = 5 - D = np.zeros((n_atoms * 3, external), np.float64) - - P = np.zeros((n_atoms, 3), np.float64) + d = np.zeros((n_atoms * 3, external), np.float64) # Transform the coordinates to the principal axes - P = np.dot(coordinates, Ixyz) + p = np.dot(coordinates, inertia_xyz) for i in range(n_atoms): # Projection vectors for translation - D[3 * i + 0, 0] = amass[i] - D[3 * i + 1, 1] = amass[i] - D[3 * i + 2, 2] = amass[i] + d[3 * i + 0, 0] = amass[i] + d[3 * i + 1, 1] = amass[i] + d[3 * i + 2, 2] = amass[i] # Construction of the projection vectors for external rotation for i in range(n_atoms): - D[3 * i, 3] = (P[i, 1] * Ixyz[0, 2] - P[i, 2] * Ixyz[0, 1]) * amass[i] - D[3 * i + 1, 3] = (P[i, 1] * Ixyz[1, 2] - P[i, 2] * Ixyz[1, 1]) * amass[i] - D[3 * i + 2, 3] = (P[i, 1] * Ixyz[2, 2] - P[i, 2] * Ixyz[2, 1]) * amass[i] - D[3 * i, 4] = (P[i, 2] * Ixyz[0, 0] - P[i, 0] * Ixyz[0, 2]) * amass[i] - D[3 * i + 1, 4] = (P[i, 2] * Ixyz[1, 0] - P[i, 0] * Ixyz[1, 2]) * amass[i] - D[3 * i + 2, 4] = (P[i, 2] * Ixyz[2, 0] - P[i, 0] * Ixyz[2, 2]) * amass[i] + d[3 * i, 3] = (p[i, 1] * inertia_xyz[0, 2] - p[i, 2] * inertia_xyz[0, 1]) * amass[i] + d[3 * i + 1, 3] = (p[i, 1] * inertia_xyz[1, 2] - p[i, 2] * inertia_xyz[1, 1]) * amass[i] + d[3 * i + 2, 3] = (p[i, 1] * inertia_xyz[2, 2] - p[i, 2] * inertia_xyz[2, 1]) * amass[i] + d[3 * i, 4] = (p[i, 2] * inertia_xyz[0, 0] - p[i, 0] * inertia_xyz[0, 2]) * amass[i] + d[3 * i + 1, 4] = (p[i, 2] * inertia_xyz[1, 0] - p[i, 0] * inertia_xyz[1, 2]) * amass[i] + d[3 * i + 2, 4] = (p[i, 2] * inertia_xyz[2, 0] - p[i, 0] * inertia_xyz[2, 2]) * amass[i] if not linear: - D[3 * i, 5] = (P[i, 0] * Ixyz[0, 1] - P[i, 1] * Ixyz[0, 0]) * amass[i] - D[3 * i + 1, 5] = (P[i, 0] * Ixyz[1, 1] - P[i, 1] * Ixyz[1, 0]) * amass[i] - D[3 * i + 2, 5] = (P[i, 0] * Ixyz[2, 1] - P[i, 1] * Ixyz[2, 0]) * amass[i] + d[3 * i, 5] = (p[i, 0] * inertia_xyz[0, 1] - p[i, 1] * inertia_xyz[0, 0]) * amass[i] + d[3 * i + 1, 5] = (p[i, 0] * inertia_xyz[1, 1] - p[i, 1] * inertia_xyz[1, 0]) * amass[i] + d[3 * i + 2, 5] = (p[i, 0] * inertia_xyz[2, 1] - p[i, 1] * inertia_xyz[2, 0]) * amass[i] # Make sure projection matrix is orthonormal inertia = np.identity(n_atoms * 3, np.float64) - P = np.zeros((n_atoms * 3, 3 * n_atoms + external), np.float64) + p = np.zeros((n_atoms * 3, 3 * n_atoms + external), np.float64) - P[:, 0:external] = D[:, 0:external] - P[:, external:external + 3 * n_atoms] = inertia[:, 0:3 * n_atoms] + p[:, 0:external] = d[:, 0:external] + p[:, external:external + 3 * n_atoms] = inertia[:, 0:3 * n_atoms] for i in range(3 * n_atoms + external): norm = 0.0 for j in range(3 * n_atoms): - norm += P[j, i] * P[j, i] + norm += p[j, i] * p[j, i] for j in range(3 * n_atoms): if norm > 1E-15: - P[j, i] /= np.sqrt(norm) + p[j, i] /= np.sqrt(norm) else: - P[j, i] = 0.0 + p[j, i] = 0.0 for j in range(i + 1, 3 * n_atoms + external): proj = 0.0 for k in range(3 * n_atoms): - proj += P[k, i] * P[k, j] + proj += p[k, i] * p[k, j] for k in range(3 * n_atoms): - P[k, j] -= proj * P[k, i] + p[k, j] -= proj * p[k, i] - # Order D, there will be vectors that are 0.0 + # Order p, there will be vectors that are 0.0 i = 0 while i < 3 * n_atoms: norm = 0.0 for j in range(3 * n_atoms): - norm += P[j, i] * P[j, i] + norm += p[j, i] * p[j, i] if norm < 0.5: - P[:, i:3 * n_atoms + external - 1] = P[:, i + 1:3 * n_atoms + external] + p[:, i:3 * n_atoms + external - 1] = p[:, i + 1:3 * n_atoms + external] else: i += 1 # T is the transformation vector from cartesian to internal coordinates T = np.zeros((n_atoms * 3, 3 * n_atoms - external), np.float64) - T[:, 0:3 * n_atoms - external] = P[:, external:3 * n_atoms] + T[:, 0:3 * n_atoms - external] = p[:, external:3 * n_atoms] # Generate mass-weighted force constant matrix # This converts the axes to mass-weighted Cartesian axes # Units of Fm are J/m^2*kg = 1/s^2 - fm = F.copy() + weighted_hessian = hessian.copy() for i in range(n_atoms): for j in range(n_atoms): for u in range(3): for v in range(3): - fm[3 * i + u, 3 * j + v] /= math.sqrt(mass[i] * mass[j]) + weighted_hessian[3 * i + u, 3 * j + v] /= math.sqrt(mass[i] * mass[j]) - f_int = np.dot(T.T, np.dot(fm, T)) + hessian_int = np.dot(T.T, np.dot(weighted_hessian, T)) # Get eigenvalues of internal force constant matrix, V = 3N-6 * 3N-6 - eig, v = np.linalg.eigh(f_int) + eig, v = np.linalg.eigh(hessian_int) logging.debug('Frequencies from internal Hessian') for i in range(3 * n_atoms - external): @@ -915,24 +912,24 @@ def projectRotors(conformer, F, rotors, linear, is_ts, getProjectedOutFreqs=Fals counter = 0 for i, rotor in enumerate(rotors): if len(rotor) == 5 and isinstance(rotor[1][0], list): - scandir, pivotss, tops, sigmas, semiclassical = rotor + scan_dir, pivots_list, tops, sigmas, semiclassical = rotor elif len(rotor) == 5: scanLog, pivots, top, symmetry, fit = rotor - pivotss = [pivots] + pivots_list = [pivots] tops = [top] elif len(rotor) == 3: pivots, top, symmetry = rotor - pivotss = [pivots] + pivots_list = [pivots] tops = [top] elif len(rotor) == 8: - scandir, pivots1, top1, symmetry1, pivots2, top2, symmetry2, symmetry = rotor - pivotss = [pivots1, pivots2] + scan_dir, pivots1, top1, symmetry1, pivots2, top2, symmetry2, symmetry = rotor + pivots_list = [pivots1, pivots2] tops = [top1, top2] else: raise ValueError("{} not a proper rotor format".format(rotor)) for k in range(len(tops)): top = tops[k] - pivots = pivotss[k] + pivots = pivots_list[k] # Determine pivot atom if pivots[0] in top: pivot1 = pivots[0] @@ -991,10 +988,10 @@ def projectRotors(conformer, F, rotors, linear, is_ts, getProjectedOutFreqs=Fals # calculate the frequencies corresponding to the internal rotors int_proj = np.dot(fm, d_int) kmus = np.array([np.linalg.norm(int_proj[:, i]) for i in range(int_proj.shape[1])]) - intRotorFreqs = np.sqrt(kmus) / (2.0 * math.pi * constants.c * 100.0) + int_rotor_freqs = np.sqrt(kmus) / (2.0 * math.pi * constants.c * 100.0) - if getProjectedOutFreqs: - return intRotorFreqs + if get_projected_out_freqs: + return int_rotor_freqs # Do the projection d_int_proj = np.dot(vmw.T, d_int) diff --git a/arkane/statmechTest.py b/arkane/statmechTest.py index dd9a2ab5c4..2706c44c20 100644 --- a/arkane/statmechTest.py +++ b/arkane/statmechTest.py @@ -55,8 +55,8 @@ class TestStatmech(unittest.TestCase): def setUp(cls): """A method that is run before each unit test in this class""" arkane = Arkane() - cls.job_list = arkane.loadInputFile(os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'data', 'Benzyl', 'input.py')) + cls.job_list = arkane.load_input_file(os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'data', 'Benzyl', 'input.py')) def test_gaussian_log_file_error(self): """Test that the proper error is raised if gaussian geometry and frequency file paths are not the same""" @@ -73,8 +73,8 @@ def test_rotor_symmetry_determination(self): path2 = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'NCC_CRotor.out') scan_log1 = QChemLog(path1) scan_log2 = QChemLog(path2) - v_list1, angle = scan_log1.loadScanEnergies() - v_list2, angle = scan_log2.loadScanEnergies() + v_list1, angle = scan_log1.load_scan_energies() + v_list2, angle = scan_log2.load_scan_energies() symmetry1 = determine_rotor_symmetry(energies=v_list1, label='NCC', pivots=[]) symmetry2 = determine_rotor_symmetry(energies=v_list2, label='NCC', pivots=[]) self.assertEqual(symmetry1, 1) diff --git a/arkane/thermo.py b/arkane/thermo.py index 53c0fbdfeb..3cf6c1c517 100644 --- a/arkane/thermo.py +++ b/arkane/thermo.py @@ -60,9 +60,9 @@ class ThermoJob(object): compute and save the thermodynamics information for a single species. """ - def __init__(self, species, thermoClass): + def __init__(self, species, thermo_class): self.species = species - self.thermoClass = thermoClass + self.thermo_class = thermo_class self.arkane_species = ArkaneSpecies(species=species) def execute(self, output_directory=None, plot=False): @@ -74,7 +74,7 @@ def execute(self, output_directory=None, plot=False): capacity, entropy, enthalpy, gibbs free energy, and hindered rotors will be saved. """ - self.generateThermo() + self.generate_thermo() if output_directory is not None: try: self.write_output(output_directory) @@ -100,18 +100,18 @@ def execute(self, output_directory=None, plot=False): logging.warning("Could not create plots due to error: " "{0} for species {1}".format(e, self.species.label)) - def generateThermo(self): + def generate_thermo(self): """ Generate the thermodynamic data for the species and fit it to the - desired heat capacity model (as specified in the `thermoClass` + desired heat capacity model (as specified in the `thermo_class` attribute). """ - if self.thermoClass.lower() not in ['wilhoit', 'nasa']: - raise InputError('Unknown thermodynamic model "{0}".'.format(self.thermoClass)) + if self.thermo_class.lower() not in ['wilhoit', 'nasa']: + raise InputError('Unknown thermodynamic model "{0}".'.format(self.thermo_class)) species = self.species - logging.debug('Generating {0} thermo model for {1}...'.format(self.thermoClass, species)) + logging.debug('Generating {0} thermo model for {1}...'.format(self.thermo_class, species)) if species.thermo is not None: logging.info("Thermo already generated for species {}. Skipping thermo generation.".format(species)) @@ -129,7 +129,6 @@ def generateThermo(self): if not any([isinstance(mode, (LinearRotor, NonlinearRotor)) for mode in conformer.modes]): # Monatomic species - linear = False n_freq = 0 n_rotors = 0 Cp0 = 2.5 * constants.R @@ -154,7 +153,7 @@ def generateThermo(self): else: wilhoit.fit_to_data(Tlist, Cplist, Cp0, CpInf, H298, S298, B0=500.0) - if self.thermoClass.lower() == 'nasa': + if self.thermo_class.lower() == 'nasa': species.thermo = wilhoit.to_nasa(Tmin=10.0, Tmax=3000.0, Tint=500.0) else: species.thermo = wilhoit @@ -247,7 +246,7 @@ def element_count_from_conformer(self): element_counts[symbol] = 1 return element_counts - def plot(self, outputDirectory): + def plot(self, output_directory): """ Plot the heat capacity, enthapy, entropy, and Gibbs free energy of the fitted thermodynamics model, along with the same values from the @@ -311,7 +310,7 @@ def plot(self, outputDirectory): fig.subplots_adjust(left=0.10, bottom=0.08, right=0.95, top=0.95, wspace=0.35, hspace=0.20) - plot_path = os.path.join(outputDirectory, 'plots') + plot_path = os.path.join(output_directory, 'plots') if not os.path.exists(plot_path): os.mkdir(plot_path) diff --git a/arkane/thermoTest.py b/arkane/thermoTest.py index db4eac1ed4..4173f26a9c 100644 --- a/arkane/thermoTest.py +++ b/arkane/thermoTest.py @@ -53,12 +53,12 @@ def setUp(cls): """A method that is run before each unit test in this class""" spc = Species().from_smiles('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 = log.load_conformer()[0] + coords, numbers, masses = log.load_geometry() spc.conformer.coordinates = coords, 'angstroms' spc.conformer.number = numbers spc.conformer.mass = masses, 'amu' - cls.thermo_job = ThermoJob(species=spc, thermoClass='NASA') + cls.thermo_job = ThermoJob(species=spc, thermo_class='NASA') def test_element_count_from_conformer(self): """Test Getting an element count dictionary from the species.conformer attribute""" diff --git a/examples/arkane/explorer/methoxy/input.py b/examples/arkane/explorer/methoxy/input.py index 72894131fc..2160a28c41 100644 --- a/examples/arkane/explorer/methoxy/input.py +++ b/examples/arkane/explorer/methoxy/input.py @@ -198,9 +198,9 @@ minimumGrainCount = 500, method = 'modified strong collision', #Other methods include: 'reservoir state', 'chemically-significant eigenvalues', - interpolationModel = ('pdeparrhenius'), + interpolationModel = 'pdeparrhenius', activeKRotor = True, -# active_j_rotor = False, # causes Arkane to crash +# active_J_rotor = False, # causes Arkane to crash rmgmode = False, ) @@ -209,6 +209,6 @@ explore_tol=0.01, energy_tol=8e1, flux_tol=1e-6, - bathGas={'He':1.0}, - maximumRadicalElectrons=2, + bathGas={'He':1.0}, + maximumRadicalElectrons=2, ) diff --git a/examples/arkane/reactions/CH3OH+HCO/ch3oh.py b/examples/arkane/reactions/CH3OH+HCO/ch3oh.py index 224fd97c18..b030c65026 100644 --- a/examples/arkane/reactions/CH3OH+HCO/ch3oh.py +++ b/examples/arkane/reactions/CH3OH+HCO/ch3oh.py @@ -11,7 +11,7 @@ spinMultiplicity = 2 -opticalIsomers = 1 #confirmed +opticalIsomers = 1 # confirmed energy = { 'm08so/mg3s*': Log('ch3oh.out'), diff --git a/examples/arkane/reactions/CH3OH+HCO/ts.py b/examples/arkane/reactions/CH3OH+HCO/ts.py index 0ebd01f7ca..734b64a96c 100644 --- a/examples/arkane/reactions/CH3OH+HCO/ts.py +++ b/examples/arkane/reactions/CH3OH+HCO/ts.py @@ -7,7 +7,7 @@ spinMultiplicity = 2 -opticalIsomers = 2 #confirmed +opticalIsomers = 2 # confirmed energy = { 'm08so/mg3s*': Log('ts1.out'),