コード例 #1
0
    def symm_check(self, ucell, wulff_vertices):
        """
        # Checks if the point group of the Wulff shape matches
        # the point group of its conventional unit cell

        Args:
            ucell (string): Unit cell that the Wulff shape is based on.
            wulff_vertices (list): List of all vertices on the Wulff
                shape. Use wulff.wulff_pt_list to obtain the list
                (see wulff_generator.py).

        return (bool)
        """

        space_group_analyzer = SpacegroupAnalyzer(ucell)
        symm_ops = space_group_analyzer.get_point_group_operations(
            cartesian=True)
        for point in wulff_vertices:
            for op in symm_ops:
                symm_point = op.operate(point)
                if in_coord_list(wulff_vertices, symm_point):
                    continue
                else:
                    return False
        return True
コード例 #2
0
    def symmetrize(self, structure):
        tensor = self._reduced_tensor

        if self._is_real_space:
            real_lattice = self._lattice
        else:
            real_lattice = self._lattice.reciprocal_lattice

        # I guess this is the reason why tensor.symmetrize (omega) is so slow!
        from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
        real_finder = SpacegroupAnalyzer(structure)

        real_symmops = real_finder.get_point_group_operations(cartesian=True)

        cartesian_tensor = self.cartesian_tensor

        sym_tensor = np.zeros((3, 3))

        my_tensor = cartesian_tensor

        for real_sym in real_symmops:
            mat = real_sym.rotation_matrix
            prod_sym = np.dot(np.transpose(mat), np.dot(cartesian_tensor, mat))
            sym_tensor = sym_tensor + prod_sym

        sym_tensor = sym_tensor / len(real_symmops)

        self._reduced_tensor = _from_cart_to_red(sym_tensor, self._lattice)
コード例 #3
0
    def get_sym_eq_kpoints(self, kpoint, cartesian=False, tol=1e-2):
        """
        Returns a list of unique symmetrically equivalent k-points.

        Args:
            kpoint (1x3 array): coordinate of the k-point
            cartesian (bool): kpoint is in cartesian or fractional coordinates
            tol (float): tolerance below which coordinates are considered equal

        Returns:
            ([1x3 array] or None): if structure is not available returns None
        """
        if not self.structure:
            return None
        sg = SpacegroupAnalyzer(self.structure)
        symmops = sg.get_point_group_operations(cartesian=cartesian)
        points = np.dot(kpoint, [m.rotation_matrix for m in symmops])
        rm_list = []
        # identify and remove duplicates from the list of equivalent k-points:
        for i in range(len(points) - 1):
            for j in range(i + 1, len(points)):
                if np.allclose(pbc_diff(points[i], points[j]), [0, 0, 0], tol):
                    rm_list.append(i)
                    break
        return np.delete(points, rm_list, axis=0)
コード例 #4
0
ファイル: test_wulff.py プロジェクト: adozier/pymatgen
    def symm_check(self, ucell, wulff_vertices):
        """
        # Checks if the point group of the Wulff shape matches
        # the point group of its conventional unit cell

        Args:
            ucell (string): Unit cell that the Wulff shape is based on.
            wulff_vertices (list): List of all vertices on the Wulff
                shape. Use wulff.wulff_pt_list to obtain the list
                (see wulff_generator.py).

        return (bool)
        """

        space_group_analyzer = SpacegroupAnalyzer(ucell)
        symm_ops = space_group_analyzer.get_point_group_operations(
            cartesian=True)
        for point in wulff_vertices:
            for op in symm_ops:
                symm_point = op.operate(point)
                if in_coord_list(wulff_vertices, symm_point):
                    continue
                else:
                    return False
        return True
