def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) with open(os.path.join(module_dir, "surface_samples.json")) as data_file: surface_properties = json.load(data_file) surface_energies, miller_indices = {}, {} for mpid in surface_properties.keys(): e_surf_list, miller_list = [], [] for surface in surface_properties[mpid]["surfaces"]: e_surf_list.append(surface["surface_energy"]) miller_list.append(surface["miller_index"]) surface_energies[mpid] = e_surf_list miller_indices[mpid] = miller_list # In the case of a high anisotropy material # Nb: mp-8636 latt_Nb = Lattice.cubic(2.992) # In the case of an fcc material # Ir: mp-101 latt_Ir = Lattice.cubic(3.8312) # In the case of a hcp material # Ti: mp-72 latt_Ti = Lattice.hexagonal(4.6000, 2.8200) self.ucell_Nb = Structure( latt_Nb, ["Nb", "Nb", "Nb", "Nb"], [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], ) self.wulff_Nb = WulffShape( latt_Nb, miller_indices["mp-8636"], surface_energies["mp-8636"] ) self.ucell_Ir = Structure( latt_Nb, ["Ir", "Ir", "Ir", "Ir"], [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], ) self.wulff_Ir = WulffShape( latt_Ir, miller_indices["mp-101"], surface_energies["mp-101"] ) self.ucell_Ti = Structure( latt_Ti, ["Ti", "Ti", "Ti"], [[0, 0, 0], [0.333333, 0.666667, 0.5], [0.666667, 0.333333, 0.5]], ) self.wulff_Ti = WulffShape( latt_Ti, miller_indices["mp-72"], surface_energies["mp-72"] ) self.cube = WulffShape(Lattice.cubic(1), [(1, 0, 0)], [1]) self.hex_prism = WulffShape( Lattice.hexagonal(2.63, 5.21), [(0, 0, 1), (1, 0, 0)], [0.35, 0.53] ) self.surface_properties = surface_properties
def get_wulff_shape(self, material_id): """ Constructs a Wulff shape for a material. Args: material_id (str): Materials Project material_id, e.g. 'mp-123'. Returns: pymatgen.analysis.wulff.WulffShape """ from pymatgen.analysis.wulff import WulffShape from pymatgen.symmetry.analyzer import SpacegroupAnalyzer structure = self.get_structure_by_material_id(material_id) surfaces = self.get_surface_data(material_id)["surfaces"] lattice = ( SpacegroupAnalyzer(structure).get_conventional_standard_structure().lattice ) miller_energy_map = {} for surf in surfaces: miller = tuple(surf["miller_index"]) # Prefer reconstructed surfaces, which have lower surface energies. if (miller not in miller_energy_map) or surf["is_reconstructed"]: miller_energy_map[miller] = surf["surface_energy"] millers, energies = zip(*miller_energy_map.items()) return WulffShape(lattice, millers, energies)
def wulff_shape_from_chempot(self, chempot, symprec=1e-5): """ Method to get the Wulff shape at a specific chemical potential. Args: chempot (float): The chemical potential the Wulff Shape exist in. """ # Check if the user provided chemical potential is within the # predetermine range of chemical potential. If not, raise a warning if not max(self.chempot_range) >= chempot >= min(self.chempot_range): warnings.warn("The provided chemical potential is outside the range " "of chemical potential (%s to %s). The resulting Wulff " "shape might not be reasonable." %(min(self.chempot_range), max(self.chempot_range))) latt = SpacegroupAnalyzer(self.ucell_entry.structure).\ get_conventional_standard_structure().lattice miller_list = self.vasprun_dict.keys() e_surf_list = [] for hkl in miller_list: # At each possible configuration, we calculate surface energy as a # function of u and take the lowest surface energy (corresponds to # the most stable slab termination at that particular u) surf_e_range_list = [self.calculate_gamma(vasprun) for vasprun in self.vasprun_dict[hkl]] e_list = [] for e_range in surf_e_range_list: slope, intercept = self.get_slope_and_intercept(e_range) e_list.append(slope * chempot + intercept) e_surf_list.append(min(e_list)) return WulffShape(latt, miller_list, e_surf_list, symprec=symprec)
def wulff(st, miller_list=None, e_surf_list=None, show=0): from pymatgen.core.structure import Structure stpm = st.convert2pymatgen() lat = stpm.lattice recp_lattice = stpm.lattice.reciprocal_lattice_crystallographic recp = Structure(recp_lattice, ["H"], [[0, 0, 0]]) dire = Structure(stpm.lattice, ["H"], [[0, 0, 0]]) print(dire.get_space_group_info()) print(recp.get_space_group_info()) # print(lat) from pymatgen.analysis.wulff import WulffShape WS = WulffShape(lat, miller_list, e_surf_list) # print(dir(WS)) anisotropy = WS.anisotropy weighted_surface_energy = WS.weighted_surface_energy if show: WS.show() return anisotropy, weighted_surface_energy
def Wullff(self, formate, surface_energy, pic_name, directions=(3, 4, 4), x=0.47, y=-16): from pymatgen.core.surface import SlabGenerator, generate_all_slabs, Structure, Lattice # Import the neccesary tools for making a Wulff shape from pymatgen.analysis.wulff import WulffShape from pymatgen.ext.matproj import MPRester from pymatgen.io.cif import CifParser import matplotlib.pyplot as plt import matplotlib.image as mpimg import pandas as pd import os if 'cif' in str(formate): os.chdir(r"D:\Desktop\VASP practical\Cif library") print(os.getcwd()) structure = CifParser(str(pic_name) + '.cif') struct = structure.get_structures()[0] else: mpr = MPRester() mp_id = formate struct = mpr.get_structure_by_material_id(mp_id) surface_energies = surface_energy miller_list = surface_energies.keys() e_surf_list = surface_energies.values() font2 = { 'family': 'Times New Roman', 'fontsize': '40', 'weight': 'bold', } wulffshape = WulffShape(struct.lattice, miller_list, e_surf_list) print(wulffshape.area_fraction_dict) os.chdir(self.dire) dict1 = wulffshape.area_fraction_dict xx = [] yy = [] for key, value in dict1.items(): xx.append(key) yy.append(value) cc = wulffshape.effective_radius bb = wulffshape.volume dd = wulffshape.shape_factor print(wulffshape.effective_radius) res = pd.DataFrame({'Slab': xx, 'area': yy}) #构造原始数据文件 df = res.sort_values(by='area', ascending=True) with open(str(pic_name) + '.txt', 'w') as f: f.write('effective radius:' + str(cc) + ' ' + "volume:" + str(bb) + ' ' + "shape factor:" + str(dd)) print(cc) # os.chdir(r"D:\Desktop\VASP practical\workdir") df.to_excel(str(pic_name) + ".xlsx") #生成Excel文件,并存到指定文件路径下 wulffshape.get_plot(bar_on=True, aspect_ratio=(8, 8), bar_pos=[0, 0.85, 1.1, 0.045], direction=directions) plt.title(str(pic_name), font2, x=x, y=y) plt.savefig(str(pic_name) + ".png", bbox_inches='tight', transparent=True, dpi=600, format='png') plt.show os.chdir(r"D:\Desktop\VASP practical\workdir") print('finished')
(2, 1, 0): 2.3969, (3, 3, 2): 2.0944, (1, 0, 0): 2.2084, (2, 1, 1): 2.2353, (3, 2, 2): 2.1242, (3, 2, 1): 2.3183, (2, 2, 1): 2.1732, (3, 3, 1): 2.2288, (3, 1, 1): 2.3039, (1, 1, 1): 1.9235 } miller_list = surface_energies_Ni.keys() e_surf_list = surface_energies_Ni.values() # We can now construct a Wulff shape with an accuracy up to a max Miller index of 3 wulffshape = WulffShape(Ni.lattice, miller_list, e_surf_list) # Let's get some useful information from our wulffshape object print("shape factor: %.3f, anisotropy: \ %.3f, weighted surface energy: %.3f J/m^2" % (wulffshape.shape_factor, wulffshape.anisotropy, wulffshape.weighted_surface_energy)) # If we want to see what our Wulff shape looks like wulffshape.show() # Lets try something a little more complicated, say LiFePO4 from pymatgen.util.testing import PymatgenTest # Get the LiFePO4 structure LiFePO4 = PymatgenTest.get_structure("LiFePO4") # Let's add some oxidation states to LiFePO4, this will be
# all_slabs = slabgen.get_slabs() # print("The Ni(111) slab only has %s termination." %(len(all_slabs))) # Now let's assume that we then calculated the surface energies for these slabs # Surface energy values in J/m^2 surface_energies_Ni = { (0, 0, 1): 2.3869, (2, 0, 1): 2.2862, (1, -1, 0): 2.3964, (0, 2, 0): 2.0944, (-2, -2, 1): 0.9353, (2, -2, 0): 2.3183, (-1, 1, 1): 2.2288, (0, 2, 2): 1.9235 } miller_list = surface_energies_Ni.keys() e_surf_list = surface_energies_Ni.values() # We can now construct a Wulff shape with an accuracy up to a max Miller index of 3 wulffshape = WulffShape(struct.lattice, miller_list, e_surf_list) # Let's get some useful information from our wulffshape object # print("shape factor: %.3f, anisotropy: \ # %.3f, weighted surface energy: %.3f J/m^2" %(wulffshape.shape_factor, # wulffshape.anisotropy, # wulffshape.weighted_surface_energy)) # If we want to see what our Wulff shape looks like wulffshape.show()