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
Esempio n. 2
0
    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