Esempio n. 1
0
 def get_ase_cell(self):
     """ cell used for visualization """
     h = max(self.atoms.get_positions()[:,2])
     phi1 = phival(self.n1[0],self.n1[1])
     phi2 = phival(self.n2[0],self.n2[1])
     a1,l1 = phi1-np.pi/2, h*self.angle1
     a2,l2 = phi2-np.pi/2, h*self.angle2
     return np.array( [[l1*cos(a1),l1*sin(a1),0],[l2*cos(a2),l2*sin(a2),0],[0,0,h]] )
Esempio n. 2
0
 def get_ase_cell(self):
     """ cell used for visualization """
     h = max(self.atoms.get_positions()[:, 2])
     phi1 = phival(self.n1[0], self.n1[1])
     phi2 = phival(self.n2[0], self.n2[1])
     a1, l1 = phi1 - np.pi / 2, h * self.angle1
     a2, l2 = phi2 - np.pi / 2, h * self.angle2
     return np.array([[l1 * cos(a1), l1 * sin(a1), 0],
                      [l2 * cos(a2), l2 * sin(a2), 0], [0, 0, h]])
Esempio n. 3
0
    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
Esempio n. 4
0
def angular(r,wf):
    """ Return angular part of wave function.
    
    The real combinations of Y_lm's
    
    parameters:
    -----------
    r: (not normalized) position vector
    wf: index or symbol for state (look below)
    """
    R=sqrt(sum(r**2))
    if R<1E-14:
        return 0.0
    theta=acos(r[2]/R)
    phi=phival(r[0],r[1])

    if type(wf)!=type(1):
        wf=states.index(wf)

    if wf==0:   return 1/sqrt(4*pi)
    elif wf==1: return sqrt(3/(4*pi))*sin(theta)*cos(phi)
    elif wf==2: return sqrt(3/(4*pi))*sin(theta)*sin(phi)
    elif wf==3: return sqrt(3/(4*pi))*cos(theta)
    elif wf==4: return sqrt(15/(4*pi))*sin(theta)**2*cos(phi)*sin(phi)
    elif wf==5: return sqrt(15/(4*pi))*sin(theta)*cos(theta)*sin(phi)
    elif wf==6: return sqrt(15/(4*pi))*sin(theta)*cos(theta)*cos(phi)
    elif wf==7: return 0.5*sqrt(15/(4*pi))*sin(theta)**2*cos(2*phi)
    elif wf==8: return 0.5*sqrt(5/(4*pi))*(3*cos(theta)**2-1)
Esempio n. 5
0
    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
Esempio n. 6
0
    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')
Esempio n. 7
0
def to_spherical_coordinates(vec):
    """ Transforms the given cartesien vector to spherical
        coordinates. """
    x, y, z = vec
    r = float(np.linalg.norm(vec))
    if r < 1e-6:
        r = 0.0
        theta = 0.0
        phi = 0.0
    else:
        theta = float(acos(z/r))
        phi = float(phival(x,y))
    assert 0 <= theta <= np.pi
    assert 0 <= phi <= 2*np.pi
    return (r, theta, phi)
Esempio n. 8
0
def to_spherical_coordinates(vec):
    """ Transforms the given cartesien vector to spherical
        coordinates. """
    x, y, z = vec
    r = float(np.linalg.norm(vec))
    if r < 1e-6:
        r = 0.0
        theta = 0.0
        phi = 0.0
    else:
        theta = float(acos(z / r))
        phi = float(phival(x, y))
    assert 0 <= theta <= np.pi
    assert 0 <= phi <= 2 * np.pi
    return (r, theta, phi)
