def test_get_mapping(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=False, allow_subset=True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7, .4, .5], [0, 0, 0.1], [0, 0, 0.2]]) s1.make_supercell([2, 1, 1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0, 0.1, -0.95], [0, 0.1, 0], [-.7, .5, .375]]) shuffle = [2, 0, 1, 3, 5, 4] s1 = Structure.from_sites([s1[i] for i in shuffle]) #test the mapping s2.make_supercell([2, 1, 1]) #equal sizes for i, x in enumerate(sm.get_mapping(s1, s2)): self.assertEqual(s1[x].species_and_occu, s2[i].species_and_occu) del s1[0] #s1 is subset of s2 for i, x in enumerate(sm.get_mapping(s2, s1)): self.assertEqual(s1[i].species_and_occu, s2[x].species_and_occu) #s2 is smaller than s1 del s2[0] del s2[1] self.assertRaises(ValueError, sm.get_mapping, s2, s1)
def test_get_mapping(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False, scale=True, attempt_supercell=False, allow_subset = True) l = Lattice.orthorhombic(1, 2, 3) s1 = Structure(l, ['Ag', 'Si', 'Si'], [[.7,.4,.5],[0,0,0.1],[0,0,0.2]]) s1.make_supercell([2,1,1]) s2 = Structure(l, ['Si', 'Si', 'Ag'], [[0,0.1,-0.95],[0,0.1,0],[-.7,.5,.375]]) shuffle = [2,0,1,3,5,4] s1 = Structure.from_sites([s1[i] for i in shuffle]) #test the mapping s2.make_supercell([2,1,1]) #equal sizes for i, x in enumerate(sm.get_mapping(s1, s2)): self.assertEqual(s1[x].species_and_occu, s2[i].species_and_occu) del s1[0] #s1 is subset of s2 for i, x in enumerate(sm.get_mapping(s2, s1)): self.assertEqual(s1[i].species_and_occu, s2[x].species_and_occu) #s2 is smaller than s1 del s2[0] del s2[1] self.assertRaises(ValueError, sm.get_mapping, s2, s1)
class observer_spinel(observer_base): def __init__(self, Asite_struct, Bspecie): super(observer_spinel, self).__init__() self.Asite_struct = Asite_struct self.Bspecie = Bspecie self.site_matcher = StructureMatcher( ltol=0.1, primitive_cell=False, allow_subset=True, comparator=FrameworkComparator(), ignored_species=["O"], ) def DOI(self, calc_state): asites = self.site_matcher.get_mapping(calc_state.config.structure, self.Asite_struct) # print asites # print spinel_config.structure # print spinel_config.Asite_struct x = 0 for i in asites: if calc_state.config.structure.species[i] == Element(self.Bspecie): x += 1 x /= float(len(asites)) return x def logfunc(self, calc_state): return calc_state.energy, self.DOI(calc_state)
def test_rms_vs_minimax(self): # This tests that structures with adjusted RMS less than stol, but minimax # greater than stol are treated properly sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=False) l = Lattice.orthorhombic(1, 2, 12) sp = ["Si", "Si", "Al"] s1 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.5]]) s2 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.6]]) self.assertArrayAlmostEqual(sm.get_rms_dist(s1, s2), (0.32 ** 0.5 / 2, 0.4)) self.assertEqual(sm.fit(s1, s2), False) self.assertEqual(sm.fit_anonymous(s1, s2), False) self.assertEqual(sm.get_mapping(s1, s2), None)
def test_rms_vs_minimax(self): # This tests that structures with adjusted RMS less than stol, but minimax # greater than stol are treated properly # stol=0.3 gives exactly an ftol of 0.1 on the c axis sm = StructureMatcher(ltol=0.2, stol=0.301, angle_tol=1, primitive_cell=False) l = Lattice.orthorhombic(1, 2, 12) sp = ["Si", "Si", "Al"] s1 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.5]]) s2 = Structure(l, sp, [[0.5, 0, 0], [0, 0, 0], [0, 0, 0.6]]) self.assertArrayAlmostEqual(sm.get_rms_dist(s1, s2), (0.32 ** 0.5 / 2, 0.4)) self.assertEqual(sm.fit(s1, s2), False) self.assertEqual(sm.fit_anonymous(s1, s2), False) self.assertEqual(sm.get_mapping(s1, s2), None)
def occu_from_structure(self, structure, return_mapping=False): """ Calculates the correlation vector. Structure must be on this supercell """ #calculate mapping to supercell sm_no_sc = StructureMatcher(primitive_cell=False, attempt_supercell=False, allow_subset=True, comparator=OrderDisorderElementComparator(), supercell_size=self.cluster_expansion.supercell_size, scale=True, ltol=self.cluster_expansion.ltol, stol=self.cluster_expansion.stol, angle_tol=self.cluster_expansion.angle_tol) #print('sc:\n',self.supercell_matrix,\ # '\nstr:\n',self.cluster_expansion.supercell_matrix_from_structure(structure)) mapping = sm_no_sc.get_mapping(self.supercell, structure) if mapping is None: raise ValueError('Structure cannot be mapped to this supercell. Structure:{}\nSupercell:{}'.format(structure,self.supercell)) mapping = mapping.tolist() #cs.supercell[mapping] = structure occu = np.zeros(len(self.supercell), dtype=np.int) for i, bit in enumerate(self.bits): # print('i=',i) # print('bit=', bit) #rather than starting with all vacancies and looping #only over mapping, explicitly loop over everything to #catch vacancies on improper sites if i in mapping: sp = str(structure[mapping.index(i)].specie) else: sp = 'Vacancy' occu[i] = bit.index(sp) if not return_mapping: return occu else: return occu, mapping
class config: """This class defines the config with lattice gas mapping""" def __init__( self, base_structure, defect_sublattices, num_defects, cellsize=[1, 1, 1], perf_structure=None, ): try: num_defect_sublat = len(defect_sublattices) except TypeError: num_defect_sublat = 1 defect_sublattices = [defect_sublattices] num_defects = [num_defects] self.matcher_base = StructureMatcher(primitive_cell=False, allow_subset=True) self.matcher_frame = StructureMatcher( stol=0.4, primitive_cell=False, allow_subset=True, comparator=FrameworkComparator(), ) self.calc_history = [] self.cellsize = cellsize self.base_structure = base_structure if self.base_structure.num_sites == 0: # we need at least one site for make_supercell self.base_structure.append("H", np.array([0, 0, 0])) self.base_structure.make_supercell( [cellsize[0], cellsize[1], cellsize[2]]) self.base_structure.remove_sites( range(self.base_structure.num_sites)) else: self.base_structure.make_supercell( [cellsize[0], cellsize[1], cellsize[2]]) if perf_structure: self.perf_structure = perf_structure self.perf_structure.make_supercell( [cellsize[0], cellsize[1], cellsize[2]]) self.supercell = self.base_structure.lattice.matrix self.n_sublat = num_defect_sublat invSuper = np.linalg.inv(self.supercell) # add supercell information to defect_sites num_sites = 0 ntot_defects = 0 sublat_id = 0 for defect_sublattice in defect_sublattices: site_centers = defect_sublattice.site_centers defect_sublattice.site_centers_sc = np.zeros( (np.prod(cellsize) * site_centers.shape[0], 3), dtype=float) idx = 0 for i in range(cellsize[0]): for j in range(cellsize[1]): for k in range(cellsize[2]): for l in range(site_centers.shape[0]): defect_sublattice.site_centers_sc[ idx] = site_centers[l] + np.array([i, j, k]) idx += 1 defect_sublattice.site_centers_sc /= np.array(cellsize) num_sites += len(defect_sublattice.site_centers_sc) # change cartesian coordinates to fractional for group in defect_sublattice.groups: for i in range(group.orientations): for j in range(group.natoms): group.coords[i][j] = np.dot(group.coords[i][j], invSuper) # fill the lattice gas representation list latgas_rep = [] for group in num_defects[sublat_id].keys(): latgas_rep.extend( [[group, 0] for i in range(num_defects[sublat_id][group])]) ntot_defects += num_defects[sublat_id][group] defect_sublattice.latgas_rep = latgas_rep sublat_id += 1 self.defect_sublattices = defect_sublattices assert num_sites == ntot_defects self.set_latgas() def set_latgas(self, defect_sublattices=False): if defect_sublattices: self.defect_sublattices = defect_sublattices assert len(self.defect_sublattices) == self.n_sublat self.structure = copy.deepcopy(self.base_structure) for defect_sublattice in self.defect_sublattices: latgas_rep = defect_sublattice.latgas_rep assert len(latgas_rep) == len(defect_sublattice.site_centers_sc) for isite in range(len(latgas_rep)): grp_name = latgas_rep[isite][0] orr = latgas_rep[isite][1] group = defect_sublattice.group_dict[grp_name] for j in range(group.natoms): self.structure.append( group.species[j], group.coords[orr][j] + defect_sublattice.site_centers_sc[isite] # properties={"velocities":[0,0,0]} ) def shuffle(self): for defect_sublattice in self.defect_sublattices: latgas_rep = defect_sublattice.latgas_rep rand.shuffle(latgas_rep) for site in latgas_rep: group = defect_sublattice.group_dict[site[0]] norr = group.orientations site[1] = rand.randrange(norr) # print(latgas_rep) self.set_latgas() def count(self, group_name, orientation): num_grp = [] for defect_sublattice in self.defect_sublattices: num_grp.append( defect_sublattice.latgas_rep.count([group_name, orientation])) return num_grp def update_basestruct(self): basesites = self.matcher_base.get_mapping(self.structure, self.base_structure) idx = 0 for i in basesites: self.base_structure[idx] = self.structure[i] idx += 1 def defect_sublattice_structure(self, sublat_id): assert sublat_id < self.n_sublat sublattice_structure = self.structure.copy() base_sites = self.matcher_base.get_mapping(self.structure, self.base_structure) sublattice_structure.remove_sites(base_sites) return sublattice_structure @property def vacancy_structure(self): filledsites = self.matcher_frame.get_mapping(self.perf_structure, self.structure) # print(self.perf_structure) # print(self.structure) # print(filledsites) vac_structure = self.perf_structure.copy() vac_structure.remove_sites(filledsites) return vac_structure
for site in Vacsites: structure.pop(site) structure_Osite = structure.copy() structure_Osite.remove_species(["Pt", "Zr"]) matcher_site = StructureMatcher( ltol=ltol, primitive_cell=False, allow_subset=True, comparator=FrameworkComparator(), ignored_species=["Pt"], ) # Figure out where the vacancies are by comparing with base_structure filled_sites = matcher_site.get_mapping(base_Osite, structure_Osite) print(filled_sites) vac_struct = base_Osite.copy() vac_struct.remove_sites(filled_sites) print(vac_struct) # assert len(vac_struct) == 10 # choose one vacancy and one O atom randomly and flip vac_flip = rand.choice(vac_struct) Osites = structure.indices_from_symbol("O") O_flip = rand.choice(Osites) del structure[O_flip] print(vac_flip.frac_coords)
class config: """This class defines the config with lattice gas mapping""" def __init__( self, base_structure, defect_sublattices, num_defects, cellsize=[1, 1, 1], perfect_structure=None, ): """ Parameters ---------- base_structure : pymatgen.Structure Structure of base sites (unsampled sites) defect_sublattices : defect_sublattice Structure of defects (sampled sites) num_defects : dict {group name: number of defects} cellsize : list, optional Cell size, by default [1, 1, 1] perfect_structure : pymatgen.Structure, optional Strucure of all sites (union of base and defect), by default None """ try: num_defect_sublat = len(defect_sublattices) except TypeError: num_defect_sublat = 1 defect_sublattices = [defect_sublattices] num_defects = [num_defects] self.matcher_base = StructureMatcher(primitive_cell=False, allow_subset=True) self.matcher_frame = StructureMatcher( stol=0.4, primitive_cell=False, allow_subset=True, comparator=FrameworkComparator(), ) self.calc_history = [] self.cellsize = cellsize self.base_structure = base_structure if self.base_structure.num_sites == 0: # we need at least one site for make_supercell self.base_structure.append("H", np.array([0, 0, 0])) self.base_structure.make_supercell( [cellsize[0], cellsize[1], cellsize[2]]) self.base_structure.remove_sites( range(self.base_structure.num_sites)) else: self.base_structure.make_supercell( [cellsize[0], cellsize[1], cellsize[2]]) if perfect_structure: self.perfect_structure = perfect_structure self.perfect_structure.make_supercell( [cellsize[0], cellsize[1], cellsize[2]]) self.supercell = self.base_structure.lattice.matrix self.n_sublat = num_defect_sublat invSuper = np.linalg.inv(self.supercell) # add supercell information to defect_sites num_sites = 0 ntot_defects = 0 sublat_id = 0 for defect_sublattice in defect_sublattices: site_centers = defect_sublattice.site_centers defect_sublattice.site_centers_sc = np.zeros( (np.prod(cellsize) * site_centers.shape[0], 3), dtype=float) idx = 0 for (idx, (i, j, k, l)) in enumerate( product( range(cellsize[0]), range(cellsize[1]), range(cellsize[2]), range(site_centers.shape[0]), )): defect_sublattice.site_centers_sc[ idx] = site_centers[l] + np.array([i, j, k]) idx += 1 defect_sublattice.site_centers_sc /= np.array(cellsize) num_sites += len(defect_sublattice.site_centers_sc) # change cartesian coordinates to fractional for group in defect_sublattice.groups: for i in range(group.orientations): for j in range(group.natoms): group.coords[i][j] = np.dot(group.coords[i][j], invSuper) # fill the lattice gas representation list latgas_rep = [] for group in num_defects[sublat_id].keys(): latgas_rep.extend( [[group, 0] for i in range(num_defects[sublat_id][group])]) ntot_defects += num_defects[sublat_id][group] defect_sublattice.latgas_rep = latgas_rep sublat_id += 1 self.defect_sublattices = defect_sublattices assert num_sites == ntot_defects self.set_latgas() def set_latgas(self, defect_sublattices=False): """ Parameters ---------- defect_sublattices: pymatgen.Structure """ if defect_sublattices: self.defect_sublattices = defect_sublattices assert len(self.defect_sublattices) == self.n_sublat self.structure = copy.deepcopy(self.base_structure) for defect_sublattice in self.defect_sublattices: latgas_rep = defect_sublattice.latgas_rep assert len(latgas_rep) == len(defect_sublattice.site_centers_sc) for isite in range(len(latgas_rep)): grp_name = latgas_rep[isite][0] orr = latgas_rep[isite][1] group = defect_sublattice.group_dict[grp_name] for j in range(group.natoms): self.structure.append( group.species[j], group.coords[orr][j] + defect_sublattice.site_centers_sc[isite], properties={ "seldyn": group.relaxations[j, :], "magnetization": group.magnetizations[j], }, ) def shuffle(self): for defect_sublattice in self.defect_sublattices: latgas_rep = defect_sublattice.latgas_rep rand.shuffle(latgas_rep) for site in latgas_rep: group = defect_sublattice.group_dict[site[0]] norr = group.orientations site[1] = rand.randint(norr) self.set_latgas() def count(self, group_name, orientation): """ Parameters ---------- group_name: str The name of the group orientation: Returns ------- """ num_grp = [] for defect_sublattice in self.defect_sublattices: num_grp.append( defect_sublattice.latgas_rep.count([group_name, orientation])) return num_grp def update_basestruct(self): basesites = self.matcher_base.get_mapping(self.structure, self.base_structure) idx = 0 for i in basesites: self.base_structure[idx] = self.structure[i] idx += 1 def defect_sublattice_structure(self, sublat_id): """ Parameters ---------- sublat_id: int index of sublattice Returns ------- sublattice_structure: pymatgen.Structure sublattice structure object """ assert sublat_id < self.n_sublat sublattice_structure = self.structure.copy() base_sites = self.matcher_base.get_mapping(self.structure, self.base_structure) sublattice_structure.remove_sites(base_sites) return sublattice_structure @property def vacancy_structure(self): filledsites = self.matcher_frame.get_mapping(self.perfect_structure, self.structure) vac_structure = self.perfect_structure.copy() vac_structure.remove_sites(filledsites) return vac_structure