def findPeriodicallyEqualAtoms(atoms, other_atoms): center = atoms.positions.mean(axis=0) center, remain = convertToBasis(center, other_atoms.cell) center = (np.array([.5, .5, .5]) - center)[0] other_atoms = wrap(other_atoms, center=center) cell = other_atoms.get_cell() pbc = atoms.get_pbc() cell = atoms.cell[pbc] group = -np.ones(len(other_atoms), dtype=np.int) for i, atom in enumerate(atoms): diff = other_atoms.get_positions() - atom.position pos = minimalDistance(diff, cell) mask = vectorLength(pos, 1) < 1e-5 indices = np.arange(len(other_atoms))[mask] group[indices] = i return group
def makeAtomsRelaxed(atoms, relaxed_atoms, tolerance=1.0, cell=None, change=None, correct_drift=False): atoms = atoms.copy() if relaxed_atoms is None: return atoms if change is None: change = np.ones(len(atoms), np.bool) if cell is None: cell = atoms.get_cell() cell[relaxed_atoms.pbc] = relaxed_atoms.cell[relaxed_atoms.pbc] drift = np.zeros(3, np.float) used = np.zeros(len(relaxed_atoms), np.bool) changed = [] if relaxed_atoms is not None: # Find relaxed atoms closest to originals. for i, atom in enumerate(atoms): if not change[i]: continue mask = np.array([r_atom.symbol == atom.symbol for r_atom in relaxed_atoms]) mask = np.logical_and(mask, np.logical_not(used)) if mask.sum() == 0: continue diff = relaxed_atoms.positions[mask] - atom.position diff = minimalDistance(diff, cell[relaxed_atoms.pbc]) index = vectorLength(diff, 1).argmin() adjustment = diff[index] if vectorLength(adjustment) < tolerance: drift += adjustment real_index = np.arange(len(relaxed_atoms))[mask][index] used[real_index] = False changed.append(i) atom.position += adjustment if correct_drift: changed = np.array(changed) drift /= len(changed) atoms.positions[changed] -= drift return atoms
def substitutionalDopingOfMiddleLayer(atoms, n_dopants=1, dopant_element='P', centers=None): assert isinstance(n_dopants, int) assert n_dopants > 0 atoms = atoms.copy() middle_layer = list(findMiddleLayer(atoms)) symbols = np.array(atoms.get_chemical_symbols()) make_dopants = [] for i in range(n_dopants): if centers is None: middle_layer_index = 0 centers = [] else: pos = atoms.positions[np.array(middle_layer, int)] for center in centers: middle_layer_index = vectorLength(minimalDistance(pos - center, atoms.cell), 1).argmax() index = middle_layer.pop(middle_layer_index) make_dopants.append(index) centers.append(atoms[index].position) symbols[np.array(make_dopants, int)] = dopant_element atoms.set_chemical_symbols(symbols) return atoms