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)
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)
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)
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)