def getResonanceHybrid(self): """ Returns a molecule object with bond orders that are the average of all the resonance structures. """ # get labeled resonance isomers self.generate_resonance_structures(keep_isomorphic=True) # only consider reactive molecules as representative structures molecules = [mol for mol in self.molecule if mol.reactive] # return if no resonance if len(molecules) == 1: return molecules[0] # create a sorted list of atom objects for each resonance structure cython.declare(atomsFromStructures = list, oldAtoms = list, newAtoms = list, numResonanceStructures=cython.short, structureNum = cython.short, oldBondOrder = cython.float, index1 = cython.short, index2 = cython.short, newMol=Molecule, oldMol = Molecule, atom1=Atom, atom2=Atom, bond=Bond, atoms=list,) atomsFromStructures = [] for newMol in molecules: newMol.atoms.sort(key=lambda atom: atom.id) atomsFromStructures.append(newMol.atoms) numResonanceStructures = len(molecules) # make original structure with no bonds newMol = Molecule() originalAtoms = atomsFromStructures[0] for atom1 in originalAtoms: atom = newMol.addAtom(Atom(atom1.element)) atom.id = atom1.id newAtoms = newMol.atoms # initialize bonds to zero order for index1, atom1 in enumerate(originalAtoms): for atom2 in atom1.bonds: index2 = originalAtoms.index(atom2) bond = Bond(newAtoms[index1],newAtoms[index2], 0) newMol.addBond(bond) # set bonds to the proper value for structureNum, oldMol in enumerate(molecules): oldAtoms = atomsFromStructures[structureNum] for index1, atom1 in enumerate(oldAtoms): # make bond orders average of resonance structures for atom2 in atom1.bonds: index2 = oldAtoms.index(atom2) newBond = newMol.getBond(newAtoms[index1], newAtoms[index2]) oldBondOrder = oldMol.getBond(oldAtoms[index1], oldAtoms[index2]).getOrderNum() newBond.applyAction(('CHANGE_BOND',None,oldBondOrder / numResonanceStructures / 2)) # set radicals in resonance hybrid to maximum of all structures if atom1.radicalElectrons > 0: newAtoms[index1].radicalElectrons = max(atom1.radicalElectrons, newAtoms[index1].radicalElectrons) newMol.updateAtomTypes(logSpecies = False, raiseException=False) return newMol