def setup(self): """ Performs initial setup for VaspJob, including overriding any settings and backing up. """ decompress_dir('.') if self.backup: for f in VASP_INPUT_FILES: shutil.copy(f, "{}.orig".format(f)) if self.auto_npar: try: incar = Incar.from_file("INCAR") # Only optimized NPAR for non-HF and non-RPA calculations. if not (incar.get("LHFCALC") or incar.get("LRPA") or incar.get("LEPSILON")): if incar.get("IBRION") in [5, 6, 7, 8]: # NPAR should not be set for Hessian matrix # calculations, whether in DFPT or otherwise. del incar["NPAR"] else: import multiprocessing # try sge environment variable first # (since multiprocessing counts cores on the current # machine only) ncores = os.environ.get('NSLOTS') or \ multiprocessing.cpu_count() ncores = int(ncores) for npar in range(int(math.sqrt(ncores)), ncores): if ncores % npar == 0: incar["NPAR"] = npar break incar.write_file("INCAR") except: pass if self.auto_continue: if os.path.exists("continue.json"): actions = loadfn("continue.json").get("actions") logger.info("Continuing previous VaspJob. Actions: {}".format(actions)) backup(VASP_BACKUP_FILES, prefix="prev_run") VaspModder().apply_actions(actions) else: # Default functionality is to copy CONTCAR to POSCAR and set # ISTART to 1 in the INCAR, but other actions can be specified if self.auto_continue is True: actions = [{"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}, {"dict": "INCAR", "action": {"_set": {"ISTART": 1}}}] else: actions = self.auto_continue dumpfn({"actions": actions}, "continue.json") if self.settings_override is not None: VaspModder().apply_actions(self.settings_override)
def correct(self): backup(VASP_BACKUP_FILES) vi = VaspInput.from_directory(".") potim = float(vi["INCAR"].get("POTIM", 0.5)) ibrion = int(vi["INCAR"].get("IBRION", 0)) if potim < 0.2 and ibrion != 3: actions = [{ "dict": "INCAR", "action": { "_set": { "IBRION": 3, "SMASS": 0.75 } } }] else: actions = [{ "dict": "INCAR", "action": { "_set": { "POTIM": potim * 0.5 } } }] VaspModder(vi=vi).apply_actions(actions) return {"errors": ["POTIM"], "actions": actions}
def correct(self): backup(VASP_BACKUP_FILES) actions = [] vi = VaspInput.from_directory(".") incar = vi["INCAR"] outcar = Outcar("OUTCAR") # Move CONTCAR to POSCAR actions.append({"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}) # First try adding ADDGRID if not incar.get("ADDGRID", False) : actions.append({"dict": "INCAR", "action": {"_set": {"ADDGRID": True}}}) # Otherwise set PREC to High so ENAUG can be used to control Augmentation Grid Size elif incar.get("PREC", "Accurate").lower() != "high": actions.append({"dict": "INCAR", "action": {"_set": {"PREC": "High"}}}) actions.append({"dict": "INCAR", "action": {"_set": {"ENAUG": incar.get("ENCUT", 520) * 2}}}) # PREC is already high and ENAUG set so just increase it else: actions.append({"dict": "INCAR", "action": {"_set": {"ENAUG": int(incar.get("ENAUG", 1040) * self.enaug_multiply)}}}) curr_drift = outcar.data.get("drift", [])[::-1][:self.to_average] curr_drift = np.average([np.linalg.norm(d) for d in curr_drift]) VaspModder(vi=vi).apply_actions(actions) return {"errors": "Excessive drift {} > {}".format(curr_drift, self.max_drift), "actions": actions}
def test_seg_fault(self): vi = VaspInput.from_directory(".") from custodian.vasp.interpreter import VaspModder VaspModder(vi=vi).apply_actions([{ "dict": "INCAR", "action": { "_set": { "KPAR": 4 } } }]) h = StdErrHandler("std_err.txt.seg_fault", correct_seg_fault=True) self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['seg_fault']) self.assertEqual(d["actions"], [{ 'dict': 'INCAR', 'action': { '_set': { 'ISMEAR': '0' } } }]) self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['seg_fault']) # no fix if still seg fault self.assertEqual(d["actions"], [])
def setup(self): """ Performs initial setup for VaspNEBJob, including overriding any settings and backing up. """ neb_dirs = self.neb_dirs if self.backup: # Back up KPOINTS, INCAR, POTCAR for f in VASP_NEB_INPUT_FILES: shutil.copy(f, "{}.orig".format(f)) # Back up POSCARs for path in neb_dirs: poscar = os.path.join(path, "POSCAR") shutil.copy(poscar, "{}.orig".format(poscar)) if self.half_kpts and os.path.exists("KPOINTS"): kpts = Kpoints.from_file("KPOINTS") kpts.kpts = np.maximum(np.array(kpts.kpts) / 2, 1) kpts.kpts = kpts.kpts.astype(int).tolist() if tuple(kpts.kpts[0]) == (1, 1, 1): kpt_dic = kpts.as_dict() kpt_dic["generation_style"] = 'Gamma' kpts = Kpoints.from_dict(kpt_dic) kpts.write_file("KPOINTS") if self.auto_npar: try: incar = Incar.from_file("INCAR") import multiprocessing # Try sge environment variable first # (since multiprocessing counts cores on the current # machine only) ncores = os.environ.get( 'NSLOTS') or multiprocessing.cpu_count() ncores = int(ncores) for npar in range(int(math.sqrt(ncores)), ncores): if ncores % npar == 0: incar["NPAR"] = npar break incar.write_file("INCAR") except: pass if self.auto_continue and \ os.path.exists("STOPCAR") and \ not os.access("STOPCAR", os.W_OK): # Remove STOPCAR os.chmod("STOPCAR", 0o644) os.remove("STOPCAR") # Copy CONTCAR to POSCAR for path in self.neb_sub: contcar = os.path.join(path, "CONTCAR") poscar = os.path.join(path, "POSCAR") shutil.copy(contcar, poscar) if self.settings_override is not None: VaspModder().apply_actions(self.settings_override)
def setup(self): """ Method is identical to custodian.vasp.jobs.setup(), except that the environment variable PBS_NUM_PPN is checked first when auto_npar = True. """ files = os.listdir(".") num_structures = 0 if not set(files).issuperset(VASP_INPUT_FILES): for f in files: try: struct = read_structure(f) num_structures += 1 except: pass if num_structures != 1: raise RuntimeError( "{} structures found. Unable to continue.".format( num_structures)) else: self.default_vis.write_input(struct, ".") if self.backup: for f in VASP_INPUT_FILES: shutil.copy(f, "{}.orig".format(f)) if self.auto_npar: try: incar = Incar.from_file("INCAR") # Only optimized NPAR for non-HF and non-RPA calculations. if not (incar.get("LHFCALC") or incar.get("LRPA") or incar.get("LEPSILON")): if incar.get("IBRION") in [5, 6, 7, 8]: # NPAR should not be set for Hessian matrix # calculations, whether in DFPT or otherwise. del incar["NPAR"] else: import multiprocessing # try pbs environment variable first # try sge environment variable second # Note! # multiprocessing.cpu_count() will include hyperthreads # in the CPU count, which will set NPAR to be too large # and can cause the job to hang if you use compute # nodes with scratch partitions. ncores = (os.environ.get("PBS_NUM_PPN") or os.environ.get('NSLOTS') or multiprocessing.cpu_count()) ncores = int(ncores) for npar in range(int(math.sqrt(ncores)), ncores): if ncores % npar == 0: incar["NPAR"] = npar break incar.write_file("INCAR") except: pass if self.settings_override is not None: VaspModder().apply_actions(self.settings_override)
def correct(self): # if change_algo is True, change ALGO = Fast to Normal if ALGO is # Fast. If still not converging, following Kresse's # recommendation, we will try two iterations of different mixing # parameters. If this error is caught again, then kil the job vi = VaspInput.from_directory(".") algo = vi["INCAR"].get("ALGO", "Normal") amix = vi["INCAR"].get("AMIX", 0.4) bmix = vi["INCAR"].get("BMIX", 1.0) amin = vi["INCAR"].get("AMIN", 0.1) actions = [] if self.change_algo: if algo == "Fast": backup(VASP_BACKUP_FILES) actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Normal" } } }) elif amix > 0.1 and bmix > 0.01: #try linear mixing backup(VASP_BACKUP_FILES) actions.append({ "dict": "INCAR", "action": { "_set": { "AMIX": 0.1, "BMIX": 0.01, "ICHARG": 2 } } }) elif bmix < 3.0 and amin > 0.01: #Try increasing bmix backup(VASP_BACKUP_FILES) actions.append({ "dict": "INCAR", "action": { "_set": { "AMIN": 0.01, "BMIX": 3.0, "ICHARG": 2 } } }) if actions: VaspModder(vi=vi).apply_actions(actions) return {"errors": ["Non-converging job"], "actions": actions} #Unfixable error. Just return None for actions. else: return {"errors": ["Non-converging job"], "actions": None}
def correct(self): backup(VASP_BACKUP_FILES | {self.output_filename}) vi = VaspInput.from_directory(".") m = reduce(operator.mul, vi["KPOINTS"].kpts[0]) m = max(int(round(m ** (1 / 3))), 1) if vi["KPOINTS"].style.name.lower().startswith("m"): m += m % 2 actions = [{"dict": "KPOINTS", "action": {"_set": {"kpoints": [[m] * 3]}}}] VaspModder(vi=vi).apply_actions(actions) return {"errors": ["mesh_symmetry"], "actions": actions}
def setup(self): """ Performs initial setup for VaspJob, including overriding any settings and backing up. """ if self.backup: for f in VASP_INPUT_FILES: shutil.copy(f, "{}.orig".format(f)) if self.auto_npar: try: incar = Incar.from_file("INCAR") # Only optimized NPAR for non-HF and non-RPA calculations. if not (incar.get("LHFCALC") or incar.get("LRPA") or incar.get("LEPSILON")): if incar.get("IBRION") in [5, 6, 7, 8]: # NPAR should not be set for Hessian matrix # calculations, whether in DFPT or otherwise. del incar["NPAR"] else: import multiprocessing # try sge environment variable first # (since multiprocessing counts cores on the current # machine only) ncores = os.environ.get('NSLOTS') or \ multiprocessing.cpu_count() ncores = int(ncores) for npar in range(int(math.sqrt(ncores)), ncores): if ncores % npar == 0: incar["NPAR"] = npar break incar.write_file("INCAR") except: pass # Auto continue if a read-only STOPCAR is present if self.auto_continue and \ os.path.exists("STOPCAR") and \ not os.access("STOPCAR", os.W_OK): # Remove STOPCAR os.chmod("STOPCAR", 0o644) os.remove("STOPCAR") # Setup INCAR to continue incar = Incar.from_file("INCAR") incar['ISTART'] = 1 incar.write_file("INCAR") shutil.copy('CONTCAR', 'POSCAR') if self.settings_override is not None: VaspModder().apply_actions(self.settings_override)
def setup(self): """ Performs initial setup for VaspJob, including overriding any settings and backing up. """ files = os.listdir(".") num_structures = 0 if not set(files).issuperset(VASP_INPUT_FILES): for f in files: try: struct = read_structure(f) num_structures += 1 except: pass if num_structures != 1: raise RuntimeError( "{} structures found. Unable to continue.".format( num_structures)) else: self.default_vis.write_input(struct, ".") if self.backup: for f in VASP_INPUT_FILES: shutil.copy(f, "{}.orig".format(f)) if self.auto_npar: try: incar = Incar.from_file("INCAR") #Only optimized NPAR for non-HF and non-RPA calculations. if not (incar.get("LHFCALC") or incar.get("LRPA") or incar.get("LEPSILON")): if incar.get("IBRION") in [5, 6, 7, 8]: # NPAR should not be set for Hessian matrix # calculations, whether in DFPT or otherwise. del incar["NPAR"] else: import multiprocessing # try sge environment variable first # (since multiprocessing counts cores on the current machine only) ncores = os.environ.get( 'NSLOTS') or multiprocessing.cpu_count() ncores = int(ncores) for npar in range(int(round(math.sqrt(ncores))), ncores): if ncores % npar == 0: incar["NPAR"] = npar break incar.write_file("INCAR") except: pass if self.settings_override is not None: VaspModder().apply_actions(self.settings_override)
def correct(self): backup(VASP_BACKUP_FILES | {self.output_filename}) vi = VaspInput.from_directory('.') actions = [] if vi["INCAR"].get("ALGO", "Normal") == "Fast": actions.append({"dict": "INCAR", "action": {"_set": {"ALGO": "Normal"}}}) VaspModder(vi=vi).apply_actions(actions) return {"errors": ["Frozen job"], "actions": actions}
def correct(self): backup(VASP_BACKUP_FILES | {self.output_filename}) vi = VaspInput.from_directory(".") ediff = float(vi["INCAR"].get("EDIFF", 1e-4)) ediffg = float(vi["INCAR"].get("EDIFFG", ediff * 10)) actions = [{"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}, {"dict": "INCAR", "action": {"_set": {"EDIFFG": ediffg * 0.5}}}] VaspModder(vi=vi).apply_actions(actions) return {"errors": ["MaxForce"], "actions": actions}
def test_oom(self): vi = VaspInput.from_directory(".") from custodian.vasp.interpreter import VaspModder VaspModder(vi=vi).apply_actions([{"dict": "INCAR", "action": {"_set": {"KPAR": 4}}}]) h = StdErrHandler("std_err.txt.oom") self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['out_of_memory']) self.assertEqual(d["actions"], [{'dict': 'INCAR', 'action': {'_set': {'KPAR': 2}}}])
def correct(self): backup(VASP_BACKUP_FILES) actions = [{"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}, {"dict": "INCAR", "action": {"_set": {"ISTART": 1, "ALGO": "Normal", "NELMDL": -6, "BMIX": 0.001, "AMIX_MAG": 0.8, "BMIX_MAG": 0.001}}}] VaspModder().apply_actions(actions) return {"errors": ["Unconverged"], "actions": actions}
def correct(self): # change ALGO = Fast to Normal if ALGO is !Normal vi = VaspInput.from_directory(".") algo = vi["INCAR"].get("ALGO", "Normal") if algo.lower() not in ['normal', 'n']: backup(VASP_BACKUP_FILES) actions = [{"dict": "INCAR", "action": {"_set": {"ALGO": "Normal"}}}] VaspModder(vi=vi).apply_actions(actions) return {"errors": ["Positive energy"], "actions": actions} # Unfixable error. Just return None for actions. else: return {"errors": ["Positive energy"], "actions": None}
def correct(self): backup(VASP_BACKUP_FILES | {self.output_filename}) actions = [] vi = VaspInput.from_directory(".") if "lrf_comm" in self.errors: if Outcar(zpath(os.path.join( os.getcwd(), "OUTCAR"))).is_stopped is False: if not vi["INCAR"].get("LPEAD"): actions.append({"dict": "INCAR", "action": {"_set": {"LPEAD": True}}}) 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 "subspacematrix" in self.errors: actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "All" } } }) VaspModder(vi=vi).apply_actions(actions) return {"errors": list(self.errors), "actions": actions}
def correct(self): backup(VASP_BACKUP_FILES) v = Vasprun(self.output_filename) actions = [{"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}] if not v.converged_electronic: actions.append({"dict": "INCAR", "action": {"_set": {"ISTART": 1, "ALGO": "Normal", "NELMDL": -6, "BMIX": 0.001, "AMIX_MAG": 0.8, "BMIX_MAG": 0.001}}}) if not v.converged_ionic: actions.append({"dict": "INCAR", "action": {"_set": {"IBRION":1}}}) VaspModder().apply_actions(actions) return {"errors": ["Unconverged"], "actions": actions}
def correct(self): backup(VASP_BACKUP_FILES | {self.output_filename}) actions = [] vi = VaspInput.from_directory(".") if "aliasing" in self.errors: with open("OUTCAR") as f: grid_adjusted = False changes_dict = {} r = re.compile(".+aliasing errors.*(NG.)\s*to\s*(\d+)") for line in f: m = r.match(line) if m: changes_dict[m.group(1)] = int(m.group(2)) grid_adjusted = True # Ensure that all NGX, NGY, NGZ have been checked if grid_adjusted and 'NGZ' in line: actions.append( {"dict": "INCAR", "action": {"_set": changes_dict}}) if vi["INCAR"].get("ICHARG", 0) < 10: actions.extend([{"file": "CHGCAR", "action": {"_file_delete": { 'mode': "actual"}}}, {"file": "WAVECAR", "action": {"_file_delete": { 'mode': "actual"}}}]) break if "aliasing_incar" in self.errors: # vasp seems to give different warnings depending on whether the # aliasing error was caused by user supplied inputs d = {k: 1 for k in ['NGX', 'NGY', 'NGZ'] if k in vi['INCAR'].keys()} actions.append({"dict": "INCAR", "action": {"_unset": d}}) if vi["INCAR"].get("ICHARG", 0) < 10: actions.extend([{"file": "CHGCAR", "action": { "_file_delete": {'mode': "actual"}}}, {"file": "WAVECAR", "action": { "_file_delete": {'mode': "actual"}}}]) 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 we encounter a DAV Sub-Space-Matrix error if "subspacematrix" or "edddav" in self.errors: # Switch to the CG algorithm actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "All" } } }) # If we encounter a ZBRENT error if "zbrent" in self.errors: # Switch to Quasi-Newton algorithm actions.append({ "dict": "INCAR", "action": { "_set": { "IBRION": 1 } } }) # Move CONTCAR to POSCAR actions.append({ "file": "CONTCAR", "action": { "_file_copy": { "dest": "POSCAR" } } }) 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 "lrf_comm" in self.errors: if self.error_count['lrf_comm'] == 0: if Outcar(zpath(os.path.join(os.getcwd(), "OUTCAR"))).is_stopped is False: # simply rerun the job and increment # error count for next time actions.append({ "dict": "INCAR", "action": { "_set": { "ISTART": 1 } } }) self.error_count['lrf_comm'] += 1 if "kpoints_trans" in self.errors: if self.error_count["kpoints_trans"] == 0: m = reduce(operator.mul, vi["KPOINTS"].kpts[0]) m = max(int(round(m**(1 / 3))), 1) if vi["KPOINTS"].style.name.lower().startswith("m"): m += m % 2 actions.append({ "dict": "KPOINTS", "action": { "_set": { "kpoints": [[m] * 3] } } }) self.error_count['kpoints_trans'] += 1 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 "kpoints_trans" in self.errors: if self.error_count["kpoints_trans"] == 0: m = reduce(operator.mul, vi["KPOINTS"].kpts[0]) m = max(int(round(m ** (1 / 3))), 1) if vi["KPOINTS"].style.name.lower().startswith("m"): m += m % 2 actions.append({"dict": "KPOINTS", "action": {"_set": {"kpoints": [[m] * 3]}}}) self.error_count['kpoints_trans'] += 1 if "out_of_memory" in self.errors: if vi["INCAR"].get("KPAR", 1) > 1: reduced_kpar = max(vi["INCAR"].get("KPAR", 1) // 2, 1) actions.append({"dict": "INCAR", "action": {"_set": {"KPAR": reduced_kpar}}}) VaspModder(vi=vi).apply_actions(actions) return {"errors": list(self.errors), "actions": actions}
def correct(self): backup(VASP_BACKUP_FILES) v = Vasprun(self.output_filename) actions = [{"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}] if not v.converged_electronic: new_settings = {"ISTART": 1, "ALGO": "Normal", "NELMDL": -6, "BMIX": 0.001, "AMIX_MAG": 0.8, "BMIX_MAG": 0.001} if all([v.incar.get(k,"") == val for k,val in new_settings.items()]): return {"errors": ["Unconverged"], "actions": None} actions.append({"dict": "INCAR", "action": {"_set": new_settings}}) if not v.converged_ionic: actions.append({"dict": "INCAR", "action": {"_set": {"IBRION": 1}}}) VaspModder().apply_actions(actions) return {"errors": ["Unconverged"], "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 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): vi = VaspInput.from_directory(".") algo = vi["INCAR"].get("ALGO", "Normal") amix = vi["INCAR"].get("AMIX", 0.4) bmix = vi["INCAR"].get("BMIX", 1.0) amin = vi["INCAR"].get("AMIN", 0.1) actions = [] # Ladder from VeryFast to Fast to Fast to All # These progressively switches to more stable but more # expensive algorithms if algo == "VeryFast": actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Fast" } } }) elif algo == "Fast": actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "Normal" } } }) elif algo == "Normal": actions.append({ "dict": "INCAR", "action": { "_set": { "ALGO": "All" } } }) elif amix > 0.1 and bmix > 0.01: # Try linear mixing actions.append({ "dict": "INCAR", "action": { "_set": { "AMIX": 0.1, "BMIX": 0.01, "ICHARG": 2 } } }) elif bmix < 3.0 and amin > 0.01: # Try increasing bmix actions.append({ "dict": "INCAR", "action": { "_set": { "AMIN": 0.01, "BMIX": 3.0, "ICHARG": 2 } } }) if actions: backup(VASP_BACKUP_FILES) VaspModder(vi=vi).apply_actions(actions) return {"errors": ["Non-converging job"], "actions": actions} # Unfixable error. Just return None for actions. else: return {"errors": ["Non-converging job"], "actions": None}
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}