コード例 #1
0
ファイル: geometry.py プロジェクト: zhenming-xu/nanocut
    def gen_cuboid(self, cuboid, periodicity=None):
        """Generates list of lattice points containing all points in a cuboid.
        
        Args:
            cuboid: lower and upper ends of the cuboid.
            periodicity: periodicity object.
            
        Returns:
            Cartesian coordinates of the grid points.
        """

        # Get the 8 corners of the cuboid
        mesh = np.mgrid[0:2, 0:2, 0:2].reshape(3, -1).transpose()
        abc_corners = [[cuboid[mm[0], 0], cuboid[mm[1], 1], cuboid[mm[2], 2]]
                       for mm in mesh]

        # Get corners of the containing parallelepiped in relative coordinates
        invlatvecs = np.linalg.inv(self.latvecs)
        nmo_corners = np.dot(abc_corners, invlatvecs)
        nmo_mininds = np.floor(nmo_corners.min(axis=0)).astype(int)
        nmo_maxinds = np.floor(nmo_corners.max(axis=0)).astype(int)

        # Generate mesh indexing all points inside the parallelepiped
        nallpoint = np.abs(np.prod(nmo_maxinds - nmo_mininds))
        printstatus("Number of necessary grid points: {:d}".format(
            int(nallpoint)),
                    indentlevel=1)
        nmo = np.mgrid[nmo_mininds[0]:nmo_maxinds[0] + 1,
                       nmo_mininds[1]:nmo_maxinds[1] + 1,
                       nmo_mininds[2]:nmo_maxinds[2] + 1, ]
        nmo = nmo.reshape(3, -1).transpose()

        # Throw away points in the parallelepiped which are farther away from
        # the cuboid as the maximal size of the unit cell along given direction
        abc = np.dot(nmo, self.latvecs)
        buffer = np.max(np.abs(self.latvecs), axis=0)
        cond1 = np.all(abc < cuboid[0] - buffer, axis=1)
        cond2 = np.all(abc > cuboid[1] + buffer, axis=1)
        inside = np.logical_not(np.logical_or(cond1, cond2))
        return np.dot(nmo[inside], self.latvecs)
コード例 #2
0
ファイル: geometry.py プロジェクト: aradi/nanocut
    def gen_cuboid(self, cuboid, periodicity=None):
        """Generates list of lattice points containing all points in a cuboid.
        
        Args:
            cuboid: lower and upper ends of the cuboid.
            periodicity: periodicity object.
            
        Returns:
            Cartesian coordinates of the grid points.
        """

        # Get the 8 corners of the cuboid
        mesh = np.mgrid[0:2,0:2,0:2].reshape(3, -1).transpose()
        abc_corners = [ [ cuboid[mm[0],0], cuboid[mm[1],1], cuboid[mm[2],2] ]
                          for mm in mesh ]

        # Get corners of the containing parallelepiped in relative coordinates
        invlatvecs = np.linalg.inv(self.latvecs)
        nmo_corners = np.dot(abc_corners, invlatvecs)
        nmo_mininds = np.floor(nmo_corners.min(axis=0)).astype(int)
        nmo_maxinds = np.floor(nmo_corners.max(axis=0)).astype(int)
        
        # Generate mesh indexing all points inside the parallelepiped
        nallpoint = np.abs(np.prod(nmo_maxinds - nmo_mininds))
        printstatus(
            "Number of necessary grid points: {:d}".format(int(nallpoint)),
            indentlevel=1)
        nmo = np.mgrid[nmo_mininds[0]:nmo_maxinds[0]+1,
                       nmo_mininds[1]:nmo_maxinds[1]+1,
                       nmo_mininds[2]:nmo_maxinds[2]+1, ]
        nmo = nmo.reshape(3, -1).transpose()
        
        # Throw away points in the parallelepiped which are farther away from
        # the cuboid as the maximal size of the unit cell along given direction
        abc = np.dot(nmo, self.latvecs)
        buffer = np.max(np.abs(self.latvecs), axis=0)
        cond1 = np.all(abc < cuboid[0] - buffer, axis=1)
        cond2 = np.all(abc > cuboid[1] + buffer, axis=1)
        inside = np.logical_not(np.logical_or(cond1, cond2))
        return np.dot(nmo[inside], self.latvecs)
