Source code for pyprocar.fermisurface3d.brillouin_zone

import numpy as np
from scipy.spatial import Voronoi
from ..core import Surface
import pyvista as pv
import trimesh

__author__ = "Pedram Tavadze"
__maintainer__ = "Pedram Tavadze"
__email__ = "petavazohi@mail.wvu.edu"
__date__ = "March 31, 2020"


[docs]class Lines: def __init__(self, verts=None, faces=None): self.verts = verts self.faces = faces self.pyvista_line = pv.PolyData() self.trimesh_line = None self.connectivity = [] self._get_connectivity() @property def nface(self): return len(self.faces) def _get_connectivity(self): for iface in range(self.nface): self.connectivity.append( [self.faces[iface][0], self.faces[iface][-1]]) # to connect the 1st and last point for ipoint in range(len(self.faces[iface]) - 1): point_1 = self.faces[ipoint] point_2 = self.faces[ipoint + 1] self.connectivity.append([point_1, point_2]) def _create_pyvista(self): cell = [] for iline in self.connectivity: cell.append([2, iline[0], iline[1]]) self.pyvista_line.lines = cell def _create_trimesh(self): entries = [] for iline in self.connectivity: entries.append(trimesh.path.entries.Line(iline)) self.trimesh_line = trimesh.path.path.Path(entries=entries, vertices=self.verts)
[docs]class BrillouinZone(Surface): """ A Surface object with verts, faces and line representation, representing the BrillouinZone """ def __init__(self, reciprocal_lattice, supercell): """ Parameters ---------- reciprocal_lattice : (3,3) float Reciprocal Lattice """ self.reciprocal = reciprocal_lattice * max(supercell) # for ix in range(3): # self.reciprocal[:,ix]*=supercell[ix] verts, faces = self.wigner_seitz() Surface.__init__(self, verts=verts, faces=faces) self._fix_normals_direction() #self.pyvista_obj.face_normals*=-1 # self.pyvista_obj['scalars'] = [0]*len(faces) # self.pyvista_obj.set_active_scalars('scalars') self.lines = Lines(verts, faces)
[docs] def wigner_seitz(self): """ Returns ------- TYPE Using the Wigner-Seitz Method, this function finds the 1st Brillouin Zone in terms of vertices and faces """ kpoints = [] for i in range(-1, 2): for j in range(-1, 2): for k in range(-1, 2): vec = i * self.reciprocal[0] + j * \ self.reciprocal[1] + k * self.reciprocal[2] kpoints.append(vec) brill = Voronoi(np.array(kpoints)) faces = [] for idict in brill.ridge_dict: if idict[0] == 13 or idict[1] == 13: faces.append(brill.ridge_dict[idict]) verts = brill.vertices return np.array(verts), np.array(faces)
def _fix_normals_direction(self): # directions = np.zeros_like(self.centers) for iface in range(self.nfaces): center = self.centers[iface] n1 = center / np.linalg.norm(center) n2 = self.face_normals[iface] correction = np.sign(np.dot(n1, n2)) self.face_normals[iface] = self.face_normals[iface] * correction self.pyvista_obj.face_normals[ iface] = self.pyvista_obj.face_normals[iface] * correction
# self.trimesh_obj.face_normals[iface]*=correction