コード例 #5
0
ファイル: tensor.py プロジェクト: gpetretto/abipy
    def symmetrize(self, structure):
        tensor = self._reduced_tensor

        if self._is_real_space:
            real_lattice = self._lattice
        else:
            real_lattice = self._lattice.reciprocal_lattice

        # I guess this is the reason why tensor.symmetrize (omega) is so slow!
        real_finder = SpacegroupAnalyzer(structure)

        real_symmops = real_finder.get_point_group_operations(cartesian=True)

        cartesian_tensor = self.cartesian_tensor

        sym_tensor = np.zeros((3,3))

        my_tensor = cartesian_tensor

        for real_sym in real_symmops:
            mat = real_sym.rotation_matrix
            prod_sym = np.dot(np.transpose(mat),np.dot(cartesian_tensor,mat))
            sym_tensor = sym_tensor + prod_sym

        sym_tensor = sym_tensor/len(real_symmops)

        self._reduced_tensor = from_cart_to_red(sym_tensor,self._lattice)
コード例 #6
0
    def get_sym_eq_kpoints(self, kpoint, cartesian=False, tol=1e-2):
        """
        Returns a list of unique symmetrically equivalent k-points.

        Args:
            kpoint (1x3 array): coordinate of the k-point
            cartesian (bool): kpoint is in cartesian or fractional coordinates
            tol (float): tolerance below which coordinates are considered equal

        Returns:
            ([1x3 array] or None): if structure is not available returns None
        """
        if not self.structure:
            return None
        sg = SpacegroupAnalyzer(self.structure)
        symmops = sg.get_point_group_operations(cartesian=cartesian)
        points = np.dot(kpoint, [m.rotation_matrix for m in symmops])
        rm_list = []
        # identify and remove duplicates from the list of equivalent k-points:
        for i in range(len(points) - 1):
            for j in range(i + 1, len(points)):
                if np.allclose(pbc_diff(points[i], points[j]), [0, 0, 0], tol):
                    rm_list.append(i)
                    break
        return np.delete(points, rm_list, axis=0)
コード例 #7
0
    def reconstruct_bz_kpoints(self):
        """
        Reconstruct all the kpoints in the 1st Brillouin zone from the
        irreducible points chosen by VASP.

        :return:
        """
        neighbors = set_up_neighbors(self._out.lattice)

        kpts_bz = []

        for k in self.kpoints:
            kpts_bz.append(return_to_brillouin(k, self._out.lattice,
                                               neighbors=neighbors,
                                               cartesian=False))

        all_kpts = np.array(kpts_bz[0])
        all_lu_energies = np.array([self.lu_energies[0], ])
        all_ho_energies = np.array([self.ho_energies[0], ])

        sg = SpacegroupAnalyzer(self._out.structures[-1])
        symmops = sg.get_point_group_operations(cartesian=False)

        # Reconstruct all the kpoints with the corresponding energies
        for k, lu_energy, ho_energy in zip(kpts_bz[1:], self.lu_energies[1:],
                                           self.ho_energies[1:]):

            # Get all symmetry equivalent kpoints of the kpoint in the IBZ
            sym_kpoints = np.dot(k, [m.rotation_matrix for m in symmops])

            add_list = [sym_kpoints[0], ]

            for point in list(sym_kpoints[1:]):

                if not any(np.linalg.norm(x - point) < 1e-6 for x in
                           add_list):
                    add_list.append(point)

            # Add the list of kpoints to the total array
            all_kpts = np.vstack([all_kpts, add_list])

            # Also add the energy value of the corresponding kpoint #sympoints
            # times
            all_lu_energies = np.vstack(
                [all_lu_energies, np.ones([len(add_list), 1]) * lu_energy]
            )
            all_ho_energies = np.vstack(
                [all_ho_energies, np.ones([len(add_list), 1]) * ho_energy]
            )

        self._all_kpoints = all_kpts
        self._all_lu_energies = all_lu_energies
        self._all_ho_energies = all_ho_energies
コード例 #8
0
def get_sym_eq_kpoints(struct, kpoint, cartesian=False, tol=1e-2):
    if not struct:
        return None

    sg = SpacegroupAnalyzer(struct)
    symmops = sg.get_point_group_operations(cartesian=cartesian)
    points = np.dot(kpoint, [m.rotation_matrix for m in symmops])
    rm_list = []
    # identify and remove duplicates from the list of equivalent k-points:
    for i in range(len(points) - 1):
        for j in range(i + 1, len(points)):
            if np.allclose(pbc_diff(points[i], points[j]), [0, 0, 0], tol):
                rm_list.append(i)
                break
    return np.delete(points, rm_list, axis=0)
