def test_input(self): self.solver.input.from_directory( os.path.join(self.datadir, "baseinput")) A = 4.0 * np.eye(3) r = np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]]) st = Structure( A, ["Al", "Al"], r, coords_are_cartesian=False, site_properties={ "seldyn": [[True, True, False], [True, False, True]] }, ) self.solver.input.update_info_by_structure(st) self.solver.input.write_input(self.workdir) res = VaspInput.from_directory(self.workdir) ref = VaspInput.from_directory(os.path.join(self.datadir, "input")) self.assertEqual(res["INCAR"], ref["INCAR"]) self.assertTrue(res["POSCAR"].structure.matches( ref["POSCAR"].structure)) self.assertEqual( res["POSCAR"].structure.site_properties, ref["POSCAR"].structure.site_properties, )
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_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 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 test_from_directory(self): vi = VaspInput.from_directory(test_dir, optional_files={"CONTCAR.Li2O": Poscar}) self.assertEqual(vi["INCAR"]["ALGO"], "Damped") self.assertIn("CONTCAR.Li2O", vi) d = vi.as_dict() vinput = VaspInput.from_dict(d) self.assertIn("CONTCAR.Li2O", vinput)
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 is not None: 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
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_from_directory(self): vi = VaspInput.from_directory(PymatgenTest.TEST_FILES_DIR, optional_files={"CONTCAR.Li2O": Poscar}) self.assertEqual(vi["INCAR"]["ALGO"], "Damped") self.assertIn("CONTCAR.Li2O", vi) d = vi.as_dict() vinput = VaspInput.from_dict(d) self.assertIn("CONTCAR.Li2O", vinput)
def get_inputs(self, sync=False): """ Read VaspInput from directory """ if sync: self.sync_from_hpc() inputs = VaspInput.from_directory(self.path) self.inputs = inputs return
def get_runs(vasp_command, target=1e-3, max_steps=10, mode="linear"): """ Generate the runs using a generator until convergence is achieved. """ 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(f"Converged to {ediff} eV/atom!") break 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=f".kpoints.{'x'.join(map(str, m))}", settings_override=settings, )
def test_too_large_kspacing(self): shutil.copy("INCAR.kspacing", "INCAR") vi = VaspInput.from_directory(".") h = VaspErrorHandler("vasp.teterror") h.check() d = h.correct() self.assertEqual(d["errors"], ['tet']) self.assertEqual(d["actions"], [{'action': {"_set": {"KSPACING": vi["INCAR"].get("KSPACING")*0.8}},'dict': 'INCAR'}])
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 from_directory(self, base_input_dir): """ Parameters ---------- base_input_dir : str Path to the directory including base input files. Returns ------- base_vasp_input : VaspInput (defined in pymatgen) vasp input object """ self.base_vasp_input = VaspInput.from_directory(base_input_dir) self.base_info = self.base_vasp_input.get("INCAR") return self.base_vasp_input
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 from_directory(path=None, job_script_filename=None, load_outputs=True, **kwargs): """ Builds VaspJob object from data stored in a directory. Input files are read using Pymatgen VaspInput class. Output files are read usign Pymatgen Vasprun class. Job settings are read from the job script file. Parameters ---------- path : (str) Path were job data is stored. If None the current wdir is used. The default is None. job_script_filename : (str), optional Filename of job script. The default is set in the config file. kwargs : (dict) Arguments to pass to Vasprun parser. Returns ------- VaspJob object. """ path = path if path else os.getcwd() inputs = VaspInput.from_directory(path) outputs = {} if load_outputs: if op.isfile(op.join(path, 'vasprun.xml')): try: outputs['Vasprun'] = Vasprun(op.join(path, 'vasprun.xml'), **kwargs) except: print('Warning: Reading of vasprun.xml in "%s" failed' % path) outputs['Vasprun'] = None job_script_filename = job_script_filename if job_script_filename else ScriptHandler( ).filename s = ScriptHandler.from_file(path, filename=job_script_filename) job_settings = s.settings return VaspJob(path, inputs, job_settings, outputs, job_script_filename)
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 = i == njobs - 1 if any(c.isdigit() for c in job): suffix = "." + job else: suffix = f".{job}{i + 1}" settings = post_settings post_settings = [] backup = i == 0 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 ( MPStaticDielectricDFPTVaspInputSet, MPStaticSet, ) # 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"): yield from VaspJob.full_opt_run(vasp_command) else: print(f"Unsupported job type: {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, )
from pymatgen.io.vasp.inputs import Incar, Poscar, VaspInput,Potcar, Kpoints import os,shutil from custodian.vasp.jobs import VaspJob from custodian.vasp.handlers import VaspErrorHandler, UnconvergedErrorHandler,MeshSymmetryErrorHandler, NonConvergingErrorHandler, PotimErrorHandler from custodian.vasp.validators import VasprunXMLValidator from custodian.custodian import Custodian inc=Incar.from_file("INCAR") pot=Potcar.from_file("POTCAR") pos=Poscar.from_file("POSCAR") kp=Kpoints.from_file("KPOINTS") shutil.copy2('/users/knc6/bin/vdw_kernel.bindat','./') vinput = VaspInput.from_directory(".") job=VaspJob(['mpirun', '-np', '16', '/users/knc6/VASP/vasp54/src/vasp.5.4.1/bin/vasp_std'], final=False, backup=False) handlers = [VaspErrorHandler(), MeshSymmetryErrorHandler(),UnconvergedErrorHandler(), NonConvergingErrorHandler(),PotimErrorHandler()] validators = [VasprunXMLValidator()] c = Custodian(handlers, [job],max_errors=5,validators=validators) c.run()
def from_directory(self, base_input_dir): # set information of base_input and pos_info from files in base_input_dir self.base_vasp_input = VaspInput.from_directory(base_input_dir) self.base_info = self.base_vasp_input.get("INCAR") return self.base_vasp_input
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}