def automatic_gamma_density(self,structure, kppa): """ Returns an automatic Kpoint object based on a structure and a kpoint density. Uses Gamma centered meshes always. For GW. """ latt = structure.lattice ngrid = kppa / len(structure.atoms) lengths = np.linalg.norm(latt,axis=1) is_2d = is_2d_structure(structure) if type(is_2d) is tuple: print('This structure will be treated as a two dimensional structure here', 'so the mesh of one direction will be set to 1 or 2') vac_idx = is_2d[1] atom_idx = np.setdiff1d(range(3),vac_idx) mult = (ngrid * lengths[atom_idx[0]] * lengths[atom_idx[1]]) ** (1 / 2) num_div = np.zeros((3,)) num_div[atom_idx[0]] = int(math.floor(max(mult / lengths[atom_idx[0]], 1))) num_div[atom_idx[1]] = int(math.floor(max(mult / lengths[atom_idx[1]], 1))) num_div[vac_idx] = 1 num_div = num_div.astype(int).tolist() elif not is_2d : mult = (ngrid * lengths[0] * lengths[1] * lengths[2]) ** (1 / 3) num_div = [int(math.floor(max(mult / l, 1))) for l in lengths] # ensure that numDiv[i] > 0 num_div = [i if i > 0 else 1 for i in num_div] # VASP documentation recommends to use even grids for n <= 8 and odd # grids for n > 8. # num_div = [i + i % 2 if i <= 8 else i - i % 2 + 1 for i in num_div] style = Kpoints.supported_modes.Gamma comment = "KPOINTS with grid density = " +"{} / atom".format(kppa) self.comment = comment self.num_kpts = 0 self._style = style self.kpts = [num_div] self.kpts_shift = [0,0,0]
def automatic_density(self, structure, kppa, force_gamma=False): """ Returns an automatic Kpoint object based on a structure and a kpoint density. Uses Gamma centered meshes for hexagonal cells and Monkhorst-Pack grids otherwise. Algorithm: Uses a simple approach scaling the number of divisions along each reciprocal lattice vector proportional to its length. Args: structure (Structure): Input structure kppa (int): Grid density force_gamma (bool): Force a gamma centered mesh (default is to use gamma only for hexagonal cells or odd meshes) """ comment = "grid density = %.0f / atom" % kppa if math.fabs((math.floor(kppa**(1 / 3) + 0.5))**3 - kppa) < 1: kppa += kppa * 0.01 ngrid = kppa / len(structure.atoms) latt = structure.lattice lengths = np.linalg.norm(latt, axis=1) is_2d = is_2d_structure(structure) if type(is_2d) is tuple: print( 'This structure will be treated as a two dimensional structure here', 'so the mesh of one direction will be set to 1') vac_idx = is_2d[1] atom_idx = np.setdiff1d(range(3), vac_idx) mult = (ngrid * lengths[atom_idx[0]] * lengths[atom_idx[1]])**(1 / 2) num_div = np.zeros((3, )) num_div[atom_idx[0]] = int( math.floor(max(mult / lengths[atom_idx[0]], 1))) num_div[atom_idx[1]] = int( math.floor(max(mult / lengths[atom_idx[1]], 1))) num_div[vac_idx] = 1 num_div = num_div.astype(int).tolist() elif not is_2d: mult = (ngrid * lengths[0] * lengths[1] * lengths[2])**(1 / 3) num_div = [int(math.floor(max(mult / l, 1))) for l in lengths] spg = structure.get_spacegroup() if int(spg.split('(')[1].split(')')[0]) in range(168, 195): is_hexagonal = True # latt.is_hexagonal() else: is_hexagonal = False has_odd = any([i % 2 == 1 for i in num_div]) if has_odd or is_hexagonal or force_gamma: style = Kpoints.supported_modes.Gamma else: style = Kpoints.supported_modes.Monkhorst self.comment = comment self.num_kpts = 0 self._style = style self.kpts = [num_div] self.kpts_shift = [0, 0, 0]
def __init__(self, poscar='POSCAR'): self.poscar = poscar if is_2d_structure(read_vasp(self.poscar)): self.dimen = 2 else: self.dimen = 3