def rotation(self,n,angles=False): """ Rotate around two axes: first around 'unit cell axis' for chirality and then around 'torus axis' for twisting.. Returns the rotation matrix. If angles==True, return (theta,phi,angle), where (theta,phi) gives the rotation axis and 'angle' the rotation angle. Approximate tangential vector by a mean tangential vector (-sin(angle/2),cos(angle/2),0) """ if n[2]==0: return np.eye(3) bend,twist = [self.get(k) for k in ['bend_angle','twist_angle']] rot1 = rotation_matrix(self.baxis,n[2]*bend) a = self.get('bend_angle') taxis = np.array([-sin(a/2),cos(a/2),0]) rot2 = rotation_matrix(taxis,n[2]*twist) R = np.dot(rot2,rot1) if angles: angle, dir = rotation_from_matrix(R) theta = np.arccos(dir[2]) if np.abs(theta)<1E-12 or np.abs(theta-np.pi)<1E-12: phi = 0. else: cosp, sinp = dir[0]/np.sin(theta), dir[1]/np.sin(theta) phi = phival(cosp,sinp) return (theta,phi,angle) else: return R
def rotation(self, n, angles=False): """ Rotate around two axes: first around 'unit cell axis' for chirality and then around 'torus axis' for twisting.. Returns the rotation matrix. If angles==True, return (theta,phi,angle), where (theta,phi) gives the rotation axis and 'angle' the rotation angle. Approximate tangential vector by a mean tangential vector (-sin(angle/2),cos(angle/2),0) """ if n[2] == 0: return np.eye(3) bend, twist = [self.get(k) for k in ['bend_angle', 'twist_angle']] rot1 = rotation_matrix(self.baxis, n[2] * bend) a = self.get('bend_angle') taxis = np.array([-sin(a / 2), cos(a / 2), 0]) rot2 = rotation_matrix(taxis, n[2] * twist) R = np.dot(rot2, rot1) if angles: angle, dir = rotation_from_matrix(R) theta = np.arccos(dir[2]) if np.abs(theta) < 1E-12 or np.abs(theta - np.pi) < 1E-12: phi = 0. else: cosp, sinp = dir[0] / np.sin(theta), dir[1] / np.sin(theta) phi = phival(cosp, sinp) return (theta, phi, angle) else: return R
def transform_arbitrary(self,r,bend,twist): """ The basic symmetry transformation with arbitrary angles b (bend angle) and t (twist angle) """ r = np.array(r) R = self.get('R') Rp = np.array([r[0],r[1],0.]) # vector on xy-plane Rv = R*Rp/np.linalg.norm(Rp) # vector to 'center' of tube rho = r-Rv # vector from tube center to r t = np.cross(np.array([0,0,1]),r) # tangential vector Rtwist = rotation_matrix(t,twist) Rbend = rotation_matrix(self.baxis,bend) return np.dot( Rbend,Rv+np.dot(Rtwist,rho) )
def transform_arbitrary(self,r,bend,twist): """ The basic symmetry transformation with arbitrary angles b (bend angle) and t (twist angle) """ r = np.array(r) R = self.get('R') Rp = np.array([r[0],r[1],0.]) Rv = R*Rp/np.linalg.norm(Rp) rho = r-Rv t = np.cross(np.array([0,0,1]),r) Rtwist = rotation_matrix(t,twist) Rbend = rotation_matrix(self.baxis,bend) return np.dot( Rbend(Rv+np.dot(Rtwist,rho)),r )
def transform_arbitrary(self, r, bend, twist): """ The basic symmetry transformation with arbitrary angles b (bend angle) and t (twist angle) """ r = np.array(r) R = self.get('R') Rp = np.array([r[0], r[1], 0.]) # vector on xy-plane Rv = R * Rp / np.linalg.norm(Rp) # vector to 'center' of tube rho = r - Rv # vector from tube center to r t = np.cross(np.array([0, 0, 1]), r) # tangential vector Rtwist = rotation_matrix(t, twist) Rbend = rotation_matrix(self.baxis, bend) return np.dot(Rbend, Rv + np.dot(Rtwist, rho))
def rotation(self,n): """ Rotate around two axes: first around 'unit cell axis' for chirality and then around 'torus axis' for twisting.. Returns the rotation matrix. """ if n[2]==0: return np.eye(3) a1,a2 = [self.get(k) for k in ['bend_angle','twist_angle']] rot1 = rotation_matrix(self.baxis,n[2]*a1) rot2 = rotation_matrix(self.taxis,n[2]*a2) return np.dot(rot2,rot1)
def transform(self,r,n): """ Symmetry transformation n for position r. """ if n[0]==n[1]==0: return r.copy() A = np.array( [0,0,2*self.R] ) a1,a2 = self.angle1*n[0], self.angle2*n[1] rot1 = rotation_matrix(self.n1,a1/self.M) rot2 = rotation_matrix(self.n2,a2/self.M) rp = r.copy() for i in range(self.M): rp = np.dot(rot1,rp) rp = A + np.dot( rot2,rp-A ) return rp
def transform(self, r, n): """ Symmetry transformation n for position r. """ if n[0] == n[1] == 0: return r.copy() A = np.array([0, 0, 2 * self.R]) a1, a2 = self.angle1 * n[0], self.angle2 * n[1] rot1 = rotation_matrix(self.n1, a1 / self.M) rot2 = rotation_matrix(self.n2, a2 / self.M) rp = r.copy() for i in range(self.M): rp = np.dot(rot1, rp) rp = A + np.dot(rot2, rp - A) return rp
def rotation(self,n,angles=False): """ Rotate around two axes, ordering depending on mode. """ if n[0]==n[1]==0: return np.eye(3) else: a1,a2 = self.angle1*n[0], self.angle2*n[1] #rot21 = np.dot( rotation_matrix(self.n2,a2/self.M),rotation_matrix(self.n1,a1/self.M) ) rot1 = rotation_matrix(self.n1,a1/self.M) rot2 = rotation_matrix(self.n2,a2/self.M) rot21 = np.dot(rot2,rot1) rot = np.eye(3) for i in range(self.M): #rot = np.dot( rot1,rot ) #rot = np.dot( rot2,rot ) rot = np.dot( rot21,rot ) return rot
def rotation(self, n, angles=False): """ Rotate around two axes, ordering depending on mode. """ if n[0] == n[1] == 0: return np.eye(3) else: a1, a2 = self.angle1 * n[0], self.angle2 * n[1] #rot21 = np.dot( rotation_matrix(self.n2,a2/self.M),rotation_matrix(self.n1,a1/self.M) ) rot1 = rotation_matrix(self.n1, a1 / self.M) rot2 = rotation_matrix(self.n2, a2 / self.M) rot21 = np.dot(rot2, rot1) rot = np.eye(3) for i in range(self.M): #rot = np.dot( rot1,rot ) #rot = np.dot( rot2,rot ) rot = np.dot(rot21, rot) return rot
def rotation(self, n, angles=False): """ Rotate around two axes, ordering depending on mode. """ if n[0] == n[1] == 0: return np.eye(3) angle1, angle2, n1, n2, mode = [ self.get(k) for k in ['angle1', 'angle2', 'n1', 'n2', 'mode'] ] if angles and mode != 4: raise NotImplementedError( 'Sphere rotation implemented only for mode 4 so far.') if self.mode == 1 or self.mode == 2: R1n = rotation_matrix(n1, n[0] * angle1) R2n = rotation_matrix(n2, n[1] * angle2) if mode == 1: return np.dot(R2n, R1n) else: return np.dot(R1n, R2n) elif mode == 3: # rotate R2**l2 * R1**l1 * (R2*R2)**m na = (abs(n[0]), abs(n[1]), 0) m = min(na[:2]) R1 = rotation_matrix(n1, np.sign(n[0]) * angle1) R2 = rotation_matrix(n2, np.sign(n[1]) * angle2) R21 = np.dot(R2, R1) R = np.eye(3) for i in range(m): R = np.dot(R, R21) # now rotate with the 'left-over' l1 = na[0] - m l2 = na[1] - m for i in range(l1): R = np.dot(R1, R) for i in range(l2): R = np.dot(R2, R) return R elif self.mode == 4: axis = angle1 * n[0] * n1 + angle2 * n[1] * n2 a1, a2 = angle1 * n[0], angle2 * n[1] angle = np.sqrt(a1**2 + a2**2 + 2 * a1 * a2 * np.dot(n1, n2)) if angles: axis = axis / np.linalg.norm(axis) return np.pi / 2., np.arctan2(axis[1], axis[0]), angle else: return rotation_matrix(axis, angle)
def rotation(self,n,angles=False): """ Rotate around two axes, ordering depending on mode. """ if n[0]==n[1]==0: return np.eye(3) angle1, angle2, n1, n2, mode = [self.get(k) for k in ['angle1','angle2','n1','n2','mode']] if angles and mode!=4: raise NotImplementedError('Sphere rotation implemented only for mode 4 so far.') if self.mode==1 or self.mode==2: R1n = rotation_matrix( n1,n[0]*angle1 ) R2n = rotation_matrix( n2,n[1]*angle2 ) if mode==1: return np.dot(R2n,R1n) else: return np.dot(R1n,R2n) elif mode==3: # rotate R2**l2 * R1**l1 * (R2*R2)**m na = (abs(n[0]),abs(n[1]),0) m = min(na[:2]) R1 = rotation_matrix( n1,np.sign(n[0])*angle1 ) R2 = rotation_matrix( n2,np.sign(n[1])*angle2 ) R21 = np.dot(R2,R1) R = np.eye(3) for i in range(m): R = np.dot(R,R21) # now rotate with the 'left-over' l1 = na[0]-m l2 = na[1]-m for i in range(l1): R = np.dot(R1,R) for i in range(l2): R = np.dot(R2,R) return R elif self.mode==4: axis = angle1*n[0]*n1 + angle2*n[1]*n2 a1,a2 = angle1*n[0], angle2*n[1] angle = np.sqrt( a1**2 + a2**2 + 2*a1*a2*np.dot(n1,n2) ) if angles: axis = axis/np.linalg.norm(axis) return np.pi/2.,np.arctan2(axis[1],axis[0]),angle else: return rotation_matrix( axis,angle )
def rotation(self,n,angles=False): """ Rotate around two axes, ordering depending on mode. """ if n[0]==n[1]==0: return np.eye(3) else: R1, R2 = self.R1, self.R2 a,b = self.angle1*n[0], self.angle2*n[1] R = ( (a*R1)**2+(b*R2)**2 )/( a**2*R1+b**2*R2 ) axis = np.array( [R2*b,R1*a,0] ) angle = ( a**2*R1+b**2*abs(R2) )/np.sqrt( (a*R1)**2+(b*R2)**2 ) return rotation_matrix( axis,angle )
def rotation(self, n, angles=False): """ Rotate around two axes, ordering depending on mode. """ if n[0] == n[1] == 0: return np.eye(3) else: R1, R2 = self.R1, self.R2 a, b = self.angle1 * n[0], self.angle2 * n[1] R = ((a * R1)**2 + (b * R2)**2) / (a**2 * R1 + b**2 * R2) axis = np.array([R2 * b, R1 * a, 0]) angle = (a**2 * R1 + b**2 * abs(R2)) / np.sqrt((a * R1)**2 + (b * R2)**2) return rotation_matrix(axis, angle)
def transform(self,r,n): """ Symmetry transformation n for position r. """ if n[2]==0: return r.copy() a1, a2, R, mode = [self.get(k) for k in ['bend_angle','twist_angle','R','mode']] n1 = self.n1 if mode == 2: orig_chir = np.cross(n2,n1) orig_chir = orig_chir/np.linalg.norm(orig_chir) A = np.dot(R,orig_chir) rot1 = rotation_matrix(n1,n[2]*a1) rot2 = rotation_matrix(n2,-n[2]*a2) Rot = np.dot( rot2,rot1 ) rp = r.copy() rp = np.dot( Rot,rp-A ) + np.dot( rot2,A ) return rp elif mode == 1: x, y, z = r x,y,z = x,z,-y alpha1 = phival(x,y) Rr = np.sqrt(x**2+y**2) R1 = R * np.array([np.cos(alpha1),np.sin(alpha1),np.zeros_like(alpha1)]) rho = np.linalg.norm(r-R1) beta1 = phival(Rr-R,z) alpha2 = alpha1 + n[2]*a1 beta2 = beta1 + n[2]*a2 Rrp = R + rho*np.cos(beta2) return np.array( [Rrp*np.cos(alpha2),Rrp*np.sin(alpha2),-rho*np.sin(beta2)] ) else: raise AssertionError('TwistAndTurn mode is not set')