Esempio n. 9
0
    def set(self, angle=None, height=None, x=None, scale_atoms=False, container=None):
        """
        Reset angle, height, or x, and maybe scale atoms.
         
        parameters:
        ===========
        height:   Height of the primitive cell in z-direction
        angle:    angle (in radians) of rotation
        x:        fractional translation offset related to 180 rotation
                  Only integers and half-integers allowed.
        """
        if container != None:
            # copy container
            assert angle == None and height == None and x == None and scale_atoms == False
            self.set(angle=container.get("angle"), height=container.get("height"), x=container.get("x"))
        else:
            if x != None:
                assert abs(np.round(2 * x) - 2 * x) < 1e-15
            if not scale_atoms:
                if angle != None:
                    self._set(angle=angle)
                if height != None:
                    self._set(height=height)
                if x != None:
                    self._set(x=x)
            else:
                if x != None:
                    raise AssertionError("It is probably illegal to change x. This changes the symmetry, right?")
                if angle is None:
                    da = 0.0
                else:
                    da = angle - self.get("angle")
                    self._set(angle=angle)

                old_height = self.get("height")
                if height != None:
                    self._set(height=height)

                newr = []
                for r in self.atoms.get_positions():
                    x, y = r[0], r[1]
                    rad = np.sqrt(x ** 2 + y ** 2)
                    frac = r[2] / old_height
                    # twist atoms z/h * da (more)
                    newphi = phival(x, y) + frac * da
                    newr.append([rad * np.cos(newphi), rad * np.sin(newphi), frac * self.get("height")])
                self.atoms.set_positions(newr)
Esempio n. 10
0
    def set(self, angle=None, height=None, scale_atoms=False, container=None):
        """
        Reset angle or height, and maybe scale atoms.
         
        @param: height   Height of the primitive cell in z-direction
        @param: angle    angle (in radians) of rotation
        """
        if container != None:
            # copy container
            assert angle == None and height == None and scale_atoms == False
            self.set(angle=container.get('angle'),
                     height=container.get('height'))
        else:
            if not scale_atoms:
                if angle != None: self._set(angle=angle)
                if height != None: self._set(height=height)
            else:
                if angle is None:
                    da = 0.0
                else:
                    da = angle - self.get('angle')
                    self._set(angle=angle)

                old_height = self.get('height')
                if height != None:
                    self._set(height=height)

                newr = []
                for r in self.atoms.get_positions():
                    x, y = r[0], r[1]
                    rad = np.sqrt(x**2 + y**2)
                    frac = r[2] / old_height
                    # twist atoms z/h * da (more)
                    newphi = phival(x, y) + frac * da
                    newr.append([
                        rad * np.cos(newphi), rad * np.sin(newphi),
                        frac * self.get('height')
                    ])
                self.atoms.set_positions(newr)
Esempio n. 11
0
def angular(r, wf):
    """ Return angular part of wave function.
    
    The real combinations of Y_lm's
    
    parameters:
    -----------
    r: (not normalized) position vector
    wf: index or symbol for state (look below)
    """
    R = sqrt(sum(r ** 2))
    if R < 1e-14:
        return 0.0
    theta = acos(r[2] / R)
    phi = phival(r[0], r[1])

    if type(wf) != type(1):
        wf = states.index(wf)

    if wf == 0:
        return 1 / sqrt(4 * pi)
    elif wf == 1:
        return sqrt(3 / (4 * pi)) * sin(theta) * cos(phi)
    elif wf == 2:
        return sqrt(3 / (4 * pi)) * sin(theta) * sin(phi)
    elif wf == 3:
        return sqrt(3 / (4 * pi)) * cos(theta)
    elif wf == 4:
        return sqrt(15 / (4 * pi)) * sin(theta) ** 2 * cos(phi) * sin(phi)
    elif wf == 5:
        return sqrt(15 / (4 * pi)) * sin(theta) * cos(theta) * sin(phi)
    elif wf == 6:
        return sqrt(15 / (4 * pi)) * sin(theta) * cos(theta) * cos(phi)
    elif wf == 7:
        return 0.5 * sqrt(15 / (4 * pi)) * sin(theta) ** 2 * cos(2 * phi)
    elif wf == 8:
        return 0.5 * sqrt(5 / (4 * pi)) * (3 * cos(theta) ** 2 - 1)
