@@ -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