def _get_sites(atoms, doped_out, doped_in): doped_in = [s2n(i) for i in doped_in] if doped_out == 'all': return [tuple([atom] + doped_in) for atom in atoms] else: doped_out = s2n(doped_out) _ins = tuple([doped_out] + doped_in) return [_ins if atom == doped_out else (atom, ) for atom in atoms]
def get_magnetic_config(self, magnetic_atom, magmon=1, magmon_identity=False, symprec=1e-3): cell = self.no_defect_cell cg = ConfigurationGenerator(cell, symprec) doped_in = get_symbol( np.setdiff1d(range(1, 56), np.unique(cell.atoms))[0]) sites = _get_sites(list(cell.atoms), doped_out=magnetic_atom, doped_in=[doped_in]) n = len(cell.atoms) magmom = [] magnetic_atom_idx = np.where( cell.atoms == s2n(magnetic_atom[0]))[0].astype("int") atoms_type = get_identity_atoms(cell, symprec) unique_atoms_type = np.unique(atoms_type) for num in range(len(magnetic_atom_idx) // 2 + 1): confs = cg.cons_specific_cell( sites, e_num=[len(magnetic_atom_idx) - num, num], symprec=symprec) for c, _def in confs: tmp_magmom = np.zeros((n, )) tmp_magmom[magnetic_atom_idx] = magmon mag_idx = [np.where(np.linalg.norm(cell.positions-c.positions[_idx],axis=1)<0.01)[0][0] \ for _idx in np.where(c.atoms==s2n(doped_in[0]))[0]] tmp_magmom[mag_idx] = -magmon if magmon_identity: flag = True for i in unique_atoms_type: if len( np.unique(tmp_magmom[np.where( atoms_type == i)[0]])) != 1: flag = False break if flag: magmom.append(tmp_magmom.tolist()) else: magmom.append(tmp_magmom.tolist()) # remove the equivalent AFM -1 1/1 -1 final_magmom = set() final_magmom.add(tuple(magmom[0])) for idx in range(1, len(magmom)): mag = np.array(magmom[idx]).astype("int") if tuple(mag) in final_magmom: continue idx_up = np.where(mag == magmon)[0].astype("int") idx_down = np.where(mag == -magmon)[0].astype("int") mag[idx_up] = -magmon mag[idx_down] = magmon if tuple(mag) in final_magmom: continue final_magmom.add(tuple(mag)) final_magmom = np.array([list(i) for i in final_magmom]) np.savetxt("INCAR-magmon", final_magmom, fmt='%2d')
def _get_sites(l_atoms, ele, l_sub): ele_n = s2n(ele) l_sub_n = [s2n(sub_n) for sub_n in l_sub] sites = [] for a in l_atoms: if a == ele_n: sites.append(tuple([a] + l_sub_n)) else: sites.append(tuple([a])) return sites
def _get_sites(atoms, doped_out, doped_in): doped_in = [s2n(i) for i in doped_in] if doped_out == ['all']: return [tuple([atom] + doped_in) for atom in atoms] elif len(doped_out) > 1: doped_out = [s2n(i) for i in doped_out] return [ tuple([atom] + doped_in) if atom in doped_out else (atom, ) for atom in atoms ] else: doped_out = [s2n(i) for i in doped_out] _ins = tuple(doped_out + doped_in) return [_ins if atom == doped_out else (atom, ) for atom in atoms]
def get_purity_defect(self, symprec=1e-3, purity_out='all', purity_in='Vacc', num=1): cg = ConfigurationGenerator(self.no_defect_cell, symprec) sites = _get_sites(list(self.atoms), purity_out=purity_out, purity_in=purity_in) if purity_out == 'all': confs = cg.cons_specific_cell(sites, e_num=(len(self.atoms) - num, num), symprec=symprec) else: purity_atom_num = np.where(self.atoms == s2n(purity_out))[0].size confs = cg.cons_specific_cell(sites, e_num=(purity_atom_num - num, num), symprec=symprec) folder = purity_out + '-' + purity_in + '-defect' if not os.path.exists('./' + folder): os.mkdir('./' + folder) else: rmtree('./' + folder) os.mkdir('./' + folder) idx = 0 for c, _ in confs: wirite_poscar(c, purity_out + '-' + purity_in, folder, idx) idx += 1
def get_purity_defect(self, symprec=1e-3, isunique=True, purity_atom='all', style='Vacc'): cg = ConfigurationGenerator(self.no_defect_cell, symprec) sites = _get_sites(list(self.atoms), l_sub=purity_atom, purity_atom=style) if purity_atom == 'all': confs = cg.cons_specific_cell(sites, e_num=(len(self.atoms) - 1, 1), symprec=symprec) else: purity_atom_num = np.where(self.atoms == s2n(purity_atom))[0].size confs = cg.cons_specific_cell(sites, e_num=(purity_atom_num - 1, 1), symprec=symprec) folder = style + 'defect' if not os.path.exists('./' + folder): os.mkdir('./' + folder) else: rmtree('./' + folder) os.mkdir('./' + folder) idx = 0 for c, _ in confs: wirite_poscar(c, purity_atom, folder, idx) idx += 1
def get_point_defect(self, symprec=1e-3, doped_out='all', doped_in=['Vac'], num=[1]): cg = ConfigurationGenerator(self.no_defect_cell, symprec) sites = _get_sites(list(self.atoms), doped_out=doped_out, doped_in=doped_in) if doped_out == 'all': if len(np.unique(self.atoms)) > 1 and len(doped_in) > 1: raise ValueError( "Multiple species elements doped in and multiple elements doped out is ambiguous" ) confs = cg.cons_specific_cell(sites, e_num=[len(self.atoms) - sum(num)] + num, symprec=symprec) else: purity_atom_num = np.where(self.atoms == s2n(doped_out))[0].size confs = cg.cons_specific_cell(sites, e_num=[purity_atom_num - sum(num)] + num, symprec=symprec) comment = list(chain(*zip(doped_in, [str(i) for i in num]))) folder = doped_out + '-' + '-'.join(comment) + '-defect' if not os.path.exists('./' + folder): os.mkdir('./' + folder) else: rmtree('./' + folder) os.mkdir('./' + folder) idx = 0 for c, _ in confs: write_poscar(c, folder, idx) idx += 1
def get_tetrahedral_defect(self, isunique=False, doped_in='H', min_d=1.5, folder='tetrahedral-defect'): all_basis = generate_all_basis(1, 1, 1) direct_lattice = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) extend_S = np.zeros((0, 3)) for basis in all_basis: new_basis = np.sum([(direct_lattice[ii] * basis[ii]).tolist() for ii in range(3)], axis=0) extend_S = np.vstack( (extend_S, self.positions + np.tile(new_basis, len(self.atoms)).reshape( (-1, 3)))) idx = np.sum((extend_S <= 1.2) & (extend_S >= -0.2), axis=1) idx = np.where(idx == 3)[0] extend_S = np.dot(extend_S[idx], self.lattice) n = extend_S.shape[0] d = np.zeros((n, n)) for ii in range(n): d[ii, ii + 1:] = np.linalg.norm(extend_S[ii] - extend_S[ii + 1:], axis=1) d = d + d.T first_tetra, sec_tetra, third_tetra = [], [], [] for ii in range(n): temp_d = sorted(d[ii]) idx = np.where(abs(d[ii] - temp_d[1]) < min_d)[0] if len(idx) < 3: continue for comb in combinations(idx, 3): comb_list = list(comb) tmp = d[comb_list][:, comb_list] comb_list.append(ii) if np.std(tmp[tmp > 0]) < 0.01: if abs(tmp[0, 1] - temp_d[1]) < 0.1: first_tetra.append(comb_list) else: sec_tetra.append(comb_list) else: tmp = d[comb_list][:, comb_list] tmp = np.triu(tmp) tmp = sorted(tmp[tmp > 0]) if (np.std(tmp[0:4]) < 0.1 or np.std(tmp[1:5]) < 0.1 or np.std(tmp[2:]) < 0.1) and np.std(tmp) < 0.5: third_tetra.append(comb_list) all_tetra = [] if len(first_tetra) != 0: first_tetra = np.unique(np.sort(first_tetra, axis=1), axis=0) first_tetra = refine_points(first_tetra, extend_S, self.lattice, min_d=min_d) all_tetra.append(first_tetra) if len(sec_tetra) != 0: sec_tetra = np.unique(np.sort(sec_tetra, axis=1), axis=0) sec_tetra = refine_points(sec_tetra, extend_S, self.lattice, min_d=min_d) all_tetra.append(sec_tetra) if len(third_tetra) != 0: third_tetra = np.unique(np.sort(third_tetra, axis=1), axis=0) third_tetra = refine_points(third_tetra, extend_S, self.lattice, min_d=min_d) all_tetra.append(third_tetra) if isunique: if not os.path.exists(folder): os.mkdir(folder) else: rmtree(folder) os.mkdir(folder) idx = 0 # deg = [] for tetra in all_tetra: if len(tetra) == 0: continue new_pos = np.vstack((self.positions, tetra)) new_atoms = np.hstack((self.atoms, s2n(doped_in) * np.ones( (tetra.shape[0], )))) new_cell = Cell(self.lattice, new_pos, new_atoms) equi_atoms = new_cell.get_symmetry()['equivalent_atoms'] purity_atom_type = np.unique(equi_atoms[-tetra.shape[0]:]) for atom_type in purity_atom_type: new_uniq_pos = np.vstack( (self.positions, new_pos[atom_type])) new_uniq_atoms = np.hstack( (self.atoms, s2n(doped_in) * np.ones((1, )))) new_uniq_cell = Cell(self.lattice, new_uniq_pos, new_uniq_atoms) # deg.append(len(np.where(equi_atoms == atom_type)[0])) write_poscar(new_uniq_cell, folder, idx) idx += 1 # np.savetxt(folder+'/deg.txt',deg,fmt='%d') else: if not os.path.exists(folder): os.mkdir(folder) else: rmtree(folder) os.mkdir(folder) idx = 0 for tetra in all_tetra: if len(tetra) == 0: continue new_pos = np.vstack((self.positions, tetra)) new_atoms = np.hstack((self.atoms, s2n(doped_in) * np.ones( (tetra.shape[0], )))) new_cell = Cell(self.lattice, new_pos, new_atoms) write_poscar(new_cell, folder, idx) idx += 1
def conf(cell_filename, comment, pmode, cmode, dimension, volume, element, substitutes, number, symprec, comprec, verbose): """ <parent_cell_file> is the parent cell to generating configurations by sites disorder.\n The non-primitive cell can only used as argument when '--pmode=sc'.\n Command line tool only provide configurations generator for elements disorder, for more flexible usage such as specific site disorder, please see document http:// , or use python library directly. """ cell = read_vasp(cell_filename) cg = ConfigurationGenerator(cell, symprec) if pmode == 'varv' and cmode == 'vc': click.secho("Expanding and generating configurations: ") click.secho("(may take much time)", blink=True, bold=True, bg='magenta', fg='white') spinner = Spinner() spinner.start() (min_v, max_v) = volume if min_v == -1: min_v = 1 sites = _get_sites(list(cell.atoms), element, substitutes) confs = cg.cons_max_volume(sites, max_v, min_volume=min_v, dimension=dimension, symprec=symprec) for idx, c in enumerate(confs): c = c.get_primitive_cell() filename = '{:s}_id{:d}'.format(comment, idx) write_vasp(c, filename) spinner.stop() click.secho("DONE", bold=True, bg='green', fg='white') elif pmode == 'svc' and cmode == 'vc': click.secho("Expanding and generating configurations: ") click.secho("(may take much time)", blink=True, bold=True, bg='magenta', fg='white') spinner = Spinner() spinner.start() (min_v, max_v) = volume sites = _get_sites(list(cell.atoms), element, substitutes) confs = cg.cons_specific_volume(sites, volume=max_v, e_num=None, dimension=dimension, symprec=symprec) f_deg = open('deg.txt', 'a') for idx, (c, d) in enumerate(confs): filename = '{:s}_id{:d}'.format(comment, idx) write_vasp(c, filename) deg_line = filename + '{:10d}'.format(d) + '\n' f_deg.write(deg_line) f_deg.close() spinner.stop() click.secho("DONE", bold=True, bg='green', fg='white') elif pmode == 'svc' and cmode == 'cc': click.secho("Expanding and generating configurations: ") click.secho("(may take much time)", blink=True, bold=True, bg='magenta', fg='white') spinner = Spinner() spinner.start() (min_v, max_v) = volume l_atoms = cell.atoms.tolist() sites = _get_sites(l_atoms, element, substitutes) # number to enum ele_n = s2n(element) e_total = l_atoms.count(ele_n) * max_v e_n = e_total - sum(number) # 第一个元素的数量 e_num = [e_n] + list(number) # 各个元素的数量 confs = cg.cons_specific_volume(sites, volume=max_v, e_num=e_num, dimension=dimension, symprec=symprec) f_deg = open('deg.txt', 'a') for idx, (c, d) in enumerate(confs): filename = '{:s}_id{:d}'.format(comment, idx) write_vasp(c, filename) deg_line = filename + '{:10d}'.format(d) + '\n' f_deg.write(deg_line) f_deg.close() spinner.stop() click.secho("DONE", bold=True, bg='green', fg='white') elif pmode == 'sc' and cmode == 'vc': click.secho("Generating configurations: ") click.secho("(may take much time)", blink=True, bold=True, bg='magenta', fg='white') spinner = Spinner() spinner.start() l_atoms = cell.atoms.tolist() sites = _get_sites(l_atoms, element, substitutes) confs = cg.cons_specific_cell(sites, None, symprec=symprec) f_deg = open('deg.txt', 'a') for idx, (c, d) in enumerate(confs): filename = '{:s}_id{:d}'.format(comment, idx) write_vasp(c, filename) # import pdb; pdb.set_trace() deg_line = filename + '{:10d}'.format(d) + '\n' f_deg.write(deg_line) f_deg.close() spinner.stop() click.secho("DONE", bold=True, bg='green', fg='white') elif pmode == 'sc' and cmode == 'cc': click.secho("Generating configurations: ") click.secho("(may take much time)", blink=True, bold=True, bg='magenta', fg='white') spinner = Spinner() spinner.start() l_atoms = cell.atoms.tolist() sites = _get_sites(l_atoms, element, substitutes) # number to enum ele_n = s2n(element) e_total = l_atoms.count(ele_n) e_n = e_total - sum(number) # 第一个元素的数量 e_num = [e_n] + list(number) # 各个元素的数量 confs = cg.cons_specific_cell(sites, e_num, symprec=symprec) f_deg = open('deg.txt', 'a') # TODO f.close() for idx, (c, d) in enumerate(confs): filename = '{:s}_id{:d}'.format(comment, idx) write_vasp(c, filename) deg_line = filename + '{:10d}'.format(d) + '\n' f_deg.write(deg_line) f_deg.close() spinner.stop() click.secho("DONE", bold=True, bg='green', fg='white') else: click.secho("ERROR: --pmode={:s} --cmode={:s} not supported.".format( pmode, cmode), bold=True, bg='red', fg='white')
def _get_sites(atoms, purity_out='all', purity_in='Vacc'): if purity_out == 'all': return [(i, s2n(purity_in)) for i in atoms] else: return [(i, s2n(purity_in)) if i == s2n(purity_out) else (i, ) for i in atoms]
def _get_sites(atoms, l_sub='all', purity_atom='Vacc'): if l_sub == 'all': return [(i, s2n(purity_atom)) for i in atoms] else: return [(i, s2n(purity_atom)) if i == s2n(l_sub) else (i, ) for i in atoms]