def test_brmix(self): h = VaspErrorHandler("vasp.brmix") self.assertEqual(h.check(), True) # The first (no good OUTCAR) correction, check IMIX d = h.correct() self.assertEqual(d["errors"], ['brmix']) vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["IMIX"], 1) self.assertTrue(os.path.exists("CHGCAR")) # The next correction check Gamma and evenize h.correct() vi = VaspInput.from_directory(".") self.assertFalse("IMIX" in vi["INCAR"]) self.assertTrue(os.path.exists("CHGCAR")) if vi["KPOINTS"].style == Kpoints.supported_modes.Gamma and vi["KPOINTS"].num_kpts < 1: all_kpts_even = all([ bool(n % 2 == 0) for n in vi["KPOINTS"].kpts[0] ]) self.assertFalse(all_kpts_even) # The next correction check ISYM and no CHGCAR h.correct() vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["ISYM"], 0) self.assertFalse(os.path.exists("CHGCAR")) shutil.copy("INCAR.nelect", "INCAR") h = VaspErrorHandler("vasp.brmix") self.assertEqual(h.check(), False) d = h.correct() self.assertEqual(d["errors"], [])
def test_check_correct(self): h = VaspErrorHandler("vasp.teterror") h.check() d = h.correct() self.assertEqual(d["errors"], ['tet']) self.assertEqual(d["actions"], [{ 'action': { '_set': { 'ISMEAR': 0, 'SIGMA': 0.05 } }, 'dict': 'INCAR' }]) h = VaspErrorHandler("vasp.teterror", errors_subset_to_catch=["eddrmm"]) self.assertFalse(h.check()) h = VaspErrorHandler("vasp.sgrcon") h.check() d = h.correct() self.assertEqual(d["errors"], ['rot_matrix']) self.assertEqual(set([a["dict"] for a in d["actions"]]), {"KPOINTS"}) h = VaspErrorHandler("vasp.real_optlay") h.check() d = h.correct() self.assertEqual(d["errors"], ['real_optlay']) self.assertEqual(d["actions"], [{ 'action': { '_set': { 'LREAL': False } }, 'dict': 'INCAR' }]) subdir = os.path.join(test_dir, "large_cell_real_optlay") os.chdir(subdir) shutil.copy("INCAR", "INCAR.orig") h = VaspErrorHandler() h.check() d = h.correct() self.assertEqual(d["errors"], ['real_optlay']) vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["LREAL"], True) h.check() d = h.correct() self.assertEqual(d["errors"], ['real_optlay']) vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["LREAL"], False) shutil.copy("INCAR.orig", "INCAR") os.remove("INCAR.orig") os.remove("error.1.tar.gz") os.remove("error.2.tar.gz") os.chdir(test_dir)
def test_lrf_comm(self): h = LrfCommutatorHandler("std_err.txt") self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['lrf_comm']) vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["LPEAD"], True)
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 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 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): # 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 load(cls, filename, Cls=None): with open(filename, 'r') as f: fc = f.read() jc = json.loads(fc) composition = jc['composition'] calculator = jc['calculator'] if calculator.lower() == 'vasp': try: inputs = VaspInput.from_dict(jc['inputs']).as_dict() except: inputs = jc['inputs'] warnings.warn("""Inproperly configure of POTCAR ! Returned instance cannot be used as input for from_dict() method """) else: if Cls: inputs = Cls.from_dict(jc['inputs']).as_dict() else: raise RuntimeError("inputs decoder must be given") data = LabeledSystem.from_dict(jc['data']).as_dict() attribute = jc['attribute'] entry_id = jc['entry_id'] tag = jc['tag'] return cls(composition, calculator, inputs, data, entry_id, attribute, tag)
def get_runs(vasp_command, target=1e-3, max_steps=10, mode="linear"): energy = 0 vinput = VaspInput.from_directory(".") kpoints = vinput["KPOINTS"].kpts[0] for i in range(max_steps): if mode == "linear": m = [k * (i + 1) for k in kpoints] else: m = [k + 1 for k in kpoints] if i == 0: settings = None backup = True else: backup = False v = Vasprun("vasprun.xml") e_per_atom = v.final_energy / len(v.final_structure) ediff = abs(e_per_atom - energy) if ediff < target: logging.info("Converged to {} eV/atom!".format(ediff)) break else: energy = e_per_atom settings = [ {"dict": "INCAR", "action": {"_set": {"ISTART": 1}}}, {'dict': 'KPOINTS', 'action': {'_set': {'kpoints': [m]}}}, {"filename": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}] yield VaspJob(vasp_command, final=False, backup=backup, suffix=".kpoints.{}".format("x".join(map(str, m))), settings_override=settings)
def check(self): msg = "Reciprocal lattice and k-lattice belong to different class of" \ " lattices." vi = VaspInput.from_directory('.') # According to VASP admins, you can disregard this error # if symmetry is off # Also disregard if automatic KPOINT generation is used if (not vi["INCAR"].get('ISYM', True)) or \ vi[ "KPOINTS"].style == Kpoints.supported_modes.Automatic: return False try: v = Vasprun(self.output_vasprun) if v.converged: return False except: pass with open(self.output_filename, "r") as f: for line in f: l = line.strip() if l.find(msg) != -1: return True return False
def test_check_correct(self): h = VaspErrorHandler("vasp.teterror") h.check() d = h.correct() self.assertEqual(d["errors"], ['tet']) self.assertEqual(d["actions"], [{'action': {'_set': {'ISMEAR': 0}}, 'dict': 'INCAR'}]) h = VaspErrorHandler("vasp.teterror", errors_subset_to_catch=["eddrmm"]) self.assertFalse(h.check()) h = VaspErrorHandler("vasp.sgrcon") h.check() d = h.correct() self.assertEqual(d["errors"], ['rot_matrix']) self.assertEqual(set([a["dict"] for a in d["actions"]]), {"KPOINTS"}) h = VaspErrorHandler("vasp.real_optlay") h.check() d = h.correct() self.assertEqual(d["errors"], ['real_optlay']) self.assertEqual(d["actions"], [{'action': {'_set': {'LREAL': False}}, 'dict': 'INCAR'}]) subdir = os.path.join(test_dir, "large_cell_real_optlay") os.chdir(subdir) shutil.copy("INCAR", "INCAR.orig") h = VaspErrorHandler() h.check() d = h.correct() self.assertEqual(d["errors"], ['real_optlay']) vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["LREAL"], True) h.check() d = h.correct() self.assertEqual(d["errors"], ['real_optlay']) vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["LREAL"], False) shutil.copy("INCAR.orig", "INCAR") os.remove("INCAR.orig") os.remove("error.1.tar.gz") os.remove("error.2.tar.gz") os.chdir(test_dir)
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 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", correct_out_of_memory=True) 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}}}]) h = StdErrHandler("std_err.txt.oom2", correct_out_of_memory=True) self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['out_of_memory']) self.assertEqual(d["actions"], [{'dict': 'INCAR', 'action': {'_set': {'KPAR': 1}}}]) 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.emlsp", correct_out_of_memory=True) 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}}}]) 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.insufficient_mem", correct_out_of_memory=True) 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 | {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.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 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(".") 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 check(self): vi = VaspInput.from_directory(".") nelm = vi["INCAR"].get("NELM", 60) try: oszicar = Oszicar(self.output_filename) esteps = oszicar.electronic_steps if len(esteps) > self.nionic_steps: return all([len(e) == nelm for e in esteps[-(self.nionic_steps + 1) : -1]]) except: pass return False
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 test_lrf_comm(self): h = StdErrHandler("std_err.txt") self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['lrf_comm']) vi = VaspInput.from_directory(".") self.assertEqual(vi["INCAR"]["ISTART"], 1) self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['lrf_comm']) self.assertEqual(d["actions"], []) # don't correct twice
def check(self): vi = VaspInput.from_directory(".") nelm = vi["INCAR"].get("NELM", 60) try: oszicar = Oszicar(self.output_filename) esteps = oszicar.electronic_steps if len(esteps) > self.nionic_steps: return all([len(e) == nelm for e in esteps[-(self.nionic_steps + 1):-1]]) except: pass return False
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 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) 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 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 | {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 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 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 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 test(): from monty.serialization import dumpfn, loadfn from monty.json import MontyDecoder, MontyEncoder from pymatgen.io.vasp.inputs import PotcarSingle, Potcar vi = VaspInput.from_directory('.') ls = LabeledSystem('OUTCAR', fmt='vasp/outcar') en0 = Entry('Al', 'vasp', inputs=vi.as_dict(), data=ls.as_dict(), entry_id='pku-1') print(en0) fname = 'pku-1.json' dumpfn(en0.as_dict(), fname, indent=4) en1 = Entry.load(fname) #vin=VaspInput.from_dict(en1.inputs) #vin.write_input('./new') print(en1) print(en1.as_dict())
def __init__(self, actions=None, strict=True, vi=None): """ Initializes a Modder for VaspInput sets Args: actions ([Action]): A sequence of supported actions. See :mod:`custodian.ansible.actions`. Default is None, which means DictActions and FileActions are supported. strict (bool): Indicating whether to use strict mode. In non-strict mode, unsupported actions are simply ignored without any errors raised. In strict mode, if an unsupported action is supplied, a ValueError is raised. Defaults to True. vi (VaspInput): A VaspInput object from the current directory. Initialized automatically if not passed (but passing it will avoid having to reparse the directory). """ self.vi = vi or VaspInput.from_directory('.') actions = actions or [FileActions, DictActions] super(VaspModder, self).__init__(actions, strict)
def run(self): """ Perform the actual VASP run. Returns: (subprocess.Popen) Used for monitoring. """ cmd = list(self.vasp_cmd) if self.auto_gamma: vi = VaspInput.from_directory(".") kpts = vi["KPOINTS"] if kpts.style == "Gamma" and tuple(kpts.kpts[0]) == (1, 1, 1): if self.gamma_vasp_cmd is not None and which( self.gamma_vasp_cmd[-1]): cmd = self.gamma_vasp_cmd elif which(cmd[-1] + ".gamma"): cmd[-1] += ".gamma" logging.info("Running {}".format(" ".join(cmd))) with open(self.output_file, 'w') as f: p = subprocess.Popen(cmd, stdout=f) return p
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 test_brmix(self): h = VaspErrorHandler("vasp.brmix") self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['brmix']) vi = VaspInput.from_directory(".") chgcar_exists = os.path.exists("CHGCAR") if h.error_count['brmix'] > 1: self.assertFalse(chgcar_exists) else: self.assertTrue(chgcar_exists) if vi["KPOINTS"].style == Kpoints.supported_modes.Gamma and vi["KPOINTS"].num_kpts < 1: all_kpts_even = all([ bool(n % 2 == 0) for n in vi["KPOINTS"].kpts[0] ]) self.assertFalse(all_kpts_even) shutil.copy("INCAR.nelect", "INCAR") h = VaspErrorHandler("vasp.brmix") self.assertEqual(h.check(), False) d = h.correct() self.assertEqual(d["errors"], [])
def test_brmix(self): h = VaspErrorHandler("vasp.brmix") self.assertEqual(h.check(), True) d = h.correct() self.assertEqual(d["errors"], ['brmix']) vi = VaspInput.from_directory(".") chgcar_exists = os.path.exists("CHGCAR") if h.error_count['brmix'] > 1: self.assertFalse(chgcar_exists) else: self.assertTrue(chgcar_exists) if vi["KPOINTS"].style == Kpoints.supported_modes.Gamma and vi[ "KPOINTS"].num_kpts < 1: all_kpts_even = all( [bool(n % 2 == 0) for n in vi["KPOINTS"].kpts[0]]) self.assertFalse(all_kpts_even) shutil.copy("INCAR.nelect", "INCAR") h = VaspErrorHandler("vasp.brmix") self.assertEqual(h.check(), False) d = h.correct() self.assertEqual(d["errors"], [])
def run(self): """ Perform the actual VASP run. Returns: (subprocess.Popen) Used for monitoring. """ cmd = list(self.vasp_cmd) if self.auto_gamma: vi = VaspInput.from_directory(".") kpts = vi["KPOINTS"] if kpts.style == Kpoints.supported_modes.Gamma \ and tuple(kpts.kpts[0]) == (1, 1, 1): if self.gamma_vasp_cmd is not None and which( self.gamma_vasp_cmd[-1]): cmd = self.gamma_vasp_cmd elif which(cmd[-1] + ".gamma"): cmd[-1] += ".gamma" logger.info("Running {}".format(" ".join(cmd))) with open(self.output_file, 'w') as f_std, \ open(self.stderr_file, "w", buffering=1) as f_err: # use line buffering for stderr p = subprocess.Popen(cmd, stdout=f_std, stderr=f_err) return p
# prepare lattice-gas type representation reps = make_latgas_reps(spec_id=[0, 1, 2], nspec=[1, 4, 1], spec_orient=[1, 2, 1]) energy_reps = np.zeros(len(reps)) # prepare vasp model path_to_vasp = "/home/i0009/i000900/src/vasp.5.3/vasp.spawnready.gamma" solver = VASPSolver(path_to_vasp) vasprun = runner( Solver=solver, nprocs=nprocs_per_vasp, comm=MPI.COMM_SELF, ) baseinput = VaspInput.from_directory( "baseinput") # (os.path.join(os.path.dirname(__file__), "baseinput")) ltol = 0.1 matcher = StructureMatcher(ltol=ltol, primitive_cell=False) matcher_base = StructureMatcher(ltol=ltol, primitive_cell=False, stol=0.5, allow_subset=True) # , # comparator=FrameworkComparator(), ignored_species=["Pt","Zr"]) drone = SimpleVaspToComputedEntryDrone(inc_structure=True) queen = BorgQueen(drone) model = dft_HAp( calcode="VASP", vasp_run=vasprun, base_vaspinput=baseinput, matcher_base=matcher_base, queen=queen,
def get_jobs(args): # Returns a generator of jobs. Allows of "infinite" jobs. vasp_command = args.command.split() # save initial INCAR for rampU runs n_ramp_u = args.jobs.count('rampU') ramps = 0 if n_ramp_u: incar = Incar.from_file('INCAR') ldauu = incar['LDAUU'] ldauj = incar['LDAUJ'] njobs = len(args.jobs) post_settings = [] # append to this list to have settings applied on next job for i, job in enumerate(args.jobs): final = False if i != njobs - 1 else True if any(c.isdigit() for c in job): suffix = "." + job else: suffix = ".{}{}".format(job, i + 1) settings = post_settings post_settings = [] backup = True if i == 0 else False copy_magmom = False vinput = VaspInput.from_directory(".") if i > 0: settings.append( {"file": "CONTCAR", "action": {"_file_copy": {"dest": "POSCAR"}}}) job_type = job.lower() auto_npar = True if args.no_auto_npar: auto_npar = False if job_type.startswith("static_derived"): from pymatgen.io.vasp.sets import MPStaticSet vis = MPStaticSet.from_prev_calc( ".", user_incar_settings={"LWAVE": True, "EDIFF": 1e-6}, ediff_per_atom=False) settings.extend([ {"dict" : "INCAR", "action": {"_set": dict(vis.incar)}}, {'dict': 'KPOINTS', 'action': {'_set': vis.kpoints.as_dict()}}]) if job_type.startswith("static_dielectric_derived"): from pymatgen.io.vasp.sets import MPStaticSet, MPStaticDielectricDFPTVaspInputSet # vis = MPStaticSet.from_prev_calc( # ".", user_incar_settings={"EDIFF": 1e-6, "IBRION": 8, # "LEPSILON": True, 'LREAL':False, # "LPEAD": True, "ISMEAR": 0, # "SIGMA": 0.01}, # ediff_per_atom=False) vis = MPStaticDielectricDFPTVaspInputSet() incar = vis.get_incar(vinput["POSCAR"].structure) unset = {} for k in ["NPAR", "KPOINT_BSE", "LAECHG", "LCHARG", "LVHAR", "NSW"]: incar.pop(k, None) if k in vinput["INCAR"]: unset[k] = 1 kpoints = vis.get_kpoints(vinput["POSCAR"].structure) settings.extend([ {"dict": "INCAR", "action": {"_set": dict(incar), "_unset": unset}}, {'dict': 'KPOINTS', 'action': {'_set': kpoints.as_dict()}}]) auto_npar = False elif job_type.startswith("static"): m = [i * args.static_kpoint for i in vinput["KPOINTS"].kpts[0]] settings.extend([ {"dict": "INCAR", "action": {"_set": {"NSW": 0}}}, {'dict': 'KPOINTS', 'action': {'_set': {'kpoints': [m]}}}]) elif job_type.startswith("nonscf_derived"): from pymatgen.io.vasp.sets import MPNonSCFSet vis = MPNonSCFSet.from_prev_calc(".", copy_chgcar=False, user_incar_settings={"LWAVE": True}) settings.extend([ {"dict": "INCAR", "action": {"_set": dict(vis.incar)}}, {'dict': 'KPOINTS', 'action': {'_set': vis.kpoints.as_dict()}}]) elif job_type.startswith("optics_derived"): from pymatgen.io.vasp.sets import MPNonSCFSet vis = MPNonSCFSet.from_prev_calc( ".", optics=True, copy_chgcar=False, nedos=2001, mode="uniform", nbands_factor=5, user_incar_settings={"LWAVE": True, "ALGO": "Exact", "SIGMA": 0.01, "EDIFF": 1e-6}, ediff_per_atom=False) settings.extend([ {"dict": "INCAR", "action": {"_set": dict(vis.incar)}}, {'dict': 'KPOINTS', 'action': {'_set': vis.kpoints.as_dict()}}]) elif job_type.startswith("rampu"): f = ramps / (n_ramp_u - 1) settings.append( {"dict": "INCAR", "action": {"_set": {"LDAUJ": [j * f for j in ldauj], "LDAUU": [u * f for u in ldauu]}}}) copy_magmom = True ramps += 1 elif job_type.startswith("quick_relax") or job_type.startswith(\ "quickrelax"): kpoints = vinput["KPOINTS"] incar = vinput["INCAR"] structure = vinput["POSCAR"].structure if "ISMEAR" in incar: post_settings.append( {"dict": "INCAR", "action": {"_set": {"ISMEAR": incar["ISMEAR"]}}}) else: post_settings.append( {"dict": "INCAR", "action": {"_unset": {"ISMEAR": 1}}}) post_settings.append({"dict": "KPOINTS", "action": {"_set": kpoints.as_dict()}}) # lattice vectors with length < 9 will get >1 KPOINT low_kpoints = Kpoints.gamma_automatic( [max(int(18/l), 1) for l in structure.lattice.abc]) settings.extend([ {"dict": "INCAR", "action": {"_set": {"ISMEAR": 0}}}, {'dict': 'KPOINTS', 'action': {'_set': low_kpoints.as_dict()}}]) # let vasp determine encut (will be lower than # needed for compatibility with other runs) if "ENCUT" in incar: post_settings.append( {"dict": "INCAR", "action": {"_set": {"ENCUT": incar["ENCUT"]}}}) settings.append( {"dict": "INCAR", "action": {"_unset": {"ENCUT": 1}}}) elif job_type.startswith("relax"): pass elif job_type.startswith("full_relax"): for j in VaspJob.full_opt_run( vasp_command): yield j else: print("Unsupported job type: {}".format(job)) sys.exit(-1) if not job_type.startswith("full_relax"): yield VaspJob(vasp_command, final=final, suffix=suffix, backup=backup, settings_override=settings, copy_magmom=copy_magmom, auto_npar=auto_npar)
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: 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 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 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. 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. 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"]): 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}}}) 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"}}}) 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 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}