def setUpRigidBodies(self): #set up one rigid body from pele.potentials.rigid_bodies.molecule import Molecule self.rb = Molecule() for atomlist in self.permlist: #make a rigid body from atomlist for i in atomlist: self.rb.insert_site( 0, self.XB0[i*3:i*3+3] )
class MinPermDistPotential(potential.potential): """ Find the rotation (in angle-axis representation) which maximizes the permutation independent overlap between two structures. This potential defines the energy as the overlap, here defined as E = - sum_i sum_j exp( -|x_Ai - X_Bj|**2 / L**2 ) There are other options for the overlap which are not implemented. For instance something with a slower decay than exp(-R**2). """ def __init__(self, XA, XB, L=0.2, permlist = []): self.XA0 = np.copy(XA) self.XB0 = np.copy(XB) self.XB = np.copy(XB) self.nsites = len(XA)/3 self.L2 = L*L self.permlist = permlist if len(self.permlist) == 0: self.permlist = [range( self.nsites)] try: from overlap import overlap, overlap_gradient self.overlap = overlap self.overlap_gradient = overlap_gradient except ImportError: #self.overlap = overlap_fast self.overlap = overlap_fast self.overlap_gradient = overlap_gradient_slow print "MinPermDistPotential> Using python energy calculation. Compile overlap.f90 to speed things up (a little)" self.setUpRigidBodies() def setUpRigidBodies(self): #set up one rigid body from pele.potentials.rigid_bodies.molecule import Molecule self.rb = Molecule() for atomlist in self.permlist: #make a rigid body from atomlist for i in atomlist: self.rb.insert_site( 0, self.XB0[i*3:i*3+3] ) def getEnergy_no_rigid_body(self, AA ): # Rotate XB0 according to angle axis AA rot_mx = rot.aa2mx( AA ) for j in range(self.nsites): i = 3*j self.XB[i:i+3] = np.dot( rot_mx, self.XB0[i:i+3] ) #return distance between XB and XA0 E = 0. for atomlist in self.permlist: E -= self.overlap( self.XA0, self.XB, self.L2, atomlist, [self.nsites, len(atomlist)]) #if E < -10.5: # print E, atomlist, [self.nsites, len(atomlist)], len(self.XA0), len(self.XB) return E def getEnergy(self, AA): # Rotate rigid body according to angle axis AA self.XB = self.rb.getxyz( aa = AA ) #get energy and gradient for each site E = 0. for atomlist in self.permlist: E -= self.overlap( self.XA0, self.XB, self.L2, atomlist, [self.nsites, len(atomlist)]) return E def getEnergyGradient(self, AA): # Rotate XB0 according to angle axis AA # Rotate rigid body according to angle axis AA self.XB = self.rb.getxyz( aa = AA ) #get energy and gradient for each site E = 0. grad = np.zeros(len(self.XB)) for atomlist in self.permlist: de, dg = self.overlap_gradient( self.XA0, self.XB, self.L2, atomlist, [self.nsites, len(atomlist)]) E -= de grad -= dg #convert site-gradients into angle -axis gradients #first calculate the rotation matrix and derivatives comgrad, aagrad = self.rb.getGradients(AA, grad, True) return E, aagrad def globalEnergyMin(self): """ return the lowest energy theoretically possible. This will happen if XB == XA """ E = 0. for atomlist in self.permlist: E -= self.overlap( self.XA0, self.XA0, self.L2, atomlist, [self.nsites, len(atomlist)]) return E