コード例 #3
0
    def fromdict(cls, geometry, inidict):
        """Builds instance from dictionary."""

        period_type = inidict.get("period_type", "0D")
        if period_type not in ["0D", "1D", "2D", "3D"]:
            error("Invalid periodicty type '" + period_type + "'")

        # 0D periodicity
        if period_type == "0D":
            return cls(geometry, "0D")

        # 1D periodicity
        if period_type == "1D":
            axis = inidict.get("axis", None)
            if axis is None:
                error("Missing axis specification for 1D periodicity.")
            try:
                axis = np.array([int(s) for s in axis.split()])
                axis.shape = (1, 3)
            except ValueError:
                error("Invalid axis specification.")
            if np.all(axis == 0):
                error("Invalid axis direction.")

        # 2D periodicity
        elif period_type == "2D":
            axis = inidict.get("axis", None)
            miller = inidict.get("miller_indices", None)
            if axis is None and miller is None:
                error("Either 'axis' or 'miller_indices' needed for "
                      "periodicity specification.")
            elif axis is not None and miller is not None:
                error(
                    "Only one of the keywords 'axis' or 'miller_indices' can "
                    "be used for periodicity specification.")
            if miller:
                try:
                    miller = np.array([int(s) for s in miller.split()])
                    miller.shape = (3, )
                except ValueError:
                    error("Invalid miller index for 2D periodicity")
                if np.all(miller == 0):
                    error("Invalid miller index for 2D periodicity")
                axis = plane_axis_from_miller(miller)
            else:
                try:
                    axis = np.array([int(s) for s in axis.split()])
                    axis.shape = (2, 3)
                except ValueError:
                    error("Invalid axis specification.")
                if np.all(axis == 0):
                    error("Invalid axis direction.")
                if np.all(np.cross(axis[0], axis[1]) == 0):
                    error("Axis are parallel.")

        # 3D periodicity
        else:
            axis = inidict.get("axis", None)
            superlattice = inidict.get("superlattice", None)
            if axis is None and superlattice is None:
                error("Either 'axis' or 'superlattice' needed for "
                      "periodicity specification.")
            elif axis is not None and superlattice is not None:
                error("Only one of the keywords 'axis' or 'superlattice'"
                      "can be used for periodicity specification.")
            if superlattice:
                try:
                    superlattice = np.array(
                        [float(s) for s in superlattice.split()])
                    superlattice.shape = (3, 3)
                except ValueError:
                    error("Invalid superlattice specification")
                if np.abs(np.linalg.det(superlattice)) < nc.EPSILON:
                    error("Linearly dependent superlattice vectors")
                axis = cell_axis_from_superlattice(
                    superlattice,
                    np.dot(geometry.bravais_cell, geometry.latvecs))
            else:
                try:
                    axis = np.array([int(s) for s in axis.split()])
                    axis.shape = (3, 3)
                except ValueError:
                    error("Invalid axis specification.")
                if np.all(axis == 0):
                    error("Invalid axis direction.")
                if np.abs(np.linalg.det(axis)) < nc.EPSILON:
                    error("Linearly dependent axis")

        # Switch back to primitive lattice, if necessary
        if np.any(geometry.bravais_cell != np.eye(3, dtype=int)):
            printstatus("Axis with respect to Bravais lattice:")
            for vec in axis:
                printstatus(
                    "{:3d} {:3d} {:3d}".format(*[int(ss) for ss in vec]),
                    indentlevel=1)
            axis = np.dot(axis, geometry.bravais_cell)

        # Get smallest possible unit cell
        for ii in range(len(axis)):
            divisor = gcd(abs(axis[ii]))
            axis[ii] = axis[ii] // divisor

        printstatus("Axis with respect to primitive lattice:")
        for vec in axis:
            printstatus("{:3d} {:3d} {:3d}".format(*[int(ss) for ss in vec]),
                        indentlevel=1)

        # Repeat unit cell
        cellrep = inidict.get("axis_repetition", None)
        if cellrep:
            try:
                cellrep = np.array([float(s) for s in cellrep.split()])
                cellrep.shape = (int(period_type[0]), )
            except ValueError:
                error("Invalid axis repetition specification.")
            axis = np.array(axis * cellrep[:, np.newaxis], int)
            printstatus("Axis repetition:" +
                        " ".join(["{:3d}".format(int(s)) for s in cellrep]))

        return cls(geometry, period_type, axis)
