def get_point_defect(self, symprec=1e-3, doped_out='all', doped_in=['Vac'], num=[1]): cell = self.no_defect_cell cg = ConfigurationGenerator(cell, symprec) sites = _get_sites(list(cell.atoms), doped_out=doped_out, doped_in=doped_in) if num == None: confs = cg.cons_specific_cell(sites, e_num=None, symprec=symprec) comment = ["-".join(doped_in) + "-all_concentration"] else: purity_atom_num = sum( [1 if len(site) > 1 else 0 for site in sites]) 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]))) comment = '-'.join(doped_out) + '-' + '-'.join(comment) + '-defect' folder = comment if not os.path.isdir(folder): os.makedirs(folder) deg = [] idx = 0 for c, _deg in confs: write_poscar(c, folder, idx) deg.append(_deg) idx += 1 np.savetxt(os.path.join(folder, "deg.txt"), deg, fmt='%d')
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_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 test_cons_specific_volume_c(self): wanted = [7] got = [] cg = CG(self.fcc_pcell) for v in [4]: con = cg.cons_specific_volume([(1, 5), (2,)], v, e_num=(3, 1)) got.append(len([i for i in con])) self.assertEqual(got, wanted)
def test_cons_specific_volume(self): wanted = [2, 6, 12, 41] got = [] cg = CG(self.fcc_pcell) for v in [1, 2, 3, 4]: con = cg.cons_specific_volume([(1, 5), (2,)], v) got.append(len([i for i in con])) self.assertEqual(got, wanted)
def test_cons_max_volume(self): # 最大体积下可能产生的所有结构的总和,不包含超胞。 wanted = [2, 4, 10, 29] got = [] cg = CG(self.fcc_pcell) for v in [1, 2, 3, 4]: con = cg.cons_max_volume([(1, 5), (2,)], v) got.append(len([i for i in con])) self.assertEqual(got, wanted)
def test_cons_specific_cell(self): fcc_latt = [5, 0, 0, 0, 5, 0, 0, 0, 5] fcc_pos = [(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0)] fcc_atoms = [0, 0, 0, 0] con_cell = Cell(fcc_latt, fcc_pos, fcc_atoms) cg = CG(con_cell) con = cg.cons_specific_cell([(2, 3), (2, 3), (2, 3), (2, 3)]) # number of all configurations wanted = 5 got = len([i for i in con]) self.assertEqual(got, wanted)
def test_cons_specific_cell_and_c(self): # FCC conventional cell fcc_latt = [5, 0, 0, 0, 5, 0, 0, 0, 5] fcc_pos = [(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0)] fcc_atoms = [0, 0, 0, 0] con_cell = Cell(fcc_latt, fcc_pos, fcc_atoms) cg = CG(con_cell) con = cg.cons_specific_cell( [(2, 3, 4), (2, 3, 4), (2, 3, 4), (2, 3, 4)], e_num=(2, 1, 1)) # number of all configurations wanted = 1 got = len([i for i in con]) self.assertEqual(got, wanted) # Zinc-blende conventional cell fcc_latt = [5, 0, 0, 0, 5, 0, 0, 0, 5] fcc_pos = [(0, 0, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0), (0.25, 0.25, 0.25), (0.75, 0.75, 0.25), (0.75, 0.25, 0.75), (0.25, 0.75, 0.75)] fcc_atoms = [0, 0, 0, 0, 1, 1, 1, 1] con_cell = Cell(fcc_latt, fcc_pos, fcc_atoms) cg = CG(con_cell) con = cg.cons_specific_cell( [(2, 3, 4), (2, 3, 4), (2, 3, 4), (2, 3, 4), (1, ), (1, ), (1, ), (1,)], e_num=(2, 1, 1)) # number of all configurations wanted = 1 got = len([i for i in con]) self.assertEqual(got, wanted)
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')