def _get_all_miller_e(self): """ from self: get miller_list(unique_miller), e_surf_list and symmetry operations(symmops) according to lattice apply symmops to get all the miller index, then get normal, get all the facets functions for wulff shape calculation: |normal| = 1, e_surf is plane's distance to (0, 0, 0), normal[0]x + normal[1]y + normal[2]z = e_surf return: [WulffFacet] """ all_hkl = [] color_ind = self.color_ind planes = [] recp = self.structure.lattice.reciprocal_lattice_crystallographic recp_symmops = get_recp_symmetry_operation(self.structure, self.symprec) for i, (hkl, energy) in enumerate(zip(self.hkl_list, self.e_surf_list)): for op in recp_symmops: miller = tuple([int(x) for x in op.operate(hkl)]) if miller not in all_hkl: all_hkl.append(miller) normal = recp.get_cartesian_coords(miller) normal /= sp.linalg.norm(normal) normal_pt = [x * energy for x in normal] dual_pt = [x / energy for x in normal] color_plane = color_ind[divmod(i, len(color_ind))[1]] planes.append( WulffFacet(normal, energy, normal_pt, dual_pt, color_plane, i, hkl)) # sort by e_surf planes.sort(key=lambda x: x.e_surf) return planes
def _get_all_miller_e(self): """ from self: get miller_list(unique_miller), e_surf_list and symmetry operations(symmops) according to lattice apply symmops to get all the miller index, then get normal, get all the facets functions for wulff shape calculation: |normal| = 1, e_surf is plane's distance to (0, 0, 0), normal[0]x + normal[1]y + normal[2]z = e_surf return: [WulffFacet] """ all_hkl = [] color_ind = self.color_ind planes = [] recp = self.structure.lattice.reciprocal_lattice_crystallographic recp_symmops = get_recp_symmetry_operation(self.structure, self.symprec) for i, (hkl, energy) in enumerate(zip(self.hkl_list, self.e_surf_list)): for op in recp_symmops: miller = tuple([int(x) for x in op.operate(hkl)]) if miller not in all_hkl: all_hkl.append(miller) normal = recp.get_cartesian_coords(miller) normal /= sp.linalg.norm(normal) normal_pt = [x * energy for x in normal] dual_pt = [x / energy for x in normal] color_plane = color_ind[divmod(i, len(color_ind))[1]] planes.append(WulffFacet(normal, energy, normal_pt, dual_pt, color_plane, i, hkl)) # sort by e_surf planes.sort(key=lambda x: x.e_surf) return planes
def __init__(self, lattice, miller_list, e_surf_list, color_set='PuBu', grid_off=True, axis_off=True, show_area=False, alpha=1, off_color='red', symprec=0.00001): """ Args: lattice: Lattice object of the conventional unit cell miller_list ([(hkl), ...]: list of hkl or hkil for hcp e_surf_list ([float]): list of corresponding surface energies color_set: default is 'PuBu' grid_off (bool): default is True axis_off (bool): default is Ture show_area (bool): default is False alpha (float): chosen from 0 to 1 (float), default is 1 off_color: color_legend for off_wulff planes on show_area legend symprec (float): for recp_operation, default is 0.01 """ latt = lattice.scale(1) structure = Structure(latt, ["H"], [[0, 0, 0]]) # 1. store input args: # store plot settings: self.alpha = alpha self.color_set = color_set self.color_ind = list(range(len(miller_list))) self.grid_off = grid_off self.axis_off = axis_off self.show_area = show_area self.off_color = off_color self.input_miller_fig = [hkl_tuple_to_str(x) for x in miller_list] # store input data self.structure = structure self.input_miller = [list(x) for x in miller_list] self.input_hkl = [[x[0], x[1], x[-1]] for x in miller_list] self.input_e_surf = list(e_surf_list) self.latt = latt self.recp = structure.lattice.reciprocal_lattice_crystallographic self.recp_symmops = get_recp_symmetry_operation(structure, symprec) sga = SpacegroupAnalyzer(structure, symprec) self.cart_symmops = sga.get_point_group_operations(cartesian=True) # 2. get all the data for wulff construction # get all the surface normal from get_all_miller_e() normal_e_m = self.get_all_miller_e() # [normal, e_surf, normal_pt, dual_pt, color_plane, m_ind_orig, miller] logger.debug(len(normal_e_m)) self.normal_e_m = normal_e_m # 3. consider the dual condition dual_pts = [x[3] for x in normal_e_m] dual_convex = ConvexHull(dual_pts) dual_cv_simp = dual_convex.simplices # simplices (ndarray of ints, shape (nfacet, ndim)) # list of [i, j, k] , ndim = 3 # i, j, k: ind for normal_e_m # recalculate the dual of dual, get the wulff shape. # conner <-> surface # get cross point from the simplices of the dual convex hull wulff_pt_list = [self.get_cross_pt_dual_simp(dual_simp) for dual_simp in dual_cv_simp] wulff_convex = ConvexHull(wulff_pt_list) wulff_cv_simp = wulff_convex.simplices logger.debug(", ".join([str(len(x)) for x in wulff_cv_simp])) # store simplices and convex self.dual_cv_simp = dual_cv_simp self.wulff_pt_list = wulff_pt_list self.wulff_cv_simp = wulff_cv_simp self.wulff_convex = wulff_convex # 4. get wulff info # return (simpx_info, plane_wulff_info, on_wulff, surface_area) wulff_info = self.get_simpx_plane() self.simpx_info = wulff_info[0] # need to update the color # plan_wulff_info: [normal, e_surf, pts, simpx, # color_plane, m_ind_orig, miller] self.plane_wulff_info = wulff_info[1] self.on_wulff = wulff_info[2] self.color_area = wulff_info[3] # 5. assign color for on_wulff plane # return (color_list, color_proxy, color_proxy_on_wulff, # miller_on_wulff, e_surf_on_wulff_list) color_info = self.get_colors() self.color_list = color_info[0] self.color_proxy = color_info[1] self.color_proxy_on_wulff = color_info[2] self.miller_on_wulff = color_info[3] self.e_surf_on_wulff = color_info[4] miller_area = [] for m, in_mill_fig in enumerate(self.input_miller_fig): miller_area.append( in_mill_fig + ' : ' + str(round(self.color_area[m], 4))) self.miller_area = miller_area