Skip to content

Commit f5c3335

Browse files
KEHANGconnie
authored andcommitted
Reduced the unnecessary calls to calculateSymmetryNumber when calculating radical thermo.
calculateSymmetryNumber for saturated structure was called too frequently when calculating entropy of radical.
1 parent ae84b9b commit f5c3335

1 file changed

Lines changed: 83 additions & 60 deletions

File tree

rmgpy/data/thermo.py

Lines changed: 83 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -814,16 +814,16 @@ def estimateRadicalThermoViaHBI(self, molecule, stableThermoEstimator ):
814814
saturatedStruct.updateLonePairs()
815815
saturatedStruct.multiplicity = 1
816816

817-
# Get thermo estimate for saturated form of structure
818-
thermoData = stableThermoEstimator(saturatedStruct)
817+
# Get thermo estimate for saturated form of structure
818+
thermoData = stableThermoEstimator(saturatedStruct)
819819
if thermoData is None:
820820
logging.info("Thermo data of saturated {0} of molecule {1} is None.".format(saturatedStruct, molecule))
821821
return None
822822
assert thermoData is not None, "Thermo data of saturated {0} of molecule {1} is None!".format(saturatedStruct, molecule)
823823

824824
# Undo symmetry number correction for saturated structure
825-
saturatedStruct.calculateSymmetryNumber()
826-
thermoData.S298.value_si += constants.R * math.log(saturatedStruct.symmetryNumber)
825+
# saturatedStruct.calculateSymmetryNumber()
826+
# thermoData.S298.value_si += constants.R * math.log(saturatedStruct.symmetryNumber)
827827
# Correct entropy for symmetry number of radical structure
828828
molecule.calculateSymmetryNumber()
829829
thermoData.S298.value_si -= constants.R * math.log(molecule.symmetryNumber)
@@ -878,71 +878,94 @@ def estimateThermoViaGroupAdditivity(self, molecule):
878878
)
879879

880880
if molecule.getRadicalCount() > 0: # radical species
881-
return self.estimateRadicalThermoViaHBI(molecule, self.estimateThermoViaGroupAdditivity )
881+
return self.estimateRadicalThermoViaHBI(molecule, self.estimateThermoViaGroupAdditivityForSaturatedStruct)
882882

883883
else: # non-radical species
884-
cyclic = molecule.isCyclic()
885-
# Generate estimate of thermodynamics
886-
for atom in molecule.atoms:
887-
# Iterate over heavy (non-hydrogen) atoms
888-
if atom.isNonHydrogen():
889-
# Get initial thermo estimate from main group database
890-
try:
891-
self.__addGroupThermoData(thermoData, self.groups['group'], molecule, {'*':atom})
892-
except KeyError:
893-
logging.error("Couldn't find in main thermo database:")
894-
logging.error(molecule)
895-
logging.error(molecule.toAdjacencyList())
896-
raise
897-
# Correct for gauche and 1,5- interactions
898-
if not cyclic:
899-
try:
900-
self.__addGroupThermoData(thermoData, self.groups['gauche'], molecule, {'*':atom})
901-
except KeyError: pass
902-
try:
903-
self.__addGroupThermoData(thermoData, self.groups['int15'], molecule, {'*':atom})
904-
except KeyError: pass
905-
try:
906-
self.__addGroupThermoData(thermoData, self.groups['other'], molecule, {'*':atom})
907-
except KeyError: pass
908-
909-
# Do ring corrections separately because we only want to match
910-
# each ring one time
911-
912-
if cyclic:
913-
if molecule.getAllPolycyclicVertices():
914-
# If the molecule has fused ring atoms, this implies that we are dealing
915-
# with a polycyclic ring system, for which separate ring strain corrections may not
916-
# be adequate. Therefore, we search the polycyclic thermo group corrections
917-
# instead of adding single ring strain corrections within the molecule.
918-
# For now, assume only one polycyclic RSC can be found per molecule
919-
try:
920-
self.__addGroupThermoData(thermoData, self.groups['polycyclic'], molecule, {})
921-
except:
922-
logging.error("Couldn't find in polycyclic ring database:")
923-
logging.error(molecule)
924-
logging.error(molecule.toAdjacencyList())
925-
raise
926-
else:
927-
rings = molecule.getSmallestSetOfSmallestRings()
928-
for ring in rings:
929-
# Make a temporary structure containing only the atoms in the ring
930-
# NB. if any of the ring corrections depend on ligands not in the ring, they will not be found!
931-
try:
932-
self.__addGroupThermoData(thermoData, self.groups['ring'], molecule, {})
933-
except KeyError:
934-
logging.error("Couldn't find in ring database:")
935-
logging.error(ring)
936-
logging.error(ring.toAdjacencyList())
937-
raise
938-
884+
thermoData = self.estimateThermoViaGroupAdditivityForSaturatedStruct(molecule)
939885

