def generate_defect_structure(self, supercell=(1, 1, 1)): """ Returns Defective Substitution structure, decorated with charge. If bulk structure had any site properties, all of these properties are removed in the resulting defect structure. Args: supercell (int, [3x1], or [[]] (3x3)): supercell integer, vector, or scaling matrix """ defect_structure = Structure( self.bulk_structure.copy().lattice, [site.specie for site in self.bulk_structure], [site.frac_coords for site in self.bulk_structure], to_unit_cell=True, coords_are_cartesian = False, site_properties = None) #remove all site_properties defect_structure.make_supercell(supercell) #create a trivial defect structure to find where supercell transformation moves the defect struct_for_defect_site = Structure( self.bulk_structure.copy().lattice, [self.site.specie], [self.site.frac_coords], to_unit_cell=True, coords_are_cartesian = False) struct_for_defect_site.make_supercell(supercell) defect_site = struct_for_defect_site[0] poss_deflist = sorted( defect_structure.get_sites_in_sphere(defect_site.coords, 0.1, include_index=True), key=lambda x: x[1]) defindex = poss_deflist[0][2] subsite = defect_structure.pop(defindex) defect_structure.append(self.site.specie.symbol, subsite.coords, coords_are_cartesian=True, properties = None) defect_structure.set_charge(self.charge) return defect_structure
def get_string(self, radius=10.): """ Returns a string representation of atomic shell coordinates to be used in the feff.inp file. Args: radius: Maximum atomic shell radius to include in atoms list Returns: String representation of Atomic Coordinate Shells. """ nopts = len(self.struct.species) ptatoms = [] for i in range(0, nopts): ptatoms.append(self.struct.species[i].symbol) index = ptatoms.index(self.central_atom) pt = self.struct.cart_coords[index] sphere = Structure.get_sites_in_sphere(self.struct, pt, radius) xshift = pt[0] yshift = pt[1] zshift = pt[2] end = len(sphere) row = [] for i in range(end): atom = sphere[i][0] atm = re.sub(r"[^aA-zZ]+", "", atom.species_string) ipot = self.pot_dict[atm] x = atom.coords[0] - xshift y = atom.coords[1] - yshift z = atom.coords[2] - zshift distance = sphere[i][1] row.append(["{:f}".format(x), "{:f}".format(y), "{:f}".format(z), ipot, atm, "{:f}".format(distance), i]) row_sorted = sorted(row, key=itemgetter(5)) row_sorted[0][3] = 0 for i in range(end): row_sorted[i][6] = i row_sorted = str_aligned(row_sorted, ["* x", "y", "z", "ipot", "Atom", "Distance", "Number"]) atom_list = row_sorted.replace("--", "**") return ''.join(["ATOMS\n", atom_list, "\nEND\n"])
def generate_defect_structure(self, supercell=(1, 1, 1)): """ Returns Defective Substitution structure, decorated with charge. If bulk structure had any site properties, all of these properties are removed in the resulting defect structure. Args: supercell (int, [3x1], or [[]] (3x3)): supercell integer, vector, or scaling matrix """ defect_structure = Structure( self.bulk_structure.copy().lattice, [site.specie for site in self.bulk_structure], [site.frac_coords for site in self.bulk_structure], to_unit_cell=True, coords_are_cartesian=False, site_properties=None, ) # remove all site_properties defect_structure.make_supercell(supercell) # create a trivial defect structure to find where supercell transformation moves the defect struct_for_defect_site = Structure( self.bulk_structure.copy().lattice, [self.site.specie], [self.site.frac_coords], to_unit_cell=True, coords_are_cartesian=False, ) struct_for_defect_site.make_supercell(supercell) defect_site = struct_for_defect_site[0] poss_deflist = sorted( defect_structure.get_sites_in_sphere(defect_site.coords, 0.1, include_index=True), key=lambda x: x[1], ) defindex = poss_deflist[0][2] subsite = defect_structure.pop(defindex) defect_structure.append( self.site.specie.symbol, subsite.coords, coords_are_cartesian=True, properties=None, ) defect_structure.set_charge(self.charge) return defect_structure
def perturb_neighboring_atoms(structure: Structure, center: List[float], cutoff: float, distance: float, inserted_atom_indices: List[int] ) -> Tuple[Structure, list]: """ Return the structure with randomly perturbed atoms near the center Args: structure (Structure): pmg Structure class object center (list): Fractional coordinates of a central position. cutoff (float): Radius of a sphere in which atoms are perturbed. distance (float): Max displacement distance for the perturbation. inserted_atom_indices (list): Inserted atom indices, which will not be perturbed. Return: Tuple of perturbed Structure and list of perturbed atom indices. """ perturbed_structure = structure.copy() cartesian_coords = structure.lattice.get_cartesian_coords(center) # neighbor is (PeriodicSite, distance, index) neighbors = structure.get_sites_in_sphere( pt=cartesian_coords, r=cutoff, include_index=True) if not neighbors: logger.warning(f"No neighbors withing the cutoff {cutoff}.") sites = [] for i in neighbors: # not perturb inserted atoms if i[2] in inserted_atom_indices: continue # Since translate_sites accepts only one vector, iterate this. vector = normalized_random_3d_vector() * distance * np.random.random() site_index = i[2] sites.append(site_index) perturbed_structure.translate_sites( indices=site_index, vector=vector, frac_coords=False) return perturbed_structure, sites
def get_string(self, radius=10.): """ Returns a string representation of atomic shell coordinates to be used in the feff.inp file. Args: radius: Maximum atomic shell radius to include in atoms list Returns: String representation of Atomic Coordinate Shells. """ #Internal variables: # #nopts = number of potentials in unit cell used #ptatoms = list of atom potential atom symbols in unit cell #index = index number of absorbing atom in list #pt = coordinates of absorbing atom #sphere = sites around absorbing atom within radius #x,y,zshift = coordinate shift to place absorbing atom at (0,0,0) #atom = site in sphere #atm = atomic symbol string for atom at atom site #ipot = index for that atom symbol in potential dictionary #distance = distance of that atom site from absorbing atom nopts = len(self.struct.species) ptatoms = [self.struct.species[i].symbol for i in range(nopts)] index = ptatoms.index(self.central_atom) pt = self.struct.cart_coords[index] sphere = Structure.get_sites_in_sphere(self.struct, pt, radius) xshift = pt[0] yshift = pt[1] zshift = pt[2] end = len(sphere) row = [] for i in range(end): atom = sphere[i][0] atm = re.sub(r"[^aA-zZ]+", "", atom.species_string) ipot = self.pot_dict[atm] x = atom.coords[0] - xshift y = atom.coords[1] - yshift z = atom.coords[2] - zshift distance = sphere[i][1] row.append(["{:f}".format(x), "{:f}".format(y), "{:f}".format(z), ipot, atm, "{:f}".format(distance), i]) #after this point table is built row_sorted = sorted(row, key=itemgetter(5)) row_sorted[0][3] = 0 for i in range(end): row_sorted[i][6] = i row_sorted = str_aligned(row_sorted, ["* x", "y", "z", "ipot", "Atom", "Distance", "Number"]) atom_list = row_sorted.replace("--", "**") return ''.join(["ATOMS\n", atom_list, "\nEND\n"])
def get_string(self, radius=10.): """ Returns a string representation of atomic shell coordinates to be used in the feff.inp file. Args: radius: Maximum atomic shell radius to include in atoms list Returns: String representation of Atomic Coordinate Shells. """ #Internal variables: # #nopts = number of potentials in unit cell used #ptatoms = list of atom potential atom symbols in unit cell #index = index number of absorbing atom in list #pt = coordinates of absorbing atom #sphere = sites around absorbing atom within radius #x,y,zshift = coordinate shift to place absorbing atom at (0,0,0) #atom = site in sphere #atm = atomic symbol string for atom at atom site #ipot = index for that atom symbol in potential dictionary #distance = distance of that atom site from absorbing atom nopts = len(self.struct.species) ptatoms = [self.struct.species[i].symbol for i in range(nopts)] index = ptatoms.index(self.central_atom) pt = self.struct.cart_coords[index] sphere = Structure.get_sites_in_sphere(self.struct, pt, radius) xshift = pt[0] yshift = pt[1] zshift = pt[2] end = len(sphere) row = [] for i in range(end): atom = sphere[i][0] atm = re.sub(r"[^aA-zZ]+", "", atom.species_string) ipot = self.pot_dict[atm] x = atom.coords[0] - xshift y = atom.coords[1] - yshift z = atom.coords[2] - zshift distance = sphere[i][1] row.append([ "{:f}".format(x), "{:f}".format(y), "{:f}".format(z), ipot, atm, "{:f}".format(distance), i ]) #after this point table is built row_sorted = sorted(row, key=itemgetter(5)) row_sorted[0][3] = 0 for i in range(end): row_sorted[i][6] = i row_sorted = str_aligned( row_sorted, ["* x", "y", "z", "ipot", "Atom", "Distance", "Number"]) atom_list = row_sorted.replace("--", "**") return ''.join(["ATOMS\n", atom_list, "\nEND\n"])