Esempio n. 12
0
    def set(self,
            angle=None,
            height=None,
            M=None,
            physical=True,
            pbcz=None,
            scale_atoms=False,
            container=None):
        """ Only height can be reset, not angle.

        parameters:
        ===========
        angle    angle (in radians) of the wedge (and M=None)
        height   Height of the primitive cell in z-direction
        M        set angle to 2*pi/M (and angle=None)
        physical (only if M=None) if angle is small, it does not be
                         exactly 2*pi/integer, i.e. situation has no physical meaning
                         (use for calculating stuff continuously)
        pbcz     True if wedge is periodic in z-direction
        scale_atoms Scale atoms according to changes in parameters. When changing angle, scale
                    also radial distances. (Radii are inversely proportional to angle.)
        """
        if container != None:
            assert angle == None and height == None and M == None and pbcz == None
            self.set(angle=container.get('angle'),height=container.get('height'),\
                     physical=container.get('physical'), pbcz=container.atoms.get_pbc()[2])

        if angle != None or M != None:
            #assert not scale_atoms
            assert not (angle != None and M != None)
            old_angle = self.get('angle')
            if M != None:
                assert isinstance(M, int)
                self._set(angle=2 * np.pi / M)
            elif angle != None:
                M = int(round(2 * np.pi / angle))
                self._set(angle=angle)

            # check parameters
            self._set(physical=float(physical))
            if self.get('angle') < 1E-6:
                raise Warning(
                    'Too small angle (%f) may bring numerical problems.' %
                    self.get('angle'))
            if self.get('angle') > np.pi:
                raise AssertionError('angle>pi')
            if np.abs(M - 2 * np.pi / self.get('angle')) > 1E-12 and self.get(
                    'physical'):
                raise AssertionError('angle not physical: angle != 2*pi/M')
            if not self.get('physical') and M < 20:
                warnings.warn('Quite large, non-physical angle 2*pi/%.4f.' %
                              (2 * np.pi / self.get('angle')))

            if scale_atoms:
                if abs(old_angle) < 1E-10:
                    raise ValueError(
                        'Atoms cannot be scaled; old wedge angle too small.')
                newr = []
                for r in self.atoms.get_positions():
                    x, y = r[0], r[1]
                    rad = np.sqrt(x**2 + y**2)
                    newphi = phival(x, y) * (self.get('angle') / old_angle)
                    rad2 = rad * old_angle / self.get('angle')
                    newr.append(
                        [rad2 * np.cos(newphi), rad2 * np.sin(newphi), r[2]])
                self.atoms.set_positions(newr)

        if height != None:
            if scale_atoms:
                r = self.atoms.get_positions()
                r[:, 2] = r[:, 2] * height / self.get('height')
                self.atoms.set_positions(r)
            self._set(height=height)

        if pbcz != None:
            self._set(pbcz=float(pbcz))
Esempio n. 13
0
    def set(self,bend_angle=None,twist_angle=None,R=None,mode=None,container=None,scale_atoms=False):
        """
        Reset angles, R or axes
        
        @param: bend_angle   bending angle
        @param: twist_angle  twisting angle
        @param: R            radius of curvature for neutral line
        @param: mode     	 mode for transformation (different modes of approximation)
        @param: scale_atoms  scale atoms according to container modifications
        """
        if container!=None:
            # copy container
            assert bend_angle==None
            assert twist_angle==None
            assert R==None
            assert mode == None
            self.set( angle1=container.bend_angle,
                      angle2=container.twist_angle,
                      R=container.R,
                      mode=container.mode)
        if bend_angle!=None:
            if scale_atoms:
                ratio = bend_angle/self.get('bend_angle')
                r = self.atoms.get_positions()
                R = np.sqrt( sum(r[:,0]**2+r[:,1]**2) )
                alpha1 = np.array([phival(x1,y1) for x1,y1 in zip(r[:,0],r[:,1])] )
                alpha = ratio*alpha1
                r2 = np.array( [R*np.cos(alpha),R*np.sin(alpha),r[:,2]] ).transpose()
                self.atoms.set_positions(r2)
            self._set(bend_angle = bend_angle)
        if twist_angle!=None:
            if scale_atoms:
                da = twist_angle - self.get('twist_angle')
                R = self.get('R')
                r = self.atoms.get_positions()
                alpha1 = np.array([phival(x1,y1) for x1,y1 in zip(r[:,0],r[:,1])] )
                Rr = np.sqrt(r[:,0]**2+r[:,1]**2)
                R1 = R * np.array( [np.cos(alpha1),np.sin(alpha1),np.zeros_like(alpha1)] ).transpose()
                rho = np.sqrt( np.sum((r-R1)**2,axis=1) ) 
                beta1 = np.array( [phival(a,b) for a,b in zip(Rr-R,-r[:,2])] )

                # scale twisting angle depending on angle between x and z (alpha1)
                x = alpha1/self.get('bend_angle')
                beta2  = beta1  + x*da 
                Rrp = R + rho*np.cos(beta2)
                r2 = np.array( [Rrp*np.cos(alpha1),Rrp*np.sin(alpha1),-rho*np.sin(beta2)] ).transpose()
                self.atoms.set_positions(r2)
            self._set(twist_angle = twist_angle)
        if R!=None:
            if scale_atoms:
                dR = R-self.get('R')
                r = self.atoms.get_positions()
                rad = np.sqrt( r[:,0]**2+r[:,1]**2 )
                phi = np.array([phival(x,y) for x,y in zip(r[:,0],r[:,1])] )
                r[:,0] = (rad+dR)*np.cos(phi)
                r[:,1] = (rad+dR)*np.sin(phi)
                self.atoms.set_positions(r)
            self._set(R = R)
        if mode!=None:
            self._set(mode = mode)

        self.atoms.set_pbc((False,False,True))