コード例 #9
0
	def enumerate_ads_config(self, adsorbate, loading, site='all', symmetry_tol=0.01):
		
		vor, mesh = self.Voronoi_tessalate()
		vcoords = vor.vertices
		base_coords = [a.position for a in self.bulk_ase]
		repeat_unit_cell = self.bulk_ase.get_cell().T
		inv_ruc = np.linalg.inv(repeat_unit_cell)

		corrected_vcoords = []
		used = []
		for coord in vcoords:
			if np.linalg.norm(coord) < 1e3:
				fcoord = np.dot(inv_ruc, coord)
				zero_threshold_indices = abs(fcoord) < 1e-6
				fcoord[zero_threshold_indices] = 0.0
				one_threshold_indices = abs(fcoord - 1.0) < 1e-6
				fcoord[one_threshold_indices] = 0.0
				
				advance = True
				for u in used:
					if np.allclose(fcoord, u):
						advance = False
						break
				
				if advance:
					corrected_vcoords.append(np.dot(repeat_unit_cell, fcoord))
					used.append(fcoord)

		vtypes = []
		for vert in corrected_vcoords:
			used = []
			spectrum = []
			for atom_coord in base_coords:
				fvert = np.dot(inv_ruc, vert)
				fatom_coord = np.dot(inv_ruc, atom_coord)
				fdist_vec, sym = PBC3DF_sym(fvert, fatom_coord)
				dist = np.linalg.norm(np.dot(repeat_unit_cell, fdist_vec))
				sym_atom_coord = np.dot(repeat_unit_cell, fatom_coord - sym)
				spectrum.append((dist,sym_atom_coord))

			spectrum.sort(key = lambda x: x[0])
			min_dist = spectrum[0][0]
			spectrum = [s[1] for s in spectrum if s[0] - min_dist < symmetry_tol] + [vert]

			spectrum_atoms = Atoms()
			for s in spectrum:
				spectrum_atoms.append(Atom('H', s))

			spectrum_atoms.set_cell(repeat_unit_cell.T)
			spectrum_struct = AseAtomsAdaptor.get_structure(spectrum_atoms)
			sga = SpacegroupAnalyzer(spectrum_struct, symprec=symmetry_tol)
			pgs = sga.get_point_group_symbol()
			symmetry_order = len(sga.get_point_group_operations())

			try:
				symmetry_type = symmetry_order_dict[symmetry_order]
			except KeyError:
				symmetry_type = 'unknown' + str(symmetry_order)

			vtypes.append((symmetry_type, vert))

		if site in ('all', 'single_site'):
			max_loading = float(len(vtypes))
		else:
			max_loading = float(len([ty for ty in vtypes if ty[0] == site]))

		all_combinations = [s for s in all_subsets(vtypes) if len(s) > 0]

		if isfloat(loading):

			fractional_loadings = [abs(len(s)/max_loading - loading) for s in all_combinations]
			closest = min(set(fractional_loadings))
			all_combinations = [all_combinations[i] for i in range(len(all_combinations)) if fractional_loadings[i] == closest]

		if site == 'single_site':
			site_dict = dict((k,[]) for k in set(ty[0] for ty in vtypes))
			for entry in vtypes:
				ty, coord = entry
				site_dict[ty].append(coord)
		elif site == 'all':
			site_dict = {'all':[]}
			for entry in vtypes:
				site_dict['all'].append(entry)
		else:
			site_dict = {site:[]}
			for entry in vtypes:
				ty, coord = entry
				if ty == site:
					site_dict[ty].append(coord)

		ads_dict = {}
		atype_counter = 0

		fingerprints = dict((len(s), dict((k,[]) for k in range(1,231))) for s in all_combinations)
		sg_counts    = dict((k,0) for k in range(1,231))		

		for subset in all_combinations:

			types  = [s[0] for s in subset]
			type_string = ''
			for ty in set(types):
				type_string += ty + '_'

			if len(set(types)) > 1 and site == 'single_site':
				continue
			elif site not in ('all', 'single_site'):
				if len(set(types)) > 1:
					continue
				else:
					if list(set(types))[0] != site:
						continue

			coords = [s[1] for s in subset]
			ld = len(subset)
			fp_dict = fingerprints[ld]

			fractional_loading = ld/max_loading
			adsorbate_combinations = itertools.product(adsorbate, repeat=ld)

			for ads_comb in adsorbate_combinations:

				adsonly_positions = []
				bulk_coords = [(sl.symbol, sl.position) for sl in self.bulk_ase]

				for s,a in zip(subset, ads_comb):

					ads, shift_ind = a
					ty, site_coord = s

					elems = []
					positions = []
					for atom in ads:
						elems.append(atom.symbol)
						positions.append(atom.position)
					elems = np.asarray(elems)
					positions = np.asarray(positions)
					positions -= positions[shift_ind]
					positions += site_coord

					for e,c in zip(elems, positions):
						bulk_coords.append((e, c))
						adsonly_positions.append(c)

				advance, index, sgs, sgn, dists, atoms, formula = redundancy_check(bulk_coords, adsonly_positions, fp_dict, repeat_unit_cell, symmetry_tol)

				if advance:
					sg_counts[sgn] += 1
					fp_dict[sgn].append(dists)

				ads_dict[formula + '_' + str(int(fractional_loading * 1000)) + '_' + type_string + str(sgn) + '_' + index] = atoms

		self.adsorbate_configuration_dict = ads_dict
