def make_supercell( cell_structure: pmg.Structure, scaling_matrix: Optional[ScalingMatrix] = None, scaling_factors: Optional[Tuple[int, int, int]] = None, ) -> pmg.Structure: """Transforms a pymatgen ``Structure`` object into a supercell according to the scaling parameters. :param cell_structure: A pymatgen ``Structure`` object. :param scaling_matrix: A matrix of transforming the lattice vectors. Has to be all integers. e.g., [[2,1,0],[0,3,0],[0,0,1]] generates a new structure with lattice vectors a" = 2a + b, b" = 3b, c" = c where a, b, and c are the lattice vectors of the original structure. :param scaling_factors: A tuple of three numbers used to scale each lattice vector. Same as: ``scaling_matrix=[[scale_a, 0, 0], [0, scale_b, 0], [0, 0, scale_c]]`` :return: A pymatgen ``Structure`` object. """ if scaling_matrix is not None: cell_transformation: SupercellTransformation = SupercellTransformation( scaling_matrix=scaling_matrix) return cell_transformation.apply_transformation(cell_structure) elif scaling_factors is not None: cell_transformation = SupercellTransformation.from_scaling_factors( scale_a=scaling_factors[0], scale_b=scaling_factors[1], scale_c=scaling_factors[2], ) return cell_transformation.apply_transformation(cell_structure) else: return cell_structure
def planar_structure_normalization(structure): ''' This function does the following: 1. check whether the structure is planar using coordniates standard deviation 2. move the planar layer to the center of c-direction Args: structure: pymatgen structure Return: a boolean whether the structure is planar tranformed pymatgen structure ''' tol = 1E-3 # tolerance to check whether the structure is planar is_planar = True coords = structure.frac_coords ts = TransformedStructure(structure, []) if np.std(coords[:,2]) < tol : center_translate = 0.5 - coords[:,2].mean() elif np.std(coords[:,0]) < tol : ts.append_transformation(SupercellTransformation([[0,0,1],[0,1,0],[1,0,0]])) ts.append_transformation(RotationTransformation([0,1,0], 90)) center_translate = 0.5 - coords[:,0].mean() elif np.std(coords[:,1]) < tol : ts.append_transformation(SupercellTransformation([[1,0,0],[0,0,1],[0,1,0]])) ts.append_transformation(RotationTransformation([1,0,0], 90)) center_translate = 0.5 - coords[:,1].mean() else : is_planar = False transformed_structure = None if is_planar: ts.append_transformation(TranslateSitesTransformation( list(range(len(structure))), [0,0,center_translate])) # Use pymatgen 2019.7.2, ts.structures[-1] may change in a newer version transformed_structure = ts.structures[-1] return is_planar, transformed_structure
def abi_sanitize(self, symprec=1e-3, primitive=True): """ Returns a new structure in which: * Oxidation states are removed. * Structure is refined. * Reduced to primitive settings. * Lattice vectors are exchanged if the triple product is negative Args: symprec: Symmetry precision used to refine the structure. if `symprec` is None, so structure refinement is peformed. primitive (bool): Whether to convert to a primitive cell. """ from pymatgen.transformations.standard_transformations import OxidationStateRemovalTransformation, \ PrimitiveCellTransformation, SupercellTransformation # Remove oxidation states. remove_ox = OxidationStateRemovalTransformation() structure = remove_ox.apply_transformation(self) # Refine structure if symprec is not None: sym_finder = SpacegroupAnalyzer(structure=structure, symprec=symprec) structure = sym_finder.get_refined_structure() # Convert to primitive structure. if primitive: get_prim = PrimitiveCellTransformation() structure = get_prim.apply_transformation(structure) # Exchange last two lattice vectors if triple product is negative. m = structure.lattice.matrix x_prod = np.dot(np.cross(m[0], m[1]), m[2]) if x_prod < 0: trans = SupercellTransformation(((1, 0, 0), (0, 0, 1), (0, 1, 0))) structure = trans.apply_transformation(structure) m = structure.lattice.matrix x_prod = np.dot(np.cross(m[0], m[1]), m[2]) if x_prod < 0: raise RuntimeError("x_prod is still negative!") return structure
def refine_structure(structure, symprec=1e-3): remove_ox = OxidationStateRemovalTransformation() structure = remove_ox.apply_transformation(structure) sym_finder = SpacegroupAnalyzer(structure=structure, symprec=symprec) structure = sym_finder.get_refined_structure() get_prim = PrimitiveCellTransformation() structure = get_prim.apply_transformation(structure) m = structure.lattice.matrix x_prod = np.dot(np.cross(m[0], m[1]), m[2]) if x_prod < 0: print(x_prod) trans = SupercellTransformation(((1, 0, 0), (0, 0, 1), (0, 1, 0))) structure = trans.apply_transformation(structure) m = structure.lattice.matrix x_prod = np.dot(np.cross(m[0], m[1]), m[2]) print(x_prod) if x_prod < 0: raise RuntimeError return structure
def correct(self): backup(VASP_BACKUP_FILES | {self.output_filename}) actions = [] vi = VaspInput.from_directory(".") if self.errors.intersection(["tet", "dentet"]): actions.append({"dict": "INCAR", "action": {"_set": {"ISMEAR": 0}}}) if "inv_rot_mat" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"SYMPREC": 1e-8}}}) if "brmix" in self.errors: # If there is not a valid OUTCAR already, increment # error count to 1 to skip first fix if self.error_count['brmix'] == 0: try: assert (Outcar(zpath(os.path.join( os.getcwd(), "OUTCAR"))).is_stopped is False) except: self.error_count['brmix'] += 1 if self.error_count['brmix'] == 0: # Valid OUTCAR - simply rerun the job and increment # error count for next time actions.append({"dict": "INCAR", "action": {"_set": {"ISTART": 1}}}) self.error_count['brmix'] += 1 elif self.error_count['brmix'] == 1: # Use Kerker mixing w/default values for other parameters actions.append({"dict": "INCAR", "action": {"_set": {"IMIX": 1}}}) self.error_count['brmix'] += 1 elif self.error_count['brmix'] == 2 and vi["KPOINTS"].style \ == Kpoints.supported_modes.Gamma: actions.append({"dict": "KPOINTS", "action": {"_set": {"generation_style": "Monkhorst"}}}) actions.append({"dict": "INCAR", "action": {"_unset": {"IMIX": 1}}}) self.error_count['brmix'] += 1 elif self.error_count['brmix'] in [2, 3] and vi["KPOINTS"].style \ == Kpoints.supported_modes.Monkhorst: actions.append({"dict": "KPOINTS", "action": {"_set": {"generation_style": "Gamma"}}}) actions.append({"dict": "INCAR", "action": {"_unset": {"IMIX": 1}}}) self.error_count['brmix'] += 1 if vi["KPOINTS"].num_kpts < 1: all_kpts_even = all([ bool(n % 2 == 0) for n in vi["KPOINTS"].kpts[0] ]) print("all_kpts_even = {}".format(all_kpts_even)) if all_kpts_even: new_kpts = ( tuple(n + 1 for n in vi["KPOINTS"].kpts[0]),) print("new_kpts = {}".format(new_kpts)) actions.append({"dict": "KPOINTS", "action": {"_set": { "kpoints": new_kpts }}}) else: actions.append({"dict": "INCAR", "action": {"_set": {"ISYM": 0}}}) if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst: actions.append({"dict": "KPOINTS", "action": { "_set": {"generation_style": "Gamma"}}}) # Based on VASP forum's recommendation, you should delete the # CHGCAR and WAVECAR when dealing with this error. if vi["INCAR"].get("ICHARG", 0) < 10: actions.append({"file": "CHGCAR", "action": { "_file_delete": {'mode': "actual"}}}) actions.append({"file": "WAVECAR", "action": { "_file_delete": {'mode': "actual"}}}) if "zpotrf" in self.errors: # Usually caused by short bond distances. If on the first step, # volume needs to be increased. Otherwise, it was due to a step # being too big and POTIM should be decreased. If a static run # try turning off symmetry. try: oszicar = Oszicar("OSZICAR") nsteps = len(oszicar.ionic_steps) except: nsteps = 0 if nsteps >= 1: potim = float(vi["INCAR"].get("POTIM", 0.5)) / 2.0 actions.append( {"dict": "INCAR", "action": {"_set": {"ISYM": 0, "POTIM": potim}}}) elif vi["INCAR"].get("NSW", 0) == 0 \ or vi["INCAR"].get("ISIF", 0) in range(3): actions.append( {"dict": "INCAR", "action": {"_set": {"ISYM": 0}}}) else: s = vi["POSCAR"].structure s.apply_strain(0.2) actions.append({"dict": "POSCAR", "action": {"_set": {"structure": s.as_dict()}}}) # Based on VASP forum's recommendation, you should delete the # CHGCAR and WAVECAR when dealing with this error. if vi["INCAR"].get("ICHARG", 0) < 10: actions.append({"file": "CHGCAR", "action": {"_file_delete": {'mode': "actual"}}}) actions.append({"file": "WAVECAR", "action": {"_file_delete": {'mode': "actual"}}}) if self.errors.intersection(["subspacematrix", "rspher", "real_optlay", "nicht_konv"]): s = vi["POSCAR"].structure if len(s) < self.natoms_large_cell: actions.append({"dict": "INCAR", "action": {"_set": {"LREAL": False}}}) else: # for large supercell, try an in-between option LREAL = True # prior to LREAL = False if self.error_count['real_optlay'] == 0: # use real space projectors generated by pot actions.append({"dict": "INCAR", "action": {"_set": {"LREAL": True}}}) self.error_count['real_optlay'] += 1 elif self.error_count['real_optlay'] == 1: actions.append({"dict": "INCAR", "action": {"_set": {"LREAL": False}}}) self.error_count['real_optlay'] += 1 if self.errors.intersection(["tetirr", "incorrect_shift"]): if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst: actions.append({"dict": "KPOINTS", "action": { "_set": {"generation_style": "Gamma"}}}) if "rot_matrix" in self.errors: if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst: actions.append({"dict": "KPOINTS", "action": { "_set": {"generation_style": "Gamma"}}}) else: actions.append({"dict": "INCAR", "action": {"_set": {"ISYM": 0}}}) if "amin" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"AMIN": "0.01"}}}) if "triple_product" in self.errors: s = vi["POSCAR"].structure trans = SupercellTransformation(((1, 0, 0), (0, 0, 1), (0, 1, 0))) new_s = trans.apply_transformation(s) actions.append({"dict": "POSCAR", "action": {"_set": {"structure": new_s.as_dict()}}, "transformation": trans.as_dict()}) if "pricel" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"SYMPREC": 1e-8, "ISYM": 0}}}) if "brions" in self.errors: potim = float(vi["INCAR"].get("POTIM", 0.5)) + 0.1 actions.append({"dict": "INCAR", "action": {"_set": {"POTIM": potim}}}) if "zbrent" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"IBRION": 1}}}) actions.append({"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}) if "too_few_bands" in self.errors: if "NBANDS" in vi["INCAR"]: nbands = int(vi["INCAR"]["NBANDS"]) else: with open("OUTCAR") as f: for line in f: if "NBANDS" in line: try: d = line.split("=") nbands = int(d[-1].strip()) break except (IndexError, ValueError): pass actions.append({"dict": "INCAR", "action": {"_set": {"NBANDS": int(1.1 * nbands)}}}) if "pssyevx" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"ALGO": "Normal"}}}) if "eddrmm" in self.errors: # RMM algorithm is not stable for this calculation if vi["INCAR"].get("ALGO", "Normal") in ["Fast", "VeryFast"]: actions.append({"dict": "INCAR", "action": {"_set": {"ALGO": "Normal"}}}) else: potim = float(vi["INCAR"].get("POTIM", 0.5)) / 2.0 actions.append({"dict": "INCAR", "action": {"_set": {"POTIM": potim}}}) if vi["INCAR"].get("ICHARG", 0) < 10: actions.append({"file": "CHGCAR", "action": {"_file_delete": {'mode': "actual"}}}) actions.append({"file": "WAVECAR", "action": {"_file_delete": {'mode': "actual"}}}) if "edddav" in self.errors: if vi["INCAR"].get("ICHARG", 0) < 10: actions.append({"file": "CHGCAR", "action": {"_file_delete": {'mode': "actual"}}}) actions.append({"dict": "INCAR", "action": {"_set": {"ALGO": "All"}}}) if "grad_not_orth" in self.errors: if vi["INCAR"].get("ISMEAR", 1) < 0: actions.append({"dict": "INCAR", "action": {"_set": {"ISMEAR": "0"}}}) if "zheev" in self.errors: if vi["INCAR"].get("ALGO", "Fast").lower() != "exact": actions.append({"dict": "INCAR", "action": {"_set": {"ALGO": "Exact"}}}) if "elf_kpar" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"KPAR": 1}}}) if "rhosyg" in self.errors: if vi["INCAR"].get("SYMPREC", 1e-4) == 1e-4: actions.append({"dict": "INCAR", "action": {"_set": {"ISYM": 0}}}) actions.append({"dict": "INCAR", "action": {"_set": {"SYMPREC": 1e-4}}}) if "posmap" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"SYMPREC": 1e-6}}}) VaspModder(vi=vi).apply_actions(actions) return {"errors": list(self.errors), "actions": actions}
def correct(self): backup(VASP_BACKUP_FILES | {self.output_filename}) actions = [] vi = VaspInput.from_directory(".") if self.errors.intersection(["tet", "dentet"]): actions.append({ "dict": "INCAR", "action": { "_set": { "ISMEAR": 0 } } }) if "inv_rot_mat" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "SYMPREC": 1e-8 } } }) if "brmix" in self.errors: if self.error_count['brmix'] == 0 and vi[ "KPOINTS"].style == Kpoints.supported_modes.Gamma: actions.append({ "dict": "KPOINTS", "action": { "_set": { "generation_style": "Monkhorst" } } }) self.error_count['brmix'] += 1 elif self.error_count['brmix'] <= 1 and vi[ "KPOINTS"].style == Kpoints.supported_modes.Monkhorst: actions.append({ "dict": "KPOINTS", "action": { "_set": { "generation_style": "Gamma" } } }) self.error_count['brmix'] += 1 if vi["KPOINTS"].num_kpts < 1: all_kpts_even = all( [bool(n % 2 == 0) for n in vi["KPOINTS"].kpts[0]]) print("all_kpts_even = {}".format(all_kpts_even)) if all_kpts_even: new_kpts = (tuple(n + 1 for n in vi["KPOINTS"].kpts[0]), ) print("new_kpts = {}".format(new_kpts)) actions.append({ "dict": "KPOINTS", "action": { "_set": { "kpoints": new_kpts } } }) else: actions.append({ "dict": "INCAR", "action": { "_set": { "ISYM": 0 } } }) if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst: actions.append({ "dict": "KPOINTS", "action": { "_set": { "generation_style": "Gamma" } } }) # Based on VASP forum's recommendation, you should delete the # CHGCAR and WAVECAR when dealing with this error. actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "file": "WAVECAR", "action": { "_file_delete": { 'mode': "actual" } } }) if "zpotrf" in self.errors: # Usually caused by short bond distances. If on the first step, # volume needs to be increased. Otherwise, it was due to a step # being too big and POTIM should be decreased. try: oszicar = Oszicar("OSZICAR") nsteps = len(oszicar.ionic_steps) except: nsteps = 0 if nsteps >= 1: potim = float(vi["INCAR"].get("POTIM", 0.5)) / 2.0 actions.append({ "dict": "INCAR", "action": { "_set": { "ISYM": 0, "POTIM": potim } } }) else: s = vi["POSCAR"].structure s.apply_strain(0.2) actions.append({ "dict": "POSCAR", "action": { "_set": { "structure": s.as_dict() } } }) # Based on VASP forum's recommendation, you should delete the # CHGCAR and WAVECAR when dealing with this error. actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "file": "WAVECAR", "action": { "_file_delete": { 'mode': "actual" } } }) if self.errors.intersection( ["subspacematrix", "rspher", "real_optlay"]): actions.append({ "dict": "INCAR", "action": { "_set": { "LREAL": False } } }) if self.errors.intersection(["tetirr", "incorrect_shift"]): if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst: actions.append({ "dict": "KPOINTS", "action": { "_set": { "generation_style": "Gamma" } } }) if "rot_matrix" in self.errors: if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst: actions.append({ "dict": "KPOINTS", "action": { "_set": { "generation_style": "Gamma" } } }) else: actions.append({ "dict": "INCAR", "action": { "_set": { "ISYM": 0 } } }) if "amin" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "AMIN": "0.01" } } }) if "triple_product" in self.errors: s = vi["POSCAR"].structure trans = SupercellTransformation(((1, 0, 0), (0, 0, 1), (0, 1, 0))) new_s = trans.apply_transformation(s) actions.append({ "dict": "POSCAR", "action": { "_set": { "structure": new_s.as_dict() } }, "transformation": trans.as_dict() }) if "pricel" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "SYMPREC": 1e-8, "ISYM": 0 } } }) if "brions" in self.errors: potim = float(vi["INCAR"].get("POTIM", 0.5)) + 0.1 actions.append({ "dict": "INCAR", "action": { "_set": { "POTIM": potim } } }) if "zbrent" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "IBRION": 1 } } }) if "too_few_bands" in self.errors: if "NBANDS" in vi["INCAR"]: nbands = int(vi["INCAR"]["NBANDS"]) else: with open("OUTCAR") as f: for line in f: if "NBANDS" in line: try: d = line.split("=") nbands = int(d[-1].strip()) break except (IndexError, ValueError): pass actions.append({ "dict": "INCAR", "action": { "_set": { "NBANDS": int(1.1 * nbands) } } }) if "pssyevx" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Normal" } } }) if "eddrmm" in self.errors: #RMM algorithm is not stable for this calculation if vi["INCAR"].get("ALGO", "Normal") in ["Fast", "VeryFast"]: actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Normal" } } }) else: potim = float(vi["INCAR"].get("POTIM", 0.5)) / 2.0 actions.append({ "dict": "INCAR", "action": { "_set": { "POTIM": potim } } }) actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "file": "WAVECAR", "action": { "_file_delete": { 'mode': "actual" } } }) if "edddav" in self.errors: actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "All" } } }) VaspModder(vi=vi).apply_actions(actions) return {"errors": list(self.errors), "actions": actions}
def test_apply_transformation(self): t = SupercellTransformation([[2, 1, 0], [0, 2, 0], [1, 0, 2]]) s = t.apply_transformation(self.struct) self.assertEqual(s.composition.formula, "Li16 O16")
def correct(self): backup(orig_handlers.VASP_BACKUP_FILES | {self.output_filename}) actions = [] vi = VaspInput.from_directory(".") if self.errors.intersection(["tet", "dentet"]): actions.append({ "dict": "INCAR", "action": { "_set": { "ISMEAR": 0 } } }) if "inv_rot_mat" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "SYMPREC": 1e-8 } } }) # ----- added --------------------------------------------------- if "plane_wave_coeff" in self.errors: actions.append({ "file": "WAVECAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) # --------------------------------------------------------------- if "zpotrf" in self.errors: # Usually caused by short bond distances. If on the first step, # volume needs to be increased. Otherwise, it was due to a step # being too big and POTIM should be decreased. If a static run # try turning off symmetry. try: oszicar = Oszicar("OSZICAR") nsteps = len(oszicar.ionic_steps) except: nsteps = 0 if nsteps >= 1: potim = float(vi["INCAR"].get("POTIM", 0.5)) / 2.0 actions.append({ "dict": "INCAR", "action": { "_set": { "ISYM": 0, "POTIM": potim } } }) elif vi["INCAR"].get("NSW", 0) == 0 \ or vi["INCAR"].get("ISIF", 0) in range(3): actions.append({ "dict": "INCAR", "action": { "_set": { "ISYM": 0 } } }) else: s = vi["POSCAR"].structure s.apply_strain(0.2) actions.append({ "dict": "POSCAR", "action": { "_set": { "structure": s.as_dict() } } }) # Based on VASP forum's recommendation, you should delete the # CHGCAR and WAVECAR when dealing with this error. if vi["INCAR"].get("ICHARG", 0) < 10: actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "file": "WAVECAR", "action": { "_file_delete": { 'mode': "actual" } } }) if self.errors.intersection(["subspacematrix"]): if self.error_count["subspacematrix"] == 0: actions.append({ "dict": "INCAR", "action": { "_set": { "LREAL": False } } }) else: actions.append({ "dict": "INCAR", "action": { "_set": { "PREC": "Accurate" } } }) self.error_count["subspacematrix"] += 1 if self.errors.intersection(["rspher", "real_optlay", "nicht_konv"]): s = vi["POSCAR"].structure if len(s) < self.natoms_large_cell: actions.append({ "dict": "INCAR", "action": { "_set": { "LREAL": False } } }) else: # for large supercell, try an in-between option LREAL = True # prior to LREAL = False if self.error_count['real_optlay'] == 0: # use real space projectors generated by pot actions.append({ "dict": "INCAR", "action": { "_set": { "LREAL": True } } }) elif self.error_count['real_optlay'] == 1: actions.append({ "dict": "INCAR", "action": { "_set": { "LREAL": False } } }) self.error_count['real_optlay'] += 1 if self.errors.intersection(["tetirr", "incorrect_shift"]): # --Modified------------------------------------------------------ if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst or \ vi["KPOINTS"].kpts_shift != [0.0, 0.0, 0.0]: actions.append({ "dict": "KPOINTS", "action": { "_set": { "generation_style": "Gamma", "usershift": [0.0, 0.0, 0.0] } } }) # ----------------------------------------------------------- if "rot_matrix" in self.errors: # --Modified------------------------------------------------------ if vi["KPOINTS"].style == Kpoints.supported_modes.Monkhorst or \ vi["KPOINTS"].kpts_shift != [0.0, 0.0, 0.0]: actions.append({ "dict": "KPOINTS", "action": { "_set": { "generation_style": "Gamma", "usershift": [0.0, 0.0, 0.0] } } }) # ----------------------------------------------------------- else: actions.append({ "dict": "INCAR", "action": { "_set": { "ISYM": 0 } } }) if "amin" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "AMIN": "0.01" } } }) if "triple_product" in self.errors: s = vi["POSCAR"].structure trans = SupercellTransformation(((1, 0, 0), (0, 0, 1), (0, 1, 0))) new_s = trans.apply_transformation(s) actions.append({ "dict": "POSCAR", "action": { "_set": { "structure": new_s.as_dict() } }, "transformation": trans.as_dict() }) if "pricel" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "SYMPREC": 1e-8, "ISYM": 0 } } }) if "brions" in self.errors: potim = float(vi["INCAR"].get("POTIM", 0.5)) + 0.1 actions.append({ "dict": "INCAR", "action": { "_set": { "POTIM": potim } } }) if "zbrent" in self.errors: # Modified so as not to use IBRION=1 as it does not show the # eigenvalues in vasprun.xml >>>>>>>>>>>> actions.append({ "dict": "INCAR", "action": { "_set": { "ADDGRID": True } } }) actions.append({ "file": "CONTCAR", "action": { "_file_copy": { "dest": "POSCAR" } } }) # actions.append({"dict": "INCAR", # "action": {"_set": {"IBRION": 1}}}) # actions.append({"file": "CONTCAR", # "action": {"_file_copy": {"dest": "POSCAR"}}}) # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if "too_few_bands" in self.errors: if "NBANDS" in vi["INCAR"]: nbands = int(vi["INCAR"]["NBANDS"]) else: with open("OUTCAR") as f: for line in f: if "NBANDS" in line: try: d = line.split("=") nbands = int(d[-1].strip()) break except (IndexError, ValueError): pass actions.append({ "dict": "INCAR", "action": { "_set": { "NBANDS": int(1.1 * nbands) } } }) if "pssyevx" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Normal" } } }) if "eddrmm" in self.errors: # RMM algorithm is not stable for this calculation if vi["INCAR"].get("ALGO", "Normal") in ["Fast", "VeryFast"]: actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Normal" } } }) else: potim = float(vi["INCAR"].get("POTIM", 0.5)) / 2.0 actions.append({ "dict": "INCAR", "action": { "_set": { "POTIM": potim } } }) if vi["INCAR"].get("ICHARG", 0) < 10: actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "file": "WAVECAR", "action": { "_file_delete": { 'mode': "actual" } } }) if "edddav" in self.errors: if vi["INCAR"].get("ICHARG", 0) < 10: actions.append({ "file": "CHGCAR", "action": { "_file_delete": { 'mode': "actual" } } }) actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "All" } } }) if "grad_not_orth" in self.errors: if vi["INCAR"].get("ISMEAR", 1) < 0: actions.append({ "dict": "INCAR", "action": { "_set": { "ISMEAR": "0" } } }) if "zheev" in self.errors: if vi["INCAR"].get("ALGO", "Fast").lower() != "exact": actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Exact" } } }) if "elf_kpar" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"KPAR": 1}}}) if "rhosyg" in self.errors: if vi["INCAR"].get("SYMPREC", 1e-4) == 1e-4: actions.append({ "dict": "INCAR", "action": { "_set": { "ISYM": 0 } } }) actions.append({ "dict": "INCAR", "action": { "_set": { "SYMPREC": 1e-4 } } }) if "posmap" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "SYMPREC": 1e-6 } } }) if "point_group" in self.errors: actions.append({"dict": "INCAR", "action": {"_set": {"ISYM": 0}}}) ViseVaspModder(vi=vi).apply_actions(actions) return {"errors": list(self.errors), "actions": actions}
def create_SNL(dirbase, molecules, atoms, spc_present, num_each_spc, struct, s): layers = len(molecules) with MPRester("sm5RbuEp83T9Wo7P") as m: first_mol = struct[0] mono_or_homo = 0 #if system is a monolayer or homogeneous use its proper .cif file, else use generic WTe2 for heterostructures if (layers == 1) or all(x == first_mol for x in struct): mono_or_homo = 1 if (first_mol == molec[0]): structure = m.get_structure_by_material_id("mp-2815") #MoS2 ref = m.get_materials_id_references("mp-2815") r1 = np.array([0, 2, 4]) elif (first_mol == molec[1]): structure = m.get_structure_by_material_id("mp-1634") #MoSe2 ref = m.get_materials_id_references("mp-1634") r1 = np.array([0, 2, 4]) elif (first_mol == molec[2]): structure = m.get_structure_by_material_id("mp-602") #MoTe2 ref = m.get_materials_id_references("mp-602") r1 = np.array([1, 2, 5]) elif (first_mol == molec[3]): structure = m.get_structure_by_material_id("mp-224") #WS2 ref = m.get_materials_id_references("mp-224") r1 = np.array([0, 3, 5]) elif (first_mol == molec[4]): structure = m.get_structure_by_material_id("mp-1821") #WSe2 ref = m.get_materials_id_references("mp-1821") r1 = np.array([0, 2, 4]) elif (first_mol == molec[5]): structure = m.get_structure_by_material_id("mp-1019322") #WTe2 ref = m.get_materials_id_references("mp-1019322") r1 = np.array([0, 3, 5]) else: structure = m.get_structure_by_material_id("mp-1019322") #WTe2 ref = m.get_materials_id_references("mp-1019322") r1 = np.array([0, 3, 5]) # initialize history history = [] #half the height of original unit cell...to be used for vacuum length calculation later halfz = (structure.lattice.c) / 2 #make supercell if necessary levels = layers if (levels % 2 == 1): levels = levels + 1 tsuper = SupercellTransformation([[1, 0, 0], [0, 1, 0], [0, 0, (levels) / 2]]) history.append(history_node(tsuper)) supercell = tsuper.apply_transformation(structure) #make species replacements for heterostructures with more than one layer levels = layers if (levels % 2 == 1): levels = levels + 1 #if heterostructure has more than one layer: if (mono_or_homo == 0): for i in range(0, len(molecules)): if (molecules[i] == 5): continue else: TMspc = elems[atoms[2 * i]] TMloc = (levels * 2) + (i % 2) * (levels / 2) + int( np.floor((i) / 2)) DCspc = elems[atoms[2 * i + 1]] DCloc1 = (levels - (levels / 2)) - i % 2 * (levels / 2) + int( np.floor((i) / 2)) DCloc2 = levels + i % 2 * (levels / 2) + int( np.floor((i) / 2)) t1 = ReplaceSiteSpeciesTransformation({TMloc: TMspc}) t2 = ReplaceSiteSpeciesTransformation({DCloc1: DCspc}) t3 = ReplaceSiteSpeciesTransformation({DCloc2: DCspc}) history.append(history_node(t1)) history.append(history_node(t2)) history.append(history_node(t3)) supercell = t1.apply_transformation(supercell) supercell = t2.apply_transformation(supercell) supercell = t3.apply_transformation(supercell) #remove top layer of atom if necessary mult_factor = (layers + 1) / 2 - 1 r = r1 + (r1 + 1) * mult_factor tremove = RemoveSitesTransformation(r) if (layers % 2 == 1): supercell = tremove.apply_transformation(supercell) history.append(history_node(tremove)) #sort structure supercell = supercell.get_sorted_structure() #extend z-axis cell vector to add vaccuum to supercell vacuum = 10.0 old_lattice = supercell.lattice if (layers % 2 == 1): new_c = old_lattice.c - halfz + vacuum else: new_c = old_lattice.c + vacuum new_lattice = Lattice.from_parameters(old_lattice.a, old_lattice.b, new_c, old_lattice.alpha, old_lattice.beta, old_lattice.gamma) final_structure = Structure( new_lattice, supercell.species, supercell.frac_coords * np.array([1., 1., (old_lattice.c / new_lattice.c)]), coords_are_cartesian=False) hnode = { 'name': 'add vaccuum', 'url': '', 'description': 'increase z-direction cell vector by 10 angstroms' } history.append(hnode) #creat final SNL authors = [{"name": "Lindsay Bassman", "email": "*****@*****.**"}] projects = ["TMDC-Heterostructures"] remarks = [ "MAGICS calculation of band structures of 2D TMDC stacked heterostructures" ] final_snl = StructureNL(final_structure, authors, projects=projects, remarks=remarks, references=ref, history=history) #optionally write POSCAR file poscar = Poscar(final_structure, s) poscar.write_file(dirbase + "POSCAR", direct=False)