コード例 #4
0
    def fromdict(cls, geometry, inidict):
        """Builds instance from dictionary."""

        period_type = inidict.get("period_type", "0D")
        if period_type not in [ "0D", "1D", "2D", "3D"]:
            error("Invalid periodicty type '" + period_type + "'")
        
        # 0D periodicity
        if period_type == "0D":
            return cls(geometry, "0D")

        # 1D periodicity        
        if period_type == "1D":
            axis = inidict.get("axis", None)
            if axis is None:
                error("Missing axis specification for 1D periodicity.")
            try:
                axis = np.array([ int(s) for s in axis.split() ])
                axis.shape = (1, 3)
            except ValueError:
                error("Invalid axis specification.")
            if np.all(axis == 0):
                error("Invalid axis direction.")
        
        # 2D periodicity
        elif period_type == "2D":
            axis = inidict.get("axis", None)
            miller = inidict.get("miller_indices", None)
            if axis is None and miller is None:
                error("Either 'axis' or 'miller_indices' needed for "
                      "periodicity specification.")
            elif axis is not None and miller is not None:
                error("Only one of the keywords 'axis' or 'miller_indices' can "
                      "be used for periodicity specification.")
            if miller:
                try:
                    miller = np.array([ int(s) for s in miller.split() ])
                    miller.shape = (3, )
                except ValueError:
                    error("Invalid miller index for 2D periodicity")
                if np.all(miller == 0):
                    error("Invalid miller index for 2D periodicity")
                axis = plane_axis_from_miller(miller)                 
            else:
                try:
                    axis = np.array([ int(s) for s in axis.split() ])
                    axis.shape = (2, 3)
                except ValueError:
                    error("Invalid axis specification.")
                if np.all(axis == 0):
                    error("Invalid axis direction.")
                if np.all(np.cross(axis[0], axis[1]) == 0):
                    error("Axis are parallel.")

        # 3D periodicity                
        else:
            axis = inidict.get("axis", None)
            superlattice = inidict.get("superlattice", None)
            if axis is None and superlattice is None:
                error("Either 'axis' or 'superlattice' needed for "
                      "periodicity specification.")
            elif axis is not None and superlattice is not None:
                error("Only one of the keywords 'axis' or 'superlattice'"
                      "can be used for periodicity specification.")                
            if superlattice:
                try:
                    superlattice = np.array([ float(s) 
                                             for s in superlattice.split() ])
                    superlattice.shape = (3, 3)
                except ValueError:
                    error("Invalid superlattice specification")
                if np.abs(np.linalg.det(superlattice)) < nc.EPSILON:
                    error("Linearly dependent superlattice vectors")
                axis = cell_axis_from_superlattice(superlattice,
                    np.dot(geometry.bravais_cell, geometry.latvecs))
            else: 
                try:
                    axis = np.array([ int(s) for s in axis.split() ])
                    axis.shape = (3, 3)
                except ValueError:
                    error("Invalid axis specification.")
                if np.all(axis == 0):
                    error("Invalid axis direction.")
                if np.abs(np.linalg.det(axis)) < nc.EPSILON:
                    error("Linearly dependent axis")

        # Switch back to primitive lattice, if necessary                    
        if np.any(geometry.bravais_cell != np.eye(3, dtype=int)):
            printstatus("Axis with respect to Bravais lattice:")
            for vec in axis:
                printstatus("{:3d} {:3d} {:3d}".format(
                    *[ int(ss) for ss in vec ]), indentlevel=1)
            axis = np.dot(axis, geometry.bravais_cell)
            
        # Get smallest possible unit cell
        for ii in range(len(axis)):
            divisor = gcd(abs(axis[ii]))
            axis[ii] /= divisor
                    
        printstatus("Axis with respect to primitive lattice:")
        for vec in axis:
            printstatus("{:3d} {:3d} {:3d}".format(
                *[ int(ss) for ss in vec ]), indentlevel=1)
                
        # Repeat unit cell
        cellrep = inidict.get("axis_repetition", None)
        if cellrep:
            try:
                cellrep = np.array([ float(s) for s in cellrep.split() ])
                cellrep.shape = (int(period_type[0]), )
            except ValueError:
                error("Invalid axis repetition specification.")
            axis *= cellrep[:,np.newaxis]
            printstatus("Axis repetition:"
                + " ".join([ "{:3d}".format(int(s)) for s in cellrep ]))

        return cls(geometry, period_type, axis)