Esempio n. 14
0
    def set(self, angle=None, height=None, M=None, physical=True, twist=None, scale_atoms=False, container=None):
        """

        parameters:
        ===========
        angle    angle (in radians) of the wedge (and M=None)
        height   Height of the primitive cell in z-direction
        M        set angle to 2*pi/M (and angle=None)
        physical (only if M=None) if angle is small, it does not be
                         exactly 2*pi/integer, i.e. situation has no physical meaning
                         (use for calculating stuff continuously)
        twist     The twist angle for z-translation
        scale_atoms Scale atoms according to changes in parameters
        """
        if container!=None:
            assert angle==None and height==None and M==None and twist==None
            self.set(angle=container.get('angle'),height=container.get('height'),\
                     physical=container.get('physical'), twist=container.get('twist'))

        if angle!=None or M!=None:
            #assert not scale_atoms
            assert not (angle!=None and M!=None)
            old_angle = self.get('angle')
            if M != None:
                assert isinstance(M,int)
                self._set(angle=2*np.pi/M)
            elif angle != None:
                M = np.abs(int( round(2*np.pi/angle) ))
                self._set(angle=angle)

            # check parameters
            self._set( physical=float(physical) )
            if np.abs(self.get('angle'))<1E-6:
                raise Warning('Too small angle (%f) may bring numerical problems.' %self.get('angle'))
            if self.get('angle')>np.pi:
                raise AssertionError('angle>pi')
            if np.abs(M-2*np.pi/np.abs(self.get('angle')))>1E-12 and self.get('physical'):
                raise AssertionError('angle not physical: angle != 2*pi/M')
            if not self.get('physical') and M<20:
                warnings.warn('Quite large, non-physical angle 2*pi/%.4f.' %(2*np.pi/self.get('angle')) )

            if scale_atoms:
                if abs(old_angle)<1E-10:
                    raise ValueError('Atoms cannot be scaled; old wedge angle too small.')
                newr = []
                for r in self.atoms.get_positions():
                    x,y = r[0],r[1]
                    rad = np.sqrt( x**2+y**2 )
                    newphi = phival(x,y)*(self.get('angle')/old_angle)
                    newr.append( [rad*np.cos(newphi),rad*np.sin(newphi),r[2]] )
                self.atoms.set_positions(newr)

        if height!=None:
            if scale_atoms:
                r = self.atoms.get_positions()
                r[:,2] = r[:,2] * height/self.get('height')
                self.atoms.set_positions(r)
            self._set(height=height)

        if twist!=None:
            if scale_atoms:
                raise NotImplementedError('Atom rescale with twist not implemented.')
            self._set(twist=twist)
