Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
    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