def addBond(self, Atom1, Atom2, jMatrix = None):     
     """Adds a bond and all symmettry equivalent bonds within the magnetic Cell
     
     Performs every symmetry operation and every possible translation for each 
     symmetry operation to find all possible bonds"""
     
     #Create Symmetry Bonds
     
     xyz = Atom1.getPosition()
     xyz2 = Atom2.getPosition()
     
     for symop in self.space_Group.iter_symops():
     # operate on coordinates in non-shifted spacegroup
         pos1 = symop(xyz)
         pos2 = symop(xyz2)
         
         #Recording symops that map bond back to itself (for symmetry constraints)
         if xyz[0] == pos1[0] and xyz2[0] == pos2[0]: #x component
             if xyz[1] == pos1[1] and xyz2[1] == pos2[1]: #y component
                 if xyz[2] == pos1[2] and xyz2[2] == pos2[2]: #z component
                     self.bondConstraints.append(BondConstraint(xyz, xyz2, symop))
         
         
         mask1 = numpy.logical_or(pos1 < 0.0, pos1 >= 1.0)
         translation = numpy.floor(pos1[mask1])  #translates the first atom back to cell at (0,0,0)
         pos1[mask1] -= translation
         pos2[mask1] -= translation  #Uses same translation to translate other atom
              
         
         #translate new Bond to all cells 
         
         #Find the number of times to translate the bond in each direction so
         #that it will will cover the whole magnetic cell but not go outside
         if pos1[0]>pos2[0]:
             Xiter = self.Na - pos1[0]
         else:
             Xiter = self.Na - pos2[0]
         
         if pos1[1] > pos2[1]:
             Yiter = self.Nb - pos1[1]
         else:
             Yiter = self.Nb - pos2[1]
         
         if pos1[2] > pos2[2]:
             Ziter = self.Nc - pos1[2]
         else:
             Ziter = self.Nc - pos2[2]
         
         Xiter = int(Xiter) + 1 
         Yiter = int(Yiter) + 1
         Ziter = int(Ziter) + 1
         
         #iterate through each possible translation and check if there are atoms there that could
         #be bonded; if so, add the bond
         for i in range(0, Xiter): #translate in x direction (Na - Cell X position) times
             for j in range(0, Yiter): #translate in y direction (Nb - Cell Y position) times
                 for k in range(0, Ziter): #translate in z direction (Nc - Cell Z position) times
                     translatedAtom1 = self.atomAtPosition((i + pos1[0],j + pos1[1],k + pos1[2]))
                     translatedAtom2 = self.atomAtPosition((i + pos2[0],j + pos2[1],k + pos2[2]))
                     
                     if translatedAtom1 != None and translatedAtom2 != None:
                         newBond = Bond(translatedAtom1, translatedAtom2, jMatrix)
                     
                         #make sure bond does not already exist
                         for currentBond in self.Bonds:
                             if newBond.sameBond(currentBond):
                                 break
                         else:  #if not, add the bond to the list of unique bonds
                             self.Bonds.append(newBond)
    def addBond(self, atom1Num = None, atom1CellPos = None, atom2Num = None,
                atom2CellPos = None, jMatrix = None, atom1 = None,
                atom2 = None):
        """Adds an interaction between two atoms.
        
        atom1Num is the unique number identifying the given atom in the unit cell.
	atom1CellPos is a 3 integer tuple with the coordinates of the unit
	cell containing atom1.
        
        JMatrix is the 3x3 matrix describing the spin-spin interaction between
        the atoms for the heisenberg hamiltonian.
        
        If a bond with the same JMatrix that links the same two atoms already exists 
        nothing happens.  If a bond linking the two atoms exists, but has a different
        JMatrix, an Exception is raised.
        """
        if atom1 == None:
            cell1 = self.cellAtPosition((atom1CellPos[0], atom1CellPos[1], atom1CellPos[2]))
            atom1 = cell1.atomWithID(atom1Num)
            
        if atom2 == None:
            cell2 = self.cellAtPosition((atom2CellPos[0], atom2CellPos[1], atom2CellPos[2]))
            atom2 = cell2.atomWithID(atom2Num)
        
        existingBond = self.getBond(atom1, atom2)
        if existingBond != None:
            if (existingBond.getJMatrix() != jMatrix).any():
                #An exception will be raised if a different bond already exists
                #that links these atoms.
                raise Exception("A Bond already exists linking Atom1: " +
                                atom1.__str__()+" and Atom2: "+atom2.__str__())
            else:#The bond exists, but it's the same bond
                return
            
    #def addBond(self, Atom1, Atom2, jMatrix = None):     
        #"""Adds a bond and all symmettry equivalent bonds within the magnetic Cell
        
        #Performs every symmetry operation and every possible translation for each 
        #symmetry operation to find all possible bonds"""
        
        #Create Symmetry Bonds
        
        xyz = atom1.getPosition()
        xyz2 = atom2.getPosition()
        
        for symop in self.space_Group.iter_symops():
        # operate on coordinates in non-shifted spacegroup
            pos1 = symop(xyz)
            pos2 = symop(xyz2)
            
            #Recording symops that map bond back to itself (for symmetry constraints)
            if xyz[0] == pos1[0] and xyz2[0] == pos2[0]: #x component
                if xyz[1] == pos1[1] and xyz2[1] == pos2[1]: #y component
                    if xyz[2] == pos1[2] and xyz2[2] == pos2[2]: #z component
                        self.bondConstraints.append(BondConstraint(xyz, xyz2, symop))
            
            
            mask1 = numpy.logical_or(pos1 < 0.0, pos1 >= 1.0)
            translation = numpy.floor(pos1[mask1])  #translates the first atom back to cell at (0,0,0)
            pos1[mask1] -= translation
            pos2[mask1] -= translation  #Uses same translation to translate other atom
                 
            
            #translate new Bond to all cells 
            
            #Find the number of times to translate the bond in each direction so
            #that it will will cover the whole magnetic cell but not go outside
            if pos1[0]>pos2[0]:
                Xiter = self.Na - pos1[0]
            else:
                Xiter = self.Na - pos2[0]
            
            if pos1[1] > pos2[1]:
                Yiter = self.Nb - pos1[1]
            else:
                Yiter = self.Nb - pos2[1]
            
            if pos1[2] > pos2[2]:
                Ziter = self.Nc - pos1[2]
            else:
                Ziter = self.Nc - pos2[2]
            
            Xiter = int(Xiter) + 1 
            Yiter = int(Yiter) + 1
            Ziter = int(Ziter) + 1
            
            #iterate through each possible translation and check if there are atoms there that could
            #be bonded; if so, add the bond
            for i in range(0, Xiter): #translate in x direction (Na - Cell X position) times
                for j in range(0, Yiter): #translate in y direction (Nb - Cell Y position) times
                    for k in range(0, Ziter): #translate in z direction (Nc - Cell Z position) times
                        translatedAtom1 = self.atomAtPosition((i + pos1[0],j + pos1[1],k + pos1[2]))
                        translatedAtom2 = self.atomAtPosition((i + pos2[0],j + pos2[1],k + pos2[2]))
                        
                        if translatedAtom1 != None and translatedAtom2 != None:
                            newBond = Bond(translatedAtom1, translatedAtom2, jMatrix)
                        
                            #make sure bond does not already exist
                            for currentBond in self.Bonds:
                                if newBond.sameBond(currentBond):
                                    break
                            else:  #if not, add the bond to the list of unique bonds
                                self.Bonds.append(newBond)
    def addBond(self,
                atom1Num=None,
                atom1CellPos=None,
                atom2Num=None,
                atom2CellPos=None,
                jMatrix=None,
                atom1=None,
                atom2=None):
        """Adds an interaction between two atoms.
        
        atom1Num is the unique number identifying the given atom in the unit cell.
	atom1CellPos is a 3 integer tuple with the coordinates of the unit
	cell containing atom1.
        
        JMatrix is the 3x3 matrix describing the spin-spin interaction between
        the atoms for the heisenberg hamiltonian.
        
        If a bond with the same JMatrix that links the same two atoms already exists 
        nothing happens.  If a bond linking the two atoms exists, but has a different
        JMatrix, an Exception is raised.
        """
        if atom1 == None:
            cell1 = self.cellAtPosition(
                (atom1CellPos[0], atom1CellPos[1], atom1CellPos[2]))
            atom1 = cell1.atomWithID(atom1Num)

        if atom2 == None:
            cell2 = self.cellAtPosition(
                (atom2CellPos[0], atom2CellPos[1], atom2CellPos[2]))
            atom2 = cell2.atomWithID(atom2Num)

        existingBond = self.getBond(atom1, atom2)
        if existingBond != None:
            if (existingBond.getJMatrix() != jMatrix).any():
                #An exception will be raised if a different bond already exists
                #that links these atoms.
                raise Exception("A Bond already exists linking Atom1: " +
                                atom1.__str__() + " and Atom2: " +
                                atom2.__str__())
            else:  #The bond exists, but it's the same bond
                return

    #def addBond(self, Atom1, Atom2, jMatrix = None):
    #"""Adds a bond and all symmettry equivalent bonds within the magnetic Cell

    #Performs every symmetry operation and every possible translation for each
    #symmetry operation to find all possible bonds"""

    #Create Symmetry Bonds

        xyz = atom1.getPosition()
        xyz2 = atom2.getPosition()

        for symop in self.space_Group.iter_symops():
            # operate on coordinates in non-shifted spacegroup
            pos1 = symop(xyz)
            pos2 = symop(xyz2)

            #Recording symops that map bond back to itself (for symmetry constraints)
            if xyz[0] == pos1[0] and xyz2[0] == pos2[0]:  #x component
                if xyz[1] == pos1[1] and xyz2[1] == pos2[1]:  #y component
                    if xyz[2] == pos1[2] and xyz2[2] == pos2[2]:  #z component
                        self.bondConstraints.append(
                            BondConstraint(xyz, xyz2, symop))

            mask1 = numpy.logical_or(pos1 < 0.0, pos1 >= 1.0)
            translation = numpy.floor(
                pos1[mask1]
            )  #translates the first atom back to cell at (0,0,0)
            pos1[mask1] -= translation
            pos2[
                mask1] -= translation  #Uses same translation to translate other atom

            #translate new Bond to all cells

            #Find the number of times to translate the bond in each direction so
            #that it will will cover the whole magnetic cell but not go outside
            if pos1[0] > pos2[0]:
                Xiter = self.Na - pos1[0]
            else:
                Xiter = self.Na - pos2[0]

            if pos1[1] > pos2[1]:
                Yiter = self.Nb - pos1[1]
            else:
                Yiter = self.Nb - pos2[1]

            if pos1[2] > pos2[2]:
                Ziter = self.Nc - pos1[2]
            else:
                Ziter = self.Nc - pos2[2]

            Xiter = int(Xiter) + 1
            Yiter = int(Yiter) + 1
            Ziter = int(Ziter) + 1

            #iterate through each possible translation and check if there are atoms there that could
            #be bonded; if so, add the bond
            for i in range(
                    0, Xiter
            ):  #translate in x direction (Na - Cell X position) times
                for j in range(
                        0, Yiter
                ):  #translate in y direction (Nb - Cell Y position) times
                    for k in range(
                            0, Ziter
                    ):  #translate in z direction (Nc - Cell Z position) times
                        translatedAtom1 = self.atomAtPosition(
                            (i + pos1[0], j + pos1[1], k + pos1[2]))
                        translatedAtom2 = self.atomAtPosition(
                            (i + pos2[0], j + pos2[1], k + pos2[2]))

                        if translatedAtom1 != None and translatedAtom2 != None:
                            newBond = Bond(translatedAtom1, translatedAtom2,
                                           jMatrix)

                            #make sure bond does not already exist
                            for currentBond in self.Bonds:
                                if newBond.sameBond(currentBond):
                                    break
                            else:  #if not, add the bond to the list of unique bonds
                                self.Bonds.append(newBond)