Esempio n. 15
0
    def set(self,
            angle=None,
            height=None,
            M=None,
            physical=True,
            twist=None,
            scale_atoms=False,
            container=None):
        """

        parameters:
        ===========
        angle    angle (in radians) of the wedge (and M=None)
        height   Height of the primitive cell in z-direction
        M        set angle to 2*pi/M (and angle=None)
        physical (only if M=None) if angle is small, it does not be
                         exactly 2*pi/integer, i.e. situation has no physical meaning
                         (use for calculating stuff continuously)
        twist     The twist angle for z-translation
        scale_atoms Scale atoms according to changes in parameters
        """
        if container != None:
            assert angle == None and height == None and M == None and twist == None
            self.set(angle=container.get('angle'),height=container.get('height'),\
                     physical=container.get('physical'), twist=container.get('twist'))

        if angle != None or M != None:
            #assert not scale_atoms
            assert not (angle != None and M != None)
            old_angle = self.get('angle')
            if M != None:
                assert isinstance(M, int)
                self._set(angle=2 * np.pi / M)
            elif angle != None:
                M = np.abs(int(round(2 * np.pi / angle)))
                self._set(angle=angle)

            # check parameters
            self._set(physical=float(physical))
            if np.abs(self.get('angle')) < 1E-6:
                raise Warning(
                    'Too small angle (%f) may bring numerical problems.' %
                    self.get('angle'))
            if self.get('angle') > np.pi:
                raise AssertionError('angle>pi')
            if np.abs(M - 2 * np.pi / np.abs(self.get('angle'))
                      ) > 1E-12 and self.get('physical'):
                raise AssertionError('angle not physical: angle != 2*pi/M')
            if not self.get('physical') and M < 20:
                warnings.warn('Quite large, non-physical angle 2*pi/%.4f.' %
                              (2 * np.pi / self.get('angle')))

            if scale_atoms:
                if abs(old_angle) < 1E-10:
                    raise ValueError(
                        'Atoms cannot be scaled; old wedge angle too small.')
                newr = []
                for r in self.atoms.get_positions():
                    x, y = r[0], r[1]
                    rad = np.sqrt(x**2 + y**2)
                    newphi = phival(x, y) * (self.get('angle') / old_angle)
                    newr.append(
                        [rad * np.cos(newphi), rad * np.sin(newphi), r[2]])
                self.atoms.set_positions(newr)

        if height != None:
            if scale_atoms:
                r = self.atoms.get_positions()
                r[:, 2] = r[:, 2] * height / self.get('height')
                self.atoms.set_positions(r)
            self._set(height=height)

        if twist != None:
            if scale_atoms:
                raise NotImplementedError(
                    'Atom rescale with twist not implemented.')
            self._set(twist=twist)
Esempio n. 16
0
    def set(self, angle=None, height=None, M=None, physical=True, pbcz=None, scale_atoms=False, container=None):
        """ Only height can be reset, not angle.

        parameters:
        ===========
        angle    angle (in radians) of the wedge (and M=None)
        height   Height of the primitive cell in z-direction
        M        set angle to 2*pi/M (and angle=None)
        physical (only if M=None) if angle is small, it does not be
                         exactly 2*pi/integer, i.e. situation has no physical meaning
                         (use for calculating stuff continuously)
        pbcz     True if wedge is periodic in z-direction
        scale_atoms Scale atoms according to changes in parameters. When changing angle, scale
                    also radial distances. (Radii are inversely proportional to angle.)
        """
        if container!=None:
            assert angle==None and height==None and M==None and pbcz==None
            self.set(angle=container.get('angle'),height=container.get('height'),\
                     physical=container.get('physical'), pbcz=container.atoms.get_pbc()[2])

        if angle!=None or M!=None:
            #assert not scale_atoms
            assert not (angle!=None and M!=None)
            old_angle = self.get('angle')
            if M != None:
                assert isinstance(M,int)
                self._set(angle=2*np.pi/M)
            elif angle != None:
                M = int( round(2*np.pi/angle) )
                self._set(angle=angle)

            # check parameters
            self._set( physical=float(physical) )
            if self.get('angle')<1E-6:
                raise Warning('Too small angle (%f) may bring numerical problems.' %self.get('angle'))
            if self.get('angle')>np.pi:
                raise AssertionError('angle>pi')
            if np.abs(M-2*np.pi/self.get('angle'))>1E-12 and self.get('physical'):
                raise AssertionError('angle not physical: angle != 2*pi/M')
            if not self.get('physical') and M<20:
                warnings.warn('Quite large, non-physical angle 2*pi/%.4f.' %(2*np.pi/self.get('angle')) )

            if scale_atoms:
                if abs(old_angle)<1E-10:
                    raise ValueError('Atoms cannot be scaled; old wedge angle too small.')
                newr = []
                for r in self.atoms.get_positions():
                    x,y = r[0],r[1]
                    rad = np.sqrt( x**2+y**2 )
                    newphi = phival(x,y)*(self.get('angle')/old_angle)
                    rad2 = rad * old_angle/self.get('angle')
                    newr.append( [rad2*np.cos(newphi),rad2*np.sin(newphi),r[2]] )
                self.atoms.set_positions(newr)

        if height!=None:
            if scale_atoms:
                r = self.atoms.get_positions()
                r[:,2] = r[:,2] * height/self.get('height')
                self.atoms.set_positions(r)
            self._set(height=height)

        if pbcz!=None:
            self._set(pbcz=float(pbcz))