940886
# Correct entropy for symmetry number
941887
molecule.calculateSymmetryNumber()
942888
thermoData.S298.value_si -= constants.R * math.log(molecule.symmetryNumber)
943889

944890
return thermoData
945891

892+
def estimateThermoViaGroupAdditivityForSaturatedStruct(self, molecule):
893+
"""
894+
Return the set of thermodynamic parameters corresponding to a given
895+
:class:`Molecule` object `molecule` by estimation using the group
896+
additivity values. If no group additivity values are loaded, a
897+
:class:`DatabaseError` is raised.
898+
"""
899+
# For thermo estimation we need the atoms to already be sorted because we
900+
# iterate over them; if the order changes during the iteration then we
901+
# will probably not visit the right atoms, and so will get the thermo wrong
902+
molecule.sortVertices()
903+
904+
# Create the ThermoData object
905+
thermoData = ThermoData(
906+
Tdata = ([300,400,500,600,800,1000,1500],"K"),
907+
Cpdata = ([0.0,0.0,0.0,0.0,0.0,0.0,0.0],"J/(mol*K)"),
908+
H298 = (0.0,"kJ/mol"),
909+
S298 = (0.0,"J/(mol*K)"),
910+
)
911+
912+
cyclic = molecule.isCyclic()
913+
# Generate estimate of thermodynamics
914+
for atom in molecule.atoms:
915+
# Iterate over heavy (non-hydrogen) atoms
916+
if atom.isNonHydrogen():
917+
# Get initial thermo estimate from main group database
918+
try:
919+
self.__addGroupThermoData(thermoData, self.groups['group'], molecule, {'*':atom})
920+
except KeyError:
921+
logging.error("Couldn't find in main thermo database:")
922+
logging.error(molecule)
923+
logging.error(molecule.toAdjacencyList())
924+
raise
925+
# Correct for gauche and 1,5- interactions
926+
if not cyclic:
927+
try:
928+
self.__addGroupThermoData(thermoData, self.groups['gauche'], molecule, {'*':atom})
929+
except KeyError: pass
930+
try:
931+
self.__addGroupThermoData(thermoData, self.groups['int15'], molecule, {'*':atom})
932+
except KeyError: pass
933+
try:
934+
self.__addGroupThermoData(thermoData, self.groups['other'], molecule, {'*':atom})
935+
except KeyError: pass
936+
937+
# Do ring corrections separately because we only want to match
938+
# each ring one time
939+
940+
if cyclic:
941+
if molecule.getAllPolycyclicVertices():
942+
# If the molecule has fused ring atoms, this implies that we are dealing
943+
# with a polycyclic ring system, for which separate ring strain corrections may not
944+
# be adequate. Therefore, we search the polycyclic thermo group corrections
945+
# instead of adding single ring strain corrections within the molecule.
946+
# For now, assume only one polycyclic RSC can be found per molecule
947+
try:
948+
self.__addGroupThermoData(thermoData, self.groups['polycyclic'], molecule, {})
949+
except:
950+
logging.error("Couldn't find in polycyclic ring database:")
951+
logging.error(molecule)
952+
logging.error(molecule.toAdjacencyList())
953+
raise
954+
else:
955+
rings = molecule.getSmallestSetOfSmallestRings()
956+
for ring in rings:
957+
# Make a temporary structure containing only the atoms in the ring
958+
# NB. if any of the ring corrections depend on ligands not in the ring, they will not be found!
959+
try:
960+
self.__addGroupThermoData(thermoData, self.groups['ring'], molecule, {})
961+
except KeyError:
962+
logging.error("Couldn't find in ring database:")
963+
logging.error(ring)
964+
logging.error(ring.toAdjacencyList())
965+
raise
966+
967+
return thermoData
968+
946969
def __addThermoData(self, thermoData1, thermoData2):
947970
"""
948971
Add the thermodynamic data `thermoData2` to the data `thermoData1`,

0 commit comments

Comments
 (0)