コード例 #10
0
    def __init__(
        self,
        uuid,
        structure,  # pristine unit cell
        sc_size="1 1 1",
        signicant_figures=4,
        muon_threshold=1e-2,
        if_pristine=False,
        if_with_distortions=True
        #         reduced_sites = False,
        #         reduced_distance = 10.0
    ):
        """
        
        Parameters
        -----------
        uuid : int
            The PK for relax structure              
        structure : Structure object
            Pymatgen Structure Object                   
        sc_size : str
            Supercell size in a, b and c direction eg "3 3 3"
        signicant_figures : int
            Round positios to significant figures. Default=4
        muon_threshold : float
            Absolute threshold for checking distance.      
        if_pristine : bool
            If True, to generate symmetry pristine structure for muon equivalent sites. 
            Default=False
        if_with_distortions : bool
            If True, to generate structure with distortions for each muon equivalent sites.
            Default=True
            
        Returns
        -------
        """
        #
        """
#         reduced_sites: Bool
#             If True, (planning for something). 
#             Default=False
#         reduced_distance : float
#             planning for something        
        """
        #

        self.relax_uuid = uuid
        self.structure = structure
        self.sc_size = sc_size
        self.signicant_figures = signicant_figures
        self.muon_threshold = muon_threshold
        self.if_pristine = if_pristine
        self.if_with_distortions = if_with_distortions

        # This parameters for future
        #         self.reduced_sites = reduced_sites
        #         self.reduced_distance = reduced_distance

        if sc_size is None or sc_size == "":
            self.sc_size = "1 1 1"
        else:
            self.sc_size = sc_size

        self.pristine_structure_supercell = self.structure.copy()
        self.pristine_structure_supercell.make_supercell(
            [int(x) for x in self.sc_size.split()])

        # Check if pritine structure is compatible to supercell size
        if len(self.pristine_structure_supercell) != self.n_atoms - 1:
            raise SiteDistortions('Invalid inputs Structure or supercell size')

        SA = SpacegroupAnalyzer(self.pristine_structure_supercell,
                                symprec=self.muon_threshold)
        self._SA = SA

        self._SG = SA.get_space_group_operations()
        self._PG = SA.get_point_group_operations()
        self._SGO = SpacegroupOperations(
            SA.get_space_group_number(), SA.get_space_group_symbol(),
            SA.get_symmetry_operations(cartesian=False))
コード例 #11
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