From 05a791679ecbc5d44f0b7a0d5f40852d5cad6fe2 Mon Sep 17 00:00:00 2001 From: Colin Grambow Date: Wed, 22 May 2019 18:00:26 -0400 Subject: [PATCH 1/4] Refactor energy corrections in Arkane Make new encorr package which handles all energy corrections. Store all correction parameters in a dedicated data file. Handle bond additivity corrections in its own module, so that new types of bond additivity corrections can easily be implemented in the future. --- arkane/encorr/__init__.py | 33 ++++ arkane/encorr/corr.py | 137 +++++++++++++ arkane/encorr/data.py | 406 ++++++++++++++++++++++++++++++++++++++ arkane/encorr/pbac.py | 79 ++++++++ arkane/exceptions.py | 48 +++++ arkane/statmech.py | 325 +----------------------------- 6 files changed, 710 insertions(+), 318 deletions(-) create mode 100644 arkane/encorr/__init__.py create mode 100644 arkane/encorr/corr.py create mode 100644 arkane/encorr/data.py create mode 100644 arkane/encorr/pbac.py create mode 100644 arkane/exceptions.py diff --git a/arkane/encorr/__init__.py b/arkane/encorr/__init__.py new file mode 100644 index 0000000000..3337d4925a --- /dev/null +++ b/arkane/encorr/__init__.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +initialize imports +""" + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2019 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### diff --git a/arkane/encorr/corr.py b/arkane/encorr/corr.py new file mode 100644 index 0000000000..a741c0d5d0 --- /dev/null +++ b/arkane/encorr/corr.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2019 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +""" +This module provides methods for applying energy and bond additivity +corrections. +""" + +import rmgpy.constants as constants + +from arkane.exceptions import AtomEnergyCorrectionError, BondAdditivityCorrectionError + +import arkane.encorr.data as data +import arkane.encorr.pbac as pbac + + +def get_energy_correction(model_chemistry, atoms, bonds, coords, nums, multiplicity=1, + atom_energies=None, apply_atom_corrections=True, + apply_bac=False, bac_type='p'): + """ + Calculate a correction to the electronic energy obtained from a + quantum chemistry calculation at a given model chemistry such that + it is consistent with the normal gas-phase reference states. + Optionally, correct the energy using bond additivity corrections. + + Args: + model_chemistry: The model chemistry, typically specified as method/basis. + atoms: A dictionary of element symbols with their associated counts. + bonds: A dictionary of bond types (e.g., 'C=O') with their associated counts. + coords: A Numpy array of Cartesian molecular coordinates. + nums: A sequence of atomic numbers. + multiplicity: The spin multiplicity of the molecule. + atom_energies: A dictionary of element symbols with their associated atomic energies in Hartree. + apply_atom_corrections: Include the atom correction to the electronic energy. + apply_bac: Include the bond additivity correction to the electronic energy. + bac_type: The type of bond additivity correction to use. + + Returns: + The correction to the electronic energy in J/mol. + """ + model_chemistry = model_chemistry.lower() + + corr = 0.0 + if apply_atom_corrections: + corr += get_atom_correction(model_chemistry, atoms, atom_energies=atom_energies) + if apply_bac: + corr += get_bac(model_chemistry, bonds, coords, nums, bac_type=bac_type, multiplicity=multiplicity) + + return corr + + +def get_atom_correction(model_chemistry, atoms, atom_energies=None): + """ + Calculate a correction to the electronic energy obtained from a + quantum chemistry calculation at a given model chemistry such that + it is consistent with the normal gas-phase reference states. + + `atoms` is a dictionary associating element symbols with the number + of that element in the molecule. The atom energies are in Hartrees, + which are from single atom calculations using corresponding model + chemistries. + + The assumption for the multiplicity of each atom is: + H doublet, C triplet, N quartet, O triplet, F doublet, Si triplet, + P quartet, S triplet, Cl doublet, Br doublet, I doublet. + """ + corr = 0.0 + + # Step 1: Reference all energies to a model chemistry-independent + # basis by subtracting out that model chemistry's atomic energies + if atom_energies is None: + try: + atom_energies = data.atom_energies[model_chemistry] + except KeyError: + raise AtomEnergyCorrectionError('Missing atom energies for model chemistry {}'.format(model_chemistry)) + + for symbol, count in atoms.items(): + if symbol in atom_energies: + corr -= count * atom_energies[symbol] * 4.35974394e-18 * constants.Na # Convert Hartree to J/mol + else: + raise AtomEnergyCorrectionError( + 'An energy correction for element "{}" is unavailable for model chemistry "{}".' + ' Turn off atom corrections if only running a kinetics jobs' + ' or supply a dictionary of atom energies' + ' as `atomEnergies` in the input file.'.format(symbol, model_chemistry) + ) + + # Step 2: Atom energy corrections to reach gas-phase reference state + atom_enthalpy_corrections = {symbol: data.atom_hf[symbol] - data.atom_thermal[symbol] for symbol in data.atom_hf} + for symbol, count in atoms.items(): + if symbol in atom_enthalpy_corrections: + corr += count * atom_enthalpy_corrections[symbol] * 4184.0 # Convert kcal/mol to J/mol + else: + raise AtomEnergyCorrectionError( + 'Element "{}" is not yet supported in Arkane.' + ' To include it, add its experimental heat of formation in the atom_hf' + ' and atom_thermal dictionaries in arkane/encorr/data.py'.format(symbol) + ) + + return corr + + +def get_bac(model_chemistry, bonds, coords, nums, bac_type='p', multiplicity=1): + """ + Calculate bond additivity correction. + """ + if bac_type.lower() == 'p': # Petersson-type BACs + return pbac.get_bac(model_chemistry, bonds) + else: + raise BondAdditivityCorrectionError('BAC type {} is not available'.format(bac_type)) diff --git a/arkane/encorr/data.py b/arkane/encorr/data.py new file mode 100644 index 0000000000..3975c90f4e --- /dev/null +++ b/arkane/encorr/data.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2019 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +""" +This file provides atomic energy and BAC parameters for several model +chemistries. +""" + +# Atom energy corrections to reach gas-phase reference state +# Experimental enthalpy of formation at 0 K, 1 bar for gas phase +# See Gaussian thermo whitepaper at http://gaussian.com/thermo/ +# Note: These values are relatively old and some improvement may be possible by using newer values +# (particularly for carbon). +# However, care should be taken to ensure that they are compatible with the BAC values (if BACs are used) +# He, Ne, K, Ca, Ti, Cu, Zn, Ge, Br, Kr, Rb, Ag, Cd, Sn, I, Xe, Cs, Hg, and Pb are taken from CODATA +# Codata: Cox, J. D., Wagman, D. D., and Medvedev, V. A., CODATA Key Values for Thermodynamics, Hemisphere +# Publishing Corp., New York, 1989. (http://www.science.uwaterloo.ca/~cchieh/cact/tools/thermodata.html) +atom_hf = {'H': 51.63, 'He': -1.481, + 'Li': 37.69, 'Be': 76.48, 'B': 136.2, 'C': 169.98, 'N': 112.53, 'O': 58.99, 'F': 18.47, 'Ne': -1.481, + 'Na': 25.69, 'Mg': 34.87, 'Al': 78.23, 'Si': 106.6, 'P': 75.42, 'S': 65.66, 'Cl': 28.59, + 'K': 36.841, 'Ca': 41.014, 'Ti': 111.2, 'Cu': 79.16, 'Zn': 29.685, 'Ge': 87.1, 'Br': 25.26, + 'Kr': -1.481, + 'Rb': 17.86, 'Ag': 66.61, 'Cd': 25.240, 'Sn': 70.50, 'I': 24.04, 'Xe': -1.481, + 'Cs': 16.80, 'Hg': 13.19, 'Pb': 15.17} + +# Thermal contribution to enthalpy for the atoms reported by Gaussian thermo whitepaper +# This will be subtracted from the corresponding value in atom_hf to produce an enthalpy used in calculating +# the enthalpy of formation at 298 K +atom_thermal = {'H': 1.01, 'He': 1.481, + 'Li': 1.1, 'Be': 0.46, 'B': 0.29, 'C': 0.25, 'N': 1.04, 'O': 1.04, 'F': 1.05, 'Ne': 1.481, + 'Na': 1.54, 'Mg': 1.19, 'Al': 1.08, 'Si': 0.76, 'P': 1.28, 'S': 1.05, 'Cl': 1.1, + 'K': 1.481, 'Ca': 1.481, 'Ti': 1.802, 'Cu': 1.481, 'Zn': 1.481, 'Ge': 1.768, 'Br': 1.481, + 'Kr': 1.481, + 'Rb': 1.481, 'Ag': 1.481, 'Cd': 1.481, 'Sn': 1.485, 'I': 1.481, 'Xe': 1.481, + 'Cs': 1.481, 'Hg': 1.481, 'Pb': 1.481} + +# Spin orbit correction (SOC) in Hartrees +# Values taken from ref 22 of http://dx.doi.org/10.1063/1.477794 and converted to Hartrees +# Values in milli-Hartree are also available (with fewer significant figures) from table VII of +# http://dx.doi.org/10.1063/1.473182 +# Iodine SOC calculated as a weighted average of the electronic spin splittings of the lowest energy state. +# The splittings are obtained from Huber, K.P.; Herzberg, G., Molecular Spectra and Molecular Structure. IV. +# Constants of Diatomic Molecules, Van Nostrand Reinhold Co., 1979 +SOC = {'H': 0.0, 'N': 0.0, 'O': -0.000355, 'C': -0.000135, 'S': -0.000893, 'P': 0.0, 'I': -0.011547226} + + +# Atomic energies +# All model chemistries here should be lower-case because the user input is changed to lower-case +atom_energies = { + # Note: If your model chemistry does not include spin orbit coupling, you should add the corrections + # to the energies here + + # cbs-qb3 and cbs-qb3-paraskevas have the same corrections + 'cbs-qb3': { + 'H': -0.499818 + SOC['H'], 'N': -54.520543 + SOC['N'], 'O': -74.987624 + SOC['O'], + 'C': -37.785385 + SOC['C'], 'P': -340.817186 + SOC['P'], 'S': -397.657360 + SOC['S'] + }, + 'cbs-qb3-paraskevas': { + 'H': -0.499818 + SOC['H'], 'N': -54.520543 + SOC['N'], 'O': -74.987624 + SOC['O'], + 'C': -37.785385 + SOC['C'], 'P': -340.817186 + SOC['P'], 'S': -397.657360 + SOC['S'] + }, + + 'm06-2x/cc-pvtz': { + 'H': -0.498135 + SOC['H'], 'N': -54.586780 + SOC['N'], 'O': -75.064242 + SOC['O'], + 'C': -37.842468 + SOC['C'], 'P': -341.246985 + SOC['P'], 'S': -398.101240 + SOC['S'] + }, + + 'g3': { + 'H': -0.5010030, 'N': -54.564343, 'O': -75.030991, 'C': -37.827717, 'P': -341.116432, 'S': -397.961110 + }, + + # * indicates that the grid size used in the [QChem] electronic + # structure calculation utilized 75 radial points and 434 angular points + # (i.e,, this is specified in the $rem section of the [qchem] input file as: XC_GRID 000075000434) + 'm08so/mg3s*': { + 'H': -0.5017321350 + SOC['H'], 'N': -54.5574039365 + SOC['N'], + 'O': -75.0382931348 + SOC['O'], 'C': -37.8245648740 + SOC['C'], + 'P': -341.2444299005 + SOC['P'], 'S': -398.0940312227 + SOC['S'] + }, + + 'klip_1': { + 'H': -0.50003976 + SOC['H'], 'N': -54.53383153 + SOC['N'], 'O': -75.00935474 + SOC['O'], + 'C': -37.79266591 + SOC['C'] + }, + + # Klip QCI(tz,qz) + 'klip_2': { + 'H': -0.50003976 + SOC['H'], 'N': -54.53169400 + SOC['N'], 'O': -75.00714902 + SOC['O'], + 'C': -37.79060419 + SOC['C'] + }, + + # Klip QCI(dz,tz) + 'klip_3': { + 'H': -0.50005578 + SOC['H'], 'N': -54.53128140 + SOC['N'], 'O': -75.00356581 + SOC['O'], + 'C': -37.79025175 + SOC['C'] + }, + + # Klip CCSD(T)(tz,qz) + 'klip_2_cc': { + 'H': -0.50003976 + SOC['H'], 'O': -75.00681155 + SOC['O'], 'C': -37.79029443 + SOC['C'] + }, + + 'ccsd(t)-f12/cc-pvdz-f12_h-tz': { + 'H': -0.499946213243 + SOC['H'], 'N': -54.526406291655 + SOC['N'], + 'O': -74.995458316117 + SOC['O'], 'C': -37.788203485235 + SOC['C'] + }, + + 'ccsd(t)-f12/cc-pvdz-f12_h-qz': { + 'H': -0.499994558325 + SOC['H'], 'N': -54.526406291655 + SOC['N'], + 'O': -74.995458316117 + SOC['O'], 'C': -37.788203485235 + SOC['C'] + }, + + # We are assuming that SOC is included in the Bond Energy Corrections + 'ccsd(t)-f12/cc-pvdz-f12': { + 'H': -0.499811124128, 'N': -54.526406291655, 'O': -74.995458316117, + 'C': -37.788203485235, 'S': -397.663040369707 + }, + + 'ccsd(t)-f12/cc-pvtz-f12': { + 'H': -0.499946213243, 'N': -54.53000909621, 'O': -75.004127673424, + 'C': -37.789862146471, 'S': -397.675447487865 + }, + + 'ccsd(t)-f12/cc-pvqz-f12': { + 'H': -0.499994558325, 'N': -54.530515226371, 'O': -75.005600062003, + 'C': -37.789961656228, 'S': -397.676719774973 + }, + + 'ccsd(t)-f12/cc-pcvdz-f12': { + 'H': -0.499811124128 + SOC['H'], 'N': -54.582137180344 + SOC['N'], + 'O': -75.053045547421 + SOC['O'], 'C': -37.840869118707 + SOC['C'] + }, + + 'ccsd(t)-f12/cc-pcvtz-f12': { + 'H': -0.499946213243 + SOC['H'], 'N': -54.588545831900 + SOC['N'], + 'O': -75.065995072347 + SOC['O'], 'C': -37.844662139972 + SOC['C'] + }, + + 'ccsd(t)-f12/cc-pcvqz-f12': { + 'H': -0.499994558325 + SOC['H'], 'N': -54.589137594139 + SOC['N'], + 'O': -75.067412234737 + SOC['O'], 'C': -37.844893820561 + SOC['C'] + }, + + 'ccsd(t)-f12/cc-pvtz-f12(-pp)': { + 'H': -0.499946213243 + SOC['H'], 'N': -54.53000909621 + SOC['N'], + 'O': -75.004127673424 + SOC['O'], 'C': -37.789862146471 + SOC['C'], + 'S': -397.675447487865 + SOC['S'], 'I': -294.81781766 + SOC['I'] + }, + + # ccsd(t)/aug-cc-pvtz(-pp) atomic energies were fit to a set of 8 small molecules: + # CH4, CH3OH, H2S, H2O, SO2, HI, I2, CH3I + 'ccsd(t)/aug-cc-pvtz(-pp)': { + 'H': -0.499821176024 + SOC['H'], 'O': -74.96738492 + SOC['O'], + 'C': -37.77385697 + SOC['C'], 'S': -397.6461604 + SOC['S'], + 'I': -294.7958443 + SOC['I'] + }, + + # note that all atom corrections but S are fitted, the correction for S is calculated + 'ccsd(t)-f12/aug-cc-pvdz': { + 'H': -0.499459066131 + SOC['H'], 'N': -54.524279516472 + SOC['N'], + 'O': -74.992097308083 + SOC['O'], 'C': -37.786694171716 + SOC['C'], + 'S': -397.648733842400 + SOC['S'] + }, + + 'ccsd(t)-f12/aug-cc-pvtz': { + 'H': -0.499844820798 + SOC['H'], 'N': -54.527419359906 + SOC['N'], + 'O': -75.000001429806 + SOC['O'], 'C': -37.788504810868 + SOC['C'], + 'S': -397.666903000231 + SOC['S'] + }, + + 'ccsd(t)-f12/aug-cc-pvqz': { + 'H': -0.499949526073 + SOC['H'], 'N': -54.529569719016 + SOC['N'], + 'O': -75.004026586610 + SOC['O'], 'C': -37.789387892348 + SOC['C'], + 'S': -397.671214204994 + SOC['S'] + }, + + 'b-ccsd(t)-f12/cc-pvdz-f12': { + 'H': -0.499811124128 + SOC['H'], 'N': -54.523269942190 + SOC['N'], + 'O': -74.990725918500 + SOC['O'], 'C': -37.785409916465 + SOC['C'], + 'S': -397.658155086033 + SOC['S'] + }, + + 'b-ccsd(t)-f12/cc-pvtz-f12': { + 'H': -0.499946213243 + SOC['H'], 'N': -54.528135889213 + SOC['N'], + 'O': -75.001094055506 + SOC['O'], 'C': -37.788233578503 + SOC['C'], + 'S': -397.671745425929 + SOC['S'] + }, + + 'b-ccsd(t)-f12/cc-pvqz-f12': { + 'H': -0.499994558325 + SOC['H'], 'N': -54.529425753163 + SOC['N'], + 'O': -75.003820485005 + SOC['O'], 'C': -37.789006506290 + SOC['C'], + 'S': -397.674145126931 + SOC['S'] + }, + + 'b-ccsd(t)-f12/cc-pcvdz-f12': { + 'H': -0.499811124128 + SOC['H'], 'N': -54.578602780288 + SOC['N'], + 'O': -75.048064317367 + SOC['O'], 'C': -37.837592033417 + SOC['C'] + }, + + 'b-ccsd(t)-f12/cc-pcvtz-f12': { + 'H': -0.499946213243 + SOC['H'], 'N': -54.586402551258 + SOC['N'], + 'O': -75.062767632757 + SOC['O'], 'C': -37.842729156944 + SOC['C'] + }, + + 'b-ccsd(t)-f12/cc-pcvqz-f12': { + 'H': -0.49999456 + SOC['H'], 'N': -54.587781507581 + SOC['N'], + 'O': -75.065397706471 + SOC['O'], 'C': -37.843634971592 + SOC['C'] + }, + + 'b-ccsd(t)-f12/aug-cc-pvdz': { + 'H': -0.499459066131 + SOC['H'], 'N': -54.520475581942 + SOC['N'], + 'O': -74.986992215049 + SOC['O'], 'C': -37.783294495799 + SOC['C'] + }, + + 'b-ccsd(t)-f12/aug-cc-pvtz': { + 'H': -0.499844820798 + SOC['H'], 'N': -54.524927371700 + SOC['N'], + 'O': -74.996328829705 + SOC['O'], 'C': -37.786320700792 + SOC['C'] + }, + + 'b-ccsd(t)-f12/aug-cc-pvqz': { + 'H': -0.499949526073 + SOC['H'], 'N': -54.528189769291 + SOC['N'], + 'O': -75.001879610563 + SOC['O'], 'C': -37.788165047059 + SOC['C'] + }, + + 'mp2_rmp2_pvdz': { + 'H': -0.49927840 + SOC['H'], 'N': -54.46141996 + SOC['N'], 'O': -74.89408254 + SOC['O'], + 'C': -37.73792713 + SOC['C'] + }, + + 'mp2_rmp2_pvtz': { + 'H': -0.49980981 + SOC['H'], 'N': -54.49615972 + SOC['N'], 'O': -74.95506980 + SOC['O'], + 'C': -37.75833104 + SOC['C'] + }, + + 'mp2_rmp2_pvqz': { + 'H': -0.49994557 + SOC['H'], 'N': -54.50715868 + SOC['N'], 'O': -74.97515364 + SOC['O'], + 'C': -37.76533215 + SOC['C'] + }, + + 'ccsd-f12/cc-pvdz-f12': { + 'H': -0.499811124128 + SOC['H'], 'N': -54.524325513811 + SOC['N'], + 'O': -74.992326577897 + SOC['O'], 'C': -37.786213495943 + SOC['C'] + }, + + 'ccsd(t)-f12/cc-pvdz-f12_noscale': { + 'H': -0.499811124128 + SOC['H'], 'N': -54.526026290887 + SOC['N'], + 'O': -74.994751897699 + SOC['O'], 'C': -37.787881871511 + SOC['C'] + }, + + 'g03_pbepbe_6-311++g_d_p': { + 'H': -0.499812273282 + SOC['H'], 'N': -54.5289567564 + SOC['N'], + 'O': -75.0033596764 + SOC['O'], 'C': -37.7937388736 + SOC['C'] + }, + + 'fci/cc-pvdz': { + 'C': -37.789527 + SOC['C'] + }, + + 'fci/cc-pvtz': { + 'C': -37.781266669684 + SOC['C'] + }, + + 'fci/cc-pvqz': { + 'C': -37.787052110598 + SOC['C'] + }, + + # 'bmk/cbsb7' and 'bmk/6-311g(2d,d,p)' have the same corrections + 'bmk/cbsb7': { + 'H': -0.498618853119 + SOC['H'], 'N': -54.5697851544 + SOC['N'], + 'O': -75.0515210278 + SOC['O'], 'C': -37.8287310027 + SOC['C'], + 'P': -341.167615941 + SOC['P'], 'S': -398.001619915 + SOC['S'] + }, + 'bmk/6-311g(2d,d,p)': { + 'H': -0.498618853119 + SOC['H'], 'N': -54.5697851544 + SOC['N'], + 'O': -75.0515210278 + SOC['O'], 'C': -37.8287310027 + SOC['C'], + 'P': -341.167615941 + SOC['P'], 'S': -398.001619915 + SOC['S'] + }, + + # Fitted to small molecules + 'b3lyp/6-31g**': { + 'H': -0.500426155, 'C': -37.850331697831, 'O': -75.0535872748806, 'S': -398.100820107242 + }, + + # Calculated atomic energies + 'b3lyp/6-311+g(3df,2p)': { + 'H': -0.502155915123 + SOC['H'], 'C': -37.8574709934 + SOC['C'], + 'N': -54.6007233609 + SOC['N'], 'O': -75.0909131284 + SOC['O'], + 'P': -341.281730319 + SOC['P'], 'S': -398.134489850 + SOC['S'] + }, + + 'wb97x-d/aug-cc-pvtz': { + 'H': -0.502803 + SOC['H'], 'N': -54.585652 + SOC['N'], 'O': -75.068286 + SOC['O'], + 'C': -37.842014 + SOC['C'] + }, + + # Calculated atomic energies (unfitted) + 'MRCI+Davidson/aug-cc-pV(T+d)Z': { + 'H': -0.49982118 + SOC['H'], 'C': -37.78321274 + SOC['C'], 'N': -54.51729444 + SOC['N'], + 'O': -74.97847534 + SOC['O'], 'S': -397.6571654 + SOC['S'] + }, + +} + + +# Petersson-type bond additivity correction parameters +pbac = { + + # 'S-H', 'C-S', 'C=S', 'S-S', 'O-S', 'O=S', 'O=S=O' taken from http://hdl.handle.net/1721.1/98155 (both for + # 'CCSD(T)-F12/cc-pVDZ-F12' and 'CCSD(T)-F12/cc-pVTZ-F12') + 'ccsd(t)-f12/cc-pvdz-f12': { + 'C-H': -0.46, 'C-C': -0.68, 'C=C': -1.90, 'C#C': -3.13, + 'O-H': -0.51, 'C-O': -0.23, 'C=O': -0.69, 'O-O': -0.02, 'C-N': -0.67, + 'C=N': -1.46, 'C#N': -2.79, 'N-O': 0.74, 'N_O': -0.23, 'N=O': -0.51, + 'N-H': -0.69, 'N-N': -0.47, 'N=N': -1.54, 'N#N': -2.05, 'S-H': 0.87, + 'C-S': 0.42, 'C=S': 0.51, 'S-S': 0.86, 'O-S': 0.23, 'O=S': -0.53, + 'O=S=O': 1.95 + }, + + 'ccsd(t)-f12/cc-pvtz-f12': { + 'C-H': -0.09, 'C-C': -0.27, 'C=C': -1.03, 'C#C': -1.79, + 'O-H': -0.06, 'C-O': 0.14, 'C=O': -0.19, 'O-O': 0.16, 'C-N': -0.18, + 'C=N': -0.41, 'C#N': -1.41, 'N-O': 0.87, 'N_O': -0.09, 'N=O': -0.23, + 'N-H': -0.01, 'N-N': -0.21, 'N=N': -0.44, 'N#N': -0.76, 'S-H': 0.52, + 'C-S': 0.13, 'C=S': -0.12, 'S-S': 0.30, 'O-S': 0.15, 'O=S': -2.61, + 'O=S=O': 0.27 + }, + + 'ccsd(t)-f12/cc-pvqz-f12': { + 'C-H': -0.08, 'C-C': -0.26, 'C=C': -1.01, 'C#C': -1.66, + 'O-H': 0.07, 'C-O': 0.25, 'C=O': -0.03, 'O-O': 0.26, 'C-N': -0.20, + 'C=N': -0.30, 'C#N': -1.33, 'N-O': 1.01, 'N_O': -0.03, 'N=O': -0.26, + 'N-H': 0.06, 'N-N': -0.23, 'N=N': -0.37, 'N#N': -0.64 + }, + + 'cbs-qb3': { + 'C-H': -0.11, 'C-C': -0.30, 'C=C': -0.08, 'C#C': -0.64, 'O-H': 0.02, 'C-O': 0.33, 'C=O': 0.55, + # Table IX: Petersson GA (1998) J. of Chemical Physics, DOI: 10.1063/1.477794 + 'N-H': -0.42, 'C-N': -0.13, 'C#N': -0.89, 'C-F': 0.55, 'C-Cl': 1.29, 'S-H': 0.0, 'C-S': 0.43, + 'O=S': -0.78, + 'N=O': 1.11, 'N-N': -1.87, 'N=N': -1.58, 'N-O': 0.35, + # Table 2: Ashcraft R (2007) J. Phys. Chem. B; DOI: 10.1021/jp073539t + 'N#N': -2.0, 'O=O': -0.2, 'H-H': 1.1, # Unknown source + }, + + 'cbs-qb3-paraskevas': { + # NOTE: The Paraskevas corrections are inaccurate for non-oxygenated hydrocarbons, + # and may do poorly in combination with the Petersson corrections + 'C-C': -0.495, 'C-H': -0.045, 'C=C': -0.825, 'C-O': 0.378, 'C=O': 0.743, 'O-H': -0.423, + # Table2: Paraskevas, PD (2013). Chemistry-A European J., DOI: 10.1002/chem.201301381 + 'C#C': -0.64, 'C#N': -0.89, 'C-S': 0.43, 'O=S': -0.78, 'S-H': 0.0, 'C-N': -0.13, 'C-Cl': 1.29, + 'C-F': 0.55, # Table IX: Petersson GA (1998) J. of Chemical Physics, DOI: 10.1063/1.477794 + 'N-H': -0.42, 'N=O': 1.11, 'N-N': -1.87, 'N=N': -1.58, 'N-O': 0.35, + # Table 2: Ashcraft R (2007) J. Phys. Chem. B; DOI: 10.1021/jp073539t + 'N#N': -2.0, 'O=O': -0.2, 'H-H': 1.1, # Unknown source + }, + + # Identical corrections for 'b3lyp/cbsb7', 'b3lyp/6-311g(2d,d,p)', 'b3lyp/6-311+g(3df,2p)', 'b3lyp/6-31g**' + 'b3lyp/cbsb7': { + 'C-H': 0.25, 'C-C': -1.89, 'C=C': -0.40, 'C#C': -1.50, + 'O-H': -1.09, 'C-O': -1.18, 'C=O': -0.01, 'N-H': 1.36, 'C-N': -0.44, + 'C#N': 0.22, 'C-S': -2.35, 'O=S': -5.19, 'S-H': -0.52, + }, + 'b3lyp/6-311g(2d,d,p)': { + 'C-H': 0.25, 'C-C': -1.89, 'C=C': -0.40, 'C#C': -1.50, + 'O-H': -1.09, 'C-O': -1.18, 'C=O': -0.01, 'N-H': 1.36, 'C-N': -0.44, + 'C#N': 0.22, 'C-S': -2.35, 'O=S': -5.19, 'S-H': -0.52, + }, + 'b3lyp/6-311+g(3df,2p)': { + 'C-H': 0.25, 'C-C': -1.89, 'C=C': -0.40, 'C#C': -1.50, + 'O-H': -1.09, 'C-O': -1.18, 'C=O': -0.01, 'N-H': 1.36, 'C-N': -0.44, + 'C#N': 0.22, 'C-S': -2.35, 'O=S': -5.19, 'S-H': -0.52, + }, + 'b3lyp/6-31g**': { + 'C-H': 0.25, 'C-C': -1.89, 'C=C': -0.40, 'C#C': -1.50, + 'O-H': -1.09, 'C-O': -1.18, 'C=O': -0.01, 'N-H': 1.36, 'C-N': -0.44, + 'C#N': 0.22, 'C-S': -2.35, 'O=S': -5.19, 'S-H': -0.52, + }, + +} diff --git a/arkane/encorr/pbac.py b/arkane/encorr/pbac.py new file mode 100644 index 0000000000..0f03ebd858 --- /dev/null +++ b/arkane/encorr/pbac.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2019 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +""" +This module provides methods for applying Petersson-type bond additivity +corrections (P-BAC) as described in: +Petersson et al., J. Chem. Phys. 1998, 109, 10570-10579 +""" + +import logging +import re + +from arkane.exceptions import BondAdditivityCorrectionError +import arkane.encorr.data as data + + +def get_bac(model_chemistry, bonds): + """ + Given the model_chemistry and a dictionary of bonds, return the + total BAC (should be ADDED to energy). + + The dictionary of bonds should have the following form: + + bonds = { + 'C-H': bac1, + 'C-C': bac2, + 'C=C': bac3, + ... + } + """ + + # Get BAC parameters + try: + params = data.pbac[model_chemistry] + except KeyError: + raise BondAdditivityCorrectionError( + 'Missing Petersson-type BAC parameters for model chemistry {}'.format(model_chemistry) + ) + + # Sum corrections + bac = 0.0 + for symbol, count in bonds.items(): + if symbol in params: + bac += count * params[symbol] + else: + symbol_flipped = ''.join(re.findall('[a-zA-Z]+|[^a-zA-Z]+', symbol)[::-1]) # Check reversed symbol + if symbol_flipped in params: + bac += count * params[symbol_flipped] + else: + logging.warning('Ignored unknown bond type {}.'.format(symbol)) + + return bac * 4184.0 # Convert kcal/mol to J/mol diff --git a/arkane/exceptions.py b/arkane/exceptions.py new file mode 100644 index 0000000000..e808fc616a --- /dev/null +++ b/arkane/exceptions.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2019 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +""" +This module provides custom Exception classes for use in Arkane. +""" + +class AtomEnergyCorrectionError(Exception): + """ + An exception to be raised when an error occurs while applying atom + energy corrections. + """ + pass + + +class BondAdditivityCorrectionError(Exception): + """ + An exception to be raised when an error occurs while applying bond + additivity corrections. + """ + pass diff --git a/arkane/statmech.py b/arkane/statmech.py index 36681c25a9..0409d07705 100644 --- a/arkane/statmech.py +++ b/arkane/statmech.py @@ -59,6 +59,7 @@ from arkane.qchem import QChemLog from arkane.common import symbol_by_number from arkane.common import ArkaneSpecies +from arkane.encorr.corr import get_energy_correction ################################################################################ @@ -416,10 +417,12 @@ def load(self, pdep=False): e_electronic *= constants.E_h * constants.Na # convert Hartree/particle into J/mol if not self.applyAtomEnergyCorrections: logging.warning('Atom corrections are not being used. Do not trust energies and thermo.') - e_electronic = applyEnergyCorrections(e_electronic, self.modelChemistry, atoms, self.bonds, - atomEnergies=self.atomEnergies, - applyAtomEnergyCorrections=self.applyAtomEnergyCorrections, - applyBondEnergyCorrections=self.applyBondEnergyCorrections) + e_electronic += get_energy_correction( + self.modelChemistry, atoms, self.bonds, coordinates, number, + multiplicity=conformer.spinMultiplicity, atom_energies=self.atomEnergies, + apply_atom_corrections=self.applyAtomEnergyCorrections, apply_bac=self.applyBondEnergyCorrections, + bac_type=self.bondEnergyCorrectionType + ) # Get ZPE only for polyatomic species (monoatomic species don't have frequencies, so ZPE = 0) zpe = statmechLog.loadZeroPointEnergy() * zpe_scale_factor if len(number) > 1 else 0 logging.debug('Scaled zero point energy (ZPE) is {0} J/mol'.format(zpe)) @@ -634,320 +637,6 @@ def plotHinderedRotor(self, angle, v_list, cosineRotor, fourierRotor, rotor, rot ################################################################################ -def applyEnergyCorrections(E0, modelChemistry, atoms, bonds, - atomEnergies=None, applyAtomEnergyCorrections=True, applyBondEnergyCorrections=False): - """ - Given an energy `E0` in J/mol as read from the output of a quantum chemistry - calculation at a given `modelChemistry`, adjust the energy such that it - is consistent with the normal gas-phase reference states. `atoms` is a - dictionary associating element symbols with the number of that element in - the molecule. The atom energies are in Hartrees, which are from single - atom calculations using corresponding model chemistries. - - The assumption for the multiplicity of each atom is: - H doublet, C triplet, O triplet, N quartet, S triplet, P quartet, I doublet. - - `bonds` is a dictionary associating bond types with the number - of that bond in the molecule. - """ - - if applyAtomEnergyCorrections: - # Spin orbit correction (SOC) in Hartrees - # Values taken from ref 22 of http://dx.doi.org/10.1063/1.477794 and converted to Hartrees - # Values in milli-Hartree are also available (with fewer significant figures) from table VII of - # http://dx.doi.org/10.1063/1.473182 - # Iodine SOC calculated as a weighted average of the electronic spin splittings of the lowest energy state. - # The splittings are obtained from Huber, K.P.; Herzberg, G., Molecular Spectra and Molecular Structure. IV. - # Constants of Diatomic Molecules, Van Nostrand Reinhold Co., 1979 - SOC = {'H': 0.0, 'N': 0.0, 'O': -0.000355, 'C': -0.000135, 'S': -0.000893, 'P': 0.0, 'I': -0.011547226, } - - # Step 1: Reference all energies to a model chemistry-independent basis - # by subtracting out that model chemistry's atomic energies - # All model chemistries here should be lower-case because the user input is changed to lower-case - if atomEnergies is None: - # Note: If your model chemistry does not include spin orbit coupling, you should add the corrections - # to the energies here - if modelChemistry.startswith('cbs-qb3'): - # only check start of string to allow different bond corrections (see below) - atomEnergies = {'H': -0.499818 + SOC['H'], 'N': -54.520543 + SOC['N'], 'O': -74.987624 + SOC['O'], - 'C': -37.785385 + SOC['C'], 'P': -340.817186 + SOC['P'], 'S': -397.657360 + SOC['S']} - elif modelChemistry == 'm06-2x/cc-pvtz': - atomEnergies = {'H': -0.498135 + SOC['H'], 'N': -54.586780 + SOC['N'], 'O': -75.064242 + SOC['O'], - 'C': -37.842468 + SOC['C'], 'P': -341.246985 + SOC['P'], 'S': -398.101240 + SOC['S']} - elif modelChemistry == 'g3': - atomEnergies = {'H': -0.5010030, 'N': -54.564343, 'O': -75.030991, 'C': -37.827717, 'P': -341.116432, - 'S': -397.961110} - elif modelChemistry == 'm08so/mg3s*': - # * indicates that the grid size used in the [QChem] electronic - # structure calculation utilized 75 radial points and 434 angular points - # (i.e,, this is specified in the $rem section of the [qchem] input file as: XC_GRID 000075000434) - atomEnergies = {'H': -0.5017321350 + SOC['H'], 'N': -54.5574039365 + SOC['N'], - 'O': -75.0382931348 + SOC['O'], 'C': -37.8245648740 + SOC['C'], - 'P': -341.2444299005 + SOC['P'], 'S': -398.0940312227 + SOC['S']} - elif modelChemistry == 'klip_1': - atomEnergies = {'H': -0.50003976 + SOC['H'], 'N': -54.53383153 + SOC['N'], 'O': -75.00935474 + SOC['O'], - 'C': -37.79266591 + SOC['C']} - elif modelChemistry == 'klip_2': - # Klip QCI(tz,qz) - atomEnergies = {'H': -0.50003976 + SOC['H'], 'N': -54.53169400 + SOC['N'], 'O': -75.00714902 + SOC['O'], - 'C': -37.79060419 + SOC['C']} - elif modelChemistry == 'klip_3': - # Klip QCI(dz,tz) - atomEnergies = {'H': -0.50005578 + SOC['H'], 'N': -54.53128140 + SOC['N'], 'O': -75.00356581 + SOC['O'], - 'C': -37.79025175 + SOC['C']} - - elif modelChemistry == 'klip_2_cc': - # Klip CCSD(T)(tz,qz) - atomEnergies = {'H': -0.50003976 + SOC['H'], 'O': -75.00681155 + SOC['O'], 'C': -37.79029443 + SOC['C']} - - elif modelChemistry == 'ccsd(t)-f12/cc-pvdz-f12_h-tz': - atomEnergies = {'H': -0.499946213243 + SOC['H'], 'N': -54.526406291655 + SOC['N'], - 'O': -74.995458316117 + SOC['O'], 'C': -37.788203485235 + SOC['C']} - elif modelChemistry == 'ccsd(t)-f12/cc-pvdz-f12_h-qz': - atomEnergies = {'H': -0.499994558325 + SOC['H'], 'N': -54.526406291655 + SOC['N'], - 'O': -74.995458316117 + SOC['O'], 'C': -37.788203485235 + SOC['C']} - - # We are assuming that SOC is included in the Bond Energy Corrections - elif modelChemistry == 'ccsd(t)-f12/cc-pvdz-f12': - atomEnergies = {'H': -0.499811124128, 'N': -54.526406291655, 'O': -74.995458316117, - 'C': -37.788203485235, 'S': -397.663040369707} - elif modelChemistry == 'ccsd(t)-f12/cc-pvtz-f12': - atomEnergies = {'H': -0.499946213243, 'N': -54.53000909621, 'O': -75.004127673424, - 'C': -37.789862146471, 'S': -397.675447487865} - elif modelChemistry == 'ccsd(t)-f12/cc-pvqz-f12': - atomEnergies = {'H': -0.499994558325, 'N': -54.530515226371, 'O': -75.005600062003, - 'C': -37.789961656228, 'S': -397.676719774973} - elif modelChemistry == 'ccsd(t)-f12/cc-pcvdz-f12': - atomEnergies = {'H': -0.499811124128 + SOC['H'], 'N': -54.582137180344 + SOC['N'], - 'O': -75.053045547421 + SOC['O'], 'C': -37.840869118707 + SOC['C']} - elif modelChemistry == 'ccsd(t)-f12/cc-pcvtz-f12': - atomEnergies = {'H': -0.499946213243 + SOC['H'], 'N': -54.588545831900 + SOC['N'], - 'O': -75.065995072347 + SOC['O'], 'C': -37.844662139972 + SOC['C']} - elif modelChemistry == 'ccsd(t)-f12/cc-pcvqz-f12': - atomEnergies = {'H': -0.499994558325 + SOC['H'], 'N': -54.589137594139 + SOC['N'], - 'O': -75.067412234737 + SOC['O'], 'C': -37.844893820561 + SOC['C']} - elif modelChemistry == 'ccsd(t)-f12/cc-pvtz-f12(-pp)': - atomEnergies = {'H': -0.499946213243 + SOC['H'], 'N': -54.53000909621 + SOC['N'], - 'O': -75.004127673424 + SOC['O'], 'C': -37.789862146471 + SOC['C'], - 'S': -397.675447487865 + SOC['S'], 'I': -294.81781766 + SOC['I']} - # ccsd(t)/aug-cc-pvtz(-pp) atomic energies were fit to a set of 8 small molecules: - # CH4, CH3OH, H2S, H2O, SO2, HI, I2, CH3I - elif modelChemistry == 'ccsd(t)/aug-cc-pvtz(-pp)': - atomEnergies = {'H': -0.499821176024 + SOC['H'], 'O': -74.96738492 + SOC['O'], - 'C': -37.77385697 + SOC['C'], 'S': -397.6461604 + SOC['S'], - 'I': -294.7958443 + SOC['I']} - - elif modelChemistry == 'ccsd(t)-f12/aug-cc-pvdz': - # note that all atom corrections but S are fitted, the correction for S is calculated - atomEnergies = {'H': -0.499459066131 + SOC['H'], 'N': -54.524279516472 + SOC['N'], - 'O': -74.992097308083 + SOC['O'], 'C': -37.786694171716 + SOC['C'], - 'S': -397.648733842400 + SOC['S']} - elif modelChemistry == 'ccsd(t)-f12/aug-cc-pvtz': - atomEnergies = {'H': -0.499844820798 + SOC['H'], 'N': -54.527419359906 + SOC['N'], - 'O': -75.000001429806 + SOC['O'], 'C': -37.788504810868 + SOC['C'], - 'S': -397.666903000231 + SOC['S']} - elif modelChemistry == 'ccsd(t)-f12/aug-cc-pvqz': - atomEnergies = {'H': -0.499949526073 + SOC['H'], 'N': -54.529569719016 + SOC['N'], - 'O': -75.004026586610 + SOC['O'], 'C': -37.789387892348 + SOC['C'], - 'S': -397.671214204994 + SOC['S']} - - elif modelChemistry == 'b-ccsd(t)-f12/cc-pvdz-f12': - atomEnergies = {'H': -0.499811124128 + SOC['H'], 'N': -54.523269942190 + SOC['N'], - 'O': -74.990725918500 + SOC['O'], 'C': -37.785409916465 + SOC['C'], - 'S': -397.658155086033 + SOC['S']} - elif modelChemistry == 'b-ccsd(t)-f12/cc-pvtz-f12': - atomEnergies = {'H': -0.499946213243 + SOC['H'], 'N': -54.528135889213 + SOC['N'], - 'O': -75.001094055506 + SOC['O'], 'C': -37.788233578503 + SOC['C'], - 'S': -397.671745425929 + SOC['S']} - elif modelChemistry == 'b-ccsd(t)-f12/cc-pvqz-f12': - atomEnergies = {'H': -0.499994558325 + SOC['H'], 'N': -54.529425753163 + SOC['N'], - 'O': -75.003820485005 + SOC['O'], 'C': -37.789006506290 + SOC['C'], - 'S': -397.674145126931 + SOC['S']} - elif modelChemistry == 'b-ccsd(t)-f12/cc-pcvdz-f12': - atomEnergies = {'H': -0.499811124128 + SOC['H'], 'N': -54.578602780288 + SOC['N'], - 'O': -75.048064317367 + SOC['O'], 'C': -37.837592033417 + SOC['C']} - elif modelChemistry == 'b-ccsd(t)-f12/cc-pcvtz-f12': - atomEnergies = {'H': -0.499946213243 + SOC['H'], 'N': -54.586402551258 + SOC['N'], - 'O': -75.062767632757 + SOC['O'], 'C': -37.842729156944 + SOC['C']} - elif modelChemistry == 'b-ccsd(t)-f12/cc-pcvqz-f12': - atomEnergies = {'H': -0.49999456 + SOC['H'], 'N': -54.587781507581 + SOC['N'], - 'O': -75.065397706471 + SOC['O'], 'C': -37.843634971592 + SOC['C']} - - elif modelChemistry == 'b-ccsd(t)-f12/aug-cc-pvdz': - atomEnergies = {'H': -0.499459066131 + SOC['H'], 'N': -54.520475581942 + SOC['N'], - 'O': -74.986992215049 + SOC['O'], 'C': -37.783294495799 + SOC['C']} - elif modelChemistry == 'b-ccsd(t)-f12/aug-cc-pvtz': - atomEnergies = {'H': -0.499844820798 + SOC['H'], 'N': -54.524927371700 + SOC['N'], - 'O': -74.996328829705 + SOC['O'], 'C': -37.786320700792 + SOC['C']} - elif modelChemistry == 'b-ccsd(t)-f12/aug-cc-pvqz': - atomEnergies = {'H': -0.499949526073 + SOC['H'], 'N': -54.528189769291 + SOC['N'], - 'O': -75.001879610563 + SOC['O'], 'C': -37.788165047059 + SOC['C']} - - elif modelChemistry == 'mp2_rmp2_pvdz': - atomEnergies = {'H': -0.49927840 + SOC['H'], 'N': -54.46141996 + SOC['N'], 'O': -74.89408254 + SOC['O'], - 'C': -37.73792713 + SOC['C']} - elif modelChemistry == 'mp2_rmp2_pvtz': - atomEnergies = {'H': -0.49980981 + SOC['H'], 'N': -54.49615972 + SOC['N'], 'O': -74.95506980 + SOC['O'], - 'C': -37.75833104 + SOC['C']} - elif modelChemistry == 'mp2_rmp2_pvqz': - atomEnergies = {'H': -0.49994557 + SOC['H'], 'N': -54.50715868 + SOC['N'], 'O': -74.97515364 + SOC['O'], - 'C': -37.76533215 + SOC['C']} - - elif modelChemistry == 'ccsd-f12/cc-pvdz-f12': - atomEnergies = {'H': -0.499811124128 + SOC['H'], 'N': -54.524325513811 + SOC['N'], - 'O': -74.992326577897 + SOC['O'], 'C': -37.786213495943 + SOC['C']} - - elif modelChemistry == 'ccsd(t)-f12/cc-pvdz-f12_noscale': - atomEnergies = {'H': -0.499811124128 + SOC['H'], 'N': -54.526026290887 + SOC['N'], - 'O': -74.994751897699 + SOC['O'], 'C': -37.787881871511 + SOC['C']} - - elif modelChemistry == 'g03_pbepbe_6-311++g_d_p': - atomEnergies = {'H': -0.499812273282 + SOC['H'], 'N': -54.5289567564 + SOC['N'], - 'O': -75.0033596764 + SOC['O'], 'C': -37.7937388736 + SOC['C']} - - elif modelChemistry == 'fci/cc-pvdz': - atomEnergies = {'C': -37.789527 + SOC['C']} - elif modelChemistry == 'fci/cc-pvtz': - atomEnergies = {'C': -37.781266669684 + SOC['C']} - elif modelChemistry == 'fci/cc-pvqz': - atomEnergies = {'C': -37.787052110598 + SOC['C']} - - elif modelChemistry in ['bmk/cbsb7', 'bmk/6-311g(2d,d,p)']: - atomEnergies = {'H': -0.498618853119 + SOC['H'], 'N': -54.5697851544 + SOC['N'], - 'O': -75.0515210278 + SOC['O'], 'C': -37.8287310027 + SOC['C'], - 'P': -341.167615941 + SOC['P'], 'S': -398.001619915 + SOC['S']} - elif modelChemistry == 'b3lyp/6-31g**': # Fitted to small molecules - atomEnergies = {'H': -0.500426155, 'C': -37.850331697831, 'O': -75.0535872748806, - 'S': -398.100820107242} - elif modelChemistry == 'b3lyp/6-311+g(3df,2p)': # Calculated atomic energies - atomEnergies = {'H': -0.502155915123 + SOC['H'], 'C': -37.8574709934 + SOC['C'], - 'N': -54.6007233609 + SOC['N'], 'O': -75.0909131284 + SOC['O'], - 'P': -341.281730319 + SOC['P'], 'S': -398.134489850 + SOC['S']} - elif modelChemistry == 'wb97x-d/aug-cc-pvtz': - atomEnergies = {'H': -0.502803 + SOC['H'], 'N': -54.585652 + SOC['N'], 'O': -75.068286 + SOC['O'], - 'C': -37.842014 + SOC['C']} - - elif modelChemistry == 'MRCI+Davidson/aug-cc-pV(T+d)Z': # Calculated atomic energies (unfitted) - atomEnergies = {'H': -0.49982118 + SOC['H'], 'C': -37.78321274 + SOC['C'], 'N': -54.51729444 + SOC['N'], - 'O': -74.97847534 + SOC['O'], 'S': -397.6571654 + SOC['S']} - - else: - raise Exception('Unknown model chemistry "{}".'.format(modelChemistry)) - - for symbol, count in atoms.items(): - if symbol in atomEnergies: - E0 -= count * atomEnergies[symbol] * 4.35974394e-18 * constants.Na - else: - raise Exception( - 'Unknown element "{}". Turn off atom corrections if only running a kinetics jobs ' - 'or supply a dictionary of atom energies.'.format(symbol) - ) - - # Step 2: Atom energy corrections to reach gas-phase reference state - # Experimental enthalpy of formation at 0 K, 1 bar for gas phase - # See Gaussian thermo whitepaper at http://www.gaussian.com/g_whitepap/thermo.htm) - # Note: These values are relatively old and some improvement may be possible by using newer values - # (particularly for carbon). - # However, care should be taken to ensure that they are compatible with the BAC values (if BACs are used) - # He, Ne, K, Ca, Ti, Cu, Zn, Ge, Br, Kr, Rb, Ag, Cd, Sn, I, Xe, Cs, Hg, and Pb are taken from CODATA - # Codata: Cox, J. D., Wagman, D. D., and Medvedev, V. A., CODATA Key Values for Thermodynamics, Hemisphere - # Publishing Corp., New York, 1989. (http://www.science.uwaterloo.ca/~cchieh/cact/tools/thermodata.html) - atom_hf = {'H': 51.63, 'He': -1.481, - 'Li': 37.69, 'Be': 76.48, 'B': 136.2, 'C': 169.98, 'N': 112.53, 'O': 58.99, 'F': 18.47, 'Ne': -1.481, - 'Na': 25.69, 'Mg': 34.87, 'Al': 78.23, 'Si': 106.6, 'P': 75.42, 'S': 65.66, 'Cl': 28.59, - 'K': 36.841, 'Ca': 41.014, 'Ti': 111.2, 'Cu': 79.16, 'Zn': 29.685, 'Ge': 87.1, 'Br': 25.26, - 'Kr': -1.481, - 'Rb': 17.86, 'Ag': 66.61, 'Cd': 25.240, 'Sn': 70.50, 'I': 24.04, 'Xe': -1.481, - 'Cs': 16.80, 'Hg': 13.19, 'Pb': 15.17} - # Thermal contribution to enthalpy Hss(298 K) - Hss(0 K) reported by Gaussian thermo whitepaper - # This will be subtracted from the corresponding value in atom_hf to produce an enthalpy used in calculating - # the enthalpy of formation at 298 K - atom_thermal = {'H': 1.01, 'He': 1.481, - 'Li': 1.1, 'Be': 0.46, 'B': 0.29, 'C': 0.25, 'N': 1.04, 'O': 1.04, 'F': 1.05, 'Ne': 1.481, - 'Na': 1.54, 'Mg': 1.19, 'Al': 1.08, 'Si': 0.76, 'P': 1.28, 'S': 1.05, 'Cl': 1.1, - 'K': 1.481, 'Ca': 1.481, 'Ti': 1.802, 'Cu': 1.481, 'Zn': 1.481, 'Ge': 1.768, 'Br': 1.481, - 'Kr': 1.481, - 'Rb': 1.481, 'Ag': 1.481, 'Cd': 1.481, 'Sn': 1.485, 'I': 1.481, 'Xe': 1.481, - 'Cs': 1.481, 'Hg': 1.481, 'Pb': 1.481} - # Total energy correction used to reach gas-phase reference state - # Note: Spin orbit coupling is no longer included in these energies, since some model chemistries include it - # automatically - atom_enthalpy_corrections = {element: atom_hf[element] - atom_thermal[element] for element in atom_hf} - for symbol, count in atoms.items(): - if symbol in atom_enthalpy_corrections: - E0 += count * atom_enthalpy_corrections[symbol] * 4184. - else: - raise Exception('Element "{0}" is not yet supported in Arkane.' - ' To include it, add its experimental heat of formation'.format(symbol)) - - if applyBondEnergyCorrections: - # Step 3: Bond energy corrections - # The order of elements in the bond correction label is important and should follow the order specified below: - # 'C', 'N', 'O', 'S', 'P', and 'H' - # Use ``-``/``=``/``#`` to denote a single/double/triple bond, respectively. - # For example, ``'C=N'`` is correct while ``'N=C'`` is incorrect - bondEnergies = {} - # 'S-H', 'C-S', 'C=S', 'S-S', 'O-S', 'O=S', 'O=S=O' taken from http://hdl.handle.net/1721.1/98155 (both for - # 'CCSD(T)-F12/cc-pVDZ-F12' and 'CCSD(T)-F12/cc-pVTZ-F12') - if modelChemistry == 'ccsd(t)-f12/cc-pvdz-f12': - bondEnergies = {'C-H': -0.46, 'C-C': -0.68, 'C=C': -1.90, 'C#C': -3.13, - 'O-H': -0.51, 'C-O': -0.23, 'C=O': -0.69, 'O-O': -0.02, 'C-N': -0.67, - 'C=N': -1.46, 'C#N': -2.79, 'N-O': 0.74, 'N_O': -0.23, 'N=O': -0.51, - 'N-H': -0.69, 'N-N': -0.47, 'N=N': -1.54, 'N#N': -2.05, 'S-H': 0.87, - 'C-S': 0.42, 'C=S': 0.51, 'S-S': 0.86, 'O-S': 0.23, 'O=S': -0.53, - 'O=S=O': 1.95, } - elif modelChemistry == 'ccsd(t)-f12/cc-pvtz-f12': - bondEnergies = {'C-H': -0.09, 'C-C': -0.27, 'C=C': -1.03, 'C#C': -1.79, - 'O-H': -0.06, 'C-O': 0.14, 'C=O': -0.19, 'O-O': 0.16, 'C-N': -0.18, - 'C=N': -0.41, 'C#N': -1.41, 'N-O': 0.87, 'N_O': -0.09, 'N=O': -0.23, - 'N-H': -0.01, 'N-N': -0.21, 'N=N': -0.44, 'N#N': -0.76, 'S-H': 0.52, - 'C-S': 0.13, 'C=S': -0.12, 'S-S': 0.30, 'O-S': 0.15, 'O=S': -2.61, - 'O=S=O': 0.27, } - elif modelChemistry == 'ccsd(t)-f12/cc-pvqz-f12': - bondEnergies = {'C-H': -0.08, 'C-C': -0.26, 'C=C': -1.01, 'C#C': -1.66, - 'O-H': 0.07, 'C-O': 0.25, 'C=O': -0.03, 'O-O': 0.26, 'C-N': -0.20, - 'C=N': -0.30, 'C#N': -1.33, 'N-O': 1.01, 'N_O': -0.03, 'N=O': -0.26, - 'N-H': 0.06, 'N-N': -0.23, 'N=N': -0.37, 'N#N': -0.64, } - elif modelChemistry == 'cbs-qb3': - bondEnergies = { - 'C-H': -0.11, 'C-C': -0.30, 'C=C': -0.08, 'C#C': -0.64, 'O-H': 0.02, 'C-O': 0.33, 'C=O': 0.55, - # Table IX: Petersson GA (1998) J. of Chemical Physics, DOI: 10.1063/1.477794 - 'N-H': -0.42, 'C-N': -0.13, 'C#N': -0.89, 'C-F': 0.55, 'C-Cl': 1.29, 'S-H': 0.0, 'C-S': 0.43, - 'O=S': -0.78, - 'N=O': 1.11, 'N-N': -1.87, 'N=N': -1.58, 'N-O': 0.35, - # Table 2: Ashcraft R (2007) J. Phys. Chem. B; DOI: 10.1021/jp073539t - 'N#N': -2.0, 'O=O': -0.2, 'H-H': 1.1, # Unknown source - } - elif modelChemistry == 'cbs-qb3-paraskevas': - # NOTE: The Paraskevas corrections are inaccurate for non-oxygenated hydrocarbons, - # and may do poorly in combination with the Petersson corrections - bondEnergies = { - 'C-C': -0.495, 'C-H': -0.045, 'C=C': -0.825, 'C-O': 0.378, 'C=O': 0.743, 'O-H': -0.423, - # Table2: Paraskevas, PD (2013). Chemistry-A European J., DOI: 10.1002/chem.201301381 - 'C#C': -0.64, 'C#N': -0.89, 'C-S': 0.43, 'O=S': -0.78, 'S-H': 0.0, 'C-N': -0.13, 'C-Cl': 1.29, - 'C-F': 0.55, # Table IX: Petersson GA (1998) J. of Chemical Physics, DOI: 10.1063/1.477794 - 'N-H': -0.42, 'N=O': 1.11, 'N-N': -1.87, 'N=N': -1.58, 'N-O': 0.35, - # Table 2: Ashcraft R (2007) J. Phys. Chem. B; DOI: 10.1021/jp073539t - 'N#N': -2.0, 'O=O': -0.2, 'H-H': 1.1, # Unknown source - } - elif modelChemistry in ['b3lyp/cbsb7', 'b3lyp/6-311g(2d,d,p)', 'b3lyp/6-311+g(3df,2p)', 'b3lyp/6-31g**']: - bondEnergies = {'C-H': 0.25, 'C-C': -1.89, 'C=C': -0.40, 'C#C': -1.50, - 'O-H': -1.09, 'C-O': -1.18, 'C=O': -0.01, 'N-H': 1.36, 'C-N': -0.44, - 'C#N': 0.22, 'C-S': -2.35, 'O=S': -5.19, 'S-H': -0.52, } - else: - logging.warning('No bond energy correction found for model chemistry: {0}'.format(modelChemistry)) - - for symbol, count in bonds.items(): - if symbol in bondEnergies: - E0 += count * bondEnergies[symbol] * 4184. - elif symbol[::-1] in bondEnergies: - E0 += count * bondEnergies[symbol[::-1]] * 4184. - else: - logging.warning('Ignored unknown bond type {0!r}.'.format(symbol)) - - return E0 - - def determine_qm_software(fullpath): """ Given a path to the log file of a QM software, determine whether it is Gaussian, Molpro, or QChem From d17fa57e87be29786c80d7994e468bfc58a46aa7 Mon Sep 17 00:00:00 2001 From: Colin Grambow Date: Wed, 22 May 2019 18:15:21 -0400 Subject: [PATCH 2/4] Implement Melius-type bond additivity corrections in Arkane Instead of correcting the electronic energy using explicitly defined bond types, Anantharaman and Melius (JPCA, 2005) only use three fitted parameters per atom type to correct the energy. Implement the framework for this type of correction in the encorr package. --- arkane/encorr/corr.py | 4 ++ arkane/encorr/data.py | 4 ++ arkane/encorr/mbac.py | 144 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 arkane/encorr/mbac.py diff --git a/arkane/encorr/corr.py b/arkane/encorr/corr.py index a741c0d5d0..14c199f1ac 100644 --- a/arkane/encorr/corr.py +++ b/arkane/encorr/corr.py @@ -39,6 +39,7 @@ import arkane.encorr.data as data import arkane.encorr.pbac as pbac +import arkane.encorr.mbac as mbac def get_energy_correction(model_chemistry, atoms, bonds, coords, nums, multiplicity=1, @@ -133,5 +134,8 @@ def get_bac(model_chemistry, bonds, coords, nums, bac_type='p', multiplicity=1): """ if bac_type.lower() == 'p': # Petersson-type BACs return pbac.get_bac(model_chemistry, bonds) + elif bac_type.lower() == 'm': # Melius-type BACs + # Return negative because the correction is subtracted in the Melius paper + return -mbac.get_bac(model_chemistry, coords, nums, multiplicity=multiplicity) else: raise BondAdditivityCorrectionError('BAC type {} is not available'.format(bac_type)) diff --git a/arkane/encorr/data.py b/arkane/encorr/data.py index 3975c90f4e..9b6667e221 100644 --- a/arkane/encorr/data.py +++ b/arkane/encorr/data.py @@ -404,3 +404,7 @@ }, } + + +# Melius-type bond additivity correction parameters +mbac = {} diff --git a/arkane/encorr/mbac.py b/arkane/encorr/mbac.py new file mode 100644 index 0000000000..89a8550b12 --- /dev/null +++ b/arkane/encorr/mbac.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +############################################################################### +# # +# RMG - Reaction Mechanism Generator # +# # +# Copyright (c) 2002-2019 Prof. William H. Green (whgreen@mit.edu), # +# Prof. Richard H. West (r.west@neu.edu) and the RMG Team (rmg_dev@mit.edu) # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the 'Software'), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, sublicense, # +# and/or sell copies of the Software, and to permit persons to whom the # +# Software is furnished to do so, subject to the following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +############################################################################### + +""" +This module provides methods for applying Melius-type bond additivity +corrections (M-BAC) as described in: +Anantharaman and Melius, J. Phys. Chem. A 2005, 109, 1734-1747 +""" + +import numpy as np +import pybel + +from rmgpy.molecule import Molecule, Atom, Bond, getElement + +from arkane.exceptions import BondAdditivityCorrectionError +import arkane.encorr.data as data + +atom_spins = { + 'H': 0.5, 'C': 1.0, 'N': 1.5, 'O': 1.0, 'F': 0.5, 'Si': 1.0, 'P': 1.5, 'S': 1.0, 'Cl': 0.5, 'Br': 0.5, 'I': 0.5 +} + + +def get_bac(model_chemistry, coords, nums, multiplicity=1, mol_corr=0.0): + """ + Given the model chemistry, molecular coordinates, atomic numbers, + and dictionaries of BAC parameters, return the total BAC + (should be SUBTRACTED from energy). + + Note that a molecular correction term other than 0 destroys the size + consistency of the quantum chemistry method. This correction also + requires the multiplicity of the molecule. + """ + alpha = 3.0 # Angstrom^-1 + + # Get BAC parameters + try: + params = data.mbac[model_chemistry] + except KeyError: + raise BondAdditivityCorrectionError( + 'Missing Melius-type BAC parameters for model chemistry {}'.format(model_chemistry) + ) + atom_corr = params['atom_corr'] + bond_corr_length = params['bond_corr_length'] + bond_corr_neighbor = params['bond_corr_neighbor'] + + # Get single-bonded RMG molecule + mol = geo_to_mol(coords, nums) + + # Molecular correction + spin = 0.5 * (multiplicity - 1) + bac_mol = mol_corr * (spin - sum(atom_spins[atom.element.symbol] for atom in mol.atoms)) + + # Atomic correction + bac_atom = sum(atom_corr[atom.element.symbol] for atom in mol.atoms) + + # Bond correction + bac_bond = 0.0 + for bond in mol.getAllEdges(): + atom1 = bond.atom1 + atom2 = bond.atom2 + symbol1 = atom1.element.symbol + symbol2 = atom2.element.symbol + + # Bond length correction + length_corr = (bond_corr_length[symbol1] * bond_corr_length[symbol2]) ** 0.5 + length = np.linalg.norm(atom1.coords - atom2.coords) + bac_bond += length_corr * np.exp(-alpha * length) + + # Neighbor correction + for other_atom, other_bond in mol.getBonds(atom1).iteritems(): # Atoms adjacent to atom1 + if other_bond is not bond: + other_symbol = other_atom.element.symbol + bac_bond += bond_corr_neighbor[symbol1] + bond_corr_neighbor[other_symbol] + for other_atom, other_bond in mol.getBonds(atom2).iteritems(): # Atoms adjacent to atom2 + if other_bond is not bond: + other_symbol = other_atom.element.symbol + bac_bond += bond_corr_neighbor[symbol2] + bond_corr_neighbor[other_symbol] + + return (bac_mol + bac_atom + bac_bond) * 4184.0 # Convert kcal/mol to J/mol + + +def geo_to_mol(coords, nums): + """ + Convert molecular geometry specified by atomic coordinates and + atomic numbers to RMG molecule. + + Use Open Babel for most cases because it's better at recognizing + long bonds. Use RMG for hydrogen because Open Babel can't do it for + mysterious reasons. + """ + if list(nums) == [1, 1]: + mol = Molecule() + mol.fromXYZ(nums, coords) + else: + xyz = '{}\n\n'.format(len(nums)) + xyz += '\n'.join('{0} {1[0]: .10f} {1[1]: .10f} {1[2]: .10f}'.format(n, c) for n, c in zip(nums, coords)) + mol = pybel.readstring('xyz', xyz) + mol = pybel_to_rmg(mol) + return mol + + +def pybel_to_rmg(pybel_mol): + """ + Convert Pybel molecule to RMG molecule but ignore charge, + multiplicity, and bond orders. + """ + mol = Molecule() + for pybel_atom in pybel_mol: + element = getElement(pybel_atom.atomicnum) + atom = Atom(element=element, coords=np.array(pybel_atom.coords)) + mol.vertices.append(atom) + for obbond in pybel.ob.OBMolBondIter(pybel_mol.OBMol): + begin_idx = obbond.GetBeginAtomIdx() - 1 # Open Babel indexes atoms starting at 1 + end_idx = obbond.GetEndAtomIdx() - 1 + bond = Bond(mol.vertices[begin_idx], mol.vertices[end_idx]) + mol.addBond(bond) + return mol From 2aadb6bd38d286f204e521a0513a9d37b81fe9c5 Mon Sep 17 00:00:00 2001 From: Colin Grambow Date: Wed, 22 May 2019 18:19:37 -0400 Subject: [PATCH 3/4] Add bondCorrectionType option to Arkane bondCorrectionType can be set to 'p' to use conventional bond additivity corrections or to 'm' to use the newly implemented Melius-type corrections. --- arkane/input.py | 2 ++ arkane/statmech.py | 1 + 2 files changed, 3 insertions(+) diff --git a/arkane/input.py b/arkane/input.py index 217ce33eec..76a24bde3c 100644 --- a/arkane/input.py +++ b/arkane/input.py @@ -651,6 +651,7 @@ def loadInputFile(path): use_hindered_rotors = local_context.get('useHinderedRotors', True) use_atom_corrections = local_context.get('useAtomCorrections', True) use_bond_corrections = local_context.get('useBondCorrections', False) + bac_type = local_context.get('bondCorrectionType', 'p') atom_energies = local_context.get('atomEnergies', None) directory = os.path.dirname(path) @@ -666,6 +667,7 @@ def loadInputFile(path): job.includeHinderedRotors = use_hindered_rotors job.applyAtomEnergyCorrections = use_atom_corrections job.applyBondEnergyCorrections = use_bond_corrections + job.bondEnergyCorrectionType = bac_type job.atomEnergies = atom_energies if isinstance(job, ThermoJob): job.arkane_species.author = author diff --git a/arkane/statmech.py b/arkane/statmech.py index 0409d07705..0d2f8a0a44 100644 --- a/arkane/statmech.py +++ b/arkane/statmech.py @@ -181,6 +181,7 @@ def __init__(self, species, path): self.includeHinderedRotors = True self.applyAtomEnergyCorrections = True self.applyBondEnergyCorrections = True + self.bondEnergyCorrectionType = 'p' self.atomEnergies = None self.supporting_info = [self.species.label] self.bonds = None From cdca610f38fde2edd06d5deab7e7c76a8d7fda0f Mon Sep 17 00:00:00 2001 From: Colin Grambow Date: Wed, 22 May 2019 18:34:52 -0400 Subject: [PATCH 4/4] Update Arkane documentation to reflect Melius-type bond additivity corrections --- documentation/source/users/arkane/input.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/documentation/source/users/arkane/input.rst b/documentation/source/users/arkane/input.rst index ab18900510..784fde4a05 100644 --- a/documentation/source/users/arkane/input.rst +++ b/documentation/source/users/arkane/input.rst @@ -28,6 +28,7 @@ Component Description ``useHinderedRotors`` ``True`` (by default) if hindered rotors are used, ``False`` if not ``useAtomCorrections`` ``True`` (by default) if atom corrections are used, ``False`` if not ``useBondCorrections`` ``True`` if bond corrections are used, ``False`` (by default) if not +``bondCorrectionType`` ``'p'`` for Petersson-type (default) or ``'m'`` for Melius-type bond additivity corrections ``species`` Contains parameters for non-transition states ``transitionState`` Contains parameters for transition state(s) ``reaction`` Required for performing kinetic computations @@ -192,7 +193,12 @@ to apply atomization energy corrections (AEC) and spin orbit corrections (SOC) f (see `Model Chemistry`_). If not interested in accurate thermodynamics (e.g., if only using ``kinetics()``), then atom corrections can be turned off by setting ``useAtomCorrections`` to ``False``. -The ``bond`` parameter is used to apply bond corrections (BC) for a given ``modelChemistry``. +The ``bonds`` parameter is used to apply bond additivity corrections (BACs) for a given ``modelChemistry`` if using +Petersson-type BACs (``bondCorrectionType = 'p'``). When using Melius-type BACs (``bondCorrectionType = 'm'``), +specifying ``bonds`` is not required because the molecular connectivity is automatically inferred from the output of the +quantum chemistry calculation. +For a description of Petersson-type BACs, see Petersson et al., J. Chem. Phys. 1998, 109, 10570-10579. +For a description of Melius-type BACs, see Anantharaman and Melius, J. Phys. Chem. A 2005, 109, 1734-1747. Allowed bond types for the ``bonds`` parameter are, e.g., ``'C-H'``, ``'C-C'``, ``'C=C'``, ``'N-O'``, ``'C=S'``, ``'O=O'``, ``'C#N'``...